@unbrained/pm-cli 2026.8.6 → 2026.8.7

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 (209) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +30 -0
  3. package/dist/cli/main.js +4 -2
  4. package/dist/cli/register-operations.js +11 -2
  5. package/dist/cli/stats-analytics-json.d.ts +9 -0
  6. package/dist/cli/stats-analytics-json.js +69 -0
  7. package/dist/cli-bundle/bundle-manifest.json +397 -397
  8. package/dist/cli-bundle/chunks/append-7BXBFDGD.js +2 -0
  9. package/dist/cli-bundle/chunks/{chunk-TPKDJ5WL.js → chunk-2AXF3VSK.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-R6RKEYYW.js → chunk-2XS43CCV.js} +2 -2
  11. package/dist/cli-bundle/chunks/{chunk-T45OHXDW.js → chunk-3A6KWB72.js} +2 -2
  12. package/dist/cli-bundle/chunks/chunk-3ISTDB42.js +8 -0
  13. package/dist/cli-bundle/chunks/{chunk-SXECIECW.js → chunk-4MTI7XOV.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-MCS73BKB.js → chunk-6BX5UDCN.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-A3XQ7VPU.js → chunk-6QPO7KLR.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-BP6EMEDP.js → chunk-7MXHZHSQ.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-GU3TSEHD.js → chunk-7ZPMJW4U.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-343QETLI.js → chunk-AGYNSNCI.js} +2 -2
  19. package/dist/cli-bundle/chunks/chunk-B4H7FEFH.js +5 -0
  20. package/dist/cli-bundle/chunks/{chunk-CA3BURYF.js → chunk-B4KLBBMN.js} +2 -2
  21. package/dist/cli-bundle/chunks/{chunk-3ZJRFYY2.js → chunk-CALJHNBL.js} +12 -12
  22. package/dist/cli-bundle/chunks/{chunk-M357ZCOR.js → chunk-CFIGP5LY.js} +2 -2
  23. package/dist/cli-bundle/chunks/{chunk-SVV3DQES.js → chunk-CS6MRHG7.js} +2 -2
  24. package/dist/cli-bundle/chunks/{chunk-DWOAOZHZ.js → chunk-CUGNQQKH.js} +2 -2
  25. package/dist/cli-bundle/chunks/chunk-D4FPS43D.js +164 -0
  26. package/dist/cli-bundle/chunks/{chunk-L6LGKJX3.js → chunk-H5Y5YE6A.js} +2 -2
  27. package/dist/cli-bundle/chunks/{chunk-5PBP2ZP3.js → chunk-H5Y6UV6E.js} +2 -2
  28. package/dist/cli-bundle/chunks/{chunk-QJ7C3JIW.js → chunk-H7KGWPDF.js} +2 -2
  29. package/dist/cli-bundle/chunks/{chunk-D7I3TUGV.js → chunk-HFSD77TQ.js} +2 -2
  30. package/dist/cli-bundle/chunks/{chunk-AOBDLU4T.js → chunk-HX2GTA6L.js} +2 -2
  31. package/dist/cli-bundle/chunks/{chunk-4AVFKHHC.js → chunk-J2IEKAVR.js} +2 -2
  32. package/dist/cli-bundle/chunks/{chunk-OXY3SJ3N.js → chunk-K44PYFXH.js} +2 -2
  33. package/dist/cli-bundle/chunks/{chunk-M4VEE3FK.js → chunk-K4KGEEBT.js} +2 -2
  34. package/dist/cli-bundle/chunks/chunk-KFLK5TRH.js +21 -0
  35. package/dist/cli-bundle/chunks/{chunk-FDBRXV25.js → chunk-KL6IEBV2.js} +2 -2
  36. package/dist/cli-bundle/chunks/{chunk-JQ4NZ5EB.js → chunk-KWQZDZSS.js} +2 -2
  37. package/dist/cli-bundle/chunks/{chunk-UVVXHGYS.js → chunk-KZ4X3DGU.js} +2 -2
  38. package/dist/cli-bundle/chunks/chunk-LD77HJMQ.js +13 -0
  39. package/dist/cli-bundle/chunks/{chunk-AYRUGRNS.js → chunk-ME2JJ4LA.js} +2 -2
  40. package/dist/cli-bundle/chunks/chunk-NFLJ3FHD.js +2 -0
  41. package/dist/cli-bundle/chunks/{chunk-MDTH7SAE.js → chunk-NG6OXIBR.js} +8 -8
  42. package/dist/cli-bundle/chunks/{chunk-R6LSRGPS.js → chunk-NYIGHWQY.js} +2 -2
  43. package/dist/cli-bundle/chunks/{chunk-3KFVGGRE.js → chunk-NZ75GNSA.js} +2 -2
  44. package/dist/cli-bundle/chunks/{chunk-Q3VOP62W.js → chunk-PCJWJNC2.js} +2 -2
  45. package/dist/cli-bundle/chunks/{chunk-C3YABSJK.js → chunk-PD3225AM.js} +2 -2
  46. package/dist/cli-bundle/chunks/{chunk-JFZIS6JF.js → chunk-PDEGKG7P.js} +2 -2
  47. package/dist/cli-bundle/chunks/chunk-PIE5HBNA.js +2 -0
  48. package/dist/cli-bundle/chunks/{chunk-SD3YXU2U.js → chunk-PW2H7YJR.js} +20 -20
  49. package/dist/cli-bundle/chunks/{chunk-PECV7L5T.js → chunk-TPKN3S7S.js} +2 -2
  50. package/dist/cli-bundle/chunks/{chunk-F4NREH3G.js → chunk-TPXAXTCO.js} +2 -2
  51. package/dist/cli-bundle/chunks/chunk-UFWUJO4V.js +2 -0
  52. package/dist/cli-bundle/chunks/{chunk-WSI5KZQJ.js → chunk-UQLZQVFW.js} +2 -2
  53. package/dist/cli-bundle/chunks/{chunk-4OVGQW22.js → chunk-VT3Z5G7D.js} +2 -2
  54. package/dist/cli-bundle/chunks/{chunk-RUAU5OSH.js → chunk-WOD3WWUN.js} +2 -2
  55. package/dist/cli-bundle/chunks/{chunk-DQGJ2RWT.js → chunk-WSJEIGJF.js} +2 -2
  56. package/dist/cli-bundle/chunks/{chunk-RAFUN7IX.js → chunk-WYNUU7ZW.js} +49 -46
  57. package/dist/cli-bundle/chunks/{chunk-5ZKQPA44.js → chunk-YGPNCCXZ.js} +2 -2
  58. package/dist/cli-bundle/chunks/close-CMY3BAUG.js +2 -0
  59. package/dist/cli-bundle/chunks/close-many-SA4XZCTK.js +2 -0
  60. package/dist/cli-bundle/chunks/comments-EZ556ZD3.js +2 -0
  61. package/dist/cli-bundle/chunks/copy-ZSGPA52X.js +2 -0
  62. package/dist/cli-bundle/chunks/{create-TG67IVFI.js → create-I5DVV4YG.js} +2 -2
  63. package/dist/cli-bundle/chunks/delete-RL3JACSW.js +2 -0
  64. package/dist/cli-bundle/chunks/{deps-AJUGP2OH.js → deps-S7UBCECS.js} +2 -2
  65. package/dist/cli-bundle/chunks/{docs-QOCLDRKJ.js → docs-ZZNVBBYO.js} +2 -2
  66. package/dist/cli-bundle/chunks/{files-3ST5TY64.js → files-27C337VT.js} +2 -2
  67. package/dist/cli-bundle/chunks/focus-5Z2SG7LU.js +2 -0
  68. package/dist/cli-bundle/chunks/{history-compact-7BJFML4S.js → history-compact-HJQK67CZ.js} +2 -2
  69. package/dist/cli-bundle/chunks/{history-redact-WJN3HYXR.js → history-redact-PWC6PDWA.js} +2 -2
  70. package/dist/cli-bundle/chunks/{history-repair-XDNZUB7F.js → history-repair-N3CY4WBF.js} +2 -2
  71. package/dist/cli-bundle/chunks/{learnings-SZMUPVNA.js → learnings-4FH23XDT.js} +2 -2
  72. package/dist/cli-bundle/chunks/{profile-KL53JIAC.js → profile-5Y5XXH5N.js} +2 -2
  73. package/dist/cli-bundle/chunks/{register-list-query-QH7ONPKU.js → register-list-query-FJZCJ67O.js} +2 -2
  74. package/dist/cli-bundle/chunks/{register-mutation-OCRQNZK4.js → register-mutation-YGYPW3BL.js} +3 -3
  75. package/dist/cli-bundle/chunks/register-operations-WMDSUMQF.js +2 -0
  76. package/dist/cli-bundle/chunks/{register-setup-QWBQ6HBS.js → register-setup-DL7FFABC.js} +2 -2
  77. package/dist/cli-bundle/chunks/restore-6KYBV5BY.js +2 -0
  78. package/dist/cli-bundle/chunks/{schema-QJ27OTRV.js → schema-EQGKBYXJ.js} +2 -2
  79. package/dist/cli-bundle/chunks/update-QVTYOD6I.js +2 -0
  80. package/dist/cli-bundle/chunks/update-many-DJSBU525.js +2 -0
  81. package/dist/cli-bundle/focused-chunks/{chunk-MBBMTDD3.js → chunk-2ECLECMK.js} +3 -3
  82. package/dist/cli-bundle/focused-chunks/{chunk-CL3NB7VW.js → chunk-3K4XV2BF.js} +2 -2
  83. package/dist/cli-bundle/focused-chunks/{chunk-ME4XVOBJ.js → chunk-4EX25PXM.js} +2 -2
  84. package/dist/cli-bundle/focused-chunks/chunk-4VJQTS3P.js +2 -0
  85. package/dist/cli-bundle/focused-chunks/chunk-73JUDYXT.js +2 -0
  86. package/dist/cli-bundle/focused-chunks/{chunk-GSW2Y7VZ.js → chunk-CIXVQPB7.js} +2 -2
  87. package/dist/cli-bundle/focused-chunks/{chunk-7YTZ7A4E.js → chunk-DLTS3IHM.js} +2 -2
  88. package/dist/cli-bundle/focused-chunks/{chunk-YHDCGUIW.js → chunk-DQ6FKGL3.js} +10 -10
  89. package/dist/cli-bundle/focused-chunks/{chunk-YLPZHWX7.js → chunk-HNL6IFGS.js} +2 -2
  90. package/dist/cli-bundle/focused-chunks/chunk-JLG2C4EQ.js +2 -0
  91. package/dist/cli-bundle/focused-chunks/{chunk-6KDHXURF.js → chunk-MHMTKV5V.js} +2 -2
  92. package/dist/cli-bundle/focused-chunks/{chunk-GEYU23YS.js → chunk-MOTJFQ3F.js} +22 -22
  93. package/dist/cli-bundle/focused-chunks/{chunk-EYO4F74Z.js → chunk-NBJKQP4S.js} +2 -2
  94. package/dist/cli-bundle/focused-chunks/{chunk-XNVXIQ4B.js → chunk-QHRTT7WT.js} +2 -2
  95. package/dist/cli-bundle/focused-chunks/{chunk-27DK4A5O.js → chunk-R2LEMEV5.js} +2 -2
  96. package/dist/cli-bundle/focused-chunks/{chunk-4JC3AOGS.js → chunk-RPNYG5MO.js} +2 -2
  97. package/dist/cli-bundle/focused-chunks/{chunk-EAXXF2HW.js → chunk-RW5IYD4J.js} +2 -2
  98. package/dist/cli-bundle/focused-chunks/{chunk-TQMFQYXR.js → chunk-TIKDBG4D.js} +16 -16
  99. package/dist/cli-bundle/focused-chunks/{chunk-N7QN3NE6.js → chunk-VZFU2R4M.js} +2 -2
  100. package/dist/cli-bundle/focused-chunks/{chunk-GIERI4YU.js → chunk-YZEZAPJK.js} +2 -2
  101. package/dist/cli-bundle/focused-chunks/chunk-ZJIMJHDB.js +2 -0
  102. package/dist/cli-bundle/main.js +2 -2
  103. package/dist/cli-bundle/sdk-authoring.js +1 -1
  104. package/dist/cli-bundle/sdk-contracts.js +1 -1
  105. package/dist/cli-bundle/sdk-core.js +29 -28
  106. package/dist/cli-bundle/sdk-governance.js +1 -1
  107. package/dist/cli-bundle/sdk-graph.js +1 -1
  108. package/dist/cli-bundle/sdk-merge.js +1 -1
  109. package/dist/cli-bundle/sdk-query.js +1 -1
  110. package/dist/cli-bundle/sdk-runtime.js +1 -1
  111. package/dist/cli-bundle/sdk-testing.js +1 -1
  112. package/dist/cli-bundle/sdk.js +1 -1
  113. package/dist/core/extensions/reserved-host-flags.js +3 -2
  114. package/dist/core/history/workspace-history.d.ts +22 -2
  115. package/dist/core/history/workspace-history.js +60 -36
  116. package/dist/core/output/output.d.ts +2 -0
  117. package/dist/core/output/output.js +3 -2
  118. package/dist/core/shared/command-types.d.ts +2 -0
  119. package/dist/core/shared/command-types.js +2 -2
  120. package/dist/mcp/tool-definitions.js +6 -2
  121. package/dist/sdk/author-attribution.js +23 -7
  122. package/dist/sdk/cli-bootstrap.d.ts +2 -0
  123. package/dist/sdk/cli-bootstrap.js +7 -2
  124. package/dist/sdk/cli-contracts/completeness.js +51 -4
  125. package/dist/sdk/cli-contracts/flag-contracts.js +3 -2
  126. package/dist/sdk/cli-contracts/registration-helpers.js +3 -2
  127. package/dist/sdk/cli-contracts/runtime-contracts.js +14 -8
  128. package/dist/sdk/cli-contracts/tool-parameter-tables.js +116 -10
  129. package/dist/sdk/cli-contracts/tool-schema.js +18 -2
  130. package/dist/sdk/cli-program.js +3 -2
  131. package/dist/sdk/completion.js +5 -2
  132. package/dist/sdk/contracts.d.ts +1 -0
  133. package/dist/sdk/contracts.js +2 -2
  134. package/dist/sdk/core.d.ts +3 -1
  135. package/dist/sdk/core.js +4 -3
  136. package/dist/sdk/extension.js +9 -11
  137. package/dist/sdk/generated-error-code-catalog.js +112 -2
  138. package/dist/sdk/history-analytics.d.ts +141 -0
  139. package/dist/sdk/history-analytics.js +283 -0
  140. package/dist/sdk/improvement-ledger-validation.d.ts +3 -0
  141. package/dist/sdk/improvement-ledger-validation.js +63 -0
  142. package/dist/sdk/improvement-ledger.d.ts +139 -0
  143. package/dist/sdk/improvement-ledger.js +261 -0
  144. package/dist/sdk/index.d.ts +6 -2
  145. package/dist/sdk/index.js +8 -4
  146. package/dist/sdk/lifecycle/plan.js +6 -3
  147. package/dist/sdk/merge/install.js +10 -2
  148. package/dist/sdk/read-output-budget.js +24 -22
  149. package/dist/sdk/read-output-contracts.d.ts +10 -2
  150. package/dist/sdk/read-output-contracts.js +124 -65
  151. package/dist/sdk/read-output-rows.d.ts +29 -0
  152. package/dist/sdk/read-output-rows.js +100 -0
  153. package/dist/sdk/read-output-session.d.ts +69 -0
  154. package/dist/sdk/read-output-session.js +200 -0
  155. package/dist/sdk/runtime-input.d.ts +2 -0
  156. package/dist/sdk/runtime-input.js +14 -2
  157. package/dist/sdk/runtime-primitives.d.ts +1 -1
  158. package/dist/sdk/runtime-primitives.js +3 -3
  159. package/dist/sdk/runtime-stats-options.d.ts +9 -0
  160. package/dist/sdk/runtime-stats-options.js +38 -0
  161. package/dist/sdk/runtime.d.ts +1 -0
  162. package/dist/sdk/runtime.js +6 -27
  163. package/dist/sdk/stats.d.ts +40 -0
  164. package/dist/sdk/stats.js +112 -29
  165. package/docs/IMPROVEMENT_ANALYTICS.md +103 -0
  166. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +5 -5
  167. package/docs/README.md +1 -0
  168. package/docs/READ_OUTPUT_CONTRACTS.md +60 -1
  169. package/marketplace.json +2 -2
  170. package/package.json +3 -3
  171. package/packages/pm-beads/package.json +1 -1
  172. package/packages/pm-calendar/package.json +1 -1
  173. package/packages/pm-command-kit/package.json +1 -1
  174. package/packages/pm-digital-twin/package.json +1 -1
  175. package/packages/pm-governance-audit/package.json +1 -1
  176. package/packages/pm-guide-shell/package.json +1 -1
  177. package/packages/pm-kanban/package.json +1 -1
  178. package/packages/pm-lifecycle-hooks/package.json +1 -1
  179. package/packages/pm-linked-test-adapters/package.json +1 -1
  180. package/packages/pm-search-advanced/package.json +1 -1
  181. package/packages/pm-templates/package.json +1 -1
  182. package/packages/pm-todos/package.json +1 -1
  183. package/packages/pm-vcs/package.json +1 -1
  184. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  185. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  186. package/sdk/public-surface.json +374 -821
  187. package/dist/cli-bundle/chunks/append-XAJ5Z4XS.js +0 -2
  188. package/dist/cli-bundle/chunks/chunk-AJE3AHPD.js +0 -8
  189. package/dist/cli-bundle/chunks/chunk-E7BFPLUZ.js +0 -5
  190. package/dist/cli-bundle/chunks/chunk-HS7OVAUN.js +0 -164
  191. package/dist/cli-bundle/chunks/chunk-SV3YQ4RY.js +0 -2
  192. package/dist/cli-bundle/chunks/chunk-V663653R.js +0 -20
  193. package/dist/cli-bundle/chunks/chunk-XPOQQJTX.js +0 -13
  194. package/dist/cli-bundle/chunks/chunk-YCCDXBNU.js +0 -2
  195. package/dist/cli-bundle/chunks/chunk-ZFBWCKYF.js +0 -2
  196. package/dist/cli-bundle/chunks/close-DI66JMSB.js +0 -2
  197. package/dist/cli-bundle/chunks/close-many-VFKT6U3O.js +0 -2
  198. package/dist/cli-bundle/chunks/comments-E73HIEZJ.js +0 -2
  199. package/dist/cli-bundle/chunks/copy-WBYVLCPC.js +0 -2
  200. package/dist/cli-bundle/chunks/delete-6XKUVVQN.js +0 -2
  201. package/dist/cli-bundle/chunks/focus-R2AWS63Y.js +0 -2
  202. package/dist/cli-bundle/chunks/register-operations-HIBJXRGB.js +0 -2
  203. package/dist/cli-bundle/chunks/restore-FXA5QPM7.js +0 -2
  204. package/dist/cli-bundle/chunks/update-7GBO4SXG.js +0 -2
  205. package/dist/cli-bundle/chunks/update-many-VF6ZKQUO.js +0 -2
  206. package/dist/cli-bundle/focused-chunks/chunk-74CWP3A4.js +0 -2
  207. package/dist/cli-bundle/focused-chunks/chunk-7AZDTGPA.js +0 -2
  208. package/dist/cli-bundle/focused-chunks/chunk-LKQXXO62.js +0 -2
  209. package/dist/cli-bundle/focused-chunks/chunk-QL5H3AQH.js +0 -2
