Skip to content

fix(release): pin npm 11 for provenance publish#28

Merged
drewstone merged 3 commits into
mainfrom
fix/release-npm11
Jul 9, 2026
Merged

fix(release): pin npm 11 for provenance publish#28
drewstone merged 3 commits into
mainfrom
fix/release-npm11

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

What changed

Pin the release workflow to npm 11 instead of npm@latest.

The failed 0.20.0 release installed npm 12.0.0, then every package publish failed with MODULE_NOT_FOUND: Cannot find module sigstore from libnpmpublish/lib/provenance.js. npm 11 satisfies the OIDC requirement and is the known-good version already used by the agent-eval publisher.

Verification

  • read failed job 86026974437 directly: all 8 package publishes failed on the same npm 12 provenance error
  • git diff --check
  • branch merges cleanly into current origin/main

The real proof is the post-merge release run publishing 0.20.0; no token fallback is added.

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — 00da486f

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: drewstone_author · 2026-07-09T22:04:48Z

@tangletools

Copy link
Copy Markdown

✅ No Blockers — 00da486f

Review health 100/100 · Reviewer score 89/100 · Confidence 65/100 · 3 findings (3 low)

opencode-kimi glm deepseek aggregate
Readiness 89 92 95 89
Confidence 65 65 65 65
Correctness 89 92 95 89
Security 89 92 95 89
Testing 89 92 95 89
Architecture 89 92 95 89

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision.

🟡 LOW Floating major pin (npm@11) leaves release reproducibility exposed to future 11.x regressions — .github/workflows/release.yml

npm install -g npm@11 resolves to the latest 11.x at run time. If a future 11.x patch reintroduces a provenance/sigstore issue, releases break silently with no code change. Pinning to an exact version (e.g. npm@11.5.1, matching the documented OIDC floor) would make the release environment fully reproducible and force an intentional bump. Low severity — current behavior is correct; this is a hardening nit.

🟡 LOW No upstream link / revisit TODO for the npm 12 pin — .github/workflows/release.yml

The comment documents the npm 12.0.0 sigstore/provenance regression as the reason for the pin, but does not link the upstream npm/cli issue or note the second concrete blocker visible in the v12.0.0 release notes: npm 12 requires Node ^22.22.2 || ^24.15.0 || >=26.0.0 while this workflow pins node-version: 22. Add an issue link and a short TODO to revisit the pin (and bump Node) once npm 12 provenance is confirmed working, so the workaround does not silently fossilize. Documentation/operational nit only; no functional defect.

🟡 LOW Pin still floats within npm major; consider exact version for fully reproducible releases — .github/workflows/release.yml

npm install -g npm@11 resolves to the latest 11.x (currently 11.18.0). This is strictly better than npm@latest, but it is the same class of floating-version risk at the patch level — a future 11.x patch could in principle regress the provenance publish path the same way 12.0.0 did. For a release pipeline, prefer an exact immutable pin (e.g. npm@11.18.0), optionally paired with a checksum, so every release runs an identical npm. Impact is low: the OIDC requirement (>= 11.5.1) remains satisfied and provenance works today.


tangletools · 2026-07-09T22:06:52Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Value Audit — sound

Verdict sound
Concerns 0 (none)
Heuristic 0.0s
Duplication 0.0s
Interrogation 103.4s (2 bridge agents)
Total 103.4s

💰 Value — sound

