Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .agents/pm/history/pm-github-4ga9.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{"ts":"2026-08-15T09:59:58.137Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"160291269a4da19f0e3cdf5b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":null,"topic":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-github-4ga9"},{"op":"add","path":"/metadata/title","value":"A github command can silently lose its preflight credential gate when the override scope drifts from the mutating command set"},{"op":"add","path":"/metadata/description","value":"registerPreflight is scoped to a fixed six-entry commands array (PR #36). That array and isMutatingGithubCommand are maintained by hand with nothing binding them: the legacy gh-issues alias already showed how easily a hand-maintained command list drifts from the real mutating set. If a command is added or reclassified as mutating on one side only, the override stops running for it (the runtime matches by exact normalized path) and the command executes with no early credential warning — silently, because the runtime swallows preflight throws and the authoritative handler gate only fires once the command actually runs and fails. A test must bind the scope to the classifier: every scoped path has to be one isMutatingGithubCommand treats as mutating (the apply-gated github export and github project sync under their apply configuration), and every declared-but-omitted path has to be read-only, so the two lists cannot drift apart again."},{"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-15T09:59:58.137Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-08-15T09:59:58.137Z"},{"op":"add","path":"/metadata/author","value":"pi-agent"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"7f5185e842ae8ae19e58b3fed488319676e1aa0aceafe3f5c8ad83bd3e0d85dc","message":""}
{"ts":"2026-08-15T10:01:20.613Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"160291269a4da19f0e3cdf5b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":null,"topic":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T10:01:20.613Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"7f5185e842ae8ae19e58b3fed488319676e1aa0aceafe3f5c8ad83bd3e0d85dc","after_hash":"f76e0a8eba61f45d0d31d0b3eea94c172deec5ae3aef5ba8d36c03ba3ba31b7d"}
{"ts":"2026-08-15T10:01:21.491Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"160291269a4da19f0e3cdf5b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":null,"topic":null},"op":"comment_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T10:01:21.491Z"},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-08-15T10:01:21.491Z","author":"pi-agent","text":"Manifest-vs-scope audit (the check CodeRabbit asked for on pm-linear #67). Commands pm-github declares: github sync, gh-issues import (legacy command alias), github validate, github project list, github project fields, github project import, github project sync (registerCommand), plus github import (registerImporter) and github export (registerExporter). Preflight scope after PR #36: github sync, github export, github import, gh-issues import, github project import, github project sync. Diff: every scoped path is a declared command; the three omitted commands (github validate, github project list, github project fields) are read-only diagnostics and were never gated — isMutatingGithubCommand returned false for them under the old global registration too, so no gate was lost. Notably the legacy alias gh-issues import was already in scope (the gap CodeRabbit caught in pm-linear/pm-jira does not exist here). Remaining defect: nothing binds the two lists, which this item fixes with a drift test."}]}],"before_hash":"f76e0a8eba61f45d0d31d0b3eea94c172deec5ae3aef5ba8d36c03ba3ba31b7d","after_hash":"9e96ef853cc07c8b776d96316fa2d26ac778b41b77f9936a64463fc1b23ad406"}
{"ts":"2026-08-15T10:02:02.393Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"160291269a4da19f0e3cdf5b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":null,"topic":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/1","value":{"created_at":"2026-08-15T10:02:02.393Z","author":"pi-agent","text":"Manifest-vs-scope audit (the check CodeRabbit asked for on pm-linear #67). Commands pm-github declares: github sync, gh-issues import (legacy command alias), github validate, github project list, github project fields, github project import, github project sync (registerCommand), plus github import (registerImporter) and github export (registerExporter). Preflight scope after PR #36: github sync, github export, github import, gh-issues import, github project import, github project sync. Diff: every scoped path is a declared command; the three omitted commands (github validate, github project list, github project fields) are read-only diagnostics and were never gated — isMutatingGithubCommand returned false for them under the old global registration too, so no gate was lost. Notably the legacy alias gh-issues import was already in scope (the gap CodeRabbit caught in pm-linear/pm-jira does not exist here). Remaining defect: nothing binds the two lists, which this item fixes with a drift test."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T10:02:02.393Z"}],"before_hash":"9e96ef853cc07c8b776d96316fa2d26ac778b41b77f9936a64463fc1b23ad406","after_hash":"60bbfde97381940e7963a985a88516c21892836b3361e5b881e4aa0e94a39b1b"}
{"ts":"2026-08-15T10:02:14.940Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"160291269a4da19f0e3cdf5b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":null,"topic":null},"op":"comment_delete","patch":[{"op":"remove","path":"/metadata/comments/1"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T10:02:14.940Z"}],"before_hash":"60bbfde97381940e7963a985a88516c21892836b3361e5b881e4aa0e94a39b1b","after_hash":"a7ee8e6f4afaa7197e4b4502fc3de44eefdbe5fed286b97efec001f8d51b2766"}
{"ts":"2026-08-15T10:02:15.603Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"160291269a4da19f0e3cdf5b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":null,"topic":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T10:02:15.603Z"},{"op":"add","path":"/metadata/files","value":[{"path":"test/smoke.test.ts","scope":"project"}]}],"before_hash":"a7ee8e6f4afaa7197e4b4502fc3de44eefdbe5fed286b97efec001f8d51b2766","after_hash":"1670cf19621454a56749e0459440bffec71bc595ac9947fcd384493fd62cef8c"}
{"ts":"2026-08-15T10:03:11.022Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"160291269a4da19f0e3cdf5b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":null,"topic":null},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T10:03:11.022Z"},{"op":"add","path":"/metadata/tests","value":[{"command":"npm test","path":"test/smoke.test.ts","scope":"project","note":"Asserts the preflight override stays scoped to exactly pm-github's owned mutating command paths and binds the scope to isMutatingGithubCommand: every scoped path must be classified mutating (github export and github project sync under their apply configuration) and every declared-but-omitted path must be read-only. Test title: preflight override is scoped to pm-github's owned command paths"}]}],"before_hash":"1670cf19621454a56749e0459440bffec71bc595ac9947fcd384493fd62cef8c","after_hash":"55d2b03b36fa212c3ad633676ff87047e8b3df14b4c4983cc912c5ca9803bc2d"}
{"ts":"2026-08-15T10:15:01.046Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"160291269a4da19f0e3cdf5b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":null,"topic":null},"op":"close","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T10:15:01.046Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-08-15T10:15:00.998Z"},{"op":"add","path":"/metadata/completed_at","value":"2026-08-15T10:15:00.998Z"},{"op":"add","path":"/metadata/close_reason","value":"Scope bound to the classifier in test/smoke.test.ts: every scoped preflight path must be one isMutatingGithubCommand treats as mutating (github export and github project sync under their apply configuration), and every declared-but-omitted path (github validate, github project list, github project fields) must be read-only, so the scope list and pm-github's declared command set cannot drift apart again. Manifest-vs-scope audit found no lost gate; gh-issues import was already in scope. Verified: npm test 251/251 pass, coverage 92.04/81.34/91.49 (thresholds 88/79/89), release:check exit 0, npx pm health --strict-exit ok:true."}],"before_hash":"55d2b03b36fa212c3ad633676ff87047e8b3df14b4c4983cc912c5ca9803bc2d","after_hash":"c0838d42424bf04a19c658a6de6a5303f0b058964f7c458a18621f14e9e0dfa6"}
{"ts":"2026-08-15T11:12:30.498Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"faf49faa4cb656dc3626f46b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":{"value":"implementer","source":"argv"},"topic":null},"op":"update","patch":[{"op":"remove","path":"/metadata/close_reason"},{"op":"remove","path":"/metadata/completed_at"},{"op":"remove","path":"/metadata/closed_at"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T11:12:30.498Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"c0838d42424bf04a19c658a6de6a5303f0b058964f7c458a18621f14e9e0dfa6","after_hash":"718f3dfba735d7db7bf147f44de32820fc9f7db426e2fee3012efa2c1cba53e5","item_hash_version":2,"message":"Reopened: PR #42 review (Greptile 3789172153 P2, CodeRabbit 3789173850 Major) correctly flags that DECLARED_READ_ONLY_COMMANDS is another hand-maintained list — the drift guard cannot detect the drift it was written for. Reworking the test to derive the declared command set from the real activation registry."}
{"ts":"2026-08-15T11:12:55.204Z","author":"pi-agent","author_source":"asserted","agent_harness":"pi","agent_model":"glm-5.3","agent_model_source":"environment","agent_instance":"faf49faa4cb656dc3626f46b","agent_provenance":{"model":{"value":"glm-5.3","source":"environment"},"effort":null,"role":{"value":"implementer","source":"argv"},"topic":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T11:12:55.204Z"},{"op":"add","path":"/metadata/assignee","value":"pi-agent"},{"op":"add","path":"/metadata/claim_principal","value":"pi-agent"}],"before_hash":"718f3dfba735d7db7bf147f44de32820fc9f7db426e2fee3012efa2c1cba53e5","after_hash":"d990301af05c9f559285be757d43072dcb333dee426166e8954209fbb05ca67d","item_hash_version":2}
{"ts":"2026-08-15T11:37:53.946Z","author":"pi-agent","author_source":"asserted","agent_harness":"claude-code","agent_instance":"2a535af1e474c92d3fda7e13","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"close","patch":[{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-15T11:37:53.946Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-08-15T11:37:53.931Z"},{"op":"add","path":"/metadata/completed_at","value":"2026-08-15T11:37:53.931Z"},{"op":"add","path":"/metadata/resolution","value":"The smoke test now derives the declared command set from real activation registrations (registerCommand, registerImporter, registerExporter) instead of a hand-maintained literal, asserts the dispatch handler paths equal that derived set, partitions it with the same isMutatingGithubCommand predicate production uses, and asserts the mutating and read-only classes reconstruct the declared set exactly. A declared path that escapes both classes therefore fails the test."},{"op":"add","path":"/metadata/expected_result","value":"Declaring a new mutating github command without adding it to the preflight override scope fails the test, naming that command, rather than leaving every assertion green."},{"op":"add","path":"/metadata/actual_result","value":"Verified by declaring a scratch mutating command github scratch drift through registerCommand and adding it to isMutatingGithubCommand without touching the override scope: the suite failed 1 of 251 with preflight override scope must equal the mutating class of the declared command set exactly, and the diff named github scratch drift. The scratch command was then removed and the suite is 251 of 251 green."},{"op":"add","path":"/metadata/close_reason","value":"The smoke test now derives the declared command set from real activation registrations (registerCommand, registerImporter, registerExporter) instead of a hand-maintained literal, asserts the dispatch handler paths equal that derived set, partitions it with the same isMutatingGithubCommand predicate production uses, and asserts the mutating and read-only classes reconstruct the declared set exactly. A declared path that escapes both classes therefore fails the test."}],"before_hash":"d990301af05c9f559285be757d43072dcb333dee426166e8954209fbb05ca67d","after_hash":"f24768279b7db8c10eaf74463125f0852378128aad087826b4bb35086a5a5621","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"}}}}
24 changes: 24 additions & 0 deletions .agents/pm/issues/pm-github-4ga9.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
id: pm-github-4ga9
title: A github command can silently lose its preflight credential gate when the override scope drifts from the mutating command set
description: "registerPreflight is scoped to a fixed six-entry commands array (PR #36). That array and isMutatingGithubCommand are maintained by hand with nothing binding them: the legacy gh-issues alias already showed how easily a hand-maintained command list drifts from the real mutating set. If a command is added or reclassified as mutating on one side only, the override stops running for it (the runtime matches by exact normalized path) and the command executes with no early credential warning — silently, because the runtime swallows preflight throws and the authoritative handler gate only fires once the command actually runs and fails. A test must bind the scope to the classifier: every scoped path has to be one isMutatingGithubCommand treats as mutating (the apply-gated github export and github project sync under their apply configuration), and every declared-but-omitted path has to be read-only, so the two lists cannot drift apart again."
type: Issue
status: closed
priority: 2
tags: []
created_at: "2026-08-15T09:59:58.137Z"
updated_at: "2026-08-15T11:37:53.946Z"
closed_at: "2026-08-15T11:37:53.931Z"
completed_at: "2026-08-15T11:37:53.931Z"
claim_principal: pi-agent
author: pi-agent
resolution: "The smoke test now derives the declared command set from real activation registrations (registerCommand, registerImporter, registerExporter) instead of a hand-maintained literal, asserts the dispatch handler paths equal that derived set, partitions it with the same isMutatingGithubCommand predicate production uses, and asserts the mutating and read-only classes reconstruct the declared set exactly. A declared path that escapes both classes therefore fails the test."
expected_result: "Declaring a new mutating github command without adding it to the preflight override scope fails the test, naming that command, rather than leaving every assertion green."
actual_result: "Verified by declaring a scratch mutating command github scratch drift through registerCommand and adding it to isMutatingGithubCommand without touching the override scope: the suite failed 1 of 251 with preflight override scope must equal the mutating class of the declared command set exactly, and the diff named github scratch drift. The scratch command was then removed and the suite is 251 of 251 green."
comments[1]{created_at,author,text}:
"2026-08-15T10:01:21.491Z",pi-agent,"Manifest-vs-scope audit (the check CodeRabbit asked for on pm-linear #67). Commands pm-github declares: github sync, gh-issues import (legacy command alias), github validate, github project list, github project fields, github project import, github project sync (registerCommand), plus github import (registerImporter) and github export (registerExporter). Preflight scope after PR #36: github sync, github export, github import, gh-issues import, github project import, github project sync. Diff: every scoped path is a declared command; the three omitted commands (github validate, github project list, github project fields) are read-only diagnostics and were never gated — isMutatingGithubCommand returned false for them under the old global registration too, so no gate was lost. Notably the legacy alias gh-issues import was already in scope (the gap CodeRabbit caught in pm-linear/pm-jira does not exist here). Remaining defect: nothing binds the two lists, which this item fixes with a drift test."
files[1]{path,scope}:
test/smoke.test.ts,project
tests[1]{command,path,scope,note}:
npm test,test/smoke.test.ts,project,"Asserts the preflight override stays scoped to exactly pm-github's owned mutating command paths and binds the scope to isMutatingGithubCommand: every scoped path must be classified mutating (github export and github project sync under their apply configuration) and every declared-but-omitted path must be read-only. Test title: preflight override is scoped to pm-github's owned command paths"
close_reason: "The smoke test now derives the declared command set from real activation registrations (registerCommand, registerImporter, registerExporter) instead of a hand-maintained literal, asserts the dispatch handler paths equal that derived set, partitions it with the same isMutatingGithubCommand predicate production uses, and asserts the mutating and read-only classes reconstruct the declared set exactly. A declared path that escapes both classes therefore fails the test."
body: ""
2 changes: 0 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,4 @@
".agents/pm/history/*.jsonl" merge=pm-history
".agents/pm/settings.json" merge=pm-json
".agents/pm/**/*.json" merge=pm-json
".agents/pm/extensions/**" -merge
".agents/pm/extensions/.managed-extensions.json" merge=pm-json
# pm-cli:merge-drivers:end
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Fixed

- A github command can silently lose its preflight credential gate when the override scope drifts from the mutating command set ([pm-github-4ga9](https://github.com/unbraind/pm-github/blob/main/.agents/pm/issues/pm-github-4ga9.toon))

## 2026.8.15 - 2026-08-15

### Fixed
Expand Down
Loading