@@ -0,0 +1,261 @@
1
+ /**
2
+ * @module sdk/improvement-ledger
3
+ *
4
+ * Persists append-only quantitative observations in an audited workspace
5
+ * singleton and exposes bounded trend reads for self-improvement loops.
6
+ */
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]="aaa927b3-4bc4-561f-aff1-85dc95c12ea1")}catch(e){}}();
9
+ import { createHash } from "node:crypto";
10
+ import { execFile } from "node:child_process";
11
+ import path from "node:path";
12
+ import { promisify } from "node:util";
13
+ import { pathExists, readFileIfExists } from "../core/fs/fs-utils.js";
14
+ import { mutateWorkspaceJsonWithHistory } from "../core/history/workspace-history.js";
15
+ import { EXIT_CODE } from "../core/shared/constants.js";
16
+ import { resolveAuthor } from "../core/shared/author.js";
17
+ import { PmCliError } from "../core/shared/errors.js";
18
+ import { stableStringify } from "../core/shared/serialization.js";
19
+ import { nowIso } from "../core/shared/time.js";
20
+ import { getSettingsPath, resolvePmRoot, resolveWorkspaceRoot, } from "../core/store/paths.js";
21
+ import { readSettings } from "../core/store/settings.js";
22
+ import { parseImprovementLedgerDocument as parseLedger } from "./improvement-ledger-validation.js";
23
+ const execFileAsync = promisify(execFile);
24
+ const DEFAULT_OBSERVATION_LIMIT = 50;
25
+ const MAX_OBSERVATION_LIMIT = 1_000;
26
+ const METRIC_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9._/-]{0,126}[a-z0-9])?$/u;
27
+ function normalizeMetricName(value) {
28
+ const metric = value.trim().toLowerCase();
29
+ if (!METRIC_NAME_PATTERN.test(metric)) {
30
+ throw new PmCliError(`Invalid metric name "${value}"; use 1-128 lowercase letters, digits, dots, slashes, underscores, or hyphens.`, EXIT_CODE.USAGE, { code: "invalid_improvement_metric" });
31
+ }
32
+ return metric;
33
+ }
34
+ function normalizeDirection(value) {
35
+ const direction = value ?? "lower";
36
+ if (!["higher", "lower", "target"].includes(direction)) {
37
+ throw new PmCliError("Improvement direction must be higher, lower, or target.", EXIT_CODE.USAGE, { code: "invalid_improvement_observation" });
38
+ }
39
+ return direction;
40
+ }
41
+ function normalizeOptionalText(value, field) {
42
+ const normalized = value?.trim();
43
+ if (!normalized)
44
+ return undefined;
45
+ if (normalized.length > 256) {
46
+ throw new PmCliError(`${field} must not exceed 256 characters.`, EXIT_CODE.USAGE, { code: "invalid_improvement_observation" });
47
+ }
48
+ return normalized;
49
+ }
50
+ function parseObservationLimit(value) {
51
+ const limit = value ?? DEFAULT_OBSERVATION_LIMIT;
52
+ if (!Number.isSafeInteger(limit) ||
53
+ limit < 0 ||
54
+ limit > MAX_OBSERVATION_LIMIT) {
55
+ throw new PmCliError(`Improvement observation limit must be an integer from 0 to ${MAX_OBSERVATION_LIMIT}.`, EXIT_CODE.USAGE, { code: "invalid_improvement_observation_limit" });
56
+ }
57
+ return limit;
58
+ }
59
+ function parseIsoTimestamp(value, field) {
60
+ const milliseconds = Date.parse(value);
61
+ if (!Number.isFinite(milliseconds)) {
62
+ throw new PmCliError(`${field} must be an ISO timestamp.`, EXIT_CODE.USAGE, {
63
+ code: "invalid_improvement_observation_timestamp",
64
+ });
65
+ }
66
+ return new Date(milliseconds).toISOString();
67
+ }
68
+ async function buildImprovementObservation(pmRoot, settings, options) {
69
+ if (!Number.isFinite(options.value)) {
70
+ throw new PmCliError("Improvement observation value must be finite.", EXIT_CODE.USAGE, { code: "invalid_improvement_observation" });
71
+ }
72
+ const metric = normalizeMetricName(options.metric);
73
+ const direction = normalizeDirection(options.direction);
74
+ if ((options.threshold !== undefined && !Number.isFinite(options.threshold)) ||
75
+ (direction === "target" && options.threshold === undefined)) {
76
+ throw new PmCliError("Target-directed observations require a finite threshold.", EXIT_CODE.USAGE, { code: "invalid_improvement_observation" });
77
+ }
78
+ const revision = await resolveObservationRevision(pmRoot, options.revision);
79
+ const source = normalizeOptionalText(options.source, "source");
80
+ const itemId = normalizeOptionalText(options.itemId, "itemId");
81
+ const unit = normalizeOptionalText(options.unit, "unit");
82
+ const idempotencyKey = normalizeOptionalText(options.idempotencyKey, "idempotencyKey") ??
83
+ (revision.revision_source === "unversioned"
84
+ ? undefined
85
+ : [
86
+ revision.revision,
87
+ metric,
88
+ source ?? "manual",
89
+ itemId ?? "workspace",
90
+ ].join(":"));
91
+ const observationWithoutId = {
92
+ metric,
93
+ value: options.value,
94
+ direction,
95
+ ...(unit === undefined ? {} : { unit }),
96
+ ...(options.threshold === undefined
97
+ ? {}
98
+ : { threshold: options.threshold }),
99
+ observed_at: parseIsoTimestamp(options.observedAt ?? nowIso(), "observedAt"),
100
+ ...revision,
101
+ author: resolveAuthor(options.author, settings.author_default),
102
+ ...(itemId === undefined ? {} : { item_id: itemId }),
103
+ ...(source === undefined ? {} : { source }),
104
+ ...(idempotencyKey === undefined
105
+ ? {}
106
+ : { idempotency_key: idempotencyKey }),
107
+ };
108
+ return {
109
+ id: createHash("sha256")
110
+ .update(stableStringify(observationWithoutId))
111
+ .digest("hex")
112
+ .slice(0, 24),
113
+ ...observationWithoutId,
114
+ };
115
+ }
116
+ function ensureObservationCanAppend(ledger, observation) {
117
+ const existing = observation.idempotency_key
118
+ ? ledger.observations.find((row) => row.idempotency_key === observation.idempotency_key)
119
+ : ledger.observations.find((row) => row.id === observation.id);
120
+ if (existing) {
121
+ if (existing.metric !== observation.metric ||
122
+ existing.value !== observation.value ||
123
+ existing.direction !== observation.direction ||
124
+ existing.threshold !== observation.threshold ||
125
+ existing.unit !== observation.unit) {
126
+ throw new PmCliError(`Improvement observation retry key already records a different value for ${observation.metric}.`, EXIT_CODE.CONFLICT, { code: "improvement_observation_conflict" });
127
+ }
128
+ return existing;
129
+ }
130
+ const priorMetric = ledger.observations.find((row) => row.metric === observation.metric);
131
+ if (priorMetric &&
132
+ (priorMetric.direction !== observation.direction ||
133
+ priorMetric.unit !== observation.unit ||
134
+ (observation.direction === "target" &&
135
+ priorMetric.threshold !== observation.threshold))) {
136
+ throw new PmCliError(`Metric ${observation.metric} is already declared with direction ${priorMetric.direction} and unit ${priorMetric.unit ?? "<none>"}.`, EXIT_CODE.CONFLICT, { code: "improvement_metric_contract_conflict" });
137
+ }
138
+ return undefined;
139
+ }
140
+ async function resolveObservationRevision(pmRoot, explicit) {
141
+ const callerRevision = normalizeOptionalText(explicit, "revision");
142
+ if (callerRevision) {
143
+ return { revision: callerRevision, revision_source: "caller" };
144
+ }
145
+ try {
146
+ const result = await execFileAsync("git", ["rev-parse", "--verify", "HEAD^{commit}"], {
147
+ cwd: resolveWorkspaceRoot(pmRoot),
148
+ encoding: "utf8",
149
+ timeout: 5_000,
150
+ });
151
+ const revision = result.stdout.trim();
152
+ return { revision, revision_source: "git" };
153
+ }
154
+ catch {
155
+ // Git is optional for root-layout and embedded SDK workspaces.
156
+ }
157
+ return { revision: "unversioned", revision_source: "unversioned" };
158
+ }
159
+ function trendForMetric(observations) {
160
+ const baseline = observations[0];
161
+ const latest = observations[observations.length - 1];
162
+ const delta = latest.value - baseline.value;
163
+ const improved = latest.direction === "higher"
164
+ ? delta > 0
165
+ : latest.direction === "lower"
166
+ ? delta < 0
167
+ : Math.abs(latest.value - latest.threshold) <
168
+ Math.abs(baseline.value - baseline.threshold);
169
+ return {
170
+ metric: latest.metric,
171
+ direction: latest.direction,
172
+ baseline,
173
+ latest,
174
+ delta,
175
+ improved,
176
+ sample_count: observations.length,
177
+ };
178
+ }
179
+ /** Record one audited observation, returning an idempotent receipt on retry. */
180
+ export async function recordImprovementObservation(options, global = {}) {
181
+ const pmRoot = resolvePmRoot(process.cwd(), global.path);
182
+ if (!(await pathExists(getSettingsPath(pmRoot)))) {
183
+ throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
184
+ }
185
+ const settings = await readSettings(pmRoot);
186
+ const observation = await buildImprovementObservation(pmRoot, settings, options);
187
+ const filePath = path.join(pmRoot, "improvement-ledger.json");
188
+ const mutation = await mutateWorkspaceJsonWithHistory({
189
+ pmRoot,
190
+ filePath,
191
+ op: "improvement_observe",
192
+ author: observation.author,
193
+ lockTtlSeconds: settings.locks.ttl_seconds,
194
+ lockWaitMs: settings.locks.wait_ms,
195
+ message: options.message ??
196
+ `Record ${observation.metric}=${String(options.value)} improvement observation`,
197
+ mutate: (beforeRaw) => {
198
+ const ledger = parseLedger(beforeRaw);
199
+ const existing = ensureObservationCanAppend(ledger, observation);
200
+ if (existing) {
201
+ return { raw: beforeRaw, result: existing };
202
+ }
203
+ ledger.observations.push(observation);
204
+ ledger.observations.sort((left, right) => left.observed_at.localeCompare(right.observed_at) ||
205
+ left.metric.localeCompare(right.metric) ||
206
+ left.id.localeCompare(right.id));
207
+ return {
208
+ raw: `${stableStringify(ledger)}\n`,
209
+ result: observation,
210
+ };
211
+ },
212
+ });
213
+ return {
214
+ changed: mutation.changed,
215
+ observation: mutation.result,
216
+ ledger_path: "improvement-ledger.json",
217
+ };
218
+ }
219
+ /** Read a bounded newest-first observation page and derive complete trends. */
220
+ export async function readImprovementLedger(options = {}) {
221
+ const pmRoot = resolvePmRoot(options.cwd ?? process.cwd(), options.pmRoot);
222
+ if (!(await pathExists(getSettingsPath(pmRoot)))) {
223
+ throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
224
+ }
225
+ const metric = options.metric === undefined
226
+ ? undefined
227
+ : normalizeMetricName(options.metric);
228
+ const since = options.since === undefined
229
+ ? undefined
230
+ : parseIsoTimestamp(options.since, "since");
231
+ const limit = parseObservationLimit(options.limit);
232
+ const ledger = parseLedger(await readFileIfExists(path.join(pmRoot, "improvement-ledger.json")));
233
+ const matching = ledger.observations.filter((row) => (metric === undefined || row.metric === metric) &&
234
+ (options.itemId === undefined || row.item_id === options.itemId) &&
235
+ (since === undefined || row.observed_at >= since));
236
+ const byMetric = new Map();
237
+ for (const observation of matching) {
238
+ const rows = byMetric.get(observation.metric) ?? [];
239
+ rows.push(observation);
240
+ byMetric.set(observation.metric, rows);
241
+ }
242
+ return {
243
+ observations: [...matching].reverse().slice(0, limit),
244
+ total: matching.length,
245
+ truncated: matching.length > limit,
246
+ trends: [...byMetric]
247
+ .map(([, observations]) => trendForMetric(observations))
248
+ .sort((left, right) => left.metric.localeCompare(right.metric)),
249
+ source: "audited_workspace_singleton",
250
+ };
251
+ }
252
+ /** Pure helpers exposed for storage and trend contract tests. */
253
+ export const _testOnlyImprovementLedger = {
254
+ normalizeMetricName,
255
+ normalizeDirection,
256
+ parseLedger,
257
+ parseObservationLimit,
258
+ trendForMetric,
259
+ };
260
+ //# sourceMappingURL=improvement-ledger.js.map
261
+ //# debugId=aaa927b3-4bc4-561f-aff1-85dc95c12ea1
@@ -20,7 +20,7 @@ export { quoteCommandArg, quoteWindowsCommandArg, renderPmCommand, } from "./com
20
20
  export { runGc, type GcCheckpointsSummary, type GcLocksSummary, } from "./governance/gc.js";
21
21
  export { _testOnlyHealthCommand, runHealth, type HealthCheck, } from "./governance/health.js";
22
22
  export { _testOnlyValidateCommand, projectValidateCounts, runValidate, type ValidateCheck, type ValidateCountsFixesSummary, type ValidateCountsResult, type ValidateFixesSummary, type ValidateMutationServices, } from "./governance/validate.js";
23
- export { runExtension, type ExtensionCommandAction, } from "./extension.js";
23
+ export { runExtension, type ExtensionCommandAction } from "./extension.js";
24
24
  export { resolveExtensionInstallSourceIdentity, type ExtensionInstallSourceCandidate, type ExtensionInstallSourceResolution, type ExtensionInstallSourceSelection, type ResolvedExtensionInstallSource, } from "./extension/source-resolution.js";
25
25
  export { applyStoredExtensionMigrationState, readExtensionMigrationState, resolveExtensionMigrationStatePath, runExtensionMigrateAction, runExtensionMigrations, type ExtensionMigrationActionContext, type ExtensionMigrationOutcomeStatus, type ExtensionMigrationReceipt, type ExtensionMigrationRunResult, type ExtensionMigrationState, type ExtensionMigrationStateEntry, type RunExtensionMigrationsOptions, } from "./extension/migrations.js";
26
26
  export { findInstalledNpmPackageCandidate, type GithubInstallSource, type InstalledNpmPackageCandidate, type InstallSource, type LocalInstallSource, type NpmInstallSource, type ResolvedInstallSource, } from "./extension/install-sources.js";
@@ -61,6 +61,8 @@ export * from "./lifecycle-completion.js";
61
61
  export * from "./lifecycle-policy.js";
62
62
  export * from "./output-projection.js";
63
63
  export * from "./read-output-contracts.js";
64
+ export * from "./read-output-rows.js";
65
+ export * from "./read-output-session.js";
64
66
  export * from "./output-token-accounting.js";
65
67
  export * from "./context-packing.js";
66
68
  export * from "./context-usage.js";
@@ -70,7 +72,7 @@ export * from "./history-compact.js";
70
72
  export * from "./history-read.js";
71
73
  export * from "./history-provenance.js";
72
74
  export * from "./mutation-events.js";
73
- export { appendWorkspaceAuditEvent, appendWorkspaceHistoryChange, getWorkspaceHistoryPath, WORKSPACE_HISTORY_ID, writeWorkspaceJsonWithHistory, type WorkspaceAuditEventOptions, type WorkspaceHistoryChange, type WorkspaceJsonWriteOptions, } from "../core/history/workspace-history.js";
75
+ export { appendWorkspaceAuditEvent, appendWorkspaceHistoryChange, getWorkspaceHistoryPath, mutateWorkspaceJsonWithHistory, WORKSPACE_HISTORY_ID, writeWorkspaceJsonWithHistory, type WorkspaceAuditEventOptions, type WorkspaceHistoryChange, type WorkspaceJsonMutation, type WorkspaceJsonMutationOptions, type WorkspaceJsonWriteOptions, } from "../core/history/workspace-history.js";
74
76
  export * from "./history-redact.js";