One-line pin of the release workflow from npm@latest to npm@11 (with a precise why-comment) to unbreak provenance publishing that npm 12.0.0 regressed — a minimal, in-grain, correct fix with no better design available.

  • What it does: Changes .github/workflows/release.yml:28 from npm install -g npm@latest to npm install -g npm@11, and updates the preceding comment (lines 26-27) to record the npm 12.0.0 sigstore regression and the npm >=11.5.1 OIDC floor. Behaviorally the release job now resolves the latest npm 11.x instead of whatever latest points at, so the changesets/action@v1 publish step (line 29, with `NPM_CONFI
  • Goals it achieves: Unblock the release pipeline: the prior run installed npm 12.0.0 via @latest and all 8 package publishes failed with MODULE_NOT_FOUND: Cannot find module sigstore from libnpmpublish/lib/provenance.js. After merge, OIDC trusted publishing + provenance (the workflow's whole purpose, per the id-token: write at line 16 and provenance env at line 37) works again on a known-good major, and the c
  • Assessment: Good on its merits. It is the smallest possible change, sits directly on the line that was just introduced in b1e51ab ci: use npm OIDC trusted publishing with provenance for releases, targets the observed failure precisely, keeps the OIDC version floor satisfied, and documents the constraint inline. The author is appropriately honest that the real proof is the post-merge run (no fake fallback to
  • Better / existing approach: none — this is the right approach. Searched: .github/workflows/ contains only ci.yml and release.yml; git grep 'npm install -g' and git grep -i provenance|sigstore|id-token return only release.yml, so there is no second publisher in this repo to reuse or keep in sync (the PR's 'agent-eval publisher' reference is cross-repo prior art, not local). Considered and rejected alternatives: pi
  • Model: opencode/kimi-for-coding/k2p7
  • Bridge attempts: 1

🎯 Usefulness — sound

Pins the release workflow's npm to major 11 to dodge the npm 12.0.0 sigstore/provenance regression — a minimal, correct fix matching a known-good org pattern.

  • Integration: The step sits directly in the release job's critical path at .github/workflows/release.yml:28, running on every push to main (lines 3-5) right before changesets/action@v1 publishes (line 29). Fully reachable; no new surface introduced.
  • Fit with existing patterns: Consistent with the existing pattern — the workflow already ran a global npm install at this exact step (just npm@latest before). The PR body notes the same npm@11 pin is already known-good in the agent-eval publisher, so it matches an established org convention rather than inventing one.
  • Real-world viability: Floating within major 11 (npm@11) deliberately gets security/patch updates while excluding the breaking 12.x provenance path — the right granularity, not a stale exact pin. npm 11 always satisfies the >= 11.5.1 OIDC requirement cited in the comment, so the constraint holds over time.
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

No concerns — sound change, no better or existing approach found. ✅


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260709T220656Z

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — 3 non-blocking findings — 00da486f

Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision.

Full immutable report for this review: trace

Summary comment for this run: full summary


tangletools · 2026-07-09T22:06:52Z · immutable trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — be74228d

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: drewstone_author · 2026-07-09T22:14:48Z

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Value Audit — sound

Verdict sound
Concerns 0 (none)
Heuristic 0.0s
Duplication 0.0s
Interrogation 59.8s (2 bridge agents)
Total 59.8s

💰 Value — sound

Pins the release workflow's global npm to the exact known-good 11.18.0 instead of floating npm@latest, fixing the npm 12 sigstore/MODULE_NOT_FOUND provenance failure — minimal, in-grain, no better approach found.

  • What it does: In .github/workflows/release.yml:28, replaces npm install -g npm@latest with npm install -g npm@11.18.0 and updates the comment (lines 26-27) to document the npm 12.0.0 sigstore omission and the OIDC >=11.5.1 floor. The pinned npm is what pnpm changeset:publish (line 32) shells out to for the OIDC/provenance publish (NPM_CONFIG_PROVENANCE true, line 37). The branch's tip be74228 already tigh
  • Goals it achieves: Unblock the failing 0.20.0 release: npm@latest resolved to 12.0.0 whose libnpmpublish/provenance.js drops the sigstore module, breaking all 8 package publishes. Pinning to the known-good 11.x restores tokenless OIDC trusted publishing + provenance on node 22 (which ships an older npm) and prevents the next npm major from silently re-breaking the same path.
  • Assessment: Good on its merits. It is the smallest lever that addresses the root cause (the npm CLI version changesets invokes), matches the existing grain of the workflow (just a version string + explanatory comment), and the exact-pin form in be74228 is strictly better than the floating npm@11 it supersedes because it removes the very drift that caused the incident.
  • Better / existing approach: none — this is the right approach. Searched the repo: only two workflows exist (release.yml, ci.yml); ci.yml does not publish; there is no shared/composite action and no other npm install -g/provenance usage to reuse or centralize (the agent-eval publisher referenced in the body lives in another repo). The realistic alternatives are worse: bumping to node 24 for a newer bundled npm is a far larg
  • Model: opencode/kimi-for-coding/k2p7
  • Bridge attempts: 1

🎯 Usefulness — sound

Pin the release workflow's npm to 11.18.0 to stop npm 12's broken provenance path from failing every publish — the minimal correct fix for the actual broken release.

  • Integration: Fully reachable: this step IS the only publish path, running before changesets/action on every push to main (release.yml:4,28); not new surface, just a narrowed version on the existing bump-npm step.
  • Fit with existing patterns: Matches the established pattern — the file already bumped npm for OIDC provenance (release.yml:15-16,26); this just replaces the unsafe @latest (which rolled to broken npm 12.0.0) with a pinned known-good version, the standard fix.
  • Real-world viability: Holds up: a hard pin is more reproducible than @latest/@11 and avoids the exact class of break that motivated it; only minor trade-off is no auto-uptake of future 11.x patches, acceptable for a release pipeline.
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

No concerns — sound change, no better or existing approach found. ✅


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260709T221653Z

@tangletools

Copy link
Copy Markdown

✅ No Blockers — be74228d

Review health 100/100 · Reviewer score 89/100 · Confidence 65/100 · 5 findings (5 low)

opencode-kimi glm deepseek aggregate
Readiness 92 89 89 89
Confidence 65 65 65 65
Correctness 92 89 89 89
Security 92 89 89 89
Testing 92 89 89 89
Architecture 92 89 89 89

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision.

🟡 LOW Comment claim about sigstore omission is imprecise — .github/workflows/release.yml

The comment states 'npm 12.0.0 omits sigstore from its provenance publish path.' Verified that sigstore is still present in npm 12.0.0's dependency tree: libnpmpublish@12 depends on sigstore@^5.0.0, and npm@12.0.0 depends on @sigstore/tuf@^5.0.0. The claim likely refers to a runtime code-path regression (sigstore not being invoked during provenance signing) rather than dependency removal, but the comment as written says 'omits sigstore' which is factually inaccurate at the dependency level. Suggest rewording to something like 'npm 12.0.0 has a regression in its sigstore-based provenance signing path' to avoid misleading future maintainers who grep the dep tree.

🟡 LOW Comment rationale rests on a single claim; consider also citing npm 12's broader breaking changes — .github/workflows/release.yml

The new comment (lines 26-27) justifies the pin solely as 'npm 12.0.0 omits sigstore from its provenance publish path.' The official v12.0.0 release notes (github.com/npm/cli/releases/tag/v12.0.0) enumerate many breaking changes but do not explicitly name a provenance/sigstore removal, and npm view shows @sigstore/tuf is still bundled in both 11.18.0 (^4.0.2) and 12.0.0 (^5.0.0). I could not independently disprove the sigstore claim (the real behavior lives in libnpmpublish@12), so this is not a correctness bug — but the pin is more defensibly justified by also citing npm 12's documented breaking changes that can break this pipeline (node engine now ^22.22.

🟡 LOW Hardcoded npm version will rot without automation — .github/workflows/release.yml

Pinning npm@11.18.0 is correct for now (npm 12.0.0 broke sigstore), but this hardcoded version won't receive security fixes for npm itself. Consider adding a dependabot config entry or a scheduled action that opens a PR when a newer npm 11.x patch is available. Currently no mechanism keeps this version current.

🟡 LOW No assertion that pinned npm is active before publish — .github/workflows/release.yml

After npm install -g npm@11.18.0, the workflow proceeds directly to changesets/action which invokes npm publish. If the global install fails silently or npm 11.18.0 is yanked from the registry, the publish would fall back to whatever npm version Node 22 ships, which is < 11.5.1 and may break OIDC provenance. Add npm --version after the install to fail fast with a readable error.

🟡 LOW No automated update mechanism for pinned npm version — .github/workflows/release.yml

Pinning to exact npm@11.18.0 improves reproducibility but means security patches to the npm 11.x line (e.g., 11.18.1 for a vuln fix) will require manual intervention. No Dependabot/Renovate config was found in the repo to alert on outdated pins. Consider adding a dependabot.yml entry for github-actions (or a periodic scheduled check) so stale pins surface automatically. Not a blocker — manual bumps are acceptable for a release workflow where reproducibility is the priority.


tangletools · 2026-07-09T22:18:28Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — 5 non-blocking findings — be74228d

Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision.

Full immutable report for this review: trace

Summary comment for this run: full summary


tangletools · 2026-07-09T22:18:28Z · immutable trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — a93fc4da

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: drewstone_author · 2026-07-09T22:20:01Z

@tangletools

Copy link
Copy Markdown

✅ No Blockers — a93fc4da

Review health 100/100 · Reviewer score 92/100 · Confidence 65/100 · 1 finding (1 low)

opencode-kimi glm deepseek aggregate
Readiness 92 95 95 92
Confidence 65 65 65 65
Correctness 92 95 95 92
Security 92 95 95 92
Testing 92 95 95 92
Architecture 92 95 95 92

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision.

🟡 LOW Pin will need a manual bump once npm 12.x fixes provenance — .github/workflows/release.yml

npm@11.18.0 is currently the head of the 11.x line (registry shows no 11.19.0; latest = 12.0.0). The hard pin is correct today, but once a 12.x release resolves the sigstore MODULE_NOT_FOUND provenance bug, staying pinned on 11.18.0 will miss upstream fixes until someone manually bumps it. The inline comment documents the trigger condition, which mitigates this; consider a follow-up tracking issue or a periodic check. Not a merge blocker.


tangletools · 2026-07-09T22:23:50Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — 1 non-blocking finding — a93fc4da

Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 1 changed files. Global verifier still owns final merge decision.

Full immutable report for this review: trace

Summary comment for this run: full summary


tangletools · 2026-07-09T22:23:50Z · immutable trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Value Audit — sound-with-nits

Verdict sound-with-nits
Concerns 1 (1 weak-concern)
Heuristic 0.0s
Duplication 0.0s
Interrogation 159.9s (2 bridge agents)
Total 159.9s

💰 Value — sound-with-nits

Pins the release publisher to npm 11.18.0 (with a hard version assertion) instead of floating npm@latest, fixing the npm 12 provenance breakage — coherent and in-grain, with only a tiny single-source nit.

  • What it does: In .github/workflows/release.yml:29-31, replaces npm install -g npm@latest with npm install -g npm@11.18.0 followed by test "$(npm --version)" = "11.18.0". Behavior delta: the release job no longer tracks the moving npm major; it installs an exact known-good npm and fails the step loudly if that version is not what actually got installed.
  • Goals it achieves: Unbreaks OIDC trusted publishing with provenance. npm 12.0.0 (pulled by npm@latest) ships a broken provenance path — libnpmpublish/lib/provenance.js throws MODULE_NOT_FOUND for sigstore — which is what failed all 8 publishes in the 0.20.0 run (job 86026974437). npm 11.18.0 clears the OIDC >=11.5.1 floor and is the known-good version; the assertion turns the pin into a self-enforcing invariant so
  • Assessment: Good change, built in the grain. The repo already pins every release input hermetically — packageManager pnpm@10.23.0 (package.json:6), pnpm install --frozen-lockfile (release.yml:25), pinned action SHAs/versions — so npm@latest was the lone non-hermetic input and it is exactly the thing that broke. Pinning + asserting matches that reproducibility posture. ci.yml (ci.yml:1-21) never invokes npm,
  • Better / existing approach: none materially better. Searched for an existing equivalent to reuse: grep npm install -g npm hits only release.yml:30; .github/ contains only workflows/ (no reusable/composite actions); packageManager pins pnpm, not npm, and npm does not reliably self-pin from engines during a global install, so the explicit install+assert is the robust path. Extracting a shared action would have exactly one co
  • Model: opencode/kimi-for-coding/k2p7
  • Bridge attempts: 1

🎯 Usefulness — error

usefulness agent produced no parseable value-audit JSON.

  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1
  • Bridge error: no parseable JSON response

💰 Value Audit

🟡 Version literal repeated in three places [maintenance] ``

11.18.0 now appears in the install spec (release.yml:30), the assertion string (release.yml:31), and the comment (release.yml:26-28). A future bump must keep all three in sync; single-sourcing via one env var (e.g. NPM_VERSION=11.18.0npm install -g npm@$NPM_VERSION and test "$(npm --version)" = "$NPM_VERSION") removes the drift window. Minor and arguably the repetition is good defense-in-depth, so it does not gate shipping.


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260709T222415Z

@drewstone drewstone merged commit 77fc6ea into main Jul 9, 2026
1 check passed
@drewstone drewstone deleted the fix/release-npm11 branch July 9, 2026 22:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants