-
Notifications
You must be signed in to change notification settings - Fork 0
Refuse to publish without provenance, and gate every publish path against regression #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
31b64be
Refuse to publish without provenance, and gate every publish path aga…
unbraind 2cc1310
Record pm item for provenance attestation gate
unbraind 7786173
Record pm item for provenance attestation gate
unbraind 2270ebb
fix(release): reconcile on the artifact, and stop the gate erasing np…
unbraind 00d6b38
fix(release): restore this package's own workflow and reconcile on th…
unbraind 89e5918
fix(gate): detect a publish whose flags come before the subcommand
unbraind 9390cd8
fix(release): stop the reconcile probe terminating the step it is pol…
unbraind 746e967
fix(release): unblock the changelog step, and judge a publish by what…
unbraind ec7b2c7
fix(pm): repair corrupted linked metadata, link three duplicate items…
unbraind 3aea875
fix(gate): inspect a shell string handed over through a combined shor…
unbraind 28229e9
docs(changelog): regenerate against the released 2026.8.28 main, and …
unbraind 4a458b3
fix(release): converge the publish-attestation gate on one tokeniser-…
unbraind 21d66ed
fix(pm): keep one record per defect instead of one per review round
unbraind a94f0b7
fix(release): inline only plain scalars, and close four more bypasses
unbraind 264c9b2
docs(pm): record pull request 57 verification evidence
unbraind File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| {"ts":"2026-08-28T12:38:36.013Z","author":"claude","author_source":"asserted","agent_harness":"claude-code","agent_instance":"2017cd99c91bf11aa4148ca1","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-github-5igz"},{"op":"add","path":"/metadata/title","value":"A publish spelled through a package runner was invisible to the attestation gate, so an unattested one read as clean"},{"op":"add","path":"/metadata/description","value":"The attestation verifier tokenises each shell segment and treats the first non-runner word as the executable. Package runners were absent from that skip list, so in npx npm publish the executable resolved to npx and the segment was not recognised as a publish at all. An unrecognised publish is never checked for the provenance flag, and the failure hides itself: the workflow's ordinary attested publish still satisfies the non-vacuity guard, so the gate reported clean while an unattested publish sat in the same file. This is strictly worse than a missed flag, because nothing in the output suggests anything went unexamined. The same hole existed for bunx, pnpx, and the two-word spellings pnpm dlx, yarn dlx, npm exec and bun x."},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":2},{"op":"add","path":"/metadata/tags","value":[]},{"op":"add","path":"/metadata/created_at","value":"2026-08-28T12:38:36.013Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-08-28T12:38:36.013Z"},{"op":"add","path":"/metadata/author","value":"claude"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"e67eae4ed3408d1a021ccb601bfa95f153a026ff3f29a25da80bc74d20d69ad3","item_hash_version":2,"message":"","context":{"agent_provenance_outcomes":{"model":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"},"version":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"}}}} | ||
| {"ts":"2026-08-28T12:38:51.885Z","author":"claude","author_source":"asserted","agent_harness":"claude-code","agent_instance":"2017cd99c91bf11aa4148ca1","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-28T12:38:51.885Z"},{"op":"add","path":"/metadata/tags/0","value":"area:gates"},{"op":"add","path":"/metadata/tags/1","value":"area:release"},{"op":"add","path":"/metadata/tags/2","value":"area:supply-chain"},{"op":"add","path":"/metadata/tags/3","value":"type:defect"},{"op":"replace","path":"/metadata/priority","value":0},{"op":"add","path":"/metadata/acceptance_criteria","value":"npx, bunx, pnpx and the two-word pnpm dlx, yarn dlx, npm exec and bun x forms are all judged as publishes; a runner-prefixed publish that does carry the attestation flag still passes; the two-word runners are consumed only when the second word matches so a plain npm publish is unaffected; and reverting the skip-list change makes the new tests fail."},{"op":"add","path":"/metadata/risk","value":"critical"},{"op":"add","path":"/metadata/severity","value":"critical"},{"op":"add","path":"/metadata/repro_steps","value":"Call auditPublishAttestation on a file holding an attested plain publish followed by npx npm publish --access public. Before the fix the result carries no failures, because the runner-prefixed publish is not recognised and the attested one satisfies the non-vacuity guard."},{"op":"add","path":"/metadata/expected_result","value":"A publish is judged on what it does, not on how it is spelled, so a runner-prefixed publish is checked for the attestation flag like any other."},{"op":"add","path":"/metadata/actual_result","value":"A runner-prefixed publish was not recognised as a publish, was never checked, and left the gate reporting clean."},{"op":"add","path":"/metadata/component","value":"scripts/verify-release-publish-attestation.ts executableIndex"},{"op":"add","path":"/metadata/customer_impact","value":"A release could publish an unattested artifact while every gate reported green, defeating the supply-chain guarantee the gate exists to provide."}],"before_hash":"e67eae4ed3408d1a021ccb601bfa95f153a026ff3f29a25da80bc74d20d69ad3","after_hash":"6682a9e1167d0663e4bad94b1fd6b55c299667de11eb756c317d3515de62f766","item_hash_version":2,"context":{"agent_provenance_outcomes":{"model":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"},"version":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"}}}} | ||
| {"ts":"2026-08-28T12:38:54.253Z","author":"claude","author_source":"asserted","agent_harness":"claude-code","agent_instance":"2017cd99c91bf11aa4148ca1","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"},"role":null,"topic":null},"op":"docs_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-28T12:38:54.253Z"},{"op":"add","path":"/metadata/docs","value":[{"path":"scripts/verify-release-publish-attestation.ts","scope":"project","note":"executableIndex now skips package runners before choosing the executable"}]}],"before_hash":"6682a9e1167d0663e4bad94b1fd6b55c299667de11eb756c317d3515de62f766","after_hash":"dee2bf6b33007af5d1f7c1d9c6c4355c3b6861d8180acd049e05537203de9f84","item_hash_version":2,"context":{"agent_provenance_outcomes":{"model":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"},"version":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"}}}} | ||
| {"ts":"2026-08-28T12:38:54.925Z","author":"claude","author_source":"asserted","agent_harness":"claude-code","agent_instance":"2017cd99c91bf11aa4148ca1","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"},"role":null,"topic":null},"op":"docs_add","patch":[{"op":"add","path":"/metadata/docs/1","value":{"path":"test/verify-release-publish-attestation.test.ts","scope":"project","note":"regression cases for every runner spelling plus the attested-runner and two-word-runner mirrors"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-28T12:38:54.925Z"}],"before_hash":"dee2bf6b33007af5d1f7c1d9c6c4355c3b6861d8180acd049e05537203de9f84","after_hash":"498c4cd79a156faa0a17c730c2ee762f80119a18d724b180cb1710599a1fb786","item_hash_version":2,"context":{"agent_provenance_outcomes":{"model":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"},"version":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"}}}} | ||
| {"ts":"2026-08-28T12:52:01.213Z","author":"claude","author_source":"asserted","agent_harness":"claude-code","agent_instance":"2017cd99c91bf11aa4148ca1","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"},"role":null,"topic":null},"op":"comment_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-28T12:52:01.213Z"},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-08-28T12:52:01.213Z","author":"claude","text":"A second bypass of the same class, raised by Greptile on PR 57 and confirmed: a shell string handed over through a combined short-option cluster was never inspected. POSIX shells accept bash -ec and bash -euc, which run the string exactly as bash -c does, but the executor resolver matched -c as a whole token only. Measured before the fix: bash -c is caught, while bash -ec, bash -euc and sh -ec all read as clean over an unattested publish, because the workflow's ordinary attested publish still satisfies the non-vacuity guard. The resolver now recognises -c inside a single-dash short-option cluster, and excludes long options deliberately so that --command is not misread as a cluster containing c. Reverting the change fails two of the thirty-two cases."}]}],"before_hash":"498c4cd79a156faa0a17c730c2ee762f80119a18d724b180cb1710599a1fb786","after_hash":"d7e1d06b1ab0d85a7409bfdca076085116ab96559c55f3829dbf78143accb06d","item_hash_version":2,"context":{"agent_provenance_outcomes":{"model":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"},"version":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"}}}} | ||
| {"ts":"2026-08-28T20:48:39.553Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"gpt-5.6-luna","agent_model_source":"environment","agent_instance":"91352467fd2ac156a36ecf8a","agent_provenance":{"model":{"value":"gpt-5.6-luna","source":"environment"},"effort":null,"role":{"value":"implementer","source":"argv"},"topic":null},"op":"update","patch":[{"op":"add","path":"/metadata/comments/1","value":{"created_at":"2026-08-28T20:48:39.523Z","author":"pi-agent","text":"Verified pull request 57 before merge. Its required CI checks are green and review threads are resolved. The published gate and its package-runner regression coverage are present on the current head."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-28T20:48:39.553Z"},{"op":"add","path":"/metadata/notes","value":[{"created_at":"2026-08-28T20:48:39.523Z","author":"pi-agent","text":"Local verification passed: npm test, npm run release:check, npm run changelog:full, npm run changelog:check, and pinned pm health --strict-exit. npm run lint is unavailable because package.json has no lint script."}]},{"op":"add","path":"/metadata/tests","value":[{"command":"npm run release:check","scope":"project","timeout_seconds":300,"note":"full release gate for pull request 57"}]}],"before_hash":"d7e1d06b1ab0d85a7409bfdca076085116ab96559c55f3829dbf78143accb06d","after_hash":"f3dccf8455b0a0e2fc7e84bcc666b0001bd16e8fc592088b68b5149030170369","item_hash_version":2,"message":"Verify pull request 57 for merge"} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| {"ts":"2026-06-03T05:07:15.430Z","author":"codex","op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-github-9dqy"},{"op":"add","path":"/metadata/title","value":"True round-trip GitHub sync: search provider, validate diagnostics, safe-by-default export, fix activation"},{"op":"add","path":"/metadata/description","value":"Deepen pm-github toward true round-trip + fix activation-breaking bug. CRITICAL: published 2026.6.2 manifest omits 'preflight' but code calls registerPreflight -> extension_activate_failed -> whole extension dead. Add validate command, github search provider (maps to local imported items), dry-run-default export upsert."},{"op":"add","path":"/metadata/type","value":"Feature"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":2},{"op":"add","path":"/metadata/tags","value":[]},{"op":"add","path":"/metadata/created_at","value":"2026-06-03T05:07:15.430Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-06-03T05:07:15.430Z"},{"op":"add","path":"/metadata/author","value":"codex"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"23d20009f5ad6dcbd01700939f47f4f0eef08c461e5f79015793083c14e03146","message":"Plan"} | ||
| {"ts":"2026-06-03T05:28:25.284Z","author":"codex","op":"close","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-06-03T05:28:25.284Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/resolution","value":"Round-trip feature delivered + released"},{"op":"add","path":"/metadata/expected_result","value":"true round-trip + activation fixed"},{"op":"add","path":"/metadata/actual_result","value":"import/upsert/export/sync/search/validate all working; activation_failed=0"},{"op":"add","path":"/metadata/close_reason","value":"All 5 tasks delivered + verified vs real public repo (sindresorhus/slugify): fixed activation-breaking manifest gap (preflight+search), added github validate, github search provider, dry-run-default export with provenance upsert, fixed pm-list-vs-list-all upsert dup bug. 16/16 tests pass; release:check green. Capabilities 4/9 -> 6/9 (commands,importers,schema,hooks,preflight,search)."}],"before_hash":"23d20009f5ad6dcbd01700939f47f4f0eef08c461e5f79015793083c14e03146","after_hash":"229bafb0ccb9aed44d48053e9d8a77ca7b7cbb90bf3ff7f2da8fb19da8f6688a"} | ||
| {"ts":"2026-08-28T12:44:03.928Z","author":"claude","author_source":"asserted","agent_harness":"claude-code","agent_instance":"2017cd99c91bf11aa4148ca1","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"close","patch":[{"op":"replace","path":"/metadata/close_reason","value":"Duplicate of pm-github-4elt"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-28T12:44:03.928Z"},{"op":"add","path":"/metadata/closed_at","value":"2026-08-28T12:44:03.924Z"},{"op":"add","path":"/metadata/completed_at","value":"2026-08-28T12:44:03.924Z"},{"op":"add","path":"/metadata/duplicate_of","value":"pm-github-4elt"}],"before_hash":"229bafb0ccb9aed44d48053e9d8a77ca7b7cbb90bf3ff7f2da8fb19da8f6688a","after_hash":"def107aded726509fbc039078ea0c08993c8c5fddd71be3eca5ef6c647d19259","item_hash_version":2,"context":{"agent_provenance_outcomes":{"model":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"},"version":{"status":"failed","reason":"resolver_failed","resolver":"claude_session_file","rule_version":"v1"}}}} | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.