75
77
  export { _testOnly } from "./history-redact.js";
76
78
  export * from "./history-repair.js";
@@ -125,6 +127,8 @@ export { BASELINE_ITEM_FORMAT_VERSION, BUILTIN_ITEM_TYPE_VALUES, CONFIDENCE_TEXT
125
127
  export { extensionMigrate, packageMigrate } from "./package-migrations.js";
126
128
  export { CONTEXT_OUTPUT_VALUES, NEXT_OUTPUT_VALUES, PM_GITIGNORE_END, PM_GITIGNORE_START, analyzeSdkActionCoverage, ensurePmGitignore, getPmGitignoreBlock, closeItem, runAggregate, runClose, runCopy, runContext, runDelete, runFocus, runGet, runNext, runRestore, runUpdate, type CloseCommandOptions, type CopyOptions, type DeleteCommandOptions, type EnsurePmGitignoreResult, type HierarchyChild, type HierarchyNode, type HotFile, type FocusOptions, type ImportPriorityValue, type ProgressEntry, type RecentContextItem, type RestoreCommandOptions, type SdkActionCoverageRow, type StaleEntry, type TestHealthSummary, type UpdateCommandOptions, type WorkloadEntry, } from "./runtime.js";
127
129
  export { runStats } from "./stats.js";
130
+ export { readImprovementLedger, recordImprovementObservation, type ImprovementDirection, type ImprovementLedgerDocument, type ImprovementLedgerResult, type ImprovementObservation, type ImprovementTrend, type ReadImprovementLedgerOptions, type RecordImprovementObservationOptions, type RecordImprovementObservationResult, } from "./improvement-ledger.js";
131
+ export { evaluateProvenanceCoverage, projectFleetAttributionAnalytics, projectProvenanceCoverageAnalytics, readHistoryAnalyticsWindow, runFleetAttributionAnalytics, runProvenanceCoverageAnalytics, type FleetAttributionAnalytics, type FleetAttributionDimension, type FleetAttributionRow, type HistoryAnalyticsWindowOptions, type HistoryAnalyticsWindowReceipt, type HistoryAnalyticsEvent, type HistoryAnalyticsWindow, type ProvenanceCoverageAnalytics, } from "./history-analytics.js";
128
132
  export { DEFAULT_EVAL_QUERIES_RELATIVE_PATH, EVAL_QUERY_SET_CONTRACT, EVAL_QUERY_SET_EXAMPLE, EVAL_QUERY_SET_SCHEMA_ID, parseEvalQuerySet, runEval, type EvalOptions, type EvalQueryReport, type EvalResult, } from "./eval.js";
129
133
  export { runTelemetry, TELEMETRY_SUBCOMMANDS, type TelemetryCommandOptions, type TelemetryFlushResult, type TelemetryStatusSummary, type TelemetrySubcommand, } from "./telemetry.js";
130
134
  export { classifyLinkedTestFailure, countFailureCategories, extractReferencedPmItemIdsFromCommand, resolveLinkedTestFailureExitCode, runLinkedTests, runTest, summarizeContextPreflight, type LinkedTestFailureCategory, type TestCommandOptions, type TestResult, type TestRunResult, } from "./test/execution.js";
package/dist/sdk/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Defines public SDK APIs and package-author helpers for Index.
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]="4e336574-f00e-5296-a55f-7f27a264188c")}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]="346cbfc0-a42a-5ae6-b95a-af3bd63fc6d1")}catch(e){}}();
8
8
  export { PM_COMMAND_VISIBILITY_CONTRACTS, PM_MCP_PROMPT_CONTRACTS, PM_MCP_RESOURCE_CONTRACTS, PM_MCP_TOOL_COMMAND_CONTRACTS, listPmCommandsForTier, listPmMcpToolsForProfile, renderPmCommandVisibilityMarkdown, resolvePmCommandVisibilityTier, } from "./agent-capability-contracts.js";
