diff --git a/.agents/pm/extensions/.managed-extensions.json b/.agents/pm/extensions/.managed-extensions.json index 4fb93e33e..73d6e39af 100644 --- a/.agents/pm/extensions/.managed-extensions.json +++ b/.agents/pm/extensions/.managed-extensions.json @@ -1,6 +1,6 @@ { "version": 1, - "updated_at": "2026-09-27T10:35:46.561Z", + "updated_at": "2026-09-27T11:48:50.897Z", "entries": [ { "name": "pm-changelog", diff --git a/.agents/pm/history/pm-aao1hy.jsonl b/.agents/pm/history/pm-aao1hy.jsonl new file mode 100644 index 000000000..a89eee0a4 --- /dev/null +++ b/.agents/pm/history/pm-aao1hy.jsonl @@ -0,0 +1 @@ +{"hash_algorithm":"sha256","ts":"2026-09-27T12:25:46.741Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-aao1hy"},{"op":"add","path":"/metadata/title","value":"GH-1328: linked-test execution does not disclose item evidence recording"},{"op":"add","path":"/metadata/description","value":"GitHub issue #1328 reports that pm test --run says changed:false both when default test-result-tracking disables item recording and when enabled tracking appends test_run_track. Background runs also report passed without item evidence. Source: https://github.com/unbraind/pm-cli/issues/1328"},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":1},{"op":"add","path":"/metadata/tags","value":["agent-ux","area:cli","area:testing","defect","github"]},{"op":"add","path":"/metadata/created_at","value":"2026-09-27T12:25:46.741Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-09-27T12:25:46.741Z"},{"op":"add","path":"/metadata/author","value":"harness:codex"},{"op":"add","path":"/metadata/acceptance_criteria","value":"Reproduce disabled and enabled policy paths in disposable trackers; add an explicit recorded state and reason or accurate changed field; verify foreground and background item history plus SDK and CLI parity; pass exact coverage"},{"op":"add","path":"/metadata/goal","value":"project management = context management"},{"op":"add","path":"/metadata/objective","value":"Linked-test results explicitly say whether execution evidence reached the item history"},{"op":"add","path":"/metadata/value","value":"Agents can trust closeout evidence without inspecting a separate history stream"},{"op":"add","path":"/metadata/impact","value":"Prevent false assumptions that a passing linked test was recorded"},{"op":"add","path":"/metadata/outcome","value":"Foreground and background test runs expose an accurate recording receipt and recovery command"},{"op":"add","path":"/metadata/parent","value":"pm-lm0j"},{"op":"add","path":"/metadata/risk","value":"high"},{"op":"add","path":"/metadata/severity","value":"high"},{"op":"add","path":"/metadata/repro_steps","value":"Run pm test --run with default tracking and then enabled tracking; both currently print changed:false although only the second appends test_run_track."},{"op":"add","path":"/metadata/expected_result","value":"The run result accurately reports recording and the command to enable it when disabled."},{"op":"add","path":"/metadata/actual_result","value":"changed:false is printed in both cases without recording provenance."},{"op":"add","path":"/metadata/affected_version","value":"2026.9.27"},{"op":"add","path":"/metadata/component","value":"linked-test runtime and item evidence"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-16f4","kind":"discovered_from","created_at":"2026-09-27T12:25:46.741Z","author":"harness:codex","source_kind":"cli:create:dep","author_source":"detected"}]},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-09-27T12:25:46.741Z","author":"harness:codex","text":"Duplicate check: all-status GH-1328 and test-result-tracking searches found the closed tracking feature pm-16f4 and its parent epic but no open owner for the false recording receipt."}]}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"165d3d0e41e03ba21fbf99aa28cec9057a0e8b98832ab39d3533484d38867451","item_hash_version":3,"message":"","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"2cbeedc45af5f49f8562a96c6e41fcfdf6dae3b5edf035a68e6e7a91ce7112ea"} diff --git a/.agents/pm/history/pm-c3aiik.jsonl b/.agents/pm/history/pm-c3aiik.jsonl new file mode 100644 index 000000000..8ca1004ae --- /dev/null +++ b/.agents/pm/history/pm-c3aiik.jsonl @@ -0,0 +1 @@ +{"hash_algorithm":"sha256","ts":"2026-09-27T12:26:03.741Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-c3aiik"},{"op":"add","path":"/metadata/title","value":"GH-1325: history diff cursor drops newest rows and strands the final page"},{"op":"add","path":"/metadata/description","value":"GitHub issue #1325 reproduces default-budget pm history --diff --format json with a cursor that advances compact_history but not diff. Later pages repeat older diffs and can report has_more:true without next_cursor; close and release diffs become unreachable. Source: https://github.com/unbraind/pm-cli/issues/1325"},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":1},{"op":"add","path":"/metadata/tags","value":["agent-ux","area:history","area:output","defect","github"]},{"op":"add","path":"/metadata/created_at","value":"2026-09-27T12:26:03.741Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-09-27T12:26:03.741Z"},{"op":"add","path":"/metadata/author","value":"harness:codex"},{"op":"add","path":"/metadata/acceptance_criteria","value":"Reproduce with disposable 20-entry history and real tracker example; advance or independently continue all truncated diff rows; never emit has_more without a cursor; verify all rows and snapshot contracts with exact coverage"},{"op":"add","path":"/metadata/goal","value":"project management = context management"},{"op":"add","path":"/metadata/objective","value":"Every bounded history diff can be fully reconstructed through continuation cursors"},{"op":"add","path":"/metadata/value","value":"Agents can recover the actual latest lifecycle and audit changes"},{"op":"add","path":"/metadata/impact","value":"Prevent false conclusions that an item was never closed or released"},{"op":"add","path":"/metadata/outcome","value":"Diff and compact history advance consistently and final pages have truthful continuation receipts"},{"op":"add","path":"/metadata/parent","value":"pm-5t33or"},{"op":"add","path":"/metadata/risk","value":"high"},{"op":"add","path":"/metadata/severity","value":"high"},{"op":"add","path":"/metadata/repro_steps","value":"Page pm history --diff --format json with default budget using --output-cursor; diff repeats earlier indices and the final page has has_more without next_cursor."},{"op":"add","path":"/metadata/expected_result","value":"Every diff row is reachable exactly once and the final page has no dangling has_more."},{"op":"add","path":"/metadata/actual_result","value":"Newest diff rows are unreachable without unbounded output."},{"op":"add","path":"/metadata/affected_version","value":"2026.9.27"},{"op":"add","path":"/metadata/component","value":"history output budgets and continuation"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-tqel","kind":"discovered_from","created_at":"2026-09-27T12:26:03.741Z","author":"harness:codex","source_kind":"cli:create:dep","author_source":"detected"}]},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-09-27T12:26:03.741Z","author":"harness:codex","text":"Duplicate check: all-status GH-1325 and cursor-diff searches found the general output-budget feature pm-5t33or and closed history grammar work pm-tqel; neither owns this specific paired-diff continuation failure."}]}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"13bc8c72eab5e788e6cc40fb9749d2d0592eee9c03f298019a5000def3ef0afe","item_hash_version":3,"message":"","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"8a54c7ecfd9f472b7a3ccf66368b4825d95e17d11a0aaab547da9c4846f4029d"} diff --git a/.agents/pm/history/pm-ft90q2.jsonl b/.agents/pm/history/pm-ft90q2.jsonl new file mode 100644 index 000000000..bca968c2f --- /dev/null +++ b/.agents/pm/history/pm-ft90q2.jsonl @@ -0,0 +1 @@ +{"hash_algorithm":"sha256","ts":"2026-09-27T12:26:45.447Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-ft90q2"},{"op":"add","path":"/metadata/title","value":"GH-1327: Windows nightly static inventory unreadable-source assertion fails"},{"op":"add","path":"/metadata/description","value":"GitHub issue #1327 records Nightly Validation run 36310799887 at main 2b14d2fdee9d65dd1699d79e617ab53a0ae91dc7. Windows Node 24 shard 2/2 failed the read-only static extension inventory unreadable-roots/sources integration case: expected managed_state_unreadable plus source detail but received extensions_unreadable. This is separate from shard 1 init test timeouts. Source: https://github.com/unbraind/pm-cli/issues/1327"},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":1},{"op":"add","path":"/metadata/tags","value":["area:extensions","ci","defect","github","nightly","node24","windows"]},{"op":"add","path":"/metadata/created_at","value":"2026-09-27T12:26:45.447Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-09-27T12:26:45.447Z"},{"op":"add","path":"/metadata/author","value":"harness:codex"},{"op":"add","path":"/metadata/acceptance_criteria","value":"Inspect run 36310799887 shard 2 and reproduce on hosted Windows Node 24; distinguish platform error mapping from fixture assumptions; fix SDK or test according to real behavior; verify no activation or writes and rerun nightly plus exact coverage"},{"op":"add","path":"/metadata/goal","value":"project management = context management"},{"op":"add","path":"/metadata/objective","value":"Static extension inventory reports precise unreadable-source receipts consistently on Windows"},{"op":"add","path":"/metadata/value","value":"Preserve trustworthy read-only extension diagnostics across platforms"},{"op":"add","path":"/metadata/impact","value":"Avoid masking a missing managed-state reason behind a generic extensions_unreadable result"},{"op":"add","path":"/metadata/outcome","value":"Windows nightly shard 2 verifies precise refusal semantics without altering inventory safety"},{"op":"add","path":"/metadata/parent","value":"pm-ul9rye"},{"op":"add","path":"/metadata/risk","value":"high"},{"op":"add","path":"/metadata/severity","value":"high"},{"op":"add","path":"/metadata/repro_steps","value":"Inspect Nightly run 36310799887 shard 2/2: static-extension-inventory.integration.spec.ts expects managed_state_unreadable and source detail but receives extensions_unreadable."},{"op":"add","path":"/metadata/expected_result","value":"Precise managed-state and source unreadable receipts match the tested read-only conditions."},{"op":"add","path":"/metadata/actual_result","value":"Generic extensions_unreadable replaces expected receipts on Windows; shard 2 fails."},{"op":"add","path":"/metadata/affected_version","value":"2026.9.27"},{"op":"add","path":"/metadata/component","value":"static extension inventory Windows nightly"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-lhhnx9","kind":"discovered_from","created_at":"2026-09-27T12:26:45.447Z","author":"harness:codex","source_kind":"cli:create:dep","author_source":"detected"}]},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-09-27T12:26:45.447Z","author":"harness:codex","text":"Duplicate check: GH-1327 and all-status static inventory and Windows nightly searches found closed pm-lhhnx9 and older nightly lineages but no owner for this exact Windows assertion. Run 36310799887 log proves a distinct shard-2 failure."}]}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"7a0605f579e3a9ad3d6e76841c8143446ea67db7143b70ed6587c992342fb147","item_hash_version":3,"message":"","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"e78823eed01e9a800143e3142a99e6bd2f45c16a00cf94704de6fd06e9c8757c"} diff --git a/.agents/pm/history/pm-kvhnb5.jsonl b/.agents/pm/history/pm-kvhnb5.jsonl new file mode 100644 index 000000000..b40b3fca0 --- /dev/null +++ b/.agents/pm/history/pm-kvhnb5.jsonl @@ -0,0 +1,2 @@ +{"hash_algorithm":"sha256","ts":"2026-09-27T12:26:27.673Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-kvhnb5"},{"op":"add","path":"/metadata/title","value":"GH-1326: Windows nightly bundled-package init test exceeds 30 seconds"},{"op":"add","path":"/metadata/description","value":"GitHub issue #1326 records Nightly Validation run 36310799887 at main 2b14d2fdee9d65dd1699d79e617ab53a0ae91dc7. Windows Node 24 shard 1/2 failed two assertions in tests/unit/commands/workspace/init-command.spec.ts because the bundled first-party package initialization test timed out at 30000 ms. This is separate from shard 2 static inventory assertion. Source: https://github.com/unbraind/pm-cli/issues/1326"},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":1},{"op":"add","path":"/metadata/tags","value":["area:packages","ci","defect","github","nightly","node24","windows"]},{"op":"add","path":"/metadata/created_at","value":"2026-09-27T12:26:27.673Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-09-27T12:26:27.673Z"},{"op":"add","path":"/metadata/author","value":"harness:codex"},{"op":"add","path":"/metadata/acceptance_criteria","value":"Inspect the two timeout cases from run 36310799887; reproduce on hosted Windows Node 24; fix the underlying package or test budget with negative control; rerun full nightly matrix and exact coverage"},{"op":"add","path":"/metadata/goal","value":"project management = context management"},{"op":"add","path":"/metadata/objective","value":"Nightly Windows package initialization tests distinguish product failures from legitimate runtime budget needs"},{"op":"add","path":"/metadata/value","value":"Keep release validation reliable without masking package install failures"},{"op":"add","path":"/metadata/impact","value":"Avoid an untrusted nightly release signal after timed-out bundled package initialization"},{"op":"add","path":"/metadata/outcome","value":"The exact Windows nightly test completes or reports a specific actionable package failure"},{"op":"add","path":"/metadata/parent","value":"pm-ul9rye"},{"op":"add","path":"/metadata/risk","value":"high"},{"op":"add","path":"/metadata/severity","value":"high"},{"op":"add","path":"/metadata/repro_steps","value":"Inspect Nightly run 36310799887 shard 1/2: both bundled first-party init assertions time out at 30000 ms in init-command.spec.ts."},{"op":"add","path":"/metadata/expected_result","value":"Bundled package init completes and assertions verify installed packages on Windows."},{"op":"add","path":"/metadata/actual_result","value":"Two test cases time out after 30 seconds; Windows nightly shard 1/2 fails."},{"op":"add","path":"/metadata/affected_version","value":"2026.9.27"},{"op":"add","path":"/metadata/component","value":"Windows nightly bundled package initialization"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-z3ez","kind":"discovered_from","created_at":"2026-09-27T12:26:27.673Z","author":"harness:codex","source_kind":"cli:create:dep","author_source":"detected"}]},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-09-27T12:26:27.673Z","author":"harness:codex","text":"Duplicate check: GH-1326 and all-status Windows nightly searches found historical closed failures including pm-gh1075 and pm-ul9rye; this exact run and bundled init timeout have no owner. Run 36310799887 log establishes a distinct shard-1 failure."}]}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"3e319abcbfeb3ac46b482dba4983838823fb4c312ddd5b9864c8742a9372f47a","item_hash_version":3,"message":"","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"6b83a0d68f3dd14319795d472d3698ea728a512f859491b4175559fee1fea7c4"} +{"hash_algorithm":"sha256","ts":"2026-09-27T12:27:49.590Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"update","patch":[{"op":"add","path":"/metadata/dependencies/1","value":{"id":"pm-gh1075","kind":"discovered_from","created_at":"2026-09-27T12:27:49.229Z","author":"harness:codex","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T12:27:49.590Z"}],"before_hash":"3e319abcbfeb3ac46b482dba4983838823fb4c312ddd5b9864c8742a9372f47a","after_hash":"174ebd6fc0dccfc34f781b75f74f6fb676a104c6f305b3edf77360dcfe8a6f69","item_hash_version":3,"message":"Link historical Windows nightly failure cited in duplicate audit","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"6405ea75eae564086711926050e13aaa6c658489b2a8f969dc5ca3aa5996d4d8"} diff --git a/.agents/pm/history/pm-s8ztcl.jsonl b/.agents/pm/history/pm-s8ztcl.jsonl new file mode 100644 index 000000000..b9baeb5ad --- /dev/null +++ b/.agents/pm/history/pm-s8ztcl.jsonl @@ -0,0 +1 @@ +{"hash_algorithm":"sha256","ts":"2026-09-27T12:25:26.400Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-s8ztcl"},{"op":"add","path":"/metadata/title","value":"GH-1330: per-command JSON help inherits the root intent and init example"},{"op":"add","path":"/metadata/description","value":"GitHub issue #1330 reports that 55 of 137 command paths in pm help --json inherit the root intent and pm init example without a provenance marker. This gives agents a misleading action for graph, extension, assurance, and history commands. Source: https://github.com/unbraind/pm-cli/issues/1330"},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":1},{"op":"add","path":"/metadata/tags","value":["agent-ux","area:cli","area:contracts","defect","github"]},{"op":"add","path":"/metadata/created_at","value":"2026-09-27T12:25:26.400Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-09-27T12:25:26.400Z"},{"op":"add","path":"/metadata/author","value":"harness:codex"},{"op":"add","path":"/metadata/acceptance_criteria","value":"Reproduce the 55-of-137 census on the affected release; correct JSON help ownership and provenance; add a negative-control contract test across all command paths; verify generated docs and exact coverage"},{"op":"add","path":"/metadata/goal","value":"project management = context management"},{"op":"add","path":"/metadata/objective","value":"Every command help response describes its own intent or explicitly marks missing or inherited guidance"},{"op":"add","path":"/metadata/value","value":"Prevent agents from following unrelated init examples during command discovery"},{"op":"add","path":"/metadata/impact","value":"Keep machine-readable help trustworthy and token efficient"},{"op":"add","path":"/metadata/outcome","value":"No non-root help response silently repeats root intent or examples"},{"op":"add","path":"/metadata/parent","value":"pm-n7rr"},{"op":"add","path":"/metadata/risk","value":"high"},{"op":"add","path":"/metadata/severity","value":"high"},{"op":"add","path":"/metadata/repro_steps","value":"Compare pm help graph --json and pm help history activity --json with pm help --json; both inherit root intent and pm init example on 2026.9.27."},{"op":"add","path":"/metadata/expected_result","value":"Command-specific guidance or explicit absence/provenance."},{"op":"add","path":"/metadata/actual_result","value":"Root intent and pm init example are silently returned on unrelated command paths."},{"op":"add","path":"/metadata/affected_version","value":"2026.9.27"},{"op":"add","path":"/metadata/component","value":"CLI help and SDK contracts"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-7i97c3","kind":"discovered_from","created_at":"2026-09-27T12:25:26.400Z","author":"harness:codex","source_kind":"cli:create:dep","author_source":"detected"}]},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-09-27T12:25:26.400Z","author":"harness:codex","text":"Duplicate check: all-status GH-1330 and distinctive root-intent searches found no exact owner; closed pm-7i97c3 covered intent completeness in contracts but not this help inheritance defect."}]}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"ad3a3b86af5757824b297d6976f93b7bc50d6a39d2611ea94d197d1549fd5fc2","item_hash_version":3,"message":"","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"afdb8f2d48da6284c8f7b01fcbe4cebf949f23998f89497f5c4973ced54d6ee5"} diff --git a/.agents/pm/history/pm-z329kd.jsonl b/.agents/pm/history/pm-z329kd.jsonl new file mode 100644 index 000000000..1d0480e2c --- /dev/null +++ b/.agents/pm/history/pm-z329kd.jsonl @@ -0,0 +1,18 @@ +{"hash_algorithm":"sha256","ts":"2026-09-27T11:02:43.845Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-z329kd"},{"op":"add","path":"/metadata/title","value":"Malformed settings writes escape as unclassified Sentry faults"},{"op":"add","path":"/metadata/description","value":"Sentry PM-CLI-3D (one handled generic SyntaxError on released 2026.9.27) maps through writeSettings to JSON.parse of an existing malformed settings.json under the workspace-history lock. A disposable config set reproduces a settings_read_invalid_json warning followed by unknown_error and exit 1 while leaving the file unchanged. Convert this expected corrupt-input refusal into a typed, actionable settings/history error without weakening mutation integrity."},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":1},{"op":"add","path":"/metadata/tags","value":["area:history","area:observability","area:settings","defect","sentry"]},{"op":"add","path":"/metadata/created_at","value":"2026-09-27T11:02:43.845Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-09-27T11:02:43.845Z"},{"op":"add","path":"/metadata/author","value":"harness:codex"},{"op":"add","path":"/metadata/acceptance_criteria","value":"A disposable malformed settings.json config mutation returns a stable typed refusal with safe repair guidance instead of an unknown runtime error; The existing file and workspace history remain unchanged after refusal, with valid settings writes and merge reconciliation still working; Exact full coverage, focused regression, packed CLI acceptance, and hosted gates pass; Sentry issue and live telemetry are rechecked with released-versus-merged evidence kept distinct"},{"op":"add","path":"/metadata/goal","value":"project management = context management"},{"op":"add","path":"/metadata/objective","value":"Settings mutations preserve context and report corrupt input as a recoverable refusal"},{"op":"add","path":"/metadata/value","value":"Avoid opaque runtime failures and noisy production Sentry incidents"},{"op":"add","path":"/metadata/impact","value":"Keep settings and hash-chained history safe while giving agents actionable recovery"},{"op":"add","path":"/metadata/outcome","value":"Malformed settings writes fail clearly without mutation or unclassified Sentry capture"},{"op":"add","path":"/metadata/parent","value":"pm-o2kc"},{"op":"add","path":"/metadata/risk","value":"high"},{"op":"add","path":"/metadata/severity","value":"high"},{"op":"add","path":"/metadata/repro_steps","value":"In a disposable initialized PM root, replace settings.json with malformed content beginning with { then run pm config set test-result-tracking enabled --json; observe settings_read_invalid_json followed by unknown_error and unchanged file."},{"op":"add","path":"/metadata/expected_result","value":"Typed settings refusal with repair steps and no settings/history mutation."},{"op":"add","path":"/metadata/actual_result","value":"Raw JSON SyntaxError exits as unknown_error and creates high-priority Sentry PM-CLI-3D."},{"op":"add","path":"/metadata/affected_version","value":"2026.9.27"},{"op":"add","path":"/metadata/component","value":"core/store/settings + core/history/workspace-history"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-flbo","kind":"discovered_from","created_at":"2026-09-27T11:02:43.845Z","author":"harness:codex","source_kind":"cli:create:dep","author_source":"detected"},{"id":"pm-k0nl2w","kind":"discovered_from","created_at":"2026-09-27T11:02:43.845Z","author":"harness:codex","source_kind":"cli:create:dep","author_source":"detected"},{"id":"pm-xdn6","kind":"discovered_from","created_at":"2026-09-27T11:02:43.845Z","author":"harness:codex","source_kind":"cli:create:dep","author_source":"detected"}]},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-09-27T11:02:43.845Z","author":"harness:codex","text":"Duplicate check: all-status searches for PM-CLI-3D, malformed settings write, JSON.parse, and unclassified Sentry found related closed read/bootstrap, merge-safety, and classifier items but no owner for write-path parse failure. The release event occurred once at 2026-09-27T10:11:18Z; a disposable local reproduction matches the error and confirms no document mutation."}]}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"288a4e6b8a836d67f90bbdc50e601306d00a1737ecabfa9270fb889ad0d6b18e","item_hash_version":3,"message":"Intake high-priority Sentry-backed malformed settings write failure with canonical lineage","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"bc27a9daf00b91114536de019aef3aabd164a1d83b2305f01ba78cd1ca82e43c"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:02:57.476Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:02:57.476Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#d47f0e0d79925f50a0df2359"}],"before_hash":"288a4e6b8a836d67f90bbdc50e601306d00a1737ecabfa9270fb889ad0d6b18e","after_hash":"4e2862a9775b5ed2b7044f07b9bb821ce4760afe6709e8461a8fc7fa0268f5f3","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"f1c30dad410aa9675f5ebba491b42f69dda8cf0f6a2620f021e70c81de38f8a3"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:02:57.579Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:02:57.579Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"4e2862a9775b5ed2b7044f07b9bb821ce4760afe6709e8461a8fc7fa0268f5f3","after_hash":"91b35ee1e3b993bcb49a2e6b9ec53aa47419a88bc5f957b0eff1f6242571b62f","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"eb0880ab7eb89619c6528b60c1113b3cdbaa78578069d3e605defca332d29912"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:06:31.514Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/1","value":{"created_at":"2026-09-27T11:06:31.514Z","author":"harness:codex","text":"TDD red: disposable malformed settings.json caused writeSettings to throw a raw SyntaxError in the focused store test (31 pass, 1 expected failure). The preexisting file and workspace-history must remain unchanged; the new assertion requires a stable settings_write_invalid_existing_json refusal. No production source changed yet."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:06:31.514Z"}],"before_hash":"91b35ee1e3b993bcb49a2e6b9ec53aa47419a88bc5f957b0eff1f6242571b62f","after_hash":"a42efb40ebb7c8df0ecaaad1a399496575815b63bee04b3ce998902e9ee6cbfb","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"f8d27ad99db856b13cbbaf6627db0aff41e9ee471ee46d6baed8d105b6d55d28"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:07:27.144Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"files_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:07:27.144Z"},{"op":"add","path":"/metadata/files","value":[{"path":"src/core/store/settings.ts","scope":"project","note":"Classify malformed existing JSON before history mutation"},{"path":"tests/unit/core/store/settings-store.spec.ts","scope":"project","note":"Real malformed settings persistence regression"}]}],"before_hash":"a42efb40ebb7c8df0ecaaad1a399496575815b63bee04b3ce998902e9ee6cbfb","after_hash":"e8b560595167df9c6ac7d8f374ea50d839f5756f6385a80bbe472567bce67c24","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"fa03a0cb2a33134776c2a4c37f566aae724b489172837b8dac2929e273b77737"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:07:28.088Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"docs_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:07:28.088Z"},{"op":"add","path":"/metadata/docs","value":[{"path":"docs/CONFIGURATION.md","scope":"project","note":"Explain refusal and repair workflow"}]}],"before_hash":"e8b560595167df9c6ac7d8f374ea50d839f5756f6385a80bbe472567bce67c24","after_hash":"46b3d9a2e96ddc2f56cf3ce623ad098c5e57ca4e809521194aedd24fc4e1b586","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"4e39599be28ad83af3a1da92d8dd39d494c2ca8b73cb0db143698f0171283385"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:07:29.022Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:07:29.022Z"},{"op":"add","path":"/metadata/tests","value":[{"command":"node scripts/run-tests.mjs test tests/unit/core/store/settings-store.spec.ts --run","scope":"project","timeout_seconds":240,"provenance":{"author":"harness:codex","created_at":"2026-09-27T11:07:28.929Z","source_kind":"local_mutation","source_ref":"fix/classify-malformed-settings-writes"}}]}],"before_hash":"46b3d9a2e96ddc2f56cf3ce623ad098c5e57ca4e809521194aedd24fc4e1b586","after_hash":"ecbcde77f72855d15aea0a7b70e298fe1e363787e6dbf467f393350d413f960b","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"998cd3ffc808aedc2a1ac3228741882ab085cdc2359b000eb8c27395a4d6efc6"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:09:44.335Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"test_run_track","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:09:44.335Z"},{"op":"add","path":"/metadata/test_runs","value":[{"run_id":"test-local-mujpv7r9-pxxk4k","kind":"test","status":"passed","started_at":"2026-09-27T11:09:36.283Z","finished_at":"2026-09-27T11:09:44.325Z","recorded_at":"2026-09-27T11:09:44.325Z","passed":1,"failed":0,"skipped":0,"executions":[{"command":"node scripts/run-tests.mjs test tests/unit/core/store/settings-store.spec.ts --run","requested_pm_context_mode":"schema","pm_context_mode":"schema","workspace_context_mode":"source","trust_reason":"local_source_ref"}]}]}],"before_hash":"ecbcde77f72855d15aea0a7b70e298fe1e363787e6dbf467f393350d413f960b","after_hash":"808841387aa928a50dd7a8222ec0fab75cbb268b4b23a90b9723bd54d3d02a4e","item_hash_version":3,"message":"Track test run summary (test-local-mujpv7r9-pxxk4k)","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"201dd8298b31d82b8ed951560d93a79bf3a4196fbc7b350a316d6ba01d031efe"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:21:26.530Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/1/note","value":"Classify malformed existing JSON before history mutation"},{"op":"replace","path":"/metadata/files/1/path","value":"src/core/store/settings.ts"},{"op":"replace","path":"/metadata/files/0/note","value":"Public SDK error vocabulary snapshot"},{"op":"replace","path":"/metadata/files/0/path","value":"sdk/public-surface.json"},{"op":"add","path":"/metadata/files/2","value":{"path":"src/sdk/generated/generated-error-code-catalog-part-1.ts","scope":"project","note":"Generated catalog partition update"}},{"op":"add","path":"/metadata/files/3","value":{"path":"src/sdk/generated/generated-error-code-catalog-part-2.ts","scope":"project","note":"Generated settings refusal contract"}},{"op":"add","path":"/metadata/files/4","value":{"path":"tests/fixtures/contracts/full.json","scope":"project","note":"Runtime contract snapshot"}},{"op":"add","path":"/metadata/files/5","value":{"path":"tests/unit/core/store/settings-store.spec.ts","scope":"project","note":"Real malformed settings persistence regression"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:21:26.530Z"}],"before_hash":"808841387aa928a50dd7a8222ec0fab75cbb268b4b23a90b9723bd54d3d02a4e","after_hash":"9d7f714977dd2ad2b7abbb6d63686778a6c4e66243c54a9e6c489a878f4c1039","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"b829a148e508521280f720260c855ba86eb03d1ac1193cf0b9809f08d5393894"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:21:27.662Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"docs_add","patch":[{"op":"add","path":"/metadata/docs/1","value":{"path":"docs/generated/REFUSAL_CLOSURE_CENSUS.md","scope":"project","note":"Generated refusal census tracks new code and outstanding executable probe"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:21:27.662Z"}],"before_hash":"9d7f714977dd2ad2b7abbb6d63686778a6c4e66243c54a9e6c489a878f4c1039","after_hash":"0918d33dfc11936bce82a949f4487c2dea708f0a2af1f1ed486b163ec970d8b3","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"2cc494cf095e1c0fd5ef626219efbbe8c408b07b0048cacbc324ada66b6adad4"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:32:41.260Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/2","value":{"created_at":"2026-09-27T11:32:41.260Z","author":"harness:codex","text":"Verification: corrected full coverage run passed 9,375 tests (2 platform skips) with exact statements/branches/functions/lines 100/100/100/100 and zero uncovered counts. Initial run failed only because the new SDK error code required an updated public-surface snapshot; snapshot updated and full run repeated successfully. Disposable CLI config set refused malformed settings with exit 2 and settings_write_invalid_existing_json, preserved settings.json and absent _workspace history, then succeeded after syntax repair."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:32:41.260Z"}],"before_hash":"0918d33dfc11936bce82a949f4487c2dea708f0a2af1f1ed486b163ec970d8b3","after_hash":"415cfc473ba3f2012df26d90d9def12492de97a430048abc1a801a4a76fd2b7a","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"cbd4bfb87440d9959b89e30fd06aa672451be70d1dee021c274bea0ff6ce03e3"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:48:18.963Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:48:18.963Z"},{"op":"add","path":"/metadata/escape_class","value":"production_defect"},{"op":"add","path":"/metadata/gate_evidence","value":{"disposition":"gate_added","gate_id":"settings-malformed-write-refusal","negative_control":"Focused settings-store regression failed against pre-fix 0c3b00880 with raw SyntaxError (TDD red)","local_checks":["node scripts/run-tests.mjs test tests/unit/core/store/settings-store.spec.ts --run","node scripts/run-tests.mjs coverage","pnpm smoke:npx"],"hosted_checks":["Gates coverage and static quality","CI packed npm and Bun first run"],"owner":"pm-cli settings store"}}],"before_hash":"415cfc473ba3f2012df26d90d9def12492de97a430048abc1a801a4a76fd2b7a","after_hash":"7edeb7796d69fc10720a668481f1f7d0da4f862268d2a4e2c05e6797cdf66098","item_hash_version":3,"message":"Classify Sentry production escape and record regression gate","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"20d83aecb010419782ef7e37271589dffdb62b3d348a5af501ea537814e4dcdf"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:48:28.318Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"learning_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:48:28.318Z"},{"op":"add","path":"/metadata/learnings","value":[{"created_at":"2026-09-27T11:48:28.318Z","author":"harness:codex","text":"Read-time fallback to defaults must never be interpreted as permission to overwrite malformed persisted settings. Parse the locked current document before any settings write and return a typed repairable refusal."}]}],"before_hash":"7edeb7796d69fc10720a668481f1f7d0da4f862268d2a4e2c05e6797cdf66098","after_hash":"dc47569cb6f798ba679d45e71df0098b0150a42b8d37fc14269e0c0c38b15780","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"5106159ef214da121891d4c8c495d165d3011898c604c9695ab9e962cf4932be"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:48:29.148Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/3","value":{"created_at":"2026-09-27T11:48:29.148Z","author":"harness:codex","text":"Verification: docs/skills gate passed; packed npx and bunx smoke passed for version 2026.9.27 with nine packages; mutation gate passed 323 killed, seven equivalent, score 97.88%; record-integrity and graph-composition assurance passed. Local quality:static passed through SDK entrypoint costs, then failed only the host-sensitive CLI transport-floor budget (get 364>362 ms, next 550>440 ms, create 553>398 ms); the benchmark ceiling was not changed. Hosted exact-head gates remain pending."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:48:29.148Z"}],"before_hash":"dc47569cb6f798ba679d45e71df0098b0150a42b8d37fc14269e0c0c38b15780","after_hash":"49df43e08f2df6e0b5706a74dd02213f656be98d8425ee5d25664a9aaffe9d64","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"0d582dc7b3a49f78dbd5ee97697083bd14b789fd9fe2720139044b7a8f1c7ced"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:48:38.516Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"close","patch":[{"op":"replace","path":"/metadata/actual_result","value":"Disposable CLI acceptance returned exit 2 with repair guidance, unchanged malformed settings and no _workspace history; repaired settings wrote successfully. Focused linked test, 9,375-test exact 100/100/100/100 coverage, docs/skills, mutation, record-integrity, graph-composition, and packed npx/bunx smoke passed. Local static aggregate stopped at host-sensitive transport timing; hosted checks remain to be verified on the PR. Existing Sentry event belongs to the published pre-fix release."},{"op":"replace","path":"/metadata/expected_result","value":"Malformed settings config writes return a stable typed refusal, preserve the existing file and history, and allow valid writes after repair."},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:48:38.516Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-09-27T11:48:38.497Z"},{"op":"add","path":"/metadata/completed_at","value":"2026-09-27T11:48:38.497Z"},{"op":"add","path":"/metadata/resolution","value":"The SDK settings store parses the locked existing JSON and raises settings_write_invalid_existing_json with repair steps before document or workspace-history mutation; generated contracts, public docs, and regression coverage are updated."},{"op":"add","path":"/metadata/close_reason","value":"Classify malformed existing settings JSON before a write"}],"before_hash":"49df43e08f2df6e0b5706a74dd02213f656be98d8425ee5d25664a9aaffe9d64","after_hash":"867f1dd9a316303e3479410df006964e97d20777d3d3b7e1cadfc1d6da990585","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"0a2002b8d77bcfb74ab8a21c3780fc222d99774e038e354263a0a85ace142084"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:48:41.826Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]},"topic":{"value":"pm-z329kd","source":"inferred","confidence":"medium","rule_version":"v2","evidence":["claim:pm-z329kd","lineage:pm-z329kd","lineage:pm-o2kc","lineage:pm-doxj"]}},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:48:41.826Z"}],"before_hash":"867f1dd9a316303e3479410df006964e97d20777d3d3b7e1cadfc1d6da990585","after_hash":"fa85bebc3855d15f32c928ea89d745d3367481ac526db107b95e07c41043f7cc","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"cf97ea6f17e0d92c9e0acc7f34eed0dd4c6d4b2ba48ccdb62e9da65ce37d203d"} +{"hash_algorithm":"sha256","ts":"2026-09-27T11:49:25.972Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":null,"topic":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/5/note","value":"Generated settings refusal contract"},{"op":"replace","path":"/metadata/files/5/path","value":"src/sdk/generated/generated-error-code-catalog-part-2.ts"},{"op":"replace","path":"/metadata/files/4/note","value":"Generated catalog partition update"},{"op":"replace","path":"/metadata/files/4/path","value":"src/sdk/generated/generated-error-code-catalog-part-1.ts"},{"op":"replace","path":"/metadata/files/3/note","value":"Classify malformed existing JSON before history mutation"},{"op":"replace","path":"/metadata/files/3/path","value":"src/core/store/settings.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"Public SDK error vocabulary snapshot"},{"op":"replace","path":"/metadata/files/2/path","value":"sdk/public-surface.json"},{"op":"replace","path":"/metadata/files/1/note","value":"Generated closed-item changelog entry"},{"op":"replace","path":"/metadata/files/1/path","value":"CHANGELOG.md"},{"op":"replace","path":"/metadata/files/0/note","value":"Latest pm-changelog install receipt refreshed during managed changelog generation"},{"op":"replace","path":"/metadata/files/0/path","value":".agents/pm/extensions/.managed-extensions.json"},{"op":"add","path":"/metadata/files/6","value":{"path":"tests/fixtures/contracts/full.json","scope":"project","note":"Runtime contract snapshot"}},{"op":"add","path":"/metadata/files/7","value":{"path":"tests/unit/core/store/settings-store.spec.ts","scope":"project","note":"Real malformed settings persistence regression"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T11:49:25.972Z"}],"before_hash":"fa85bebc3855d15f32c928ea89d745d3367481ac526db107b95e07c41043f7cc","after_hash":"d0ea24321c963c31aa0910fb5e5f7f90871946b4bfd858a1a083fb51d8428a56","item_hash_version":3,"context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"maintenance","record_hash_version":1,"record_hash":"8acdc5d80b82347a94b9e8517a8a683b595b0474ace1f65914cd3b073f018e25"} +{"hash_algorithm":"sha256","ts":"2026-09-27T12:07:19.053Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_model":"gpt-6-sol","agent_model_source":"probe","agent_instance":"d47f0e0d79925f50a0df2359","agent_provenance":{"model":{"value":"gpt-6-sol","source":"probe"},"effort":{"value":"high","source":"probe"},"role":{"value":"implementer","source":"argv"},"topic":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-09-27T12:07:19.053Z"},{"op":"replace","path":"/metadata/title","value":"Refuse malformed settings writes with typed recovery"}],"before_hash":"d0ea24321c963c31aa0910fb5e5f7f90871946b4bfd858a1a083fb51d8428a56","after_hash":"e9e57641e7defaf694b494a15faef7303b21c97d7b8655131e27ef220b12a6b9","item_hash_version":3,"message":"Describe the delivered fix in generated changelog","context":{"agent_provenance_outcomes":{"model":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"effort":{"status":"resolved","resolver":"codex_session_file","rule_version":"v1"},"version":{"status":"unavailable","reason":"harness_unavailable","resolver":"ai_agent_version","rule_version":"v1"}}},"event_class":"substantive","record_hash_version":1,"record_hash":"103acce47c9ce2ae87d35ffa600cfe3bc528082c06f447b2d00e4cf696bee09e"} diff --git a/.agents/pm/issues/pm-aao1hy.toon b/.agents/pm/issues/pm-aao1hy.toon new file mode 100644 index 000000000..dd4226f97 --- /dev/null +++ b/.agents/pm/issues/pm-aao1hy.toon @@ -0,0 +1,29 @@ +id: pm-aao1hy +title: "GH-1328: linked-test execution does not disclose item evidence recording" +description: "GitHub issue #1328 reports that pm test --run says changed:false both when default test-result-tracking disables item recording and when enabled tracking appends test_run_track. Background runs also report passed without item evidence. Source: https://github.com/unbraind/pm-cli/issues/1328" +type: Issue +status: open +priority: 1 +tags[5]: agent-ux,"area:cli","area:testing",defect,github +created_at: "2026-09-27T12:25:46.741Z" +updated_at: "2026-09-27T12:25:46.741Z" +author: "harness:codex" +acceptance_criteria: Reproduce disabled and enabled policy paths in disposable trackers; add an explicit recorded state and reason or accurate changed field; verify foreground and background item history plus SDK and CLI parity; pass exact coverage +goal: project management = context management +objective: Linked-test results explicitly say whether execution evidence reached the item history +value: Agents can trust closeout evidence without inspecting a separate history stream +impact: Prevent false assumptions that a passing linked test was recorded +outcome: Foreground and background test runs expose an accurate recording receipt and recovery command +parent: pm-lm0j +risk: high +severity: high +repro_steps: "Run pm test --run with default tracking and then enabled tracking; both currently print changed:false although only the second appends test_run_track." +expected_result: The run result accurately reports recording and the command to enable it when disabled. +actual_result: "changed:false is printed in both cases without recording provenance." +affected_version: 2026.9.27 +component: linked-test runtime and item evidence +dependencies[1]{id,kind,created_at,author,source_kind,author_source}: + pm-16f4,discovered_from,"2026-09-27T12:25:46.741Z","harness:codex","cli:create:dep",detected +comments[1]{created_at,author,text}: + "2026-09-27T12:25:46.741Z","harness:codex","Duplicate check: all-status GH-1328 and test-result-tracking searches found the closed tracking feature pm-16f4 and its parent epic but no open owner for the false recording receipt." +body: "" diff --git a/.agents/pm/issues/pm-c3aiik.toon b/.agents/pm/issues/pm-c3aiik.toon new file mode 100644 index 000000000..7e64a5e6e --- /dev/null +++ b/.agents/pm/issues/pm-c3aiik.toon @@ -0,0 +1,29 @@ +id: pm-c3aiik +title: "GH-1325: history diff cursor drops newest rows and strands the final page" +description: "GitHub issue #1325 reproduces default-budget pm history --diff --format json with a cursor that advances compact_history but not diff. Later pages repeat older diffs and can report has_more:true without next_cursor; close and release diffs become unreachable. Source: https://github.com/unbraind/pm-cli/issues/1325" +type: Issue +status: open +priority: 1 +tags[5]: agent-ux,"area:history","area:output",defect,github +created_at: "2026-09-27T12:26:03.741Z" +updated_at: "2026-09-27T12:26:03.741Z" +author: "harness:codex" +acceptance_criteria: Reproduce with disposable 20-entry history and real tracker example; advance or independently continue all truncated diff rows; never emit has_more without a cursor; verify all rows and snapshot contracts with exact coverage +goal: project management = context management +objective: Every bounded history diff can be fully reconstructed through continuation cursors +value: Agents can recover the actual latest lifecycle and audit changes +impact: Prevent false conclusions that an item was never closed or released +outcome: Diff and compact history advance consistently and final pages have truthful continuation receipts +parent: pm-5t33or +risk: high +severity: high +repro_steps: Page pm history --diff --format json with default budget using --output-cursor; diff repeats earlier indices and the final page has has_more without next_cursor. +expected_result: Every diff row is reachable exactly once and the final page has no dangling has_more. +actual_result: Newest diff rows are unreachable without unbounded output. +affected_version: 2026.9.27 +component: history output budgets and continuation +dependencies[1]{id,kind,created_at,author,source_kind,author_source}: + pm-tqel,discovered_from,"2026-09-27T12:26:03.741Z","harness:codex","cli:create:dep",detected +comments[1]{created_at,author,text}: + "2026-09-27T12:26:03.741Z","harness:codex","Duplicate check: all-status GH-1325 and cursor-diff searches found the general output-budget feature pm-5t33or and closed history grammar work pm-tqel; neither owns this specific paired-diff continuation failure." +body: "" diff --git a/.agents/pm/issues/pm-ft90q2.toon b/.agents/pm/issues/pm-ft90q2.toon new file mode 100644 index 000000000..cc01ff7b7 --- /dev/null +++ b/.agents/pm/issues/pm-ft90q2.toon @@ -0,0 +1,29 @@ +id: pm-ft90q2 +title: "GH-1327: Windows nightly static inventory unreadable-source assertion fails" +description: "GitHub issue #1327 records Nightly Validation run 36310799887 at main 2b14d2fdee9d65dd1699d79e617ab53a0ae91dc7. Windows Node 24 shard 2/2 failed the read-only static extension inventory unreadable-roots/sources integration case: expected managed_state_unreadable plus source detail but received extensions_unreadable. This is separate from shard 1 init test timeouts. Source: https://github.com/unbraind/pm-cli/issues/1327" +type: Issue +status: open +priority: 1 +tags[7]: "area:extensions",ci,defect,github,nightly,node24,windows +created_at: "2026-09-27T12:26:45.447Z" +updated_at: "2026-09-27T12:26:45.447Z" +author: "harness:codex" +acceptance_criteria: Inspect run 36310799887 shard 2 and reproduce on hosted Windows Node 24; distinguish platform error mapping from fixture assumptions; fix SDK or test according to real behavior; verify no activation or writes and rerun nightly plus exact coverage +goal: project management = context management +objective: Static extension inventory reports precise unreadable-source receipts consistently on Windows +value: Preserve trustworthy read-only extension diagnostics across platforms +impact: Avoid masking a missing managed-state reason behind a generic extensions_unreadable result +outcome: Windows nightly shard 2 verifies precise refusal semantics without altering inventory safety +parent: pm-ul9rye +risk: high +severity: high +repro_steps: "Inspect Nightly run 36310799887 shard 2/2: static-extension-inventory.integration.spec.ts expects managed_state_unreadable and source detail but receives extensions_unreadable." +expected_result: Precise managed-state and source unreadable receipts match the tested read-only conditions. +actual_result: Generic extensions_unreadable replaces expected receipts on Windows; shard 2 fails. +affected_version: 2026.9.27 +component: static extension inventory Windows nightly +dependencies[1]{id,kind,created_at,author,source_kind,author_source}: + pm-lhhnx9,discovered_from,"2026-09-27T12:26:45.447Z","harness:codex","cli:create:dep",detected +comments[1]{created_at,author,text}: + "2026-09-27T12:26:45.447Z","harness:codex","Duplicate check: GH-1327 and all-status static inventory and Windows nightly searches found closed pm-lhhnx9 and older nightly lineages but no owner for this exact Windows assertion. Run 36310799887 log proves a distinct shard-2 failure." +body: "" diff --git a/.agents/pm/issues/pm-kvhnb5.toon b/.agents/pm/issues/pm-kvhnb5.toon new file mode 100644 index 000000000..50b0a8480 --- /dev/null +++ b/.agents/pm/issues/pm-kvhnb5.toon @@ -0,0 +1,30 @@ +id: pm-kvhnb5 +title: "GH-1326: Windows nightly bundled-package init test exceeds 30 seconds" +description: "GitHub issue #1326 records Nightly Validation run 36310799887 at main 2b14d2fdee9d65dd1699d79e617ab53a0ae91dc7. Windows Node 24 shard 1/2 failed two assertions in tests/unit/commands/workspace/init-command.spec.ts because the bundled first-party package initialization test timed out at 30000 ms. This is separate from shard 2 static inventory assertion. Source: https://github.com/unbraind/pm-cli/issues/1326" +type: Issue +status: open +priority: 1 +tags[7]: "area:packages",ci,defect,github,nightly,node24,windows +created_at: "2026-09-27T12:26:27.673Z" +updated_at: "2026-09-27T12:27:49.590Z" +author: "harness:codex" +acceptance_criteria: Inspect the two timeout cases from run 36310799887; reproduce on hosted Windows Node 24; fix the underlying package or test budget with negative control; rerun full nightly matrix and exact coverage +goal: project management = context management +objective: Nightly Windows package initialization tests distinguish product failures from legitimate runtime budget needs +value: Keep release validation reliable without masking package install failures +impact: Avoid an untrusted nightly release signal after timed-out bundled package initialization +outcome: The exact Windows nightly test completes or reports a specific actionable package failure +parent: pm-ul9rye +risk: high +severity: high +repro_steps: "Inspect Nightly run 36310799887 shard 1/2: both bundled first-party init assertions time out at 30000 ms in init-command.spec.ts." +expected_result: Bundled package init completes and assertions verify installed packages on Windows. +actual_result: Two test cases time out after 30 seconds; Windows nightly shard 1/2 fails. +affected_version: 2026.9.27 +component: Windows nightly bundled package initialization +dependencies[2]{id,kind,created_at,author,source_kind,author_source}: + pm-z3ez,discovered_from,"2026-09-27T12:26:27.673Z","harness:codex","cli:create:dep",detected + pm-gh1075,discovered_from,"2026-09-27T12:27:49.229Z","harness:codex","cli:update:dep",detected +comments[1]{created_at,author,text}: + "2026-09-27T12:26:27.673Z","harness:codex","Duplicate check: GH-1326 and all-status Windows nightly searches found historical closed failures including pm-gh1075 and pm-ul9rye; this exact run and bundled init timeout have no owner. Run 36310799887 log establishes a distinct shard-1 failure." +body: "" diff --git a/.agents/pm/issues/pm-s8ztcl.toon b/.agents/pm/issues/pm-s8ztcl.toon new file mode 100644 index 000000000..2b21e8aa5 --- /dev/null +++ b/.agents/pm/issues/pm-s8ztcl.toon @@ -0,0 +1,29 @@ +id: pm-s8ztcl +title: "GH-1330: per-command JSON help inherits the root intent and init example" +description: "GitHub issue #1330 reports that 55 of 137 command paths in pm help --json inherit the root intent and pm init example without a provenance marker. This gives agents a misleading action for graph, extension, assurance, and history commands. Source: https://github.com/unbraind/pm-cli/issues/1330" +type: Issue +status: open +priority: 1 +tags[5]: agent-ux,"area:cli","area:contracts",defect,github +created_at: "2026-09-27T12:25:26.400Z" +updated_at: "2026-09-27T12:25:26.400Z" +author: "harness:codex" +acceptance_criteria: Reproduce the 55-of-137 census on the affected release; correct JSON help ownership and provenance; add a negative-control contract test across all command paths; verify generated docs and exact coverage +goal: project management = context management +objective: Every command help response describes its own intent or explicitly marks missing or inherited guidance +value: Prevent agents from following unrelated init examples during command discovery +impact: Keep machine-readable help trustworthy and token efficient +outcome: No non-root help response silently repeats root intent or examples +parent: pm-n7rr +risk: high +severity: high +repro_steps: Compare pm help graph --json and pm help history activity --json with pm help --json; both inherit root intent and pm init example on 2026.9.27. +expected_result: Command-specific guidance or explicit absence/provenance. +actual_result: Root intent and pm init example are silently returned on unrelated command paths. +affected_version: 2026.9.27 +component: CLI help and SDK contracts +dependencies[1]{id,kind,created_at,author,source_kind,author_source}: + pm-7i97c3,discovered_from,"2026-09-27T12:25:26.400Z","harness:codex","cli:create:dep",detected +comments[1]{created_at,author,text}: + "2026-09-27T12:25:26.400Z","harness:codex","Duplicate check: all-status GH-1330 and distinctive root-intent searches found no exact owner; closed pm-7i97c3 covered intent completeness in contracts but not this help inheritance defect." +body: "" diff --git a/.agents/pm/issues/pm-z329kd.toon b/.agents/pm/issues/pm-z329kd.toon new file mode 100644 index 000000000..d114f0b1e --- /dev/null +++ b/.agents/pm/issues/pm-z329kd.toon @@ -0,0 +1,74 @@ +id: pm-z329kd +title: Refuse malformed settings writes with typed recovery +description: "Sentry PM-CLI-3D (one handled generic SyntaxError on released 2026.9.27) maps through writeSettings to JSON.parse of an existing malformed settings.json under the workspace-history lock. A disposable config set reproduces a settings_read_invalid_json warning followed by unknown_error and exit 1 while leaving the file unchanged. Convert this expected corrupt-input refusal into a typed, actionable settings/history error without weakening mutation integrity." +type: Issue +status: closed +priority: 1 +tags[5]: "area:history","area:observability","area:settings",defect,sentry +created_at: "2026-09-27T11:02:43.845Z" +updated_at: "2026-09-27T12:07:19.053Z" +closed_at: "2026-09-27T11:48:38.497Z" +completed_at: "2026-09-27T11:48:38.497Z" +author: "harness:codex" +acceptance_criteria: "A disposable malformed settings.json config mutation returns a stable typed refusal with safe repair guidance instead of an unknown runtime error; The existing file and workspace history remain unchanged after refusal, with valid settings writes and merge reconciliation still working; Exact full coverage, focused regression, packed CLI acceptance, and hosted gates pass; Sentry issue and live telemetry are rechecked with released-versus-merged evidence kept distinct" +goal: project management = context management +objective: Settings mutations preserve context and report corrupt input as a recoverable refusal +value: Avoid opaque runtime failures and noisy production Sentry incidents +impact: Keep settings and hash-chained history safe while giving agents actionable recovery +outcome: Malformed settings writes fail clearly without mutation or unclassified Sentry capture +parent: pm-o2kc +risk: high +severity: high +repro_steps: "In a disposable initialized PM root, replace settings.json with malformed content beginning with { then run pm config set test-result-tracking enabled --json; observe settings_read_invalid_json followed by unknown_error and unchanged file." +resolution: "The SDK settings store parses the locked existing JSON and raises settings_write_invalid_existing_json with repair steps before document or workspace-history mutation; generated contracts, public docs, and regression coverage are updated." +expected_result: "Malformed settings config writes return a stable typed refusal, preserve the existing file and history, and allow valid writes after repair." +actual_result: "Disposable CLI acceptance returned exit 2 with repair guidance, unchanged malformed settings and no _workspace history; repaired settings wrote successfully. Focused linked test, 9,375-test exact 100/100/100/100 coverage, docs/skills, mutation, record-integrity, graph-composition, and packed npx/bunx smoke passed. Local static aggregate stopped at host-sensitive transport timing; hosted checks remain to be verified on the PR. Existing Sentry event belongs to the published pre-fix release." +affected_version: 2026.9.27 +component: core/store/settings + core/history/workspace-history +dependencies[3]{id,kind,created_at,author,source_kind,author_source}: + pm-flbo,discovered_from,"2026-09-27T11:02:43.845Z","harness:codex","cli:create:dep",detected + pm-k0nl2w,discovered_from,"2026-09-27T11:02:43.845Z","harness:codex","cli:create:dep",detected + pm-xdn6,discovered_from,"2026-09-27T11:02:43.845Z","harness:codex","cli:create:dep",detected +comments[4]{created_at,author,text}: + "2026-09-27T11:02:43.845Z","harness:codex","Duplicate check: all-status searches for PM-CLI-3D, malformed settings write, JSON.parse, and unclassified Sentry found related closed read/bootstrap, merge-safety, and classifier items but no owner for write-path parse failure. The release event occurred once at 2026-09-27T10:11:18Z; a disposable local reproduction matches the error and confirms no document mutation." + "2026-09-27T11:06:31.514Z","harness:codex","TDD red: disposable malformed settings.json caused writeSettings to throw a raw SyntaxError in the focused store test (31 pass, 1 expected failure). The preexisting file and workspace-history must remain unchanged; the new assertion requires a stable settings_write_invalid_existing_json refusal. No production source changed yet." + "2026-09-27T11:32:41.260Z","harness:codex","Verification: corrected full coverage run passed 9,375 tests (2 platform skips) with exact statements/branches/functions/lines 100/100/100/100 and zero uncovered counts. Initial run failed only because the new SDK error code required an updated public-surface snapshot; snapshot updated and full run repeated successfully. Disposable CLI config set refused malformed settings with exit 2 and settings_write_invalid_existing_json, preserved settings.json and absent _workspace history, then succeeded after syntax repair." + "2026-09-27T11:48:29.148Z","harness:codex","Verification: docs/skills gate passed; packed npx and bunx smoke passed for version 2026.9.27 with nine packages; mutation gate passed 323 killed, seven equivalent, score 97.88%; record-integrity and graph-composition assurance passed. Local quality:static passed through SDK entrypoint costs, then failed only the host-sensitive CLI transport-floor budget (get 364>362 ms, next 550>440 ms, create 553>398 ms); the benchmark ceiling was not changed. Hosted exact-head gates remain pending." +learnings[1]{created_at,author,text}: + "2026-09-27T11:48:28.318Z","harness:codex",Read-time fallback to defaults must never be interpreted as permission to overwrite malformed persisted settings. Parse the locked current document before any settings write and return a typed repairable refusal. +files[8]{path,scope,note}: + .agents/pm/extensions/.managed-extensions.json,project,Latest pm-changelog install receipt refreshed during managed changelog generation + CHANGELOG.md,project,Generated closed-item changelog entry + sdk/public-surface.json,project,Public SDK error vocabulary snapshot + src/core/store/settings.ts,project,Classify malformed existing JSON before history mutation + src/sdk/generated/generated-error-code-catalog-part-1.ts,project,Generated catalog partition update + src/sdk/generated/generated-error-code-catalog-part-2.ts,project,Generated settings refusal contract + tests/fixtures/contracts/full.json,project,Runtime contract snapshot + tests/unit/core/store/settings-store.spec.ts,project,Real malformed settings persistence regression +tests[1]{command,scope,timeout_seconds,provenance{author,created_at,source_kind,source_ref}}: + node scripts/run-tests.mjs test tests/unit/core/store/settings-store.spec.ts --run,project,240,"harness:codex","2026-09-27T11:07:28.929Z",local_mutation,fix/classify-malformed-settings-writes +test_runs[1]: + - run_id: test-local-mujpv7r9-pxxk4k + kind: test + status: passed + started_at: "2026-09-27T11:09:36.283Z" + finished_at: "2026-09-27T11:09:44.325Z" + recorded_at: "2026-09-27T11:09:44.325Z" + passed: 1 + failed: 0 + skipped: 0 + executions[1]{command,requested_pm_context_mode,pm_context_mode,workspace_context_mode,trust_reason}: + node scripts/run-tests.mjs test tests/unit/core/store/settings-store.spec.ts --run,schema,schema,source,local_source_ref +docs[2]{path,scope,note}: + docs/CONFIGURATION.md,project,Explain refusal and repair workflow + docs/generated/REFUSAL_CLOSURE_CENSUS.md,project,Generated refusal census tracks new code and outstanding executable probe +close_reason: Classify malformed existing settings JSON before a write +escape_class: production_defect +gate_evidence: + disposition: gate_added + gate_id: settings-malformed-write-refusal + negative_control: Focused settings-store regression failed against pre-fix 0c3b00880 with raw SyntaxError (TDD red) + local_checks[3]: node scripts/run-tests.mjs test tests/unit/core/store/settings-store.spec.ts --run,node scripts/run-tests.mjs coverage,"pnpm smoke:npx" + hosted_checks[2]: Gates coverage and static quality,CI packed npm and Bun first run + owner: pm-cli settings store +body: "" diff --git a/CHANGELOG.md b/CHANGELOG.md index fb7d82105..c4ac0c765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Allow self-isolating linked package tests without inherited PM_PATH ([pm-t05d8d](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-t05d8d.toon)) - Preserve every tracker merge fence during nested init and detect lost active mappings ([pm-kynkl8](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-kynkl8.toon)) +- Refuse malformed settings writes with typed recovery ([pm-z329kd](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-z329kd.toon)) - Refuse local package installation when source scan stops at entry limit ([pm-erogk1](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-erogk1.toon)) ### Security diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 31d789dc3..d1e42f837 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -67,6 +67,8 @@ Precedence: When `settings.json` cannot be loaded, `pm` falls back to built-in defaults and prints a one-time `settings_read_fs_error`, `settings_read_invalid_json`, or `settings_read_invalid_schema` warning to stderr (stdout output is unchanged); run `pm health` for remediation. +If the existing project `settings.json` has invalid JSON, a configuration write refuses with `settings_write_invalid_existing_json`. It leaves the file and workspace history untouched. Repair the syntax in `.agents/pm/settings.json`, run `pm health`, then retry the configuration command. The read fallback to defaults does not authorize replacing malformed settings. + ## Common Settings | Setting | Purpose | diff --git a/docs/generated/REFUSAL_CLOSURE_CENSUS.md b/docs/generated/REFUSAL_CLOSURE_CENSUS.md index 7601de258..ed7e21740 100644 --- a/docs/generated/REFUSAL_CLOSURE_CENSUS.md +++ b/docs/generated/REFUSAL_CLOSURE_CENSUS.md @@ -4,12 +4,12 @@ Tracker: `pm-f05lsg`. Every catalog code is listed. An `uncovered` row is an explicit closure obligation, never an omission or implied approval. -- Catalog error codes: 388 +- Catalog error codes: 389 - Executable error codes: 19 - Executable-code ratchet floor: 18 - Required executable canonical codes: `bulk_ids_input_empty`, `bulk_ids_input_missing_path`, `bulk_ids_input_unreadable`, `invalid_argument_value`, `manifest_unknown_key`, `missing_lifecycle_target`, `missing_required_argument`, `no_version_bounds_declared`, `projection_options_mutually_exclusive`, `tracker_not_initialized`, `tracker_root_missing`, `tracker_root_not_directory`, `tracker_root_unreadable`, `unknown_context_intent`, `unknown_field_projection`, `unknown_option`, `unknown_subcommand` -- Uncovered error codes: 369 -- Coverage fraction: 0.048969 +- Uncovered error codes: 370 +- Coverage fraction: 0.048843 - Closed-domain probes: 19 - Grammar probes: 117 @@ -288,6 +288,7 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati | `settings_read_invalid_schema` | `settings_read_invalid_schema` | uncovered | none | 0 | | `settings_read_merge_failed` | `settings_read_merge_failed` | uncovered | none | 0 | | `settings_unreadable` | `settings_unreadable` | uncovered | none | 0 | +| `settings_write_invalid_existing_json` | `settings_write_invalid_existing_json` | uncovered | none | 0 | | `stale_budget` | `stale_budget` | uncovered | none | 0 | | `stale_destination` | `stale_destination` | uncovered | none | 0 | | `stale_observed_signature` | `stale_observed_signature` | uncovered | none | 0 | diff --git a/sdk/public-surface.json b/sdk/public-surface.json index 5957ea6f2..020ab199f 100644 --- a/sdk/public-surface.json +++ b/sdk/public-surface.json @@ -35441,6 +35441,7 @@ "settings_read_invalid_schema", "settings_read_merge_failed", "settings_unreadable", + "settings_write_invalid_existing_json", "stale_budget", "stale_destination", "stale_observed_signature", diff --git a/src/core/store/settings.ts b/src/core/store/settings.ts index 1474bcfe2..3dd152a99 100644 --- a/src/core/store/settings.ts +++ b/src/core/store/settings.ts @@ -9,9 +9,11 @@ import { runActiveOnWriteHooks, } from "../extensions/index.js"; import { + EXIT_CODE, GOVERNANCE_PRESET_DEFAULTS, SETTINGS_DEFAULTS, } from "../shared/constants.js"; +import { PmCliError } from "../shared/errors.js"; import { resolveAuthor } from "../shared/author.js"; import { readFileIfExists } from "../fs/fs-utils.js"; import { mutateWorkspaceJsonWithHistory } from "../history/workspace-history.js"; @@ -2034,16 +2036,38 @@ export async function writeSettings( await mutateWorkspaceJsonWithHistory({ pmRoot, filePath: settingsPath, - mutate: (beforeRaw) => ({ - raw: source - ? `${JSON.stringify(orderObject(reconcileSettingsSnapshot( - source.persisted_settings, - proposed, - beforeRaw === null ? null : JSON.parse(beforeRaw) as unknown, - ) as Record, SETTINGS_TOP_LEVEL_KEY_ORDER), null, 2)}\n` - : afterRaw, - result: undefined, - }), + mutate: (beforeRaw) => { + let current: unknown = null; + if (beforeRaw !== null) { + try { + current = JSON.parse(beforeRaw) as unknown; + } catch { + throw new PmCliError( + "Existing settings.json is malformed; the settings write was refused.", + EXIT_CODE.USAGE, + { + code: "settings_write_invalid_existing_json", + reason: "existing_settings_json_malformed", + why: "Writing defaults over malformed settings could destroy intended project configuration.", + nextSteps: [ + "Repair the syntax in .agents/pm/settings.json, then retry the original command.", + "Run pm health to confirm the settings warning has cleared.", + ], + }, + ); + } + } + return { + raw: source + ? `${JSON.stringify(orderObject(reconcileSettingsSnapshot( + source.persisted_settings, + proposed, + current, + ) as Record, SETTINGS_TOP_LEVEL_KEY_ORDER), null, 2)}\n` + : afterRaw, + result: undefined, + }; + }, op, author: resolveAuthor(undefined, settings.author_default), lockTtlSeconds: settings.locks.ttl_seconds, diff --git a/src/sdk/generated/generated-error-code-catalog-part-1.ts b/src/sdk/generated/generated-error-code-catalog-part-1.ts index e64cd0a9e..7648c03ec 100644 --- a/src/sdk/generated/generated-error-code-catalog-part-1.ts +++ b/src/sdk/generated/generated-error-code-catalog-part-1.ts @@ -2552,4 +2552,17 @@ export const PM_ERROR_CODE_CATALOG_PART_1: PmErrorCodeContract[] = [ canonical_code: "merge_receipt_history_reference_missing", aliases: [], }, + { + code: "merge_receipts_pending", + meaning: "Merge receipts pending condition.", + stability: "provisional", + exit_code: 1, + class: "generic_failure", + recovery: + "Inspect the structured error guidance and retry the suggested command.", + sources: ["core/diagnostics/remediation.ts"], + emitting_commands: ["*"], + canonical_code: "merge_receipts_pending", + aliases: [], + }, ]; diff --git a/src/sdk/generated/generated-error-code-catalog-part-2.ts b/src/sdk/generated/generated-error-code-catalog-part-2.ts index bd7605611..606fd8ef7 100644 --- a/src/sdk/generated/generated-error-code-catalog-part-2.ts +++ b/src/sdk/generated/generated-error-code-catalog-part-2.ts @@ -7,19 +7,6 @@ import type { PmErrorCodeContract } from "../error-code-catalog.js"; /** Generated partition 2 of the exhaustive error-code catalog. */ export const PM_ERROR_CODE_CATALOG_PART_2: PmErrorCodeContract[] = [ - { - code: "merge_receipts_pending", - meaning: "Merge receipts pending condition.", - stability: "provisional", - exit_code: 1, - class: "generic_failure", - recovery: - "Inspect the structured error guidance and retry the suggested command.", - sources: ["core/diagnostics/remediation.ts"], - emitting_commands: ["*"], - canonical_code: "merge_receipts_pending", - aliases: [], - }, { code: "merge_reconcile_receipt_evidence_untrusted", meaning: "Merge reconcile receipt evidence untrusted condition.", @@ -1052,6 +1039,19 @@ export const PM_ERROR_CODE_CATALOG_PART_2: PmErrorCodeContract[] = [ canonical_code: "settings_unreadable", aliases: [], }, + { + code: "settings_write_invalid_existing_json", + meaning: "Settings write invalid existing json condition.", + stability: "provisional", + exit_code: 2, + class: "usage", + recovery: + "Inspect the structured error guidance and retry the suggested command.", + sources: ["core/store/settings.ts"], + emitting_commands: ["*"], + canonical_code: "settings_write_invalid_existing_json", + aliases: [], + }, { code: "stale_budget", meaning: "Stale budget condition.", diff --git a/tests/fixtures/contracts/full.json b/tests/fixtures/contracts/full.json index a89c6cdd0..ebbaf2d1c 100644 --- a/tests/fixtures/contracts/full.json +++ b/tests/fixtures/contracts/full.json @@ -24643,6 +24643,23 @@ ], "stability": "provisional" }, + { + "aliases": [], + "canonical_code": "settings_write_invalid_existing_json", + "class": "usage", + "code": "settings_write_invalid_existing_json", + "emitting_commands": [ + "*" + ], + "exit_code": 2, + "meaning": "Settings write invalid existing json condition.", + "owned_states": [], + "recovery": "Inspect the structured error guidance and retry the suggested command.", + "sources": [ + "core/store/settings.ts" + ], + "stability": "provisional" + }, { "aliases": [], "canonical_code": "stale_budget", diff --git a/tests/unit/core/store/settings-store.spec.ts b/tests/unit/core/store/settings-store.spec.ts index d916707d6..2ab8faa7a 100644 --- a/tests/unit/core/store/settings-store.spec.ts +++ b/tests/unit/core/store/settings-store.spec.ts @@ -6,6 +6,7 @@ import { clearActiveExtensionHooks, setActiveExtensionHooks } from "../../../../ import type { ExtensionHookRegistry } from "../../../../src/core/extensions/loader.js"; import { normalizeRuntimeSchemaSettings } from "../../../../src/core/schema/runtime-schema.js"; import { DEFAULT_STATUS_DEFINITIONS, SETTINGS_DEFAULTS } from "../../../../src/core/shared/constants.js"; +import { getWorkspaceHistoryPath } from "../../../../src/core/history/workspace-history.js"; import { getSettingsPath } from "../../../../src/core/store/paths.js"; import { clearSettingsReadCache, @@ -108,6 +109,23 @@ describe("core/store/settings", () => { }); }); + it("refuses a settings write over malformed JSON without changing the file or workspace history", async () => { + await withTempPmRoot(async (pmRoot) => { + const settingsPath = getSettingsPath(pmRoot); + const malformed = "{ invalid-json"; + await fs.mkdir(path.dirname(settingsPath), { recursive: true }); + await fs.writeFile(settingsPath, malformed, "utf8"); + + const settings = await readSettings(pmRoot); + await expect(writeSettings(pmRoot, settings)).rejects.toMatchObject({ + code: "settings_write_invalid_existing_json", + exitCode: 2, + }); + expect(await fs.readFile(settingsPath, "utf8")).toBe(malformed); + await expect(fs.stat(getWorkspaceHistoryPath(pmRoot))).rejects.toMatchObject({ code: "ENOENT" }); + }); + }); + it("falls back and recovers when settings.json cannot be read as a file", async () => { await withTempPmRoot(async (pmRoot) => { const settingsPath = getSettingsPath(pmRoot);