@unbrained/pm-cli 2026.9.6 → 2026.9.8

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 (719) 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 +5 -0
  6. package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
  7. package/.claude-plugin/marketplace.json +2 -2
  8. package/CHANGELOG.md +218 -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.js +19 -1893
  92. package/dist/cli/register-operations.js +1 -920
  93. package/dist/cli/register-setup.js +1 -716
  94. package/dist/cli/register-structured-mutation.js +1 -196
  95. package/dist/cli/registration-helpers.js +1 -5
  96. package/dist/cli/runtime-compatibility-boundary.js +4 -42
  97. package/dist/cli/schema-registration-helpers.js +1 -73
  98. package/dist/cli/search-refresh.js +1 -13
  99. package/dist/cli/stats-analytics-json.js +1 -68
  100. package/dist/cli/telemetry-flush.js +1 -10
  101. package/dist/cli-bundle/bundle-manifest.json +164 -156
  102. package/dist/cli-bundle/chunks/chunk-3BZZA6A3.js +5 -0
  103. package/dist/cli-bundle/chunks/chunk-AMRDVX36.js +235 -0
  104. package/dist/cli-bundle/chunks/chunk-DAM4CBBR.js +2202 -0
  105. package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
  106. package/dist/cli-bundle/chunks/chunk-FLDWYEND.js +77 -0
  107. package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-G5ADGQ2D.js} +3 -3
  108. package/dist/cli-bundle/chunks/chunk-JAAEYHUA.js +2 -0
  109. package/dist/cli-bundle/chunks/{chunk-JX4DH4WC.js → chunk-KR3RP4FH.js} +3 -3
  110. package/dist/cli-bundle/chunks/chunk-LEZOUXG6.js +2 -0
  111. package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
  112. package/dist/cli-bundle/chunks/chunk-QOEKOECV.js +29 -0
  113. package/dist/cli-bundle/chunks/chunk-RHSFOMHU.js +2 -0
  114. package/dist/cli-bundle/chunks/chunk-XOD2PCB6.js +20 -0
  115. package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-YVEQ2AMO.js} +4 -4
  116. package/dist/cli-bundle/chunks/register-list-query-KSK3R63M.js +11 -0
  117. package/dist/cli-bundle/chunks/register-mutation-IQ5C7U6O.js +20 -0
  118. package/dist/cli-bundle/chunks/{register-operations-I5W3KMGB.js → register-operations-DWVHR2NC.js} +2 -2
  119. package/dist/cli-bundle/chunks/register-setup-BQ5SVD4B.js +2 -0
  120. package/dist/cli-bundle/focused-chunks/chunk-3WRPWLA7.js +3 -0
  121. package/dist/cli-bundle/focused-chunks/chunk-7MBUII7U.js +2 -0
  122. package/dist/cli-bundle/focused-chunks/chunk-COPBO5HW.js +8 -0
  123. package/dist/cli-bundle/focused-chunks/chunk-DUN4IXYN.js +20 -0
  124. package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-EE5QSM4Z.js} +3 -3
  125. package/dist/cli-bundle/focused-chunks/chunk-HJVARYM3.js +6 -0
  126. package/dist/cli-bundle/focused-chunks/chunk-IAUOUGVR.js +177 -0
  127. package/dist/cli-bundle/focused-chunks/chunk-KOOMJ54F.js +2 -0
  128. package/dist/cli-bundle/focused-chunks/chunk-MZDXX7JY.js +56 -0
  129. package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-OPFHFGDD.js} +2 -2
  130. package/dist/cli-bundle/focused-chunks/chunk-QHNETP77.js +9 -0
  131. package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-RMWES4M6.js} +2 -2
  132. package/dist/cli-bundle/focused-chunks/chunk-RXT4P5QH.js +10 -0
  133. package/dist/cli-bundle/focused-chunks/chunk-SDOL6FM2.js +12 -0
  134. package/dist/cli-bundle/focused-chunks/chunk-SQV4AAUC.js +2 -0
  135. package/dist/cli-bundle/focused-chunks/{chunk-PEFABF7E.js → chunk-WE3IUNIW.js} +3 -3
  136. package/dist/cli-bundle/focused-chunks/chunk-YALOUBWJ.js +2 -0
  137. package/dist/cli-bundle/main.js +20 -20
  138. package/dist/cli-bundle/sdk-authoring.js +1 -1
  139. package/dist/cli-bundle/sdk-contracts.js +2 -2
  140. package/dist/cli-bundle/sdk-core.js +29 -29
  141. package/dist/cli-bundle/sdk-governance.js +1 -1
  142. package/dist/cli-bundle/sdk-graph.js +1 -1
  143. package/dist/cli-bundle/sdk-merge.js +42 -42
  144. package/dist/cli-bundle/sdk-query.js +1 -1
  145. package/dist/cli-bundle/sdk-runtime.js +1 -1
  146. package/dist/cli-bundle/sdk-testing.js +1 -1
  147. package/dist/cli-bundle/sdk.js +11 -11
  148. package/dist/cli.js +1 -104
  149. package/dist/core/checkpoint/checkpoint-gc.js +1 -169
  150. package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
  151. package/dist/core/config/nested-settings.js +1 -534
  152. package/dist/core/config/positional-value.js +1 -109
  153. package/dist/core/diagnostics/remediation.js +1 -506
  154. package/dist/core/extensions/activation-summary-markdown.js +2 -145
  155. package/dist/core/extensions/activation-summary.js +1 -92
  156. package/dist/core/extensions/activation-transaction.js +1 -46
  157. package/dist/core/extensions/capability-usage.js +1 -173
  158. package/dist/core/extensions/command-hook-context.js +1 -13
  159. package/dist/core/extensions/command-metadata-contract.js +1 -22
  160. package/dist/core/extensions/command-visibility-tier.js +1 -29
  161. package/dist/core/extensions/contribution-inventory.js +1 -173
  162. package/dist/core/extensions/exporter-output-contract.js +1 -66
  163. package/dist/core/extensions/extension-candidate.js +1 -18
  164. package/dist/core/extensions/extension-capability-aliases.js +1 -158
  165. package/dist/core/extensions/extension-hook-runtime.js +1 -699
  166. package/dist/core/extensions/extension-policy.js +1 -599
  167. package/dist/core/extensions/extension-registries.js +1 -62
  168. package/dist/core/extensions/extension-runtime-helpers.js +1 -33
  169. package/dist/core/extensions/extension-types.js +1 -102
  170. package/dist/core/extensions/flag-definition-validation.js +1 -52
  171. package/dist/core/extensions/flag-value-types.js +1 -64
  172. package/dist/core/extensions/index.js +1 -526
  173. package/dist/core/extensions/item-field-types.js +1 -39
  174. package/dist/core/extensions/item-fields.js +1 -261
  175. package/dist/core/extensions/loader.js +1 -2223
  176. package/dist/core/extensions/manifest-schema.js +1 -69
  177. package/dist/core/extensions/module-graph-snapshot.js +1 -33
  178. package/dist/core/extensions/preflight-ownership.js +1 -41
  179. package/dist/core/extensions/registration-validation.js +1 -82
  180. package/dist/core/extensions/registration-values.js +1 -209
  181. package/dist/core/extensions/reserved-host-flags.js +1 -36
  182. package/dist/core/extensions/runtime-registrations.js +1 -67
  183. package/dist/core/extensions/service-ownership.js +1 -19
  184. package/dist/core/extensions/version-compat.js +1 -216
  185. package/dist/core/fs/fs-utils.js +2 -158
  186. package/dist/core/fs/host-environment-errors.js +1 -141
  187. package/dist/core/fs/index.js +1 -9
  188. package/dist/core/fs/path-utils.js +1 -17
  189. package/dist/core/governance/content-fields.js +1 -160
  190. package/dist/core/governance/issue-codes.js +1 -151
  191. package/dist/core/governance/metadata-coverage.js +1 -358
  192. package/dist/core/history/drift-cache.js +3 -72
  193. package/dist/core/history/drift-scan.js +1 -342
  194. package/dist/core/history/event-classification.js +1 -109
  195. package/dist/core/history/event-index.js +8 -784
  196. package/dist/core/history/history-compact-bulk.js +1 -104
  197. package/dist/core/history/history-diff.js +1 -158
  198. package/dist/core/history/history-rewrite.d.ts +6 -1
  199. package/dist/core/history/history-rewrite.js +1 -107
  200. package/dist/core/history/history-storage-stats.js +1 -102
  201. package/dist/core/history/history-stream-policy.js +1 -62
  202. package/dist/core/history/history.js +2 -617
  203. package/dist/core/history/identity.js +1 -30
  204. package/dist/core/history/index.js +1 -9
  205. package/dist/core/history/projection.js +1 -196
  206. package/dist/core/history/read.d.ts +9 -0
  207. package/dist/core/history/read.js +1 -57
  208. package/dist/core/history/replay.js +2 -439
  209. package/dist/core/history/version-address.js +1 -32
  210. package/dist/core/history/workspace-history.js +2 -433
  211. package/dist/core/io/body-file.js +1 -62
  212. package/dist/core/io/bulk-ids-input.js +1 -112
  213. package/dist/core/item/actionability.js +1 -327
  214. package/dist/core/item/dependency-reference.js +1 -20
  215. package/dist/core/item/id.js +1 -112
  216. package/dist/core/item/index.js +1 -12
  217. package/dist/core/item/item-format-version.js +1 -78
  218. package/dist/core/item/item-format.js +5 -1473
  219. package/dist/core/item/item-record.js +1 -23
  220. package/dist/core/item/item-type-definition.js +1 -133
  221. package/dist/core/item/parent-reference-policy.js +1 -57
  222. package/dist/core/item/parse.js +2 -603
  223. package/dist/core/item/plan-lifecycle.js +1 -19
  224. package/dist/core/item/priority.js +1 -61
  225. package/dist/core/item/sprint-release-format.js +1 -38
  226. package/dist/core/item/status-filter.js +1 -115
  227. package/dist/core/item/status.js +1 -43
  228. package/dist/core/item/toon-decode.js +1 -29
  229. package/dist/core/item/type-registry.js +1 -715
  230. package/dist/core/item/type-synonyms.js +1 -38
  231. package/dist/core/lock/index.js +1 -9
  232. package/dist/core/lock/lock-gc.js +1 -240
  233. package/dist/core/lock/lock.js +3 -590
  234. package/dist/core/output/mutation-projection.js +1 -217
  235. package/dist/core/output/output-control.js +1 -25
  236. package/dist/core/output/output.js +11 -494
  237. package/dist/core/output/query-summary.js +1 -58
  238. package/dist/core/output/tabular.js +1 -77
  239. package/dist/core/packages/manifest.js +1 -244
  240. package/dist/core/packages/root.js +1 -84
  241. package/dist/core/profile/profile-describe.js +1 -83
  242. package/dist/core/profile/profile-lint.js +1 -415
  243. package/dist/core/profile/profile-plan.js +0 -0
  244. package/dist/core/profile/profile-presets.js +1 -370
  245. package/dist/core/reproducibility/context.js +1 -82
  246. package/dist/core/schema/fields-file.js +2 -288
  247. package/dist/core/schema/item-types-file.js +2 -296
  248. package/dist/core/schema/runtime-field-filters.js +1 -49
  249. package/dist/core/schema/runtime-field-values.js +1 -313
  250. package/dist/core/schema/runtime-schema.js +2 -826
  251. package/dist/core/schema/status-defs-file.js +2 -227
  252. package/dist/core/schema/status-token.js +1 -31
  253. package/dist/core/schema/type-inference.js +1 -95
  254. package/dist/core/schema/type-presets.js +1 -87
  255. package/dist/core/schema/type-workflows.js +1 -104
  256. package/dist/core/search/background-refresh.js +2 -286
  257. package/dist/core/search/bm25.js +1 -146
  258. package/dist/core/search/cache.js +2 -534
  259. package/dist/core/search/corpus.js +1 -311
  260. package/dist/core/search/embedding-batches.js +1 -163
  261. package/dist/core/search/eval.js +1 -225
  262. package/dist/core/search/http-client.js +1 -75
  263. package/dist/core/search/providers.js +1 -242
  264. package/dist/core/search/relevance.js +1 -244
  265. package/dist/core/search/semantic-defaults.js +1 -199
  266. package/dist/core/search/staleness.js +1 -30
  267. package/dist/core/search/vector-stores.js +2 -664
  268. package/dist/core/search/vectorization-metadata.js +1 -81
  269. package/dist/core/sentry/helpers.js +1 -272
  270. package/dist/core/sentry/instrument.js +1 -387
  271. package/dist/core/session/session-state.js +1 -260
  272. package/dist/core/shared/agent-session-context.js +1 -133
  273. package/dist/core/shared/author.js +1 -1172
  274. package/dist/core/shared/command-types.js +1 -4
  275. package/dist/core/shared/conflict-markers.js +1 -31
  276. package/dist/core/shared/constants.js +1 -405
  277. package/dist/core/shared/errors.js +1 -20
  278. package/dist/core/shared/html-entity-decode.js +1 -131
  279. package/dist/core/shared/index.js +1 -12
  280. package/dist/core/shared/item-metadata-contract.js +1 -89
  281. package/dist/core/shared/lazy-module.js +1 -16
  282. package/dist/core/shared/levenshtein.js +1 -61
  283. package/dist/core/shared/memo.js +1 -19
  284. package/dist/core/shared/numeric-parsers.js +1 -20
  285. package/dist/core/shared/option-alias-visibility.js +1 -67
  286. package/dist/core/shared/primitives.js +1 -127
  287. package/dist/core/shared/serial-queue.js +1 -79
  288. package/dist/core/shared/serialization.js +1 -210
  289. package/dist/core/shared/split-comma-list.js +1 -30
  290. package/dist/core/shared/text-normalization.js +1 -38
  291. package/dist/core/shared/time.js +1 -306
  292. package/dist/core/store/index.js +1 -12
  293. package/dist/core/store/item-format-migration.js +1 -125
  294. package/dist/core/store/item-metadata-cache.js +1 -1116
  295. package/dist/core/store/item-metadata-query-index.js +9 -394
  296. package/dist/core/store/item-metadata-read-work.js +1 -43
  297. package/dist/core/store/item-store.js +1 -693
  298. package/dist/core/store/paths.d.ts +1 -1
  299. package/dist/core/store/paths.js +1 -214
  300. package/dist/core/store/settings-read-cache.js +1 -85
  301. package/dist/core/store/settings-validator.js +1 -421
  302. package/dist/core/store/settings.js +3 -1309
  303. package/dist/core/store/tracker-preflight.js +1 -141
  304. package/dist/core/telemetry/consent.js +5 -108
  305. package/dist/core/telemetry/observability.js +1 -246
  306. package/dist/core/telemetry/runtime.js +4 -1988
  307. package/dist/core/test/background-runs.js +4 -945
  308. package/dist/core/test/item-test-run-tracking.js +1 -63
  309. package/dist/core/test/run-selectors.js +1 -120
  310. package/dist/core/validate/estimate-defaults.js +1 -89
  311. package/dist/core/validate/fix-planning.js +1 -189
  312. package/dist/core/validate/linked-artifact-reference.js +1 -36
  313. package/dist/core/validate/missing-by-type.js +1 -34
  314. package/dist/core/validate/missing-link-owners.js +1 -95
  315. package/dist/core/validate/stale-file-classification.js +1 -82
  316. package/dist/mcp/http-server.js +5 -448
  317. package/dist/mcp/legacy-adapter.js +1 -77
  318. package/dist/mcp/runtime-capabilities.js +1 -200
  319. package/dist/mcp/server.js +4 -1233
  320. package/dist/mcp/tool-definitions.js +1 -804
  321. package/dist/sdk/actionability.js +1 -13
  322. package/dist/sdk/agent/closed-domain-contracts.js +1 -161
  323. package/dist/sdk/agent/command-recovery.js +1 -59
  324. package/dist/sdk/agent/command-suggestions.js +1 -66
  325. package/dist/sdk/agent/create-option-policy.js +1 -31
  326. package/dist/sdk/agent/identity-config.js +1 -106
  327. package/dist/sdk/agent/item-addressing.js +1 -207
  328. package/dist/sdk/agent/refusal-closure-census.js +1 -151
  329. package/dist/sdk/agent/refusal-closure.js +1 -133
  330. package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
  331. package/dist/sdk/agent/refusal-reachability.js +1 -593
  332. package/dist/sdk/agent/subcommand-recovery.js +1 -83
  333. package/dist/sdk/agent/task-transcript-contracts.js +1 -197
  334. package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
  335. package/dist/sdk/agent-capability-contracts.js +1 -428
  336. package/dist/sdk/agent-session-context.js +1 -9
  337. package/dist/sdk/annotations.js +1 -448
  338. package/dist/sdk/author-attribution.js +1 -468
  339. package/dist/sdk/authoring.js +1 -20
  340. package/dist/sdk/cli-bootstrap.js +1 -838
  341. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
  342. package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
  343. package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
  344. package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
  345. package/dist/sdk/cli-contracts/command-aliases.js +1 -107
  346. package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
  347. package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
  348. package/dist/sdk/cli-contracts/commander-types.js +1 -159
  349. package/dist/sdk/cli-contracts/completeness.js +1 -393
  350. package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
  351. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
  352. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
  353. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
  354. package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
  355. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
  356. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
  357. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
  358. package/dist/sdk/cli-contracts/string-lists.js +1 -16
  359. package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
  360. package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
  361. package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
  362. package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
  363. package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
  364. package/dist/sdk/cli-contracts.d.ts +1 -1
  365. package/dist/sdk/cli-contracts.js +1 -17
  366. package/dist/sdk/cli-program.js +1 -49
  367. package/dist/sdk/command-line.d.ts +2 -5
  368. package/dist/sdk/command-line.js +1 -78
  369. package/dist/sdk/comments.js +1 -133
  370. package/dist/sdk/compile-cache.js +1 -73
  371. package/dist/sdk/completion.js +157 -837
  372. package/dist/sdk/compose.js +1 -1090
  373. package/dist/sdk/config.js +1 -1204
  374. package/dist/sdk/context/recency.js +1 -33
  375. package/dist/sdk/context/semantic-session-attribution.js +1 -82
  376. package/dist/sdk/context/usage-egress.js +1 -29
  377. package/dist/sdk/context/usage-ledger.js +3 -185
  378. package/dist/sdk/context-intent-contracts.js +1 -709
  379. package/dist/sdk/context-intent-runtime.js +1 -115
  380. package/dist/sdk/context-packing.js +1 -218
  381. package/dist/sdk/context-relevance.js +1 -503
  382. package/dist/sdk/context-signal-store.js +2 -426
  383. package/dist/sdk/context-usage.js +1 -367
  384. package/dist/sdk/contracts.js +1 -23
  385. package/dist/sdk/core-governance.js +1 -14
  386. package/dist/sdk/core.js +1 -14
  387. package/dist/sdk/corpus-shape.js +1 -401
  388. package/dist/sdk/define.js +1 -220
  389. package/dist/sdk/dependencies.js +1 -718
  390. package/dist/sdk/dependency-flag-validation.js +1 -156
  391. package/dist/sdk/dependency-provenance.js +1 -135
  392. package/dist/sdk/docs.js +1 -14
  393. package/dist/sdk/duplicates.js +1 -40
  394. package/dist/sdk/environment/agent-environment.js +1 -466
  395. package/dist/sdk/environment/host-environment-errors.js +1 -8
  396. package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
  397. package/dist/sdk/environment/source-context.js +1 -28
  398. package/dist/sdk/environment/tracker-preflight.js +1 -9
  399. package/dist/sdk/error-code-catalog.js +1 -153
  400. package/dist/sdk/error-runtime.js +1 -58
  401. package/dist/sdk/errors.js +1 -58
  402. package/dist/sdk/eval.js +1 -190
  403. package/dist/sdk/extension/author-manifest.js +1 -92
  404. package/dist/sdk/extension/bundled-catalog.js +1 -332
  405. package/dist/sdk/extension/concurrency.js +1 -25
  406. package/dist/sdk/extension/copy-scope.d.ts +2 -0
  407. package/dist/sdk/extension/copy-scope.js +2 -0
  408. package/dist/sdk/extension/custom-field-collisions.js +1 -30
  409. package/dist/sdk/extension/describe.js +3 -189
  410. package/dist/sdk/extension/doctor.js +1 -606
  411. package/dist/sdk/extension/install-plan.d.ts +69 -0
  412. package/dist/sdk/extension/install-plan.js +2 -0
  413. package/dist/sdk/extension/install-receipts.d.ts +7 -0
  414. package/dist/sdk/extension/install-receipts.js +2 -0
  415. package/dist/sdk/extension/install-runtime.js +3 -313
  416. package/dist/sdk/extension/install-snapshot.js +1 -66
  417. package/dist/sdk/extension/install-sources.js +5 -1057
  418. package/dist/sdk/extension/managed-state.js +2 -252
  419. package/dist/sdk/extension/migrations.js +2 -174
  420. package/dist/sdk/extension/output-ownership.js +1 -25
  421. package/dist/sdk/extension/runtime-summary.js +1 -18
  422. package/dist/sdk/extension/scaffold.js +4 -2308
  423. package/dist/sdk/extension/shared.js +1 -147
  424. package/dist/sdk/extension/source-resolution.js +1 -65
  425. package/dist/sdk/extension/update-check.js +1 -67
  426. package/dist/sdk/extension-command-context.js +1 -44
  427. package/dist/sdk/extension-contracts.js +1 -73
  428. package/dist/sdk/extension.d.ts +7 -2
  429. package/dist/sdk/extension.js +1 -2196
  430. package/dist/sdk/files.js +1 -535
  431. package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
  432. package/dist/sdk/flag-invocation-contracts.js +1 -344
  433. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
  434. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
  435. package/dist/sdk/generated-error-code-catalog.js +1 -16
  436. package/dist/sdk/governance/assurance-action-contracts.js +1 -4
  437. package/dist/sdk/governance/assurance-action.js +1 -411
  438. package/dist/sdk/governance/assurance-limits.js +1 -10
  439. package/dist/sdk/governance/assurance-mutation-error.js +1 -81
  440. package/dist/sdk/governance/assurance-presets.js +1 -135
  441. package/dist/sdk/governance/assurance-runtime.js +1 -238
  442. package/dist/sdk/governance/assurance.js +4 -1182
  443. package/dist/sdk/governance/boundary-fixtures.js +1 -200
  444. package/dist/sdk/governance/coverage-assurance.js +1 -60
  445. package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
  446. package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
  447. package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
  448. package/dist/sdk/governance/defect-recurrence.js +1 -623
  449. package/dist/sdk/governance/extension-host-version.js +1 -115
  450. package/dist/sdk/governance/gc.js +1 -368
  451. package/dist/sdk/governance/health.js +1 -2367
  452. package/dist/sdk/governance/hierarchy-validation.js +1 -108
  453. package/dist/sdk/governance/linked-file-report.js +1 -71
  454. package/dist/sdk/governance/merge-receipt-history.js +1 -206
  455. package/dist/sdk/governance/provenance-health.js +1 -282
  456. package/dist/sdk/governance/reindex.js +4 -761
  457. package/dist/sdk/governance/stale-work.js +1 -82
  458. package/dist/sdk/governance/status-role-diagnostics.js +1 -35
  459. package/dist/sdk/governance/storage-integrity.js +1 -280
  460. package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
  461. package/dist/sdk/governance/upgrade.js +2 -327
  462. package/dist/sdk/governance/validate-history-drift.js +1 -81
  463. package/dist/sdk/governance/validate-item-reader.js +1 -17
  464. package/dist/sdk/governance/validate-normalization.js +1 -36
  465. package/dist/sdk/governance/validate.js +1 -2261
  466. package/dist/sdk/governance/workspace-position.js +1 -163
  467. package/dist/sdk/governance.d.ts +1 -0
  468. package/dist/sdk/governance.js +1 -31
  469. package/dist/sdk/graph/adapter.js +1 -181
  470. package/dist/sdk/graph/analytics.js +1 -474
  471. package/dist/sdk/graph/assembly.js +1 -377
  472. package/dist/sdk/graph/cache.js +1 -160
  473. package/dist/sdk/graph/centrality.js +1 -258
  474. package/dist/sdk/graph/conformance.js +1 -130
  475. package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
  476. package/dist/sdk/graph/deadline-scheduling.js +2 -0
  477. package/dist/sdk/graph/durable-cache.d.ts +1 -1
  478. package/dist/sdk/graph/durable-cache.js +1 -361
  479. package/dist/sdk/graph/governance-contracts.js +1 -34
  480. package/dist/sdk/graph/governance.d.ts +13 -1
  481. package/dist/sdk/graph/governance.js +1 -735
  482. package/dist/sdk/graph/hierarchy-integrity.js +1 -310
  483. package/dist/sdk/graph/index.d.ts +3 -2
  484. package/dist/sdk/graph/index.js +1 -26
  485. package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
  486. package/dist/sdk/graph/lifecycle-coverage.js +2 -0
  487. package/dist/sdk/graph/mutation-advisory.js +1 -176
  488. package/dist/sdk/graph/remediation.js +1 -197
  489. package/dist/sdk/graph/run.d.ts +15 -1
  490. package/dist/sdk/graph/run.js +1 -768
  491. package/dist/sdk/graph/scheduling.js +1 -124
  492. package/dist/sdk/graph/traversal.js +1 -284
  493. package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
  494. package/dist/sdk/graph.js +1 -15
  495. package/dist/sdk/guide-topics.js +1 -707
  496. package/dist/sdk/guide.js +1 -279
  497. package/dist/sdk/history/maintenance.d.ts +71 -0
  498. package/dist/sdk/history/maintenance.js +2 -0
  499. package/dist/sdk/history/salvage.js +2 -247
  500. package/dist/sdk/history/subject.d.ts +19 -0
  501. package/dist/sdk/history/subject.js +2 -0
  502. package/dist/sdk/history-analytics.js +1 -282
  503. package/dist/sdk/history-compact.js +1 -527
  504. package/dist/sdk/history-mcp.js +1 -68
  505. package/dist/sdk/history-provenance.js +1 -182
  506. package/dist/sdk/history-read.js +1 -96
  507. package/dist/sdk/history-redact.d.ts +1 -14
  508. package/dist/sdk/history-redact.js +1 -643
  509. package/dist/sdk/history-repair.d.ts +5 -0
  510. package/dist/sdk/history-repair.js +1 -657
  511. package/dist/sdk/improvement-ledger-validation.js +1 -62
  512. package/dist/sdk/improvement-ledger.js +2 -257
  513. package/dist/sdk/index.d.ts +4 -0
  514. package/dist/sdk/index.js +1 -183
  515. package/dist/sdk/init-agent-guidance.js +2 -496
  516. package/dist/sdk/init.js +2 -820
  517. package/dist/sdk/invocation-author.js +1 -39
  518. package/dist/sdk/item-children.js +1 -90
  519. package/dist/sdk/item-metadata-index.js +1 -15
  520. package/dist/sdk/item-schedule.js +1 -27
  521. package/dist/sdk/item-transaction.js +1 -396
  522. package/dist/sdk/learnings.js +1 -29
  523. package/dist/sdk/lifecycle/append.js +2 -53
  524. package/dist/sdk/lifecycle/claim.d.ts +2 -0
  525. package/dist/sdk/lifecycle/claim.js +1 -242
  526. package/dist/sdk/lifecycle/close-many.js +1 -438
  527. package/dist/sdk/lifecycle/close.js +1 -468
  528. package/dist/sdk/lifecycle/copy.js +1 -212
  529. package/dist/sdk/lifecycle/create.js +1 -1949
  530. package/dist/sdk/lifecycle/delete.js +1 -45
  531. package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
  532. package/dist/sdk/lifecycle/focus.js +1 -91
  533. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
  534. package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
  535. package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
  536. package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
  537. package/dist/sdk/lifecycle/mcp-actions.js +1 -51
  538. package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
  539. package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
  540. package/dist/sdk/lifecycle/plan.js +1 -1606
  541. package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
  542. package/dist/sdk/lifecycle/reopen.js +1 -68
  543. package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
  544. package/dist/sdk/lifecycle/restore.d.ts +1 -0
  545. package/dist/sdk/lifecycle/restore.js +1 -330
  546. package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
  547. package/dist/sdk/lifecycle/update-many.js +1 -861
  548. package/dist/sdk/lifecycle/update.js +1 -2136
  549. package/dist/sdk/lifecycle-completion.js +1 -92
  550. package/dist/sdk/lifecycle-policy.js +1 -120
  551. package/dist/sdk/linked-artifacts.js +1 -530
  552. package/dist/sdk/mcp/apps.js +4 -133
  553. package/dist/sdk/mcp/authorization.js +1 -404
  554. package/dist/sdk/mcp/discovery.js +1 -494
  555. package/dist/sdk/mcp/interactions.js +1 -336
  556. package/dist/sdk/mcp/protocol.d.ts +7 -0
  557. package/dist/sdk/mcp/protocol.js +1 -184
  558. package/dist/sdk/mcp/skills.js +1 -389
  559. package/dist/sdk/mcp/subscriptions.js +1 -211
  560. package/dist/sdk/mcp/tasks.js +2 -430
  561. package/dist/sdk/mcp/transport.js +1 -260
  562. package/dist/sdk/merge/abandoned-receipts.js +1 -46
  563. package/dist/sdk/merge/driver.js +1 -212
  564. package/dist/sdk/merge/index.js +1 -16
  565. package/dist/sdk/merge/install.js +3 -561
  566. package/dist/sdk/merge/receipt-file-boundary.js +1 -46
  567. package/dist/sdk/merge/receipt-operation.js +1 -96
  568. package/dist/sdk/merge/receipt-schema.js +1 -397
  569. package/dist/sdk/merge/receipts.js +4 -525
  570. package/dist/sdk/merge/reconcile.js +1 -352
  571. package/dist/sdk/merge/three-way.js +3 -775
  572. package/dist/sdk/merge.js +1 -10
  573. package/dist/sdk/mutation-events.js +1 -292
  574. package/dist/sdk/mutation-guard.js +1 -216
  575. package/dist/sdk/notes.js +1 -139
  576. package/dist/sdk/output-contracts.js +1 -172
  577. package/dist/sdk/output-projection.js +1 -430
  578. package/dist/sdk/output-token-accounting.js +1 -140
  579. package/dist/sdk/output.js +1 -64
  580. package/dist/sdk/ownership-source.js +1 -21
  581. package/dist/sdk/package-import-adapters.js +1 -442
  582. package/dist/sdk/package-migrations.js +1 -20
  583. package/dist/sdk/package-runtime-options.js +1 -80
  584. package/dist/sdk/pagination.js +1 -162
  585. package/dist/sdk/profile.js +1 -454
  586. package/dist/sdk/provenance.js +1 -258
  587. package/dist/sdk/public-surface.json +1 -1
  588. package/dist/sdk/query/activity.js +1 -401
  589. package/dist/sdk/query/aggregate.d.ts +16 -0
  590. package/dist/sdk/query/aggregate.js +1 -390
  591. package/dist/sdk/query/calendar.js +1 -964
  592. package/dist/sdk/query/complete-list.js +1 -215
  593. package/dist/sdk/query/context.js +1 -1702
  594. package/dist/sdk/query/duplicate-candidates.js +1 -70
  595. package/dist/sdk/query/get.js +1 -450
  596. package/dist/sdk/query/history.js +1 -186
  597. package/dist/sdk/query/item-filter-options.js +1 -9
  598. package/dist/sdk/query/light-metadata.js +1 -18
  599. package/dist/sdk/query/list-filter-shared.js +1 -81
  600. package/dist/sdk/query/list.js +1 -1304
  601. package/dist/sdk/query/multi-value-filters.js +1 -78
  602. package/dist/sdk/query/next.js +1 -513
  603. package/dist/sdk/query/parsers.js +1 -44
  604. package/dist/sdk/query/projection-contracts.js +1 -184
  605. package/dist/sdk/query/search-contracts.js +1 -230
  606. package/dist/sdk/query/search-pagination.js +1 -35
  607. package/dist/sdk/query/search-rendering.js +1 -105
  608. package/dist/sdk/query/search.js +2 -1987
  609. package/dist/sdk/query.js +1 -35
  610. package/dist/sdk/read-output/continuation.js +1 -194
  611. package/dist/sdk/read-output-budget.js +1 -135
  612. package/dist/sdk/read-output-contracts.js +1 -1225
  613. package/dist/sdk/read-output-rows.js +1 -186
  614. package/dist/sdk/read-output-session.js +1 -208
  615. package/dist/sdk/relationship-analytics.js +1 -410
  616. package/dist/sdk/relationship-context.js +1 -284
  617. package/dist/sdk/relationship-history.js +4 -519
  618. package/dist/sdk/relationship-kinds/contract.js +1 -22
  619. package/dist/sdk/relationship-migration.js +1 -77
  620. package/dist/sdk/relationships.js +1 -579
  621. package/dist/sdk/reproducibility/process.js +1 -87
  622. package/dist/sdk/runtime-action-aliases.js +1 -59
  623. package/dist/sdk/runtime-extended-actions.js +1 -177
  624. package/dist/sdk/runtime-input.js +1 -614
  625. package/dist/sdk/runtime-primitives.js +1 -84
  626. package/dist/sdk/runtime-public-contracts.js +1 -4
  627. package/dist/sdk/runtime-stats-options.js +1 -38
  628. package/dist/sdk/runtime.js +1 -1928
  629. package/dist/sdk/scheduling-shortcuts.js +1 -63
  630. package/dist/sdk/schema-migration.js +3 -856
  631. package/dist/sdk/schema.js +1 -1376
  632. package/dist/sdk/search-refresh-worker.js +1 -18
  633. package/dist/sdk/similarity-scoring.js +1 -53
  634. package/dist/sdk/similarity.js +1 -326
  635. package/dist/sdk/start-task-status.js +1 -14
  636. package/dist/sdk/stats.js +1 -270
  637. package/dist/sdk/structured-mutations.js +1 -580
  638. package/dist/sdk/telemetry-flush.js +1 -13
  639. package/dist/sdk/telemetry.js +1 -405
  640. package/dist/sdk/templates.js +2 -292
  641. package/dist/sdk/test/batch.js +2 -509
  642. package/dist/sdk/test/entry.js +1 -70
  643. package/dist/sdk/test/execution.js +6 -2211
  644. package/dist/sdk/test/linked-command-detection.js +1 -546
  645. package/dist/sdk/test/measurements.js +1 -91
  646. package/dist/sdk/test/parsers.js +1 -545
  647. package/dist/sdk/test/runs.js +1 -193
  648. package/dist/sdk/test/trust.js +2 -206
  649. package/dist/sdk/testing.js +4 -1391
  650. package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
  651. package/dist/sdk/traceability/source-traceability.js +1 -292
  652. package/dist/sdk/tracker-root-discovery.js +1 -9
  653. package/dist/sdk/workspace-contracts-cache.js +1 -28
  654. package/dist/sdk/workspace-contracts.js +1 -33
  655. package/dist/sdk/workspace-memory.js +2 -318
  656. package/dist/sdk/workspace-recipe.js +1 -71
  657. package/dist/sdk/workspace-snapshot.js +4 -613
  658. package/dist/sdk/workspace-transaction-gc.js +1 -149
  659. package/dist/sdk/workspace-transaction.js +2 -363
  660. package/dist/sdk/workspace.js +3 -127
  661. package/dist/types/index.js +1 -9
  662. package/dist/types.js +1 -245
  663. package/docs/AGENT_GUIDE.md +1 -1
  664. package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
  665. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
  666. package/docs/EXTENSIONS.md +1 -0
  667. package/docs/HISTORY_MAINTENANCE.md +125 -0
  668. package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
  669. package/docs/PACKAGE_EVIDENCE.md +92 -0
  670. package/docs/PLANNING_MEASUREMENTS.md +183 -0
  671. package/docs/README.md +3 -0
  672. package/docs/RELEASING.md +1 -0
  673. package/docs/SCRIPTING.md +21 -0
  674. package/docs/TESTING.md +23 -0
  675. package/docs/generated/FLAG_LEXICON_BUDGETS.md +5 -5
  676. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +2 -2
  677. package/marketplace.json +2 -2
  678. package/package.json +1 -1
  679. package/packages/pm-beads/package.json +1 -1
  680. package/packages/pm-calendar/package.json +1 -1
  681. package/packages/pm-command-kit/package.json +1 -1
  682. package/packages/pm-digital-twin/package.json +1 -1
  683. package/packages/pm-governance-audit/package.json +1 -1
  684. package/packages/pm-guide-shell/package.json +1 -1
  685. package/packages/pm-kanban/package.json +1 -1
  686. package/packages/pm-lifecycle-hooks/package.json +1 -1
  687. package/packages/pm-linked-test-adapters/package.json +1 -1
  688. package/packages/pm-search-advanced/package.json +1 -1
  689. package/packages/pm-templates/package.json +1 -1
  690. package/packages/pm-todos/package.json +1 -1
  691. package/packages/pm-vcs/package.json +1 -1
  692. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  693. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  694. package/scripts/finalize-build.mjs +45 -3
  695. package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
  696. package/dist/cli-bundle/chunks/chunk-BAX2BYUW.js +0 -2111
  697. package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
  698. package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
  699. package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
  700. package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
  701. package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
  702. package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
  703. package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
  704. package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
  705. package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
  706. package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
  707. package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
  708. package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
  709. package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
  710. package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
  711. package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
  712. package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
  713. package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
  714. package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
  715. package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
  716. package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
  717. package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
  718. package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
  719. 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