9
9
  export * from "./agent-session-context.js";
10
10
  export { isErrnoError, limitAnnotationEntries, parseAnnotationTextInput, readAnnotationEntries, resolveAnnotationInput, resolveAnnotationIndex, runAnnotationCommand, wrapOwnershipConflict, } from "./annotations.js";
@@ -21,7 +21,7 @@ export { quoteCommandArg, quoteWindowsCommandArg, renderPmCommand, } from "./com
21
21
  export { runGc, } from "./governance/gc.js";
22
22
  export { _testOnlyHealthCommand, runHealth, } from "./governance/health.js";
23
23
  export { _testOnlyValidateCommand, projectValidateCounts, runValidate, } from "./governance/validate.js";
24
- export { runExtension, } from "./extension.js";
24
+ export { runExtension } from "./extension.js";
25
25
  export { resolveExtensionInstallSourceIdentity, } from "./extension/source-resolution.js";
26
26
  export { applyStoredExtensionMigrationState, readExtensionMigrationState, resolveExtensionMigrationStatePath, runExtensionMigrateAction, runExtensionMigrations, } from "./extension/migrations.js";
27
27
  export { findInstalledNpmPackageCandidate, } from "./extension/install-sources.js";
@@ -59,6 +59,8 @@ export * from "./lifecycle-completion.js";
59
59
  export * from "./lifecycle-policy.js";
60
60
  export * from "./output-projection.js";
