@unbrained/pm-cli 2026.9.4 → 2026.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/HARNESS_COMPATIBILITY.md +1 -1
- package/.agents/skills/README.md +2 -2
- package/.agents/skills/pm-developer/SKILL.md +4 -1
- package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +10 -0
- package/.agents/skills/pm-developer/references/GRAPH_AND_RELATIONSHIPS.md +3 -1
- package/.agents/skills/pm-extensions/SKILL.md +2 -2
- package/.agents/skills/pm-extensions/references/LIFECYCLE.md +3 -3
- package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +3 -3
- package/.agents/skills/pm-user/SKILL.md +2 -0
- package/.agents/skills/pm-user/references/BACKLOG_SHAPING.md +5 -0
- package/.agents/skills/pm-user/references/WORKFLOWS.md +20 -5
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +58 -3
- package/dist/cli/commander-usage.d.ts +2 -0
- package/dist/cli/commander-usage.js +15 -12
- package/dist/cli/help-json-payload.js +12 -7
- package/dist/cli/main.js +22 -11
- package/dist/cli/register-list-query.js +4 -2
- package/dist/cli/register-mutation.js +4 -2
- package/dist/cli/register-operations.js +17 -8
- package/dist/cli-bundle/bundle-manifest.json +153 -161
- package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +9 -0
- package/dist/cli-bundle/chunks/{chunk-V72UV7QS.js → chunk-BAX2BYUW.js} +73 -73
- package/dist/cli-bundle/chunks/{chunk-HI6BHPCU.js → chunk-CKOL5U7J.js} +51 -51
- package/dist/cli-bundle/chunks/{chunk-A24WAVE6.js → chunk-JT6XF6GE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-I2AS367G.js → chunk-JX4DH4WC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-YW4QK2G7.js → chunk-NPN5I67J.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +5 -0
- package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +232 -0
- package/dist/cli-bundle/chunks/{chunk-RI4XNOYS.js → chunk-RWWBOWJ5.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +40 -0
- package/dist/cli-bundle/chunks/{chunk-X6CMGV6L.js → chunk-WI2AYPA7.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-Z5YYSJJG.js → register-list-query-5JL52D33.js} +3 -3
- package/dist/cli-bundle/chunks/{register-mutation-ELSP6I4I.js → register-mutation-ZPG7KMVP.js} +4 -4
- package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-E2AE72QG.js → register-setup-H4SVAVX7.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-3646BZ4W.js → chunk-3BZEOXLT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +20 -0
- package/dist/cli-bundle/focused-chunks/{chunk-NBMJD6MK.js → chunk-EZR3GHFE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +56 -0
- package/dist/cli-bundle/focused-chunks/{chunk-53IHPICX.js → chunk-LIJIA4TY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-25UJBH4M.js → chunk-M6PBRFSH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-AJR3OP2E.js → chunk-NTPY5GSO.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +177 -0
- package/dist/cli-bundle/focused-chunks/{chunk-MHKUIPJW.js → chunk-PEFABF7E.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-6PWPQKDN.js → chunk-QTVCLMSZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-7N2TV7WZ.js → chunk-QTZRBUYA.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +10 -0
- package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +2 -0
- package/dist/cli-bundle/main.js +22 -15
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +37 -37
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +42 -39
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +9 -9
- package/dist/core/extensions/extension-types.d.ts +2 -0
- package/dist/core/extensions/extension-types.js +2 -2
- package/dist/core/extensions/module-graph-snapshot.js +5 -4
- package/dist/core/fs/host-environment-errors.d.ts +27 -0
- package/dist/core/fs/host-environment-errors.js +142 -0
- package/dist/core/history/drift-scan.d.ts +5 -0
- package/dist/core/history/drift-scan.js +16 -6
- package/dist/core/history/event-classification.d.ts +1 -1
- package/dist/core/history/event-classification.js +3 -2
- package/dist/core/history/history.js +37 -5
- package/dist/core/history/identity.d.ts +15 -0
- package/dist/core/history/identity.js +31 -0
- package/dist/core/history/projection.js +50 -17
- package/dist/core/history/read.js +6 -3
- package/dist/core/history/replay.d.ts +1 -2
- package/dist/core/history/replay.js +4 -4
- package/dist/core/history/version-address.d.ts +13 -0
- package/dist/core/history/version-address.js +33 -0
- package/dist/core/item/actionability.d.ts +21 -1
- package/dist/core/item/actionability.js +45 -10
- package/dist/core/item/id.js +8 -4
- package/dist/core/item/item-type-definition.d.ts +2 -0
- package/dist/core/item/item-type-definition.js +9 -2
- package/dist/core/item/type-registry.d.ts +5 -1
- package/dist/core/item/type-registry.js +9 -4
- package/dist/core/output/mutation-projection.js +12 -5
- package/dist/core/shared/errors.d.ts +8 -0
- package/dist/core/shared/errors.js +2 -2
- package/dist/core/store/item-metadata-query-index.js +13 -10
- package/dist/core/store/item-metadata-read-work.d.ts +19 -0
- package/dist/core/store/item-metadata-read-work.js +44 -0
- package/dist/core/store/item-store.d.ts +14 -0
- package/dist/core/store/item-store.js +52 -10
- package/dist/core/store/settings-validator.js +3 -2
- package/dist/core/validate/fix-planning.d.ts +1 -1
- package/dist/core/validate/fix-planning.js +2 -2
- package/dist/core/validate/missing-link-owners.d.ts +1 -1
- package/dist/core/validate/missing-link-owners.js +5 -3
- package/dist/core/validate/stale-file-classification.d.ts +6 -4
- package/dist/core/validate/stale-file-classification.js +20 -5
- package/dist/mcp/server.js +12 -5
- package/dist/sdk/actionability.d.ts +1 -1
- package/dist/sdk/actionability.js +3 -3
- package/dist/sdk/cli-contracts/command-aliases.js +11 -2
- package/dist/sdk/cli-contracts/completeness.js +4 -3
- package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
- package/dist/sdk/cli-contracts/flag-contracts.js +31 -5
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +21 -13
- package/dist/sdk/cli-contracts/grammar-contracts.js +11 -2
- package/dist/sdk/cli-contracts/runtime-contracts.js +5 -2
- package/dist/sdk/cli-contracts/schemas/assurance-definition.d.ts +254 -5
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +52 -2
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +30 -6
- package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
- package/dist/sdk/cli-contracts/tool-schema.js +32 -7
- package/dist/sdk/context/usage-ledger.d.ts +41 -0
- package/dist/sdk/context/usage-ledger.js +186 -0
- package/dist/sdk/context-intent-contracts.js +3 -3
- package/dist/sdk/context-usage.d.ts +18 -9
- package/dist/sdk/context-usage.js +44 -121
- package/dist/sdk/define.d.ts +1 -1
- package/dist/sdk/define.js +2 -2
- package/dist/sdk/dependency-provenance.d.ts +7 -0
- package/dist/sdk/dependency-provenance.js +14 -4
- package/dist/sdk/duplicates.d.ts +2 -0
- package/dist/sdk/duplicates.js +3 -2
- package/dist/sdk/environment/host-environment-errors.d.ts +5 -27
- package/dist/sdk/environment/host-environment-errors.js +4 -137
- package/dist/sdk/extension/install-runtime.js +9 -6
- package/dist/sdk/extension/install-snapshot.js +7 -6
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +104 -56
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +50 -2
- package/dist/sdk/governance/assurance-action.d.ts +3 -2
- package/dist/sdk/governance/assurance-action.js +23 -11
- package/dist/sdk/governance/assurance-runtime.d.ts +2 -0
- package/dist/sdk/governance/assurance-runtime.js +6 -3
- package/dist/sdk/governance/defect-recurrence-coverage.d.ts +93 -0
- package/dist/sdk/governance/defect-recurrence-coverage.js +189 -0
- package/dist/sdk/governance/defect-recurrence-graph.d.ts +33 -0
- package/dist/sdk/governance/defect-recurrence-graph.js +121 -0
- package/dist/sdk/governance/defect-recurrence.d.ts +8 -0
- package/dist/sdk/governance/defect-recurrence.js +118 -17
- package/dist/sdk/governance/health.d.ts +17 -2
- package/dist/sdk/governance/health.js +31 -10
- package/dist/sdk/governance/linked-file-report.d.ts +41 -0
- package/dist/sdk/governance/linked-file-report.js +72 -0
- package/dist/sdk/governance/validate-history-drift.js +16 -5
- package/dist/sdk/governance/validate.d.ts +5 -2
- package/dist/sdk/governance/validate.js +21 -37
- package/dist/sdk/governance.d.ts +2 -0
- package/dist/sdk/governance.js +4 -2
- package/dist/sdk/guide-topics.js +116 -2
- package/dist/sdk/history/salvage.d.ts +35 -0
- package/dist/sdk/history/salvage.js +248 -0
- package/dist/sdk/history-compact.js +32 -37
- package/dist/sdk/history-read.d.ts +3 -2
- package/dist/sdk/history-read.js +6 -3
- package/dist/sdk/history-repair.d.ts +12 -0
- package/dist/sdk/history-repair.js +60 -13
- package/dist/sdk/lifecycle/claim.d.ts +4 -0
- package/dist/sdk/lifecycle/claim.js +9 -3
- package/dist/sdk/lifecycle/close.d.ts +8 -0
- package/dist/sdk/lifecycle/close.js +16 -8
- package/dist/sdk/lifecycle/create.js +9 -12
- package/dist/sdk/lifecycle/restore.d.ts +1 -0
- package/dist/sdk/lifecycle/restore.js +19 -7
- package/dist/sdk/lifecycle/update.js +12 -12
- package/dist/sdk/lifecycle-policy.d.ts +3 -0
- package/dist/sdk/lifecycle-policy.js +2 -2
- package/dist/sdk/merge/abandoned-receipts.d.ts +15 -0
- package/dist/sdk/merge/abandoned-receipts.js +47 -0
- package/dist/sdk/merge/driver.js +4 -2
- package/dist/sdk/merge/index.d.ts +1 -0
- package/dist/sdk/merge/index.js +2 -2
- package/dist/sdk/merge/receipt-operation.d.ts +15 -0
- package/dist/sdk/merge/receipt-operation.js +97 -0
- package/dist/sdk/merge/receipt-schema.d.ts +20 -0
- package/dist/sdk/merge/receipt-schema.js +398 -0
- package/dist/sdk/merge/receipts.d.ts +16 -7
- package/dist/sdk/merge/receipts.js +54 -340
- package/dist/sdk/merge/reconcile.d.ts +2 -0
- package/dist/sdk/merge/reconcile.js +11 -4
- package/dist/sdk/output-projection.d.ts +3 -1
- package/dist/sdk/output-projection.js +11 -3
- package/dist/sdk/public-surface.json +1 -0
- package/dist/sdk/query/context.d.ts +9 -0
- package/dist/sdk/query/context.js +33 -21
- package/dist/sdk/query/duplicate-candidates.d.ts +7 -0
- package/dist/sdk/query/duplicate-candidates.js +71 -0
- package/dist/sdk/query/get.d.ts +2 -2
- package/dist/sdk/query/get.js +9 -8
- package/dist/sdk/query/history.d.ts +11 -0
- package/dist/sdk/query/history.js +34 -10
- package/dist/sdk/query/next.d.ts +15 -1
- package/dist/sdk/query/next.js +43 -20
- package/dist/sdk/query.d.ts +3 -0
- package/dist/sdk/query.js +5 -2
- package/dist/sdk/read-output-session.js +5 -3
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +3 -3
- package/dist/sdk/runtime.js +4 -2
- package/dist/sdk/similarity.d.ts +24 -3
- package/dist/sdk/similarity.js +50 -55
- package/dist/types.d.ts +2 -0
- package/dist/types.js +2 -2
- package/docs/AGENT_GUIDE.md +58 -1
- package/docs/BOUNDED_CONTEXT_READS.md +185 -0
- package/docs/CLOSE_EVIDENCE_RECOVERY.md +35 -0
- package/docs/COMMANDS.md +30 -8
- package/docs/CONTEXT_RELEVANCE.md +16 -4
- package/docs/DEFECT_RECURRENCE.md +80 -6
- package/docs/EXTENSIONS.md +18 -19
- package/docs/HISTORY_RECOVERY.md +146 -0
- package/docs/MERGE_SAFETY.md +50 -0
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +66 -0
- package/docs/PR_REVIEW_LOOP.md +18 -3
- package/docs/README.md +19 -1
- package/docs/RELEASING.md +31 -13
- package/docs/SDK_CONTEXT_TRUTH_CONTRACTS.md +24 -1
- package/docs/SDK_EXECUTION_CONTRACTS.md +105 -0
- package/docs/SDK_LIFECYCLE.md +27 -0
- package/docs/SDK_RUNTIME_BOUNDARIES.md +11 -0
- package/docs/TESTING.md +5 -0
- package/docs/agent-task-token-baseline.json +17 -17
- package/docs/agent-task-transcripts.json +2 -1
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +11 -11
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -3
- package/marketplace.json +2 -2
- package/package.json +8 -6
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/README.md +10 -1
- package/packages/pm-governance-audit/extensions/governance-audit/dedupe-audit.ts +50 -65
- package/packages/pm-governance-audit/extensions/governance-audit/index.ts +2 -2
- package/packages/pm-governance-audit/extensions/governance-audit/sdk.ts +1 -0
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/skills/pm-audit/SKILL.md +2 -2
- package/plugins/pm-claude/skills/pm-developer/SKILL.md +2 -2
- package/plugins/pm-claude/skills/pm-planner/SKILL.md +2 -2
- package/plugins/pm-claude/skills/pm-release/SKILL.md +2 -2
- package/plugins/pm-claude/skills/pm-workflow/SKILL.md +3 -3
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/skills/pm-auditor/SKILL.md +2 -2
- package/plugins/pm-codex/skills/pm-native/SKILL.md +3 -4
- package/plugins/pm-codex/skills/pm-release/SKILL.md +2 -2
- package/scripts/finalize-build.mjs +13 -1
- package/dist/cli-bundle/chunks/chunk-6XSKPNCF.js +0 -230
- package/dist/cli-bundle/chunks/chunk-OGBVU67G.js +0 -5
- package/dist/cli-bundle/chunks/chunk-TXW6VL33.js +0 -38
- package/dist/cli-bundle/chunks/chunk-VGLHECAP.js +0 -9
- package/dist/cli-bundle/chunks/register-operations-OH7R3ZT4.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-4YRAVI43.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-5P4HVOWG.js +0 -176
- package/dist/cli-bundle/focused-chunks/chunk-636VVQ7F.js +0 -54
- package/dist/cli-bundle/focused-chunks/chunk-B3A6MJYE.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-BFDDJ2T2.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-BHUIRZWQ.js +0 -9
- package/dist/cli-bundle/focused-chunks/chunk-JADHHPY6.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-NSKBLHVI.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-P2GOAOQN.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-YARWJM2B.js +0 -2
- package/sdk/public-surface.json +0 -33034
package/docs/AGENT_GUIDE.md
CHANGED
|
@@ -105,10 +105,22 @@ pm learnings <item-id> --add "Durable lesson for future work."
|
|
|
105
105
|
pm test <item-id> --run --progress
|
|
106
106
|
node scripts/run-tests.mjs coverage
|
|
107
107
|
pm comments <item-id> "Evidence: linked test and coverage passed."
|
|
108
|
-
pm close <item-id> "Acceptance criteria met; verification passed." --validate-close warn
|
|
108
|
+
pm close <item-id> "Acceptance criteria met; verification passed." --resolution "Delivered behavior" --expected "Required outcome" --actual "Verified outcome" --validate-close warn
|
|
109
109
|
pm release <item-id>
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
+
If a warning close omitted evidence, use its `recovery.suggested_retry_args`
|
|
113
|
+
to append an evidence update while preserving the original close event. See
|
|
114
|
+
[Close Evidence Recovery](CLOSE_EVIDENCE_RECOVERY.md).
|
|
115
|
+
|
|
116
|
+
For real subprocess tests, set `cwd`, `PM_PATH`, and `PM_GLOBAL_PATH` to the
|
|
117
|
+
fixture's temporary workspace and trackers. This also isolates bootstrap and
|
|
118
|
+
implicit discovery reads. Disable external probes with
|
|
119
|
+
`PM_AGENT_PROBES=0` when testing deterministic process output.
|
|
120
|
+
When testing conflicting ambient context, preserve that deliberate input in the
|
|
121
|
+
fixture. CLI and MCP dispatch scope SDK identity signals to the resolved tracker;
|
|
122
|
+
tests compare complete history bytes while the unrelated tracker's claims change.
|
|
123
|
+
|
|
112
124
|
## Token-Minimal Retrieval
|
|
113
125
|
|
|
114
126
|
| Need | Command |
|
|
@@ -181,6 +193,12 @@ Use the canonical [guide topic map](README.md#guide-topic-map) when local in-CLI
|
|
|
181
193
|
|
|
182
194
|
## Reviewed Delivery Closeout
|
|
183
195
|
|
|
196
|
+
Before closing repository defects, set `escape_class` and structured
|
|
197
|
+
`gate_evidence` through `pm update` as described in
|
|
198
|
+
[Defect Evidence](DEFECT_RECURRENCE.md#defect-evidence-on-pm-items).
|
|
199
|
+
Run `pnpm quality:defect-evidence` after the terminal transitions: a static
|
|
200
|
+
gate run before closure cannot validate evidence required only for closed items.
|
|
201
|
+
|
|
184
202
|
Treat PM evidence, item closure, and the generated changelog as part of the
|
|
185
203
|
reviewed change. Add all evidence known before merge to the active branch,
|
|
186
204
|
close and release the item there, regenerate `CHANGELOG.md`, and include those
|
|
@@ -195,6 +213,35 @@ post-merge observations on GitHub without changing repository state when no
|
|
|
195
213
|
tracked closeout update is required. See [Releasing](RELEASING.md#reviewed-delivery-closeout)
|
|
196
214
|
for the release contract.
|
|
197
215
|
|
|
216
|
+
## Review and Analyzer Proof
|
|
217
|
+
|
|
218
|
+
Use the [review helper](../scripts/reviews/pr-review-loop.mjs) to wait for
|
|
219
|
+
terminal checks, then inspect its paginated inventory of comments, reviews,
|
|
220
|
+
inline threads, edits, reactions, and resolution state. Inspect failed-check
|
|
221
|
+
details in the receipt even when the helper itself exits successfully.
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
node scripts/reviews/pr-review-loop.mjs watch --pr <number> --repo unbraind/pm-cli --interval 60
|
|
225
|
+
node scripts/release/hosted-analysis-gate.mjs --repo unbraind/pm-cli --sha <full-40-character-head-sha> --json
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Both receipts must pass for the exact current head before merge. A successful
|
|
229
|
+
CodeFactor check can still contain a notice: the stricter analyzer gate requires
|
|
230
|
+
zero outstanding annotations and verifies DeepScan plus branch protection.
|
|
231
|
+
Do not substitute a green check conclusion for that proof. This escape and its
|
|
232
|
+
correction are recorded in [pm-08mt4k](../.agents/pm/issues/pm-08mt4k.toon).
|
|
233
|
+
|
|
234
|
+
Use the helper's `acknowledge-inline` operation for actionable inline findings
|
|
235
|
+
and `acknowledge` for top-level comments or review summaries. Rate valid feedback
|
|
236
|
+
positively and explain false or stale findings on their actual review surface.
|
|
237
|
+
After each push, request the reviewers again and wait for terminal results;
|
|
238
|
+
provider quota or skipped reviews are limitations, not approvals. Before merge,
|
|
239
|
+
run `inventory` once more to catch new or edited feedback, and require all
|
|
240
|
+
findings to have an explicit disposition. Compare each artifact's `revision`
|
|
241
|
+
and pass it as `--revision` when acknowledging feedback, so edited bodies get
|
|
242
|
+
fresh decisions and retrying a handled revision adds no duplicate reply.
|
|
243
|
+
See [Review Loop](PR_REVIEW_LOOP.md) for the revision and reply contracts.
|
|
244
|
+
|
|
198
245
|
## Documentation Rules for Agents
|
|
199
246
|
|
|
200
247
|
- Keep [README](../README.md) short.
|
|
@@ -205,6 +252,16 @@ for the release contract.
|
|
|
205
252
|
- Link docs back to the active item with `pm docs`.
|
|
206
253
|
- Do not link public docs to ignored local operations artifacts or private evidence logs.
|
|
207
254
|
|
|
255
|
+
## Scheduling and Handoff
|
|
256
|
+
|
|
257
|
+
Read [SDK execution contracts](SDK_EXECUTION_CONTRACTS.md) before building an
|
|
258
|
+
agent work allocator. Use `next` and `claim --next` for executable work; inspect
|
|
259
|
+
`decision_needed`, `gate_needed`, and `containers` when no recommendation is
|
|
260
|
+
available. Only opt into those buckets when the current task calls for them.
|
|
261
|
+
Use `pause-task` to stop work; `release` alone preserves in-progress status.
|
|
262
|
+
Context summary totals describe the matching population, while `returned_focus`
|
|
263
|
+
describes the bounded selection.
|
|
264
|
+
|
|
208
265
|
## Safe Defaults
|
|
209
266
|
|
|
210
267
|
Use these defaults unless the task requires otherwise:
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Bounded context reads and duplicate discovery
|
|
2
|
+
|
|
3
|
+
Tracked by [pm-pshhry](../.agents/pm/issues/pm-pshhry.toon),
|
|
4
|
+
[pm-ydshl9](../.agents/pm/issues/pm-ydshl9.toon),
|
|
5
|
+
[pm-bab3gb](../.agents/pm/issues/pm-bab3gb.toon),
|
|
6
|
+
[pm-fx80w2](../.agents/pm/issues/pm-fx80w2.toon),
|
|
7
|
+
[pm-gtw5zh](../.agents/pm/issues/pm-gtw5zh.toon), and
|
|
8
|
+
[pm-s8ybl9](../.agents/pm/issues/pm-s8ybl9.toon).
|
|
9
|
+
|
|
10
|
+
Project management is context management. Routine reads should pay for the
|
|
11
|
+
requested evidence, and derived feedback should not grow with every candidate
|
|
12
|
+
in a project's history. These primitives share SDK implementations across CLI,
|
|
13
|
+
MCP, and package consumers.
|
|
14
|
+
|
|
15
|
+
## Point reads
|
|
16
|
+
|
|
17
|
+
`pm get <id>` at standard depth reads the addressed item and its own history.
|
|
18
|
+
It does not enumerate unrelated items to compute child counts. `--depth brief`
|
|
19
|
+
and `--fields id,title` also omit claim-history work and heavy output facets.
|
|
20
|
+
The cost still depends on the addressed record, registered type directories,
|
|
21
|
+
and extension activation; this is not a constant-latency guarantee for arbitrary
|
|
22
|
+
extensions or unbounded individual history streams.
|
|
23
|
+
|
|
24
|
+
Request hierarchy work explicitly with `--fields id,children`, `--tree`, or a
|
|
25
|
+
deep/full container read. These paths preserve registered hierarchy semantics,
|
|
26
|
+
including inverse and custom relationship kinds, rather than treating only the
|
|
27
|
+
scalar `parent` field as authoritative. An omitted `children` facet carries a
|
|
28
|
+
restore selector in the omission receipt. Explicit deep/full and child-field
|
|
29
|
+
projections retain a zero-count rollup for an empty container.
|
|
30
|
+
|
|
31
|
+
Caller-carried output sessions retain only portable item identities in
|
|
32
|
+
`next_state.seen_item_ids`. Workspace activity such as `_workspace` remains
|
|
33
|
+
visible in full on subsequent reads. It cannot become an invalid item reference
|
|
34
|
+
or make the next read reject a state produced by the previous read.
|
|
35
|
+
|
|
36
|
+
The optional SQLite projection binds each FTS document to the corresponding
|
|
37
|
+
`items.rowid`. Maintenance resolves the indexed item identity and deletes the
|
|
38
|
+
single FTS row, avoiding a scan of the unindexed FTS `id` column on every insert,
|
|
39
|
+
update, or deletion. Derived index version 5 rejects older projections and
|
|
40
|
+
rebuilds them from authoritative metadata. Real SQLite query-plan tests retain
|
|
41
|
+
the old predicate as a negative control and verify search results after updates
|
|
42
|
+
and deletions. SQLite documents the distinction between
|
|
43
|
+
[FTS columns and row identity](https://www.sqlite.org/fts5.html).
|
|
44
|
+
|
|
45
|
+
## Exact duplicate candidates
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pm duplicates --status all --threshold 0.8 --json
|
|
49
|
+
pm duplicates --status open --exhaustive --json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The default algorithm orders title tokens by corpus frequency and uses a
|
|
53
|
+
Jaccard prefix join. For a set of size `n` and threshold `t`, a prefix of length
|
|
54
|
+
`n - ceil(t*n) + 1` must intersect the similarly ordered prefix of every
|
|
55
|
+
qualifying set. The length filter rejects impossible token matches before
|
|
56
|
+
scoring. Exact normalized titles, issue codes, and empty-token matches retain
|
|
57
|
+
the canonical scorer's separate rules. This follows the established
|
|
58
|
+
[all-pairs similarity-search approach](https://research.google/pubs/scaling-up-all-pairs-similarity-search/).
|
|
59
|
+
|
|
60
|
+
Both modes retain exact recall relative to the canonical title scorer.
|
|
61
|
+
`cost` discloses `algorithm`, `item_count`, `possible_pairs`, `candidate_pairs`,
|
|
62
|
+
`scored_pairs`, `pair_limit`, and `recall_guarantee`. The one-million-candidate
|
|
63
|
+
safety ceiling remains enforced. Dense duplicate output or a zero threshold
|
|
64
|
+
can still require quadratic work; the command refuses without returning a
|
|
65
|
+
partial answer. Exact recall is not a claim that every semantic duplicate has
|
|
66
|
+
similar titles. Review the actual item evidence before merging or closing.
|
|
67
|
+
|
|
68
|
+
Packages with remote or custom stores can use the same kernel without building
|
|
69
|
+
a filesystem tracker:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { analyzeDuplicateItems } from "@unbrained/pm-cli/sdk/query";
|
|
73
|
+
|
|
74
|
+
const result = analyzeDuplicateItems([
|
|
75
|
+
{ id: "work-a", title: "Publish research protocol", type: "Task", status: "open" },
|
|
76
|
+
{ id: "work-b", title: "Publish research protocol", type: "Task", status: "closed" },
|
|
77
|
+
]);
|
|
78
|
+
console.log(result.clusters, result.cost);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The function preserves its input, validates unique nonempty identifiers, and
|
|
82
|
+
returns deterministic components and scored pair evidence. The filesystem
|
|
83
|
+
`findDuplicateClusters`, `PmClient.duplicates`, CLI and MCP adapters reuse it.
|
|
84
|
+
Record the algorithm and cost receipt in create-time duplicate-check evidence.
|
|
85
|
+
|
|
86
|
+
## Feedback storage
|
|
87
|
+
|
|
88
|
+
Serving receipts retain the full candidate population in memory for final
|
|
89
|
+
delivery validation. Persisted events retain only the first 256 candidate rows,
|
|
90
|
+
with explicit population and omission counts. Only sampled ids observed in the
|
|
91
|
+
final emitted result can train affinity. This deterministic sample has no
|
|
92
|
+
unbiased-propensity claim. Unknown row properties are not persisted.
|
|
93
|
+
|
|
94
|
+
`CONTEXT_USAGE_LIMITS` publishes a 256 KiB physical ceiling, a 32 KiB individual
|
|
95
|
+
event ceiling, 2,048 retained events and a 30-day default horizon. Writers share
|
|
96
|
+
a cross-process lock. High-water compaction atomically replaces the ledger with
|
|
97
|
+
a suffix of at most half the byte ceiling, leaving append headroom. Readers
|
|
98
|
+
consume at most the byte ceiling even for an oversized legacy file. Custom
|
|
99
|
+
retention controls can tighten the limits; invalid controls fail before I/O.
|
|
100
|
+
|
|
101
|
+
Serving receipt `storage` reports actual `written_bytes`, `ledger_bytes`,
|
|
102
|
+
`compacted`, and `lock_wait_ms`. Written bytes count ledger data rather than lock
|
|
103
|
+
metadata or filesystem block allocation. The receipt is attached to results
|
|
104
|
+
through a non-JSON symbol and does not inflate normal CLI output. Storage is
|
|
105
|
+
derived and disposable; item history remains independent. Ledger access refuses
|
|
106
|
+
existing symbolic links, shared hard links, non-regular files, and a redirected
|
|
107
|
+
runtime directory. Appends use a validated descriptor with no-follow opening
|
|
108
|
+
where supported; replacement files are created exclusively with private
|
|
109
|
+
permissions. Compaction closes both data handles before replacing the ledger,
|
|
110
|
+
including on Windows.
|
|
111
|
+
|
|
112
|
+
Feedback persistence requires trusted, stable workspace directory entries and
|
|
113
|
+
ancestors. It is unsafe when an untrusted actor can concurrently replace those
|
|
114
|
+
entries: portable Node filesystem APIs do not pin ancestor directories through
|
|
115
|
+
the whole operation. The link checks reject existing redirections; the lock
|
|
116
|
+
coordinates cooperating SDK writers and is not a security boundary. Before
|
|
117
|
+
using an adversary-writable live workspace, set `PM_CONTEXT_USAGE_DISABLED=1`
|
|
118
|
+
to disable feedback reads and writes, or work in an isolated copy owned by the
|
|
119
|
+
caller. Public feedback API callers can also pass `enabled: false`.
|
|
120
|
+
|
|
121
|
+
## Reproducible measurements
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
pnpm build
|
|
125
|
+
node scripts/bench/context-read-costs.mjs 10000 100000 1000000
|
|
126
|
+
node scripts/bench/point-read-costs.mjs 100 10000 100000
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The script uses paired titles with common project vocabulary, compares a
|
|
130
|
+
1,000-item subset against exhaustive scoring, and runs four concurrent writers
|
|
131
|
+
for 40 serves per tier in temporary storage. It asserts exact reference equality,
|
|
132
|
+
expected pair counts, reachable byte ceilings, and append headroom. Property
|
|
133
|
+
tests additionally vary thresholds, Unicode, punctuation, and issue identifiers.
|
|
134
|
+
|
|
135
|
+
The point-read script holds the addressed Epic constant while varying corpus
|
|
136
|
+
size. The public `measureItemMetadataReadWork` query SDK wrapper reports actual
|
|
137
|
+
item-store enumeration calls and returned metadata rows, including cache hits.
|
|
138
|
+
Ordinary reads must perform zero enumerations; an explicit child scan must
|
|
139
|
+
observe every generated item. A regression test deliberately enumerates and
|
|
140
|
+
discards the corpus before a normal read, proving that output shape alone cannot
|
|
141
|
+
satisfy this work gate. Measurements preserve operation failures, isolate
|
|
142
|
+
concurrent roots, include nested work, and release their observers on completion.
|
|
143
|
+
They cover item-store enumeration APIs rather than arbitrary extension I/O.
|
|
144
|
+
Fixture setup
|
|
145
|
+
registers all generated types, including `Story`, through the live SDK schema
|
|
146
|
+
and uses deterministic SDK execution for byte-reproducible workspace history.
|
|
147
|
+
|
|
148
|
+
The 2026-09-05 filesystem run observed the following timings (10 reads per
|
|
149
|
+
projection, including feedback writes). The explicit scan includes the cold
|
|
150
|
+
derived-index rebuild; these are host observations rather than latency gates.
|
|
151
|
+
|
|
152
|
+
| Corpus items | Standard p95 | Brief p95 | Fields p95 | Explicit full scan | Verified scan rows |
|
|
153
|
+
| ---: | ---: | ---: | ---: | ---: | ---: |
|
|
154
|
+
| 100 | 4.53 ms | 4.24 ms | 3.54 ms | 48 ms | 100 |
|
|
155
|
+
| 10,000 | 3.61 ms | 3.03 ms | 4.08 ms | 4.91 s | 10,000 |
|
|
156
|
+
| 100,000 | 3.69 ms | 11.00 ms | 3.11 ms | 48.59 s | 100,000 |
|
|
157
|
+
|
|
158
|
+
Measured on 2026-09-05 with Node 26.7.0; these are observations, not portable
|
|
159
|
+
latency guarantees. Duplicate timings exclude filesystem ingestion.
|
|
160
|
+
|
|
161
|
+
| Items | Possible pairs | Scored pairs | Analysis time | Mean bytes written per serve | Compactions / serves | Final ledger bytes |
|
|
162
|
+
| ---: | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
163
|
+
| 10,000 | 49,995,000 | 5,000 | 92 ms | 18,138 | 2 / 40 | 237,785 |
|
|
164
|
+
| 100,000 | 4,999,950,000 | 50,000 | 864 ms | 18,149 | 2 / 40 | 237,821 |
|
|
165
|
+
| 1,000,000 | 499,999,500,000 | 500,000 | 10,367 ms | 18,135 | 2 / 40 | 237,857 |
|
|
166
|
+
|
|
167
|
+
The same four-writer runs include full in-memory candidate validation and final
|
|
168
|
+
delivery recording. Throughput therefore still falls with candidate population.
|
|
169
|
+
|
|
170
|
+
Lock-wait percentiles use the empirical nearest rank across all 40 serving
|
|
171
|
+
receipts; these are four concurrent tasks sharing a cross-process lock, not a
|
|
172
|
+
measurement of four separate OS processes.
|
|
173
|
+
|
|
174
|
+
| Candidate rows per serve | Serves/s/workspace | Minimum wait | p50 wait | p95 wait | Maximum wait |
|
|
175
|
+
| ---: | ---: | ---: | ---: | ---: | ---: |
|
|
176
|
+
| 10,000 | 46.73 | 3.11 ms | 25.15 ms | 84.97 ms | 105.66 ms |
|
|
177
|
+
| 100,000 | 20.82 | 18.29 ms | 50.10 ms | 193.86 ms | 229.60 ms |
|
|
178
|
+
| 1,000,000 | 1.92 | 198.10 ms | 809.52 ms | 1,367.67 ms | 1,622.77 ms |
|
|
179
|
+
|
|
180
|
+
Reference recall was 100% at every tier. The million-item batch does not meet
|
|
181
|
+
the broader one-second project target; persistent incremental ingestion and
|
|
182
|
+
analysis remain necessary for that target. Full candidate validation still
|
|
183
|
+
costs O(candidate count) in memory even though persisted feedback is bounded.
|
|
184
|
+
On the live 2,638-item corpus, default discovery completed after scoring 3,136
|
|
185
|
+
of 3,478,203 possible pairs; the prior algorithm refused at its safety ceiling.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Recovering missing close evidence
|
|
2
|
+
|
|
3
|
+
Tracked by [pm-ub1ott](../.agents/pm/issues/pm-ub1ott.toon).
|
|
4
|
+
|
|
5
|
+
`pm close --validate-close warn` can close an item while reporting missing
|
|
6
|
+
resolution, expected outcome, or actual outcome. Its SDK result and compact CLI
|
|
7
|
+
output now include `recovery.missing`, `suggested_retry`, and
|
|
8
|
+
`suggested_retry_args` when evidence is incomplete. The argument vector selects
|
|
9
|
+
the same tracker and uses `pm update` to add only the missing evidence fields.
|
|
10
|
+
Use `recovery.suggested_retry_args` as the authoritative argument vector. Replace
|
|
11
|
+
each `<value>` with the observed outcome before executing it; retain its tracker
|
|
12
|
+
selection and only the flags it supplies for missing fields. Do not add flags
|
|
13
|
+
for evidence already present, because `pm update` would overwrite that evidence.
|
|
14
|
+
|
|
15
|
+
For example, when only the actual outcome is missing, the recovery arguments
|
|
16
|
+
contain `--actual-result` alone (plus the item and tracker selection):
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pm --pm-path <tracker-root> update <item-id> \
|
|
20
|
+
--actual-result "Evidence update appended; original close event unchanged"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
An attempt to close an already terminal item also returns evidence-update
|
|
24
|
+
recovery when applicable. `--force` is reserved for an intentional repeated
|
|
25
|
+
lifecycle transition. Adding evidence with `pm update` preserves the original
|
|
26
|
+
close timestamp, close reason, and immutable history event, then appends a
|
|
27
|
+
normal update event. It does not retroactively claim that evidence existed at
|
|
28
|
+
the original close. Complete closes have no extra recovery payload.
|
|
29
|
+
|
|
30
|
+
The update flags for the other missing fields are `--resolution` and
|
|
31
|
+
`--expected-result`; include them only when the generated recovery requests them.
|
|
32
|
+
|
|
33
|
+
For new work, include all three fields in the original close command so its
|
|
34
|
+
immutable event contains the full evidence. Warning-mode recovery exists for
|
|
35
|
+
incomplete historical or interrupted workflows.
|
package/docs/COMMANDS.md
CHANGED
|
@@ -173,12 +173,18 @@ Use `context` first for a compact active-work snapshot. Use `search` when the re
|
|
|
173
173
|
Use `duplicates --status all` for a true whole-history duplicate check. The
|
|
174
174
|
result echoes `filters.statuses: null` for the unrestricted corpus; named or
|
|
175
175
|
custom statuses are normalized through the runtime status registry and an
|
|
176
|
-
unknown status fails instead of returning a false-clean result.
|
|
176
|
+
unknown status fails instead of returning a false-clean result. The default
|
|
177
|
+
lossless prefix filter preserves every pair that meets the canonical similarity
|
|
178
|
+
threshold. `--exhaustive` compares all pairs for small-corpus verification. Both
|
|
179
|
+
modes disclose the algorithm, possible and scored pair counts, exact recall
|
|
180
|
+
guarantee, and safety ceiling; exceeding that ceiling refuses without returning
|
|
181
|
+
a partial result. Review clusters before closing anything: title similarity is
|
|
182
|
+
evidence for investigation, not proof that work is interchangeable.
|
|
177
183
|
As a read-only structured surface, `duplicates` accepts the universal output
|
|
178
184
|
controls, including `--output-format json`, `--lean`, projection/amount
|
|
179
185
|
controls, and token accounting, while its default TOON output remains bounded.
|
|
180
186
|
Tracked by [pm-gh1076](../.agents/pm/issues/pm-gh1076.toon).
|
|
181
|
-
Use `pm get <id>` to read a single item by ID — the single-item read primitive used throughout the agent loop. It accepts `--fields <list>` and `--depth brief|standard|deep|full` for token-minimal projections, and `--tree`/`--tree-depth <n>` to include descendants. The universal `--output-include` selector can request stored collections directly, for example `pm get <id> --output-include comments,learnings,tests`; the same bare and `item.<field>` grammar works through CLI, SDK, and MCP transports. Standard/deep reads expose a normalized `schedule` facet (`deadline`, `start_at`, `end_at`, `location`, reminders, and events) when scheduling metadata exists.
|
|
187
|
+
Use `pm get <id>` to read a single item by ID — the single-item read primitive used throughout the agent loop. It accepts `--fields <list>` and `--depth brief|standard|deep|full` for token-minimal projections, and `--tree`/`--tree-depth <n>` to include descendants. The universal `--output-include` selector can request stored collections directly, for example `pm get <id> --output-include comments,learnings,tests`; the same bare and `item.<field>` grammar works through CLI, SDK, and MCP transports. Standard/deep reads expose a normalized `schedule` facet (`deadline`, `start_at`, `end_at`, `location`, reminders, and events) when scheduling metadata exists. Standard reads of every item type avoid a workspace child scan. For container-oriented built-ins (Epic, Feature, Milestone, and Plan) and custom types, `--depth deep|full` adds type-agnostic child counts, a bounded sample, and continuation metadata. An explicit `--fields id,children` requests that rollup for any type. See [bounded context reads](BOUNDED_CONTEXT_READS.md) for the cost contract. `pm get <id> --json` returns the `body` inside the `item` object (`.item.body`); see [Full results, totals, and bodies](#full-results-totals-and-bodies). To duplicate an existing item as a starting point, `pm copy <id> --title "New title"` clones it into a fresh id with lifecycle fields reset.
|
|
182
188
|
|
|
183
189
|
When the strongest duplicate match is terminal because the same work recurred,
|
|
184
190
|
reuse its lineage instead of creating or copying another item:
|
|
@@ -526,7 +532,7 @@ pm notes <id> --event-type step.completed --since 2026-07-31T00:00:00Z --include
|
|
|
526
532
|
|
|
527
533
|
`append` mutates the scalar Markdown body and is not a concurrency-safe event log. `notes --add` stores union-merged text entries; `notes --add-json` stores a validated JSON payload plus timestamp and author in that same merge-safe collection. Structured events retain canonical JSON text for older readers and expose `format: json`, `data`, and optional `event_type` to SDK/CLI/MCP consumers. `--since`, `--event-type`, `--limit`, and `--include-meta` provide bounded reads without client-side free-text parsing.
|
|
528
534
|
|
|
529
|
-
can make non-lifecycle metadata updates and append comments, linked files, and linked
|
|
535
|
+
`pm update` can make non-lifecycle metadata updates and append comments, linked files, and linked
|
|
530
536
|
docs in one audited history entry. It is intentionally append-only for evidence:
|
|
531
537
|
lifecycle/ownership fields, dependencies, tests, notes, learnings, reminders, events,
|
|
532
538
|
and all clear/replace operations stay restricted or use their dedicated commands.
|
|
@@ -760,7 +766,7 @@ pm deps <id> --format context --direction both --kind blocked_by,parent --token-
|
|
|
760
766
|
|
|
761
767
|
Linked files and docs keep reviews reproducible. `deps` is read-only and projects item relationships. Tree and graph formats are bounded by depth, node, edge, and estimated-token budgets (safe defaults: depth 32, 200 nodes, 400 edges, 16,000 tokens); pass `--max-depth`, `--node-limit`, `--edge-limit`, or `--token-budget` to tighten them. A bounded result carries deterministic `truncation.reasons`, effective limits, full unique-node/edge totals, and omitted counts. The estimate is calculated from the emitted JSON or TOON representation, including its accounting envelope. `--format context` returns one bounded, explainable relationship packet: a counts-first summary, per-node `role`/`via`/`reasons`, root evidence pointers, enumerated `missing_references` with active-versus-legacy classification, `meta.completeness`, exact rendered `meta.usedTokens`, and cursor continuation; `--direction`, repeatable or comma-separated `--kind`, and `--cursor` further control that traversal (see [Relationship Graph](RELATIONSHIP_GRAPH.md)). `--edge-limit` caps both returned graph edges and enumerated `missing_references`; `missing_reference_count` retains the total when rows are omitted. The standalone `--note <text>` flag annotates every link added by `--add`/`--add-glob` in the same invocation (a per-entry embedded `note=` wins); `--note` without an add is a usage error.
|
|
762
768
|
|
|
763
|
-
Structured key/value forms reject unrecognized keys with an `Allowed keys: …` error (matching `test --add`), so a typoed key (`lable=` instead of `label=`) fails fast instead of being silently dropped: `--add`/`--file`/`--doc` accept `path,scope,note`; `--add-glob` accepts `pattern,glob,path,scope,note`; `--remove` accepts `path`; `--migrate` accepts `from,to`; create/update `--dep` accepts `id,kind,type,author,created_at,source_kind`; `--reminder` accepts `at,date,text,title`; `--event` accepts `start,date,end,duration,title,description,location,timezone,all_day` and the `recur_*` recurrence keys. Set `source_kind=global` for a dependency owned by another workspace: pm preserves its id verbatim, materializes it as an external graph endpoint, and excludes it from dangling-local-reference findings.
|
|
769
|
+
Structured key/value forms reject unrecognized keys with an `Allowed keys: …` error (matching `test --add`), so a typoed key (`lable=` instead of `label=`) fails fast instead of being silently dropped: `--add`/`--file`/`--doc` accept `path,scope,note`; `--add-glob` accepts `pattern,glob,path,scope,note`; `--remove` accepts `path`; `--migrate` accepts `from,to`; create/update `--dep` accepts `id,kind,type,author,created_at,source_kind`; `--reminder` accepts `at,date,text,title`; `--event` accepts `start,date,end,duration,title,description,location,timezone,all_day` and the `recur_*` recurrence keys. Set `source_kind=global` for a dependency owned by another workspace: pm preserves its id verbatim, materializes it as an external graph endpoint, and excludes it from dangling-local-reference findings. Explicit remote locators also retain their spelling; other dependency and parent references share local `id_prefix` normalization, including uppercase and `#` shorthand. Bare values (`--add src/cli/main.ts`) skip key validation.
|
|
764
770
|
|
|
765
771
|
## Graph Queries
|
|
766
772
|
|
|
@@ -886,7 +892,11 @@ pm gc --scope locks --dry-run
|
|
|
886
892
|
|
|
887
893
|
Use dry-run modes before broad lifecycle or cleanup changes.
|
|
888
894
|
|
|
889
|
-
`pm gc
|
|
895
|
+
`pm gc --scope` accepts `index`, `embeddings`, `runtime`, `locks`, and `checkpoints`, comma-separated or repeated. Omitting the flag selects all scopes:
|
|
896
|
+
|
|
897
|
+
- `runtime` clears `runtime/test-runs/` and `runtime/history-drift-cache.json`. The next health check rescans history drift.
|
|
898
|
+
- `embeddings` removes keyword/semantic artifacts (`search/embeddings.jsonl`, `search/vectorization-status.json`, `search/lancedb/`) plus `search/pending-refresh.json` and its gate, preventing a background worker from rebuilding a partial index against an empty ledger. Rebuild with keyword reindex and semantic reindex when enabled.
|
|
899
|
+
- `locks` removes only provably expired locks, using embedded `created_at + ttl_seconds`. Active, unreadable, or unparseable locks remain. The result reports `scanned`, `removed`, and `retained` counts.
|
|
890
900
|
|
|
891
901
|
The `checkpoints` scope prunes bulk-mutation rollback checkpoints under `checkpoints/` (written by `pm update-many`/`pm close-many`) that are older than `checkpoints.retention_days` (default 14; set via `pm config <scope> set checkpoints_retention_days <n>`). Checkpoints whose `created_at` cannot be parsed are retained (safety-first, like the locks sweep), and the result includes a `checkpoints` summary (`scanned`/`removed`/`retained`/`retention_days`). Removing aged checkpoints permanently closes their `--rollback` window.
|
|
892
902
|
|
|
@@ -894,7 +904,7 @@ The `checkpoints` scope prunes bulk-mutation rollback checkpoints under `checkpo
|
|
|
894
904
|
|
|
895
905
|
`pm validate --check-metadata` also groups missing-required-field counts per item type in `details.missing_by_type` (for example `{ "Task": { "close_reason": 3 } }`) — counts only, zero-suppressed, and limited to the active metadata profile's required fields, so remediation can be targeted by type without verbose row dumps.
|
|
896
906
|
|
|
897
|
-
`--counts` keeps the validation envelope, check statuses, warning codes, scalar counts/totals, nested count maps, and fix summary totals while recursively omitting diagnostic and fix row arrays. It is the preferred agent projection when deciding whether drift exists; remove it only when the affected ids or remediation rows are needed. The public SDK `projectValidateCounts` helper applies the identical projection to an already-computed `ValidateResult`.
|
|
907
|
+
`--counts` keeps the validation envelope, check statuses, warning codes, scalar counts/totals, nested count maps, and fix summary totals while recursively omitting diagnostic and fix row arrays. False `*_truncated` markers are omitted; true markers, other false values, and zero counts remain. It is the preferred agent projection when deciding whether drift exists; remove it only when the affected ids or remediation rows are needed. The public SDK `projectValidateCounts` helper applies the identical projection to an already-computed `ValidateResult`.
|
|
898
908
|
|
|
899
909
|
By default the human view caps each diagnostic `*_item_ids` list at 5 entries and sets the matching `*_truncated` flag. `--json` **never** truncates those lists (machine consumers always receive the complete arrays), and `--all-affected-ids` (equivalent to `--verbose-diagnostics`) emits the full lists in human mode too — so bulk remediation can pipe every affected id straight into `pm update-many`:
|
|
900
910
|
|
|
@@ -903,13 +913,25 @@ pm validate --check-metadata --all-affected-ids
|
|
|
903
913
|
pm validate --check-metadata --json | jq -r '.checks[] | select(.name=="metadata") | .details.missing_acceptance_criteria_item_ids[]'
|
|
904
914
|
```
|
|
905
915
|
|
|
906
|
-
`--auto-fix`
|
|
916
|
+
`--auto-fix` reports `planned_fixes`, `applied_fixes`, `gated_fixes`, and `failed_fixes` under `fixes`. Each row identifies the item, check, field, and equivalent standalone command:
|
|
917
|
+
|
|
918
|
+
- Safe field backfills derive a missing terminal `resolution` from `close_reason` (falling back to `"completed"`) or a missing `close_reason` from existing `resolution`. Every applied change uses the audited update path; auto-fix never closes, cancels, or deletes items.
|
|
919
|
+
- `--fix-scope lifecycle` explicitly permits reparenting an active item from its terminal parent to an active grandparent, or clearing that parent link. These structural fixes are otherwise planned only.
|
|
920
|
+
- `--fix-scope estimates` explicitly permits heuristic per-type estimates. Defaults in minutes are Epic/Milestone 2880, Feature/Story 480, Task/Plan 120, Issue/Bug 60, Chore 30, Decision 15, and fallback 120. Override `validation.estimate_defaults_by_type` with a type-to-minutes map.
|
|
921
|
+
- `--fix-scope` is an exact, repeatable or comma-separated allowlist: `metadata`, `resolution`, `estimates`, `lifecycle`. Omitting it grants only the safe metadata/resolution scopes; specifying only estimates grants only estimates.
|
|
922
|
+
- `--dry-run` previews without mutation. With no explicit check flags, auto-fix runs only metadata, resolution, and lifecycle checks. Output checks describe the pre-fix state; rerun validation to confirm convergence.
|
|
907
923
|
|
|
908
924
|
> Note: acceptance-criteria gaps are intentionally **not** auto-fixed. Unlike resolution/close_reason (derivable from the item's own fields) or estimates (a config-driven type default), acceptance criteria have no deterministic source — synthesizing them from the description would fabricate content rather than derive it, violating the auto-fix safety invariant. They remain `--fix-hints`-only.
|
|
909
925
|
|
|
910
926
|
`pm validate --check-lifecycle` detects dependency cycles from explicit dependency edges, scalar `blocked_by` item ids, and exact pm-id references in `definition_of_ready`. That catches logical deadlocks such as A blocked by B while B's readiness text names A; `--dependency-cycle-severity off|warn|error` still controls whether those cycles warn, error, or remain informational in details.
|
|
911
927
|
|
|
912
|
-
`pm validate --check-files`
|
|
928
|
+
`pm validate --check-files` joins stale paths, owning items, and relocation candidates in structured `details.missing_linked_path_rows` in both compact and full output:
|
|
929
|
+
|
|
930
|
+
- `moved` means same-basename candidates exist; these are suggestions requiring verification. `deleted` means none exists. `malformed` marks ambiguous missing CSV or path:note literals and never infers a relocation or prune.
|
|
931
|
+
- Counters distinguish unique paths from linked holder/field pairs, active holders from the closed subset, and all terminal holders. Only active missing paths cause the files warning; historical debt remains visible. Custom lifecycle roles determine the partition.
|
|
932
|
+
- Active paths and owners appear first. Compact output bounds both dimensions and includes total counts and truncation flags; `--verbose-file-lists` restores every row. See [Linked-file repair rows](OUTPUT_PROJECTION_CONTRACTS.md#linked-file-repair-rows) for the SDK contract.
|
|
933
|
+
- Existing unlinked paths retain `orphaned_path_classifications` and `orphaned_path_rows`, with `docs_unowned`, `tests_unowned`, `source_unowned`, or `unlinked_existing` classifications and concrete ownership hints where available.
|
|
934
|
+
- `--prune-missing` removes only links classified `deleted`, retaining moved and malformed references for review. It never removes real files, honors `--dry-run`, implies `--check-files`, and records equivalent files/docs removal commands in `fixes.applied_fixes`.
|
|
913
935
|
|
|
914
936
|
The default `pm validate` run also includes a `format_version` check that compares every item's stored item metadata format version (`pm_format_version`, absent meaning the implicit baseline version `1`) against the version this pm runtime writes. `details.outdated_items` lists items that predate the current version (a future storage migration would rewrite them — advisory `warn`); `details.ahead_items` lists items written by a _newer_ pm than the one running, which is an `error` because validation cannot vouch for fields it does not understand (upgrade pm to read them safely). At the current baseline version both lists are empty and the check is `ok`. The same `pm_format_version` integrity is surfaced by `pm health` under the `integrity` check (`details.counts.item_outdated_format_version` / `item_ahead_format_version`).
|
|
915
937
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Context relevance and packing
|
|
2
2
|
|
|
3
|
-
Tracked by [pm-4k6b](../.agents/pm/features/pm-4k6b.toon), [pm-07pt16](../.agents/pm/issues/pm-07pt16.toon), [pm-wv47pf](../.agents/pm/issues/pm-wv47pf.toon), [pm-3hps](../.agents/pm/tasks/pm-3hps.toon), and [pm-801d](../.agents/pm/features/pm-801d.toon).
|
|
3
|
+
Tracked by [pm-bab3gb](../.agents/pm/issues/pm-bab3gb.toon), [pm-4k6b](../.agents/pm/features/pm-4k6b.toon), [pm-07pt16](../.agents/pm/issues/pm-07pt16.toon), [pm-wv47pf](../.agents/pm/issues/pm-wv47pf.toon), [pm-3hps](../.agents/pm/tasks/pm-3hps.toon), and [pm-801d](../.agents/pm/features/pm-801d.toon).
|
|
4
4
|
|
|
5
5
|
`pm context` and `pm next` share one public SDK relevance pipeline. The built-in
|
|
6
6
|
commands assemble authoritative item metadata, load rebuildable signal rows,
|
|
@@ -104,9 +104,13 @@ the same explanation as the ranking it serves.
|
|
|
104
104
|
### Delivered usage feedback
|
|
105
105
|
|
|
106
106
|
Usage affinity learns from post-egress delivery rather than pre-budget packing.
|
|
107
|
-
A versioned serve event records
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
A versioned serve event records at most 256 candidate rows in input order,
|
|
108
|
+
plus `candidate_count`, `omitted_row_count`, and a correlation id. The SDK
|
|
109
|
+
receipt keeps the complete candidate set in memory to validate final delivery.
|
|
110
|
+
CLI and `PmClient` egress append the final `result_omitted` decision and emitted
|
|
111
|
+
item ids intersected with the recorded sample. Unsampled items produce no
|
|
112
|
+
exposure or affinity judgment; the sample is deterministic, not an unbiased
|
|
113
|
+
propensity estimate. A whole-result omission
|
|
110
114
|
therefore delivers zero items even when the packer selected rows earlier.
|
|
111
115
|
|
|
112
116
|
Direct `runContext` and `runNext` calls record only their assembled rows on a
|
|
@@ -116,6 +120,14 @@ Legacy serve events have no correlation marker, so the affinity reader ignores
|
|
|
116
120
|
their inclusion flags and reports them as `untrusted_serving_events` instead of
|
|
117
121
|
training on unverifiable phantom serves.
|
|
118
122
|
|
|
123
|
+
The physical ledger is capped at 256 KiB. Appends exceeding that ceiling compact
|
|
124
|
+
atomically under the writer lock to a suffix of at most 128 KiB, leaving headroom
|
|
125
|
+
for subsequent requests. Reads consume at most 256 KiB even for oversized legacy
|
|
126
|
+
files, dropping a partial first row. Age and event-count limits also apply.
|
|
127
|
+
`CONTEXT_USAGE_LIMITS` and serving receipt `storage` expose the ceilings, actual
|
|
128
|
+
written bytes, retained bytes, compaction decision, and lock wait to SDK hosts.
|
|
129
|
+
See [bounded context reads](BOUNDED_CONTEXT_READS.md) for cost measurements.
|
|
130
|
+
|
|
119
131
|
For corpora of at least 10,000 items, `context` automatically allocates a
|
|
120
132
|
bounded fraction of its token budget to recent calendar-epoch and epic-lineage
|
|
121
133
|
rollups. `search` attaches only matching rollups. The projection contains
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
# Defect Recurrence and Boundary Evidence
|
|
2
2
|
|
|
3
|
-
Tracked by [pm-1qkivy](../.agents/pm/features/pm-1qkivy.toon), [pm-rtn5h6](../.agents/pm/tasks/pm-rtn5h6.toon), [pm-0pzgit](../.agents/pm/tasks/pm-0pzgit.toon), and [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon).
|
|
3
|
+
Tracked by [pm-1qkivy](../.agents/pm/features/pm-1qkivy.toon), [pm-rtn5h6](../.agents/pm/tasks/pm-rtn5h6.toon), [pm-0pzgit](../.agents/pm/tasks/pm-0pzgit.toon), [pm-7c27ep](../.agents/pm/issues/pm-7c27ep.toon), and [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon).
|
|
4
4
|
|
|
5
5
|
## Agent Quick Context
|
|
6
6
|
|
|
7
7
|
`pm` treats project management as context management. A resolved defect is therefore not only a closed item: it is durable context that should select the checks most likely to prevent the same failure from recurring.
|
|
8
8
|
|
|
9
|
-
The public SDK
|
|
9
|
+
The public SDK provides four composable contracts:
|
|
10
10
|
|
|
11
11
|
- a captured-boundary registry that rejects self-generated fixtures, unsafe samples, missing samples, and expired waivers;
|
|
12
12
|
- a defect-evidence ratchet that requires a typed escape class plus a gate improvement or reviewed, expiring waiver on new terminal defects;
|
|
13
|
-
- a versioned recurrence index that maps proposed files, packages, PM items, tags, and error codes to shared local and hosted checks
|
|
13
|
+
- a versioned recurrence index that maps proposed files, packages, PM items, tags, and error codes to shared local and hosted checks;
|
|
14
|
+
- a complete-population recurrence coverage report with bounded, resumable evidence rows.
|
|
14
15
|
|
|
15
16
|
The CLI and MCP use the same SDK action path. Repository policy can be replaced by a package or workspace policy without changing the analyzer.
|
|
16
17
|
|
|
@@ -63,7 +64,8 @@ Use `pm assurance risk` for an operator or agent decision. Use the pure SDK func
|
|
|
63
64
|
|
|
64
65
|
### TypeScript compatibility
|
|
65
66
|
|
|
66
|
-
The exported `ASSURANCE_ACTIONS` tuple and `AssuranceActionResult` union
|
|
67
|
+
The exported `ASSURANCE_ACTIONS` tuple and `AssuranceActionResult` union include `risk`, `lineages`,
|
|
68
|
+
`DefectChangeRiskReport`, and `DefectRecurrenceCoverageReport`. This is additive at runtime, but TypeScript consumers with an exhaustive action or result switch must add the new branch. The SDK surface snapshot records that source-compatibility change explicitly.
|
|
67
69
|
|
|
68
70
|
## Policy Model
|
|
69
71
|
|
|
@@ -79,7 +81,69 @@ The repository example is [config/defect-recurrence-policy.json](../config/defec
|
|
|
79
81
|
|
|
80
82
|
Repository policy validation rejects duplicate ids, absent historical examples, missing family negative controls, invalid taxonomy values, and budgets outside zero through one. Deterministic sorting makes the serialized policy merge-friendly.
|
|
81
83
|
|
|
82
|
-
Register a family
|
|
84
|
+
Register a semantic family seed using its owner, trigger item ids, or historical
|
|
85
|
+
item ids. The SDK follows every recorded local `recurs_from` edge in either
|
|
86
|
+
direction to derive family membership for the complete connected lineage.
|
|
87
|
+
Cycles and deep chains do not impose a traversal cutoff. Related, parent, and
|
|
88
|
+
external edges never establish recurrence coverage; tags and matching file
|
|
89
|
+
globs select change risk but cannot certify lineage registration.
|
|
90
|
+
|
|
91
|
+
Derived members inherit the family's checks. Changes naming a member or one of
|
|
92
|
+
its exact project-scoped linked files select those checks even when the policy
|
|
93
|
+
never named that member. Incremental indexes retain sparse direct evidence so
|
|
94
|
+
removing or changing an edge also removes obsolete inherited matches.
|
|
95
|
+
|
|
96
|
+
### Complete-population coverage
|
|
97
|
+
|
|
98
|
+
Tracked by [pm-7c27ep](../.agents/pm/issues/pm-7c27ep.toon).
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { analyzeDefectRecurrenceCoverage } from "@unbrained/pm-cli/sdk/governance";
|
|
102
|
+
|
|
103
|
+
const coverage = analyzeDefectRecurrenceCoverage(policy, allStatusItems, {
|
|
104
|
+
limit: 25,
|
|
105
|
+
uncoveredOnly: true,
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Supply an authoritative complete item corpus. The workspace action loads it
|
|
110
|
+
with strict read semantics. Unreadable item documents or directories refuse
|
|
111
|
+
both workspace analyses and the repository gate with `list_source_incomplete`.
|
|
112
|
+
Embedding hosts can request the same policy with
|
|
113
|
+
`createAssuranceWorkspaceContext(pmRoot, { strict_read: true })`.
|
|
114
|
+
Duplicate ids are rejected. Missing local targets
|
|
115
|
+
remain in the population and produce `missing_recurrence_item`; an unregistered
|
|
116
|
+
component produces `unregistered_recurrence_item`. The complete verdict is
|
|
117
|
+
computed before filtering or pagination, so a covered first page cannot hide
|
|
118
|
+
an uncovered member later in the graph.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
lineage_request=$(jq -cn --slurpfile policy config/defect-recurrence-policy.json \
|
|
122
|
+
'{policy:$policy[0],limit:25,uncoveredOnly:true}')
|
|
123
|
+
pm assurance lineages --definition "$lineage_request" --json
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
SDK, CLI, and MCP accept the same `definition`. Use `limit` from 1 through 100,
|
|
127
|
+
`cursor`, and `uncoveredOnly` inside that object. Continuations bind the policy,
|
|
128
|
+
complete recurrence evidence, item presence, and filter; changing page size is
|
|
129
|
+
allowed. `total`, `has_more`, and `next_cursor` describe the selected rows;
|
|
130
|
+
`population` always describes every recorded recurrence member. The CLI analysis
|
|
131
|
+
returns a report; the repository gate makes its `ok` predicate blocking.
|
|
132
|
+
|
|
133
|
+
The denominator includes covered, uncovered, and missing recurrence ids across
|
|
134
|
+
all lifecycle states. Recorded recognized `escape_class` values produce class
|
|
135
|
+
counts; unclassified members are never silently counted as non-escapes.
|
|
136
|
+
`escape_rate` is null for an empty or incompletely classified population.
|
|
137
|
+
`escape_rate_lower_bound` separately reports known production defects divided by
|
|
138
|
+
the entire population. Family labels never backfill item classifications, and
|
|
139
|
+
`budget_scope: "registered_families_only"` prevents policy budgets from being
|
|
140
|
+
mistaken for proof about an unknown population.
|
|
141
|
+
|
|
142
|
+
Registration means checks are selected, not that the defect is fixed or a
|
|
143
|
+
hosted check has passed. The policy includes domain seeds for all current
|
|
144
|
+
recorded components, while future disconnected recurrences fail the gate until
|
|
145
|
+
a justified family is registered. Future edges within a registered lineage
|
|
146
|
+
inherit protection automatically.
|
|
83
147
|
|
|
84
148
|
## Defect Evidence on PM Items
|
|
85
149
|
|
|
@@ -123,10 +187,20 @@ pnpm quality:defect-evidence
|
|
|
123
187
|
node scripts/release/defect-evidence-gate.mjs --negative-control --json
|
|
124
188
|
```
|
|
125
189
|
|
|
126
|
-
The first command must pass. The negative control must exit `1` after replacing a captured sample with a forbidden source and adding a terminal defect without evidence.
|
|
190
|
+
The first command must pass. The negative control must exit `1` after replacing a captured sample with a forbidden source and adding a terminal defect without evidence. The policy-only negative control
|
|
191
|
+
adds a disconnected, unregistered recurrence pair and must also exit `1`. Focused provider modes are available as `--boundary-only`, `--evidence-only`, and `--policy-only`.
|
|
127
192
|
|
|
128
193
|
`repository-defect-evidence-required` is part of the blocking `repository-static-quality` assurance composition. That makes local and CI behavior share the same provider result, assertion negative control, enforcement, and immutable verdict semantics.
|
|
129
194
|
|
|
195
|
+
The mandatory `gate-registry` check also compares each recurrence family's `checks.hosted` values with concrete names derived from the repository workflows. It expands static matrix axes and applies exclusions before inclusions according to [GitHub's matrix rules](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstrategymatrixinclude). Renamed or removed checks produce named findings. Runtime expressions, unnamed matrix jobs, and static expansions beyond 256 combinations cannot certify a required check name. The public SDK policy parser remains provider-neutral; this workflow binding belongs to the repository gate.
|
|
196
|
+
|
|
197
|
+
Assurance request schemas declare each family's required identity, triggers,
|
|
198
|
+
checks, historical IDs, budgets, and negative-control input. Runtime policy
|
|
199
|
+
validation additionally verifies unique family IDs and that each negative control
|
|
200
|
+
actually selects its family; structural JSON Schema validation alone cannot prove
|
|
201
|
+
those relationships. Risk reasons are sorted after direct and inherited matches
|
|
202
|
+
are combined, using signal, value, then matched evidence as stable ordering keys.
|
|
203
|
+
|
|
130
204
|
## Recovery Producer Census
|
|
131
205
|
|
|
132
206
|
`censusPmRecoveryReferenceProducers` scans complete source files for static object-literal recovery fields. It ignores type literals, destructuring patterns, labels, comments, strings, templates, and regular expressions. Aliases such as `candidate_commands`, nested `fallback_candidates[].command`, `next_best_command`, `retry_command`, and `suggested_next_steps` normalize to the same six public recovery kinds used by executable reachability verification.
|