From 5d804f0f6ec0eb29039f76455c9fa99755be6a65 Mon Sep 17 00:00:00 2001 From: Stefan Preu Date: Sun, 27 Sep 2026 13:54:46 +0200 Subject: [PATCH 1/3] Refuse malformed settings writes with typed recovery Parse the existing settings document under the workspace-history lock and stop configuration writes when its JSON is malformed. Return a stable settings_write_invalid_existing_json error with repair steps before any document or history mutation. Cover the refusal with a real persistence regression and disposable CLI acceptance, update the public error contracts and configuration guidance, and record the Sentry production defect plus verified closeout in pm history and the generated changelog. --- .../pm/extensions/.managed-extensions.json | 2 +- .agents/pm/history/pm-z329kd.jsonl | 17 +++++ .agents/pm/issues/pm-z329kd.toon | 74 +++++++++++++++++++ CHANGELOG.md | 1 + docs/CONFIGURATION.md | 2 + docs/generated/REFUSAL_CLOSURE_CENSUS.md | 7 +- sdk/public-surface.json | 1 + src/core/store/settings.ts | 44 ++++++++--- .../generated-error-code-catalog-part-1.ts | 13 ++++ .../generated-error-code-catalog-part-2.ts | 26 +++---- tests/fixtures/contracts/full.json | 17 +++++ tests/unit/core/store/settings-store.spec.ts | 18 +++++ 12 files changed, 195 insertions(+), 27 deletions(-) create mode 100644 .agents/pm/history/pm-z329kd.jsonl create mode 100644 .agents/pm/issues/pm-z329kd.toon 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-z329kd.jsonl b/.agents/pm/history/pm-z329kd.jsonl new file mode 100644 index 000000000..4480b534f --- /dev/null +++ b/.agents/pm/history/pm-z329kd.jsonl @@ -0,0 +1,17 @@ +{"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"} diff --git a/.agents/pm/issues/pm-z329kd.toon b/.agents/pm/issues/pm-z329kd.toon new file mode 100644 index 000000000..fb4e63abb --- /dev/null +++ b/.agents/pm/issues/pm-z329kd.toon @@ -0,0 +1,74 @@ +id: pm-z329kd +title: Malformed settings writes escape as unclassified Sentry faults +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-27T11:49:25.972Z" +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..d95027cde 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)) +- Malformed settings writes escape as unclassified Sentry faults ([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); From 71fabab400fa9f0e3f22490e511529685f2968b7 Mon Sep 17 00:00:00 2001 From: Stefan Preu Date: Sun, 27 Sep 2026 14:08:20 +0200 Subject: [PATCH 2/3] Describe the settings refusal in generated changelog Rename the closed PM issue to state the delivered behavior, then regenerate CHANGELOG.md from the updated item. This makes the Fixed entry describe the typed refusal rather than the escaped fault. --- .agents/pm/history/pm-z329kd.jsonl | 1 + .agents/pm/issues/pm-z329kd.toon | 4 ++-- CHANGELOG.md | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.agents/pm/history/pm-z329kd.jsonl b/.agents/pm/history/pm-z329kd.jsonl index 4480b534f..1d0480e2c 100644 --- a/.agents/pm/history/pm-z329kd.jsonl +++ b/.agents/pm/history/pm-z329kd.jsonl @@ -15,3 +15,4 @@ {"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-z329kd.toon b/.agents/pm/issues/pm-z329kd.toon index fb4e63abb..d114f0b1e 100644 --- a/.agents/pm/issues/pm-z329kd.toon +++ b/.agents/pm/issues/pm-z329kd.toon @@ -1,12 +1,12 @@ id: pm-z329kd -title: Malformed settings writes escape as unclassified Sentry faults +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-27T11:49:25.972Z" +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" diff --git a/CHANGELOG.md b/CHANGELOG.md index d95027cde..c4ac0c765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +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)) -- Malformed settings writes escape as unclassified Sentry faults ([pm-z329kd](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-z329kd.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 From 2ddf1cd7aa1774b06497dee0dc758035232a2b18 Mon Sep 17 00:00:00 2001 From: Stefan Preu Date: Sun, 27 Sep 2026 14:30:20 +0200 Subject: [PATCH 3/3] Track new GitHub defects in canonical PM lineage Add five open PM issues for the recent command-help, linked-test evidence, history cursor, and two distinct Windows nightly failures. Each intake records its GitHub source, reproduction, acceptance criteria, parent, duplicate check, and typed historical relationships. Keep the two Windows shard failures separate because one timed out during bundled package initialization while the other failed the static inventory unreadable-source assertion. Verify every new history stream and the repository graph before review. --- .agents/pm/history/pm-aao1hy.jsonl | 1 + .agents/pm/history/pm-c3aiik.jsonl | 1 + .agents/pm/history/pm-ft90q2.jsonl | 1 + .agents/pm/history/pm-kvhnb5.jsonl | 2 ++ .agents/pm/history/pm-s8ztcl.jsonl | 1 + .agents/pm/issues/pm-aao1hy.toon | 29 +++++++++++++++++++++++++++++ .agents/pm/issues/pm-c3aiik.toon | 29 +++++++++++++++++++++++++++++ .agents/pm/issues/pm-ft90q2.toon | 29 +++++++++++++++++++++++++++++ .agents/pm/issues/pm-kvhnb5.toon | 30 ++++++++++++++++++++++++++++++ .agents/pm/issues/pm-s8ztcl.toon | 29 +++++++++++++++++++++++++++++ 10 files changed, 152 insertions(+) create mode 100644 .agents/pm/history/pm-aao1hy.jsonl create mode 100644 .agents/pm/history/pm-c3aiik.jsonl create mode 100644 .agents/pm/history/pm-ft90q2.jsonl create mode 100644 .agents/pm/history/pm-kvhnb5.jsonl create mode 100644 .agents/pm/history/pm-s8ztcl.jsonl create mode 100644 .agents/pm/issues/pm-aao1hy.toon create mode 100644 .agents/pm/issues/pm-c3aiik.toon create mode 100644 .agents/pm/issues/pm-ft90q2.toon create mode 100644 .agents/pm/issues/pm-kvhnb5.toon create mode 100644 .agents/pm/issues/pm-s8ztcl.toon 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/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: ""