61
61
  export * from "./read-output-contracts.js";
62
+ export * from "./read-output-rows.js";
63
+ export * from "./read-output-session.js";
62
64
  export * from "./output-token-accounting.js";
63
65
  export * from "./context-packing.js";
64
66
  export * from "./context-usage.js";
@@ -68,7 +70,7 @@ export * from "./history-compact.js";
68
70
  export * from "./history-read.js";
69
71
  export * from "./history-provenance.js";
70
72
  export * from "./mutation-events.js";
71
- export { appendWorkspaceAuditEvent, appendWorkspaceHistoryChange, getWorkspaceHistoryPath, WORKSPACE_HISTORY_ID, writeWorkspaceJsonWithHistory, } from "../core/history/workspace-history.js";
73
+ export { appendWorkspaceAuditEvent, appendWorkspaceHistoryChange, getWorkspaceHistoryPath, mutateWorkspaceJsonWithHistory, WORKSPACE_HISTORY_ID, writeWorkspaceJsonWithHistory, } from "../core/history/workspace-history.js";
72
74
  export * from "./history-redact.js";
73
75
  export { _testOnly } from "./history-redact.js";
74
76
  export * from "./history-repair.js";
@@ -117,6 +119,8 @@ export { BASELINE_ITEM_FORMAT_VERSION, BUILTIN_ITEM_TYPE_VALUES, CONFIDENCE_TEXT
117
119
  export { extensionMigrate, packageMigrate } from "./package-migrations.js";
118
120
  export { CONTEXT_OUTPUT_VALUES, NEXT_OUTPUT_VALUES, PM_GITIGNORE_END, PM_GITIGNORE_START, analyzeSdkActionCoverage, ensurePmGitignore, getPmGitignoreBlock, closeItem, runAggregate, runClose, runCopy, runContext, runDelete, runFocus, runGet, runNext, runRestore, runUpdate, } from "./runtime.js";
119
121
  export { runStats } from "./stats.js";
122
+ export { readImprovementLedger, recordImprovementObservation, } from "./improvement-ledger.js";
123
+ export { evaluateProvenanceCoverage, projectFleetAttributionAnalytics, projectProvenanceCoverageAnalytics, readHistoryAnalyticsWindow, runFleetAttributionAnalytics, runProvenanceCoverageAnalytics, } from "./history-analytics.js";
120
124
  export { DEFAULT_EVAL_QUERIES_RELATIVE_PATH, EVAL_QUERY_SET_CONTRACT, EVAL_QUERY_SET_EXAMPLE, EVAL_QUERY_SET_SCHEMA_ID, parseEvalQuerySet, runEval, } from "./eval.js";
121
125
  export { runTelemetry, TELEMETRY_SUBCOMMANDS, } from "./telemetry.js";
122
126
  export { classifyLinkedTestFailure, countFailureCategories, extractReferencedPmItemIdsFromCommand, resolveLinkedTestFailureExitCode, runLinkedTests, runTest, summarizeContextPreflight, } from "./test/execution.js";
@@ -133,4 +137,4 @@ export * from "./governance.js";
133
137
  export * from "./query.js";
134
138
  export * from "./testing.js";
135
139
  //# sourceMappingURL=index.js.map
136
- //# debugId=4e336574-f00e-5296-a55f-7f27a264188c
140
+ //# debugId=346cbfc0-a42a-5ae6-b95a-af3bd63fc6d1
@@ -4,7 +4,7 @@
4
4
  * Implements the pm plan 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]="d4b9caa3-59eb-5747-ba76-49f786c5010e")}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]="5d3c68a6-0b40-56b5-ae9e-776e1830ed3e")}catch(e){}}();
8
8
  import { pathExists, getActiveExtensionRegistrations, isTerminalStatus, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, resolveTypeName, EXIT_CODE, PmCliError, splitCommaList, nowIso, locateItem, mutateItem, readLocatedItem, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, isTerminalPlanMode, } from "../runtime-primitives.js";
9
9
  import { PLAN_HARNESS_VALUES, PLAN_MODE_VALUES, PLAN_STEP_LINK_KIND_VALUES, PLAN_STEP_STATUS_VALUES, } from "../../types/index.js";
10
10
  import { runCreate, } from "./create.js";
@@ -726,7 +726,10 @@ async function planCreate(options, global, ctx) {
726
726
  test: toSpecArray(options.test),
727
727
  doc: toSpecArray(options.doc),
728
728
  field: toSpecArray(options.field),
729
- assignee: requestedAssignee,
729
+ // Ownership is assigned by the atomic Plan metadata mutation below. The
730
+ // base create must remain author-owned so strict ownership governance does
731
+ // not reject the metadata seed as a cross-owner follow-up mutation.
732
+ assignee: resolveAuthor(options.author, ctx.settings.author_default),
730
733
  blockedBy: undefined,
731
734
  dep: buildPlanCreateDependencies(options),
732
735
  message: options.message ??
@@ -1576,4 +1579,4 @@ export const _testOnlyPlanCommand = {
1576
1579
  changedPlanMetadataFields,
1577
1580
  };
1578
1581
  //# sourceMappingURL=plan.js.map
1579
- //# debugId=d4b9caa3-59eb-5747-ba76-49f786c5010e
1582
+ //# debugId=5d3c68a6-0b40-56b5-ae9e-776e1830ed3e
@@ -8,7 +8,7 @@
8
8
  * mutations refresh the fenced block automatically once it is installed.
9
9
  */
10
10
 
11
- !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]="1729579e-ef08-55c3-914f-c025ba3033e4")}catch(e){}}();
11
+ !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]="a250384a-0279-5d01-ade4-f64be3119ed9")}catch(e){}}();
12
12
  import { readFile, realpath, writeFile } from "node:fs/promises";
13
13
  import { execFile } from "node:child_process";
14
14
  import path from "node:path";
