@unbrained/pm-cli 2026.9.7 → 2026.9.9

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 (746) hide show
  1. package/.agents/skills/pm-developer/SKILL.md +12 -4
  2. package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +19 -10
  3. package/.agents/skills/pm-extensions/SKILL.md +6 -0
  4. package/.agents/skills/pm-sdk/SKILL.md +11 -2
  5. package/.agents/skills/pm-user/SKILL.md +7 -2
  6. package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
  7. package/.claude-plugin/marketplace.json +2 -2
  8. package/CHANGELOG.md +231 -182
  9. package/dist/cli/after-command-context-usage.js +1 -48
  10. package/dist/cli/argv-utils.js +1 -40
  11. package/dist/cli/bootstrap-args.js +1 -9
  12. package/dist/cli/bundle-integrity.js +2 -110
  13. package/dist/cli/commander-usage.js +11 -771
  14. package/dist/cli/commands/activity.js +1 -9
  15. package/dist/cli/commands/aggregate.js +1 -5
  16. package/dist/cli/commands/append.js +1 -5
  17. package/dist/cli/commands/claim.js +1 -5
  18. package/dist/cli/commands/close-many.js +1 -5
  19. package/dist/cli/commands/close.js +1 -9
  20. package/dist/cli/commands/comments.js +1 -5
  21. package/dist/cli/commands/config.js +1 -9
  22. package/dist/cli/commands/context.js +1 -9
  23. package/dist/cli/commands/contracts.js +1 -5
  24. package/dist/cli/commands/copy.js +1 -9
  25. package/dist/cli/commands/create.js +1 -9
  26. package/dist/cli/commands/delete.js +1 -9
  27. package/dist/cli/commands/deps.js +1 -9
  28. package/dist/cli/commands/docs.js +1 -9
  29. package/dist/cli/commands/duplicates.js +1 -9
  30. package/dist/cli/commands/eval.js +1 -9
  31. package/dist/cli/commands/extension/describe.js +1 -5
  32. package/dist/cli/commands/extension/scaffold.js +1 -5
  33. package/dist/cli/commands/extension/shared.js +1 -5
  34. package/dist/cli/commands/extension.js +1 -9
  35. package/dist/cli/commands/files.js +1 -9
  36. package/dist/cli/commands/focus.js +1 -9
  37. package/dist/cli/commands/gc.js +1 -9
  38. package/dist/cli/commands/get.js +1 -9
  39. package/dist/cli/commands/graph.js +1 -10
  40. package/dist/cli/commands/health.js +1 -9
  41. package/dist/cli/commands/history-compact.js +1 -10
  42. package/dist/cli/commands/history-redact.js +1 -11
  43. package/dist/cli/commands/history-repair.js +1 -10
  44. package/dist/cli/commands/history.js +1 -5
  45. package/dist/cli/commands/index.js +1 -58
  46. package/dist/cli/commands/init-agent-guidance.js +1 -9
  47. package/dist/cli/commands/init.js +1 -9
  48. package/dist/cli/commands/learnings.js +1 -5
  49. package/dist/cli/commands/lifecycle-transitions.js +1 -5
  50. package/dist/cli/commands/list.js +1 -9
  51. package/dist/cli/commands/merge.js +1 -11
  52. package/dist/cli/commands/next.js +1 -9
  53. package/dist/cli/commands/notes.js +1 -5
  54. package/dist/cli/commands/plan.js +1 -9
  55. package/dist/cli/commands/profile.js +1 -9
  56. package/dist/cli/commands/restore.js +1 -9
  57. package/dist/cli/commands/scheduling-shortcuts.js +1 -9
  58. package/dist/cli/commands/schema.js +1 -10
  59. package/dist/cli/commands/search.js +1 -9
  60. package/dist/cli/commands/stats.js +1 -9
  61. package/dist/cli/commands/telemetry.js +1 -9
  62. package/dist/cli/commands/test-all.js +1 -9
  63. package/dist/cli/commands/test-runs.js +1 -9
  64. package/dist/cli/commands/test.js +1 -9
  65. package/dist/cli/commands/update-many.js +1 -5
  66. package/dist/cli/commands/update.js +1 -9
  67. package/dist/cli/commands/upgrade.js +1 -5
  68. package/dist/cli/commands/validate.js +1 -15
  69. package/dist/cli/context-intent-invocation.js +1 -20
  70. package/dist/cli/description-stdin.js +1 -17
  71. package/dist/cli/error-guidance.js +1 -1353
  72. package/dist/cli/extension-command-help.js +5 -636
  73. package/dist/cli/extension-command-options.js +1 -427
  74. package/dist/cli/extension-recovery.js +1 -126
  75. package/dist/cli/help-content.js +2 -1001
  76. package/dist/cli/help-json-payload.js +4 -570
  77. package/dist/cli/main.d.ts +4 -0
  78. package/dist/cli/main.js +5 -2573
  79. package/dist/cli/migration-gates.js +1 -289
  80. package/dist/cli/public.js +1 -20
  81. package/dist/cli/register-annotations.js +1 -270
  82. package/dist/cli/register-assurance.js +1 -62
  83. package/dist/cli/register-files-lookup.js +1 -56
  84. package/dist/cli/register-history-activity.d.ts +8 -0
  85. package/dist/cli/register-history-activity.js +2 -0
  86. package/dist/cli/register-history-author.js +1 -38
  87. package/dist/cli/register-history-maintenance.d.ts +9 -0
  88. package/dist/cli/register-history-maintenance.js +2 -0
  89. package/dist/cli/register-list-query.js +10 -943
  90. package/dist/cli/register-mutation-options.js +1 -9
  91. package/dist/cli/register-mutation.d.ts +0 -5
  92. package/dist/cli/register-mutation.js +19 -1893
  93. package/dist/cli/register-operations.js +1 -920
  94. package/dist/cli/register-setup.js +1 -716
  95. package/dist/cli/register-structured-mutation.js +1 -196
  96. package/dist/cli/registration-helpers.js +1 -5
  97. package/dist/cli/runtime-compatibility-boundary.js +4 -42
  98. package/dist/cli/schema-registration-helpers.js +1 -73
  99. package/dist/cli/search-refresh.js +1 -13
  100. package/dist/cli/stats-analytics-json.js +1 -68
  101. package/dist/cli/telemetry-flush.js +1 -10
  102. package/dist/cli-bundle/bundle-manifest.json +164 -156
  103. package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-3IPRM75M.js} +3 -3
  104. package/dist/cli-bundle/chunks/chunk-4VL5P22L.js +2 -0
  105. package/dist/cli-bundle/chunks/chunk-AAFBV3U3.js +29 -0
  106. package/dist/cli-bundle/chunks/chunk-D3YVILJJ.js +20 -0
  107. package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
  108. package/dist/cli-bundle/chunks/chunk-ECBLPN7B.js +3 -0
  109. package/dist/cli-bundle/chunks/chunk-J6ERHBV2.js +235 -0
  110. package/dist/cli-bundle/chunks/chunk-JUNJ5EKI.js +2 -0
  111. package/dist/cli-bundle/chunks/chunk-L5RCDKQ2.js +2 -0
  112. package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
  113. package/dist/cli-bundle/chunks/chunk-OHNLSGGV.js +79 -0
  114. package/dist/cli-bundle/chunks/chunk-WQKMSFBV.js +5 -0
  115. package/dist/cli-bundle/chunks/{chunk-BAX2BYUW.js → chunk-XZ6T7YPP.js} +256 -150
  116. package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-Z3XVXUVF.js} +4 -4
  117. package/dist/cli-bundle/chunks/register-list-query-UIHRCS6D.js +11 -0
  118. package/dist/cli-bundle/chunks/register-mutation-WHWMGRVX.js +20 -0
  119. package/dist/cli-bundle/chunks/register-operations-64YZYTC5.js +2 -0
  120. package/dist/cli-bundle/chunks/register-setup-PERI45EM.js +2 -0
  121. package/dist/cli-bundle/focused-chunks/chunk-2W4XIYOB.js +2 -0
  122. package/dist/cli-bundle/focused-chunks/chunk-2WSBXIGF.js +12 -0
  123. package/dist/cli-bundle/focused-chunks/chunk-5FHTCOHS.js +3 -0
  124. package/dist/cli-bundle/focused-chunks/chunk-7N6DOREF.js +26 -0
  125. package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-7PC4R5QB.js} +2 -2
  126. package/dist/cli-bundle/focused-chunks/chunk-BUCJUZVG.js +6 -0
  127. package/dist/cli-bundle/focused-chunks/chunk-FE3BABLJ.js +2 -0
  128. package/dist/cli-bundle/focused-chunks/chunk-IWITF53W.js +2 -0
  129. package/dist/cli-bundle/focused-chunks/chunk-OQUGRHKV.js +10 -0
  130. package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-PNKIANFZ.js} +2 -2
  131. package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-QQQ4SAUO.js} +3 -3
  132. package/dist/cli-bundle/focused-chunks/chunk-TTYXF5YD.js +177 -0
  133. package/dist/cli-bundle/focused-chunks/chunk-XNR3DM6J.js +2 -0
  134. package/dist/cli-bundle/focused-chunks/chunk-XSS3APUF.js +9 -0
  135. package/dist/cli-bundle/focused-chunks/chunk-YCDQ2N23.js +8 -0
  136. package/dist/cli-bundle/focused-chunks/chunk-YJUXGS57.js +20 -0
  137. package/dist/cli-bundle/focused-chunks/chunk-ZTCE4UO6.js +58 -0
  138. package/dist/cli-bundle/main.js +20 -20
  139. package/dist/cli-bundle/sdk-authoring.js +1 -1
  140. package/dist/cli-bundle/sdk-contracts.js +2 -2
  141. package/dist/cli-bundle/sdk-core.js +37 -37
  142. package/dist/cli-bundle/sdk-governance.js +1 -1
  143. package/dist/cli-bundle/sdk-graph.js +1 -1
  144. package/dist/cli-bundle/sdk-merge.js +42 -42
  145. package/dist/cli-bundle/sdk-query.js +1 -1
  146. package/dist/cli-bundle/sdk-runtime.js +1 -1
  147. package/dist/cli-bundle/sdk-testing.js +1 -1
  148. package/dist/cli-bundle/sdk.js +11 -11
  149. package/dist/cli.js +1 -104
  150. package/dist/core/checkpoint/checkpoint-gc.js +1 -169
  151. package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
  152. package/dist/core/config/nested-settings.js +1 -534
  153. package/dist/core/config/positional-value.js +1 -109
  154. package/dist/core/diagnostics/remediation.js +1 -506
  155. package/dist/core/extensions/activation-summary-markdown.js +2 -145
  156. package/dist/core/extensions/activation-summary.js +1 -92
  157. package/dist/core/extensions/activation-transaction.js +1 -46
  158. package/dist/core/extensions/capability-usage.js +1 -173
  159. package/dist/core/extensions/command-hook-context.js +1 -13
  160. package/dist/core/extensions/command-metadata-contract.js +1 -22
  161. package/dist/core/extensions/command-visibility-tier.js +1 -29
  162. package/dist/core/extensions/contribution-inventory.js +1 -173
  163. package/dist/core/extensions/exporter-output-contract.js +1 -66
  164. package/dist/core/extensions/extension-candidate.js +1 -18
  165. package/dist/core/extensions/extension-capability-aliases.js +1 -158
  166. package/dist/core/extensions/extension-hook-runtime.js +1 -699
  167. package/dist/core/extensions/extension-policy.js +1 -599
  168. package/dist/core/extensions/extension-registries.js +1 -62
  169. package/dist/core/extensions/extension-runtime-helpers.js +1 -33
  170. package/dist/core/extensions/extension-types.js +1 -102
  171. package/dist/core/extensions/flag-definition-validation.js +1 -52
  172. package/dist/core/extensions/flag-value-types.js +1 -64
  173. package/dist/core/extensions/index.js +1 -526
  174. package/dist/core/extensions/item-field-types.js +1 -39
  175. package/dist/core/extensions/item-fields.js +1 -261
  176. package/dist/core/extensions/loader.js +1 -2223
  177. package/dist/core/extensions/manifest-schema.js +1 -69
  178. package/dist/core/extensions/module-graph-snapshot.js +1 -33
  179. package/dist/core/extensions/preflight-ownership.js +1 -41
  180. package/dist/core/extensions/registration-validation.js +1 -82
  181. package/dist/core/extensions/registration-values.js +1 -209
  182. package/dist/core/extensions/reserved-host-flags.js +1 -36
  183. package/dist/core/extensions/runtime-registrations.js +1 -67
  184. package/dist/core/extensions/service-ownership.js +1 -19
  185. package/dist/core/extensions/version-compat.js +1 -216
  186. package/dist/core/fs/fs-utils.js +2 -158
  187. package/dist/core/fs/host-environment-errors.js +1 -141
  188. package/dist/core/fs/index.js +1 -9
  189. package/dist/core/fs/path-utils.js +1 -17
  190. package/dist/core/governance/content-fields.js +1 -160
  191. package/dist/core/governance/issue-codes.js +1 -151
  192. package/dist/core/governance/metadata-coverage.js +1 -358
  193. package/dist/core/history/drift-cache.js +3 -72
  194. package/dist/core/history/drift-scan.js +1 -342
  195. package/dist/core/history/event-classification.js +1 -109
  196. package/dist/core/history/event-index.js +8 -784
  197. package/dist/core/history/history-compact-bulk.js +1 -104
  198. package/dist/core/history/history-diff.js +1 -158
  199. package/dist/core/history/history-rewrite.d.ts +6 -1
  200. package/dist/core/history/history-rewrite.js +1 -107
  201. package/dist/core/history/history-storage-stats.js +1 -102
  202. package/dist/core/history/history-stream-policy.js +1 -62
  203. package/dist/core/history/history.js +2 -617
  204. package/dist/core/history/identity.js +1 -30
  205. package/dist/core/history/index.js +1 -9
  206. package/dist/core/history/projection.js +1 -196
  207. package/dist/core/history/read.d.ts +9 -0
  208. package/dist/core/history/read.js +1 -57
  209. package/dist/core/history/replay.js +2 -439
  210. package/dist/core/history/version-address.js +1 -32
  211. package/dist/core/history/workspace-history.js +2 -433
  212. package/dist/core/io/body-file.js +1 -62
  213. package/dist/core/io/bulk-ids-input.js +1 -112
  214. package/dist/core/item/actionability.js +1 -327
  215. package/dist/core/item/dependency-reference.js +1 -20
  216. package/dist/core/item/id.js +1 -112
  217. package/dist/core/item/index.js +1 -12
  218. package/dist/core/item/item-format-version.js +1 -78
  219. package/dist/core/item/item-format.js +5 -1473
  220. package/dist/core/item/item-record.js +1 -23
  221. package/dist/core/item/item-type-definition.js +1 -133
  222. package/dist/core/item/parent-reference-policy.js +1 -57
  223. package/dist/core/item/parse.js +2 -603
  224. package/dist/core/item/plan-lifecycle.js +1 -19
  225. package/dist/core/item/priority.js +1 -61
  226. package/dist/core/item/sprint-release-format.js +1 -38
  227. package/dist/core/item/status-filter.js +1 -115
  228. package/dist/core/item/status.js +1 -43
  229. package/dist/core/item/toon-decode.js +1 -29
  230. package/dist/core/item/type-registry.js +1 -715
  231. package/dist/core/item/type-synonyms.js +1 -38
  232. package/dist/core/lock/index.js +1 -9
  233. package/dist/core/lock/lock-gc.js +1 -240
  234. package/dist/core/lock/lock.js +3 -590
  235. package/dist/core/output/mutation-projection.js +1 -217
  236. package/dist/core/output/output-control.js +1 -25
  237. package/dist/core/output/output.js +11 -494
  238. package/dist/core/output/query-summary.js +1 -58
  239. package/dist/core/output/tabular.js +1 -77
  240. package/dist/core/packages/manifest.js +1 -244
  241. package/dist/core/packages/root.js +1 -84
  242. package/dist/core/policy/workflow-policy-schema.d.ts +312 -0
  243. package/dist/core/policy/workflow-policy-schema.js +2 -0
  244. package/dist/core/policy/workflow-policy-store.d.ts +24 -0
  245. package/dist/core/policy/workflow-policy-store.js +2 -0
  246. package/dist/core/policy/workflow-policy.d.ts +139 -0
  247. package/dist/core/policy/workflow-policy.js +2 -0
  248. package/dist/core/profile/profile-describe.js +1 -83
  249. package/dist/core/profile/profile-lint.js +1 -415
  250. package/dist/core/profile/profile-plan.js +0 -0
  251. package/dist/core/profile/profile-presets.js +1 -370
  252. package/dist/core/reproducibility/context.js +1 -82
  253. package/dist/core/schema/fields-file.js +2 -288
  254. package/dist/core/schema/item-types-file.js +2 -296
  255. package/dist/core/schema/runtime-field-filters.js +1 -49
  256. package/dist/core/schema/runtime-field-values.js +1 -313
  257. package/dist/core/schema/runtime-schema.js +2 -826
  258. package/dist/core/schema/status-defs-file.js +2 -227
  259. package/dist/core/schema/status-token.js +1 -31
  260. package/dist/core/schema/type-inference.js +1 -95
  261. package/dist/core/schema/type-presets.js +1 -87
  262. package/dist/core/schema/type-workflows.js +1 -104
  263. package/dist/core/search/background-refresh.js +2 -286
  264. package/dist/core/search/bm25.js +1 -146
  265. package/dist/core/search/cache.js +2 -534
  266. package/dist/core/search/corpus.js +1 -311
  267. package/dist/core/search/embedding-batches.js +1 -163
  268. package/dist/core/search/eval.js +1 -225
  269. package/dist/core/search/http-client.js +1 -75
  270. package/dist/core/search/providers.js +1 -242
  271. package/dist/core/search/relevance.js +1 -244
  272. package/dist/core/search/semantic-defaults.js +1 -199
  273. package/dist/core/search/staleness.js +1 -30
  274. package/dist/core/search/vector-stores.js +2 -664
  275. package/dist/core/search/vectorization-metadata.js +1 -81
  276. package/dist/core/sentry/helpers.js +1 -272
  277. package/dist/core/sentry/instrument.js +1 -387
  278. package/dist/core/session/session-state.js +1 -260
  279. package/dist/core/shared/agent-session-context.js +1 -133
  280. package/dist/core/shared/author.js +1 -1172
  281. package/dist/core/shared/command-types.js +1 -4
  282. package/dist/core/shared/conflict-markers.js +1 -31
  283. package/dist/core/shared/constants.js +1 -405
  284. package/dist/core/shared/errors.js +1 -20
  285. package/dist/core/shared/html-entity-decode.js +1 -131
  286. package/dist/core/shared/index.js +1 -12
  287. package/dist/core/shared/item-metadata-contract.js +1 -89
  288. package/dist/core/shared/lazy-module.js +1 -16
  289. package/dist/core/shared/levenshtein.js +1 -61
  290. package/dist/core/shared/memo.js +1 -19
  291. package/dist/core/shared/numeric-parsers.js +1 -20
  292. package/dist/core/shared/option-alias-visibility.js +1 -67
  293. package/dist/core/shared/primitives.js +1 -127
  294. package/dist/core/shared/serial-queue.js +1 -79
  295. package/dist/core/shared/serialization.js +1 -210
  296. package/dist/core/shared/split-comma-list.js +1 -30
  297. package/dist/core/shared/text-normalization.js +1 -38
  298. package/dist/core/shared/time.js +1 -306
  299. package/dist/core/store/index.js +1 -12
  300. package/dist/core/store/item-format-migration.js +1 -125
  301. package/dist/core/store/item-metadata-cache.js +1 -1116
  302. package/dist/core/store/item-metadata-query-index.js +9 -394
  303. package/dist/core/store/item-metadata-read-work.js +1 -43
  304. package/dist/core/store/item-store.js +1 -693
  305. package/dist/core/store/paths.d.ts +1 -1
  306. package/dist/core/store/paths.js +1 -214
  307. package/dist/core/store/settings-read-cache.js +1 -85
  308. package/dist/core/store/settings-validator.d.ts +1 -0
  309. package/dist/core/store/settings-validator.js +1 -421
  310. package/dist/core/store/settings.js +3 -1309
  311. package/dist/core/store/tracker-preflight.js +1 -141
  312. package/dist/core/telemetry/consent.js +5 -108
  313. package/dist/core/telemetry/observability.js +1 -246
  314. package/dist/core/telemetry/runtime.js +4 -1988
  315. package/dist/core/test/background-runs.js +4 -945
  316. package/dist/core/test/item-test-run-tracking.js +1 -63
  317. package/dist/core/test/run-selectors.js +1 -120
  318. package/dist/core/validate/estimate-defaults.js +1 -89
  319. package/dist/core/validate/fix-planning.js +1 -189
  320. package/dist/core/validate/linked-artifact-reference.js +1 -36
  321. package/dist/core/validate/missing-by-type.js +1 -34
  322. package/dist/core/validate/missing-link-owners.js +1 -95
  323. package/dist/core/validate/stale-file-classification.js +1 -82
  324. package/dist/mcp/http-server.js +5 -448
  325. package/dist/mcp/legacy-adapter.js +1 -77
  326. package/dist/mcp/runtime-capabilities.js +1 -200
  327. package/dist/mcp/server.js +4 -1233
  328. package/dist/mcp/tool-definitions.js +1 -804
  329. package/dist/sdk/actionability.js +1 -13
  330. package/dist/sdk/agent/closed-domain-contracts.js +1 -161
  331. package/dist/sdk/agent/command-recovery.js +1 -59
  332. package/dist/sdk/agent/command-suggestions.js +1 -66
  333. package/dist/sdk/agent/create-option-policy.js +1 -31
  334. package/dist/sdk/agent/identity-config.js +1 -106
  335. package/dist/sdk/agent/item-addressing.js +1 -207
  336. package/dist/sdk/agent/refusal-closure-census.js +1 -151
  337. package/dist/sdk/agent/refusal-closure.js +1 -133
  338. package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
  339. package/dist/sdk/agent/refusal-reachability.js +1 -593
  340. package/dist/sdk/agent/subcommand-recovery.js +1 -83
  341. package/dist/sdk/agent/task-transcript-contracts.js +1 -197
  342. package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
  343. package/dist/sdk/agent-capability-contracts.js +1 -428
  344. package/dist/sdk/agent-session-context.js +1 -9
  345. package/dist/sdk/annotations.js +1 -448
  346. package/dist/sdk/author-attribution.js +1 -468
  347. package/dist/sdk/authoring.js +1 -20
  348. package/dist/sdk/cli-bootstrap.js +1 -838
  349. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
  350. package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
  351. package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
  352. package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
  353. package/dist/sdk/cli-contracts/command-aliases.js +1 -107
  354. package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
  355. package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
  356. package/dist/sdk/cli-contracts/commander-types.js +1 -159
  357. package/dist/sdk/cli-contracts/completeness.js +1 -393
  358. package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
  359. package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
  360. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
  361. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
  362. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
  363. package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
  364. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
  365. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
  366. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
  367. package/dist/sdk/cli-contracts/string-lists.js +1 -16
  368. package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
  369. package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
  370. package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
  371. package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
  372. package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
  373. package/dist/sdk/cli-contracts.d.ts +1 -1
  374. package/dist/sdk/cli-contracts.js +1 -17
  375. package/dist/sdk/cli-program.js +1 -49
  376. package/dist/sdk/command-line.d.ts +2 -5
  377. package/dist/sdk/command-line.js +1 -78
  378. package/dist/sdk/comments.js +1 -133
  379. package/dist/sdk/compile-cache.js +1 -73
  380. package/dist/sdk/completion.js +174 -839
  381. package/dist/sdk/compose.js +1 -1090
  382. package/dist/sdk/config.js +1 -1204
  383. package/dist/sdk/context/recency.js +1 -33
  384. package/dist/sdk/context/semantic-session-attribution.js +1 -82
  385. package/dist/sdk/context/usage-egress.js +1 -29
  386. package/dist/sdk/context/usage-ledger.js +3 -185
  387. package/dist/sdk/context-intent-contracts.js +1 -709
  388. package/dist/sdk/context-intent-runtime.js +1 -115
  389. package/dist/sdk/context-packing.js +1 -218
  390. package/dist/sdk/context-relevance.js +1 -503
  391. package/dist/sdk/context-signal-store.js +2 -426
  392. package/dist/sdk/context-usage.js +1 -367
  393. package/dist/sdk/contracts.js +1 -23
  394. package/dist/sdk/core-governance.js +1 -14
  395. package/dist/sdk/core.js +1 -14
  396. package/dist/sdk/corpus-shape.js +1 -401
  397. package/dist/sdk/define.js +1 -220
  398. package/dist/sdk/dependencies.js +1 -718
  399. package/dist/sdk/dependency-flag-validation.js +1 -156
  400. package/dist/sdk/dependency-provenance.js +1 -135
  401. package/dist/sdk/docs.js +1 -14
  402. package/dist/sdk/duplicates.js +1 -40
  403. package/dist/sdk/environment/agent-environment.js +1 -466
  404. package/dist/sdk/environment/host-environment-errors.js +1 -8
  405. package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
  406. package/dist/sdk/environment/source-context.js +1 -28
  407. package/dist/sdk/environment/tracker-preflight.js +1 -9
  408. package/dist/sdk/error-code-catalog.js +1 -153
  409. package/dist/sdk/error-runtime.js +1 -58
  410. package/dist/sdk/errors.js +1 -58
  411. package/dist/sdk/eval.js +1 -190
  412. package/dist/sdk/extension/author-manifest.js +1 -92
  413. package/dist/sdk/extension/bundled-catalog.js +1 -332
  414. package/dist/sdk/extension/concurrency.js +1 -25
  415. package/dist/sdk/extension/copy-scope.d.ts +2 -0
  416. package/dist/sdk/extension/copy-scope.js +2 -0
  417. package/dist/sdk/extension/custom-field-collisions.js +1 -30
  418. package/dist/sdk/extension/describe.js +3 -189
  419. package/dist/sdk/extension/doctor.js +1 -606
  420. package/dist/sdk/extension/install-plan.d.ts +69 -0
  421. package/dist/sdk/extension/install-plan.js +2 -0
  422. package/dist/sdk/extension/install-receipts.d.ts +7 -0
  423. package/dist/sdk/extension/install-receipts.js +2 -0
  424. package/dist/sdk/extension/install-runtime.js +3 -313
  425. package/dist/sdk/extension/install-snapshot.js +1 -66
  426. package/dist/sdk/extension/install-sources.js +5 -1057
  427. package/dist/sdk/extension/managed-state.js +2 -252
  428. package/dist/sdk/extension/migrations.js +2 -174
  429. package/dist/sdk/extension/output-ownership.js +1 -25
  430. package/dist/sdk/extension/runtime-summary.js +1 -18
  431. package/dist/sdk/extension/scaffold.js +4 -2308
  432. package/dist/sdk/extension/shared.js +1 -147
  433. package/dist/sdk/extension/source-resolution.js +1 -65
  434. package/dist/sdk/extension/update-check.js +1 -67
  435. package/dist/sdk/extension-command-context.js +1 -44
  436. package/dist/sdk/extension-contracts.js +1 -73
  437. package/dist/sdk/extension.d.ts +7 -2
  438. package/dist/sdk/extension.js +1 -2196
  439. package/dist/sdk/files.js +1 -535
  440. package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
  441. package/dist/sdk/flag-invocation-contracts.js +1 -344
  442. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
  443. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
  444. package/dist/sdk/generated-error-code-catalog.js +1 -16
  445. package/dist/sdk/governance/assurance-action-contracts.js +1 -4
  446. package/dist/sdk/governance/assurance-action.js +1 -411
  447. package/dist/sdk/governance/assurance-limits.js +1 -10
  448. package/dist/sdk/governance/assurance-mutation-error.js +1 -81
  449. package/dist/sdk/governance/assurance-presets.js +1 -135
  450. package/dist/sdk/governance/assurance-runtime.js +1 -238
  451. package/dist/sdk/governance/assurance.js +4 -1182
  452. package/dist/sdk/governance/boundary-fixtures.js +1 -200
  453. package/dist/sdk/governance/coverage-assurance.js +1 -60
  454. package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
  455. package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
  456. package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
  457. package/dist/sdk/governance/defect-recurrence.js +1 -623
  458. package/dist/sdk/governance/extension-host-version.js +1 -115
  459. package/dist/sdk/governance/gc.js +1 -368
  460. package/dist/sdk/governance/health.js +1 -2367
  461. package/dist/sdk/governance/hierarchy-validation.js +1 -108
  462. package/dist/sdk/governance/linked-file-report.js +1 -71
  463. package/dist/sdk/governance/merge-receipt-history.js +1 -206
  464. package/dist/sdk/governance/provenance-health.js +1 -282
  465. package/dist/sdk/governance/reindex.js +4 -761
  466. package/dist/sdk/governance/stale-work.js +1 -82
  467. package/dist/sdk/governance/status-role-diagnostics.js +1 -35
  468. package/dist/sdk/governance/storage-integrity.js +1 -280
  469. package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
  470. package/dist/sdk/governance/upgrade.js +2 -327
  471. package/dist/sdk/governance/validate-history-drift.js +1 -81
  472. package/dist/sdk/governance/validate-item-reader.js +1 -17
  473. package/dist/sdk/governance/validate-normalization.js +1 -36
  474. package/dist/sdk/governance/validate.d.ts +3 -1
  475. package/dist/sdk/governance/validate.js +1 -2261
  476. package/dist/sdk/governance/workflow-completeness.d.ts +32 -0
  477. package/dist/sdk/governance/workflow-completeness.js +2 -0
  478. package/dist/sdk/governance/workflow-policy.d.ts +47 -0
  479. package/dist/sdk/governance/workflow-policy.js +4 -0
  480. package/dist/sdk/governance/workspace-position.js +1 -163
  481. package/dist/sdk/governance.d.ts +2 -0
  482. package/dist/sdk/governance.js +1 -31
  483. package/dist/sdk/graph/adapter.js +1 -181
  484. package/dist/sdk/graph/analytics.js +1 -474
  485. package/dist/sdk/graph/assembly.js +1 -377
  486. package/dist/sdk/graph/cache.js +1 -160
  487. package/dist/sdk/graph/centrality.js +1 -258
  488. package/dist/sdk/graph/conformance.js +1 -130
  489. package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
  490. package/dist/sdk/graph/deadline-scheduling.js +2 -0
  491. package/dist/sdk/graph/durable-cache.d.ts +1 -1
  492. package/dist/sdk/graph/durable-cache.js +1 -361
  493. package/dist/sdk/graph/governance-contracts.js +1 -34
  494. package/dist/sdk/graph/governance.d.ts +13 -1
  495. package/dist/sdk/graph/governance.js +1 -735
  496. package/dist/sdk/graph/hierarchy-integrity.js +1 -310
  497. package/dist/sdk/graph/index.d.ts +3 -2
  498. package/dist/sdk/graph/index.js +1 -26
  499. package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
  500. package/dist/sdk/graph/lifecycle-coverage.js +2 -0
  501. package/dist/sdk/graph/mutation-advisory.js +1 -176
  502. package/dist/sdk/graph/remediation.js +1 -197
  503. package/dist/sdk/graph/run.d.ts +15 -1
  504. package/dist/sdk/graph/run.js +1 -768
  505. package/dist/sdk/graph/scheduling.js +1 -124
  506. package/dist/sdk/graph/traversal.js +1 -284
  507. package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
  508. package/dist/sdk/graph.js +1 -15
  509. package/dist/sdk/guide-topics.js +1 -707
  510. package/dist/sdk/guide.js +1 -279
  511. package/dist/sdk/history/maintenance.d.ts +71 -0
  512. package/dist/sdk/history/maintenance.js +2 -0
  513. package/dist/sdk/history/salvage.js +2 -247
  514. package/dist/sdk/history/subject.d.ts +19 -0
  515. package/dist/sdk/history/subject.js +2 -0
  516. package/dist/sdk/history-analytics.js +1 -282
  517. package/dist/sdk/history-compact.js +1 -527
  518. package/dist/sdk/history-mcp.js +1 -68
  519. package/dist/sdk/history-provenance.js +1 -182
  520. package/dist/sdk/history-read.js +1 -96
  521. package/dist/sdk/history-redact.d.ts +1 -14
  522. package/dist/sdk/history-redact.js +1 -643
  523. package/dist/sdk/history-repair.d.ts +5 -0
  524. package/dist/sdk/history-repair.js +1 -657
  525. package/dist/sdk/improvement-ledger-validation.js +1 -62
  526. package/dist/sdk/improvement-ledger.js +2 -257
  527. package/dist/sdk/index.d.ts +4 -1
  528. package/dist/sdk/index.js +1 -183
  529. package/dist/sdk/init-agent-guidance.js +2 -496
  530. package/dist/sdk/init.js +2 -820
  531. package/dist/sdk/invocation-author.js +1 -39
  532. package/dist/sdk/item-children.js +1 -90
  533. package/dist/sdk/item-metadata-index.js +1 -15
  534. package/dist/sdk/item-schedule.js +1 -27
  535. package/dist/sdk/item-transaction.js +1 -396
  536. package/dist/sdk/learnings.js +1 -29
  537. package/dist/sdk/lifecycle/append.js +2 -53
  538. package/dist/sdk/lifecycle/claim.d.ts +2 -0
  539. package/dist/sdk/lifecycle/claim.js +1 -242
  540. package/dist/sdk/lifecycle/close-many.js +1 -438
  541. package/dist/sdk/lifecycle/close.js +1 -468
  542. package/dist/sdk/lifecycle/copy.js +1 -212
  543. package/dist/sdk/lifecycle/create.js +1 -1949
  544. package/dist/sdk/lifecycle/delete.js +1 -45
  545. package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
  546. package/dist/sdk/lifecycle/focus.js +1 -91
  547. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
  548. package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
  549. package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
  550. package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
  551. package/dist/sdk/lifecycle/mcp-actions.js +1 -51
  552. package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
  553. package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
  554. package/dist/sdk/lifecycle/plan.js +1 -1606
  555. package/dist/sdk/lifecycle/recurrence-parsers.d.ts +1 -1
  556. package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
  557. package/dist/sdk/lifecycle/reopen.js +1 -68
  558. package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
  559. package/dist/sdk/lifecycle/restore.d.ts +1 -0
  560. package/dist/sdk/lifecycle/restore.js +1 -330
  561. package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
  562. package/dist/sdk/lifecycle/update-many.js +1 -861
  563. package/dist/sdk/lifecycle/update.js +1 -2136
  564. package/dist/sdk/lifecycle-completion.js +1 -92
  565. package/dist/sdk/lifecycle-policy.js +1 -120
  566. package/dist/sdk/linked-artifacts.js +1 -530
  567. package/dist/sdk/mcp/apps.js +4 -133
  568. package/dist/sdk/mcp/authorization.js +1 -404
  569. package/dist/sdk/mcp/discovery.js +1 -494
  570. package/dist/sdk/mcp/interactions.js +1 -336
  571. package/dist/sdk/mcp/protocol.d.ts +7 -0
  572. package/dist/sdk/mcp/protocol.js +1 -184
  573. package/dist/sdk/mcp/skills.js +1 -389
  574. package/dist/sdk/mcp/subscriptions.js +1 -211
  575. package/dist/sdk/mcp/tasks.js +2 -430
  576. package/dist/sdk/mcp/transport.js +1 -260
  577. package/dist/sdk/merge/abandoned-receipts.js +1 -46
  578. package/dist/sdk/merge/driver.js +1 -212
  579. package/dist/sdk/merge/index.js +1 -16
  580. package/dist/sdk/merge/install.js +3 -561
  581. package/dist/sdk/merge/receipt-file-boundary.js +1 -46
  582. package/dist/sdk/merge/receipt-operation.js +1 -96
  583. package/dist/sdk/merge/receipt-schema.js +1 -397
  584. package/dist/sdk/merge/receipts.js +4 -525
  585. package/dist/sdk/merge/reconcile.js +1 -352
  586. package/dist/sdk/merge/three-way.js +3 -775
  587. package/dist/sdk/merge.js +1 -10
  588. package/dist/sdk/mutation-events.js +1 -292
  589. package/dist/sdk/mutation-guard.js +1 -216
  590. package/dist/sdk/notes.js +1 -139
  591. package/dist/sdk/output-contracts.js +1 -172
  592. package/dist/sdk/output-projection.js +1 -430
  593. package/dist/sdk/output-token-accounting.js +1 -140
  594. package/dist/sdk/output.js +1 -64
  595. package/dist/sdk/ownership-source.js +1 -21
  596. package/dist/sdk/package-import-adapters.js +1 -442
  597. package/dist/sdk/package-migrations.js +1 -20
  598. package/dist/sdk/package-runtime-options.js +1 -80
  599. package/dist/sdk/pagination.js +1 -162
  600. package/dist/sdk/profile.js +1 -454
  601. package/dist/sdk/provenance.js +1 -258
  602. package/dist/sdk/public-surface.json +1 -1
  603. package/dist/sdk/query/activity.js +1 -401
  604. package/dist/sdk/query/aggregate.d.ts +16 -0
  605. package/dist/sdk/query/aggregate.js +1 -390
  606. package/dist/sdk/query/calendar.js +1 -964
  607. package/dist/sdk/query/complete-list.js +1 -215
  608. package/dist/sdk/query/context.js +1 -1702
  609. package/dist/sdk/query/duplicate-candidates.js +1 -70
  610. package/dist/sdk/query/get.js +1 -450
  611. package/dist/sdk/query/history.js +1 -186
  612. package/dist/sdk/query/item-filter-options.js +1 -9
  613. package/dist/sdk/query/light-metadata.js +1 -18
  614. package/dist/sdk/query/list-filter-shared.js +1 -81
  615. package/dist/sdk/query/list.js +1 -1304
  616. package/dist/sdk/query/multi-value-filters.js +1 -78
  617. package/dist/sdk/query/next.js +1 -513
  618. package/dist/sdk/query/parsers.js +1 -44
  619. package/dist/sdk/query/projection-contracts.js +1 -184
  620. package/dist/sdk/query/search-contracts.d.ts +27 -0
  621. package/dist/sdk/query/search-contracts.js +1 -230
  622. package/dist/sdk/query/search-pagination.js +1 -35
  623. package/dist/sdk/query/search-rendering.js +1 -105
  624. package/dist/sdk/query/search.d.ts +6 -4
  625. package/dist/sdk/query/search.js +2 -1987
  626. package/dist/sdk/query.js +1 -35
  627. package/dist/sdk/read-output/continuation.js +1 -194
  628. package/dist/sdk/read-output-budget.js +1 -135
  629. package/dist/sdk/read-output-contracts.d.ts +1 -1
  630. package/dist/sdk/read-output-contracts.js +1 -1225
  631. package/dist/sdk/read-output-rows.js +1 -186
  632. package/dist/sdk/read-output-session.js +1 -208
  633. package/dist/sdk/relationship-analytics.js +1 -410
  634. package/dist/sdk/relationship-context.js +1 -284
  635. package/dist/sdk/relationship-history.js +4 -519
  636. package/dist/sdk/relationship-kinds/contract.js +1 -22
  637. package/dist/sdk/relationship-migration.js +1 -77
  638. package/dist/sdk/relationships.js +1 -579
  639. package/dist/sdk/reproducibility/process.js +1 -87
  640. package/dist/sdk/runtime-action-aliases.js +1 -59
  641. package/dist/sdk/runtime-extended-actions.js +1 -177
  642. package/dist/sdk/runtime-input.js +1 -614
  643. package/dist/sdk/runtime-primitives.js +1 -84
  644. package/dist/sdk/runtime-public-contracts.d.ts +2 -1
  645. package/dist/sdk/runtime-public-contracts.js +1 -4
  646. package/dist/sdk/runtime-stats-options.js +1 -38
  647. package/dist/sdk/runtime.d.ts +4 -0
  648. package/dist/sdk/runtime.js +1 -1928
  649. package/dist/sdk/scheduling-shortcuts.js +1 -63
  650. package/dist/sdk/schema-migration.js +3 -856
  651. package/dist/sdk/schema.d.ts +2 -1
  652. package/dist/sdk/schema.js +1 -1376
  653. package/dist/sdk/search-refresh-worker.js +1 -18
  654. package/dist/sdk/similarity-scoring.js +1 -53
  655. package/dist/sdk/similarity.js +1 -326
  656. package/dist/sdk/start-task-status.js +1 -14
  657. package/dist/sdk/stats.js +1 -270
  658. package/dist/sdk/structured-mutations.js +1 -580
  659. package/dist/sdk/telemetry-flush.js +1 -13
  660. package/dist/sdk/telemetry.js +1 -405
  661. package/dist/sdk/templates.js +2 -292
  662. package/dist/sdk/test/batch.js +2 -509
  663. package/dist/sdk/test/entry.js +1 -70
  664. package/dist/sdk/test/execution.js +6 -2211
  665. package/dist/sdk/test/linked-command-detection.js +1 -546
  666. package/dist/sdk/test/measurements.js +1 -91
  667. package/dist/sdk/test/parsers.js +1 -545
  668. package/dist/sdk/test/runs.js +1 -193
  669. package/dist/sdk/test/trust.js +2 -206
  670. package/dist/sdk/testing.js +4 -1391
  671. package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
  672. package/dist/sdk/traceability/source-traceability.js +1 -292
  673. package/dist/sdk/tracker-root-discovery.js +1 -9
  674. package/dist/sdk/workspace-contracts-cache.js +1 -28
  675. package/dist/sdk/workspace-contracts.js +1 -33
  676. package/dist/sdk/workspace-memory.js +2 -318
  677. package/dist/sdk/workspace-recipe.js +1 -71
  678. package/dist/sdk/workspace-snapshot.js +4 -613
  679. package/dist/sdk/workspace-transaction-gc.js +1 -149
  680. package/dist/sdk/workspace-transaction.js +2 -363
  681. package/dist/sdk/workspace.js +3 -127
  682. package/dist/types/index.js +1 -9
  683. package/dist/types.d.ts +4 -0
  684. package/dist/types.js +1 -245
  685. package/docs/AGENT_GUIDE.md +1 -1
  686. package/docs/COMMANDS.md +10 -0
  687. package/docs/CONFIGURATION.md +12 -1
  688. package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
  689. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
  690. package/docs/EXTENSIONS.md +1 -0
  691. package/docs/HISTORY_MAINTENANCE.md +125 -0
  692. package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
  693. package/docs/PACKAGE_EVIDENCE.md +92 -0
  694. package/docs/PLANNING_MEASUREMENTS.md +183 -0
  695. package/docs/README.md +4 -0
  696. package/docs/READ_OUTPUT_CONTRACTS.md +5 -0
  697. package/docs/SCRIPTING.md +21 -0
  698. package/docs/TESTING.md +33 -0
  699. package/docs/WORKFLOW_POLICIES.md +129 -0
  700. package/docs/generated/FLAG_LEXICON_BUDGETS.md +7 -7
  701. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -5
  702. package/marketplace.json +2 -2
  703. package/package.json +5 -5
  704. package/packages/pm-beads/package.json +1 -1
  705. package/packages/pm-calendar/package.json +1 -1
  706. package/packages/pm-command-kit/package.json +1 -1
  707. package/packages/pm-digital-twin/package.json +1 -1
  708. package/packages/pm-governance-audit/package.json +1 -1
  709. package/packages/pm-guide-shell/package.json +1 -1
  710. package/packages/pm-kanban/package.json +1 -1
  711. package/packages/pm-lifecycle-hooks/package.json +1 -1
  712. package/packages/pm-linked-test-adapters/package.json +1 -1
  713. package/packages/pm-search-advanced/package.json +1 -1
  714. package/packages/pm-templates/package.json +1 -1
  715. package/packages/pm-todos/package.json +1 -1
  716. package/packages/pm-vcs/package.json +1 -1
  717. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  718. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  719. package/scripts/finalize-build.mjs +45 -3
  720. package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
  721. package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
  722. package/dist/cli-bundle/chunks/chunk-JX4DH4WC.js +0 -3
  723. package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
  724. package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
  725. package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
  726. package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
  727. package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
  728. package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
  729. package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
  730. package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
  731. package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +0 -2
  732. package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
  733. package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
  734. package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
  735. package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
  736. package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
  737. package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
  738. package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
  739. package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
  740. package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
  741. package/dist/cli-bundle/focused-chunks/chunk-PEFABF7E.js +0 -26
  742. package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
  743. package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
  744. package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
  745. package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
  746. package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
