@unbrained/pm-cli 2026.8.21 → 2026.8.23

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.
Files changed (228) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +44 -0
  3. package/dist/cli/error-guidance.d.ts +22 -4
  4. package/dist/cli/error-guidance.js +73 -16
  5. package/dist/cli/main.d.ts +3 -0
  6. package/dist/cli/main.js +51 -9
  7. package/dist/cli/register-mutation.js +6 -6
  8. package/dist/cli/register-operations.d.ts +73 -0
  9. package/dist/cli/register-operations.js +39 -14
  10. package/dist/cli/register-setup.js +3 -3
  11. package/dist/cli/schema-registration-helpers.d.ts +8 -1
  12. package/dist/cli/schema-registration-helpers.js +14 -5
  13. package/dist/cli-bundle/bundle-manifest.json +149 -149
  14. package/dist/cli-bundle/chunks/chunk-3ENVHX6C.js +36 -0
  15. package/dist/cli-bundle/chunks/{chunk-LOVTQ52Z.js → chunk-DW2CGEMU.js} +2 -2
  16. package/dist/cli-bundle/chunks/chunk-EG6CLDZT.js +5 -0
  17. package/dist/cli-bundle/chunks/{chunk-LARJJ3RK.js → chunk-F3AI2JFL.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-N3DSV4CH.js → chunk-HWZ6CELB.js} +8 -8
  19. package/dist/cli-bundle/chunks/chunk-HZBMLSZI.js +201 -0
  20. package/dist/cli-bundle/chunks/chunk-JB4KZWBF.js +3 -0
  21. package/dist/cli-bundle/chunks/chunk-KPH73XXJ.js +2 -0
  22. package/dist/cli-bundle/chunks/{chunk-BKYB45NQ.js → chunk-KXPMB2YL.js} +50 -50
  23. package/dist/cli-bundle/chunks/{chunk-BUNIEJNE.js → chunk-QDVHNHAQ.js} +2 -2
  24. package/dist/cli-bundle/chunks/chunk-TFI5V5N2.js +13 -0
  25. package/dist/cli-bundle/chunks/{register-list-query-F57EWDEF.js → register-list-query-UJB5FMV2.js} +2 -2
  26. package/dist/cli-bundle/chunks/register-mutation-NX5XE4VX.js +20 -0
  27. package/dist/cli-bundle/chunks/register-operations-RXIJIYXC.js +2 -0
  28. package/dist/cli-bundle/chunks/{register-setup-HXU7IZZD.js → register-setup-GFUZEKRE.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-F4YEW5I2.js → chunk-37Z4OEAP.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-3UPTYG44.js +8 -0
  31. package/dist/cli-bundle/focused-chunks/chunk-5S7E72FY.js +16 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-4ERLO7QD.js → chunk-AUFH5H35.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/chunk-E7X25GC3.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/chunk-FQCSTBWE.js +4 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-FH6DYED3.js → chunk-FZS4H32O.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/chunk-IFLWKY2R.js +156 -0
  37. package/dist/cli-bundle/focused-chunks/{chunk-YKBKIEAJ.js → chunk-JOWDB2MH.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-LYVSW5VM.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/chunk-MRCNF3U6.js +2 -0
  40. package/dist/cli-bundle/focused-chunks/{chunk-UZE7XUZK.js → chunk-OFVUGTLJ.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/{chunk-FJ22HNRP.js → chunk-OGLQBL46.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/chunk-OY7QAV4Y.js +51 -0
  43. package/dist/cli-bundle/focused-chunks/chunk-QGFNI65N.js +26 -0
  44. package/dist/cli-bundle/focused-chunks/{chunk-KDNG7TKQ.js → chunk-R27IDGHD.js} +2 -2
  45. package/dist/cli-bundle/focused-chunks/chunk-UYRFYCDQ.js +5 -0
  46. package/dist/cli-bundle/focused-chunks/{chunk-2NIY5NKG.js → chunk-ZHVA42R5.js} +9 -9
  47. package/dist/cli-bundle/main.js +13 -13
  48. package/dist/cli-bundle/sdk-authoring.js +1 -1
  49. package/dist/cli-bundle/sdk-contracts.js +2 -2
  50. package/dist/cli-bundle/sdk-core.js +40 -40
  51. package/dist/cli-bundle/sdk-governance.js +1 -1
  52. package/dist/cli-bundle/sdk-graph.js +1 -1
  53. package/dist/cli-bundle/sdk-merge.js +33 -32
  54. package/dist/cli-bundle/sdk-query.js +1 -1
  55. package/dist/cli-bundle/sdk-runtime.js +1 -1
  56. package/dist/cli-bundle/sdk-testing.js +1 -1
  57. package/dist/cli-bundle/sdk.js +5 -5
  58. package/dist/core/config/nested-settings.js +8 -2
  59. package/dist/core/config/positional-value.d.ts +1 -1
  60. package/dist/core/config/positional-value.js +5 -2
  61. package/dist/core/extensions/extension-hook-runtime.js +22 -20
  62. package/dist/core/extensions/extension-types.d.ts +8 -1
  63. package/dist/core/extensions/extension-types.js +2 -2
  64. package/dist/core/extensions/loader.js +7 -3
  65. package/dist/core/extensions/service-ownership.d.ts +8 -0
  66. package/dist/core/extensions/service-ownership.js +20 -0
  67. package/dist/core/history/history.js +3 -3
  68. package/dist/core/item/id.js +20 -5
  69. package/dist/core/item/item-format.js +81 -2
  70. package/dist/core/reproducibility/context.d.ts +4 -0
  71. package/dist/core/reproducibility/context.js +14 -8
  72. package/dist/core/shared/author.d.ts +55 -1
  73. package/dist/core/shared/author.js +333 -16
  74. package/dist/core/shared/constants.js +3 -2
  75. package/dist/core/shared/errors.d.ts +4 -0
  76. package/dist/core/shared/errors.js +2 -2
  77. package/dist/core/store/settings-validator.d.ts +1 -0
  78. package/dist/core/store/settings-validator.js +6 -3
  79. package/dist/core/store/settings.js +5 -2
  80. package/dist/mcp/server.d.ts +1 -1
  81. package/dist/mcp/server.js +30 -9
  82. package/dist/sdk/agent/identity-config.d.ts +63 -0
  83. package/dist/sdk/agent/identity-config.js +107 -0
  84. package/dist/sdk/agent/refusal-corpus-contracts.d.ts +76 -0
  85. package/dist/sdk/agent/refusal-corpus-contracts.js +194 -0
  86. package/dist/sdk/agent/refusal-reachability.d.ts +1 -1
  87. package/dist/sdk/authoring.d.ts +1 -1
  88. package/dist/sdk/authoring.js +2 -2
  89. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +77 -0
  90. package/dist/sdk/cli-contracts/agent-output-contracts.js +326 -2
  91. package/dist/sdk/cli-contracts/commander-mutation-options.js +3 -3
  92. package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -0
  93. package/dist/sdk/cli-contracts/enum-contracts.js +9 -2
  94. package/dist/sdk/cli-contracts/flag-contracts.js +9 -2
  95. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +4 -4
  96. package/dist/sdk/cli-contracts/registration-helpers.js +5 -2
  97. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +3 -1
  98. package/dist/sdk/cli-contracts/runtime-contracts.js +4 -3
  99. package/dist/sdk/cli-contracts/tool-parameter-tables.js +22 -2
  100. package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
  101. package/dist/sdk/cli-contracts/tool-schema.js +14 -3
  102. package/dist/sdk/cli-contracts.d.ts +4 -4
  103. package/dist/sdk/cli-contracts.js +5 -5
  104. package/dist/sdk/config.d.ts +6 -1
  105. package/dist/sdk/config.js +119 -14
  106. package/dist/sdk/context-intent-contracts.js +4 -2
  107. package/dist/sdk/core-governance.d.ts +1 -1
  108. package/dist/sdk/core-governance.js +3 -3
  109. package/dist/sdk/extension/install-sources.d.ts +1 -1
  110. package/dist/sdk/extension/install-sources.js +6 -3
  111. package/dist/sdk/extension/output-ownership.d.ts +1 -0
  112. package/dist/sdk/extension/output-ownership.js +3 -2
  113. package/dist/sdk/extension/scaffold.js +11 -5
  114. package/dist/sdk/flag-invocation-contracts.js +4 -2
  115. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +74 -2
  116. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +87 -26
  117. package/dist/sdk/governance/assurance-action.js +30 -10
  118. package/dist/sdk/governance/health.d.ts +3 -0
  119. package/dist/sdk/governance/health.js +39 -7
  120. package/dist/sdk/governance/hierarchy-validation.d.ts +29 -0
  121. package/dist/sdk/governance/hierarchy-validation.js +109 -0
  122. package/dist/sdk/governance/validate.d.ts +3 -9
  123. package/dist/sdk/governance/validate.js +84 -111
  124. package/dist/sdk/graph/assembly.d.ts +6 -1
  125. package/dist/sdk/graph/assembly.js +16 -22
  126. package/dist/sdk/graph/governance-contracts.d.ts +1 -1
  127. package/dist/sdk/graph/governance-contracts.js +8 -2
  128. package/dist/sdk/graph/governance.js +46 -2
  129. package/dist/sdk/graph/hierarchy-integrity.d.ts +94 -0
  130. package/dist/sdk/graph/hierarchy-integrity.js +311 -0
  131. package/dist/sdk/graph/index.d.ts +2 -1
  132. package/dist/sdk/graph/index.js +3 -2
  133. package/dist/sdk/graph/remediation.js +32 -2
  134. package/dist/sdk/graph/run.d.ts +31 -2
  135. package/dist/sdk/graph/run.js +80 -31
  136. package/dist/sdk/graph/workspace-relationship-kind-registry.d.ts +8 -0
  137. package/dist/sdk/graph/workspace-relationship-kind-registry.js +28 -0
  138. package/dist/sdk/index.d.ts +8 -3
  139. package/dist/sdk/index.js +9 -4
  140. package/dist/sdk/item-children.js +21 -8
  141. package/dist/sdk/lifecycle/create.js +129 -97
  142. package/dist/sdk/lifecycle/hierarchy-mutation-lock.d.ts +15 -0
  143. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +25 -0
  144. package/dist/sdk/lifecycle/update.d.ts +2 -0
  145. package/dist/sdk/lifecycle/update.js +174 -84
  146. package/dist/sdk/merge/three-way.js +105 -26
  147. package/dist/sdk/query/complete-list.d.ts +3 -3
  148. package/dist/sdk/query/complete-list.js +46 -3
  149. package/dist/sdk/query/list.d.ts +4 -3
  150. package/dist/sdk/query/list.js +89 -49
  151. package/dist/sdk/read-output-budget.d.ts +21 -0
  152. package/dist/sdk/read-output-budget.js +39 -2
  153. package/dist/sdk/read-output-contracts.d.ts +10 -4
  154. package/dist/sdk/read-output-contracts.js +105 -32
  155. package/dist/sdk/relationship-context.js +3 -4
  156. package/dist/sdk/relationships.js +17 -10
  157. package/dist/sdk/reproducibility/process.d.ts +19 -0
  158. package/dist/sdk/reproducibility/process.js +88 -0
  159. package/dist/sdk/runtime-primitives.d.ts +1 -1
  160. package/dist/sdk/runtime-primitives.js +3 -3
  161. package/dist/sdk/runtime.d.ts +3 -2
  162. package/dist/sdk/runtime.js +7 -5
  163. package/dist/sdk/test/batch.d.ts +6 -0
  164. package/dist/sdk/test/batch.js +26 -6
  165. package/dist/sdk/test/entry.d.ts +1 -1
  166. package/dist/sdk/test/entry.js +3 -2
  167. package/dist/sdk/test/execution.d.ts +28 -3
  168. package/dist/sdk/test/execution.js +201 -34
  169. package/dist/sdk/test/parsers.d.ts +6 -0
  170. package/dist/sdk/test/parsers.js +21 -2
  171. package/dist/sdk/test/trust.d.ts +33 -0
  172. package/dist/sdk/test/trust.js +207 -0
  173. package/dist/types.d.ts +34 -0
  174. package/dist/types.js +2 -2
  175. package/docs/AGENT_PROVENANCE_ADR.md +41 -5
  176. package/docs/AGENT_UX_CONTRACTS.md +20 -4
  177. package/docs/COMMANDS.md +29 -14
  178. package/docs/CONFIGURATION.md +4 -0
  179. package/docs/DEPENDENCY_KIND_CONTRACT.md +31 -3
  180. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +115 -0
  181. package/docs/EXTENSIONS.md +2 -1
  182. package/docs/MERGE_SAFETY.md +15 -1
  183. package/docs/README.md +1 -0
  184. package/docs/READ_OUTPUT_CONTRACTS.md +19 -2
  185. package/docs/RELATIONSHIP_GRAPH.md +6 -3
  186. package/docs/REPRODUCIBLE_WORKSPACES.md +42 -8
  187. package/docs/SDK.md +9 -0
  188. package/docs/SDK_AGENT_SESSION_CONTEXT.md +6 -4
  189. package/docs/SDK_EVIDENCE_TRACEABILITY.md +1 -1
  190. package/docs/TESTING.md +83 -1
  191. package/docs/agent-task-token-baseline.json +2 -2
  192. package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
  193. package/marketplace.json +2 -2
  194. package/package.json +2 -2
  195. package/packages/pm-beads/package.json +1 -1
  196. package/packages/pm-calendar/package.json +1 -1
  197. package/packages/pm-command-kit/package.json +1 -1
  198. package/packages/pm-digital-twin/package.json +1 -1
  199. package/packages/pm-governance-audit/package.json +1 -1
  200. package/packages/pm-guide-shell/package.json +1 -1
  201. package/packages/pm-kanban/package.json +1 -1
  202. package/packages/pm-lifecycle-hooks/package.json +1 -1
  203. package/packages/pm-linked-test-adapters/package.json +1 -1
  204. package/packages/pm-search-advanced/package.json +1 -1
  205. package/packages/pm-templates/package.json +1 -1
  206. package/packages/pm-todos/package.json +1 -1
  207. package/packages/pm-vcs/package.json +1 -1
  208. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  209. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  210. package/sdk/public-surface.json +1021 -53
  211. package/dist/cli-bundle/chunks/chunk-2MA6ZQVZ.js +0 -197
  212. package/dist/cli-bundle/chunks/chunk-3AFAUHUE.js +0 -2
  213. package/dist/cli-bundle/chunks/chunk-7VHZS727.js +0 -5
  214. package/dist/cli-bundle/chunks/chunk-JSLOFXGA.js +0 -3
  215. package/dist/cli-bundle/chunks/chunk-OCLPLFAY.js +0 -35
  216. package/dist/cli-bundle/chunks/chunk-S4IRYKBU.js +0 -13
  217. package/dist/cli-bundle/chunks/register-mutation-7IY2D5KO.js +0 -20
  218. package/dist/cli-bundle/chunks/register-operations-FALL3YTU.js +0 -2
  219. package/dist/cli-bundle/focused-chunks/chunk-7WZRLCYF.js +0 -50
  220. package/dist/cli-bundle/focused-chunks/chunk-CKKQSJNN.js +0 -2
  221. package/dist/cli-bundle/focused-chunks/chunk-EEFKYMDR.js +0 -16
  222. package/dist/cli-bundle/focused-chunks/chunk-F2A56DHV.js +0 -8
  223. package/dist/cli-bundle/focused-chunks/chunk-FV5ACOK7.js +0 -2
  224. package/dist/cli-bundle/focused-chunks/chunk-JEAVFOWM.js +0 -2
  225. package/dist/cli-bundle/focused-chunks/chunk-NJ63LOP6.js +0 -155
  226. package/dist/cli-bundle/focused-chunks/chunk-NXRTQ7HI.js +0 -2
  227. package/dist/cli-bundle/focused-chunks/chunk-TJ7EMJ46.js +0 -4
  228. package/dist/cli-bundle/focused-chunks/chunk-ZOSEELYJ.js +0 -26
@@ -0,0 +1,115 @@
1
+ # Diagnostic Output Contracts
2
+
3
+ Tracker references: [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-f05lsg](../.agents/pm/features/pm-f05lsg.toon), and [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon).
4
+
5
+ ## Agent Quick Context
6
+
7
+ Failures are context-management surfaces. Every diagnostic family now declares
8
+ a format-aware token ceiling and one degradation ladder in the public SDK:
9
+
10
+ | Class | Text | JSON | Corrective action that survives degradation |
11
+ | -------------------- | ---: | ---: | ------------------------------------------- |
12
+ | `error` | 768 | 2000 | required action, retry/domain, or next step |
13
+ | `warning` | 768 | 2000 | required action, retry/domain, or next step |
14
+ | `validation_summary` | 1500 | 3000 | required action, retry/domain, or next step |
15
+ | `recovery_bundle` | 768 | 2000 | required action, retry/domain, or next step |
16
+
17
+ The smallest explicit ceiling is 192 estimated tokens. At that floor, the
18
+ projector may reduce the diagnostic to its code, required action, compact
19
+ recovery, and exit status. It never removes the first corrective action.
20
+
21
+ ## SDK Contract
22
+
23
+ Use the public contract surface rather than maintaining a package-local error
24
+ budget:
25
+
26
+ ```ts
27
+ import {
28
+ PM_DIAGNOSTIC_OUTPUT_BUDGET_CONTRACTS,
29
+ projectPmDiagnosticOutput,
30
+ projectPmDiagnosticText,
31
+ resolvePmDiagnosticOutputBudget,
32
+ } from "@unbrained/pm-cli/sdk/contracts";
33
+
34
+ const contract = resolvePmDiagnosticOutputBudget("error");
35
+ const projected = projectPmDiagnosticOutput(
36
+ {
37
+ code: "invalid_argument_value",
38
+ required: "Use --status open and retry.",
39
+ recovery: { suggested_retry: "pm list --status open" },
40
+ detail: "The supplied status is not declared.",
41
+ exit_code: 2,
42
+ },
43
+ { maxEstimatedTokens: contract.minimum_max_estimated_tokens },
44
+ );
45
+
46
+ const text = projectPmDiagnosticText(
47
+ "A long rendered diagnostic",
48
+ "Use --status open and retry.",
49
+ ).output;
50
+ ```
51
+
52
+ The JSON projector orders `code`, `required`, recovery, and next steps before
53
+ explanation. Untruncated diagnostics add no per-call receipt overhead; their
54
+ binding declaration is discoverable from `pm contracts --full --json` under
55
+ `diagnostic_output_contracts`. When degradation occurs, the returned
56
+ `diagnostic_output` receipt records the effective budget, original and emitted
57
+ estimates, applied stages, and omitted top-level fields. Minimal fallbacks bound
58
+ the named omission list and disclose any additional count through
59
+ `omitted_fields_overflow_count`.
60
+
61
+ Structured CLI refusals also include a compact `refusal` identity with the
62
+ failing command/flag/operand surface, rejected scalar when observable, complete
63
+ legal domain when one exists, and the process exit code. Recovery-bearing
64
+ errors use the `recovery_bundle` diagnostic class. Collection degradation may
65
+ compact explanatory domains inside `recovery`, but `refusal.legal_domain`
66
+ remains complete and `recovery.suggested_retry_args` is atomic: the projector
67
+ either retains the executable argv or removes the recovery rather than slicing
68
+ it into a dead command.
69
+
70
+ The deterministic ladder is:
71
+
72
+ 1. full diagnostic;
73
+ 2. omit explanation;
74
+ 3. limit diagnostic collections;
75
+ 4. compact recovery to actionable keys;
76
+ 5. retain the action-only envelope.
77
+
78
+ Human diagnostics lead with `What is required` and next steps before explaining
79
+ what happened. If their declared ceiling binds, the compact text still begins
80
+ with the required action and points to structured JSON for the bounded recovery
81
+ envelope.
82
+
83
+ ## Executable Assurance
84
+
85
+ `pnpm quality:recovery-closure` builds the current CLI and replays 117 refusal
86
+ contracts in isolated trackers: 18 closed-domain rows, 88 required-argument
87
+ omissions derived from core executable positional signatures, seven
88
+ closed-action families, and four tracker-preflight states. Package-owned
89
+ commands enter executable coverage when their package runtime is active rather
90
+ than being misreported as core. Ten representative, high-frequency failure
91
+ paths are also ratcheted by
92
+ `scripts/release/diagnostic-output-baseline.json`. The gate requires every row
93
+ to remain within the SDK-declared JSON ceiling and retain a mechanically
94
+ actionable correction. It reports the aggregate original and emitted token
95
+ estimates without claiming a reduction when no degradation was required.
96
+
97
+ The baseline is a coverage ratchet, not permission to weaken a ceiling. Its
98
+ negative control requires a missing baseline probe to fail. The existing
99
+ refusal-closure negative controls independently prove that incomplete domains,
100
+ broken retries, and malformed recovery envelopes remain blocking findings.
101
+ The grammar corpus additionally hashes authoritative tracker state around each
102
+ refusal; schema, items, history, settings, and package state must not change.
103
+ Ephemeral runtime lock/cache directories are excluded from that semantic
104
+ snapshot.
105
+
106
+ Run the focused proof with:
107
+
108
+ ```bash
109
+ pnpm build
110
+ node scripts/release/refusal-closure-gate.mjs
111
+ node scripts/run-tests.mjs test -- \
112
+ tests/unit/sdk/agent-output-contracts.spec.ts \
113
+ tests/unit/cli/error-guidance.spec.ts \
114
+ tests/unit/scripts/refusal-closure-gate.spec.ts
115
+ ```
@@ -45,6 +45,7 @@ pm install kanban --project
45
45
  External registry packages are installed by exact package name. If `npm:<name>` returns a registry 404, JSON error output includes `fallback_candidates` and `next_best_command`; unpublished first-party packages fall back to `pm install --project github.com/unbraind/<name>`. Install results include package-owned `command_paths`, `action_paths`, `contributions`, `command_discovery`, and a light `verification` block covering the target tracker, activation status, registered commands/actions/item types, and health verdict. Agents should consume those fields instead of guessing from the package name or immediately spending another invocation on doctor. A successful activation persists the versioned contribution inventory in `.managed-extensions.json`; subsequent discovery can enumerate command handlers, hooks, parser/renderer targets, schema names, and the other registered surfaces without importing the package module. A failed runtime activation returns `ok: false`, `activated: false`, a non-zero CLI exit, and actionable diagnostics; missing SDK resolution adds an explicit dependency recovery step. Local installs are containment-safe when the extension destination is nested inside the source checkout: pm stages the package outside the source and prunes the destination, `.agents`, `node_modules`, and install-backup directories before copying, so reinstalling cannot recursively copy tracker history, host dependencies, or prior backups.
46
46
  Local `.tgz` and `.tar.gz` npm archives are inspected and extracted in an isolated temporary directory without invoking a shell. Archives must contain one `package/package.json` root, regular files/directories only, and bounded entry and expanded-byte totals. Absolute paths, traversal, alternate roots, links, device entries, oversized entries, and decompression-ratio abuse fail before installation. The managed source remains the original archive path, so reload and upgrade provenance do not point at a temporary extraction directory.
47
47
  Registry dependency names and versions are parsed as npm package specs before the install subprocess starts. Leading-option names and shell control syntax are rejected. npm reads those validated dependencies from an isolated runtime-only manifest; no caller-controlled spec is forwarded through the Windows command shell, and the fixed invocation still ends option parsing with `--`. Runtime verification then activates a temporary snapshot of the complete installed extension directory, so an upgrade cannot silently reuse stale transitive ESM dependencies from the current process. Successful install details expose `module_graph_verification: "fresh_snapshot"` for this check.
48
+ pm-owned npm subprocesses clear any inherited, case-insensitive `npm_config_allow_scripts` value while retaining registry, auth, proxy, and executable-path environment; `--ignore-scripts` remains authoritative. Tracked by [pm-gh1072](../.agents/pm/issues/pm-gh1072.toon).
48
49
  An explicit `--pm-path` scopes project installs to that tracker root, including extension files, managed state, settings, type-folder scaffolding, and verification output. This is the safe form for temporary package testing from inside another repository checkout.
49
50
 
50
51
  ```bash
@@ -308,7 +309,7 @@ Common APIs:
308
309
  - `api.registerMigration(definition)` adds schema migrations.
309
310
  - `api.registerProfile(profile)` contributes a project profile — a declarative archetype bundling item types, statuses, fields, per-type workflows, config, templates, and package recommendations. Once active it resolves by name through `pm profile list/show/apply` alongside the core `agile`/`ops`/`research` archetypes (built-in names are reserved; a colliding registration is ignored with a warning). Requires the `schema` capability.
310
311
  - `api.registerAssuranceMeasurementProvider(provider)` contributes typed measurements to assurance. It requires `services`; network providers also require manifest `permissions.network: true`. Gates allow providers and cost/network limits per trigger. See [Project Assurance Primitives](ASSURANCE.md#extension-measurement-providers) for examples.
311
- - `api.registerService("output_format", handler)` customizes output formatting through the service override API. Use `handleServiceOverride(result)` to claim a payload and return the scaffold-compatible literal `{ handled: false }` (or `declineServiceOverride()`) for commands the extension does not own. Legacy `null`/`undefined` declines remain supported; returning the original payload is now an unambiguous handled result.
312
+ - `api.registerService("output_format", handler, ownership?)` customizes output formatting through the service override API. Use `handleServiceOverride(result)` to claim a payload and return the scaffold-compatible literal `{ handled: false }` (or `declineServiceOverride()`) for commands the extension does not own. An override that is unconditionally inert can declare `{ passThrough: true }`; the host then ignores and diagnoses any handled result, and package doctor treats the registration as statically safe. Legacy `null`/`undefined` declines remain supported; returning the original payload is now an unambiguous handled result. Tracked by [pm-gh1074](../.agents/pm/issues/pm-gh1074.toon).
312
313
  - `api.registerRenderer("toon" | "json", renderer, ownership?)` adds format-specific renderers. Scope ownership with `commands` and/or a `resultDiscriminator`; the host checks both before invoking the renderer and falls back to native rendering for unrelated output. The legacy unscoped callback remains supported, but doctor warns because package ownership cannot be proven statically.
313
314
  - `suppressHostOutput(result?)` from `@unbrained/pm-cli/sdk` marks commands that already wrote output, preventing a second CLI payload while retaining the optional result for hooks, telemetry, and embedded hosts.
314
315
  - `api.hooks.beforeCommand(handler)`, `api.hooks.beforeMutation(handler)`, `api.hooks.afterCommand(handler)`, `api.hooks.onWrite(handler)`, `api.hooks.onRead(handler)`, and `api.hooks.onIndex(handler)` add lifecycle hooks.
@@ -1,6 +1,6 @@
1
1
  # Multi-Branch Tracker Merge Safety
2
2
 
3
- Tracked by [pm-wc1r](../.agents/pm/features/pm-wc1r.toon), with the integrity and concurrency fixes [pm-9q2t](../.agents/pm/issues/pm-9q2t.toon), [pm-cxyv](../.agents/pm/issues/pm-cxyv.toon), [pm-gpo7](../.agents/pm/issues/pm-gpo7.toon), [pm-m3nl](../.agents/pm/issues/pm-m3nl.toon), [pm-wwfd](../.agents/pm/issues/pm-wwfd.toon), and [pm-xdn6](../.agents/pm/issues/pm-xdn6.toon). Fresh-init fence ownership is tracked by [pm-1w3ljt](../.agents/pm/issues/pm-1w3ljt.toon); runtime-cache index governance by [pm-hous](../.agents/pm/issues/pm-hous.toon); local allocation safety by [pm-khdq](../.agents/pm/issues/pm-khdq.toon); fence-coverage completeness and drift detection by [pm-i4fx](../.agents/pm/issues/pm-i4fx.toon); package-defined item coverage by [pm-5rexki](../.agents/pm/issues/pm-5rexki.toon); non-item JSON coverage by [pm-gjicmx](../.agents/pm/issues/pm-gjicmx.toon); portable driver identity by [pm-w91mvg](../.agents/pm/issues/pm-w91mvg.toon); pending receipt validation by [pm-ysqb6n](../.agents/pm/issues/pm-ysqb6n.toon); receipt classification by [pm-jtwsct](../.agents/pm/issues/pm-jtwsct.toon); direction-independent item conflict selection by [pm-dlx7v7](../.agents/pm/issues/pm-dlx7v7.toon); corrected reconciliation guidance by [pm-lwmstb](../.agents/pm/issues/pm-lwmstb.toon); cross-branch id collision safety by [pm-pibw](../.agents/pm/issues/pm-pibw.toon); auditable merge history by [pm-9j2r3b](../.agents/pm/tasks/pm-9j2r3b.toon); durable conflict decisions by [pm-rh98vo](../.agents/pm/issues/pm-rh98vo.toon); continuous conformance by [pm-76dnfg](../.agents/pm/tasks/pm-76dnfg.toon); workspace-wide CI enforcement by [pm-pdr8t1](../.agents/pm/tasks/pm-pdr8t1.toon); post-merge reconciliation by [pm-mfkv92](../.agents/pm/issues/pm-mfkv92.toon); this repository's own adoption by [pm-iwsj](../.agents/pm/chores/pm-iwsj.toon).
3
+ Tracked by [pm-wc1r](../.agents/pm/features/pm-wc1r.toon), with the integrity and concurrency fixes [pm-9q2t](../.agents/pm/issues/pm-9q2t.toon), [pm-cxyv](../.agents/pm/issues/pm-cxyv.toon), [pm-gpo7](../.agents/pm/issues/pm-gpo7.toon), [pm-m3nl](../.agents/pm/issues/pm-m3nl.toon), [pm-wwfd](../.agents/pm/issues/pm-wwfd.toon), and [pm-xdn6](../.agents/pm/issues/pm-xdn6.toon). Fresh-init fence ownership is tracked by [pm-1w3ljt](../.agents/pm/issues/pm-1w3ljt.toon); runtime-cache index governance by [pm-hous](../.agents/pm/issues/pm-hous.toon); local allocation safety by [pm-khdq](../.agents/pm/issues/pm-khdq.toon); fence-coverage completeness and drift detection by [pm-i4fx](../.agents/pm/issues/pm-i4fx.toon); package-defined item coverage by [pm-5rexki](../.agents/pm/issues/pm-5rexki.toon); non-item JSON coverage by [pm-gjicmx](../.agents/pm/issues/pm-gjicmx.toon); portable driver identity by [pm-w91mvg](../.agents/pm/issues/pm-w91mvg.toon); pending receipt validation by [pm-ysqb6n](../.agents/pm/issues/pm-ysqb6n.toon); receipt classification by [pm-jtwsct](../.agents/pm/issues/pm-jtwsct.toon); direction-independent item conflict selection by [pm-dlx7v7](../.agents/pm/issues/pm-dlx7v7.toon); corrected reconciliation guidance by [pm-lwmstb](../.agents/pm/issues/pm-lwmstb.toon); cross-branch id collision safety by [pm-pibw](../.agents/pm/issues/pm-pibw.toon); auditable merge history by [pm-9j2r3b](../.agents/pm/tasks/pm-9j2r3b.toon); durable conflict decisions by [pm-rh98vo](../.agents/pm/issues/pm-rh98vo.toon); continuous conformance by [pm-76dnfg](../.agents/pm/tasks/pm-76dnfg.toon); workspace-wide CI enforcement by [pm-pdr8t1](../.agents/pm/tasks/pm-pdr8t1.toon); post-merge reconciliation by [pm-mfkv92](../.agents/pm/issues/pm-mfkv92.toon); linked-command execution trust by [pm-ed28wi](../.agents/pm/issues/pm-ed28wi.toon); this repository's own adoption by [pm-iwsj](../.agents/pm/chores/pm-iwsj.toon).
4
4
 
5
5
  pm stores project context as reviewable repository files. Concurrent agents can therefore use ordinary branches and worktrees, but tracker artifacts need semantic merge behavior: raw line merging cannot preserve TOON collection counts, JSON object structure, or append-only history hash chains.
6
6
 
@@ -61,6 +61,20 @@ pm merge install --dry-run --json
61
61
  | tracker `**/*.jsonl` except the later `history/*.jsonl` override | `pm-relationship` | Covers default and package-owned custom relationship event paths, unions divergent suffixes by `eventId` (timestamp-ordered, ours-first on ties), and renumbers `sequence` consecutively so the strict-sequence store loader accepts the merged stream. |
62
62
  | root `settings.json` and nested `**/*.json` | `pm-json` | Recursively merges objects per key. Arrays compose when both branches preserve the base and add distinct entries, so independent extension installs and evaluation additions merge without weakening edit/removal conflict detection. |
63
63
 
64
+ The `tests` collection has an additional execution-safety rule. Its semantic
65
+ identity excludes provenance so the same command/context does not duplicate
66
+ when branches record different authorship metadata. A test definition newly
67
+ contributed by the other merge side is persisted with
68
+ `provenance.source_kind=merge_union` while retaining its author, creation time,
69
+ and source ref. `pm test --run` and `pm test-all` refuse that command before
70
+ spawning a process until the receiving clone acknowledges its fingerprint or
71
+ uses the two-part project-policy plus per-run override documented in
72
+ [Testing](TESTING.md#linked-test-command-trust). `pm validate
73
+ --check-command-references` reports outstanding entries. This is the threat
74
+ boundary for append-like data that becomes executable after a merge; ordinary
75
+ notes, files, and other non-executable collections retain normal set-union
76
+ behavior.
77
+
64
78
  When both sides change the same item scalar differently, the driver writes the same stable value regardless of which branch Git labels ours or theirs, but exits nonzero. Item results and receipts expose the caller's `requested_preference`; the per-decision `retained` and `discarded` values or hashes are authoritative because stable value order can retain either side. Readers normalize the legacy receipt key `preferred`, while new receipts no longer emit it. JSON leaf conflicts retain the explicit preferred-side policy. Git keeps either path conflicted so a human or coordinating agent must review the discarded value and explicitly `git add` the resolution. This correction is tracked by [pm-qckpnq](../.agents/pm/issues/pm-qckpnq.toon).
65
79
 
66
80
  The driver result's `guidance` always points unresolved conflicts to `pm merge report`. When a clone-local receipt exists, guidance includes its privacy-safe receipt and item ids for exact correlation; discarded values remain confined to the local receipt and never appear in generic logs or tracker history. Tracked by [pm-fbrz7p](../.agents/pm/issues/pm-fbrz7p.toon).
package/docs/README.md CHANGED
@@ -51,6 +51,7 @@ pm guide release --json
51
51
  - [SDK Context Platform](SDK_CONTEXT.md) - task-oriented entry point for authoritative reads, ranking, package workflows, diagnostics, recovery, and verification.
52
52
  - [Self-Describing Context Contracts](SELF_DESCRIBING_CONTEXT_CONTRACTS.md) - intent-scoped reads, semantic flag invocation metadata, visibility parity, and generated error vocabulary.
53
53
  - [Universal Read Output Contracts](READ_OUTPUT_CONTRACTS.md) - cross-command include, amount, cost, and encoding controls for CLI, SDK, MCP, and packages.
54
+ - [Diagnostic Output Contracts](DIAGNOSTIC_OUTPUT_CONTRACTS.md) - action-first error budgets, deterministic degradation, SDK projection, and executable refusal assurance.
54
55
  - [Mutation Integrity](MUTATION_INTEGRITY.md) - shared CLI/SDK/MCP author, secret, append-only disposition, and stale-work guardrails.
55
56
  - [Agent Provenance ADR Amendment](AGENT_PROVENANCE_ADR.md) - extensible model, effort, role, and host provenance with privacy and compatibility boundaries.
56
57
  - [SDK Agent Session and Episode Context](SDK_AGENT_SESSION_CONTEXT.md) - inherited role/topic context, cross-process episode identity, and deterministic history grouping.
@@ -1,6 +1,6 @@
1
1
  # Universal Read Output Contracts
2
2
 
3
- Tracker references: [pm-hb7ug8](../.agents/pm/features/pm-hb7ug8.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), [pm-hid9g1](../.agents/pm/features/pm-hid9g1.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-eugaqy](../.agents/pm/issues/pm-eugaqy.toon), [pm-jt8aa2](../.agents/pm/issues/pm-jt8aa2.toon), [pm-kyjdne](../.agents/pm/issues/pm-kyjdne.toon), [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon), [pm-e5gl05](../.agents/pm/issues/pm-e5gl05.toon), [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), and [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.toon).
3
+ Tracker references: [pm-hb7ug8](../.agents/pm/features/pm-hb7ug8.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), [pm-hid9g1](../.agents/pm/features/pm-hid9g1.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-srns](../.agents/pm/issues/pm-srns.toon), [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-eugaqy](../.agents/pm/issues/pm-eugaqy.toon), [pm-jt8aa2](../.agents/pm/issues/pm-jt8aa2.toon), [pm-kyjdne](../.agents/pm/issues/pm-kyjdne.toon), [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon), [pm-e5gl05](../.agents/pm/issues/pm-e5gl05.toon), [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.toon), and [pm-xam9bt](../.agents/pm/issues/pm-xam9bt.toon).
4
4
 
5
5
  ## Agent Quick Context
6
6
 
@@ -140,7 +140,7 @@ pm stats --output-row-contract
140
140
  pm contracts --full --json
141
141
  ```
142
142
 
143
- Every projected result carries a `read_output` receipt with the requested dimensions, precedence, observed compatibility aliases, deterministic estimated token count, string/row compaction signals, and budget outcome. Budget degradation discovers nested arrays as well as declared result rows, so validation diagnostics and other governance payloads compact their inner findings before the useful result is omitted. `compacted_row_paths` names every reduced collection without redefining those nested arrays as ordinary pagination rows.
143
+ Every projected result carries a `read_output` receipt with the requested dimensions, precedence, observed option provenance, deterministic estimated token count, string/row compaction signals, and budget outcome. When canonical controls are present, `canonical_options_used` records spellings such as `--output-include`; the optional field is omitted when no canonical control was supplied so minimum-budget session receipts remain compact. `legacy_aliases_used` and `migration_hints` record only compatibility flags the caller actually supplied. A command-local flag synthesized internally to execute a canonical projection mode is therefore never misreported as deprecated syntax. When both spellings are supplied, both provenance arrays report that mixed invocation. Budget degradation discovers nested arrays as well as declared result rows, so validation diagnostics and other governance payloads compact their inner findings before the useful result is omitted. `compacted_row_paths` names every reduced collection without redefining those nested arrays as ordinary pagination rows.
144
144
 
145
145
  When rows are dropped to satisfy a ceiling, the result also carries `output_budget_truncation`, naming the binding budget and its source, any explicitly requested dimension the budget overrode, every compacted collection path, and executable CLI/SDK/MCP recovery options — a default ceiling can override an explicit `--output-limit unbounded`, and that override is reported rather than silent. If a producer supplied an opaque item-page cursor, compaction rebases it to the last row actually returned and reports `continuation_cursor_rebased: true`; following the cursor therefore cannot skip rows removed from the middle of a producer page. If no useful content can fit, `PmReadOutputBudgetExceeded` provides a discriminated omission result, a compact `{ outputBudget: "unbounded" }` recovery object, and `omitted_result_estimated_tokens`, the last useful-result estimate before omission; use `isReadOutputBudgetExceeded` before accessing result-specific fields. Universal controls are rejected on mutation commands and on the mutation mode of hybrid commands such as `comments`, `notes`, `files`, and `docs`.
146
146
 
@@ -164,6 +164,16 @@ an unbounded multi-megabyte response;
164
164
  `recovery_budget_multiplier: 1` declares that each next page retains the same
165
165
  useful-result ceiling.
166
166
 
167
+ When compaction affects a nested collection that is not declared resumable,
168
+ the recovery budget is derived from the larger of the binding ceiling plus one
169
+ and the measured pre-compaction result. The SDK adds a 25% envelope margin and
170
+ rounds up to 100 tokens. The CLI, SDK, and MCP bindings therefore receive the
171
+ same finite value, which is strictly larger than the request that already
172
+ truncated. If safe-integer arithmetic cannot represent that value, recovery
173
+ uses `unbounded` explicitly. `resolveReadOutputRecoveryBudget()` exposes the
174
+ versioned pure calculation to package authors; there is no hard-coded smaller
175
+ retry and no recovery cycle.
176
+
167
177
  Assurance declares `budget_retention_policy: verdict_priority`: failing block,
168
178
  warn, and observe rows precede retired and passing rows while preserving order
169
179
  within each class. `assertions_total` remains the pre-projection denominator,
@@ -179,6 +189,13 @@ key. Health retains at most 100 warning rows and reports `warning_count`,
179
189
  projection unless `--full` is explicit, keeping the failing check identities
180
190
  and warning codes inside the ordinary budget.
181
191
 
192
+ Failure transports use the companion
193
+ [Diagnostic Output Contracts](DIAGNOSTIC_OUTPUT_CONTRACTS.md). Those contracts
194
+ bind errors, warnings, validation summaries, and recovery bundles independently
195
+ from successful command results. Corrective actions precede explanation and
196
+ survive every degradation stage, while untruncated JSON avoids a per-call
197
+ receipt tax.
198
+
182
199
  ## SDK and Package Usage
183
200
 
184
201
  Typed `PmClient` read methods accept `PmReadOutputOptions` directly:
@@ -314,9 +314,12 @@ outcome milestones are roots, not work subjects, and are excluded from those
314
314
  populations. Rate or
315
315
  all-status floors are lifecycle-stable; an absolute active-population floor is
316
316
  invalid because completing reachable work legitimately moves it into the
317
- terminal population. `finding_subjects_by_code` includes every known finding
318
- code even when its population is zero, so assurance selectors never confuse a
319
- clean class with a missing contract field.
317
+ terminal population. Detailed output's nested SDK profile census,
318
+ `finding_subjects_by_code`, includes every known finding code even when its
319
+ population is zero, so assurance selectors never confuse a clean class with a
320
+ missing contract field. The top-level audit and persisted-baseline census is
321
+ `affected_subjects_by_code`; both fields count affected subjects, but their
322
+ locations and consumers differ and neither is an alias for the other.
320
323
 
321
324
  ```ts
322
325
  import {
@@ -1,7 +1,8 @@
1
1
  # Reproducible Workspaces and Snapshots
2
2
 
3
- Tracked by [pm-rbcvt2](../.agents/pm/features/pm-rbcvt2.toon) and
4
- [pm-dkrmzv](../.agents/pm/features/pm-dkrmzv.toon).
3
+ Tracked by [pm-rbcvt2](../.agents/pm/features/pm-rbcvt2.toon),
4
+ [pm-dkrmzv](../.agents/pm/features/pm-dkrmzv.toon), and
5
+ [pm-gh1089](../.agents/pm/issues/pm-gh1089.toon).
5
6
 
6
7
  These SDK primitives make a pm workspace reproducible without changing normal
7
8
  interactive behavior. Recipes control time and identifier entropy only inside
@@ -22,9 +23,7 @@ const recipe: WorkspaceRecipe = {
22
23
  seed: "example-fixture-v1",
23
24
  clock: "2026-07-28T10:00:00.000Z",
24
25
  tickMs: 1,
25
- operations: [
26
- { action: "create", input: { title: "Deterministic task" } },
27
- ],
26
+ operations: [{ action: "create", input: { title: "Deterministic task" } }],
28
27
  };
29
28
 
30
29
  const results = await executeWorkspaceRecipe(
@@ -36,9 +35,9 @@ const results = await executeWorkspaceRecipe(
36
35
  The caller owns action dispatch. pm owns the deterministic execution context:
37
36
  `nowIso()` advances from `clock` by `tickMs`, and generated item identifiers
38
37
  derive from `seed`. Async scopes are isolated with `AsyncLocalStorage`, so
39
- concurrent recipes do not share counters. Outside `runWithWorkspaceRecipe` or
40
- `executeWorkspaceRecipe`, the CLI continues using the system clock and
41
- cryptographic randomness.
38
+ concurrent recipes do not share counters. Normal CLI and MCP execution still
39
+ uses the system clock and cryptographic randomness unless the process opts in
40
+ through the environment contract below.
42
41
 
43
42
  `defineWorkspaceRecipe` immediately validates the clock, seed, tick, schema,
44
43
  operation actions, and recursively JSON-compatible inputs. Its TypeScript
@@ -51,6 +50,41 @@ Seeds are reproducibility inputs, not secrets. A replay is byte-identical only
51
50
  when it begins from equivalent authoritative state and invokes the same ordered
52
51
  operations with the same recipe.
53
52
 
53
+ ## CLI and MCP process configuration
54
+
55
+ Shell-based harnesses can install the same SDK-owned deterministic context for
56
+ the `pm` and `pm-mcp` processes without patching JavaScript globals:
57
+
58
+ ```bash
59
+ PM_CLOCK=2026-07-28T10:00:00.000Z \
60
+ PM_CLOCK_TICK_MS=1 \
61
+ PM_SEED=example-fixture-v1 \
62
+ pm create --title "Deterministic task" --type Task --json
63
+ ```
64
+
65
+ `PM_CLOCK` and `PM_SEED` are required together. `PM_CLOCK` must be an ISO-8601
66
+ instant with `Z` or a numeric UTC offset; timezone-less and non-ISO inputs are
67
+ rejected so separate hosts cannot interpret the same configuration differently.
68
+ `PM_CLOCK_TICK_MS` is optional, defaults to `1`, and must be a non-negative integer. Partial or invalid input
69
+ fails before command dispatch with the stable
70
+ `invalid_reproducible_process_environment` code and recovery that names the
71
+ missing or invalid variable. Unset all three variables for normal interactive
72
+ behavior.
73
+
74
+ Every CLI process invocation begins a fresh deterministic scope. A workflow
75
+ that launches several CLI processes must derive a stable, distinct seed for
76
+ each ordered step; reusing one seed intentionally reproduces the same entropy
77
+ sequence and can reproduce an existing generated identifier. A long-lived MCP
78
+ server instead owns one process-lifetime sequence and advances it across its
79
+ serialized JSON-RPC requests. Two equivalent servers therefore produce the
80
+ same files without generating duplicate identifiers inside either server.
81
+
82
+ The public SDK exports `PM_REPRODUCIBLE_PROCESS_ENV`,
83
+ `resolveReproducibleProcessEnvironment`,
84
+ `runWithReproducibleProcessEnvironment`, and
85
+ `createReproducibleProcessRunner` for custom one-shot and long-lived process
86
+ transports.
87
+
54
88
  ## Content-addressed snapshots
55
89
 
56
90
  The SDK exports:
package/docs/SDK.md CHANGED
@@ -1702,6 +1702,15 @@ const telemetry = await runTelemetry(
1702
1702
  global tracker roots. `pm_context_mode`, run-level overrides, automatic tracker
1703
1703
  context, assertion requirements, empty-run detection, and failure categories are
1704
1704
  part of the SDK result contract rather than presentation-layer behavior.
1705
+ Workspace results distinguish the run-level requested mode from the effective
1706
+ per-test mode. `isolated` executes from an empty disposable directory;
1707
+ `snapshot` executes from a filtered disposable workspace. Trust preflight
1708
+ failures report `trust_refusal`, while malformed or incomplete provenance uses
1709
+ the additive `provenance_invalid` storage marker and fail-closed
1710
+ `invalid_provenance` trust reason. Package mutation adapters can call
1711
+ `attachLinkedTestMutationProvenance` so Git inspection occurs only when commands
1712
+ are added; `resolveLinkedTestSourceWorkspaceRoot` keeps their source-ref lookup
1713
+ aligned with CLI execution and `PM_SOURCE_WORKSPACE_ROOT` overrides.
1705
1714
  When item test-result tracking is enabled, `measure` persists typed numeric
1706
1715
  evidence on the producing run. Each entry has a stable name, finite numeric
1707
1716
  value, optional unit and threshold, and the run timestamp. Run history remains
@@ -6,7 +6,8 @@ Tracker references: [pm-9wbiye](../.agents/pm/issues/pm-9wbiye.toon),
6
6
  [pm-3zgh2c](../.agents/pm/features/pm-3zgh2c.toon),
7
7
  [pm-eq9dlw](../.agents/pm/issues/pm-eq9dlw.toon), and
8
8
  [pm-lu6sca](../.agents/pm/features/pm-lu6sca.toon), plus
9
- [pm-5q8wa0](../.agents/pm/issues/pm-5q8wa0.toon).
9
+ [pm-5q8wa0](../.agents/pm/issues/pm-5q8wa0.toon) and
10
+ [pm-c0lrdm](../.agents/pm/features/pm-c0lrdm.toon).
10
11
 
11
12
  Project management is context management. The public SDK therefore carries a
12
13
  session's purpose and episode boundary through the same immutable history that
@@ -128,9 +129,10 @@ public SDK exports for custom hosts.
128
129
  the bounded built-in resolver. It never contains environment values, session
129
130
  paths, prompts, or file contents.
130
131
 
131
- New mutation history records failed resolver outcomes under
132
- `context.agent_provenance_outcomes`; ordinary unavailable dimensions retain
133
- the compact legacy-compatible null projection. A resolver is only counted as
132
+ New mutation history records failed or explicitly unavailable configured
133
+ resolver outcomes under `context.agent_provenance_outcomes`; dimensions with
134
+ no configured resolver retain the compact legacy-compatible null projection.
135
+ A resolver is only counted as
134
136
  attempted when its required input belongs to the detected harness; a foreign
135
137
  host's shared `AI_AGENT` value is not Codex input. Consequently `pm health` can report
136
138
  `provenance_resolver_zero_success:<harness>:<dimension>:<resolver>:<attempts>`
@@ -111,7 +111,7 @@ pair pre-redaction item content with post-redaction history during validation.
111
111
 
112
112
  ## Operational receipts
113
113
 
114
- Linked tests recognize compound acquisition failures such as “could not acquire … lock” together with contention context such as “already running” or “held by another” as `infra_collision`. Generic assertion text mentioning a lock or timeout remains `assertion_failure`, preventing false infrastructure classifications.
114
+ Linked tests recognize compound acquisition failures such as “could not acquire … lock” together with contention context such as “already running” or “held by another” as `infra_collision`. Generic assertion text mentioning a lock or timeout remains `assertion_failure`, preventing false infrastructure classifications. A command refused by clone-local provenance policy is classified separately as `trust_refusal`, so reports do not misstate a pre-execution safety decision as an assertion failure.
115
115
 
116
116
  Telemetry flush receipts distinguish progress from completion:
117
117
 
package/docs/TESTING.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This page describes safe local tests, linked tests, coverage, and release-readiness checks.
4
4
 
5
- Tracked implementation updates: [pm-52eh](../.agents/pm/features/pm-52eh.toon), [pm-mcxr](../.agents/pm/issues/pm-mcxr.toon), [pm-u42x](../.agents/pm/issues/pm-u42x.toon), [pm-atfm](../.agents/pm/features/pm-atfm.toon), [pm-xmp5](../.agents/pm/tasks/pm-xmp5.toon), [pm-39cqqx](../.agents/pm/tasks/pm-39cqqx.toon), [pm-5cgm2z](../.agents/pm/chores/pm-5cgm2z.toon), [pm-avv3wx](../.agents/pm/issues/pm-avv3wx.toon), [pm-rizqb6](../.agents/pm/issues/pm-rizqb6.toon), [pm-95h7pg](../.agents/pm/issues/pm-95h7pg.toon), [pm-giks4s](../.agents/pm/issues/pm-giks4s.toon), [pm-xa3t0o](../.agents/pm/issues/pm-xa3t0o.toon).
5
+ Tracked implementation updates: [pm-52eh](../.agents/pm/features/pm-52eh.toon), [pm-mcxr](../.agents/pm/issues/pm-mcxr.toon), [pm-u42x](../.agents/pm/issues/pm-u42x.toon), [pm-atfm](../.agents/pm/features/pm-atfm.toon), [pm-xmp5](../.agents/pm/tasks/pm-xmp5.toon), [pm-39cqqx](../.agents/pm/tasks/pm-39cqqx.toon), [pm-5cgm2z](../.agents/pm/chores/pm-5cgm2z.toon), [pm-avv3wx](../.agents/pm/issues/pm-avv3wx.toon), [pm-rizqb6](../.agents/pm/issues/pm-rizqb6.toon), [pm-95h7pg](../.agents/pm/issues/pm-95h7pg.toon), [pm-giks4s](../.agents/pm/issues/pm-giks4s.toon), [pm-xa3t0o](../.agents/pm/issues/pm-xa3t0o.toon), [pm-e97jyf](../.agents/pm/issues/pm-e97jyf.toon), [pm-efkvdy](../.agents/pm/issues/pm-efkvdy.toon), and [pm-ed28wi](../.agents/pm/issues/pm-ed28wi.toon).
6
6
 
7
7
  ## Agent Quick Context
8
8
 
@@ -366,6 +366,21 @@ The manifest records baseline bytes and estimated tokens for visible review
366
366
  deltas. Updating it cannot raise answer ceilings, which remain owned by
367
367
  `PM_COMMAND_OUTPUT_BUDGET_CONTRACTS`.
368
368
 
369
+ Diagnostic ceilings share the executable refusal gate:
370
+
371
+ ```bash
372
+ pnpm quality:recovery-closure
373
+ ```
374
+
375
+ The gate replays 117 refusal contracts: 18 closed-domain rows, 88
376
+ grammar-derived required-argument omissions, seven closed positional-action
377
+ families, and four tracker-preflight states. It also ratchets ten representative
378
+ failure paths against `PM_DIAGNOSTIC_OUTPUT_BUDGET_CONTRACTS`. Every diagnostic
379
+ must fit its declared JSON ceiling and preserve a mechanically actionable
380
+ correction; executable retry argv is never collection-truncated. The
381
+ missing-probe negative control and the authoritative tracker-state snapshot
382
+ prove that the corpus cannot silently shrink or turn a refusal into a mutation.
383
+
369
384
  The gate derives every supported harness, model, session, and provenance
370
385
  environment key from the SDK-owned harness descriptor registry. It deletes
371
386
  those host inputs before each fixture invocation, then supplies only the
@@ -429,6 +444,69 @@ into constrained temporary storage.
429
444
  Capacity, permission, and resource failures while seeding a required tracker
430
445
  surface as typed, path-redacted host-environment refusals with recovery steps.
431
446
 
447
+ ## Source Workspace Modes
448
+
449
+ Linked tests have a separate source-workspace contract. Store a default on one
450
+ entry with `workspace_context_mode`, or choose a run-level mode with
451
+ `--workspace-context`:
452
+
453
+ ```bash
454
+ pm test <item-id> --add-json '{"command":"pnpm quality:static","workspace_context_mode":"isolated"}'
455
+ pm test <item-id> --run --workspace-context snapshot --override-linked-workspace-context
456
+ ```
457
+
458
+ - `source` (default) runs in the source checkout and exposes its read-only
459
+ source-context environment, preserving existing linked-test behavior.
460
+ - `isolated` runs from an empty disposable directory and removes
461
+ `PM_SOURCE_WORKSPACE_ROOT`, `PM_SOURCE_PM_PATH`, and the source-context access
462
+ declaration. Use it only for commands that do not require checkout files.
463
+ - `snapshot` copies the workspace into the linked-test sandbox, runs from that
464
+ copy, and binds its `.agents/pm` path to the selected temporary tracker.
465
+ `.git`, `.agents`, `node_modules`, coverage output, and common cache
466
+ directories are excluded at every directory depth; an existing top-level
467
+ `node_modules` is linked read-only by convention. Built output remains
468
+ available so linked commands such as `node dist/cli.js` keep working. Writes
469
+ therefore land in the disposable snapshot rather than the source checkout.
470
+
471
+ Every result reports the requested/effective workspace mode, working
472
+ directory, exposed source root, and trust decision. Recorded `test_runs` retain
473
+ the effective workspace mode and trust reason beside the command.
474
+
475
+ ## Linked-Test Command Trust
476
+
477
+ Linked commands are stored shell programs, so merge-unioned tracker data is an
478
+ execution boundary. New command entries record author, creation time, source
479
+ branch when available, and whether the item merge driver introduced the entry.
480
+ Locally created commands keep their previous run behavior. Commands marked as
481
+ merge-unioned or carrying a different source ref fail before process creation.
482
+ Malformed provenance is sanitized to the additive `provenance_invalid` marker
483
+ and receives the same fail-closed treatment; it is never normalized into a
484
+ trusted legacy command.
485
+ These pre-execution refusals use the `trust_refusal` failure category, separate
486
+ from command or assertion failures.
487
+
488
+ Choose one explicit recovery:
489
+
490
+ ```bash
491
+ # Review and trust the item's current command fingerprints in this clone.
492
+ pm test <item-id> --acknowledge-linked-tests
493
+
494
+ # Or permit a single reviewed run. Both controls are required.
495
+ pm config project set untrusted-linked-test-execution enabled
496
+ pm test <item-id> --run --allow-untrusted-linked-tests
497
+ ```
498
+
499
+ Acknowledgments live in the clone-local ignored runtime directory and bind to
500
+ the full command, tracker/workspace context, environment controls, host-safety
501
+ mode, and provenance fingerprint; editing any of those fields requires a new
502
+ review. Enabling the project policy alone never executes
503
+ an untrusted command, and the per-run flag alone is also refused. Inspect all
504
+ unacknowledged entries without executing them with:
505
+
506
+ ```bash
507
+ pm validate --check-command-references --verbose-diagnostics
508
+ ```
509
+
432
510
  Use explicit modes when needed:
433
511
 
434
512
  ```bash
@@ -480,6 +558,10 @@ pm test <item-id> --metric-below coverage=100 --metric-diff p95_latency
480
558
 
481
559
  Measurements are stored on the producing `test_runs` row, retained with the
482
560
  bounded run history, and exposed consistently by CLI, SDK, MCP, and contracts.
561
+ Each recorded row also keeps a bounded `executions` list with the exact linked
562
+ command, requested/effective `pm_context_mode`, effective workspace mode, and
563
+ trust reason, so tracker-backed verification remains attributable after the
564
+ transient process logs are gone.
483
565
 
484
566
  ## Linked-Test Assertions
485
567
 
@@ -18,8 +18,8 @@
18
18
  },
19
19
  {
20
20
  "id": "failing-command",
21
- "max_estimated_tokens": 200
21
+ "max_estimated_tokens": 219
22
22
  }
23
23
  ],
24
- "composite_max_estimated_tokens": 2178
24
+ "composite_max_estimated_tokens": 2197
25
25
  }
@@ -55,8 +55,8 @@ This file is generated by `listPmFlagLexicon()`. Compatibility aliases do not co
55
55
  | `docs` | evidence | 30 | 30 |
56
56
  | `deps` | graph | 32 | 32 |
57
57
  | `plan` | graph | 109 | 109 |
58
- | `test` | quality | 48 | 48 |
59
- | `test-all` | quality | 37 | 37 |
58
+ | `test` | quality | 52 | 52 |
59
+ | `test-all` | quality | 40 | 40 |
60
60
  | `telemetry` | workspace | 21 | 21 |
61
61
  | `stats` | context | 29 | 29 |
62
62
  | `health` | workspace | 36 | 36 |
package/marketplace.json CHANGED
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.",
9
- "version": "2026.8.21"
9
+ "version": "2026.8.23"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "pm-claude",
14
14
  "source": "./plugins/pm-claude",
15
15
  "description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.",
16
- "version": "2026.8.21",
16
+ "version": "2026.8.23",
17
17
  "author": {
18
18
  "name": "unbrained",
19
19
  "url": "https://github.com/unbraind/pm-cli"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-cli",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.23",
4
4
  "description": "Git-native project management CLI for humans and agents.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.10.0",
@@ -220,7 +220,7 @@
220
220
  "@types/npm-package-arg": "^6.1.4",
221
221
  "@vitest/coverage-v8": "^4.1.11",
222
222
  "esbuild": "0.28.2",
223
- "eslint": "^10.8.1",
223
+ "eslint": "^10.9.0",
224
224
  "eslint-plugin-sonarjs": "^4.2.0",
225
225
  "eslint-plugin-unicorn": "^73.0.0",
226
226
  "fast-check": "^4.9.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-beads",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.23",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm package for importing Beads JSONL records.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-calendar",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.23",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm package for calendar and agenda views.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-command-kit",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.23",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm exemplar package for the commands capability: registerCommand, registerFlags, and registerParser.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-digital-twin",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.23",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Beyond-PM exemplar: a temporal production-facility digital twin built entirely on public pm SDK and extension primitives.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-governance-audit",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.23",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm package for governance audit and normalization workflows.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-guide-shell",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.23",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm package for guide and shell completion workflows.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-kanban",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.23",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm archetype package: a complete Kanban continuous-flow profile built on public SDK primitives.",