@unbrained/pm-cli 2026.8.21 → 2026.8.22

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 (158) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +16 -0
  3. package/dist/cli/error-guidance.d.ts +9 -4
  4. package/dist/cli/error-guidance.js +16 -15
  5. package/dist/cli/main.d.ts +3 -0
  6. package/dist/cli/main.js +40 -7
  7. package/dist/cli-bundle/bundle-manifest.json +153 -153
  8. package/dist/cli-bundle/chunks/{chunk-BKYB45NQ.js → chunk-BWX4SK46.js} +48 -48
  9. package/dist/cli-bundle/chunks/chunk-EMWDM5FI.js +13 -0
  10. package/dist/cli-bundle/chunks/chunk-HYG6LRL4.js +200 -0
  11. package/dist/cli-bundle/chunks/{chunk-LARJJ3RK.js → chunk-MYYI3ZOA.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-BUNIEJNE.js → chunk-MZTZQTMS.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-LOVTQ52Z.js → chunk-QI2CT3IX.js} +2 -2
  14. package/dist/cli-bundle/chunks/chunk-SMWXHMVB.js +35 -0
  15. package/dist/cli-bundle/chunks/{chunk-N3DSV4CH.js → chunk-U6GQ4VMV.js} +6 -6
  16. package/dist/cli-bundle/chunks/{chunk-3AFAUHUE.js → chunk-VMMIL3SI.js} +2 -2
  17. package/dist/cli-bundle/chunks/chunk-WG4STC36.js +5 -0
  18. package/dist/cli-bundle/chunks/{chunk-JSLOFXGA.js → chunk-YBPJAOQQ.js} +2 -2
  19. package/dist/cli-bundle/chunks/{register-list-query-F57EWDEF.js → register-list-query-HZKBQNWW.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-mutation-7IY2D5KO.js → register-mutation-HTKEEGRD.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-operations-FALL3YTU.js → register-operations-6EMRWJJY.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-setup-HXU7IZZD.js → register-setup-QK4OTOXN.js} +2 -2
  23. package/dist/cli-bundle/focused-chunks/{chunk-FJ22HNRP.js → chunk-2ARQGDDW.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/{chunk-CKKQSJNN.js → chunk-2AZT5WXZ.js} +2 -2
  25. package/dist/cli-bundle/focused-chunks/{chunk-F4YEW5I2.js → chunk-2POVTNLY.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/chunk-3LKU6PTJ.js +4 -0
  27. package/dist/cli-bundle/focused-chunks/chunk-5SHSBMX2.js +2 -0
  28. package/dist/cli-bundle/focused-chunks/{chunk-FH6DYED3.js → chunk-6S2MO3Q3.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-UZE7XUZK.js → chunk-A2BC5PQL.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-C4S4A4JJ.js +5 -0
  31. package/dist/cli-bundle/focused-chunks/{chunk-KDNG7TKQ.js → chunk-D6RBZEJJ.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/chunk-E2EWYPY6.js +16 -0
  33. package/dist/cli-bundle/focused-chunks/{chunk-4ERLO7QD.js → chunk-GMYPD4FX.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/chunk-L5LDSRO2.js +155 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-ZOSEELYJ.js → chunk-MB37AYN6.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/chunk-MCOR37QK.js +2 -0
  37. package/dist/cli-bundle/focused-chunks/{chunk-2NIY5NKG.js → chunk-PH2OXXVZ.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/{chunk-YKBKIEAJ.js → chunk-PMGJUFNQ.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/chunk-R6SR45XU.js +50 -0
  40. package/dist/cli-bundle/focused-chunks/chunk-WZE4LIPW.js +8 -0
  41. package/dist/cli-bundle/main.js +13 -13
  42. package/dist/cli-bundle/sdk-authoring.js +1 -1
  43. package/dist/cli-bundle/sdk-contracts.js +2 -2
  44. package/dist/cli-bundle/sdk-core.js +40 -40
  45. package/dist/cli-bundle/sdk-governance.js +1 -1
  46. package/dist/cli-bundle/sdk-graph.js +1 -1
  47. package/dist/cli-bundle/sdk-merge.js +32 -32
  48. package/dist/cli-bundle/sdk-query.js +1 -1
  49. package/dist/cli-bundle/sdk-runtime.js +1 -1
  50. package/dist/cli-bundle/sdk-testing.js +1 -1
  51. package/dist/cli-bundle/sdk.js +5 -5
  52. package/dist/core/extensions/extension-hook-runtime.js +22 -20
  53. package/dist/core/extensions/extension-types.d.ts +8 -1
  54. package/dist/core/extensions/extension-types.js +2 -2
  55. package/dist/core/extensions/loader.js +7 -3
  56. package/dist/core/extensions/service-ownership.d.ts +8 -0
  57. package/dist/core/extensions/service-ownership.js +20 -0
  58. package/dist/core/item/id.js +20 -5
  59. package/dist/core/item/item-format.js +27 -2
  60. package/dist/core/shared/errors.d.ts +4 -0
  61. package/dist/core/shared/errors.js +2 -2
  62. package/dist/sdk/agent/refusal-reachability.d.ts +1 -1
  63. package/dist/sdk/authoring.d.ts +1 -1
  64. package/dist/sdk/authoring.js +2 -2
  65. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +77 -0
  66. package/dist/sdk/cli-contracts/agent-output-contracts.js +324 -2
  67. package/dist/sdk/cli-contracts/commander-mutation-options.js +3 -3
  68. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +3 -1
  69. package/dist/sdk/cli-contracts/runtime-contracts.js +4 -3
  70. package/dist/sdk/cli-contracts.d.ts +1 -1
  71. package/dist/sdk/cli-contracts.js +3 -3
  72. package/dist/sdk/extension/install-sources.d.ts +1 -1
  73. package/dist/sdk/extension/install-sources.js +6 -3
  74. package/dist/sdk/extension/output-ownership.d.ts +1 -0
  75. package/dist/sdk/extension/output-ownership.js +3 -2
  76. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +38 -14
  77. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -2
  78. package/dist/sdk/governance/health.d.ts +3 -0
  79. package/dist/sdk/governance/health.js +39 -7
  80. package/dist/sdk/governance/hierarchy-validation.d.ts +29 -0
  81. package/dist/sdk/governance/hierarchy-validation.js +109 -0
  82. package/dist/sdk/governance/validate.d.ts +1 -7
  83. package/dist/sdk/governance/validate.js +47 -99
  84. package/dist/sdk/graph/assembly.d.ts +6 -1
  85. package/dist/sdk/graph/assembly.js +16 -22
  86. package/dist/sdk/graph/governance-contracts.d.ts +1 -1
  87. package/dist/sdk/graph/governance-contracts.js +8 -2
  88. package/dist/sdk/graph/governance.js +46 -2
  89. package/dist/sdk/graph/hierarchy-integrity.d.ts +94 -0
  90. package/dist/sdk/graph/hierarchy-integrity.js +311 -0
  91. package/dist/sdk/graph/index.d.ts +2 -1
  92. package/dist/sdk/graph/index.js +3 -2
  93. package/dist/sdk/graph/remediation.js +32 -2
  94. package/dist/sdk/graph/run.d.ts +31 -2
  95. package/dist/sdk/graph/run.js +80 -31
  96. package/dist/sdk/graph/workspace-relationship-kind-registry.d.ts +8 -0
  97. package/dist/sdk/graph/workspace-relationship-kind-registry.js +28 -0
  98. package/dist/sdk/index.d.ts +2 -2
  99. package/dist/sdk/index.js +3 -3
  100. package/dist/sdk/item-children.js +21 -8
  101. package/dist/sdk/lifecycle/create.js +125 -96
  102. package/dist/sdk/lifecycle/hierarchy-mutation-lock.d.ts +15 -0
  103. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +25 -0
  104. package/dist/sdk/lifecycle/update.d.ts +2 -0
  105. package/dist/sdk/lifecycle/update.js +171 -83
  106. package/dist/sdk/query/complete-list.d.ts +3 -3
  107. package/dist/sdk/query/complete-list.js +46 -3
  108. package/dist/sdk/query/list.d.ts +4 -3
  109. package/dist/sdk/query/list.js +89 -49
  110. package/dist/sdk/read-output-contracts.d.ts +5 -1
  111. package/dist/sdk/read-output-contracts.js +87 -22
  112. package/dist/sdk/relationship-context.js +3 -4
  113. package/dist/sdk/relationships.js +17 -10
  114. package/dist/sdk/runtime.d.ts +3 -2
  115. package/dist/sdk/runtime.js +3 -2
  116. package/dist/sdk/test/batch.js +13 -5
  117. package/dist/sdk/test/execution.js +10 -2
  118. package/dist/types.d.ts +11 -0
  119. package/dist/types.js +2 -2
  120. package/docs/AGENT_UX_CONTRACTS.md +20 -4
  121. package/docs/COMMANDS.md +29 -14
  122. package/docs/DEPENDENCY_KIND_CONTRACT.md +31 -3
  123. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +98 -0
  124. package/docs/EXTENSIONS.md +2 -1
  125. package/docs/README.md +1 -0
  126. package/docs/READ_OUTPUT_CONTRACTS.md +9 -2
  127. package/docs/RELATIONSHIP_GRAPH.md +6 -3
  128. package/docs/TESTING.md +15 -0
  129. package/marketplace.json +2 -2
  130. package/package.json +1 -1
  131. package/packages/pm-beads/package.json +1 -1
  132. package/packages/pm-calendar/package.json +1 -1
  133. package/packages/pm-command-kit/package.json +1 -1
  134. package/packages/pm-digital-twin/package.json +1 -1
  135. package/packages/pm-governance-audit/package.json +1 -1
  136. package/packages/pm-guide-shell/package.json +1 -1
  137. package/packages/pm-kanban/package.json +1 -1
  138. package/packages/pm-lifecycle-hooks/package.json +1 -1
  139. package/packages/pm-linked-test-adapters/package.json +1 -1
  140. package/packages/pm-search-advanced/package.json +1 -1
  141. package/packages/pm-templates/package.json +1 -1
  142. package/packages/pm-todos/package.json +1 -1
  143. package/packages/pm-vcs/package.json +1 -1
  144. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  145. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  146. package/sdk/public-surface.json +593 -35
  147. package/dist/cli-bundle/chunks/chunk-2MA6ZQVZ.js +0 -197
  148. package/dist/cli-bundle/chunks/chunk-7VHZS727.js +0 -5
  149. package/dist/cli-bundle/chunks/chunk-OCLPLFAY.js +0 -35
  150. package/dist/cli-bundle/chunks/chunk-S4IRYKBU.js +0 -13
  151. package/dist/cli-bundle/focused-chunks/chunk-7WZRLCYF.js +0 -50
  152. package/dist/cli-bundle/focused-chunks/chunk-EEFKYMDR.js +0 -16
  153. package/dist/cli-bundle/focused-chunks/chunk-F2A56DHV.js +0 -8
  154. package/dist/cli-bundle/focused-chunks/chunk-FV5ACOK7.js +0 -2
  155. package/dist/cli-bundle/focused-chunks/chunk-JEAVFOWM.js +0 -2
  156. package/dist/cli-bundle/focused-chunks/chunk-NJ63LOP6.js +0 -155
  157. package/dist/cli-bundle/focused-chunks/chunk-NXRTQ7HI.js +0 -2
  158. package/dist/cli-bundle/focused-chunks/chunk-TJ7EMJ46.js +0 -4
@@ -4,7 +4,7 @@
4
4
  * Implements the pm test all command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="aeb0a1a7-bc73-5c56-bbed-9472c651b5f6")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="bb2758a5-a5c1-5f6e-be42-0e173fe16fe3")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
9
  import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
10
10
  import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
@@ -15,7 +15,7 @@ import { EXIT_CODE } from "../../core/shared/constants.js";
15
15
  import { PmCliError } from "../../core/shared/errors.js";
16
16
  import { nowIso } from "../../core/shared/time.js";
17
17
  import { listAllItemMetadataLight } from "../../core/store/item-store.js";
18
- import { resolveGlobalPmRoot, resolvePmRoot, } from "../../core/store/paths.js";
18
+ import { resolveGlobalPmRoot, resolvePmRoot } from "../../core/store/paths.js";
19
19
  import { readSettings } from "../../core/store/settings.js";
20
20
  import { appendTrackedTestRunSummary } from "../../core/test/item-test-run-tracking.js";
21
21
  import { resolveAuthor } from "../../core/shared/author.js";
@@ -245,7 +245,7 @@ const runTestAllItem = async (entry, context) => {
245
245
  });
246
246
  const summary = countStatuses(runResults);
247
247
  const failureCategories = countFailureCategories(runResults);
248
- const trackingWarnings = await appendTestAllItemTracking(entry, summary, context);
248
+ const trackingWarnings = await appendTestAllItemTracking(entry, summary, runResults, context);
249
249
  return {
250
250
  passed: summary.passed,
251
251
  failed: summary.failed,
@@ -273,7 +273,7 @@ const trackedRunFailed = (summary, options) => [
273
273
  ].includes(true);
274
274
  /** Projects true flags while keeping false values absent from persisted rows. */
275
275
  const optionalTrue = (value) => value ? true : undefined;
276
- const appendTestAllItemTracking = async (entry, summary, context) => {
276
+ const appendTestAllItemTracking = async (entry, summary, runResults, context) => {
277
277
  if (!context.trackingEnabled) {
278
278
  return [];
279
279
  }
@@ -300,6 +300,14 @@ const appendTestAllItemTracking = async (entry, summary, context) => {
300
300
  items: 1,
301
301
  linked_tests: entry.tests.length,
302
302
  fail_on_skipped_triggered: optionalTrue(context.options.failOnSkipped === true && summary.skipped > 0),
303
+ executions: runResults
304
+ .filter((result) => result.command?.trim())
305
+ .slice(0, 32)
306
+ .map((result) => ({
307
+ command: result.command.trim(),
308
+ requested_pm_context_mode: result.execution_context?.requested_pm_context_mode,
309
+ pm_context_mode: result.execution_context?.pm_context_mode,
310
+ })),
303
311
  },
304
312
  });
305
313
  }
@@ -487,4 +495,4 @@ export const _testOnlyTestAll = {
487
495
  formatTrackingError,
488
496
  };
489
497
  //# sourceMappingURL=batch.js.map
490
- //# debugId=aeb0a1a7-bc73-5c56-bbed-9472c651b5f6
498
+ //# debugId=bb2758a5-a5c1-5f6e-be42-0e173fe16fe3
@@ -4,7 +4,7 @@
4
4
  * Implements the pm test command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2354c553-3a81-59d8-9c0a-3d19cd3cedd2")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5fe0ee3e-9590-56fc-b238-e56ff1970e52")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
9
  import { spawn } from "node:child_process";
10
10
  import { cp, mkdir, mkdtemp, open, readdir, rm } from "node:fs/promises";
@@ -1791,6 +1791,14 @@ function buildTrackedTestRunSummary(params) {
1791
1791
  skipped: summary.skipped,
1792
1792
  fail_on_skipped_triggered: params.failOnSkippedTriggered ? true : undefined,
1793
1793
  measurements: measurements.length > 0 ? measurements : undefined,
1794
+ executions: params.runResults
1795
+ .filter((result) => result.command?.trim())
1796
+ .slice(0, 32)
1797
+ .map((result) => ({
1798
+ command: result.command.trim(),
1799
+ requested_pm_context_mode: result.execution_context?.requested_pm_context_mode,
1800
+ pm_context_mode: result.execution_context?.pm_context_mode,
1801
+ })),
1794
1802
  };
1795
1803
  }
1796
1804
  async function recordTestRunSummary(params) {
@@ -1964,4 +1972,4 @@ export const _testOnlyTestCommand = {
1964
1972
  summarizeRunResultStatuses,
1965
1973
  };
1966
1974
  //# sourceMappingURL=execution.js.map
1967
- //# debugId=2354c553-3a81-59d8-9c0a-3d19cd3cedd2
1975
+ //# debugId=5fe0ee3e-9590-56fc-b238-e56ff1970e52
package/dist/types.d.ts CHANGED
@@ -558,6 +558,15 @@ export interface TestRunMeasurement {
558
558
  /** ISO 8601 timestamp binding the measurement to its producing run. */
559
559
  recorded_at: string;
560
560
  }
561
+ /** Bounded command and tracker-context provenance for one linked-test execution. */
562
+ export interface ItemTestRunExecution {
563
+ /** Exact linked command selected for execution. */
564
+ command: string;
565
+ /** Context mode requested before linked-test overrides or auto-remediation. */
566
+ requested_pm_context_mode?: "schema" | "tracker" | "auto";
567
+ /** Effective context mode used by the linked command. */
568
+ pm_context_mode?: "schema" | "tracker" | "auto";
569
+ }
561
570
  /** Documents the item test run summary payload exchanged by command, SDK, and package integrations. */
562
571
  export interface ItemTestRunSummary {
563
572
  /** Executes the id operation through the package runtime. */
@@ -590,6 +599,8 @@ export interface ItemTestRunSummary {
590
599
  fail_on_skipped_triggered?: boolean;
591
600
  /** Bounded, deterministic quantitative evidence produced by this run. */
592
601
  measurements?: TestRunMeasurement[];
602
+ /** Commands and effective tracker contexts bound to this recorded run. */
603
+ executions?: ItemTestRunExecution[];
593
604
  }
594
605
  /** Documents the item metadata payload exchanged by command, SDK, and package integrations. */
595
606
  export interface ItemMetadata {
package/dist/types.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /** Supported values accepted by the builtin item type contract. */
7
7
 
8
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f6ab5bae-53b3-5feb-b89f-46e64afe7058")}catch(e){}}();
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="13c65470-8f5f-59ca-acb5-50c926c68870")}catch(e){}}();
9
9
  export const BUILTIN_ITEM_TYPE_VALUES = [
10
10
  "Epic",
11
11
  "Feature",
@@ -243,4 +243,4 @@ export const CONTEXT_SECTION_VALUES = [
243
243
  "tests",
244
244
  ];
245
245
  //# sourceMappingURL=types.js.map
246
- //# debugId=f6ab5bae-53b3-5feb-b89f-46e64afe7058
246
+ //# debugId=13c65470-8f5f-59ca-acb5-50c926c68870
@@ -1,6 +1,6 @@
1
1
  # Agent UX Contracts
2
2
 
3
- Tracker references: [pm-v1yo](../.agents/pm/issues/pm-v1yo.toon), [pm-i6pi](../.agents/pm/issues/pm-i6pi.toon), [pm-um4g](../.agents/pm/issues/pm-um4g.toon), [pm-tmhs](../.agents/pm/issues/pm-tmhs.toon), [pm-6m1i](../.agents/pm/issues/pm-6m1i.toon), [pm-cj9v](../.agents/pm/issues/pm-cj9v.toon), [pm-yp56](../.agents/pm/issues/pm-yp56.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), and [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon).
3
+ Tracker references: [pm-v1yo](../.agents/pm/issues/pm-v1yo.toon), [pm-i6pi](../.agents/pm/issues/pm-i6pi.toon), [pm-um4g](../.agents/pm/issues/pm-um4g.toon), [pm-tmhs](../.agents/pm/issues/pm-tmhs.toon), [pm-6m1i](../.agents/pm/issues/pm-6m1i.toon), [pm-cj9v](../.agents/pm/issues/pm-cj9v.toon), [pm-yp56](../.agents/pm/issues/pm-yp56.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon), [pm-rggtvd](../.agents/pm/issues/pm-rggtvd.toon), and [pm-vk7zek](../.agents/pm/issues/pm-vk7zek.toon).
4
4
 
5
5
  These contracts keep common agent loops deterministic, token-efficient, and recoverable. Runtime contracts and `--help --json` remain the exact source for available flags.
6
6
 
@@ -13,9 +13,25 @@ The public SDK exports `collectNewOrderingCycleWarnings(beforeItems, afterItems,
13
13
  Dependency removal is lossless. `--dep-remove` rejects the same malformed
14
14
  shorthand as `--dep`, and a selector that matches nothing returns the typed
15
15
  `dependency_remove_no_match` refusal instead of a successful no-op. Exact
16
- duplicate rows can be normalized without delete-then-add risk by re-adding the
17
- same `id`, `kind`, and `source_kind`; the mutation keeps one canonical row and
18
- never removes the logical edge.
16
+ rows can be retired by selecting `id`, `kind` (or its input-only `type` alias),
17
+ `source_kind`, `author`, and `created_at`; omitted coordinates intentionally broaden the match. Exact
18
+ duplicate rows can still be normalized without delete-then-add risk by
19
+ re-adding the same identity; the mutation keeps one canonical row and never
20
+ removes the logical edge. Identity comparison includes normalized `id`, `kind`,
21
+ `source_kind`, `author`, and creation instant, preserving provenance-distinct
22
+ siblings.
23
+
24
+ Hierarchy mutations are stricter than ordering advisories. `pm create` and
25
+ `pm update` refuse a new cycle, registry cardinality breach, or contradictory
26
+ scalar/dependency parent before writing. The structured refusal names the
27
+ changed holder plus the cycle members or competing parents. Existing legacy
28
+ debt remains mutable only toward a cleaner state, so repair does not require a
29
+ global bypass. Read paths canonicalize every registry-declared hierarchy kind;
30
+ an item cannot disappear from `pm list --parent` or `pm get --tree` merely
31
+ because an integration used a dependency row instead of the scalar field.
32
+ `pm update-many` applies the same hierarchy guard independently to each matched
33
+ item: one refused row is reported as failed while other rows may still commit,
34
+ so a bulk hierarchy mutation is not atomic across the complete match set.
19
35
 
20
36
  `pm graph audit` uses two explicit units:
21
37
 
package/docs/COMMANDS.md CHANGED
@@ -6,6 +6,8 @@ Tracked implementation updates: [pm-52eh](../.agents/pm/features/pm-52eh.toon),
6
6
 
7
7
  Workspace-integrity contracts are tracked by [pm-22rzjp](../.agents/pm/issues/pm-22rzjp.toon), [pm-76fkpp](../.agents/pm/issues/pm-76fkpp.toon), [pm-igdvfq](../.agents/pm/issues/pm-igdvfq.toon), [pm-643e0k](../.agents/pm/issues/pm-643e0k.toon), and [pm-larv4r](../.agents/pm/issues/pm-larv4r.toon).
8
8
 
9
+ Create-safe init prefix normalization is tracked by [pm-gh1073](../.agents/pm/issues/pm-gh1073.toon).
10
+
9
11
  ```bash
10
12
  pm <command> --help
11
13
  pm <command> --help --json
@@ -49,21 +51,21 @@ JSON ceiling; TOON uses the smaller default agent ceiling.
49
51
 
50
52
  ## Command Families
51
53
 
52
- | Family | Commands | Purpose |
53
- | ------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
54
- | Bootstrap | `init`, `config`, `health`, `telemetry` | create and inspect tracker setup |
54
+ | Family | Commands | Purpose |
55
+ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
56
+ | Bootstrap | `init`, `config`, `health`, `telemetry` | create and inspect tracker setup |
55
57
  | Lifecycle | `create`, `copy`, `focus`, `claim`, `update`, `item reopen`, `append`, `close`, `release`, `delete`, `start-task`, `pause-task`, `close-task` | mutate item state, including terminal-work recurrence without duplicate creation |
56
- | Bulk | `item mutate`, `item complete`, `update-many`, `close-many` | atomically commit heterogeneous SDK mutation batches or evidence-backed completion, or apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
57
- | Scheduling | `meet`, `event`, `remind` | low-friction Meeting/Event/Reminder creation |
58
- | Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize` | agent-optimized living plans with ordered steps, evidence, decisions, validation, and materialization |
59
- | Links | `files`, `docs`, `test`, `deps` | connect items to artifacts, tests, and relationships |
60
- | Verification | `test`, `test-all`, `test-runs`†, `validate`, `gc` | run linked tests and repository checks |
61
- | History | `history`, `history-compact`, `history-redact`, `history-repair`, `activity`, `restore`, `stats` | inspect, compact, redact, re-anchor, and recover item state |
62
- | Schema | `schema add/remove-*` / `rename-type` / `rename-field` / `remap-status` / `apply-preset` | manage config-driven types, statuses, and fields; losslessly migrate existing items when definitions evolve; adopt presets or infer types |
63
- | Profiles | `profile list` / `show` / `apply` / `lint` | compose item types, statuses, fields, workflows, config, templates, and recommended packages into archetype bundles (agile/ops/research); `apply` stages every dimension idempotently; `lint` reports author-time consistency findings without writing |
64
- | Calendar | `calendar`, `cal` | project deadlines, reminders, and events |
65
- | Packages | `install`, `upgrade`, `package`, `packages`, `extension`, package/extension command groups | install, upgrade, manage, and run package-backed extension commands |
66
- | Machines | `contracts`, `help`, optional `guide`/`completion` | command contracts plus optional guide-shell docs routing and shell helpers |
58
+ | Bulk | `item mutate`, `item complete`, `update-many`, `close-many` | atomically commit heterogeneous SDK mutation batches or evidence-backed completion, or apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
59
+ | Scheduling | `meet`, `event`, `remind` | low-friction Meeting/Event/Reminder creation |
60
+ | Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize` | agent-optimized living plans with ordered steps, evidence, decisions, validation, and materialization |
61
+ | Links | `files`, `docs`, `test`, `deps` | connect items to artifacts, tests, and relationships |
62
+ | Verification | `test`, `test-all`, `test-runs`†, `validate`, `gc` | run linked tests and repository checks |
63
+ | History | `history`, `history-compact`, `history-redact`, `history-repair`, `activity`, `restore`, `stats` | inspect, compact, redact, re-anchor, and recover item state |
64
+ | Schema | `schema add/remove-*` / `rename-type` / `rename-field` / `remap-status` / `apply-preset` | manage config-driven types, statuses, and fields; losslessly migrate existing items when definitions evolve; adopt presets or infer types |
65
+ | Profiles | `profile list` / `show` / `apply` / `lint` | compose item types, statuses, fields, workflows, config, templates, and recommended packages into archetype bundles (agile/ops/research); `apply` stages every dimension idempotently; `lint` reports author-time consistency findings without writing |
66
+ | Calendar | `calendar`, `cal` | project deadlines, reminders, and events |
67
+ | Packages | `install`, `upgrade`, `package`, `packages`, `extension`, package/extension command groups | install, upgrade, manage, and run package-backed extension commands |
68
+ | Machines | `contracts`, `help`, optional `guide`/`completion` | command contracts plus optional guide-shell docs routing and shell helpers |
67
69
 
68
70
  `†` `test-runs` subcommands are provided by the optional `linked-test-adapters` package (`pm install linked-test-adapters --project`).
69
71
 
@@ -89,6 +91,15 @@ ID prefix without relying on the legacy positional form. `pm init ops` remains
89
91
  compatible, and supplying both forms is accepted only when they normalize to the
90
92
  same prefix; conflicting values fail with `init_id_prefix_conflict` instead of
91
93
  silently choosing one.
94
+ Prefixes normalize through the same primitive used by item creation: letters
95
+ become lowercase, each run of whitespace or punctuation becomes one `-`, edge
96
+ separators are removed, and exactly one trailing `-` is stored. For example,
97
+ `"Release Candidate"` persists as `release-candidate-`; an input with no ASCII
98
+ letters or digits falls back to `pm-`. Path-like values remain invalid tracker
99
+ prefixes when passed through `--id-prefix`; a path-like positional value remains
100
+ the advanced tracker-root target described below. To repair an older unsafe
101
+ value, rerun init with a safe prefix and explicit replacement intent, for example
102
+ `pm init --id-prefix "release candidate" --force --defaults`.
92
103
  Use `pm init --workspace <dir>` when `<dir>` is a project root; it creates `<dir>/.agents/pm`. A path-like positional remains the advanced tracker-root form and writes tracker files directly at that path. Both explicit target forms return `target.mode`, `target.tracker_root`, and tracker-scoped executable `next_steps` so agents can run the suggestions from any working directory.
93
104
  Implicit init discovery also reports whether the selected tracker is local or was found in an ancestor. If `pm init <name>` would change an ancestor tracker, the refusal names both directories and gives the safe current-directory retry: `pm init <name> --pm-path "$PWD/.agents/pm" --defaults`.
94
105
  `pm init --agent-guidance ask` is the default behavior: prompt in TTY only when AGENTS/CLAUDE guidance is missing and no decline is recorded.
@@ -163,6 +174,10 @@ Use `duplicates --status all` for a true whole-history duplicate check. The
163
174
  result echoes `filters.statuses: null` for the unrestricted corpus; named or
164
175
  custom statuses are normalized through the runtime status registry and an
165
176
  unknown status fails instead of returning a false-clean result.
177
+ As a read-only structured surface, `duplicates` accepts the universal output
178
+ controls, including `--output-format json`, `--lean`, projection/amount
179
+ controls, and token accounting, while its default TOON output remains bounded.
180
+ Tracked by [pm-gh1076](../.agents/pm/issues/pm-gh1076.toon).
166
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. Standard/deep reads expose a normalized `schedule` facet (`deadline`, `start_at`, `end_at`, `location`, reminders, and events) when scheduling metadata exists. Container-oriented built-ins (Epic, Feature, Milestone, and Plan) plus custom types automatically expose type-agnostic child counts and continuation metadata. Standard depth keeps that rollup counts-only; `--depth deep|full` or an explicit `--fields id,children` request adds the deterministic bounded child sample. Built-in leaf reads avoid a workspace scan unless children are explicitly requested. `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.
167
182
 
168
183
  When the strongest duplicate match is terminal because the same work recurred,
@@ -1,6 +1,6 @@
1
1
  # Dependency-kind contract
2
2
 
3
- Tracker: [pm-4020c5](../.agents/pm/issues/pm-4020c5.toon), [pm-jkbqt8](../.agents/pm/issues/pm-jkbqt8.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), and [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon).
3
+ Tracker: [pm-4020c5](../.agents/pm/issues/pm-4020c5.toon), [pm-jkbqt8](../.agents/pm/issues/pm-jkbqt8.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon), [pm-rggtvd](../.agents/pm/issues/pm-rggtvd.toon), and [pm-vk7zek](../.agents/pm/issues/pm-vk7zek.toon).
4
4
 
5
5
  Dependency rows have one canonical stored spelling per relationship meaning. Command inputs remain compatibility-friendly: hyphens normalize to underscores and the aliases below are accepted, but `pm create` and `pm update` persist the canonical kind. Existing historical rows are never rewritten implicitly.
6
6
 
@@ -15,9 +15,17 @@ Dependency rows have one canonical stored spelling per relationship meaning. Com
15
15
 
16
16
  The SDK relationship registry is authoritative. `canonicalizeRelationshipKind()` rejects unknown spellings, while `resolveCanonicalRelationshipKind()` supports validation flows that need an undefined result. `pm contracts` publishes `relationship_kind_contracts` with canonical names, aliases, inverses, and ordering/hierarchy semantics.
17
17
 
18
+ Extension kinds may opt into both ordering and hierarchy semantics. Unless they
19
+ declare an explicit `traversal`, ordering is the primary traversal and context
20
+ role family; hierarchy direction and cardinality remain enforceable integrity
21
+ constraints. This ordering-first precedence is shared by registry snapshots and
22
+ direct-edge context explanations.
23
+
18
24
  Dependency additions and removals share the same lossless input grammar. A
19
- bare value is an item id; structured input uses `id=<id>` plus an optional
20
- canonical `kind`/`type` and `source_kind`. Punctuation-shaped shorthand such as
25
+ bare value is an item id; structured removal input uses `id=<id>` plus optional
26
+ canonical `kind` (with `type` accepted only as an input alias), `source_kind`, `author`, and ISO `created_at`
27
+ selectors. Supplying all stored coordinates retires exactly one dependency row
28
+ without deleting siblings that share an id and kind. Punctuation-shaped shorthand such as
21
29
  `OTHER,related` is rejected with `dependency_flag_value_invalid` on both
22
30
  `--dep` and `--dep-remove`, before prefix normalization can turn it into a
23
31
  dangling id. A removal selector that matches no stored row fails with
@@ -25,6 +33,26 @@ dangling id. A removal selector that matches no stored row fails with
25
33
  available identities. Re-adding a stored dependency identity is idempotent; if
26
34
  legacy storage contains that exact identity more than once, the same mutation
27
35
  collapses the touched copies to one without creating an edge-absence window.
36
+ The stored identity includes normalized `id`, `kind`, `source_kind`, `author`,
37
+ and creation instant, so provenance-distinct sibling rows remain independent.
38
+
39
+ ## Hierarchy integrity
40
+
41
+ The registry's `hierarchy`, `hierarchyDirection`, `outgoing`, and `incoming`
42
+ fields are executable contracts. Scalar `parent` metadata and every registered
43
+ hierarchy dependency spelling normalize into the same parent-to-child relation.
44
+ That normalized relation powers `pm list --parent`, list/get tree projections,
45
+ child rollups, graph traversal, graph analysis, graph audit, validate, and
46
+ health. Extensions therefore gain hierarchy behavior by registering semantics;
47
+ consumers do not hard-code kind names.
48
+
49
+ Create and update transactions reject a newly introduced hierarchy cycle,
50
+ registry cardinality violation, or scalar/dependency direction contradiction
51
+ before persistence. Existing debt remains readable and repairable. Active debt
52
+ is gate-failing in graph governance and health; defects confined to terminal
53
+ items are labeled legacy and are never mutated automatically. `pm validate`
54
+ reports cycle, cardinality, and parent-divergence counts and exact bounded rows,
55
+ while `pm graph analyze` exposes a compact `hierarchy` summary.
28
56
 
29
57
  `recurs_from` has no alias: a later occurrence points to an earlier occurrence.
30
58
  It is persistent after both items become terminal and carries temporal identity,
@@ -0,0 +1,98 @@
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
+ The deterministic ladder is:
62
+
63
+ 1. full diagnostic;
64
+ 2. omit explanation;
65
+ 3. limit diagnostic collections;
66
+ 4. compact recovery to actionable keys;
67
+ 5. retain the action-only envelope.
68
+
69
+ Human diagnostics lead with `What is required` and next steps before explaining
70
+ what happened. If their declared ceiling binds, the compact text still begins
71
+ with the required action and points to structured JSON for the bounded recovery
72
+ envelope.
73
+
74
+ ## Executable Assurance
75
+
76
+ `pnpm quality:recovery-closure` builds the current CLI and replays 22 refusal
77
+ contracts in isolated trackers. Ten representative, high-frequency failure
78
+ paths are also ratcheted by
79
+ `scripts/release/diagnostic-output-baseline.json`. The gate requires every row
80
+ to remain within the SDK-declared JSON ceiling and retain a mechanically
81
+ actionable correction. It reports the aggregate original and emitted token
82
+ estimates without claiming a reduction when no degradation was required.
83
+
84
+ The baseline is a coverage ratchet, not permission to weaken a ceiling. Its
85
+ negative control requires a missing baseline probe to fail. The existing
86
+ refusal-closure negative controls independently prove that incomplete domains,
87
+ broken retries, and malformed recovery envelopes remain blocking findings.
88
+
89
+ Run the focused proof with:
90
+
91
+ ```bash
92
+ pnpm build
93
+ node scripts/release/refusal-closure-gate.mjs
94
+ node scripts/run-tests.mjs test -- \
95
+ tests/unit/sdk/agent-output-contracts.spec.ts \
96
+ tests/unit/cli/error-guidance.spec.ts \
97
+ tests/unit/scripts/refusal-closure-gate.spec.ts
98
+ ```
@@ -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.
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), and [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.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
 
@@ -179,6 +179,13 @@ key. Health retains at most 100 warning rows and reports `warning_count`,
179
179
  projection unless `--full` is explicit, keeping the failing check identities
180
180
  and warning codes inside the ordinary budget.
181
181
 
182
+ Failure transports use the companion
183
+ [Diagnostic Output Contracts](DIAGNOSTIC_OUTPUT_CONTRACTS.md). Those contracts
184
+ bind errors, warnings, validation summaries, and recovery bundles independently
185
+ from successful command results. Corrective actions precede explanation and
186
+ survive every degradation stage, while untruncated JSON avoids a per-call
187
+ receipt tax.
188
+
182
189
  ## SDK and Package Usage
183
190
 
184
191
  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 {
package/docs/TESTING.md CHANGED
@@ -366,6 +366,18 @@ 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 22 refusal contracts and ratchets ten representative failure
376
+ paths against `PM_DIAGNOSTIC_OUTPUT_BUDGET_CONTRACTS`. Every diagnostic must fit
377
+ its declared JSON ceiling and preserve a mechanically actionable correction;
378
+ the missing-probe negative control proves that the diagnostic corpus cannot
379
+ silently shrink.
380
+
369
381
  The gate derives every supported harness, model, session, and provenance
370
382
  environment key from the SDK-owned harness descriptor registry. It deletes
371
383
  those host inputs before each fixture invocation, then supplies only the
@@ -480,6 +492,9 @@ pm test <item-id> --metric-below coverage=100 --metric-diff p95_latency
480
492
 
481
493
  Measurements are stored on the producing `test_runs` row, retained with the
482
494
  bounded run history, and exposed consistently by CLI, SDK, MCP, and contracts.
495
+ Each recorded row also keeps a bounded `executions` list with the exact linked
496
+ command plus its requested and effective `pm_context_mode`, so tracker-backed
497
+ verification remains attributable after the transient process logs are gone.
483
498
 
484
499
  ## Linked-Test Assertions
485
500
 
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.22"
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.22",
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.22",
4
4
  "description": "Git-native project management CLI for humans and agents.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.10.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-beads",
3
- "version": "2026.8.21",
3
+ "version": "2026.8.22",
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.22",
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.22",
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.22",
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.22",
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.22",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm package for guide and shell completion workflows.",