@@ -1,1703 +1,2 @@
1
- /**
2
- * @module sdk/query/context
3
- *
4
- * Implements the pm context command surface and its agent-facing runtime behavior.
5
- */
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]="4f8e82a2-f4ea-5ecb-8ef5-3ca795cdeda5")}catch(e){}}();
8
- import { SETTINGS_DEFAULTS, EXIT_CODE, PmCliError, compareTimestampStrings, nowIso, isTerminalStatus, normalizeStatusForRegistry, normalizeStatusInput, resolveRuntimeStatusRegistry, resolvePmRoot, readSettings, resolveAuthor, discoverExtensions, resolveItemTypeRegistry, } from "../runtime-primitives.js";
9
- import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
10
- import { collectDependencyBlockedIds, resolveItemBlockers, resolveItemExecutionRole, computeActionabilityReport, } from "../actionability.js";
11
- import { CONTEXT_DEPTH_VALUES, CONTEXT_SECTION_VALUES, } from "../../types/index.js";
12
- import { parseIntegerLimit } from "./parsers.js";
13
- import { runCalendar, } from "./calendar.js";
14
- import { runList } from "./list.js";
15
- import { runActivity } from "./activity.js";
16
- import { scoreContextCandidatesWithActiveExtensions, } from "../context-relevance.js";
17
- export { buildItemContextRelevanceCandidates } from "../context-relevance.js";
18
- import { createQueryFingerprint, encodeQueryCursor, resolveQueryCursorStart, selectCursorSemanticOptions, } from "../pagination.js";
19
- import { CONTEXT_FLAG_CONTRACTS } from "../cli-contracts/flag-contracts.js";
20
- import { packContextCandidates, } from "../context-packing.js";
21
- import { attachContextUsageServingReceipt, collectContextUsageDeliveredItemIds, readContextUsageAffinity, recordContextUsageServing, } from "../context-usage.js";
22
- import { readWorkspaceContextSignals, } from "../context-signal-store.js";
23
- import { readWorkspaceMemory, selectWorkspaceMemory, } from "../workspace-memory.js";
24
- import { detectAgentIdentity } from "../../core/shared/author.js";
25
- import { readSessionState, semanticAttributionKey, } from "../../core/session/session-state.js";
26
- import { semanticAttributionAffinity } from "../context/semantic-session-attribution.js";
27
- // ---------------------------------------------------------------------------
28
- // Output format
29
- // ---------------------------------------------------------------------------
30
- /** Supported values accepted by the context output contract. */
31
- export const CONTEXT_OUTPUT_VALUES = [
32
- "markdown",
33
- "toon",
34
- "json",
35
- "ndjson",
36
- ];
37
- // ---------------------------------------------------------------------------
38
- // Constants
39
- // ---------------------------------------------------------------------------
40
- const HIGH_LEVEL_TYPES = new Set(["Epic", "Feature"]);
41
- const DEFAULT_CONTEXT_LIMIT = 10;
42
- const CONTEXT_SCALE_THRESHOLD = 10_000;
43
- const STANDARD_SECTIONS = [
44
- "hierarchy",
45
- "activity",
46
- "progress",
47
- "recently_created",
48
- "unparented",
49
- "workload",
50
- ];
51
- const DEEP_SECTIONS = [
52
- ...STANDARD_SECTIONS,
53
- "blockers",
54
- "files",
55
- "staleness",
56
- "tests",
57
- ];
58
- const LEADING_HYPHEN_DATE = /^(\d{4})-(\d{2})-(\d{2})/;
59
- const LEADING_COMPACT_DATE = /^(\d{4})(\d{2})(\d{2})(?:[T ]?\d{2}|$)/;
60
- const COMPACT_DATE = /^(\d{4})(\d{2})(\d{2})$/;
61
- const COMPACT_DATETIME = /^(\d{4})(\d{2})(\d{2})(?:[T\s]?)(\d{2})(\d{2})(\d{2})?(Z|[+-]\d{2}:?\d{2})?$/i;
62
- // ---------------------------------------------------------------------------
63
- // Parsers
64
- // ---------------------------------------------------------------------------
65
- function parseOutputFormat(raw) {
66
- if (!raw)
67
- return undefined;
68
- const normalized = raw.trim().toLowerCase();
69
- if (!CONTEXT_OUTPUT_VALUES.includes(normalized)) {
70
- throw new PmCliError("Context format must be one of markdown|toon|json|ndjson", EXIT_CODE.USAGE);
71
- }
72
- return normalized;
73
- }
74
- // Fields selectable by `pm context --fields` for focus-row projection. Every
75
- // ContextFocusItem scalar plus `created_at` (carried by recently-created rows)
76
- // is addressable; unknown names are rejected with a usage hint.
77
- const FOCUS_PROJECTION_FIELDS = new Set([
78
- "id",
79
- "title",
80
- "type",
81
- "status",
82
- "priority",
83
- "order",
84
- "deadline",
85
- "assignee",
86
- "tags",
87
- "tags_inherited",
88
- "updated_at",
89
- "parent",
90
- "children_total",
91
- "children_closed",
92
- "completion_pct",
93
- "blocked",
94
- "blocker_ids",
95
- "created_at",
96
- ]);
97
- /** Parses the comma-separated `--fields` value into a validated, de-duplicated focus-row projection list. Returns undefined when no projection was requested. */
98
- export function parseContextFocusFields(raw) {
99
- if (raw === undefined)
100
- return undefined;
101
- const fields = [];
102
- for (const token of raw.split(",")) {
103
- const normalized = token.trim().toLowerCase();
104
- if (normalized.length === 0)
105
- continue;
106
- if (!FOCUS_PROJECTION_FIELDS.has(normalized)) {
107
- throw new PmCliError(`Context --fields value not projectable: ${normalized} (valid: ${[...FOCUS_PROJECTION_FIELDS].join(", ")})`, EXIT_CODE.USAGE);
108
- }
109
- if (!fields.includes(normalized))
110
- fields.push(normalized);
111
- }
112
- if (fields.length === 0) {
113
- throw new PmCliError("Context --fields requires at least one field name", EXIT_CODE.USAGE);
114
- }
115
- return fields;
116
- }
117
- /** Projects focus rows onto the requested field subset, preserving field order so the rendered/serialized output mirrors the `--fields` argument. */
118
- export function projectContextFocusRows(rows, fields) {
119
- return rows.map((row) => {
120
- const projected = {};
121
- const source = row;
122
- for (const field of fields) {
123
- projected[field] = source[field] ?? null;
124
- }
125
- return projected;
126
- });
127
- }
128
- /** Implements resolve context output format for the public runtime surface of this module. */
129
- export function resolveContextOutputFormat(options, global) {
130
- const commandFormat = parseOutputFormat(options.format);
131
- if (global.json &&
132
- commandFormat &&
133
- commandFormat !== "json" &&
134
- commandFormat !== "ndjson") {
135
- throw new PmCliError("Cannot combine --json with --format markdown|toon", EXIT_CODE.USAGE);
136
- }
137
- if (global.json) {
138
- return commandFormat === "ndjson" ? "ndjson" : "json";
139
- }
140
- return commandFormat ?? "toon";
141
- }
142
- // --depth full surfaces the entire backlog: when no explicit --limit is given,
143
- // every section returns all rows instead of the default top-N sample.
144
- function parseContextLimit(raw, depth) {
145
- return (parseIntegerLimit(raw, "--limit") ??
146
- (depth === "full" ? Number.MAX_SAFE_INTEGER : DEFAULT_CONTEXT_LIMIT));
147
- }
148
- /** Resolve a positive context-packing budget from CLI or SDK input. */
149
- export function resolveContextTokenBudget(raw, fallback) {
150
- if (raw === undefined)
151
- return fallback;
152
- const parsed = typeof raw === "number" ? raw : Number(raw);
153
- if (!Number.isInteger(parsed) || parsed < 1) {
154
- throw new PmCliError("--token-budget must be a positive integer", EXIT_CODE.USAGE);
155
- }
156
- return parsed;
157
- }
158
- function resolveContextLimitAtScale(limit, itemCount) {
159
- return itemCount >= CONTEXT_SCALE_THRESHOLD &&
160
- limit === Number.MAX_SAFE_INTEGER
161
- ? DEFAULT_CONTEXT_LIMIT
162
- : limit;
163
- }
164
- /** Implements parse context depth for the public runtime surface of this module. */
165
- export function parseContextDepth(raw, settings) {
166
- if (!raw)
167
- return settings.default_depth;
168
- const normalized = raw.trim().toLowerCase();
169
- if (!CONTEXT_DEPTH_VALUES.includes(normalized)) {
170
- throw new PmCliError(`Context --depth must be one of ${CONTEXT_DEPTH_VALUES.join("|")}`, EXIT_CODE.USAGE);
171
- }
172
- return normalized;
173
- }
174
- /** Implements parse context sections for the public runtime surface of this module. */
175
- export function parseContextSections(raw, depth, settings) {
176
- if (raw && raw.length > 0) {
177
- const sections = [];
178
- for (const value of raw) {
179
- const normalized = value.trim().toLowerCase();
180
- if (!CONTEXT_SECTION_VALUES.includes(normalized)) {
181
- throw new PmCliError(`Context --section must be one of ${CONTEXT_SECTION_VALUES.join("|")}`, EXIT_CODE.USAGE);
182
- }
183
- if (!sections.includes(normalized)) {
184
- sections.push(normalized);
185
- }
186
- }
187
- return sections;
188
- }
189
- if (depth === "brief")
190
- return [];
191
- // --depth full is the comprehensive snapshot: every known section, regardless
192
- // of the per-section settings toggles that brief/standard/deep respect.
193
- if (depth === "full")
194
- return [...CONTEXT_SECTION_VALUES];
195
- const pool = depth === "deep" ? DEEP_SECTIONS : STANDARD_SECTIONS;
196
- return pool.filter((section) => settings.sections[section]);
197
- }
198
- function parseActivityLimit(raw, settings) {
199
- if (!raw)
200
- return settings.activity_limit;
201
- const parsed = parseIntegerLimit(raw, "--activity-limit");
202
- /* c8 ignore start -- parseIntegerLimit either throws or returns a number; fallback is defensive typing guard */
203
- return parsed ?? settings.activity_limit;
204
- /* c8 ignore stop */
205
- }
206
- function parseStaleThresholdDays(raw, settings) {
207
- if (!raw)
208
- return settings.stale_threshold_days;
209
- const trimmed = raw.trim().toLowerCase();
210
- const match = /^(\d+)d?$/.exec(trimmed);
211
- if (!match) {
212
- throw new PmCliError("--stale-threshold must be a number of days (e.g. 7 or 7d)", EXIT_CODE.USAGE);
213
- }
214
- const days = parseInt(match[1], 10);
215
- if (days <= 0) {
216
- throw new PmCliError("--stale-threshold must be positive", EXIT_CODE.USAGE);
217
- }
218
- return days;
219
- }
220
- // ---------------------------------------------------------------------------
221
- // Status helpers
222
- // ---------------------------------------------------------------------------
223
- function statusRank(status, statusRegistry) {
224
- const normalizedStatus = normalizeStatusForRegistry(status, statusRegistry);
225
- const blockedStatus = normalizeStatusInput("blocked", statusRegistry);
226
- const draftStatus = normalizeStatusInput("draft", statusRegistry);
227
- if (normalizedStatus === statusRegistry.in_progress_status)
228
- return 0;
229
- if (statusRegistry.active_statuses.has(normalizedStatus))
230
- return 1;
231
- if (blockedStatus && normalizedStatus === blockedStatus)
232
- return 2;
233
- if (draftStatus && normalizedStatus === draftStatus)
234
- return 3;
235
- if (statusRegistry.blocked_statuses.has(normalizedStatus))
236
- return 5;
237
- if (statusRegistry.terminal_statuses.has(normalizedStatus))
238
- return 7;
239
- return 6;
240
- }
241
- function isClosedStatus(status, statusRegistry) {
242
- const closeStatus = normalizeStatusInput("closed", statusRegistry);
243
- return normalizeStatusForRegistry(status, statusRegistry) === closeStatus;
244
- }
245
- function isInProgressStatus(status, statusRegistry) {
246
- return (normalizeStatusForRegistry(status, statusRegistry) ===
247
- statusRegistry.in_progress_status);
248
- }
249
- function isOpenStatus(status, statusRegistry) {
250
- const normalizedStatus = normalizeStatusForRegistry(status, statusRegistry);
251
- return (normalizedStatus !== statusRegistry.in_progress_status &&
252
- statusRegistry.active_statuses.has(normalizedStatus));
253
- }
254
- function isBlockedStatus(status, statusRegistry) {
255
- return statusRegistry.blocked_statuses.has(normalizeStatusForRegistry(status, statusRegistry));
256
- }
257
- // Projection flags belong to list/calendar/activity output shaping and must not
258
- // leak into runContext's downstream calls, which need full ItemMetadata rows.
259
- // --parent is a context-level subtree scope computed here transitively, so it
260
- // must not reach runList (whose --parent matches direct children only).
261
- const LIST_PROJECTION_FLAGS = [
262
- "compact",
263
- "brief",
264
- "fields",
265
- "includeBody",
266
- "include_body",
267
- "parent",
268
- ];
269
- function stripListProjectionFlags(options) {
270
- const copy = {
271
- ...options,
272
- };
273
- for (const key of LIST_PROJECTION_FLAGS) {
274
- delete copy[key];
275
- }
276
- return copy;
277
- }
278
- /**
279
- * Resolves the transitive subtree (the anchor item plus every descendant via
280
- * parent links) so `--parent` can scope a snapshot to one epic/milestone. Reuses
281
- * the same {@link buildChildrenByParent}/{@link collectDescendants} helpers the
282
- * hierarchy section relies on, so subtree membership stays consistent across the
283
- * snapshot. Ids are normalized to lowercase for case-insensitive membership; the
284
- * `found` flag is false when the anchor id is absent from the corpus. Exported so
285
- * sibling read commands (e.g. `pm next`) can apply the same subtree scoping.
286
- */
287
- export function collectSubtreeIds(corpus, parentId) {
288
- const target = parentId.trim().toLowerCase();
289
- const anchor = corpus.find((item) => item.id.trim().toLowerCase() === target);
290
- if (!anchor) {
291
- return { ids: new Set(), found: false };
292
- }
293
- const childrenByParent = buildChildrenByParent(corpus);
294
- const descendants = collectDescendants(anchor.id, childrenByParent);
295
- // Store normalized ids so membership checks are case-insensitive end-to-end.
296
- const ids = new Set([anchor.id, ...descendants.map((item) => item.id)].map((id) => id.trim().toLowerCase()));
297
- return { ids, found: true };
298
- }
299
- function parseContextParent(raw) {
300
- if (raw === undefined)
301
- return undefined;
302
- const trimmed = raw.trim();
303
- if (trimmed.length === 0) {
304
- throw new PmCliError("Context --parent requires an item id", EXIT_CODE.USAGE);
305
- }
306
- return trimmed;
307
- }
308
- // ---------------------------------------------------------------------------
309
- // Sorting / mapping helpers (unchanged from original)
310
- // ---------------------------------------------------------------------------
311
- function compareOptionalOrder(left, right) {
312
- const leftValue = left ?? null;
313
- const rightValue = right ?? null;
314
- if (leftValue === null && rightValue === null)
315
- return 0;
316
- if (leftValue === null)
317
- return 1;
318
- if (rightValue === null)
319
- return -1;
320
- return leftValue - rightValue;
321
- }
322
- function compareOptionalDeadline(left, right) {
323
- const leftValue = left ?? null;
324
- const rightValue = right ?? null;
325
- if (leftValue === null && rightValue === null)
326
- return 0;
327
- if (leftValue === null)
328
- return 1;
329
- if (rightValue === null)
330
- return -1;
331
- return compareTimestampStrings(leftValue, rightValue);
332
- }
333
- function daysInUtcMonth(year, monthIndex) {
334
- return new Date(Date.UTC(year, monthIndex + 1, 0)).getUTCDate();
335
- }
336
- function hasNoInvalidDatePrefix(value) {
337
- const match = LEADING_HYPHEN_DATE.exec(value) ?? LEADING_COMPACT_DATE.exec(value);
338
- if (!match) {
339
- return true;
340
- }
341
- const year = Number.parseInt(match[1], 10);
342
- const month = Number.parseInt(match[2], 10);
343
- const day = Number.parseInt(match[3], 10);
344
- return (month >= 1 &&
345
- month <= 12 &&
346
- day >= 1 &&
347
- day <= daysInUtcMonth(year, month - 1));
348
- }
349
- function normalizeTimestampCandidate(value) {
350
- const compactDate = COMPACT_DATE.exec(value);
351
- if (compactDate) {
352
- return `${compactDate[1]}-${compactDate[2]}-${compactDate[3]}`;
353
- }
354
- const compactDateTime = COMPACT_DATETIME.exec(value);
355
- if (compactDateTime) {
356
- const [, year, month, day, hour, minute, secondRaw, offsetRaw] = compactDateTime;
357
- const second = secondRaw ? `:${secondRaw}` : "";
358
- const offset = offsetRaw && offsetRaw.length === 5 && offsetRaw !== "Z"
359
- ? `${offsetRaw.slice(0, 3)}:${offsetRaw.slice(3)}`
360
- : (offsetRaw ?? "");
361
- return `${year}-${month}-${day}T${hour}:${minute}${second}${offset}`;
362
- }
363
- return value;
364
- }
365
- function parseContextTimestampMs(value) {
366
- if (typeof value !== "string") {
367
- return Number.NaN;
368
- }
369
- const trimmed = value.trim();
370
- if (trimmed.length === 0 || !hasNoInvalidDatePrefix(trimmed)) {
371
- return Number.NaN;
372
- }
373
- const parsed = Date.parse(normalizeTimestampCandidate(trimmed));
374
- return Number.isFinite(parsed) ? parsed : Number.NaN;
375
- }
376
- function sortableTimestamp(value) {
377
- const parsed = parseContextTimestampMs(value);
378
- return Number.isFinite(parsed) ? new Date(parsed).toISOString() : "";
379
- }
380
- function dateTokenForTimestamp(value) {
381
- const parsed = parseContextTimestampMs(value);
382
- return Number.isFinite(parsed)
383
- ? new Date(parsed).toISOString().slice(0, 10)
384
- : "unknown";
385
- }
386
- function normalizedParentId(value) {
387
- if (typeof value !== "string") {
388
- return null;
389
- }
390
- const trimmed = value.trim();
391
- return trimmed.length > 0 ? trimmed : null;
392
- }
393
- /**
394
- * Ranks two items by work criticality: in-progress before open before blocked
395
- * before draft (via {@link statusRank}), then ascending priority, explicit order,
396
- * earliest deadline, most-recently-updated, and finally id for a total order.
397
- * Exported as the canonical focus ordering so sibling read commands (e.g.
398
- * `pm next`) recommend work in the exact same sequence as `pm context`.
399
- */
400
- export function compareCriticalItems(left, right, statusRegistry) {
401
- const byStatus = statusRank(left.status, statusRegistry) -
402
- statusRank(right.status, statusRegistry);
403
- if (byStatus !== 0)
404
- return byStatus;
405
- const byPriority = left.priority - right.priority;
406
- if (byPriority !== 0)
407
- return byPriority;
408
- const byOrder = compareOptionalOrder(left.order, right.order);
409
- if (byOrder !== 0)
410
- return byOrder;
411
- const byDeadline = compareOptionalDeadline(left.deadline, right.deadline);
412
- if (byDeadline !== 0)
413
- return byDeadline;
414
- const byUpdated = compareTimestampStrings(sortableTimestamp(right.updated_at), sortableTimestamp(left.updated_at));
415
- const byId = left.id.localeCompare(right.id);
416
- return byUpdated !== 0 ? byUpdated : byId;
417
- }
418
- function estimateJsonTokens(value) {
419
- return Math.max(1, Math.ceil(Buffer.byteLength(JSON.stringify(value), "utf8") / 4));
420
- }
421
- /** Packs a relevance report with monotone identity, summary, and full item projections. */
422
- export function packRankedContextItems(report, tokenBudget, requiredIds = new Set(), profile = "context") {
423
- return packContextCandidates(report.ranked.map((entry) => ({
424
- id: entry.id,
425
- item: entry.item,
426
- rank: entry.rank,
427
- score: entry.score,
428
- required: requiredIds.has(entry.id),
429
- cluster: entry.item.parent?.trim() || entry.item.type,
430
- token_costs: {
431
- identity: estimateJsonTokens({ id: entry.id, title: entry.item.title }),
432
- summary: estimateJsonTokens({
433
- id: entry.id,
434
- title: entry.item.title,
435
- type: entry.item.type,
436
- status: entry.item.status,
437
- priority: entry.item.priority,
438
- parent: entry.item.parent,
439
- }),
440
- full: estimateJsonTokens(entry.item),
441
- },
442
- })), { tokenBudget, profile, latencyBudgetMs: 25 });
443
- }
444
- /** Projects the SDK packer report onto the stable low-token command envelope. */
445
- export function toContextPackingSummary(report) {
446
- return {
447
- ...report,
448
- included: report.included.map((entry) => ({
449
- id: entry.id,
450
- projection: entry.projection,
451
- tokens: entry.tokens,
452
- })),
453
- };
454
- }
455
- /** Project a full scorer report onto the low-token command explanation shape. */
456
- export function toContextRankingSummary(report, featureStore, servedItemIds) {
457
- const ranked = servedItemIds === undefined
458
- ? report.ranked
459
- : report.ranked.filter((entry) => servedItemIds.has(entry.id));
460
- return {
461
- model: report.model,
462
- available_signals: report.available_signals,
463
- items: ranked.map((entry) => ({
464
- id: entry.id,
465
- rank: entry.rank,
466
- baseline_rank: entry.baseline_rank,
467
- score: entry.score,
468
- contributions: entry.contributions,
469
- ...(entry.signal_provenance === undefined
470
- ? {}
471
- : { recency: entry.signal_provenance.recency }),
472
- })),
473
- candidate_count: report.ranked.length,
474
- omitted_count: report.ranked.length - ranked.length,
475
- ...(featureStore
476
- ? {
477
- feature_store: {
478
- source: featureStore.snapshot.source,
479
- cache_status: featureStore.cache_status,
480
- source_cursor: featureStore.snapshot.source_cursor,
481
- generated_at: featureStore.snapshot.generated_at,
482
- },
483
- }
484
- : {}),
485
- };
486
- }
487
- function completionPct(closed, total) {
488
- return total > 0 ? Math.round((closed / total) * 100) : 0;
489
- }
490
- /** Indexes items by their parent id, yielding a parent→direct-children map used by the hierarchy/progress rollups and by focus-row child completion. Items without a parent are skipped. Exported so sibling read commands reuse the same index. */
491
- export function buildChildrenByParent(allItems) {
492
- const childrenByParent = new Map();
493
- for (const item of allItems) {
494
- const parent = normalizedParentId(item.parent);
495
- if (!parent)
496
- continue;
497
- const children = childrenByParent.get(parent) ?? [];
498
- children.push(item);
499
- childrenByParent.set(parent, children);
500
- }
501
- return childrenByParent;
502
- }
503
- /**
504
- * Projects an item onto the compact {@link ContextFocusItem} focus row. When both
505
- * a status registry and a parent→children index are supplied, it also folds in the
506
- * descendant rollup (`children_total`/`children_closed`/`completion_pct`). Exported
507
- * so sibling read commands (e.g. `pm next`) emit identically-shaped focus rows.
508
- */
509
- export function toContextFocusItem(item, statusRegistry, childrenByParent) {
510
- const focus = {
511
- id: item.id,
512
- title: item.title,
513
- type: item.type,
514
- status: item.status,
515
- priority: item.priority,
516
- order: item.order ?? null,
517
- deadline: item.deadline ?? null,
518
- assignee: item.assignee ?? null,
519
- tags: Array.isArray(item.tags) ? [...item.tags] : [],
520
- updated_at: item.updated_at,
521
- parent: normalizedParentId(item.parent),
522
- };
523
- if (statusRegistry && childrenByParent) {
524
- const descendants = collectDescendants(item.id, childrenByParent);
525
- const total = descendants.length;
526
- if (total > 0) {
527
- const closed = descendants.filter((desc) => isClosedStatus(desc.status, statusRegistry)).length;
528
- focus.children_total = total;
529
- focus.children_closed = closed;
530
- focus.completion_pct = completionPct(closed, total);
531
- }
532
- }
533
- return focus;
534
- }
535
- function summarizeAgenda(events) {
536
- let deadlines = 0;
537
- let reminders = 0;
538
- let scheduled = 0;
539
- const itemIds = new Set();
540
- for (const event of events) {
541
- itemIds.add(event.item_id);
542
- if (event.kind === "deadline") {
543
- deadlines += 1;
544
- continue;
545
- }
546
- if (event.kind === "reminder") {
547
- reminders += 1;
548
- continue;
549
- }
550
- scheduled += 1;
551
- }
552
- return {
553
- events: events.length,
554
- items: itemIds.size,
555
- deadlines,
556
- reminders,
557
- scheduled,
558
- };
559
- }
560
- /** Combines warning groups into a stable, duplicate-free lexical ordering. */
561
- export function mergeSortedWarnings(...warningGroups) {
562
- return [...new Set(warningGroups.flatMap((group) => group ?? []))].sort((left, right) => left.localeCompare(right));
563
- }
564
- function filterTerminalCalendarEvents(events, statusRegistry) {
565
- return events.filter((event) => !statusRegistry.terminal_statuses.has(normalizeStatusForRegistry(event.item_status, statusRegistry)));
566
- }
567
- // ---------------------------------------------------------------------------
568
- // Section builders
569
- // ---------------------------------------------------------------------------
570
- function buildHierarchy(allItems, activeItems, statusRegistry, limit) {
571
- const itemMap = new Map();
572
- for (const item of allItems) {
573
- itemMap.set(item.id, item);
574
- }
575
- const childrenByParent = buildChildrenByParent(allItems);
576
- const activeHighLevelIds = new Set(activeItems
577
- .filter((item) => HIGH_LEVEL_TYPES.has(item.type))
578
- .map((item) => item.id));
579
- const nodes = [];
580
- for (const parentId of activeHighLevelIds) {
581
- const parent = itemMap.get(parentId);
582
- if (!parent)
583
- continue;
584
- const allDescendants = collectDescendants(parentId, childrenByParent);
585
- const childItems = childrenByParent.get(parentId) ?? [];
586
- let closedCount = 0;
587
- let openCount = 0;
588
- let inProgressCount = 0;
589
- let blockedCount = 0;
590
- /* c8 ignore start -- chained status-classification branch accounting is noisy under v8 for mixed descendant sets */
591
- for (const desc of allDescendants) {
592
- if (isClosedStatus(desc.status, statusRegistry))
593
- closedCount++;
594
- else if (isInProgressStatus(desc.status, statusRegistry))
595
- inProgressCount++;
596
- else if (isBlockedStatus(desc.status, statusRegistry))
597
- blockedCount++;
598
- else if (isOpenStatus(desc.status, statusRegistry))
599
- openCount++;
600
- }
601
- /* c8 ignore stop */
602
- const children = childItems
603
- .sort((a, b) => compareCriticalItems(a, b, statusRegistry))
604
- .slice(0, limit)
605
- .map((child) => {
606
- const grandchildren = collectDescendants(child.id, childrenByParent);
607
- const gcClosed = grandchildren.filter((gc) => isClosedStatus(gc.status, statusRegistry)).length;
608
- return {
609
- id: child.id,
610
- title: child.title,
611
- type: child.type,
612
- status: child.status,
613
- children_total: grandchildren.length,
614
- children_closed: gcClosed,
615
- };
616
- });
617
- nodes.push({
618
- id: parent.id,
619
- title: parent.title,
620
- type: parent.type,
621
- status: parent.status,
622
- children_total: allDescendants.length,
623
- children_closed: closedCount,
624
- children_open: openCount,
625
- children_in_progress: inProgressCount,
626
- children_blocked: blockedCount,
627
- children,
628
- });
629
- }
630
- return nodes
631
- .sort((a, b) => {
632
- const aParent = itemMap.get(a.id);
633
- const bParent = itemMap.get(b.id);
634
- return compareCriticalItems(aParent, bParent, statusRegistry);
635
- })
636
- .slice(0, limit);
637
- }
638
- function collectDescendants(parentId, childrenByParent) {
639
- const result = [];
640
- const stack = [parentId];
641
- const visited = new Set();
642
- while (stack.length > 0) {
643
- const current = stack.pop();
644
- if (visited.has(current))
645
- continue;
646
- visited.add(current);
647
- const children = childrenByParent.get(current) ?? [];
648
- for (const child of children) {
649
- result.push(child);
650
- stack.push(child.id);
651
- }
652
- }
653
- return result;
654
- }
655
- /** Public contract for test only, shared by SDK and presentation-layer consumers. */
656
- export const _testOnly = {
657
- buildActivity,
658
- buildBlockers,
659
- buildChildrenByParent,
660
- buildHierarchy,
661
- buildHotFiles,
662
- buildProgress,
663
- buildRecentlyCreated,
664
- buildStaleness,
665
- buildTestHealth,
666
- buildUnparented,
667
- buildWorkload,
668
- collectDescendants,
669
- collectSubtreeIds,
670
- compareCriticalItems,
671
- compareOptionalDeadline,
672
- compareOptionalOrder,
673
- completionPct,
674
- dateTokenForTimestamp,
675
- filterTerminalCalendarEvents,
676
- formatAgendaLine,
677
- isBlockedStatus,
678
- isClosedStatus,
679
- isInProgressStatus,
680
- isOpenStatus,
681
- mergeSortedWarnings,
682
- normalizedParentId,
683
- parseActivityLimit,
684
- parseContextLimit,
685
- resolveContextLimitAtScale,
686
- parseContextParent,
687
- parseContextTimestampMs,
688
- parseStaleThresholdDays,
689
- sortableTimestamp,
690
- statusRank,
691
- stripListProjectionFlags,
692
- summarizeAgenda,
693
- toContextFocusItem,
694
- };
695
- async function buildActivity(activityLimit, global) {
696
- const result = await runActivity({ compact: true, limit: String(activityLimit) }, global);
697
- return result.compact_activity ?? [];
698
- }
699
- function buildProgress(allItems, activeItems, blockedIds, statusRegistry, limit) {
700
- const childrenByParent = new Map();
701
- for (const item of allItems) {
702
- if (!item.parent)
703
- continue;
704
- const children = childrenByParent.get(item.parent) ?? [];
705
- children.push(item);
706
- childrenByParent.set(item.parent, children);
707
- }
708
- const activeHighLevel = activeItems.filter((item) => HIGH_LEVEL_TYPES.has(item.type));
709
- const entries = [];
710
- for (const parent of activeHighLevel) {
711
- const descendants = collectDescendants(parent.id, childrenByParent);
712
- const total = descendants.length;
713
- if (total === 0)
714
- continue;
715
- let closed = 0;
716
- let open = 0;
717
- let inProgress = 0;
718
- let blocked = 0;
719
- /* c8 ignore start -- chained status-classification branch accounting is noisy under v8 for mixed descendant sets */
720
- for (const desc of descendants) {
721
- // Blocked is edge-aware (GH-578): dependency-blocked descendants count as
722
- // blocked regardless of lifecycle status, matching pm next and list-blocked.
723
- if (isClosedStatus(desc.status, statusRegistry))
724
- closed++;
725
- else if (blockedIds.has(desc.id.trim().toLowerCase()))
726
- blocked++;
727
- else if (isInProgressStatus(desc.status, statusRegistry))
728
- inProgress++;
729
- else if (isOpenStatus(desc.status, statusRegistry))
730
- open++;
731
- }
732
- /* c8 ignore stop */
733
- entries.push({
734
- id: parent.id,
735
- title: parent.title,
736
- type: parent.type,
737
- total,
738
- closed,
739
- open,
740
- in_progress: inProgress,
741
- blocked,
742
- completion_pct: completionPct(closed, total),
743
- });
744
- }
745
- return entries
746
- .sort((a, b) => a.completion_pct - b.completion_pct)
747
- .slice(0, limit);
748
- }
749
- function buildBlockers(blockedItems, fullCorpus, statusRegistry, limit) {
750
- const itemsById = new Map(fullCorpus.map((item) => [item.id.trim().toLowerCase(), item]));
751
- return blockedItems.slice(0, limit).map((item) => {
752
- // Prefer a currently open blocker edge. The legacy scalar may still name a
753
- // resolved predecessor, so it is only a fallback when no open edge exists.
754
- const blockers = resolveItemBlockers(item, itemsById, statusRegistry);
755
- const blockedBy = blockers.find((blocker) => !blocker.resolved)?.id ??
756
- blockers[0]?.id ??
757
- null;
758
- const blockerItem = blockedBy
759
- ? itemsById.get(blockedBy.trim().toLowerCase())
760
- : undefined;
761
- return {
762
- id: item.id,
763
- title: item.title,
764
- blocked_by: blockedBy,
765
- blocked_by_title: blockerItem?.title ?? null,
766
- blocked_by_status: blockerItem?.status ?? null,
767
- blocked_reason: item.blocked_reason ?? null,
768
- unblock_note: item.unblock_note ?? null,
769
- };
770
- });
771
- }
772
- function buildHotFiles(activeItems, limit) {
773
- const fileMap = new Map();
774
- for (const item of activeItems) {
775
- for (const file of item.files ?? []) {
776
- const existing = fileMap.get(file.path) ?? new Set();
777
- existing.add(item.id);
778
- fileMap.set(file.path, existing);
779
- }
780
- }
781
- return [...fileMap.entries()]
782
- .map(([filePath, itemIds]) => ({
783
- path: filePath,
784
- references: itemIds.size,
785
- items: [...itemIds].sort(),
786
- }))
787
- .sort((a, b) => b.references - a.references)
788
- .slice(0, limit);
789
- }
790
- function buildWorkload(activeItems, statusRegistry, limit) {
791
- const groups = new Map();
792
- for (const item of activeItems) {
793
- const key = item.assignee ?? null;
794
- const existing = groups.get(key) ?? [];
795
- existing.push(item);
796
- groups.set(key, existing);
797
- }
798
- return [...groups.entries()]
799
- .map(([assignee, items]) => ({
800
- assignee,
801
- active: items.length,
802
- in_progress: items.filter((item) => isInProgressStatus(item.status, statusRegistry)).length,
803
- items: items.map((item) => item.id).sort(),
804
- }))
805
- .sort((a, b) => b.active - a.active)
806
- .slice(0, limit);
807
- }
808
- function buildStaleness(allNonTerminal, staleThresholdDays, now, limit) {
809
- const cutoffMs = new Date(now).getTime() - staleThresholdDays * 24 * 60 * 60 * 1000;
810
- return allNonTerminal
811
- .filter((item) => new Date(item.updated_at).getTime() < cutoffMs)
812
- .map((item) => ({
813
- id: item.id,
814
- title: item.title,
815
- status: item.status,
816
- updated_at: item.updated_at,
817
- stale_days: Math.floor((new Date(now).getTime() - new Date(item.updated_at).getTime()) /
818
- (24 * 60 * 60 * 1000)),
819
- }))
820
- .sort((a, b) => b.stale_days - a.stale_days)
821
- .slice(0, limit);
822
- }
823
- function buildRecentlyCreated(allNonTerminal, statusRegistry, childrenByParent, limit) {
824
- return allNonTerminal
825
- .map((item) => ({ item, sortKey: sortableTimestamp(item.created_at) }))
826
- .sort((left, right) => {
827
- const byCreated = compareTimestampStrings(right.sortKey, left.sortKey);
828
- return byCreated !== 0
829
- ? byCreated
830
- : left.item.id.localeCompare(right.item.id);
831
- })
832
- .slice(0, limit)
833
- .map(({ item }) => ({
834
- ...toContextFocusItem(item, statusRegistry, childrenByParent),
835
- created_at: item.created_at,
836
- }));
837
- }
838
- function buildUnparented(allNonTerminal, statusRegistry, childrenByParent, limit) {
839
- return allNonTerminal
840
- .filter((item) => !normalizedParentId(item.parent) && !HIGH_LEVEL_TYPES.has(item.type))
841
- .sort((left, right) => compareCriticalItems(left, right, statusRegistry))
842
- .slice(0, limit)
843
- .map((item) => toContextFocusItem(item, statusRegistry, childrenByParent));
844
- }
845
- function buildTestHealth(activeItems) {
846
- let itemsWithTests = 0;
847
- let itemsWithRecentRuns = 0;
848
- let passed = 0;
849
- let failed = 0;
850
- let skipped = 0;
851
- const itemsFailing = [];
852
- for (const item of activeItems) {
853
- if ((item.tests ?? []).length > 0) {
854
- itemsWithTests++;
855
- }
856
- const runs = item.test_runs ?? [];
857
- if (runs.length > 0) {
858
- itemsWithRecentRuns++;
859
- let itemHasFailure = false;
860
- for (const run of runs) {
861
- passed += run.passed ?? 0;
862
- failed += run.failed ?? 0;
863
- skipped += run.skipped ?? 0;
864
- if ((run.failed ?? 0) > 0) {
865
- itemHasFailure = true;
866
- }
867
- }
868
- if (itemHasFailure) {
869
- itemsFailing.push(item.id);
870
- }
871
- }
872
- }
873
- return {
874
- items_with_tests: itemsWithTests,
875
- items_with_recent_runs: itemsWithRecentRuns,
876
- recent_runs: { passed, failed, skipped },
877
- items_failing: itemsFailing.sort(),
878
- };
879
- }
880
- // ---------------------------------------------------------------------------
881
- // Markdown formatting
882
- // ---------------------------------------------------------------------------
883
- function formatClock(timestamp) {
884
- return `${new Date(timestamp).toISOString().slice(11, 16)}Z`;
885
- }
886
- function formatFocusLine(item) {
887
- const orderToken = item.order === null ? "-" : String(item.order);
888
- const deadlineToken = item.deadline ?? "-";
889
- const parentToken = item.parent ? ` parent:${item.parent}` : "";
890
- const progressToken = item.children_total !== undefined &&
891
- item.children_closed !== undefined &&
892
- item.completion_pct !== undefined
893
- ? ` children:${item.children_closed}/${item.children_total} done:${item.completion_pct}%`
894
- : "";
895
- const blockedToken = item.blocked === true
896
- ? ` blocked:${item.blocker_ids?.join(",") || "lifecycle"}`
897
- : "";
898
- return `${item.id} p${item.priority} ${item.status} ${item.type} order:${orderToken} deadline:${deadlineToken}${parentToken}${progressToken}${blockedToken} ${item.title}`;
899
- }
900
- // Renders a focus row projected to a `--fields` subset as space-separated
901
- // field:value tokens, mirroring the projection field order. Array values join
902
- // with commas; missing/null values render as `-`.
903
- function formatProjectedFocusLine(item, fields) {
904
- const source = item;
905
- return fields
906
- .map((field) => {
907
- const value = source[field];
908
- if (Array.isArray(value))
909
- return `${field}:${value.join(",")}`;
910
- return `${field}:${value ?? "-"}`;
911
- })
912
- .join(" ");
913
- }
914
- function formatAgendaLine(event) {
915
- if ("reference_only" in event) {
916
- const suffix = event.kind === "reminder"
917
- ? ` — ${event.reminder_text ?? "reminder"}`
918
- : event.kind === "event"
919
- ? ` — ${event.event_title ?? "event"}${event.event_recurring ? " (recurring)" : ""}`
920
- : "";
921
- return `${formatClock(event.at)} [${event.kind}] ${event.item_id} (see focus item)${suffix}`;
922
- }
923
- const base = `${formatClock(event.at)} [${event.kind}] ${event.item_id} p${event.item_priority} ${event.item_status} ${event.item_title}`;
924
- if (event.kind === "reminder") {
925
- return `${base} — ${event.reminder_text}`;
926
- }
927
- if (event.kind === "event") {
928
- const recurringSuffix = event.event_recurring ? " (recurring)" : "";
929
- const title = event.event_title ?? event.item_title;
930
- return `${base} — ${title}${recurringSuffix}`;
931
- }
932
- return base;
933
- }
934
- function pushContextFocusSection(lines, title, rows, emptyText, renderFocus) {
935
- lines.push(`## ${title}`);
936
- if (rows.length === 0) {
937
- lines.push(emptyText);
938
- }
939
- else {
940
- for (const item of rows) {
941
- lines.push(`- ${renderFocus(item)}`);
942
- }
943
- }
944
- lines.push("");
945
- }
946
- function pushBlockedFallbackSection(lines, result, renderFocus) {
947
- if (result.blocked_fallback.length === 0) {
948
- return;
949
- }
950
- lines.push("## Blocked fallback");
951
- for (const item of result.blocked_fallback) {
952
- lines.push(`- ${renderFocus(item)}`);
953
- }
954
- lines.push("");
955
- }
956
- function pushAgendaSection(lines, result) {
957
- lines.push("## Agenda");
958
- lines.push(`- events: ${result.agenda.summary.events} (deadlines: ${result.agenda.summary.deadlines}, reminders: ${result.agenda.summary.reminders}, scheduled: ${result.agenda.summary.scheduled})`);
959
- if (result.agenda.events.length === 0) {
960
- lines.push("No agenda events matched the selected filters.");
961
- }
962
- else {
963
- for (const event of result.agenda.events) {
964
- lines.push(`- ${formatAgendaLine(event)}`);
965
- }
966
- }
967
- lines.push("");
968
- }
969
- function pushHierarchySection(lines, result) {
970
- if (!result.hierarchy || result.hierarchy.length === 0) {
971
- return;
972
- }
973
- lines.push("## Hierarchy");
974
- for (const node of result.hierarchy) {
975
- const pct = node.children_total > 0
976
- ? Math.round((node.children_closed / node.children_total) * 100)
977
- : 0;
978
- lines.push(`- ${node.id} ${node.type} ${node.status} "${node.title}" [${node.children_closed}/${node.children_total} done ${pct}%]`);
979
- for (const child of node.children) {
980
- const cpct = child.children_total > 0
981
- ? Math.round((child.children_closed / child.children_total) * 100)
982
- : 0;
983
- lines.push(` - ${child.id} ${child.type} ${child.status} "${child.title}" [${child.children_closed}/${child.children_total} done ${cpct}%]`);
984
- }
985
- }
986
- lines.push("");
987
- }
988
- function pushProgressSection(lines, result) {
989
- if (!result.progress || result.progress.length === 0) {
990
- return;
991
- }
992
- lines.push("## Progress");
993
- for (const entry of result.progress) {
994
- lines.push(`- ${entry.id} "${entry.title}" ${entry.completion_pct}% (${entry.closed}/${entry.total} closed, ${entry.in_progress} wip, ${entry.open} open, ${entry.blocked} blocked)`);
995
- }
996
- lines.push("");
997
- }
998
- function pushRecentlyCreatedSection(lines, result, focusFields, renderFocus) {
999
- if (!result.recently_created || result.recently_created.length === 0) {
1000
- return;
1001
- }
1002
- lines.push("## Recently created");
1003
- for (const item of result.recently_created) {
1004
- lines.push(focusFields
1005
- ? `- ${renderFocus(item)}`
1006
- : `- ${dateTokenForTimestamp(item.created_at)} ${formatFocusLine(item)}`);
1007
- }
1008
- lines.push("");
1009
- }
1010
- function pushUnparentedSection(lines, result, renderFocus) {
1011
- if (!result.unparented || result.unparented.length === 0) {
1012
- return;
1013
- }
1014
- lines.push("## Unparented");
1015
- for (const item of result.unparented) {
1016
- lines.push(`- ${renderFocus(item)}`);
1017
- }
1018
- lines.push("");
1019
- }
1020
- function pushActivitySection(lines, result) {
1021
- if (!result.activity || result.activity.length === 0) {
1022
- return;
1023
- }
1024
- lines.push("## Recent activity");
1025
- for (const entry of result.activity) {
1026
- const msg = entry.msg ? ` ${entry.msg}` : "";
1027
- lines.push(`- ${entry.ts.slice(0, 16)}Z ${entry.id} ${entry.op} by:${entry.author}${msg}`);
1028
- }
1029
- lines.push("");
1030
- }
1031
- function pushBlockersSection(lines, result) {
1032
- if (!result.blockers || result.blockers.length === 0) {
1033
- return;
1034
- }
1035
- lines.push("## Blockers");
1036
- for (const entry of result.blockers) {
1037
- const by = entry.blocked_by
1038
- ? `blocked_by:${entry.blocked_by}(${entry.blocked_by_status ?? "?"})`
1039
- : "blocked_by:-";
1040
- const reason = entry.blocked_reason
1041
- ? ` reason:"${entry.blocked_reason}"`
1042
- : "";
1043
- const note = entry.unblock_note ? ` unblock:"${entry.unblock_note}"` : "";
1044
- lines.push(`- ${entry.id} "${entry.title}" ${by}${reason}${note}`);
1045
- }
1046
- lines.push("");
1047
- }
1048
- function pushFilesSection(lines, result) {
1049
- if (!result.files || result.files.length === 0) {
1050
- return;
1051
- }
1052
- lines.push("## Hot files");
1053
- for (const file of result.files) {
1054
- lines.push(`- ${file.path} refs:${file.references} items:[${file.items.join(",")}]`);
1055
- }
1056
- lines.push("");
1057
- }
1058
- function pushWorkloadSection(lines, result) {
1059
- if (!result.workload || result.workload.length === 0) {
1060
- return;
1061
- }
1062
- lines.push("## Workload");
1063
- for (const entry of result.workload) {
1064
- const who = entry.assignee ?? "(unassigned)";
1065
- lines.push(`- ${who} active:${entry.active} wip:${entry.in_progress} items:[${entry.items.join(",")}]`);
1066
- }
1067
- lines.push("");
1068
- }
1069
- function pushStalenessSection(lines, result) {
1070
- if (!result.staleness || result.staleness.length === 0) {
1071
- return;
1072
- }
1073
- lines.push("## Stale items");
1074
- for (const entry of result.staleness) {
1075
- lines.push(`- ${entry.id} ${entry.status} stale:${entry.stale_days}d last:${entry.updated_at.slice(0, 10)} "${entry.title}"`);
1076
- }
1077
- lines.push("");
1078
- }
1079
- function pushTestHealthSection(lines, result) {
1080
- if (!result.tests) {
1081
- return;
1082
- }
1083
- lines.push("## Test health");
1084
- lines.push(`- items_with_tests: ${result.tests.items_with_tests}`);
1085
- lines.push(`- items_with_recent_runs: ${result.tests.items_with_recent_runs}`);
1086
- lines.push(`- passed: ${result.tests.recent_runs.passed}, failed: ${result.tests.recent_runs.failed}, skipped: ${result.tests.recent_runs.skipped}`);
1087
- if (result.tests.items_failing.length > 0) {
1088
- lines.push(`- items_failing: [${result.tests.items_failing.join(",")}]`);
1089
- }
1090
- lines.push("");
1091
- }
1092
- function pushEmptyContextSuggestions(lines, result) {
1093
- const isEmpty = result.summary.active_items === 0 &&
1094
- result.summary.blocked === 0 &&
1095
- result.agenda.summary.events === 0;
1096
- if (!isEmpty) {
1097
- return;
1098
- }
1099
- lines.push("## Suggestions");
1100
- lines.push("No active work items or upcoming events. Consider:");
1101
- lines.push('- `pm create --type Task --title "..."` to add a new work item');
1102
- lines.push("- `pm list --status closed --limit 5` to review recent completions");
1103
- lines.push("- `pm search <keywords>` to find related past work");
1104
- lines.push("- `pm aggregate` for a full project status overview");
1105
- }
1106
- /** Implements render context markdown for the public runtime surface of this module. */
1107
- export function renderContextMarkdown(result) {
1108
- const lines = [];
1109
- const focusFields = result.focus_fields;
1110
- const renderFocus = (item) => focusFields
1111
- ? formatProjectedFocusLine(item, focusFields)
1112
- : formatFocusLine(item);
1113
- lines.push("# pm context");
1114
- lines.push("");
1115
- lines.push(`- now: ${result.now}`);
1116
- lines.push(`- depth: ${result.depth}`);
1117
- if (result.filters.parent) {
1118
- lines.push(`- scope: subtree of ${result.filters.parent}`);
1119
- }
1120
- lines.push(`- active_items: ${result.summary.active_items} (in_progress: ${result.summary.in_progress}, open: ${result.summary.open})`);
1121
- if (result.summary.total_items !== undefined) {
1122
- lines.push(`- total_items: ${result.summary.total_items} (closed: ${result.summary.closed ?? 0}, canceled: ${result.summary.canceled ?? 0})`);
1123
- }
1124
- lines.push(`- agenda_events: ${result.summary.agenda_events}`);
1125
- lines.push(`- blocked_fallback_used: ${result.summary.blocked_fallback_used}`);
1126
- if (result.extension_health) {
1127
- const degradedNames = result.extension_health.packages
1128
- .filter((entry) => entry.status === "degraded")
1129
- .map((entry) => entry.name);
1130
- lines.push(`- extensions: ${result.extension_health.ok} ok, ${result.extension_health.degraded} degraded${degradedNames.length > 0 ? ` (${degradedNames.join(", ")})` : ""}`);
1131
- }
1132
- const renderedSections = result.sections_included.filter((section) => section !== "blockers" || (result.blockers?.length ?? 0) > 0);
1133
- if (renderedSections.length > 0) {
1134
- lines.push(`- sections: ${renderedSections.join(", ")}`);
1135
- }
1136
- lines.push("");
1137
- pushContextFocusSection(lines, "High-level focus", result.high_level, "No high-level active items.", renderFocus);
1138
- pushContextFocusSection(lines, "Low-level focus", result.low_level, "No low-level active items.", renderFocus);
1139
- pushBlockedFallbackSection(lines, result, renderFocus);
1140
- pushAgendaSection(lines, result);
1141
- if (result.workspace_memory) {
1142
- lines.push("## Workspace memory");
1143
- for (const rollup of result.workspace_memory.rollups) {
1144
- lines.push(`- ${rollup.kind}:${rollup.key} — ${rollup.label} (${rollup.item_count} completed, latest ${rollup.last_closed_at})`);
1145
- }
1146
- lines.push("");
1147
- }
1148
- pushHierarchySection(lines, result);
1149
- pushProgressSection(lines, result);
1150
- pushRecentlyCreatedSection(lines, result, focusFields, renderFocus);
1151
- pushUnparentedSection(lines, result, renderFocus);
1152
- pushActivitySection(lines, result);
1153
- pushBlockersSection(lines, result);
1154
- pushFilesSection(lines, result);
1155
- pushWorkloadSection(lines, result);
1156
- pushStalenessSection(lines, result);
1157
- pushTestHealthSection(lines, result);
1158
- pushEmptyContextSuggestions(lines, result);
1159
- return lines.join("\n");
1160
- }
1161
- async function resolveContextRuntime(options, global) {
1162
- const pmRoot = resolvePmRoot(process.cwd(), global.path);
1163
- const settings = await readSettings(pmRoot);
1164
- /* c8 ignore start -- settings persistence currently always materializes context defaults */
1165
- const contextSettings = settings.context ?? SETTINGS_DEFAULTS.context;
1166
- /* c8 ignore stop */
1167
- const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
1168
- const depth = parseContextDepth(options.depth, contextSettings);
1169
- const limit = parseContextLimit(options.limit ?? options.maxItems, depth);
1170
- return {
1171
- settings,
1172
- contextSettings,
1173
- statusRegistry,
1174
- depth,
1175
- limit,
1176
- sectionsIncluded: parseContextSections(options.section, depth, contextSettings),
1177
- activityLimit: parseActivityLimit(options.activityLimit, contextSettings),
1178
- staleThresholdDays: parseStaleThresholdDays(options.staleThreshold, contextSettings),
1179
- parentScope: parseContextParent(options.parent),
1180
- focusFields: parseContextFocusFields(options.fields),
1181
- baseListOptions: stripListProjectionFlags(options),
1182
- };
1183
- }
1184
- function contextNeedsAllItems(sectionsIncluded) {
1185
- return sectionsIncluded.some((section) => [
1186
- "hierarchy",
1187
- "progress",
1188
- "blockers",
1189
- "staleness",
1190
- "recently_created",
1191
- "unparented",
1192
- ].includes(section));
1193
- }
1194
- function buildUnpaginatedContextListOptions(baseListOptions, extra) {
1195
- return {
1196
- ...baseListOptions,
1197
- ...extra,
1198
- noTruncate: true,
1199
- limit: undefined,
1200
- offset: undefined,
1201
- after: undefined,
1202
- };
1203
- }
1204
- async function loadContextCorpus(global, runtime) {
1205
- // One full-corpus scan serves every consumer: runList always reads all item
1206
- // files before filtering, so deriving the non-terminal subset in memory is
1207
- // free and keeps terminal blocker targets available for the shared
1208
- // edge-aware blocked classification (GH-578).
1209
- const listed = await runList(undefined, buildUnpaginatedContextListOptions(runtime.baseListOptions, {
1210
- excludeTerminal: false,
1211
- }), global);
1212
- const fullCorpus = listed.items;
1213
- let listedItemMetadata = fullCorpus.filter((item) => !isTerminalStatus(item.status, runtime.statusRegistry));
1214
- let allItems = fullCorpus;
1215
- const subtreeIds = resolveContextSubtreeIds(runtime.parentScope, fullCorpus);
1216
- if (subtreeIds) {
1217
- listedItemMetadata = listedItemMetadata.filter((item) => subtreeIds.has(item.id.trim().toLowerCase()));
1218
- allItems = allItems.filter((item) => subtreeIds.has(item.id.trim().toLowerCase()));
1219
- }
1220
- return { listed, listedItemMetadata, allItems, fullCorpus, subtreeIds };
1221
- }
1222
- function resolveContextSubtreeIds(parentScope, fullCorpus) {
1223
- if (parentScope === undefined) {
1224
- return undefined;
1225
- }
1226
- const subtree = collectSubtreeIds(fullCorpus, parentScope);
1227
- if (!subtree.found) {
1228
- throw new PmCliError(`Context --parent item not found: ${parentScope}`, EXIT_CODE.NOT_FOUND);
1229
- }
1230
- return subtree.ids;
1231
- }
1232
- /** Classify strategic and human-directed context through the shared execution rules. */
1233
- function collectHighLevelContextIds(activeItems, fullCorpus, statusRegistry, typeRegistry) {
1234
- const containers = new Set(computeActionabilityReport(activeItems, fullCorpus, statusRegistry, typeRegistry)
1235
- .containers.map((entry) => entry.item.id));
1236
- return new Set(activeItems.filter((item) => HIGH_LEVEL_TYPES.has(item.type) || containers.has(item.id) ||
1237
- resolveItemExecutionRole(item.type, typeRegistry) !== "agent").map((item) => item.id));
1238
- }
1239
- async function resolveContextFocusGroups(listedItemMetadata, allItems, fullCorpus, blockedIds, statusRegistry, sectionsIncluded, limit, now, author, cursor, cursorFingerprint, useBoundedPage, pmRoot, tokenBudget, claimFocus, typeRegistry) {
1240
- const structural = [...listedItemMetadata].sort((left, right) => compareCriticalItems(left, right, statusRegistry));
1241
- const usage = await readContextUsageAffinity({
1242
- pmRoot,
1243
- author,
1244
- enabled: process.env.PM_CONTEXT_USAGE_DISABLED !== "1",
1245
- });
1246
- const featureStore = await readWorkspaceContextSignals(structural, {
1247
- pmRoot,
1248
- storeKey: "context",
1249
- statusRegistry,
1250
- now,
1251
- author,
1252
- usageAffinity: usage.affinity,
1253
- claimFocus,
1254
- });
1255
- const ranking = await scoreContextCandidatesWithActiveExtensions("context", featureStore.candidates);
1256
- const ranked = ranking.ranked.map((entry) => entry.item);
1257
- const activeStatuses = statusRegistry.active_statuses;
1258
- const rankedActiveItems = ranked.filter((item) => activeStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1259
- const pageStart = useBoundedPage
1260
- ? resolveQueryCursorStart(rankedActiveItems, cursor, cursorFingerprint, (item) => item.id)
1261
- : 0;
1262
- const focusPage = useBoundedPage
1263
- ? rankedActiveItems.slice(pageStart, pageStart + limit)
1264
- : rankedActiveItems;
1265
- const hasMore = useBoundedPage &&
1266
- focusPage.length > 0 &&
1267
- pageStart + focusPage.length < rankedActiveItems.length;
1268
- const nextCursor = hasMore && focusPage.length > 0
1269
- ? encodeQueryCursor(cursorFingerprint, focusPage[focusPage.length - 1].id, pageStart + focusPage.length - 1)
1270
- : undefined;
1271
- const rankedBlockedItems = ranked.filter((item) => blockedIds.has(item.id.trim().toLowerCase()));
1272
- const packingIds = new Set([
1273
- ...focusPage.map((item) => item.id),
1274
- ...rankedBlockedItems.slice(0, limit).map((item) => item.id),
1275
- ]);
1276
- const packing = packRankedContextItems({
1277
- ...ranking,
1278
- ranked: ranking.ranked.filter((entry) => packingIds.has(entry.id)),
1279
- }, tokenBudget, new Set(Object.entries(claimFocus ?? {})
1280
- .filter(([, affinity]) => affinity >= 1)
1281
- .map(([id]) => id)));
1282
- const packedItems = packing.included.map((entry) => entry.item);
1283
- const activeItems = packedItems.filter((item) => activeStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1284
- const blockedItems = packedItems.filter((item) => blockedIds.has(item.id.trim().toLowerCase()));
1285
- const childrenByParent = buildChildrenByParent(allItems);
1286
- const focusChildrenByParent = contextNeedsAllItems(sectionsIncluded)
1287
- ? childrenByParent
1288
- : undefined;
1289
- const fullCorpusById = new Map(fullCorpus.map((item) => [item.id.trim().toLowerCase(), item]));
1290
- const projectFocusItem = (item) => {
1291
- const focus = toContextFocusItem(item, statusRegistry, focusChildrenByParent);
1292
- if (!blockedIds.has(item.id.trim().toLowerCase())) {
1293
- return focus;
1294
- }
1295
- focus.blocked = true;
1296
- focus.blocker_ids = resolveItemBlockers(item, fullCorpusById, statusRegistry)
1297
- .filter((blocker) => !blocker.resolved)
1298
- .map((blocker) => blocker.id);
1299
- return focus;
1300
- };
1301
- const highLevelIds = collectHighLevelContextIds(activeItems, fullCorpus, statusRegistry, typeRegistry);
1302
- const highLevel = activeItems
1303
- .filter((item) => highLevelIds.has(item.id))
1304
- .slice(0, useBoundedPage ? focusPage.length : limit)
1305
- .map(projectFocusItem);
1306
- const lowLevel = activeItems
1307
- .filter((item) => !highLevelIds.has(item.id))
1308
- .slice(0, useBoundedPage ? focusPage.length : limit)
1309
- .map(projectFocusItem);
1310
- const blockedFallbackUsed = rankedActiveItems.length === 0;
1311
- return {
1312
- activeItems,
1313
- blockedItems,
1314
- highLevel,
1315
- lowLevel,
1316
- blockedFallback: blockedFallbackUsed
1317
- ? blockedItems.slice(0, limit).map(projectFocusItem)
1318
- : [],
1319
- blockedFallbackUsed,
1320
- ranking,
1321
- packing,
1322
- featureStore,
1323
- pageExtras: {
1324
- ...(useBoundedPage ? { applied_limit: limit } : {}),
1325
- ...(hasMore ? { has_more: true, truncated: true } : {}),
1326
- ...(nextCursor ? { next_cursor: nextCursor } : {}),
1327
- },
1328
- };
1329
- }
1330
- function buildContextCursorFingerprint(options) {
1331
- return createQueryFingerprint("context", selectCursorSemanticOptions(options, CONTEXT_FLAG_CONTRACTS));
1332
- }
1333
- function shouldPageContextFocus(options, corpusItemCount) {
1334
- return (options.limit !== undefined ||
1335
- options.maxItems !== undefined ||
1336
- options.after !== undefined ||
1337
- corpusItemCount >= CONTEXT_SCALE_THRESHOLD);
1338
- }
1339
- async function buildContextAgenda(global, runtime, subtreeIds, listedFocusIds) {
1340
- const calendarOptions = {
1341
- ...runtime.baseListOptions,
1342
- view: "agenda",
1343
- include: "all",
1344
- limit: runtime.parentScope === undefined ? String(runtime.limit) : undefined,
1345
- };
1346
- const agenda = await runCalendar(calendarOptions, global);
1347
- const scopedAgenda = subtreeIds === undefined
1348
- ? agenda.events
1349
- : agenda.events.filter((event) => subtreeIds.has(event.item_id.trim().toLowerCase()));
1350
- const fullAgendaEvents = filterTerminalCalendarEvents(scopedAgenda, runtime.statusRegistry).slice(0, runtime.limit);
1351
- const agendaEvents = fullAgendaEvents.map((event) => {
1352
- if (!listedFocusIds.has(event.item_id)) {
1353
- return event;
1354
- }
1355
- return {
1356
- at: event.at,
1357
- date: event.date,
1358
- kind: event.kind,
1359
- item_id: event.item_id,
1360
- reference_only: true,
1361
- ...(event.kind === "reminder"
1362
- ? { reminder_text: event.reminder_text }
1363
- : {}),
1364
- ...(event.kind === "event"
1365
- ? {
1366
- event_title: event.event_title,
1367
- event_recurring: event.event_recurring,
1368
- }
1369
- : {}),
1370
- };
1371
- });
1372
- return {
1373
- agenda,
1374
- agendaEvents,
1375
- agendaSummary: summarizeAgenda(fullAgendaEvents),
1376
- };
1377
- }
1378
- function countContextStatus(items, status, statusRegistry) {
1379
- const targetStatus = String(status);
1380
- return items.filter((item) => normalizeStatusForRegistry(item.status, statusRegistry) === targetStatus).length;
1381
- }
1382
- async function buildOptionalContextSections(params) {
1383
- const { runtime, allItems, fullCorpus, blockedIds, focusGroups, now, global, } = params;
1384
- const childrenByParent = buildChildrenByParent(allItems);
1385
- const allNonTerminal = allItems.filter((item) => !isTerminalStatus(item.status, runtime.statusRegistry));
1386
- const has = (section) => runtime.sectionsIncluded.includes(section);
1387
- return {
1388
- hierarchy: has("hierarchy")
1389
- ? buildHierarchy(allItems, focusGroups.activeItems, runtime.statusRegistry, runtime.limit)
1390
- : undefined,
1391
- activity: has("activity")
1392
- ? await buildActivity(runtime.activityLimit, global)
1393
- : undefined,
1394
- progress: has("progress")
1395
- ? buildProgress(allItems, focusGroups.activeItems, blockedIds, runtime.statusRegistry, runtime.limit)
1396
- : undefined,
1397
- blockersSection: has("blockers")
1398
- ? buildBlockers(focusGroups.blockedItems, fullCorpus, runtime.statusRegistry, runtime.limit)
1399
- : undefined,
1400
- recentlyCreated: has("recently_created")
1401
- ? buildRecentlyCreated(allNonTerminal, runtime.statusRegistry, childrenByParent, runtime.limit)
1402
- : undefined,
1403
- unparented: has("unparented")
1404
- ? buildUnparented(allNonTerminal, runtime.statusRegistry, childrenByParent, runtime.limit)
1405
- : undefined,
1406
- filesSection: has("files")
1407
- ? buildHotFiles(focusGroups.activeItems, runtime.limit)
1408
- : undefined,
1409
- workload: has("workload")
1410
- ? buildWorkload(focusGroups.activeItems, runtime.statusRegistry, runtime.limit)
1411
- : undefined,
1412
- staleness: has("staleness")
1413
- ? buildStaleness(allNonTerminal, runtime.staleThresholdDays, now, runtime.limit)
1414
- : undefined,
1415
- tests: has("tests") ? buildTestHealth(focusGroups.activeItems) : undefined,
1416
- };
1417
- }
1418
- function buildContextSummaryExtras(allItems, statusRegistry, blockedIds) {
1419
- const canceledStatus = normalizeStatusInput("canceled", statusRegistry);
1420
- const activeItems = allItems.filter((item) => statusRegistry.active_statuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1421
- const inProgress = countContextStatus(activeItems, statusRegistry.in_progress_status, statusRegistry);
1422
- return {
1423
- scope: "matching_items",
1424
- active_items: activeItems.length,
1425
- open: activeItems.length - inProgress,
1426
- in_progress: inProgress,
1427
- blocked: allItems.filter((item) => blockedIds.has(item.id.trim().toLowerCase())).length,
1428
- total_items: allItems.length,
1429
- closed: allItems.filter((item) => isClosedStatus(item.status, statusRegistry)).length,
1430
- canceled: allItems.filter((item) => normalizeStatusForRegistry(item.status, statusRegistry) ===
1431
- canceledStatus).length,
1432
- };
1433
- }
1434
- function attachOptionalContextSections(result, sections, warningDetails) {
1435
- if (sections.hierarchy)
1436
- result.hierarchy = sections.hierarchy;
1437
- if (sections.activity)
1438
- result.activity = sections.activity;
1439
- if (sections.progress)
1440
- result.progress = sections.progress;
1441
- if (sections.blockersSection)
1442
- result.blockers = sections.blockersSection;
1443
- if (sections.recentlyCreated)
1444
- result.recently_created = sections.recentlyCreated;
1445
- if (sections.unparented)
1446
- result.unparented = sections.unparented;
1447
- if (sections.filesSection)
1448
- result.files = sections.filesSection;
1449
- if (sections.workload)
1450
- result.workload = sections.workload;
1451
- if (sections.staleness)
1452
- result.staleness = sections.staleness;
1453
- if (sections.tests)
1454
- result.tests = sections.tests;
1455
- if (warningDetails !== undefined && warningDetails.length > 0) {
1456
- result.warning_details = warningDetails;
1457
- }
1458
- }
1459
- function applyContextFocusProjection(result, focusFields) {
1460
- if (!focusFields) {
1461
- return;
1462
- }
1463
- result.focus_fields = focusFields;
1464
- result.high_level = projectContextFocusRows(result.high_level, focusFields);
1465
- result.low_level = projectContextFocusRows(result.low_level, focusFields);
1466
- result.blocked_fallback = projectContextFocusRows(result.blocked_fallback, focusFields);
1467
- if (result.recently_created) {
1468
- result.recently_created = projectContextFocusRows(result.recently_created, focusFields);
1469
- }
1470
- if (result.unparented) {
1471
- result.unparented = projectContextFocusRows(result.unparented, focusFields);
1472
- }
1473
- }
1474
- /**
1475
- * Remove redundant context tags while preserving their provenance. Identical
1476
- * child tag sets are folded only when the parent row is present in the same
1477
- * bounded result, so consumers never need an unavailable follow-up read.
1478
- * `--no-tags` removes both tag values and inheritance markers.
1479
- */
1480
- export function applyContextTagProjection(result, noTags) {
1481
- const rows = [
1482
- result.high_level,
1483
- result.low_level,
1484
- result.blocked_fallback,
1485
- result.recently_created ?? [],
1486
- result.unparented ?? [],
1487
- ].flat();
1488
- if (noTags) {
1489
- for (const row of rows) {
1490
- delete row.tags;
1491
- delete row.tags_inherited;
1492
- }
1493
- return;
1494
- }
1495
- const rowsById = new Map(rows.map((row) => [row.id, row]));
1496
- const originalTagSignatures = new Map(rows.map((row) => [
1497
- row.id,
1498
- row.tags ? [...row.tags].sort().join("\0") : undefined,
1499
- ]));
1500
- for (const row of rows) {
1501
- if (!row.parent || !row.tags) {
1502
- continue;
1503
- }
1504
- const parent = rowsById.get(row.parent);
1505
- if (parent &&
1506
- originalTagSignatures.get(row.id) === originalTagSignatures.get(parent.id)) {
1507
- delete row.tags;
1508
- row.tags_inherited = parent.id;
1509
- }
1510
- }
1511
- }
1512
- function maybeAttachEmptyContextSuggestions(result, activeItems, blockedItems) {
1513
- if (activeItems.length > 0 ||
1514
- blockedItems.length > 0 ||
1515
- result.agenda.events.length > 0) {
1516
- return;
1517
- }
1518
- result.suggestions = [
1519
- 'pm create --type Task --title "..." to add a new work item',
1520
- "pm list --status closed --limit 5 to review recent completions",
1521
- "pm search <keywords> to find related past work",
1522
- "pm aggregate for a full project status overview",
1523
- ];
1524
- }
1525
- async function attachContextUsageFeedback(result, focusGroups, pmRoot, author) {
1526
- try {
1527
- const included = new Set(focusGroups.packing.included.map((entry) => entry.id));
1528
- const rows = focusGroups.ranking.ranked.map((entry) => ({
1529
- id: entry.id,
1530
- rank: entry.rank,
1531
- included: included.has(entry.id),
1532
- }));
1533
- const rankedIds = new Set(rows.map((row) => row.id));
1534
- for (const id of collectContextUsageDeliveredItemIds(result, "context")) {
1535
- if (!rankedIds.has(id)) {
1536
- rows.push({ id, rank: rows.length + 1, included: false });
1537
- rankedIds.add(id);
1538
- }
1539
- }
1540
- const receipt = await recordContextUsageServing({
1541
- pmRoot,
1542
- author,
1543
- surface: "context",
1544
- profile: focusGroups.packing.profile,
1545
- rows,
1546
- enabled: process.env.PM_CONTEXT_USAGE_DISABLED !== "1",
1547
- });
1548
- attachContextUsageServingReceipt(result, receipt);
1549
- }
1550
- catch {
1551
- result.warnings = mergeSortedWarnings(result.warnings, [
1552
- "context_usage_feedback_write_failed",
1553
- ]);
1554
- }
1555
- }
1556
- /** Resolve the optional static extension-health projection without module imports. */
1557
- export async function resolveContextExtensionHealthProjection(omitted, pmRoot, settings) {
1558
- if (omitted)
1559
- return {};
1560
- const discovery = await discoverExtensions({
1561
- pmRoot,
1562
- settings,
1563
- cwd: process.cwd(),
1564
- noExtensions: false,
1565
- });
1566
- const packages = discovery.discovered
1567
- .map((diagnostic) => ({
1568
- name: diagnostic.name ?? diagnostic.directory,
1569
- status: diagnostic.status === "ok" ? "ok" : "degraded",
1570
- }))
1571
- .sort((left, right) => left.name.localeCompare(right.name));
1572
- const degraded = packages.filter((entry) => entry.status === "degraded").length;
1573
- if (packages.length === 0)
1574
- return {};
1575
- return {
1576
- extension_health: {
1577
- total: packages.length,
1578
- ok: packages.length - degraded,
1579
- degraded,
1580
- packages: packages.slice(0, 20),
1581
- ...(packages.length > 20 ? { truncated: true } : {}),
1582
- },
1583
- };
1584
- }
1585
- async function resolveContextSemanticAffinity(pmRoot, author) {
1586
- const identity = detectAgentIdentity();
1587
- const semanticState = await readSessionState(pmRoot);
1588
- const attributionKey = identity.instance || semanticAttributionKey(author);
1589
- return semanticAttributionAffinity(semanticState.semantic_attribution?.[attributionKey]);
1590
- }
1591
- /** Implements run context for the public runtime surface of this module. */
1592
- export async function runContext(options, global) {
1593
- const pmRoot = resolvePmRoot(process.cwd(), global.path);
1594
- const resolvedRuntime = await resolveContextRuntime(options, global);
1595
- const corpus = await loadContextCorpus(global, resolvedRuntime);
1596
- const scaledLimit = resolveContextLimitAtScale(resolvedRuntime.limit, corpus.fullCorpus.length);
1597
- const runtime = {
1598
- ...resolvedRuntime,
1599
- limit: scaledLimit,
1600
- tokenBudget: resolveContextTokenBudget(options.tokenBudget, Math.max(256, scaledLimit * 160)),
1601
- };
1602
- const author = resolveAuthor(undefined, runtime.settings.author_default);
1603
- const claimFocus = await resolveContextSemanticAffinity(pmRoot, author);
1604
- const extensionHealthPromise = resolveContextExtensionHealthProjection(options.noExtensionHealth === true, pmRoot, runtime.settings);
1605
- // Single shared edge-aware blocked classification (GH-578): resolved against
1606
- // the full corpus so terminal blocker targets count as satisfied at every depth.
1607
- const blockedIds = collectDependencyBlockedIds(corpus.fullCorpus, runtime.statusRegistry);
1608
- const focusGroups = await resolveContextFocusGroups(corpus.listedItemMetadata, corpus.allItems, corpus.fullCorpus, blockedIds, runtime.statusRegistry, runtime.sectionsIncluded, runtime.limit, nowIso(), author, options.after, buildContextCursorFingerprint(options), shouldPageContextFocus(options, corpus.fullCorpus.length), pmRoot, runtime.tokenBudget, claimFocus, resolveItemTypeRegistry(runtime.settings, getActiveExtensionRegistrations()));
1609
- const agendaContext = await buildContextAgenda(global, runtime, corpus.subtreeIds, new Set([
1610
- ...focusGroups.highLevel,
1611
- ...focusGroups.lowLevel,
1612
- ...focusGroups.blockedFallback,
1613
- ].map((item) => item.id)));
1614
- const workspaceMemory = await readWorkspaceMemory(corpus.fullCorpus, {
1615
- pmRoot,
1616
- statusRegistry: runtime.statusRegistry,
1617
- now: agendaContext.agenda.now,
1618
- });
1619
- const warnings = mergeSortedWarnings(corpus.listed.warnings, agendaContext.agenda.warnings, focusGroups.ranking.warnings, [...focusGroups.featureStore.warnings], workspaceMemory.warnings);
1620
- const inProgressCount = countContextStatus(focusGroups.activeItems, runtime.statusRegistry.in_progress_status, runtime.statusRegistry);
1621
- const openCount = focusGroups.activeItems.length - inProgressCount;
1622
- const sections = await buildOptionalContextSections({
1623
- runtime,
1624
- allItems: corpus.allItems,
1625
- fullCorpus: corpus.fullCorpus,
1626
- blockedIds,
1627
- focusGroups,
1628
- now: agendaContext.agenda.now,
1629
- global,
1630
- });
1631
- const summaryExtras = buildContextSummaryExtras(corpus.allItems, runtime.statusRegistry, blockedIds);
1632
- const result = {
1633
- output_default: "toon",
1634
- now: agendaContext.agenda.now,
1635
- depth: runtime.depth,
1636
- sections_included: runtime.sectionsIncluded,
1637
- window: {
1638
- anchor: agendaContext.agenda.anchor,
1639
- start: agendaContext.agenda.range.start,
1640
- end: agendaContext.agenda.range.end,
1641
- past: agendaContext.agenda.range.past,
1642
- from: agendaContext.agenda.range.from,
1643
- to: agendaContext.agenda.range.to,
1644
- },
1645
- filters: {
1646
- type: options.type ?? null,
1647
- tag: options.tag ?? null,
1648
- priority: options.priority ?? null,
1649
- assignee: options.assignee ?? null,
1650
- assignee_filter: options.assigneeFilter ?? null,
1651
- sprint: options.sprint ?? null,
1652
- release: options.release ?? null,
1653
- limit: options.limit ?? options.maxItems ?? null,
1654
- parent: runtime.parentScope ?? null,
1655
- token_budget: runtime.tokenBudget,
1656
- /* c8 ignore next -- listed/calendar runtime filters are always materialized by their command handlers */
1657
- runtime_filters: (corpus.listed.filters.runtime_filters ??
1658
- agendaContext.agenda.filters.runtime_filters ??
1659
- {}),
1660
- },
1661
- summary: {
1662
- returned_focus: {
1663
- active_items: focusGroups.activeItems.length,
1664
- in_progress: inProgressCount,
1665
- open: openCount,
1666
- blocked: focusGroups.blockedItems.length,
1667
- },
1668
- blocked_fallback_used: focusGroups.blockedFallbackUsed,
1669
- high_level: focusGroups.highLevel.length,
1670
- low_level: focusGroups.lowLevel.length,
1671
- agenda_events: agendaContext.agendaSummary.events,
1672
- ...summaryExtras,
1673
- },
1674
- high_level: focusGroups.highLevel,
1675
- low_level: focusGroups.lowLevel,
1676
- blocked_fallback: focusGroups.blockedFallback,
1677
- agenda: {
1678
- summary: agendaContext.agendaSummary,
1679
- events: agendaContext.agendaEvents,
1680
- },
1681
- ...focusGroups.pageExtras,
1682
- };
1683
- result.workspace_memory = selectWorkspaceMemory(workspaceMemory, Math.min(800, Math.floor(runtime.tokenBudget * 0.2)));
1684
- Object.assign(result, await extensionHealthPromise);
1685
- attachOptionalContextSections(result, sections, focusGroups.featureStore.warning_details);
1686
- applyContextTagProjection(result, options.noTags === true);
1687
- if (options.explainRanking === true) {
1688
- result.ranking = toContextRankingSummary(focusGroups.ranking, focusGroups.featureStore, new Set([
1689
- ...focusGroups.highLevel,
1690
- ...focusGroups.lowLevel,
1691
- ...focusGroups.blockedFallback,
1692
- ].map((entry) => entry.id)));
1693
- result.packing = toContextPackingSummary(focusGroups.packing);
1694
- }
1695
- applyContextFocusProjection(result, runtime.focusFields);
1696
- if (warnings.length > 0)
1697
- result.warnings = warnings;
1698
- maybeAttachEmptyContextSuggestions(result, focusGroups.activeItems, focusGroups.blockedItems);
1699
- await attachContextUsageFeedback(result, focusGroups, pmRoot, author);
1700
- return result;
1701
- }
1
+ !(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]="ec0faae4-1fdb-5c7c-bcf1-eb338d73958a")}catch(e2){}})();import{SETTINGS_DEFAULTS,EXIT_CODE,PmCliError,compareTimestampStrings,nowIso,isTerminalStatus,normalizeStatusForRegistry,normalizeStatusInput,resolveRuntimeStatusRegistry,resolvePmRoot,readSettings,resolveAuthor,discoverExtensions,resolveItemTypeRegistry}from"../runtime-primitives.js";import{getActiveExtensionRegistrations}from"../../core/extensions/index.js";import{collectDependencyBlockedIds,resolveItemBlockers,resolveItemExecutionRole,computeActionabilityReport}from"../actionability.js";import{CONTEXT_DEPTH_VALUES,CONTEXT_SECTION_VALUES}from"../../types/index.js";import{parseIntegerLimit}from"./parsers.js";import{runCalendar}from"./calendar.js";import{runList}from"./list.js";import{runActivity}from"./activity.js";import{scoreContextCandidatesWithActiveExtensions}from"../context-relevance.js";import{buildItemContextRelevanceCandidates}from"../context-relevance.js";import{createQueryFingerprint,encodeQueryCursor,resolveQueryCursorStart,selectCursorSemanticOptions}from"../pagination.js";import{CONTEXT_FLAG_CONTRACTS}from"../cli-contracts/flag-contracts.js";import{packContextCandidates}from"../context-packing.js";import{attachContextUsageServingReceipt,collectContextUsageDeliveredItemIds,readContextUsageAffinity,recordContextUsageServing}from"../context-usage.js";import{readWorkspaceContextSignals}from"../context-signal-store.js";import{readWorkspaceMemory,selectWorkspaceMemory}from"../workspace-memory.js";import{detectAgentIdentity}from"../../core/shared/author.js";import{readSessionState,semanticAttributionKey}from"../../core/session/session-state.js";import{semanticAttributionAffinity}from"../context/semantic-session-attribution.js";const CONTEXT_OUTPUT_VALUES=["markdown","toon","json","ndjson"];const HIGH_LEVEL_TYPES=new Set(["Epic","Feature"]);const DEFAULT_CONTEXT_LIMIT=10;const CONTEXT_SCALE_THRESHOLD=1e4;const STANDARD_SECTIONS=["hierarchy","activity","progress","recently_created","unparented","workload"];const DEEP_SECTIONS=[...STANDARD_SECTIONS,"blockers","files","staleness","tests"];const LEADING_HYPHEN_DATE=/^(\d{4})-(\d{2})-(\d{2})/;const LEADING_COMPACT_DATE=/^(\d{4})(\d{2})(\d{2})(?:[T ]?\d{2}|$)/;const COMPACT_DATE=/^(\d{4})(\d{2})(\d{2})$/;const COMPACT_DATETIME=/^(\d{4})(\d{2})(\d{2})(?:[T\s]?)(\d{2})(\d{2})(\d{2})?(Z|[+-]\d{2}:?\d{2})?$/i;function parseOutputFormat(raw){if(!raw)return void 0;const normalized=raw.trim().toLowerCase();if(!CONTEXT_OUTPUT_VALUES.includes(normalized)){throw new PmCliError("Context format must be one of markdown|toon|json|ndjson",EXIT_CODE.USAGE)}return normalized}const FOCUS_PROJECTION_FIELDS=new Set(["id","title","type","status","priority","order","deadline","assignee","tags","tags_inherited","updated_at","parent","children_total","children_closed","completion_pct","blocked","blocker_ids","created_at"]);function parseContextFocusFields(raw){if(raw===void 0)return void 0;const fields=[];for(const token of raw.split(",")){const normalized=token.trim().toLowerCase();if(normalized.length===0)continue;if(!FOCUS_PROJECTION_FIELDS.has(normalized)){throw new PmCliError(`Context --fields value not projectable: ${normalized} (valid: ${[...FOCUS_PROJECTION_FIELDS].join(", ")})`,EXIT_CODE.USAGE)}if(!fields.includes(normalized))fields.push(normalized)}if(fields.length===0){throw new PmCliError("Context --fields requires at least one field name",EXIT_CODE.USAGE)}return fields}function projectContextFocusRows(rows,fields){return rows.map(row=>{const projected={};const source=row;for(const field of fields){projected[field]=source[field]??null}return projected})}function resolveContextOutputFormat(options,global2){const commandFormat=parseOutputFormat(options.format);if(global2.json&&commandFormat&&commandFormat!=="json"&&commandFormat!=="ndjson"){throw new PmCliError("Cannot combine --json with --format markdown|toon",EXIT_CODE.USAGE)}if(global2.json){return commandFormat==="ndjson"?"ndjson":"json"}return commandFormat??"toon"}function parseContextLimit(raw,depth){return parseIntegerLimit(raw,"--limit")??(depth==="full"?Number.MAX_SAFE_INTEGER:DEFAULT_CONTEXT_LIMIT)}function resolveContextTokenBudget(raw,fallback){if(raw===void 0)return fallback;const parsed=typeof raw==="number"?raw:Number(raw);if(!Number.isInteger(parsed)||parsed<1){throw new PmCliError("--token-budget must be a positive integer",EXIT_CODE.USAGE)}return parsed}function resolveContextLimitAtScale(limit,itemCount){return itemCount>=CONTEXT_SCALE_THRESHOLD&&limit===Number.MAX_SAFE_INTEGER?DEFAULT_CONTEXT_LIMIT:limit}function parseContextDepth(raw,settings){if(!raw)return settings.default_depth;const normalized=raw.trim().toLowerCase();if(!CONTEXT_DEPTH_VALUES.includes(normalized)){throw new PmCliError(`Context --depth must be one of ${CONTEXT_DEPTH_VALUES.join("|")}`,EXIT_CODE.USAGE)}return normalized}function parseContextSections(raw,depth,settings){if(raw&&raw.length>0){const sections=[];for(const value of raw){const normalized=value.trim().toLowerCase();if(!CONTEXT_SECTION_VALUES.includes(normalized)){throw new PmCliError(`Context --section must be one of ${CONTEXT_SECTION_VALUES.join("|")}`,EXIT_CODE.USAGE)}if(!sections.includes(normalized)){sections.push(normalized)}}return sections}if(depth==="brief")return[];if(depth==="full")return[...CONTEXT_SECTION_VALUES];const pool=depth==="deep"?DEEP_SECTIONS:STANDARD_SECTIONS;return pool.filter(section=>settings.sections[section])}function parseActivityLimit(raw,settings){if(!raw)return settings.activity_limit;const parsed=parseIntegerLimit(raw,"--activity-limit");return parsed??settings.activity_limit}function parseStaleThresholdDays(raw,settings){if(!raw)return settings.stale_threshold_days;const trimmed=raw.trim().toLowerCase();const match=/^(\d+)d?$/.exec(trimmed);if(!match){throw new PmCliError("--stale-threshold must be a number of days (e.g. 7 or 7d)",EXIT_CODE.USAGE)}const days=parseInt(match[1],10);if(days<=0){throw new PmCliError("--stale-threshold must be positive",EXIT_CODE.USAGE)}return days}function statusRank(status,statusRegistry){const normalizedStatus=normalizeStatusForRegistry(status,statusRegistry);const blockedStatus=normalizeStatusInput("blocked",statusRegistry);const draftStatus=normalizeStatusInput("draft",statusRegistry);if(normalizedStatus===statusRegistry.in_progress_status)return 0;if(statusRegistry.active_statuses.has(normalizedStatus))return 1;if(blockedStatus&&normalizedStatus===blockedStatus)return 2;if(draftStatus&&normalizedStatus===draftStatus)return 3;if(statusRegistry.blocked_statuses.has(normalizedStatus))return 5;if(statusRegistry.terminal_statuses.has(normalizedStatus))return 7;return 6}function isClosedStatus(status,statusRegistry){const closeStatus=normalizeStatusInput("closed",statusRegistry);return normalizeStatusForRegistry(status,statusRegistry)===closeStatus}function isInProgressStatus(status,statusRegistry){return normalizeStatusForRegistry(status,statusRegistry)===statusRegistry.in_progress_status}function isOpenStatus(status,statusRegistry){const normalizedStatus=normalizeStatusForRegistry(status,statusRegistry);return normalizedStatus!==statusRegistry.in_progress_status&&statusRegistry.active_statuses.has(normalizedStatus)}function isBlockedStatus(status,statusRegistry){return statusRegistry.blocked_statuses.has(normalizeStatusForRegistry(status,statusRegistry))}const LIST_PROJECTION_FLAGS=["compact","brief","fields","includeBody","include_body","parent"];function stripListProjectionFlags(options){const copy={...options};for(const key of LIST_PROJECTION_FLAGS){delete copy[key]}return copy}function collectSubtreeIds(corpus,parentId){const target=parentId.trim().toLowerCase();const anchor=corpus.find(item=>item.id.trim().toLowerCase()===target);if(!anchor){return{ids:new Set,found:false}}const childrenByParent=buildChildrenByParent(corpus);const descendants=collectDescendants(anchor.id,childrenByParent);const ids=new Set([anchor.id,...descendants.map(item=>item.id)].map(id=>id.trim().toLowerCase()));return{ids,found:true}}function parseContextParent(raw){if(raw===void 0)return void 0;const trimmed=raw.trim();if(trimmed.length===0){throw new PmCliError("Context --parent requires an item id",EXIT_CODE.USAGE)}return trimmed}function compareOptionalOrder(left,right){const leftValue=left??null;const rightValue=right??null;if(leftValue===null&&rightValue===null)return 0;if(leftValue===null)return 1;if(rightValue===null)return-1;return leftValue-rightValue}function compareOptionalDeadline(left,right){const leftValue=left??null;const rightValue=right??null;if(leftValue===null&&rightValue===null)return 0;if(leftValue===null)return 1;if(rightValue===null)return-1;return compareTimestampStrings(leftValue,rightValue)}function daysInUtcMonth(year,monthIndex){return new Date(Date.UTC(year,monthIndex+1,0)).getUTCDate()}function hasNoInvalidDatePrefix(value){const match=LEADING_HYPHEN_DATE.exec(value)??LEADING_COMPACT_DATE.exec(value);if(!match){return true}const year=Number.parseInt(match[1],10);const month=Number.parseInt(match[2],10);const day=Number.parseInt(match[3],10);return month>=1&&month<=12&&day>=1&&day<=daysInUtcMonth(year,month-1)}function normalizeTimestampCandidate(value){const compactDate=COMPACT_DATE.exec(value);if(compactDate){return`${compactDate[1]}-${compactDate[2]}-${compactDate[3]}`}const compactDateTime=COMPACT_DATETIME.exec(value);if(compactDateTime){const[,year,month,day,hour,minute,secondRaw,offsetRaw]=compactDateTime;const second=secondRaw?`:${secondRaw}`:"";const offset=offsetRaw&&offsetRaw.length===5&&offsetRaw!=="Z"?`${offsetRaw.slice(0,3)}:${offsetRaw.slice(3)}`:offsetRaw??"";return`${year}-${month}-${day}T${hour}:${minute}${second}${offset}`}return value}function parseContextTimestampMs(value){if(typeof value!=="string"){return Number.NaN}const trimmed=value.trim();if(trimmed.length===0||!hasNoInvalidDatePrefix(trimmed)){return Number.NaN}const parsed=Date.parse(normalizeTimestampCandidate(trimmed));return Number.isFinite(parsed)?parsed:Number.NaN}function sortableTimestamp(value){const parsed=parseContextTimestampMs(value);return Number.isFinite(parsed)?new Date(parsed).toISOString():""}function dateTokenForTimestamp(value){const parsed=parseContextTimestampMs(value);return Number.isFinite(parsed)?new Date(parsed).toISOString().slice(0,10):"unknown"}function normalizedParentId(value){if(typeof value!=="string"){return null}const trimmed=value.trim();return trimmed.length>0?trimmed:null}function compareCriticalItems(left,right,statusRegistry){const byStatus=statusRank(left.status,statusRegistry)-statusRank(right.status,statusRegistry);if(byStatus!==0)return byStatus;const byPriority=left.priority-right.priority;if(byPriority!==0)return byPriority;const byOrder=compareOptionalOrder(left.order,right.order);if(byOrder!==0)return byOrder;const byDeadline=compareOptionalDeadline(left.deadline,right.deadline);if(byDeadline!==0)return byDeadline;const byUpdated=compareTimestampStrings(sortableTimestamp(right.updated_at),sortableTimestamp(left.updated_at));const byId=left.id.localeCompare(right.id);return byUpdated!==0?byUpdated:byId}function estimateJsonTokens(value){return Math.max(1,Math.ceil(Buffer.byteLength(JSON.stringify(value),"utf8")/4))}function packRankedContextItems(report,tokenBudget,requiredIds=new Set,profile="context"){return packContextCandidates(report.ranked.map(entry=>({id:entry.id,item:entry.item,rank:entry.rank,score:entry.score,required:requiredIds.has(entry.id),cluster:entry.item.parent?.trim()||entry.item.type,token_costs:{identity:estimateJsonTokens({id:entry.id,title:entry.item.title}),summary:estimateJsonTokens({id:entry.id,title:entry.item.title,type:entry.item.type,status:entry.item.status,priority:entry.item.priority,parent:entry.item.parent}),full:estimateJsonTokens(entry.item)}})),{tokenBudget,profile,latencyBudgetMs:25})}function toContextPackingSummary(report){return{...report,included:report.included.map(entry=>({id:entry.id,projection:entry.projection,tokens:entry.tokens}))}}function toContextRankingSummary(report,featureStore,servedItemIds){const ranked=servedItemIds===void 0?report.ranked:report.ranked.filter(entry=>servedItemIds.has(entry.id));return{model:report.model,available_signals:report.available_signals,items:ranked.map(entry=>({id:entry.id,rank:entry.rank,baseline_rank:entry.baseline_rank,score:entry.score,contributions:entry.contributions,...entry.signal_provenance===void 0?{}:{recency:entry.signal_provenance.recency}})),candidate_count:report.ranked.length,omitted_count:report.ranked.length-ranked.length,...featureStore?{feature_store:{source:featureStore.snapshot.source,cache_status:featureStore.cache_status,source_cursor:featureStore.snapshot.source_cursor,generated_at:featureStore.snapshot.generated_at}}:{}}}function completionPct(closed,total){return total>0?Math.round(closed/total*100):0}function buildChildrenByParent(allItems){const childrenByParent=new Map;for(const item of allItems){const parent=normalizedParentId(item.parent);if(!parent)continue;const children=childrenByParent.get(parent)??[];children.push(item);childrenByParent.set(parent,children)}return childrenByParent}function toContextFocusItem(item,statusRegistry,childrenByParent){const focus={id:item.id,title:item.title,type:item.type,status:item.status,priority:item.priority,order:item.order??null,deadline:item.deadline??null,assignee:item.assignee??null,tags:Array.isArray(item.tags)?[...item.tags]:[],updated_at:item.updated_at,parent:normalizedParentId(item.parent)};if(statusRegistry&&childrenByParent){const descendants=collectDescendants(item.id,childrenByParent);const total=descendants.length;if(total>0){const closed=descendants.filter(desc=>isClosedStatus(desc.status,statusRegistry)).length;focus.children_total=total;focus.children_closed=closed;focus.completion_pct=completionPct(closed,total)}}return focus}function summarizeAgenda(events){let deadlines=0;let reminders=0;let scheduled=0;const itemIds=new Set;for(const event of events){itemIds.add(event.item_id);if(event.kind==="deadline"){deadlines+=1;continue}if(event.kind==="reminder"){reminders+=1;continue}scheduled+=1}return{events:events.length,items:itemIds.size,deadlines,reminders,scheduled}}function mergeSortedWarnings(...warningGroups){return[...new Set(warningGroups.flatMap(group=>group??[]))].sort((left,right)=>left.localeCompare(right))}function filterTerminalCalendarEvents(events,statusRegistry){return events.filter(event=>!statusRegistry.terminal_statuses.has(normalizeStatusForRegistry(event.item_status,statusRegistry)))}function buildHierarchy(allItems,activeItems,statusRegistry,limit){const itemMap=new Map;for(const item of allItems){itemMap.set(item.id,item)}const childrenByParent=buildChildrenByParent(allItems);const activeHighLevelIds=new Set(activeItems.filter(item=>HIGH_LEVEL_TYPES.has(item.type)).map(item=>item.id));const nodes=[];for(const parentId of activeHighLevelIds){const parent=itemMap.get(parentId);if(!parent)continue;const allDescendants=collectDescendants(parentId,childrenByParent);const childItems=childrenByParent.get(parentId)??[];let closedCount=0;let openCount=0;let inProgressCount=0;let blockedCount=0;for(const desc of allDescendants){if(isClosedStatus(desc.status,statusRegistry))closedCount++;else if(isInProgressStatus(desc.status,statusRegistry))inProgressCount++;else if(isBlockedStatus(desc.status,statusRegistry))blockedCount++;else if(isOpenStatus(desc.status,statusRegistry))openCount++}const children=childItems.sort((a,b)=>compareCriticalItems(a,b,statusRegistry)).slice(0,limit).map(child=>{const grandchildren=collectDescendants(child.id,childrenByParent);const gcClosed=grandchildren.filter(gc=>isClosedStatus(gc.status,statusRegistry)).length;return{id:child.id,title:child.title,type:child.type,status:child.status,children_total:grandchildren.length,children_closed:gcClosed}});nodes.push({id:parent.id,title:parent.title,type:parent.type,status:parent.status,children_total:allDescendants.length,children_closed:closedCount,children_open:openCount,children_in_progress:inProgressCount,children_blocked:blockedCount,children})}return nodes.sort((a,b)=>{const aParent=itemMap.get(a.id);const bParent=itemMap.get(b.id);return compareCriticalItems(aParent,bParent,statusRegistry)}).slice(0,limit)}function collectDescendants(parentId,childrenByParent){const result=[];const stack=[parentId];const visited=new Set;while(stack.length>0){const current=stack.pop();if(visited.has(current))continue;visited.add(current);const children=childrenByParent.get(current)??[];for(const child of children){result.push(child);stack.push(child.id)}}return result}const _testOnly={buildActivity,buildBlockers,buildChildrenByParent,buildHierarchy,buildHotFiles,buildProgress,buildRecentlyCreated,buildStaleness,buildTestHealth,buildUnparented,buildWorkload,collectDescendants,collectSubtreeIds,compareCriticalItems,compareOptionalDeadline,compareOptionalOrder,completionPct,dateTokenForTimestamp,filterTerminalCalendarEvents,formatAgendaLine,isBlockedStatus,isClosedStatus,isInProgressStatus,isOpenStatus,mergeSortedWarnings,normalizedParentId,parseActivityLimit,parseContextLimit,resolveContextLimitAtScale,parseContextParent,parseContextTimestampMs,parseStaleThresholdDays,sortableTimestamp,statusRank,stripListProjectionFlags,summarizeAgenda,toContextFocusItem};async function buildActivity(activityLimit,global2){const result=await runActivity({compact:true,limit:String(activityLimit)},global2);return result.compact_activity??[]}function buildProgress(allItems,activeItems,blockedIds,statusRegistry,limit){const childrenByParent=new Map;for(const item of allItems){if(!item.parent)continue;const children=childrenByParent.get(item.parent)??[];children.push(item);childrenByParent.set(item.parent,children)}const activeHighLevel=activeItems.filter(item=>HIGH_LEVEL_TYPES.has(item.type));const entries=[];for(const parent of activeHighLevel){const descendants=collectDescendants(parent.id,childrenByParent);const total=descendants.length;if(total===0)continue;let closed=0;let open=0;let inProgress=0;let blocked=0;for(const desc of descendants){if(isClosedStatus(desc.status,statusRegistry))closed++;else if(blockedIds.has(desc.id.trim().toLowerCase()))blocked++;else if(isInProgressStatus(desc.status,statusRegistry))inProgress++;else if(isOpenStatus(desc.status,statusRegistry))open++}entries.push({id:parent.id,title:parent.title,type:parent.type,total,closed,open,in_progress:inProgress,blocked,completion_pct:completionPct(closed,total)})}return entries.sort((a,b)=>a.completion_pct-b.completion_pct).slice(0,limit)}function buildBlockers(blockedItems,fullCorpus,statusRegistry,limit){const itemsById=new Map(fullCorpus.map(item=>[item.id.trim().toLowerCase(),item]));return blockedItems.slice(0,limit).map(item=>{const blockers=resolveItemBlockers(item,itemsById,statusRegistry);const blockedBy=blockers.find(blocker=>!blocker.resolved)?.id??blockers[0]?.id??null;const blockerItem=blockedBy?itemsById.get(blockedBy.trim().toLowerCase()):void 0;return{id:item.id,title:item.title,blocked_by:blockedBy,blocked_by_title:blockerItem?.title??null,blocked_by_status:blockerItem?.status??null,blocked_reason:item.blocked_reason??null,unblock_note:item.unblock_note??null}})}function buildHotFiles(activeItems,limit){const fileMap=new Map;for(const item of activeItems){for(const file of item.files??[]){const existing=fileMap.get(file.path)??new Set;existing.add(item.id);fileMap.set(file.path,existing)}}return[...fileMap.entries()].map(([filePath,itemIds])=>({path:filePath,references:itemIds.size,items:[...itemIds].sort()})).sort((a,b)=>b.references-a.references).slice(0,limit)}function buildWorkload(activeItems,statusRegistry,limit){const groups=new Map;for(const item of activeItems){const key=item.assignee??null;const existing=groups.get(key)??[];existing.push(item);groups.set(key,existing)}return[...groups.entries()].map(([assignee,items])=>({assignee,active:items.length,in_progress:items.filter(item=>isInProgressStatus(item.status,statusRegistry)).length,items:items.map(item=>item.id).sort()})).sort((a,b)=>b.active-a.active).slice(0,limit)}function buildStaleness(allNonTerminal,staleThresholdDays,now,limit){const cutoffMs=new Date(now).getTime()-staleThresholdDays*24*60*60*1e3;return allNonTerminal.filter(item=>new Date(item.updated_at).getTime()<cutoffMs).map(item=>({id:item.id,title:item.title,status:item.status,updated_at:item.updated_at,stale_days:Math.floor((new Date(now).getTime()-new Date(item.updated_at).getTime())/(24*60*60*1e3))})).sort((a,b)=>b.stale_days-a.stale_days).slice(0,limit)}function buildRecentlyCreated(allNonTerminal,statusRegistry,childrenByParent,limit){return allNonTerminal.map(item=>({item,sortKey:sortableTimestamp(item.created_at)})).sort((left,right)=>{const byCreated=compareTimestampStrings(right.sortKey,left.sortKey);return byCreated!==0?byCreated:left.item.id.localeCompare(right.item.id)}).slice(0,limit).map(({item})=>({...toContextFocusItem(item,statusRegistry,childrenByParent),created_at:item.created_at}))}function buildUnparented(allNonTerminal,statusRegistry,childrenByParent,limit){return allNonTerminal.filter(item=>!normalizedParentId(item.parent)&&!HIGH_LEVEL_TYPES.has(item.type)).sort((left,right)=>compareCriticalItems(left,right,statusRegistry)).slice(0,limit).map(item=>toContextFocusItem(item,statusRegistry,childrenByParent))}function buildTestHealth(activeItems){let itemsWithTests=0;let itemsWithRecentRuns=0;let passed=0;let failed=0;let skipped=0;const itemsFailing=[];for(const item of activeItems){if((item.tests??[]).length>0){itemsWithTests++}const runs=item.test_runs??[];if(runs.length>0){itemsWithRecentRuns++;let itemHasFailure=false;for(const run of runs){passed+=run.passed??0;failed+=run.failed??0;skipped+=run.skipped??0;if((run.failed??0)>0){itemHasFailure=true}}if(itemHasFailure){itemsFailing.push(item.id)}}}return{items_with_tests:itemsWithTests,items_with_recent_runs:itemsWithRecentRuns,recent_runs:{passed,failed,skipped},items_failing:itemsFailing.sort()}}function formatClock(timestamp){return`${new Date(timestamp).toISOString().slice(11,16)}Z`}function formatFocusLine(item){const orderToken=item.order===null?"-":String(item.order);const deadlineToken=item.deadline??"-";const parentToken=item.parent?` parent:${item.parent}`:"";const progressToken=item.children_total!==void 0&&item.children_closed!==void 0&&item.completion_pct!==void 0?` children:${item.children_closed}/${item.children_total} done:${item.completion_pct}%`:"";const blockedToken=item.blocked===true?` blocked:${item.blocker_ids?.join(",")||"lifecycle"}`:"";return`${item.id} p${item.priority} ${item.status} ${item.type} order:${orderToken} deadline:${deadlineToken}${parentToken}${progressToken}${blockedToken} ${item.title}`}function formatProjectedFocusLine(item,fields){const source=item;return fields.map(field=>{const value=source[field];if(Array.isArray(value))return`${field}:${value.join(",")}`;return`${field}:${value??"-"}`}).join(" ")}function formatAgendaLine(event){if("reference_only"in event){const suffix=event.kind==="reminder"?` \u2014 ${event.reminder_text??"reminder"}`:event.kind==="event"?` \u2014 ${event.event_title??"event"}${event.event_recurring?" (recurring)":""}`:"";return`${formatClock(event.at)} [${event.kind}] ${event.item_id} (see focus item)${suffix}`}const base=`${formatClock(event.at)} [${event.kind}] ${event.item_id} p${event.item_priority} ${event.item_status} ${event.item_title}`;if(event.kind==="reminder"){return`${base} \u2014 ${event.reminder_text}`}if(event.kind==="event"){const recurringSuffix=event.event_recurring?" (recurring)":"";const title=event.event_title??event.item_title;return`${base} \u2014 ${title}${recurringSuffix}`}return base}function pushContextFocusSection(lines,title,rows,emptyText,renderFocus){lines.push(`## ${title}`);if(rows.length===0){lines.push(emptyText)}else{for(const item of rows){lines.push(`- ${renderFocus(item)}`)}}lines.push("")}function pushBlockedFallbackSection(lines,result,renderFocus){if(result.blocked_fallback.length===0){return}lines.push("## Blocked fallback");for(const item of result.blocked_fallback){lines.push(`- ${renderFocus(item)}`)}lines.push("")}function pushAgendaSection(lines,result){lines.push("## Agenda");lines.push(`- events: ${result.agenda.summary.events} (deadlines: ${result.agenda.summary.deadlines}, reminders: ${result.agenda.summary.reminders}, scheduled: ${result.agenda.summary.scheduled})`);if(result.agenda.events.length===0){lines.push("No agenda events matched the selected filters.")}else{for(const event of result.agenda.events){lines.push(`- ${formatAgendaLine(event)}`)}}lines.push("")}function pushHierarchySection(lines,result){if(!result.hierarchy||result.hierarchy.length===0){return}lines.push("## Hierarchy");for(const node of result.hierarchy){const pct=node.children_total>0?Math.round(node.children_closed/node.children_total*100):0;lines.push(`- ${node.id} ${node.type} ${node.status} "${node.title}" [${node.children_closed}/${node.children_total} done ${pct}%]`);for(const child of node.children){const cpct=child.children_total>0?Math.round(child.children_closed/child.children_total*100):0;lines.push(` - ${child.id} ${child.type} ${child.status} "${child.title}" [${child.children_closed}/${child.children_total} done ${cpct}%]`)}}lines.push("")}function pushProgressSection(lines,result){if(!result.progress||result.progress.length===0){return}lines.push("## Progress");for(const entry of result.progress){lines.push(`- ${entry.id} "${entry.title}" ${entry.completion_pct}% (${entry.closed}/${entry.total} closed, ${entry.in_progress} wip, ${entry.open} open, ${entry.blocked} blocked)`)}lines.push("")}function pushRecentlyCreatedSection(lines,result,focusFields,renderFocus){if(!result.recently_created||result.recently_created.length===0){return}lines.push("## Recently created");for(const item of result.recently_created){lines.push(focusFields?`- ${renderFocus(item)}`:`- ${dateTokenForTimestamp(item.created_at)} ${formatFocusLine(item)}`)}lines.push("")}function pushUnparentedSection(lines,result,renderFocus){if(!result.unparented||result.unparented.length===0){return}lines.push("## Unparented");for(const item of result.unparented){lines.push(`- ${renderFocus(item)}`)}lines.push("")}function pushActivitySection(lines,result){if(!result.activity||result.activity.length===0){return}lines.push("## Recent activity");for(const entry of result.activity){const msg=entry.msg?` ${entry.msg}`:"";lines.push(`- ${entry.ts.slice(0,16)}Z ${entry.id} ${entry.op} by:${entry.author}${msg}`)}lines.push("")}function pushBlockersSection(lines,result){if(!result.blockers||result.blockers.length===0){return}lines.push("## Blockers");for(const entry of result.blockers){const by=entry.blocked_by?`blocked_by:${entry.blocked_by}(${entry.blocked_by_status??"?"})`:"blocked_by:-";const reason=entry.blocked_reason?` reason:"${entry.blocked_reason}"`:"";const note=entry.unblock_note?` unblock:"${entry.unblock_note}"`:"";lines.push(`- ${entry.id} "${entry.title}" ${by}${reason}${note}`)}lines.push("")}function pushFilesSection(lines,result){if(!result.files||result.files.length===0){return}lines.push("## Hot files");for(const file of result.files){lines.push(`- ${file.path} refs:${file.references} items:[${file.items.join(",")}]`)}lines.push("")}function pushWorkloadSection(lines,result){if(!result.workload||result.workload.length===0){return}lines.push("## Workload");for(const entry of result.workload){const who=entry.assignee??"(unassigned)";lines.push(`- ${who} active:${entry.active} wip:${entry.in_progress} items:[${entry.items.join(",")}]`)}lines.push("")}function pushStalenessSection(lines,result){if(!result.staleness||result.staleness.length===0){return}lines.push("## Stale items");for(const entry of result.staleness){lines.push(`- ${entry.id} ${entry.status} stale:${entry.stale_days}d last:${entry.updated_at.slice(0,10)} "${entry.title}"`)}lines.push("")}function pushTestHealthSection(lines,result){if(!result.tests){return}lines.push("## Test health");lines.push(`- items_with_tests: ${result.tests.items_with_tests}`);lines.push(`- items_with_recent_runs: ${result.tests.items_with_recent_runs}`);lines.push(`- passed: ${result.tests.recent_runs.passed}, failed: ${result.tests.recent_runs.failed}, skipped: ${result.tests.recent_runs.skipped}`);if(result.tests.items_failing.length>0){lines.push(`- items_failing: [${result.tests.items_failing.join(",")}]`)}lines.push("")}function pushEmptyContextSuggestions(lines,result){const isEmpty=result.summary.active_items===0&&result.summary.blocked===0&&result.agenda.summary.events===0;if(!isEmpty){return}lines.push("## Suggestions");lines.push("No active work items or upcoming events. Consider:");lines.push('- `pm create --type Task --title "..."` to add a new work item');lines.push("- `pm list --status closed --limit 5` to review recent completions");lines.push("- `pm search <keywords>` to find related past work");lines.push("- `pm aggregate` for a full project status overview")}function renderContextMarkdown(result){const lines=[];const focusFields=result.focus_fields;const renderFocus=item=>focusFields?formatProjectedFocusLine(item,focusFields):formatFocusLine(item);lines.push("# pm context");lines.push("");lines.push(`- now: ${result.now}`);lines.push(`- depth: ${result.depth}`);if(result.filters.parent){lines.push(`- scope: subtree of ${result.filters.parent}`)}lines.push(`- active_items: ${result.summary.active_items} (in_progress: ${result.summary.in_progress}, open: ${result.summary.open})`);if(result.summary.total_items!==void 0){lines.push(`- total_items: ${result.summary.total_items} (closed: ${result.summary.closed??0}, canceled: ${result.summary.canceled??0})`)}lines.push(`- agenda_events: ${result.summary.agenda_events}`);lines.push(`- blocked_fallback_used: ${result.summary.blocked_fallback_used}`);if(result.extension_health){const degradedNames=result.extension_health.packages.filter(entry=>entry.status==="degraded").map(entry=>entry.name);lines.push(`- extensions: ${result.extension_health.ok} ok, ${result.extension_health.degraded} degraded${degradedNames.length>0?` (${degradedNames.join(", ")})`:""}`)}const renderedSections=result.sections_included.filter(section=>section!=="blockers"||(result.blockers?.length??0)>0);if(renderedSections.length>0){lines.push(`- sections: ${renderedSections.join(", ")}`)}lines.push("");pushContextFocusSection(lines,"High-level focus",result.high_level,"No high-level active items.",renderFocus);pushContextFocusSection(lines,"Low-level focus",result.low_level,"No low-level active items.",renderFocus);pushBlockedFallbackSection(lines,result,renderFocus);pushAgendaSection(lines,result);if(result.workspace_memory){lines.push("## Workspace memory");for(const rollup of result.workspace_memory.rollups){lines.push(`- ${rollup.kind}:${rollup.key} \u2014 ${rollup.label} (${rollup.item_count} completed, latest ${rollup.last_closed_at})`)}lines.push("")}pushHierarchySection(lines,result);pushProgressSection(lines,result);pushRecentlyCreatedSection(lines,result,focusFields,renderFocus);pushUnparentedSection(lines,result,renderFocus);pushActivitySection(lines,result);pushBlockersSection(lines,result);pushFilesSection(lines,result);pushWorkloadSection(lines,result);pushStalenessSection(lines,result);pushTestHealthSection(lines,result);pushEmptyContextSuggestions(lines,result);return lines.join("\n")}async function resolveContextRuntime(options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);const settings=await readSettings(pmRoot);const contextSettings=settings.context??SETTINGS_DEFAULTS.context;const statusRegistry=resolveRuntimeStatusRegistry(settings.schema);const depth=parseContextDepth(options.depth,contextSettings);const limit=parseContextLimit(options.limit??options.maxItems,depth);return{settings,contextSettings,statusRegistry,depth,limit,sectionsIncluded:parseContextSections(options.section,depth,contextSettings),activityLimit:parseActivityLimit(options.activityLimit,contextSettings),staleThresholdDays:parseStaleThresholdDays(options.staleThreshold,contextSettings),parentScope:parseContextParent(options.parent),focusFields:parseContextFocusFields(options.fields),baseListOptions:stripListProjectionFlags(options)}}function contextNeedsAllItems(sectionsIncluded){return sectionsIncluded.some(section=>["hierarchy","progress","blockers","staleness","recently_created","unparented"].includes(section))}function buildUnpaginatedContextListOptions(baseListOptions,extra){return{...baseListOptions,...extra,noTruncate:true,limit:void 0,offset:void 0,after:void 0}}async function loadContextCorpus(global2,runtime){const listed=await runList(void 0,buildUnpaginatedContextListOptions(runtime.baseListOptions,{excludeTerminal:false}),global2);const fullCorpus=listed.items;let listedItemMetadata=fullCorpus.filter(item=>!isTerminalStatus(item.status,runtime.statusRegistry));let allItems=fullCorpus;const subtreeIds=resolveContextSubtreeIds(runtime.parentScope,fullCorpus);if(subtreeIds){listedItemMetadata=listedItemMetadata.filter(item=>subtreeIds.has(item.id.trim().toLowerCase()));allItems=allItems.filter(item=>subtreeIds.has(item.id.trim().toLowerCase()))}return{listed,listedItemMetadata,allItems,fullCorpus,subtreeIds}}function resolveContextSubtreeIds(parentScope,fullCorpus){if(parentScope===void 0){return void 0}const subtree=collectSubtreeIds(fullCorpus,parentScope);if(!subtree.found){throw new PmCliError(`Context --parent item not found: ${parentScope}`,EXIT_CODE.NOT_FOUND)}return subtree.ids}function collectHighLevelContextIds(activeItems,fullCorpus,statusRegistry,typeRegistry){const containers=new Set(computeActionabilityReport(activeItems,fullCorpus,statusRegistry,typeRegistry).containers.map(entry=>entry.item.id));return new Set(activeItems.filter(item=>HIGH_LEVEL_TYPES.has(item.type)||containers.has(item.id)||resolveItemExecutionRole(item.type,typeRegistry)!=="agent").map(item=>item.id))}async function resolveContextFocusGroups(listedItemMetadata,allItems,fullCorpus,blockedIds,statusRegistry,sectionsIncluded,limit,now,author,cursor,cursorFingerprint,useBoundedPage,pmRoot,tokenBudget,claimFocus,typeRegistry){const structural=[...listedItemMetadata].sort((left,right)=>compareCriticalItems(left,right,statusRegistry));const usage=await readContextUsageAffinity({pmRoot,author,enabled:process.env.PM_CONTEXT_USAGE_DISABLED!=="1"});const featureStore=await readWorkspaceContextSignals(structural,{pmRoot,storeKey:"context",statusRegistry,now,author,usageAffinity:usage.affinity,claimFocus});const ranking=await scoreContextCandidatesWithActiveExtensions("context",featureStore.candidates);const ranked=ranking.ranked.map(entry=>entry.item);const activeStatuses=statusRegistry.active_statuses;const rankedActiveItems=ranked.filter(item=>activeStatuses.has(normalizeStatusForRegistry(item.status,statusRegistry)));const pageStart=useBoundedPage?resolveQueryCursorStart(rankedActiveItems,cursor,cursorFingerprint,item=>item.id):0;const focusPage=useBoundedPage?rankedActiveItems.slice(pageStart,pageStart+limit):rankedActiveItems;const hasMore=useBoundedPage&&focusPage.length>0&&pageStart+focusPage.length<rankedActiveItems.length;const nextCursor=hasMore&&focusPage.length>0?encodeQueryCursor(cursorFingerprint,focusPage[focusPage.length-1].id,pageStart+focusPage.length-1):void 0;const rankedBlockedItems=ranked.filter(item=>blockedIds.has(item.id.trim().toLowerCase()));const packingIds=new Set([...focusPage.map(item=>item.id),...rankedBlockedItems.slice(0,limit).map(item=>item.id)]);const packing=packRankedContextItems({...ranking,ranked:ranking.ranked.filter(entry=>packingIds.has(entry.id))},tokenBudget,new Set(Object.entries(claimFocus??{}).filter(([,affinity])=>affinity>=1).map(([id])=>id)));const packedItems=packing.included.map(entry=>entry.item);const activeItems=packedItems.filter(item=>activeStatuses.has(normalizeStatusForRegistry(item.status,statusRegistry)));const blockedItems=packedItems.filter(item=>blockedIds.has(item.id.trim().toLowerCase()));const childrenByParent=buildChildrenByParent(allItems);const focusChildrenByParent=contextNeedsAllItems(sectionsIncluded)?childrenByParent:void 0;const fullCorpusById=new Map(fullCorpus.map(item=>[item.id.trim().toLowerCase(),item]));const projectFocusItem=item=>{const focus=toContextFocusItem(item,statusRegistry,focusChildrenByParent);if(!blockedIds.has(item.id.trim().toLowerCase())){return focus}focus.blocked=true;focus.blocker_ids=resolveItemBlockers(item,fullCorpusById,statusRegistry).filter(blocker=>!blocker.resolved).map(blocker=>blocker.id);return focus};const highLevelIds=collectHighLevelContextIds(activeItems,fullCorpus,statusRegistry,typeRegistry);const highLevel=activeItems.filter(item=>highLevelIds.has(item.id)).slice(0,useBoundedPage?focusPage.length:limit).map(projectFocusItem);const lowLevel=activeItems.filter(item=>!highLevelIds.has(item.id)).slice(0,useBoundedPage?focusPage.length:limit).map(projectFocusItem);const blockedFallbackUsed=rankedActiveItems.length===0;return{activeItems,blockedItems,highLevel,lowLevel,blockedFallback:blockedFallbackUsed?blockedItems.slice(0,limit).map(projectFocusItem):[],blockedFallbackUsed,ranking,packing,featureStore,pageExtras:{...useBoundedPage?{applied_limit:limit}:{},...hasMore?{has_more:true,truncated:true}:{},...nextCursor?{next_cursor:nextCursor}:{}}}}function buildContextCursorFingerprint(options){return createQueryFingerprint("context",selectCursorSemanticOptions(options,CONTEXT_FLAG_CONTRACTS))}function shouldPageContextFocus(options,corpusItemCount){return options.limit!==void 0||options.maxItems!==void 0||options.after!==void 0||corpusItemCount>=CONTEXT_SCALE_THRESHOLD}async function buildContextAgenda(global2,runtime,subtreeIds,listedFocusIds){const calendarOptions={...runtime.baseListOptions,view:"agenda",include:"all",limit:runtime.parentScope===void 0?String(runtime.limit):void 0};const agenda=await runCalendar(calendarOptions,global2);const scopedAgenda=subtreeIds===void 0?agenda.events:agenda.events.filter(event=>subtreeIds.has(event.item_id.trim().toLowerCase()));const fullAgendaEvents=filterTerminalCalendarEvents(scopedAgenda,runtime.statusRegistry).slice(0,runtime.limit);const agendaEvents=fullAgendaEvents.map(event=>{if(!listedFocusIds.has(event.item_id)){return event}return{at:event.at,date:event.date,kind:event.kind,item_id:event.item_id,reference_only:true,...event.kind==="reminder"?{reminder_text:event.reminder_text}:{},...event.kind==="event"?{event_title:event.event_title,event_recurring:event.event_recurring}:{}}});return{agenda,agendaEvents,agendaSummary:summarizeAgenda(fullAgendaEvents)}}function countContextStatus(items,status,statusRegistry){const targetStatus=String(status);return items.filter(item=>normalizeStatusForRegistry(item.status,statusRegistry)===targetStatus).length}async function buildOptionalContextSections(params){const{runtime,allItems,fullCorpus,blockedIds,focusGroups,now,global:global2}=params;const childrenByParent=buildChildrenByParent(allItems);const allNonTerminal=allItems.filter(item=>!isTerminalStatus(item.status,runtime.statusRegistry));const has=section=>runtime.sectionsIncluded.includes(section);return{hierarchy:has("hierarchy")?buildHierarchy(allItems,focusGroups.activeItems,runtime.statusRegistry,runtime.limit):void 0,activity:has("activity")?await buildActivity(runtime.activityLimit,global2):void 0,progress:has("progress")?buildProgress(allItems,focusGroups.activeItems,blockedIds,runtime.statusRegistry,runtime.limit):void 0,blockersSection:has("blockers")?buildBlockers(focusGroups.blockedItems,fullCorpus,runtime.statusRegistry,runtime.limit):void 0,recentlyCreated:has("recently_created")?buildRecentlyCreated(allNonTerminal,runtime.statusRegistry,childrenByParent,runtime.limit):void 0,unparented:has("unparented")?buildUnparented(allNonTerminal,runtime.statusRegistry,childrenByParent,runtime.limit):void 0,filesSection:has("files")?buildHotFiles(focusGroups.activeItems,runtime.limit):void 0,workload:has("workload")?buildWorkload(focusGroups.activeItems,runtime.statusRegistry,runtime.limit):void 0,staleness:has("staleness")?buildStaleness(allNonTerminal,runtime.staleThresholdDays,now,runtime.limit):void 0,tests:has("tests")?buildTestHealth(focusGroups.activeItems):void 0}}function buildContextSummaryExtras(allItems,statusRegistry,blockedIds){const canceledStatus=normalizeStatusInput("canceled",statusRegistry);const activeItems=allItems.filter(item=>statusRegistry.active_statuses.has(normalizeStatusForRegistry(item.status,statusRegistry)));const inProgress=countContextStatus(activeItems,statusRegistry.in_progress_status,statusRegistry);return{scope:"matching_items",active_items:activeItems.length,open:activeItems.length-inProgress,in_progress:inProgress,blocked:allItems.filter(item=>blockedIds.has(item.id.trim().toLowerCase())).length,total_items:allItems.length,closed:allItems.filter(item=>isClosedStatus(item.status,statusRegistry)).length,canceled:allItems.filter(item=>normalizeStatusForRegistry(item.status,statusRegistry)===canceledStatus).length}}function attachOptionalContextSections(result,sections,warningDetails){if(sections.hierarchy)result.hierarchy=sections.hierarchy;if(sections.activity)result.activity=sections.activity;if(sections.progress)result.progress=sections.progress;if(sections.blockersSection)result.blockers=sections.blockersSection;if(sections.recentlyCreated)result.recently_created=sections.recentlyCreated;if(sections.unparented)result.unparented=sections.unparented;if(sections.filesSection)result.files=sections.filesSection;if(sections.workload)result.workload=sections.workload;if(sections.staleness)result.staleness=sections.staleness;if(sections.tests)result.tests=sections.tests;if(warningDetails!==void 0&&warningDetails.length>0){result.warning_details=warningDetails}}function applyContextFocusProjection(result,focusFields){if(!focusFields){return}result.focus_fields=focusFields;result.high_level=projectContextFocusRows(result.high_level,focusFields);result.low_level=projectContextFocusRows(result.low_level,focusFields);result.blocked_fallback=projectContextFocusRows(result.blocked_fallback,focusFields);if(result.recently_created){result.recently_created=projectContextFocusRows(result.recently_created,focusFields)}if(result.unparented){result.unparented=projectContextFocusRows(result.unparented,focusFields)}}function applyContextTagProjection(result,noTags){const rows=[result.high_level,result.low_level,result.blocked_fallback,result.recently_created??[],result.unparented??[]].flat();if(noTags){for(const row of rows){delete row.tags;delete row.tags_inherited}return}const rowsById=new Map(rows.map(row=>[row.id,row]));const originalTagSignatures=new Map(rows.map(row=>[row.id,row.tags?[...row.tags].sort().join("\0"):void 0]));for(const row of rows){if(!row.parent||!row.tags){continue}const parent=rowsById.get(row.parent);if(parent&&originalTagSignatures.get(row.id)===originalTagSignatures.get(parent.id)){delete row.tags;row.tags_inherited=parent.id}}}function maybeAttachEmptyContextSuggestions(result,activeItems,blockedItems){if(activeItems.length>0||blockedItems.length>0||result.agenda.events.length>0){return}result.suggestions=['pm create --type Task --title "..." to add a new work item',"pm list --status closed --limit 5 to review recent completions","pm search <keywords> to find related past work","pm aggregate for a full project status overview"]}async function attachContextUsageFeedback(result,focusGroups,pmRoot,author){try{const included=new Set(focusGroups.packing.included.map(entry=>entry.id));const rows=focusGroups.ranking.ranked.map(entry=>({id:entry.id,rank:entry.rank,included:included.has(entry.id)}));const rankedIds=new Set(rows.map(row=>row.id));for(const id of collectContextUsageDeliveredItemIds(result,"context")){if(!rankedIds.has(id)){rows.push({id,rank:rows.length+1,included:false});rankedIds.add(id)}}const receipt=await recordContextUsageServing({pmRoot,author,surface:"context",profile:focusGroups.packing.profile,rows,enabled:process.env.PM_CONTEXT_USAGE_DISABLED!=="1"});attachContextUsageServingReceipt(result,receipt)}catch{result.warnings=mergeSortedWarnings(result.warnings,["context_usage_feedback_write_failed"])}}async function resolveContextExtensionHealthProjection(omitted,pmRoot,settings){if(omitted)return{};const discovery=await discoverExtensions({pmRoot,settings,cwd:process.cwd(),noExtensions:false});const packages=discovery.discovered.map(diagnostic=>({name:diagnostic.name??diagnostic.directory,status:diagnostic.status==="ok"?"ok":"degraded"})).sort((left,right)=>left.name.localeCompare(right.name));const degraded=packages.filter(entry=>entry.status==="degraded").length;if(packages.length===0)return{};return{extension_health:{total:packages.length,ok:packages.length-degraded,degraded,packages:packages.slice(0,20),...packages.length>20?{truncated:true}:{}}}}async function resolveContextSemanticAffinity(pmRoot,author){const identity=detectAgentIdentity();const semanticState=await readSessionState(pmRoot);const attributionKey=identity.instance||semanticAttributionKey(author);return semanticAttributionAffinity(semanticState.semantic_attribution?.[attributionKey])}async function runContext(options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);const resolvedRuntime=await resolveContextRuntime(options,global2);const corpus=await loadContextCorpus(global2,resolvedRuntime);const scaledLimit=resolveContextLimitAtScale(resolvedRuntime.limit,corpus.fullCorpus.length);const runtime={...resolvedRuntime,limit:scaledLimit,tokenBudget:resolveContextTokenBudget(options.tokenBudget,Math.max(256,scaledLimit*160))};const author=resolveAuthor(void 0,runtime.settings.author_default);const claimFocus=await resolveContextSemanticAffinity(pmRoot,author);const extensionHealthPromise=resolveContextExtensionHealthProjection(options.noExtensionHealth===true,pmRoot,runtime.settings);const blockedIds=collectDependencyBlockedIds(corpus.fullCorpus,runtime.statusRegistry);const focusGroups=await resolveContextFocusGroups(corpus.listedItemMetadata,corpus.allItems,corpus.fullCorpus,blockedIds,runtime.statusRegistry,runtime.sectionsIncluded,runtime.limit,nowIso(),author,options.after,buildContextCursorFingerprint(options),shouldPageContextFocus(options,corpus.fullCorpus.length),pmRoot,runtime.tokenBudget,claimFocus,resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()));const agendaContext=await buildContextAgenda(global2,runtime,corpus.subtreeIds,new Set([...focusGroups.highLevel,...focusGroups.lowLevel,...focusGroups.blockedFallback].map(item=>item.id)));const workspaceMemory=await readWorkspaceMemory(corpus.fullCorpus,{pmRoot,statusRegistry:runtime.statusRegistry,now:agendaContext.agenda.now});const warnings=mergeSortedWarnings(corpus.listed.warnings,agendaContext.agenda.warnings,focusGroups.ranking.warnings,[...focusGroups.featureStore.warnings],workspaceMemory.warnings);const inProgressCount=countContextStatus(focusGroups.activeItems,runtime.statusRegistry.in_progress_status,runtime.statusRegistry);const openCount=focusGroups.activeItems.length-inProgressCount;const sections=await buildOptionalContextSections({runtime,allItems:corpus.allItems,fullCorpus:corpus.fullCorpus,blockedIds,focusGroups,now:agendaContext.agenda.now,global:global2});const summaryExtras=buildContextSummaryExtras(corpus.allItems,runtime.statusRegistry,blockedIds);const result={output_default:"toon",now:agendaContext.agenda.now,depth:runtime.depth,sections_included:runtime.sectionsIncluded,window:{anchor:agendaContext.agenda.anchor,start:agendaContext.agenda.range.start,end:agendaContext.agenda.range.end,past:agendaContext.agenda.range.past,from:agendaContext.agenda.range.from,to:agendaContext.agenda.range.to},filters:{type:options.type??null,tag:options.tag??null,priority:options.priority??null,assignee:options.assignee??null,assignee_filter:options.assigneeFilter??null,sprint:options.sprint??null,release:options.release??null,limit:options.limit??options.maxItems??null,parent:runtime.parentScope??null,token_budget:runtime.tokenBudget,runtime_filters:corpus.listed.filters.runtime_filters??agendaContext.agenda.filters.runtime_filters??{}},summary:{returned_focus:{active_items:focusGroups.activeItems.length,in_progress:inProgressCount,open:openCount,blocked:focusGroups.blockedItems.length},blocked_fallback_used:focusGroups.blockedFallbackUsed,high_level:focusGroups.highLevel.length,low_level:focusGroups.lowLevel.length,agenda_events:agendaContext.agendaSummary.events,...summaryExtras},high_level:focusGroups.highLevel,low_level:focusGroups.lowLevel,blocked_fallback:focusGroups.blockedFallback,agenda:{summary:agendaContext.agendaSummary,events:agendaContext.agendaEvents},...focusGroups.pageExtras};result.workspace_memory=selectWorkspaceMemory(workspaceMemory,Math.min(800,Math.floor(runtime.tokenBudget*.2)));Object.assign(result,await extensionHealthPromise);attachOptionalContextSections(result,sections,focusGroups.featureStore.warning_details);applyContextTagProjection(result,options.noTags===true);if(options.explainRanking===true){result.ranking=toContextRankingSummary(focusGroups.ranking,focusGroups.featureStore,new Set([...focusGroups.highLevel,...focusGroups.lowLevel,...focusGroups.blockedFallback].map(entry=>entry.id)));result.packing=toContextPackingSummary(focusGroups.packing)}applyContextFocusProjection(result,runtime.focusFields);if(warnings.length>0)result.warnings=warnings;maybeAttachEmptyContextSuggestions(result,focusGroups.activeItems,focusGroups.blockedItems);await attachContextUsageFeedback(result,focusGroups,pmRoot,author);return result}export{CONTEXT_OUTPUT_VALUES,_testOnly,applyContextTagProjection,buildChildrenByParent,buildItemContextRelevanceCandidates,collectSubtreeIds,compareCriticalItems,mergeSortedWarnings,packRankedContextItems,parseContextDepth,parseContextFocusFields,parseContextSections,projectContextFocusRows,renderContextMarkdown,resolveContextExtensionHealthProjection,resolveContextOutputFormat,resolveContextTokenBudget,runContext,toContextFocusItem,toContextPackingSummary,toContextRankingSummary};
1702
2
  //# sourceMappingURL=context.js.map
1703
- //# debugId=4f8e82a2-f4ea-5ecb-8ef5-3ca795cdeda5