diff --git a/.agents/pm/chores/pm-bdvm.toon b/.agents/pm/chores/pm-bdvm.toon index c0b067a36..fc50aa320 100644 --- a/.agents/pm/chores/pm-bdvm.toon +++ b/.agents/pm/chores/pm-bdvm.toon @@ -2,14 +2,18 @@ id: pm-bdvm title: Add remediation registry entry for extension_update_health_partial_coverage warning description: "The remediation registry (src/core/diagnostics/remediation.ts) covers all core pm health / pm validate warning codes but is missing an entry for `extension_update_health_partial_coverage`, which is emitted by the extensions health check when unmanaged extensions are present (health.ts line 705). Agents gating on pm health --json get a warning with no remediation_map entry, so they must hardcode the fix command." type: Chore -status: open +status: closed priority: 3 tags[3]: agent-ux,"area:health","area:observability" created_at: "2026-06-07T10:03:47.039Z" -updated_at: "2026-06-07T10:16:05.087Z" +updated_at: "2026-06-19T20:57:52.270Z" author: audit-observability-agent acceptance_criteria: "- Add `extension_update_health_partial_coverage` code to REMEDIATION_REGISTRY with command: 'pm extension --adopt-all --project' and a summary explaining the adoption flow.\n- The existing mutually-exclusive-codes test in remediation-registry.spec.ts still passes.\n- pm health --json on a repo with unmanaged extensions shows remediation_map for this code." parent: pm-5oj5 risk: low confidence: high +resolution: "src/core/diagnostics/remediation.ts: new extensions-section registry entry. src/cli/commands/health.ts: checkRemediationSources made total and extensions:extensionCheck.warnings added; dead 'sources===undefined' guard removed. Tests: health-command.spec remediation_map assertion + remediation-registry.spec resolveRemediation assertion. Verified in sandbox (skipped_unmanaged:1 -> adopt-all command)." +dependencies[1]{id,kind,created_at,author,source_kind}: + pm-sdbo,related,"2026-06-19T20:43:15.807Z",null,null +close_reason: "Implemented: added extension_update_health_partial_coverage to REMEDIATION_REGISTRY (command 'pm extension --adopt-all --project') and wired the extensions check into pm health's checkRemediationSources (now total over HealthCheck['name']). pm health --json on a repo with unmanaged extensions now emits details.remediation_map for this code; other per-extension findings keep their richer triage.remediation and resolve to nothing in the registry." body: "## Context\n\nFile: src/cli/commands/health.ts line 705 — warning `extension_update_health_partial_coverage:skipped_unmanaged:` is emitted when extensions are unmanaged.\n\nFile: src/core/diagnostics/remediation.ts — no entry for `extension_update_health_partial_coverage`. The comment at line 40 says extension findings are excluded, but partial-coverage is not a per-extension triage result — it is a system-wide finding about adoption gaps, making it a legitimate registry candidate.\n\n## Acceptance criteria\n\n- Add `extension_update_health_partial_coverage` code to REMEDIATION_REGISTRY with command: 'pm extension --adopt-all --project' and a summary explaining the adoption flow.\n- The existing mutually-exclusive-codes test in remediation-registry.spec.ts still passes.\n- pm health --json on a repo with unmanaged extensions shows remediation_map for this code.\n\n## Evidence\n\nsrc/cli/commands/health.ts:705 — warning code emitted.\nsrc/core/diagnostics/remediation.ts:43 — registry list; no extension_update_health_partial_coverage entry." diff --git a/.agents/pm/chores/pm-sdbo.toon b/.agents/pm/chores/pm-sdbo.toon new file mode 100644 index 000000000..9b6924335 --- /dev/null +++ b/.agents/pm/chores/pm-sdbo.toon @@ -0,0 +1,21 @@ +id: pm-sdbo +title: Add remediation registry entry for validate_metadata_duplicate_issue_codes warning +description: "pm validate emits validate_metadata_duplicate_issue_codes:N (GH-235) as an advisory metadata warning, but the shared remediation registry (src/core/diagnostics/remediation.ts) has no entry for it. So pm validate --fix-hints surfaces every other metadata finding's fix command but leaves duplicate-issue-code findings with no machine-executable remediation, forcing agents to hardcode the rename/merge fix." +type: Chore +status: closed +priority: 3 +tags[3]: agent-ux,"area:observability","area:validate" +created_at: "2026-06-19T20:43:00.587Z" +updated_at: "2026-06-19T20:57:52.778Z" +author: claude-code-agent +acceptance_criteria: Add validate_metadata_duplicate_issue_codes to REMEDIATION_REGISTRY with an executable command + summary covering the rename-or-close-as-duplicate fix; the mutual-exclusivity test still passes; pm validate --fix-hints on a tracker with duplicate issue codes lists the fix command. +parent: pm-5oj5 +risk: low +confidence: high +resolution: "src/core/diagnostics/remediation.ts: new validate-metadata registry entry before the resolution section. Tests: validate-command.spec attachValidateFixHints assertion + remediation-registry.spec resolveRemediation assertion. Verified in sandbox (two BUG-7 issues -> fix_hints includes the title command)." +dependencies[3]{id,kind,created_at,author,source_kind}: + pm-bdvm,related,"2026-06-19T20:43:15.520Z",null,null + pm-cc04,related,"2026-06-19T20:43:15.520Z",null,null + pm-sz6w,related,"2026-06-19T20:43:15.520Z",null,null +close_reason: "Implemented: added validate_metadata_duplicate_issue_codes to REMEDIATION_REGISTRY with command 'pm update --title \"\"' and a summary covering the rename-or-close-as-duplicate fix. pm validate --check-metadata --fix-hints now lists the fix command for duplicate-issue-code findings (GH-235) instead of leaving them with no machine-executable remediation." +body: "" diff --git a/.agents/pm/history/pm-28cf.jsonl b/.agents/pm/history/pm-28cf.jsonl index 8d6db8cbc..62ff85848 100644 --- a/.agents/pm/history/pm-28cf.jsonl +++ b/.agents/pm/history/pm-28cf.jsonl @@ -1,2 +1,6 @@ {"ts":"2026-06-16T11:28:29.128Z","author":"codex-sdk-cli-consolidation-20260616","op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-28cf"},{"op":"add","path":"/metadata/title","value":"GH-244: empty search provider adapter strings should auto-normalize"},{"op":"add","path":"/metadata/description","value":"Tracks GitHub issue #244: empty search.provider/vector_store.adapter strings should not persist as misleading not-configured values after runtime auto-detection."},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":2},{"op":"add","path":"/metadata/tags","value":[]},{"op":"add","path":"/metadata/created_at","value":"2026-06-16T11:28:29.128Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-06-16T11:28:29.128Z"},{"op":"add","path":"/metadata/author","value":"codex-sdk-cli-consolidation-20260616"},{"op":"add","path":"/metadata/parent","value":"pm-8jdc"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"c075081c2287175ef179401212e965c17c337ee080b6488d3957374e0debae17","message":""} {"ts":"2026-06-18T21:58:24.218Z","author":"claude-code-agent","op":"comment_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-06-18T21:58:24.218Z"},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-06-18T21:58:24.218Z","author":"claude-code-agent","text":"Triage (during pm-ldr1/GH-157 work): GH-244 is CLOSED on GitHub — resolved in #254 (commit 0447c6e4) by surfacing provider_source/vector_store_source + persisted *_configured values in pm health, so auto-detected providers are no longer misreported as 'not configured'. The narrower 'persist the resolved provider/adapter strings back into settings.json' idea is DECLINED: writing settings.json on every read risks the governance persist-trap (cf pm-haak file-backed-schema leak) and churns the file under VCS. Recommend closing as resolved-by-#254 in a NON-release-bearing touch (closing here would mis-bucket the changelog since the fix already shipped). Related: [[pm-ldr1]] search ergonomics."}]}],"before_hash":"c075081c2287175ef179401212e965c17c337ee080b6488d3957374e0debae17","after_hash":"810626a8b0e2de8cb51dba895564a165ebdafeef32766c89bfa317371b78c76c"} +{"ts":"2026-06-19T20:57:11.856Z","author":"claude-code-agent","op":"note_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-06-19T20:57:11.856Z"},{"op":"add","path":"/metadata/notes","value":[{"created_at":"2026-06-19T20:57:11.856Z","author":"claude-code-agent","text":"Verified GH-244 is already fully implemented and the GitHub issue is CLOSED. resolveProviderConfigSource() (src/core/search/providers.ts:61) classifies configured|auto-detected|unconfigured, and pm health surfaces provider_configured/provider_source + vector_store_configured/vector_store_source in the vectorization check (src/cli/commands/health.ts:1518-1533), so a config audit can tell an auto-detected empty provider/adapter apart from a genuine misconfiguration. No code change required."}]}],"before_hash":"810626a8b0e2de8cb51dba895564a165ebdafeef32766c89bfa317371b78c76c","after_hash":"b694b5a6a6b695e11dd2602ec0f0ffa4f9f21f00f0b97637d7fb477683831dad"} +{"ts":"2026-06-19T20:57:18.041Z","author":"claude-code-agent","op":"close","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-06-19T20:57:18.041Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/resolution","value":"Verified the runtime provider/adapter source classifier and pm health surfacing already satisfy GH-244; closing the stale tracking item."},{"op":"add","path":"/metadata/close_reason","value":"Already shipped: GH-244 implemented via resolveProviderConfigSource + pm health provider_source/vector_store_source surfacing; GitHub issue #244 is CLOSED. Verified in this session, no further code change needed."}],"before_hash":"b694b5a6a6b695e11dd2602ec0f0ffa4f9f21f00f0b97637d7fb477683831dad","after_hash":"d702fb64db6250ddbc84dbcc5ad6346341a358dee58f5961e264a363bc789160"} +{"ts":"2026-06-19T21:20:03.575Z","author":"claude-code-agent","op":"update","patch":[{"op":"remove","path":"/metadata/close_reason"},{"op":"replace","path":"/metadata/updated_at","value":"2026-06-19T21:20:03.575Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"d702fb64db6250ddbc84dbcc5ad6346341a358dee58f5961e264a363bc789160","after_hash":"a6568b1475d217bf4adea054eda106fec97d9ce3f36741ed378a38f6d46e0855"} +{"ts":"2026-06-19T21:20:03.881Z","author":"claude-code-agent","op":"note_add","patch":[{"op":"add","path":"/metadata/notes/1","value":{"created_at":"2026-06-19T21:20:03.881Z","author":"claude-code-agent","text":"Reopened in PR #306: GH-244 is verified already-shipped (#254, commit 0447c6e4). Closing this item in a release-bearing PR mis-buckets the CHANGELOG (CodeRabbit + prior triage both flagged it would list GH-244 under the next release's Fixed though the fix already shipped). Close only in a NON-release-bearing touch. The verification of the implementation stands."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-06-19T21:20:03.881Z"}],"before_hash":"a6568b1475d217bf4adea054eda106fec97d9ce3f36741ed378a38f6d46e0855","after_hash":"ebf7589566687bba7648e0915d4f7c59eb6e8cd1c274c81c5228af7bec739fd1"} diff --git a/.agents/pm/history/pm-bdvm.jsonl b/.agents/pm/history/pm-bdvm.jsonl index 6e40a25a0..52b858e68 100644 --- a/.agents/pm/history/pm-bdvm.jsonl +++ b/.agents/pm/history/pm-bdvm.jsonl @@ -1,2 +1,4 @@ {"ts":"2026-06-07T10:03:47.039Z","author":"audit-observability-agent","op":"create","patch":[{"op":"replace","path":"/body","value":"## Context\n\nFile: src/cli/commands/health.ts line 705 — warning `extension_update_health_partial_coverage:skipped_unmanaged:` is emitted when extensions are unmanaged.\n\nFile: src/core/diagnostics/remediation.ts — no entry for `extension_update_health_partial_coverage`. The comment at line 40 says extension findings are excluded, but partial-coverage is not a per-extension triage result — it is a system-wide finding about adoption gaps, making it a legitimate registry candidate.\n\n## Acceptance criteria\n\n- Add `extension_update_health_partial_coverage` code to REMEDIATION_REGISTRY with command: 'pm extension --adopt-all --project' and a summary explaining the adoption flow.\n- The existing mutually-exclusive-codes test in remediation-registry.spec.ts still passes.\n- pm health --json on a repo with unmanaged extensions shows remediation_map for this code.\n\n## Evidence\n\nsrc/cli/commands/health.ts:705 — warning code emitted.\nsrc/core/diagnostics/remediation.ts:43 — registry list; no extension_update_health_partial_coverage entry."},{"op":"add","path":"/metadata/id","value":"pm-bdvm"},{"op":"add","path":"/metadata/title","value":"Add remediation registry entry for extension_update_health_partial_coverage warning"},{"op":"add","path":"/metadata/description","value":"The remediation registry (src/core/diagnostics/remediation.ts) covers all core pm health / pm validate warning codes but is missing an entry for `extension_update_health_partial_coverage`, which is emitted by the extensions health check when unmanaged extensions are present (health.ts line 705). Agents gating on pm health --json get a warning with no remediation_map entry, so they must hardcode the fix command."},{"op":"add","path":"/metadata/type","value":"Chore"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":3},{"op":"add","path":"/metadata/tags","value":["agent-ux","area:health","area:observability"]},{"op":"add","path":"/metadata/created_at","value":"2026-06-07T10:03:47.039Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-06-07T10:03:47.039Z"},{"op":"add","path":"/metadata/author","value":"audit-observability-agent"},{"op":"add","path":"/metadata/acceptance_criteria","value":"Registry entry present; mutually-exclusive-codes test passes; --json shows remediation_map for the code when unmanaged extensions exist."},{"op":"add","path":"/metadata/parent","value":"pm-5oj5"},{"op":"add","path":"/metadata/risk","value":"low"},{"op":"add","path":"/metadata/confidence","value":"high"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"3709cb3483eacbfb37f8e27bdf4a076be890ca2844b93c90516c379b0ab5dc97","message":""} {"ts":"2026-06-07T10:16:05.087Z","author":"maintainer-agent","op":"update","patch":[{"op":"replace","path":"/metadata/acceptance_criteria","value":"- Add `extension_update_health_partial_coverage` code to REMEDIATION_REGISTRY with command: 'pm extension --adopt-all --project' and a summary explaining the adoption flow.\n- The existing mutually-exclusive-codes test in remediation-registry.spec.ts still passes.\n- pm health --json on a repo with unmanaged extensions shows remediation_map for this code."},{"op":"replace","path":"/metadata/updated_at","value":"2026-06-07T10:16:05.087Z"}],"before_hash":"3709cb3483eacbfb37f8e27bdf4a076be890ca2844b93c90516c379b0ab5dc97","after_hash":"17814db5737a1c5ae7d67c44b0951fe33872c7c67a9d90e1e83b7bb3375cddcb","message":"Backfill structured acceptance_criteria from body (best-practice/dogfooding)"} +{"ts":"2026-06-19T20:43:15.817Z","author":"claude-code-agent","op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-06-19T20:43:15.817Z"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-sdbo","kind":"related","created_at":"2026-06-19T20:43:15.807Z"}]}],"before_hash":"17814db5737a1c5ae7d67c44b0951fe33872c7c67a9d90e1e83b7bb3375cddcb","after_hash":"967ae7ef4abbbde3a754cdf1b2bb122ef10c9ac06d04b10e146978fc30e8879e"} +{"ts":"2026-06-19T20:57:52.270Z","author":"claude-code-agent","op":"close","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-06-19T20:57:52.270Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/resolution","value":"src/core/diagnostics/remediation.ts: new extensions-section registry entry. src/cli/commands/health.ts: checkRemediationSources made total and extensions:extensionCheck.warnings added; dead 'sources===undefined' guard removed. Tests: health-command.spec remediation_map assertion + remediation-registry.spec resolveRemediation assertion. Verified in sandbox (skipped_unmanaged:1 -> adopt-all command)."},{"op":"add","path":"/metadata/close_reason","value":"Implemented: added extension_update_health_partial_coverage to REMEDIATION_REGISTRY (command 'pm extension --adopt-all --project') and wired the extensions check into pm health's checkRemediationSources (now total over HealthCheck['name']). pm health --json on a repo with unmanaged extensions now emits details.remediation_map for this code; other per-extension findings keep their richer triage.remediation and resolve to nothing in the registry."}],"before_hash":"967ae7ef4abbbde3a754cdf1b2bb122ef10c9ac06d04b10e146978fc30e8879e","after_hash":"893b89955f41508007ee95712a16ccc5329a3ff98ab80c15be4b39728a872031"} diff --git a/.agents/pm/history/pm-sdbo.jsonl b/.agents/pm/history/pm-sdbo.jsonl new file mode 100644 index 000000000..c3c5ec6f4 --- /dev/null +++ b/.agents/pm/history/pm-sdbo.jsonl @@ -0,0 +1,3 @@ +{"ts":"2026-06-19T20:43:00.587Z","author":"claude-code-agent","op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-sdbo"},{"op":"add","path":"/metadata/title","value":"Add remediation registry entry for validate_metadata_duplicate_issue_codes warning"},{"op":"add","path":"/metadata/description","value":"pm validate emits validate_metadata_duplicate_issue_codes:N (GH-235) as an advisory metadata warning, but the shared remediation registry (src/core/diagnostics/remediation.ts) has no entry for it. So pm validate --fix-hints surfaces every other metadata finding's fix command but leaves duplicate-issue-code findings with no machine-executable remediation, forcing agents to hardcode the rename/merge fix."},{"op":"add","path":"/metadata/type","value":"Chore"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":3},{"op":"add","path":"/metadata/tags","value":["agent-ux","area:observability","area:validate"]},{"op":"add","path":"/metadata/created_at","value":"2026-06-19T20:43:00.587Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-06-19T20:43:00.587Z"},{"op":"add","path":"/metadata/author","value":"claude-code-agent"},{"op":"add","path":"/metadata/acceptance_criteria","value":"Add validate_metadata_duplicate_issue_codes to REMEDIATION_REGISTRY with an executable command + summary covering the rename-or-close-as-duplicate fix; the mutual-exclusivity test still passes; pm validate --fix-hints on a tracker with duplicate issue codes lists the fix command."},{"op":"add","path":"/metadata/parent","value":"pm-5oj5"},{"op":"add","path":"/metadata/risk","value":"low"},{"op":"add","path":"/metadata/confidence","value":"high"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"7e01706a76eae23e1553afca977834c41230b41caf85512c02a8e7928c4e1036","message":""} +{"ts":"2026-06-19T20:43:15.529Z","author":"claude-code-agent","op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-06-19T20:43:15.529Z"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-bdvm","kind":"related","created_at":"2026-06-19T20:43:15.520Z"},{"id":"pm-cc04","kind":"related","created_at":"2026-06-19T20:43:15.520Z"},{"id":"pm-sz6w","kind":"related","created_at":"2026-06-19T20:43:15.520Z"}]}],"before_hash":"7e01706a76eae23e1553afca977834c41230b41caf85512c02a8e7928c4e1036","after_hash":"2f10a2c427877c4ee839d9a06eba4f9fae06a3811f327cc8be1470a7029c3074"} +{"ts":"2026-06-19T20:57:52.778Z","author":"claude-code-agent","op":"close","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-06-19T20:57:52.778Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/resolution","value":"src/core/diagnostics/remediation.ts: new validate-metadata registry entry before the resolution section. Tests: validate-command.spec attachValidateFixHints assertion + remediation-registry.spec resolveRemediation assertion. Verified in sandbox (two BUG-7 issues -> fix_hints includes the title command)."},{"op":"add","path":"/metadata/close_reason","value":"Implemented: added validate_metadata_duplicate_issue_codes to REMEDIATION_REGISTRY with command 'pm update --title \"\"' and a summary covering the rename-or-close-as-duplicate fix. pm validate --check-metadata --fix-hints now lists the fix command for duplicate-issue-code findings (GH-235) instead of leaving them with no machine-executable remediation."}],"before_hash":"2f10a2c427877c4ee839d9a06eba4f9fae06a3811f327cc8be1470a7029c3074","after_hash":"743b5bfe43710a580ba80736da8a2bcdbd6f075e0233d63e6ae8c18d226fa11f"} diff --git a/.agents/pm/issues/pm-28cf.toon b/.agents/pm/issues/pm-28cf.toon index baa9a0ed4..65623e2bf 100644 --- a/.agents/pm/issues/pm-28cf.toon +++ b/.agents/pm/issues/pm-28cf.toon @@ -6,9 +6,13 @@ status: open priority: 2 tags: [] created_at: "2026-06-16T11:28:29.128Z" -updated_at: "2026-06-18T21:58:24.218Z" +updated_at: "2026-06-19T21:20:03.881Z" author: codex-sdk-cli-consolidation-20260616 parent: pm-8jdc +resolution: Verified the runtime provider/adapter source classifier and pm health surfacing already satisfy GH-244; closing the stale tracking item. comments[1]{created_at,author,text}: "2026-06-18T21:58:24.218Z",claude-code-agent,"Triage (during pm-ldr1/GH-157 work): GH-244 is CLOSED on GitHub — resolved in #254 (commit 0447c6e4) by surfacing provider_source/vector_store_source + persisted *_configured values in pm health, so auto-detected providers are no longer misreported as 'not configured'. The narrower 'persist the resolved provider/adapter strings back into settings.json' idea is DECLINED: writing settings.json on every read risks the governance persist-trap (cf pm-haak file-backed-schema leak) and churns the file under VCS. Recommend closing as resolved-by-#254 in a NON-release-bearing touch (closing here would mis-bucket the changelog since the fix already shipped). Related: [[pm-ldr1]] search ergonomics." +notes[2]{created_at,author,text}: + "2026-06-19T20:57:11.856Z",claude-code-agent,"Verified GH-244 is already fully implemented and the GitHub issue is CLOSED. resolveProviderConfigSource() (src/core/search/providers.ts:61) classifies configured|auto-detected|unconfigured, and pm health surfaces provider_configured/provider_source + vector_store_configured/vector_store_source in the vectorization check (src/cli/commands/health.ts:1518-1533), so a config audit can tell an auto-detected empty provider/adapter apart from a genuine misconfiguration. No code change required." + "2026-06-19T21:20:03.881Z",claude-code-agent,"Reopened in PR #306: GH-244 is verified already-shipped (#254, commit 0447c6e4). Closing this item in a release-bearing PR mis-buckets the CHANGELOG (CodeRabbit + prior triage both flagged it would list GH-244 under the next release's Fixed though the fix already shipped). Close only in a NON-release-bearing touch. The verification of the implementation stands." body: "" diff --git a/CHANGELOG.md b/CHANGELOG.md index 34cb5b4db..d5842d46d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added +- Add remediation registry entry for validate\_metadata\_duplicate\_issue\_codes warning ([pm-sdbo](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/chores/pm-sdbo.toon)) +- Add remediation registry entry for extension\_update\_health\_partial\_coverage warning ([pm-bdvm](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/chores/pm-bdvm.toon)) - gc --scope checkpoints: prune stale bulk-mutation checkpoint files ([pm-tyj8](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/features/pm-tyj8.toon)) - LanceDB snapshot: add gc --scope embeddings to include pending-refresh.json and drift-cache coordination ([pm-3b1t](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/chores/pm-3b1t.toon)) - Sentry KNOWN\_NOISY\_CONSOLE\_MESSAGE\_PATTERNS maintenance: add a governance test to prevent silent accumulation of stale patterns ([pm-jxls](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/chores/pm-jxls.toon)) diff --git a/src/cli/commands/health.ts b/src/cli/commands/health.ts index 289cf5f2d..f6c54f929 100644 --- a/src/cli/commands/health.ts +++ b/src/cli/commands/health.ts @@ -1767,11 +1767,19 @@ export async function runHealth(global: GlobalOptions, options: RunHealthOptions // never have to hardcode the warning-code -> fix mapping. The extensions check // keeps its richer, contextual `details.triage.remediation`; brief/summary // projections omit remediation_map (it lives only in full check details). - const checkRemediationSources: Partial> = { + // Every health check contributes its warning tokens as a remediation source. + // Most resolve to a registered fix command; the extensions check passes its + // full warning list because only the system-wide partial-coverage adoption + // gap is registered — per-extension findings resolve to nothing here and keep + // their richer `details.triage.remediation`, so buildRemediationMap simply + // skips every unregistered code (pm-bdvm). The map is total over + // HealthCheck["name"], so no check is ever silently missing a source. + const checkRemediationSources: Record = { settings: normalizedSettingsReadWarnings, directories: missingDirs.map((dir) => `missing_directory:${dir}`), settings_values: settingWarnings, telemetry: telemetryCheck.warnings, + extensions: extensionCheck.warnings, storage: historySummary.over_threshold.map((id) => `history_stream_over_compact_threshold:${id}`), locks: locksCheck.warnings, integrity: integrityCheck.warnings, @@ -1783,11 +1791,7 @@ export async function runHealth(global: GlobalOptions, options: RunHealthOptions ? ((historyDriftCheck.check.details.counts as { drifted: number }).drifted) : 0; for (const check of checks) { - const sources = checkRemediationSources[check.name]; - if (sources === undefined) { - continue; - } - const remediationMap = buildRemediationMap(sources); + const remediationMap = buildRemediationMap(checkRemediationSources[check.name]); // With multiple drifted streams the per-item `pm history-repair ` // template would have to be run once per stream; suggest the bulk audited // pass instead so agents repair everything in one command. diff --git a/src/core/diagnostics/remediation.ts b/src/core/diagnostics/remediation.ts index 02e8c20db..9e92f3be4 100644 --- a/src/core/diagnostics/remediation.ts +++ b/src/core/diagnostics/remediation.ts @@ -193,6 +193,19 @@ export const REMEDIATION_REGISTRY: readonly RemediationEntry[] = Object.freeze([ summary: "Some lock files could not be read; preview the sweep and inspect the unreadable files manually — gc never deletes what it cannot read.", }, + // --- pm health: extensions --- + // Most extension findings keep their richer, contextual + // `details.triage.remediation` and are intentionally absent here. The + // partial-coverage code is the exception: it is not a per-extension triage + // result but a system-wide adoption gap (unmanaged installs the update-health + // scan had to skip), so it has a single deterministic fix and belongs in the + // shared registry like any other health finding (pm-bdvm). + { + code: "extension_update_health_partial_coverage", + command: "pm extension --adopt-all --project", + summary: + "Update-health coverage is partial because unmanaged extensions were skipped; adopt the existing installs into managed metadata so the update scan covers them (use --global for global-scope extensions, or pm package --adopt-all when working with packages).", + }, // --- pm health: vectorization --- { code: "vectorization_stale_items_remaining", @@ -256,6 +269,12 @@ export const REMEDIATION_REGISTRY: readonly RemediationEntry[] = Object.freeze([ summary: "Config-driven finding: the custom metadata profile has no required fields configured and falls back to core, so configure the fields rather than mutating items.", }, + { + code: "validate_metadata_duplicate_issue_codes", + command: 'pm update --title ""', + summary: + "Two or more items share one logical issue code (GH-235); give each a distinct title so the derived code is unique, or close the redundant item with pm close --duplicate-of (closed-as-duplicate items are excluded from the check).", + }, // --- pm validate: resolution --- { code: "validate_resolution_missing_fields", diff --git a/tests/integration/remediation-registry.spec.ts b/tests/integration/remediation-registry.spec.ts index 45089538d..4437a479a 100644 --- a/tests/integration/remediation-registry.spec.ts +++ b/tests/integration/remediation-registry.spec.ts @@ -71,6 +71,18 @@ describe("shared remediation registry", () => { ); }); + it("resolves the unmanaged-extension partial-coverage gap to adopt-all guidance", () => { + expect(resolveRemediation("extension_update_health_partial_coverage:skipped_unmanaged:2")?.command).toBe( + "pm extension --adopt-all --project", + ); + }); + + it("resolves the duplicate-issue-code metadata warning to rename/close guidance", () => { + expect(resolveRemediation("validate_metadata_duplicate_issue_codes:3")?.command).toBe( + 'pm update --title ""', + ); + }); + it("resolves pm health locks warnings to gc lock-sweep guidance", () => { expect(resolveRemediation("locks_stale_count:3")?.command).toBe("pm gc --scope locks"); expect(resolveRemediation("locks_unreadable:1")?.command).toBe("pm gc --scope locks --dry-run"); diff --git a/tests/unit/commands/health-command.spec.ts b/tests/unit/commands/health-command.spec.ts index 7cbe52794..5da1f3461 100644 --- a/tests/unit/commands/health-command.spec.ts +++ b/tests/unit/commands/health-command.spec.ts @@ -1363,6 +1363,14 @@ describe("runHealth", () => { activation_failure_count: 0, }, }); + // The system-wide adoption gap surfaces a machine-executable remediation + // map alongside the per-extension triage; the load-failure code is not in + // the shared registry and is intentionally absent (pm-bdvm). + expect( + (extensionCheck?.details as { remediation_map?: Record }).remediation_map, + ).toEqual({ + extension_update_health_partial_coverage: "pm extension --adopt-all --project", + }); const loaded = ( extensionCheck?.details as { loaded?: Array<{ name: string; has_activate: boolean; module?: unknown }> } diff --git a/tests/unit/commands/validate-command.spec.ts b/tests/unit/commands/validate-command.spec.ts index fefce54f6..b302c7f63 100644 --- a/tests/unit/commands/validate-command.spec.ts +++ b/tests/unit/commands/validate-command.spec.ts @@ -183,6 +183,20 @@ describe("runValidate", () => { validateInternals.attachValidateFixHints(checkWithoutHints, []); expect(checkWithoutHints.details).toEqual({}); + // The duplicate-issue-code metadata warning must resolve to an executable + // fix command now that it is in the shared remediation registry (pm-sdbo). + const metadataCheckWithDuplicates = { + name: "metadata", + status: "warn", + details: {}, + } as never; + validateInternals.attachValidateFixHints(metadataCheckWithDuplicates, [ + "validate_metadata_duplicate_issue_codes:2", + ]); + expect((metadataCheckWithDuplicates.details as { fix_hints?: string[] }).fix_hints).toEqual([ + 'pm update --title ""', + ]); + const graph = validateInternals.buildLifecycleDependencyGraph([ { id: "pm-a",