@@ -185,6 +185,14 @@ export function buildMergeAttributePatterns(trackerRelativeRoot, typeFolders) {
185
185
  patterns.push(`${quoteGitAttributePattern(`${prefix}history/*.jsonl`)} merge=pm-history`);
186
186
  patterns.push(`${quoteGitAttributePattern(`${prefix}settings.json`)} merge=pm-json`);
187
187
  patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.json`)} merge=pm-json`);
188
+ // Extensions are package assets, not tracker item streams. The broad
189
+ // fallback patterns above intentionally protect unknown contributed item
190
+ // folders, so this last-match escape hatch must explicitly unset merge for
191
+ // every file beneath the reserved extension package root.
192
+ patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/**`)} -merge`);
193
+ // The managed extension inventory is tracker state rather than package
194
+ // content, so restore its structured JSON driver after the asset exclusion.
195
+ patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`);
188
196
  return patterns;
189
197
  }
190
198
  async function reconcileGitattributesBlock(workspaceRoot, patterns, dryRun) {
@@ -510,4 +518,4 @@ export async function installMergeFence(options) {
510
518
  };
511
519
  }
512
520
  //# sourceMappingURL=install.js.map
513
- //# debugId=1729579e-ef08-55c3-914f-c025ba3033e4
521
+ //# debugId=a250384a-0279-5d01-ade4-f64be3119ed9
@@ -1,21 +1,12 @@
1
1
 
2
- !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]="64c4e6e1-d7c4-50e0-a444-fb2fa3c65443")}catch(e){}}();
2
+ !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]="1726fdce-dc71-5707-ae75-b588691e813d")}catch(e){}}();
3
+ import { countReadOutputRows, readOutputRowCollections, } from "./read-output-rows.js";
3
4
  const MAX_ESTIMATE_ITERATIONS = 8;
4
5
  const MAX_COMPACTION_ITERATIONS = 64;
5
6
  /** Return whether a value is a non-array object record. */
6
7
  function isRecord(value) {
7
8
  return value !== null && typeof value === "object" && !Array.isArray(value);
8
9
  }
9
- /** Resolve declared row keys, falling back to top-level array properties. */
10
- function rowKeys(result) {
11
- const contract = result.row_contract;
12
- if (isRecord(contract) && Array.isArray(contract.row_keys)) {
13
- return contract.row_keys.filter((entry) => typeof entry === "string");
14
- }
15
- return Object.entries(result)
16
- .filter(([, value]) => Array.isArray(value))
17
- .map(([key]) => key);
18
- }
19
10
  /** Recursively shorten explanatory strings and record whether content changed. */
20
11
  function compactStrings(value, state) {
21
12
  if (typeof value === "string") {
@@ -48,27 +39,38 @@ export function updateReadOutputReceiptEstimate(result, receipt) {
48
39
  }
49
40
  /** Reduce the largest row collection until the budget fits or no rows can move. */
50
41
  function compactRowsToBudget(result, receipt, budget) {
51
- const keys = rowKeys(result);
52
42
  for (let iteration = 0; iteration < MAX_COMPACTION_ITERATIONS; iteration += 1) {
53
43
  updateReadOutputReceiptEstimate(result, receipt);
54
44
  if (receipt.estimated_tokens <= budget)
55
45
  return;
56
- const candidate = keys
57
- .map((key) => ({
58
- key,
59
- rows: Array.isArray(result[key]) ? result[key] : [],
46
+ const candidate = readOutputRowCollections(result)
47
+ .filter((collection) => (Array.isArray(collection.value)
48
+ ? collection.value.length
49
+ : Object.keys(collection.value).length) > 1)
50
+ .map((collection) => ({
51
+ collection,
52
+ length: Array.isArray(collection.value)
53
+ ? collection.value.length
54
+ : Object.keys(collection.value).length,
60
55
  }))
61
- .filter(({ rows }) => rows.length > 1)
62
- .sort((left, right) => right.rows.length - left.rows.length ||
63
- left.key.localeCompare(right.key))[0];
56
+ .sort((left, right) => right.length - left.length ||
57
+ left.collection.path.localeCompare(right.collection.path))[0]?.collection;
64
58
  if (!candidate)
65
59
  return;
66
- candidate.rows.splice(-Math.max(1, Math.ceil(candidate.rows.length / 2)));
60
+ if (Array.isArray(candidate.value)) {
61
+ candidate.value.splice(-Math.max(1, Math.ceil(candidate.value.length / 2)));
62
+ }
63
+ else {
64
+ const keys = Object.keys(candidate.value);
65
+ for (const key of keys.slice(-Math.max(1, Math.ceil(keys.length / 2)))) {
66
+ delete candidate.value[key];
67
+ }
68
+ }
67
69
  receipt.rows_compacted = true;
68
70
  result.has_more = true;
69
71
  result.truncated = true;
70
72
  if (typeof result.count === "number") {
71
- result.count = keys.reduce((total, key) => total + (Array.isArray(result[key]) ? result[key].length : 0), 0);
73
+ result.count = countReadOutputRows(result);
72
74
  }
73
75
  }
74
76
  }
@@ -83,4 +85,4 @@ export function compactReadOutputToBudget(result, receipt, budget) {
83
85
  return compacted;
84
86
  }
85
87
  //# sourceMappingURL=read-output-budget.js.map
86
- //# debugId=64c4e6e1-d7c4-50e0-a444-fb2fa3c65443
88
+ //# debugId=1726fdce-dc71-5707-ae75-b588691e813d
@@ -1,3 +1,4 @@
1
+ import { type PmReadOutputSessionReceipt, type PmReadOutputSessionState } from "./read-output-session.js";
1
2
  /** Stable output dimensions shared by every read surface. */
2
3
  export declare const PM_READ_OUTPUT_DIMENSIONS: readonly ["include", "amount", "cost", "encoding"];
3
4
  /** One member of the universal read-output dimension set. */
@@ -16,6 +17,8 @@ export interface PmReadOutputOptions {
16
17
  outputBudget?: string | number;
17
18
  /** Requested static renderer encoding; streaming remains a command behavior. */
18
19
  outputFormat?: "json" | "toon";
20
+ /** Caller-carried cross-call budget and served-fact state. */
21
+ outputSession?: string | PmReadOutputSessionState;
19
22
  }
20
23
  /** Compatibility spelling retained for a command-specific output control. */
21
24
  export interface PmReadOutputLegacyAlias {
@@ -118,11 +121,16 @@ export interface PmReadOutputBudgetExceeded {
118
121
  /** Read result with an optional shaping receipt or a discriminated omission. */
119
122
  export type PmReadOutputResult<Result> = (Result & {
120
123
  read_output?: PmReadOutputReceipt;
121
- }) | PmReadOutputBudgetExceeded;
124
+ read_session?: PmReadOutputSessionReceipt;
125
+ }) | (PmReadOutputBudgetExceeded & {
126
+ read_session?: PmReadOutputSessionReceipt;
127
+ });
122
128
  /** Select the omission-aware result type when an option shape can request a budget. */
123
- export type PmReadOutputResultFor<Result, Options> = "outputBudget" extends keyof Options ? PmReadOutputResult<Result> : Result;
129
+ export type PmReadOutputResultFor<Result, Options> = "outputBudget" extends keyof Options ? PmReadOutputResult<Result> : "outputSession" extends keyof Options ? PmReadOutputResult<Result> : Result;
124
130
  /** Canonical CLI flags that opt a read invocation into universal output shaping. */
125
131
  export declare const PM_READ_OUTPUT_OPTION_FLAGS: readonly string[];
132
+ /** Canonical control that composes the four per-call dimensions across reads. */
133
+ export declare const PM_READ_OUTPUT_COMPOSITION_OPTION_FLAGS: readonly ["--output-session"];
126
134
  /** Universal output contract for every built-in read surface. */
127
135
  export declare const PM_READ_OUTPUT_SURFACE_CONTRACTS: readonly PmReadOutputSurfaceContract[];
128
136
  /** Resolve a command or list/context alias to its canonical read-output surface. */