@unbrained/pm-cli 2026.9.7 → 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 (718) 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 +211 -181
  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/SCRIPTING.md +21 -0
  673. package/docs/TESTING.md +23 -0
  674. package/docs/generated/FLAG_LEXICON_BUDGETS.md +5 -5
  675. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +2 -2
  676. package/marketplace.json +2 -2
  677. package/package.json +1 -1
  678. package/packages/pm-beads/package.json +1 -1
  679. package/packages/pm-calendar/package.json +1 -1
  680. package/packages/pm-command-kit/package.json +1 -1
  681. package/packages/pm-digital-twin/package.json +1 -1
  682. package/packages/pm-governance-audit/package.json +1 -1
  683. package/packages/pm-guide-shell/package.json +1 -1
  684. package/packages/pm-kanban/package.json +1 -1
  685. package/packages/pm-lifecycle-hooks/package.json +1 -1
  686. package/packages/pm-linked-test-adapters/package.json +1 -1
  687. package/packages/pm-search-advanced/package.json +1 -1
  688. package/packages/pm-templates/package.json +1 -1
  689. package/packages/pm-todos/package.json +1 -1
  690. package/packages/pm-vcs/package.json +1 -1
  691. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  692. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  693. package/scripts/finalize-build.mjs +45 -3
  694. package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
  695. package/dist/cli-bundle/chunks/chunk-BAX2BYUW.js +0 -2111
  696. package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
  697. package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
  698. package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
  699. package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
  700. package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
  701. package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
  702. package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
  703. package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
  704. package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
  705. package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
  706. package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
  707. package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
  708. package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
  709. package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
  710. package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
  711. package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
  712. package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
  713. package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
  714. package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
  715. package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
  716. package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
  717. package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
  718. package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
@@ -1,1117 +1,2 @@
1
- /**
2
- * @module core/store/item-metadata-cache
3
- *
4
- * Reads and writes tracker storage with format-aware helpers for the item metadata cache.
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]="8b8c705a-8d80-576f-8642-f6f686cdbed9")}catch(e){}}();
8
- import fs from "node:fs/promises";
9
- import path from "node:path";
10
- import { createHash, randomUUID } from "node:crypto";
11
- import { getActiveExtensionRegistrations, hasActiveOnReadHooks, runActiveOnReadHooks, } from "../extensions/index.js";
12
- import { collectRegisteredItemFieldNames } from "../extensions/item-fields.js";
13
- import { parseItemDocument } from "../item/item-format.js";
14
- import { evictOldestMemoEntries } from "../shared/memo.js";
15
- import { isFileMissingError, writeFileAtomic } from "../fs/fs-utils.js";
16
- import { acquireLock } from "../lock/lock.js";
17
- import { ITEM_FILE_EXTENSIONS, getItemFormatFromPath } from "./paths.js";
18
- import { rebuildItemMetadataQueryIndex, removeItemMetadataQueryIndex, updateItemMetadataQueryIndex, } from "./item-metadata-query-index.js";
19
- const CACHE_VERSION = 8;
20
- /** Minimum item count at which derived-index mutations use cross-process locking. */
21
- export const DEFAULT_DERIVED_INDEX_MINIMUM_ITEMS = 500;
22
- const DERIVED_INDEX_LOCK_ID = "metadata-derived-index";
23
- const CACHE_FILENAME = "metadata-cache.json";
24
- const BODY_CACHE_FILENAME = "metadata-cache-bodies.json";
25
- const COLLECTIONS_CACHE_FILENAME = "metadata-cache-collections.json";
26
- const DELTA_CACHE_FILENAME = "metadata-cache-delta.json";
27
- const MANIFEST_CACHE_FILENAME = "metadata-cache-manifest.json";
28
- const MAX_CACHE_CONTEXTS = 4;
29
- /** Heavy "collection" item-metadata fields. These arrays dominate the on-disk cache (e.g. a single item's comment thread can be hundreds of KB) yet the hot list path (`pm list`, stats, deps, activity, calendar, close) never reads them. They are stored in a separate collections cache that is parsed only when a caller opts in (`includeCollections`), keeping the always-loaded light cache an order of magnitude smaller and its JSON.parse correspondingly cheaper. */
30
- export const HEAVY_METADATA_KEYS = [
31
- "comments",
32
- "notes",
33
- "learnings",
34
- "files",
35
- "tests",
36
- "test_runs",
37
- "docs",
38
- ];
39
- function resolveActiveExtensionFieldNames() {
40
- return collectRegisteredItemFieldNames(getActiveExtensionRegistrations());
41
- }
42
- /** Split parsed item-metadata into the light scalar/small fields (everything except the heavy collection arrays) and the heavy collection fields. Only keys that are actually present are moved, so an item without comments stays without comments in both tiers. */
43
- function splitHeavyMetadata(metadata) {
44
- const light = { ...metadata };
45
- const heavy = {};
46
- for (const key of HEAVY_METADATA_KEYS) {
47
- if (key in light) {
48
- heavy[key] = light[key];
49
- delete light[key];
50
- }
51
- }
52
- return { light: light, heavy };
53
- }
54
- /** Recombine light metadata with cached heavy collection fields. Key order differs from the on-disk document, but every downstream hash/serialization canonicalizes and sorts keys (`stableStringify`), so the merged record is byte-identical once hashed. */
55
- function mergeHeavyMetadata(light, heavy) {
56
- if (!heavy || Object.keys(heavy).length === 0) {
57
- return light;
58
- }
59
- return { ...light, ...heavy };
60
- }
61
- function computeContextFingerprint(preferredFormat, typeToFolder, schema, extensionFieldNames) {
62
- const hash = createHash("sha256");
63
- hash.update(`format:${preferredFormat ?? "default"}`);
64
- const sortedTypes = Object.entries(typeToFolder)
65
- .sort(([a], [b]) => a.localeCompare(b))
66
- .map(([type, folder]) => `${type}=${folder}`)
67
- .join(",");
68
- hash.update(`|types:${sortedTypes}`);
69
- if (schema) {
70
- hash.update(`|schema:${JSON.stringify(schema)}`);
71
- }
72
- if (extensionFieldNames.length > 0) {
73
- hash.update(`|extension_fields:${extensionFieldNames.join(",")}`);
74
- }
75
- return hash.digest("hex").slice(0, 16);
76
- }
77
- function getCachePath(pmRoot) {
78
- return path.join(pmRoot, "runtime", CACHE_FILENAME);
79
- }
80
- function getBodyCachePath(pmRoot) {
81
- return path.join(pmRoot, "runtime", BODY_CACHE_FILENAME);
82
- }
83
- function getCollectionsCachePath(pmRoot) {
84
- return path.join(pmRoot, "runtime", COLLECTIONS_CACHE_FILENAME);
85
- }
86
- function getDeltaCachePath(pmRoot) {
87
- return path.join(pmRoot, "runtime", DELTA_CACHE_FILENAME);
88
- }
89
- function getManifestCachePath(pmRoot) {
90
- return path.join(pmRoot, "runtime", MANIFEST_CACHE_FILENAME);
91
- }
92
- function getContextCachePath(cachePath, contextFingerprint) {
93
- const extension = path.extname(cachePath);
94
- return `${cachePath.slice(0, -extension.length)}.${contextFingerprint}${extension}`;
95
- }
96
- /**
97
- * In-process memo of parsed cache envelopes keyed by cache file path and validated
98
- * against the file's stat signature on every load. Commands that scan the corpus more
99
- * than once per invocation (`pm next`, `pm context`) and long-lived in-process hosts
100
- * (the MCP server) would otherwise re-read and re-parse multi-megabyte JSON on every
101
- * scan. Envelopes handed out from the memo are shared, so they must be treated as
102
- * read-only — the write path always goes through `mutateItem` on a `structuredClone`d
103
- * document parsed fresh from the item file, never through listed cache metadata.
104
- *
105
- * The cap bounds memory when one long-lived process serves many project roots
106
- * (3 envelopes per root). Hits re-insert their entry so Map insertion order tracks
107
- * recency, making the half-eviction drop the least-recently-used roots.
108
- */
109
- const ENVELOPE_MEMO_MAX_ENTRIES = 24;
110
- const envelopeMemo = new Map();
111
- const projectedBaseCursor = new WeakMap();
112
- function baseCursorFor(envelope) {
113
- return projectedBaseCursor.get(envelope) ?? envelope.source_cursor;
114
- }
115
- function applyMetadataDelta(envelope, delta) {
116
- const baseCursor = baseCursorFor(envelope);
117
- if (delta.base_source_cursor !== baseCursor ||
118
- envelope.source_cursor === delta.source_cursor) {
119
- return;
120
- }
121
- projectedBaseCursor.set(envelope, baseCursor);
122
- for (const [relativePath, change] of Object.entries(delta.changes)) {
123
- if (change.entry)
124
- envelope.entries[relativePath] = change.entry;
125
- else
126
- delete envelope.entries[relativePath];
127
- }
128
- envelope.directory_signatures = delta.directory_signatures;
129
- envelope.source_cursor = delta.source_cursor;
130
- }
131
- function applyBodyDelta(envelope, delta) {
132
- if (!envelope)
133
- return;
134
- const baseCursor = baseCursorFor(envelope);
135
- if (delta.base_source_cursor !== baseCursor ||
136
- envelope.source_cursor === delta.source_cursor) {
137
- return;
138
- }
139
- projectedBaseCursor.set(envelope, baseCursor);
140
- for (const [relativePath, change] of Object.entries(delta.changes)) {
141
- if (change.body)
142
- envelope.bodies[relativePath] = change.body;
143
- else
144
- delete envelope.bodies[relativePath];
145
- }
146
- envelope.source_cursor = delta.source_cursor;
147
- }
148
- function applyCollectionsDelta(envelope, delta) {
149
- if (!envelope)
150
- return;
151
- const baseCursor = baseCursorFor(envelope);
152
- if (delta.base_source_cursor !== baseCursor ||
153
- envelope.source_cursor === delta.source_cursor) {
154
- return;
155
- }
156
- projectedBaseCursor.set(envelope, baseCursor);
157
- for (const [relativePath, change] of Object.entries(delta.changes)) {
158
- if (change.collections)
159
- envelope.collections[relativePath] = change.collections;
160
- else
161
- delete envelope.collections[relativePath];
162
- }
163
- envelope.source_cursor = delta.source_cursor;
164
- }
165
- function applyDerivedIndexDelta(metadata, bodies, collections, delta) {
166
- if (!metadata ||
167
- !delta ||
168
- metadata.context_fingerprint !== delta.context_fingerprint) {
169
- return;
170
- }
171
- applyMetadataDelta(metadata, delta);
172
- applyBodyDelta(bodies, delta);
173
- applyCollectionsDelta(collections, delta);
174
- }
175
- function memoizeEnvelope(cachePath, entry) {
176
- if (envelopeMemo.size >= ENVELOPE_MEMO_MAX_ENTRIES &&
177
- !envelopeMemo.has(cachePath)) {
178
- evictOldestMemoEntries(envelopeMemo);
179
- }
180
- envelopeMemo.set(cachePath, entry);
181
- }
182
- async function loadEnvelopeMemoized(cachePath, parse) {
183
- let stat;
184
- try {
185
- stat = await fs.stat(cachePath);
186
- }
187
- catch {
188
- envelopeMemo.delete(cachePath);
189
- return null;
190
- }
191
- const memoized = envelopeMemo.get(cachePath);
192
- if (memoized &&
193
- statMatches(memoized.signature, stat.mtimeMs, stat.ctimeMs, stat.size)) {
194
- // Re-insert on hit so insertion order tracks recency for the LRU half-eviction.
195
- envelopeMemo.delete(cachePath);
196
- envelopeMemo.set(cachePath, memoized);
197
- return memoized.envelope;
198
- }
199
- let envelope;
200
- try {
201
- envelope = parse(await fs.readFile(cachePath, "utf8"));
202
- }
203
- catch {
204
- envelope = null;
205
- }
206
- memoizeEnvelope(cachePath, {
207
- signature: {
208
- mtime_ms: stat.mtimeMs,
209
- ctime_ms: stat.ctimeMs,
210
- size: stat.size,
211
- },
212
- envelope,
213
- });
214
- return envelope;
215
- }
216
- /**
217
- * Drop memoized envelopes. Exposed for tests; production invalidation is stat-driven
218
- * plus the explicit delete in {@link persistCache} after a rewrite.
219
- */
220
- export function clearItemMetadataEnvelopeMemo() {
221
- envelopeMemo.clear();
222
- }
223
- async function loadCache(pmRoot, contextFingerprint, diagnostics) {
224
- const parse = (raw) => {
225
- const parsed = JSON.parse(raw);
226
- if (parsed.version !== CACHE_VERSION ||
227
- typeof parsed.source_cursor !== "string" ||
228
- typeof parsed.entries !== "object" ||
229
- parsed.entries === null) {
230
- return null;
231
- }
232
- return parsed;
233
- };
234
- const cachePath = getCachePath(pmRoot);
235
- const active = await loadEnvelopeMemoized(cachePath, parse);
236
- if (!contextFingerprint ||
237
- active === null ||
238
- active.context_fingerprint === contextFingerprint) {
239
- return active;
240
- }
241
- const retained = await loadEnvelopeMemoized(getContextCachePath(cachePath, contextFingerprint), parse);
242
- if (retained === null) {
243
- appendWarning(diagnostics, `metadata_cache_context_changed:${active.context_fingerprint}->${contextFingerprint}`);
244
- }
245
- return retained;
246
- }
247
- async function loadBodyCache(pmRoot, contextFingerprint) {
248
- const parse = (raw) => {
249
- const parsed = JSON.parse(raw);
250
- if (parsed.version !== CACHE_VERSION ||
251
- typeof parsed.source_cursor !== "string" ||
252
- typeof parsed.bodies !== "object" ||
253
- parsed.bodies === null) {
254
- return null;
255
- }
256
- return parsed;
257
- };
258
- const cachePath = getBodyCachePath(pmRoot);
259
- const active = await loadEnvelopeMemoized(cachePath, parse);
260
- return contextFingerprint &&
261
- active?.context_fingerprint !== contextFingerprint
262
- ? await loadEnvelopeMemoized(getContextCachePath(cachePath, contextFingerprint), parse)
263
- : active;
264
- }
265
- async function loadCollectionsCache(pmRoot, contextFingerprint) {
266
- const parse = (raw) => {
267
- const parsed = JSON.parse(raw);
268
- if (parsed.version !== CACHE_VERSION ||
269
- typeof parsed.source_cursor !== "string" ||
270
- typeof parsed.collections !== "object" ||
271
- parsed.collections === null) {
272
- return null;
273
- }
274
- return parsed;
275
- };
276
- const cachePath = getCollectionsCachePath(pmRoot);
277
- const active = await loadEnvelopeMemoized(cachePath, parse);
278
- return contextFingerprint &&
279
- active?.context_fingerprint !== contextFingerprint
280
- ? await loadEnvelopeMemoized(getContextCachePath(cachePath, contextFingerprint), parse)
281
- : active;
282
- }
283
- async function loadDerivedIndexDelta(pmRoot) {
284
- const deltaPath = getDeltaCachePath(pmRoot);
285
- const envelope = await loadEnvelopeMemoized(deltaPath, (raw) => {
286
- const parsed = JSON.parse(raw);
287
- if (parsed.version !== CACHE_VERSION ||
288
- typeof parsed.base_source_cursor !== "string" ||
289
- typeof parsed.source_cursor !== "string" ||
290
- typeof parsed.changes !== "object" ||
291
- parsed.changes === null) {
292
- return null;
293
- }
294
- return parsed;
295
- });
296
- if (envelope)
297
- return { envelope, invalid: false };
298
- try {
299
- await fs.stat(deltaPath);
300
- return { envelope: null, invalid: true };
301
- }
302
- catch {
303
- return { envelope: null, invalid: false };
304
- }
305
- }
306
- async function loadDerivedIndexManifest(pmRoot) {
307
- const manifestPath = getManifestCachePath(pmRoot);
308
- const manifest = await loadEnvelopeMemoized(manifestPath, (raw) => {
309
- const parsed = JSON.parse(raw);
310
- if (parsed.version !== CACHE_VERSION ||
311
- typeof parsed.context_fingerprint !== "string" ||
312
- typeof parsed.source_cursor !== "string" ||
313
- !Number.isInteger(parsed.entry_count) ||
314
- parsed.entry_count < 0 ||
315
- typeof parsed.directory_signatures !== "object" ||
316
- parsed.directory_signatures === null) {
317
- return null;
318
- }
319
- return parsed;
320
- });
321
- if (manifest)
322
- return manifest;
323
- try {
324
- await fs.stat(manifestPath);
325
- await removeDerivedIndexFiles(pmRoot);
326
- }
327
- catch {
328
- // Missing manifests are the normal pre-index and small-workspace state.
329
- }
330
- return null;
331
- }
332
- async function persistCache(cachePath, envelope) {
333
- await fs.mkdir(path.dirname(cachePath), { recursive: true });
334
- await writeFileAtomic(cachePath, JSON.stringify(envelope));
335
- // Repopulate the memo with the just-written envelope so the next read after a
336
- // write skips the cold re-read; fall back to plain invalidation when the fresh
337
- // stat signature cannot be captured.
338
- try {
339
- const stat = await fs.stat(cachePath);
340
- memoizeEnvelope(cachePath, {
341
- signature: {
342
- mtime_ms: stat.mtimeMs,
343
- ctime_ms: stat.ctimeMs,
344
- size: stat.size,
345
- },
346
- envelope,
347
- });
348
- }
349
- catch {
350
- envelopeMemo.delete(cachePath);
351
- }
352
- const pmRoot = path.dirname(path.dirname(cachePath));
353
- if (cachePath === getCachePath(pmRoot) ||
354
- cachePath === getBodyCachePath(pmRoot) ||
355
- cachePath === getCollectionsCachePath(pmRoot)) {
356
- const contextPath = getContextCachePath(cachePath, envelope.context_fingerprint);
357
- await writeFileAtomic(contextPath, JSON.stringify(envelope));
358
- try {
359
- const contextStat = await fs.stat(contextPath);
360
- memoizeEnvelope(contextPath, {
361
- signature: {
362
- mtime_ms: contextStat.mtimeMs,
363
- ctime_ms: contextStat.ctimeMs,
364
- size: contextStat.size,
365
- },
366
- envelope,
367
- });
368
- }
369
- catch {
370
- envelopeMemo.delete(contextPath);
371
- }
372
- const directory = path.dirname(cachePath);
373
- const extension = path.extname(cachePath);
374
- const stem = path.basename(cachePath, extension);
375
- const variants = (await fs.readdir(directory, { withFileTypes: true }).catch(() => []))
376
- .filter((entry) => entry.isFile() &&
377
- entry.name !== path.basename(cachePath) &&
378
- entry.name.startsWith(`${stem}.`) &&
379
- entry.name.endsWith(extension))
380
- .map((entry) => path.join(directory, entry.name));
381
- if (variants.length > MAX_CACHE_CONTEXTS) {
382
- const byAge = (await Promise.all(variants.map(async (variantPath) => {
383
- try {
384
- return {
385
- path: variantPath,
386
- mtime: (await fs.stat(variantPath)).mtimeMs,
387
- };
388
- }
389
- catch {
390
- return null;
391
- }
392
- }))).filter((entry) => entry !== null);
393
- for (const stale of byAge
394
- .sort((left, right) => left.mtime - right.mtime)
395
- .slice(0, Math.max(0, byAge.length - MAX_CACHE_CONTEXTS))) {
396
- await fs.rm(stale.path, { force: true });
397
- envelopeMemo.delete(stale.path);
398
- }
399
- }
400
- }
401
- }
402
- /**
403
- * Decide whether a freshly parsed document candidate should replace the one
404
- * already recorded for the same item id when both an explicit-format file and a
405
- * fallback-format file exist (e.g. `pm-x.toon` and `pm-x.md`). An explicit
406
- * `preferredFormat` wins; otherwise `toon` wins over any non-toon format.
407
- *
408
- * This is a pure decision so the winner is fully deterministic regardless of the
409
- * order in which the concurrent per-file reads resolve — the inline call site
410
- * populates the map as each async read completes, so without a pure rule the
411
- * branch taken (and thus its coverage) would race. Keep this exported and
412
- * unit-tested across every format combination.
413
- */
414
- export function shouldReplaceCachedDocumentCandidate(existingFormat, candidateFormat, preferredFormat) {
415
- if (preferredFormat) {
416
- return (candidateFormat === preferredFormat && existingFormat !== preferredFormat);
417
- }
418
- return candidateFormat === "toon" && existingFormat !== "toon";
419
- }
420
- /** Decide whether a scanned candidate should be recorded for its item id. An unseen id is always recorded; duplicate ids delegate to the deterministic cross-format preference rule. Keeping the short-circuit in this pure helper makes both outcomes testable without relying on filesystem enumeration or concurrent read completion order. */
421
- export function shouldRecordCachedDocumentCandidate(existingFormat, candidateFormat, preferredFormat) {
422
- return (existingFormat === undefined ||
423
- shouldReplaceCachedDocumentCandidate(existingFormat, candidateFormat, preferredFormat));
424
- }
425
- function appendWarning(warnings, warning) {
426
- if (warnings && !warnings.includes(warning)) {
427
- warnings.push(warning);
428
- }
429
- }
430
- function statMatches(signature, mtimeMs, ctimeMs, size) {
431
- return (signature.mtime_ms === mtimeMs &&
432
- signature.ctime_ms === ctimeMs &&
433
- signature.size === size);
434
- }
435
- async function readItemDirectoryFiles(pmRoot, folder, warnings) {
436
- const dirPath = path.join(pmRoot, folder);
437
- try {
438
- const files = await fs.readdir(dirPath);
439
- return { folder, dirPath, files };
440
- }
441
- catch (error) {
442
- if (typeof error === "object" &&
443
- error !== null &&
444
- "code" in error &&
445
- !isFileMissingError(error)) {
446
- appendWarning(warnings, `item_list_directory_read_failed:${folder}`);
447
- }
448
- return { folder, dirPath, files: [] };
449
- }
450
- }
451
- async function readDirectorySignature(pmRoot, folder) {
452
- try {
453
- const stat = await fs.stat(path.join(pmRoot, folder));
454
- return [
455
- folder,
456
- {
457
- exists: true,
458
- mtime_ms: stat.mtimeMs,
459
- ctime_ms: stat.ctimeMs,
460
- size: stat.size,
461
- },
462
- ];
463
- }
464
- catch {
465
- return [folder, { exists: false, mtime_ms: 0, ctime_ms: 0, size: 0 }];
466
- }
467
- }
468
- async function readDirectorySignatures(pmRoot, folders) {
469
- return Object.fromEntries(await Promise.all(folders.map(async (folder) => await readDirectorySignature(pmRoot, folder))));
470
- }
471
- function directorySignaturesMatch(left, right) {
472
- if (!left || Object.keys(left).length !== Object.keys(right).length) {
473
- return false;
474
- }
475
- return Object.entries(right).every(([folder, signature]) => {
476
- const previous = left[folder];
477
- return (previous !== undefined &&
478
- previous.exists === signature.exists &&
479
- statMatches(previous, signature.mtime_ms, signature.ctime_ms, signature.size));
480
- });
481
- }
482
- function isItemDocumentFile(file) {
483
- return ITEM_FILE_EXTENSIONS.some((ext) => file.toLowerCase().endsWith(ext));
484
- }
485
- function markDocumentCacheMisses(misses, includeBody, includeCollections, metadataCached, bodyCached, collectionsCached) {
486
- if (!metadataCached) {
487
- misses.metadata = true;
488
- }
489
- if (includeBody && !bodyCached) {
490
- misses.body = true;
491
- }
492
- if (includeCollections && !collectionsCached) {
493
- misses.collections = true;
494
- }
495
- }
496
- async function dispatchCachedDocumentReadHooks(filePath, warnings, dispatchReadHooks) {
497
- if (!dispatchReadHooks) {
498
- return;
499
- }
500
- for (const warning of await runActiveOnReadHooks({
501
- path: filePath,
502
- scope: "project",
503
- })) {
504
- appendWarning(warnings, warning);
505
- }
506
- }
507
- function selectHeavyMetadata(includeCollections, collectionsCached, cachedCollections, parsedCollections) {
508
- if (!includeCollections) {
509
- return undefined;
510
- }
511
- return collectionsCached && cachedCollections
512
- ? cachedCollections.collections
513
- : parsedCollections;
514
- }
515
- async function readCachedDocumentParts(filePath, relativePath, context) {
516
- const stat = await fs.stat(filePath);
517
- const mtimeMs = stat.mtimeMs;
518
- const ctimeMs = stat.ctimeMs;
519
- const { size } = stat;
520
- const itemFormat = getItemFormatFromPath(filePath);
521
- await dispatchCachedDocumentReadHooks(filePath, context.warnings, context.dispatchReadHooks);
522
- const cachedEntry = context.previousEntries[relativePath];
523
- const metadataCached = !context.forceSourceRead &&
524
- cachedEntry !== undefined &&
525
- statMatches(cachedEntry, mtimeMs, ctimeMs, size);
526
- const cachedBody = context.previousBodies[relativePath];
527
- const bodyCached = !context.forceSourceRead &&
528
- cachedBody !== undefined &&
529
- statMatches(cachedBody, mtimeMs, ctimeMs, size);
530
- const cachedCollections = context.previousCollections[relativePath];
531
- const collectionsCached = !context.forceSourceRead &&
532
- cachedCollections !== undefined &&
533
- statMatches(cachedCollections, mtimeMs, ctimeMs, size);
534
- const needRead = !metadataCached ||
535
- (context.includeBody && !bodyCached) ||
536
- (context.includeCollections && !collectionsCached);
537
- if (!needRead) {
538
- return {
539
- mtimeMs,
540
- ctimeMs,
541
- size,
542
- itemFormat,
543
- lightMetadata: cachedEntry.metadata,
544
- heavyMetadata: selectHeavyMetadata(context.includeCollections, collectionsCached, cachedCollections, undefined),
545
- bodyLength: cachedEntry.body_length,
546
- body: context.includeBody ? cachedBody.body : undefined,
547
- };
548
- }
549
- const raw = await fs.readFile(filePath, "utf8");
550
- const parsed = parseItemDocument(raw, {
551
- format: itemFormat,
552
- schema: context.schema,
553
- extensionFieldNames: context.extensionFieldNames,
554
- onWarning: (warning) => appendWarning(context.warnings, warning),
555
- });
556
- const split = splitHeavyMetadata(parsed.metadata);
557
- markDocumentCacheMisses(context.state.misses, context.includeBody, context.includeCollections, metadataCached, bodyCached, collectionsCached);
558
- return {
559
- mtimeMs,
560
- ctimeMs,
561
- size,
562
- itemFormat,
563
- lightMetadata: metadataCached ? cachedEntry.metadata : split.light,
564
- heavyMetadata: selectHeavyMetadata(context.includeCollections, collectionsCached, cachedCollections, split.heavy),
565
- bodyLength: metadataCached ? cachedEntry.body_length : parsed.body.length,
566
- body: context.includeBody ? parsed.body : undefined,
567
- };
568
- }
569
- function recordCachedDocumentCandidate(filePath, relativePath, context, parts) {
570
- context.state.newEntries[relativePath] = {
571
- mtime_ms: parts.mtimeMs,
572
- ctime_ms: parts.ctimeMs,
573
- size: parts.size,
574
- metadata: parts.lightMetadata,
575
- body_length: parts.bodyLength,
576
- };
577
- if (context.includeBody && parts.body !== undefined) {
578
- context.state.newBodies[relativePath] = {
579
- mtime_ms: parts.mtimeMs,
580
- ctime_ms: parts.ctimeMs,
581
- size: parts.size,
582
- body: parts.body,
583
- };
584
- }
585
- if (context.includeCollections && parts.heavyMetadata !== undefined) {
586
- context.state.newCollections[relativePath] = {
587
- mtime_ms: parts.mtimeMs,
588
- ctime_ms: parts.ctimeMs,
589
- size: parts.size,
590
- collections: parts.heavyMetadata,
591
- };
592
- }
593
- const metadata = context.includeCollections
594
- ? mergeHeavyMetadata(parts.lightMetadata, parts.heavyMetadata)
595
- : parts.lightMetadata;
596
- const existing = context.state.documentsById.get(metadata.id);
597
- const candidate = {
598
- metadata,
599
- body: parts.body,
600
- item_format: parts.itemFormat,
601
- item_path: filePath,
602
- };
603
- if (shouldRecordCachedDocumentCandidate(existing?.itemFormat, parts.itemFormat, context.preferredFormat)) {
604
- context.state.documentsById.set(metadata.id, {
605
- candidate,
606
- itemFormat: parts.itemFormat,
607
- });
608
- }
609
- }
610
- async function processCachedDocumentFile(folder, filePath, relativePath, context) {
611
- try {
612
- const parts = await readCachedDocumentParts(filePath, relativePath, context);
613
- recordCachedDocumentCandidate(filePath, relativePath, context, parts);
614
- }
615
- catch {
616
- appendWarning(context.warnings, `item_list_item_read_failed:${folder}/${path.basename(filePath)}`);
617
- }
618
- }
619
- function selectPreviousMetadataEntries(existingCache, contextFingerprint) {
620
- return existingCache &&
621
- existingCache.context_fingerprint === contextFingerprint
622
- ? existingCache.entries
623
- : {};
624
- }
625
- function selectPreviousBodyEntries(existingBodyCache, contextFingerprint) {
626
- return existingBodyCache &&
627
- existingBodyCache.context_fingerprint === contextFingerprint
628
- ? existingBodyCache.bodies
629
- : {};
630
- }
631
- function selectPreviousCollectionEntries(existingCollectionsCache, contextFingerprint) {
632
- return existingCollectionsCache &&
633
- existingCollectionsCache.context_fingerprint === contextFingerprint
634
- ? existingCollectionsCache.collections
635
- : {};
636
- }
637
- function createDocumentCacheMutableState() {
638
- return {
639
- newEntries: {},
640
- newBodies: {},
641
- newCollections: {},
642
- documentsById: new Map(),
643
- misses: {
644
- metadata: false,
645
- body: false,
646
- collections: false,
647
- },
648
- };
649
- }
650
- function collectCachedDocumentParseTasks(dirResults, context) {
651
- const parseTasks = [];
652
- for (const { folder, dirPath, files } of dirResults) {
653
- for (const file of files) {
654
- if (!isItemDocumentFile(file)) {
655
- continue;
656
- }
657
- const filePath = path.join(dirPath, file);
658
- const relativePath = path.relative(context.pmRoot, filePath);
659
- parseTasks.push(processCachedDocumentFile(folder, filePath, relativePath, context));
660
- }
661
- }
662
- return parseTasks;
663
- }
664
- async function persistMetadataCacheIfNeeded(params) {
665
- const metadataDirty = params.state.misses.metadata ||
666
- Object.keys(params.previousEntries).length !==
667
- Object.keys(params.state.newEntries).length ||
668
- !directorySignaturesMatch(params.existingCache?.directory_signatures, params.directorySignatures);
669
- if (!metadataDirty &&
670
- params.existingCache !== null &&
671
- params.existingCache.context_fingerprint === params.contextFingerprint) {
672
- return;
673
- }
674
- try {
675
- await persistCache(getCachePath(params.pmRoot), {
676
- version: CACHE_VERSION,
677
- context_fingerprint: params.contextFingerprint,
678
- source_cursor: params.sourceCursor,
679
- directory_signatures: params.directorySignatures,
680
- entries: params.state.newEntries,
681
- });
682
- await persistCache(getManifestCachePath(params.pmRoot), {
683
- version: CACHE_VERSION,
684
- context_fingerprint: params.contextFingerprint,
685
- source_cursor: params.sourceCursor,
686
- entry_count: Object.keys(params.state.newEntries).length,
687
- directory_signatures: params.directorySignatures,
688
- });
689
- const rows = [...params.state.documentsById.values()].map(({ candidate }) => ({
690
- relativePath: path.relative(params.pmRoot, candidate.item_path),
691
- metadata: splitHeavyMetadata(candidate.metadata).light,
692
- linkedFiles: candidate.metadata.files ?? [],
693
- }));
694
- if (rows.length >= params.minimumIndexedItems) {
695
- await rebuildItemMetadataQueryIndex({
696
- pmRoot: params.pmRoot,
697
- contextFingerprint: params.contextFingerprint,
698
- sourceCursor: params.sourceCursor,
699
- rows,
700
- });
701
- }
702
- else {
703
- await removeItemMetadataQueryIndex(params.pmRoot);
704
- }
705
- }
706
- catch {
707
- // Cache persistence is best-effort; authoritative item reads rebuild it.
708
- }
709
- }
710
- async function persistBodyCacheIfNeeded(params) {
711
- const bodyDirty = params.state.misses.body ||
712
- Object.keys(params.previousBodies).length !==
713
- Object.keys(params.state.newBodies).length;
714
- if (!bodyDirty &&
715
- params.existingBodyCache !== null &&
716
- params.existingBodyCache.context_fingerprint === params.contextFingerprint) {
717
- return;
718
- }
719
- await persistCache(getBodyCachePath(params.pmRoot), {
720
- version: CACHE_VERSION,
721
- context_fingerprint: params.contextFingerprint,
722
- source_cursor: params.sourceCursor,
723
- bodies: params.state.newBodies,
724
- }).catch(() => { });
725
- }
726
- async function persistCollectionsCacheIfNeeded(params) {
727
- const collectionsDirty = params.state.misses.collections ||
728
- Object.keys(params.previousCollections).length !==
729
- Object.keys(params.state.newCollections).length;
730
- if (!collectionsDirty &&
731
- params.existingCollectionsCache !== null &&
732
- params.existingCollectionsCache.context_fingerprint ===
733
- params.contextFingerprint) {
734
- return;
735
- }
736
- await persistCache(getCollectionsCachePath(params.pmRoot), {
737
- version: CACHE_VERSION,
738
- context_fingerprint: params.contextFingerprint,
739
- source_cursor: params.sourceCursor,
740
- collections: params.state.newCollections,
741
- }).catch(() => { });
742
- }
743
- /** Acquire the cross-process derived-index writer lock when an index exists. */
744
- export async function acquireItemMetadataDerivedIndexLock(pmRoot, author, options = {}) {
745
- const cache = await loadDerivedIndexManifest(pmRoot);
746
- if (options.required !== true &&
747
- (cache === null || cache.entry_count < DEFAULT_DERIVED_INDEX_MINIMUM_ITEMS)) {
748
- return async () => { };
749
- }
750
- return acquireLock(pmRoot, DERIVED_INDEX_LOCK_ID, 30, author, false, false, 3_000);
751
- }
752
- /** Read the effective derived-index cursor without exposing cache file layout. */
753
- export async function readItemMetadataDerivedIndexState(pmRoot, folders) {
754
- const manifest = await loadDerivedIndexManifest(pmRoot);
755
- if (manifest === null)
756
- return null;
757
- const delta = await loadDerivedIndexDelta(pmRoot);
758
- if (delta.invalid) {
759
- await removeDerivedIndexFiles(pmRoot);
760
- return null;
761
- }
762
- const effectiveCursor = delta.envelope?.context_fingerprint === manifest.context_fingerprint &&
763
- delta.envelope.base_source_cursor === manifest.source_cursor
764
- ? delta.envelope.source_cursor
765
- : manifest.source_cursor;
766
- const effectiveDirectorySignatures = delta.envelope?.context_fingerprint === manifest.context_fingerprint &&
767
- delta.envelope.base_source_cursor === manifest.source_cursor
768
- ? delta.envelope.directory_signatures
769
- : manifest.directory_signatures;
770
- if (folders &&
771
- !directorySignaturesMatch(effectiveDirectorySignatures, await readDirectorySignatures(pmRoot, folders))) {
772
- return null;
773
- }
774
- return { source_cursor: effectiveCursor, entry_count: manifest.entry_count };
775
- }
776
- function relativeIndexPath(pmRoot, itemPath) {
777
- const relative = path.relative(pmRoot, itemPath);
778
- return relative === "" ||
779
- relative === ".." ||
780
- relative.startsWith(`..${path.sep}`) ||
781
- path.isAbsolute(relative)
782
- ? null
783
- : relative;
784
- }
785
- async function removeDerivedIndexFiles(pmRoot) {
786
- await Promise.all([
787
- getCachePath(pmRoot),
788
- getBodyCachePath(pmRoot),
789
- getCollectionsCachePath(pmRoot),
790
- getDeltaCachePath(pmRoot),
791
- getManifestCachePath(pmRoot),
792
- ].map(async (cachePath) => {
793
- await fs.rm(cachePath, { force: true });
794
- envelopeMemo.delete(cachePath);
795
- }));
796
- await removeItemMetadataQueryIndex(pmRoot);
797
- }
798
- async function createDerivedIndexDeltaChange(params) {
799
- if (params.mutation.document === null) {
800
- return { entry: null, body: null, collections: null };
801
- }
802
- const stat = await fs.stat(params.mutation.itemPath);
803
- const split = splitHeavyMetadata(params.mutation.document.metadata);
804
- const signature = {
805
- mtime_ms: stat.mtimeMs,
806
- ctime_ms: stat.ctimeMs,
807
- size: stat.size,
808
- };
809
- return {
810
- entry: {
811
- ...signature,
812
- metadata: split.light,
813
- body_length: params.mutation.document.body.length,
814
- },
815
- body: { ...signature, body: params.mutation.document.body },
816
- collections: {
817
- ...signature,
818
- collections: split.heavy,
819
- },
820
- };
821
- }
822
- function selectDerivedIndexDeltaChanges(delta, contextFingerprint, baseSourceCursor) {
823
- return delta?.context_fingerprint === contextFingerprint &&
824
- delta.base_source_cursor === baseSourceCursor
825
- ? structuredClone(delta.changes)
826
- : {};
827
- }
828
- /**
829
- * Project one already-committed authoritative item write into every compatible
830
- * derived-index tier. Callers hold {@link acquireItemMetadataDerivedIndexLock}
831
- * from before the item write until this function finishes, so independent pm
832
- * mutations cannot publish a cursor that omits a concurrent write. One small
833
- * atomic delta carries the shared source cursor and all tier projections, so
834
- * mutation cost is bounded by changed items instead of total workspace size.
835
- * Any refresh failure deletes the rebuildable cache so the next read scans.
836
- */
837
- export async function refreshItemMetadataDerivedIndex(mutation) {
838
- const relativePath = relativeIndexPath(mutation.pmRoot, mutation.itemPath);
839
- const previousRelativePath = mutation.previousItemPath
840
- ? relativeIndexPath(mutation.pmRoot, mutation.previousItemPath)
841
- : undefined;
842
- if (relativePath === null || previousRelativePath === null) {
843
- await removeDerivedIndexFiles(mutation.pmRoot);
844
- return ["metadata_derived_index_path_invalidated"];
845
- }
846
- try {
847
- const contextFingerprint = computeContextFingerprint(mutation.preferredFormat, mutation.typeToFolder, mutation.schema, resolveActiveExtensionFieldNames());
848
- const existingCache = await loadDerivedIndexManifest(mutation.pmRoot);
849
- if (existingCache === null ||
850
- existingCache.context_fingerprint !== contextFingerprint) {
851
- return [];
852
- }
853
- const baseSourceCursor = existingCache.source_cursor;
854
- const delta = await loadDerivedIndexDelta(mutation.pmRoot);
855
- if (delta.invalid) {
856
- await removeDerivedIndexFiles(mutation.pmRoot);
857
- return ["metadata_derived_index_refresh_failed"];
858
- }
859
- const changes = selectDerivedIndexDeltaChanges(delta.envelope, contextFingerprint, baseSourceCursor);
860
- const expectedSourceCursor = delta.envelope?.context_fingerprint === contextFingerprint &&
861
- delta.envelope.base_source_cursor === baseSourceCursor
862
- ? delta.envelope.source_cursor
863
- : baseSourceCursor;
864
- if (previousRelativePath !== undefined) {
865
- changes[previousRelativePath] = {
866
- entry: null,
867
- body: null,
868
- collections: null,
869
- };
870
- }
871
- changes[relativePath] = await createDerivedIndexDeltaChange({ mutation });
872
- const sourceCursor = randomUUID();
873
- await persistCache(getDeltaCachePath(mutation.pmRoot), {
874
- version: CACHE_VERSION,
875
- context_fingerprint: contextFingerprint,
876
- base_source_cursor: baseSourceCursor,
877
- source_cursor: sourceCursor,
878
- directory_signatures: await readDirectorySignatures(mutation.pmRoot, [
879
- ...new Set(Object.values(mutation.typeToFolder)),
880
- ]),
881
- changes,
882
- });
883
- const queryIndexUpdated = await updateItemMetadataQueryIndex({
884
- pmRoot: mutation.pmRoot,
885
- contextFingerprint,
886
- expectedSourceCursor,
887
- sourceCursor,
888
- row: mutation.document === null
889
- ? null
890
- : {
891
- relativePath,
892
- metadata: splitHeavyMetadata(mutation.document.metadata).light,
893
- linkedFiles: mutation.document.metadata.files,
894
- },
895
- deletedRelativePaths: [
896
- ...(previousRelativePath === undefined ? [] : [previousRelativePath]),
897
- ...(mutation.document === null ? [relativePath] : []),
898
- ],
899
- });
900
- if (!queryIndexUpdated) {
901
- await removeItemMetadataQueryIndex(mutation.pmRoot);
902
- }
903
- return [];
904
- }
905
- catch {
906
- await removeDerivedIndexFiles(mutation.pmRoot).catch(() => { });
907
- return ["metadata_derived_index_refresh_failed"];
908
- }
909
- }
910
- function sortedCachedDocumentCandidates(state) {
911
- return [...state.documentsById.values()]
912
- .sort((left, right) => left.candidate.metadata.id.localeCompare(right.candidate.metadata.id))
913
- .map((entry) => entry.candidate);
914
- }
915
- function cacheTierMatchesContext(envelope, contextFingerprint, sourceCursor) {
916
- return (envelope?.context_fingerprint === contextFingerprint &&
917
- envelope.source_cursor === sourceCursor);
918
- }
919
- function hasEveryDerivedIndexPart(keys, includeBody, includeCollections, previousBodies, previousCollections) {
920
- return keys.every((key) => (!includeBody || previousBodies[key] !== undefined) &&
921
- (!includeCollections || previousCollections[key] !== undefined));
922
- }
923
- function candidatesFromDerivedIndex(params) {
924
- const candidatesById = new Map();
925
- for (const [relativePath, entry] of Object.entries(params.previousEntries)) {
926
- const itemFormat = getItemFormatFromPath(relativePath);
927
- if (!itemFormat) {
928
- continue;
929
- }
930
- const metadata = params.includeCollections
931
- ? mergeHeavyMetadata(entry.metadata, params.previousCollections[relativePath]?.collections)
932
- : entry.metadata;
933
- const existing = candidatesById.get(metadata.id);
934
- if (shouldRecordCachedDocumentCandidate(existing?.itemFormat, itemFormat, params.preferredFormat)) {
935
- candidatesById.set(metadata.id, {
936
- itemFormat,
937
- candidate: {
938
- metadata,
939
- body: params.includeBody
940
- ? params.previousBodies[relativePath]?.body
941
- : undefined,
942
- item_format: itemFormat,
943
- item_path: path.join(params.pmRoot, relativePath),
944
- },
945
- });
946
- }
947
- }
948
- return [...candidatesById.values()]
949
- .sort((left, right) => left.candidate.metadata.id.localeCompare(right.candidate.metadata.id))
950
- .map((entry) => entry.candidate);
951
- }
952
- function canUseDerivedIndex(params) {
953
- if (params.forceSourceScan ||
954
- hasActiveOnReadHooks() ||
955
- params.existingCache?.context_fingerprint !== params.contextFingerprint ||
956
- params.entryKeys.length < params.minimumIndexedItems ||
957
- !directorySignaturesMatch(params.existingCache?.directory_signatures, params.directorySignatures)) {
958
- return false;
959
- }
960
- const requiredTiersMatch = [
961
- !params.includeBody ||
962
- cacheTierMatchesContext(params.existingBodyCache, params.contextFingerprint, params.existingCache.source_cursor),
963
- !params.includeCollections ||
964
- cacheTierMatchesContext(params.existingCollectionsCache, params.contextFingerprint, params.existingCache.source_cursor),
965
- ];
966
- return (requiredTiersMatch.every(Boolean) &&
967
- hasEveryDerivedIndexPart(params.entryKeys, params.includeBody, params.includeCollections, params.previousBodies, params.previousCollections));
968
- }
969
- /**
970
- * List all item documents using a persistent on-disk metadata cache.
971
- *
972
- * Metadata and bodies are stored in two separate cache files so the hot path
973
- * (`pm list` and friends, which discard bodies) never loads or rewrites the much
974
- * larger body payload. Each file is rewritten only when its contents actually
975
- * change, and per-file onRead hooks are dispatched only when an extension
976
- * registers one. Only files whose mtime/ctime/size changed since the last run are
977
- * re-parsed.
978
- */
979
- export async function listAllDocumentCandidatesCached(pmRoot, preferredFormat, typeToFolder, warnings, schema, options = {}) {
980
- const includeBody = options.includeBody !== false;
981
- const includeCollections = options.includeCollections !== false;
982
- const extensionFieldNames = resolveActiveExtensionFieldNames();
983
- const contextFingerprint = computeContextFingerprint(preferredFormat, typeToFolder, schema, extensionFieldNames);
984
- const delta = await loadDerivedIndexDelta(pmRoot);
985
- if (delta.invalid)
986
- await removeDerivedIndexFiles(pmRoot);
987
- const existingCache = await loadCache(pmRoot, contextFingerprint, options.cacheDiagnostics);
988
- const existingBodyCache = includeBody
989
- ? await loadBodyCache(pmRoot, contextFingerprint)
990
- : null;
991
- const existingCollectionsCache = includeCollections
992
- ? await loadCollectionsCache(pmRoot, contextFingerprint)
993
- : null;
994
- applyDerivedIndexDelta(existingCache, existingBodyCache, existingCollectionsCache, delta.envelope);
995
- const previousEntries = selectPreviousMetadataEntries(existingCache, contextFingerprint);
996
- const previousBodies = selectPreviousBodyEntries(existingBodyCache, contextFingerprint);
997
- const previousCollections = selectPreviousCollectionEntries(existingCollectionsCache, contextFingerprint);
998
- const folders = [...new Set(Object.values(typeToFolder))];
999
- const directorySignaturesBefore = await readDirectorySignatures(pmRoot, folders);
1000
- const entryKeys = Object.keys(previousEntries);
1001
- const minimumIndexedItems = Math.max(1, Math.floor(options.derivedIndexMinimumItems ?? DEFAULT_DERIVED_INDEX_MINIMUM_ITEMS));
1002
- if (canUseDerivedIndex({
1003
- forceSourceScan: options.forceSourceScan === true,
1004
- contextFingerprint,
1005
- existingCache,
1006
- existingBodyCache,
1007
- existingCollectionsCache,
1008
- directorySignatures: directorySignaturesBefore,
1009
- entryKeys,
1010
- minimumIndexedItems,
1011
- includeBody,
1012
- includeCollections,
1013
- previousBodies,
1014
- previousCollections,
1015
- })) {
1016
- return candidatesFromDerivedIndex({
1017
- pmRoot,
1018
- preferredFormat,
1019
- includeBody,
1020
- includeCollections,
1021
- previousEntries,
1022
- previousBodies,
1023
- previousCollections,
1024
- });
1025
- }
1026
- const dirResults = await Promise.all(folders.map((folder) => readItemDirectoryFiles(pmRoot, folder, warnings)));
1027
- const dispatchReadHooks = hasActiveOnReadHooks();
1028
- const state = createDocumentCacheMutableState();
1029
- const context = {
1030
- pmRoot,
1031
- preferredFormat,
1032
- warnings,
1033
- schema,
1034
- extensionFieldNames,
1035
- includeBody,
1036
- includeCollections,
1037
- forceSourceRead: options.forceSourceScan === true,
1038
- dispatchReadHooks,
1039
- previousEntries,
1040
- previousBodies,
1041
- previousCollections,
1042
- state,
1043
- };
1044
- await Promise.all(collectCachedDocumentParseTasks(dirResults, context));
1045
- const directorySignaturesAfter = await readDirectorySignatures(pmRoot, folders);
1046
- const stableDirectorySignatures = directorySignaturesMatch(directorySignaturesBefore, directorySignaturesAfter)
1047
- ? directorySignaturesAfter
1048
- : {};
1049
- const metadataChanged = state.misses.metadata ||
1050
- Object.keys(previousEntries).length !==
1051
- Object.keys(state.newEntries).length ||
1052
- !directorySignaturesMatch(existingCache?.directory_signatures, stableDirectorySignatures);
1053
- const sourceCursor = metadataChanged || existingCache === null
1054
- ? randomUUID()
1055
- : existingCache.source_cursor;
1056
- // Rewrite a cache file only when its contents changed: any re-parsed (missing or
1057
- // stale) entry, or a different set of keys (additions/deletions).
1058
- await persistMetadataCacheIfNeeded({
1059
- pmRoot,
1060
- contextFingerprint,
1061
- sourceCursor,
1062
- existingCache,
1063
- previousEntries,
1064
- directorySignatures: stableDirectorySignatures,
1065
- state,
1066
- minimumIndexedItems,
1067
- });
1068
- if (includeBody) {
1069
- await persistBodyCacheIfNeeded({
1070
- pmRoot,
1071
- contextFingerprint,
1072
- sourceCursor,
1073
- existingBodyCache,
1074
- previousBodies,
1075
- state,
1076
- });
1077
- }
1078
- if (includeCollections) {
1079
- await persistCollectionsCacheIfNeeded({
1080
- pmRoot,
1081
- contextFingerprint,
1082
- sourceCursor,
1083
- existingCollectionsCache,
1084
- previousCollections,
1085
- state,
1086
- });
1087
- }
1088
- return sortedCachedDocumentCandidates(state);
1089
- }
1090
- /** Implements list all documents cached for the public runtime surface of this module. */
1091
- export async function listAllDocumentsCached(pmRoot, preferredFormat, typeToFolder, warnings, schema) {
1092
- const candidates = await listAllDocumentCandidatesCached(pmRoot, preferredFormat, typeToFolder, warnings, schema, {
1093
- includeBody: false,
1094
- });
1095
- return candidates.map((candidate) => ({
1096
- metadata: candidate.metadata,
1097
- body: candidate.body ?? "",
1098
- }));
1099
- }
1100
- /**
1101
- * Light variant of {@link listAllDocumentsCached}: returns metadata WITHOUT the heavy
1102
- * collection fields (comments/notes/learnings/files/tests/test_runs/docs), skipping the
1103
- * large collections cache entirely. Only safe for callers that read just the light
1104
- * scalar/small fields (id/title/status/type/priority/parent/tags/dates/dependencies/…).
1105
- */
1106
- export async function listAllDocumentsCachedLight(pmRoot, preferredFormat, typeToFolder, warnings, schema) {
1107
- const candidates = await listAllDocumentCandidatesCached(pmRoot, preferredFormat, typeToFolder, warnings, schema, {
1108
- includeBody: false,
1109
- includeCollections: false,
1110
- });
1111
- return candidates.map((candidate) => ({
1112
- metadata: candidate.metadata,
1113
- body: candidate.body ?? "",
1114
- }));
1115
- }
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]="1c60c095-9763-5372-9dc3-c0ea1a5caca6")}catch(e2){}})();import fs from"node:fs/promises";import path from"node:path";import{createHash,randomUUID}from"node:crypto";import{getActiveExtensionRegistrations,hasActiveOnReadHooks,runActiveOnReadHooks}from"../extensions/index.js";import{collectRegisteredItemFieldNames}from"../extensions/item-fields.js";import{parseItemDocument}from"../item/item-format.js";import{evictOldestMemoEntries}from"../shared/memo.js";import{isFileMissingError,writeFileAtomic}from"../fs/fs-utils.js";import{acquireLock}from"../lock/lock.js";import{ITEM_FILE_EXTENSIONS,getItemFormatFromPath}from"./paths.js";import{rebuildItemMetadataQueryIndex,removeItemMetadataQueryIndex,updateItemMetadataQueryIndex}from"./item-metadata-query-index.js";const CACHE_VERSION=8;const DEFAULT_DERIVED_INDEX_MINIMUM_ITEMS=500;const DERIVED_INDEX_LOCK_ID="metadata-derived-index";const CACHE_FILENAME="metadata-cache.json";const BODY_CACHE_FILENAME="metadata-cache-bodies.json";const COLLECTIONS_CACHE_FILENAME="metadata-cache-collections.json";const DELTA_CACHE_FILENAME="metadata-cache-delta.json";const MANIFEST_CACHE_FILENAME="metadata-cache-manifest.json";const MAX_CACHE_CONTEXTS=4;const HEAVY_METADATA_KEYS=["comments","notes","learnings","files","tests","test_runs","docs"];function resolveActiveExtensionFieldNames(){return collectRegisteredItemFieldNames(getActiveExtensionRegistrations())}function splitHeavyMetadata(metadata){const light={...metadata};const heavy={};for(const key of HEAVY_METADATA_KEYS){if(key in light){heavy[key]=light[key];delete light[key]}}return{light,heavy}}function mergeHeavyMetadata(light,heavy){if(!heavy||Object.keys(heavy).length===0){return light}return{...light,...heavy}}function computeContextFingerprint(preferredFormat,typeToFolder,schema,extensionFieldNames){const hash=createHash("sha256");hash.update(`format:${preferredFormat??"default"}`);const sortedTypes=Object.entries(typeToFolder).sort(([a],[b])=>a.localeCompare(b)).map(([type,folder])=>`${type}=${folder}`).join(",");hash.update(`|types:${sortedTypes}`);if(schema){hash.update(`|schema:${JSON.stringify(schema)}`)}if(extensionFieldNames.length>0){hash.update(`|extension_fields:${extensionFieldNames.join(",")}`)}return hash.digest("hex").slice(0,16)}function getCachePath(pmRoot){return path.join(pmRoot,"runtime",CACHE_FILENAME)}function getBodyCachePath(pmRoot){return path.join(pmRoot,"runtime",BODY_CACHE_FILENAME)}function getCollectionsCachePath(pmRoot){return path.join(pmRoot,"runtime",COLLECTIONS_CACHE_FILENAME)}function getDeltaCachePath(pmRoot){return path.join(pmRoot,"runtime",DELTA_CACHE_FILENAME)}function getManifestCachePath(pmRoot){return path.join(pmRoot,"runtime",MANIFEST_CACHE_FILENAME)}function getContextCachePath(cachePath,contextFingerprint){const extension=path.extname(cachePath);return`${cachePath.slice(0,-extension.length)}.${contextFingerprint}${extension}`}const ENVELOPE_MEMO_MAX_ENTRIES=24;const envelopeMemo=new Map;const projectedBaseCursor=new WeakMap;function baseCursorFor(envelope){return projectedBaseCursor.get(envelope)??envelope.source_cursor}function applyMetadataDelta(envelope,delta){const baseCursor=baseCursorFor(envelope);if(delta.base_source_cursor!==baseCursor||envelope.source_cursor===delta.source_cursor){return}projectedBaseCursor.set(envelope,baseCursor);for(const[relativePath,change]of Object.entries(delta.changes)){if(change.entry)envelope.entries[relativePath]=change.entry;else delete envelope.entries[relativePath]}envelope.directory_signatures=delta.directory_signatures;envelope.source_cursor=delta.source_cursor}function applyBodyDelta(envelope,delta){if(!envelope)return;const baseCursor=baseCursorFor(envelope);if(delta.base_source_cursor!==baseCursor||envelope.source_cursor===delta.source_cursor){return}projectedBaseCursor.set(envelope,baseCursor);for(const[relativePath,change]of Object.entries(delta.changes)){if(change.body)envelope.bodies[relativePath]=change.body;else delete envelope.bodies[relativePath]}envelope.source_cursor=delta.source_cursor}function applyCollectionsDelta(envelope,delta){if(!envelope)return;const baseCursor=baseCursorFor(envelope);if(delta.base_source_cursor!==baseCursor||envelope.source_cursor===delta.source_cursor){return}projectedBaseCursor.set(envelope,baseCursor);for(const[relativePath,change]of Object.entries(delta.changes)){if(change.collections)envelope.collections[relativePath]=change.collections;else delete envelope.collections[relativePath]}envelope.source_cursor=delta.source_cursor}function applyDerivedIndexDelta(metadata,bodies,collections,delta){if(!metadata||!delta||metadata.context_fingerprint!==delta.context_fingerprint){return}applyMetadataDelta(metadata,delta);applyBodyDelta(bodies,delta);applyCollectionsDelta(collections,delta)}function memoizeEnvelope(cachePath,entry){if(envelopeMemo.size>=ENVELOPE_MEMO_MAX_ENTRIES&&!envelopeMemo.has(cachePath)){evictOldestMemoEntries(envelopeMemo)}envelopeMemo.set(cachePath,entry)}async function loadEnvelopeMemoized(cachePath,parse){let stat;try{stat=await fs.stat(cachePath)}catch{envelopeMemo.delete(cachePath);return null}const memoized=envelopeMemo.get(cachePath);if(memoized&&statMatches(memoized.signature,stat.mtimeMs,stat.ctimeMs,stat.size)){envelopeMemo.delete(cachePath);envelopeMemo.set(cachePath,memoized);return memoized.envelope}let envelope;try{envelope=parse(await fs.readFile(cachePath,"utf8"))}catch{envelope=null}memoizeEnvelope(cachePath,{signature:{mtime_ms:stat.mtimeMs,ctime_ms:stat.ctimeMs,size:stat.size},envelope});return envelope}function clearItemMetadataEnvelopeMemo(){envelopeMemo.clear()}async function loadCache(pmRoot,contextFingerprint,diagnostics){const parse=raw=>{const parsed=JSON.parse(raw);if(parsed.version!==CACHE_VERSION||typeof parsed.source_cursor!=="string"||typeof parsed.entries!=="object"||parsed.entries===null){return null}return parsed};const cachePath=getCachePath(pmRoot);const active=await loadEnvelopeMemoized(cachePath,parse);if(!contextFingerprint||active===null||active.context_fingerprint===contextFingerprint){return active}const retained=await loadEnvelopeMemoized(getContextCachePath(cachePath,contextFingerprint),parse);if(retained===null){appendWarning(diagnostics,`metadata_cache_context_changed:${active.context_fingerprint}->${contextFingerprint}`)}return retained}async function loadBodyCache(pmRoot,contextFingerprint){const parse=raw=>{const parsed=JSON.parse(raw);if(parsed.version!==CACHE_VERSION||typeof parsed.source_cursor!=="string"||typeof parsed.bodies!=="object"||parsed.bodies===null){return null}return parsed};const cachePath=getBodyCachePath(pmRoot);const active=await loadEnvelopeMemoized(cachePath,parse);return contextFingerprint&&active?.context_fingerprint!==contextFingerprint?await loadEnvelopeMemoized(getContextCachePath(cachePath,contextFingerprint),parse):active}async function loadCollectionsCache(pmRoot,contextFingerprint){const parse=raw=>{const parsed=JSON.parse(raw);if(parsed.version!==CACHE_VERSION||typeof parsed.source_cursor!=="string"||typeof parsed.collections!=="object"||parsed.collections===null){return null}return parsed};const cachePath=getCollectionsCachePath(pmRoot);const active=await loadEnvelopeMemoized(cachePath,parse);return contextFingerprint&&active?.context_fingerprint!==contextFingerprint?await loadEnvelopeMemoized(getContextCachePath(cachePath,contextFingerprint),parse):active}async function loadDerivedIndexDelta(pmRoot){const deltaPath=getDeltaCachePath(pmRoot);const envelope=await loadEnvelopeMemoized(deltaPath,raw=>{const parsed=JSON.parse(raw);if(parsed.version!==CACHE_VERSION||typeof parsed.base_source_cursor!=="string"||typeof parsed.source_cursor!=="string"||typeof parsed.changes!=="object"||parsed.changes===null){return null}return parsed});if(envelope)return{envelope,invalid:false};try{await fs.stat(deltaPath);return{envelope:null,invalid:true}}catch{return{envelope:null,invalid:false}}}async function loadDerivedIndexManifest(pmRoot){const manifestPath=getManifestCachePath(pmRoot);const manifest=await loadEnvelopeMemoized(manifestPath,raw=>{const parsed=JSON.parse(raw);if(parsed.version!==CACHE_VERSION||typeof parsed.context_fingerprint!=="string"||typeof parsed.source_cursor!=="string"||!Number.isInteger(parsed.entry_count)||parsed.entry_count<0||typeof parsed.directory_signatures!=="object"||parsed.directory_signatures===null){return null}return parsed});if(manifest)return manifest;try{await fs.stat(manifestPath);await removeDerivedIndexFiles(pmRoot)}catch{}return null}async function persistCache(cachePath,envelope){await fs.mkdir(path.dirname(cachePath),{recursive:true});await writeFileAtomic(cachePath,JSON.stringify(envelope));try{const stat=await fs.stat(cachePath);memoizeEnvelope(cachePath,{signature:{mtime_ms:stat.mtimeMs,ctime_ms:stat.ctimeMs,size:stat.size},envelope})}catch{envelopeMemo.delete(cachePath)}const pmRoot=path.dirname(path.dirname(cachePath));if(cachePath===getCachePath(pmRoot)||cachePath===getBodyCachePath(pmRoot)||cachePath===getCollectionsCachePath(pmRoot)){const contextPath=getContextCachePath(cachePath,envelope.context_fingerprint);await writeFileAtomic(contextPath,JSON.stringify(envelope));try{const contextStat=await fs.stat(contextPath);memoizeEnvelope(contextPath,{signature:{mtime_ms:contextStat.mtimeMs,ctime_ms:contextStat.ctimeMs,size:contextStat.size},envelope})}catch{envelopeMemo.delete(contextPath)}const directory=path.dirname(cachePath);const extension=path.extname(cachePath);const stem=path.basename(cachePath,extension);const variants=(await fs.readdir(directory,{withFileTypes:true}).catch(()=>[])).filter(entry=>entry.isFile()&&entry.name!==path.basename(cachePath)&&entry.name.startsWith(`${stem}.`)&&entry.name.endsWith(extension)).map(entry=>path.join(directory,entry.name));if(variants.length>MAX_CACHE_CONTEXTS){const byAge=(await Promise.all(variants.map(async variantPath=>{try{return{path:variantPath,mtime:(await fs.stat(variantPath)).mtimeMs}}catch{return null}}))).filter(entry=>entry!==null);for(const stale of byAge.sort((left,right)=>left.mtime-right.mtime).slice(0,Math.max(0,byAge.length-MAX_CACHE_CONTEXTS))){await fs.rm(stale.path,{force:true});envelopeMemo.delete(stale.path)}}}}function shouldReplaceCachedDocumentCandidate(existingFormat,candidateFormat,preferredFormat){if(preferredFormat){return candidateFormat===preferredFormat&&existingFormat!==preferredFormat}return candidateFormat==="toon"&&existingFormat!=="toon"}function shouldRecordCachedDocumentCandidate(existingFormat,candidateFormat,preferredFormat){return existingFormat===void 0||shouldReplaceCachedDocumentCandidate(existingFormat,candidateFormat,preferredFormat)}function appendWarning(warnings,warning){if(warnings&&!warnings.includes(warning)){warnings.push(warning)}}function statMatches(signature,mtimeMs,ctimeMs,size){return signature.mtime_ms===mtimeMs&&signature.ctime_ms===ctimeMs&&signature.size===size}async function readItemDirectoryFiles(pmRoot,folder,warnings){const dirPath=path.join(pmRoot,folder);try{const files=await fs.readdir(dirPath);return{folder,dirPath,files}}catch(error){if(typeof error==="object"&&error!==null&&"code"in error&&!isFileMissingError(error)){appendWarning(warnings,`item_list_directory_read_failed:${folder}`)}return{folder,dirPath,files:[]}}}async function readDirectorySignature(pmRoot,folder){try{const stat=await fs.stat(path.join(pmRoot,folder));return[folder,{exists:true,mtime_ms:stat.mtimeMs,ctime_ms:stat.ctimeMs,size:stat.size}]}catch{return[folder,{exists:false,mtime_ms:0,ctime_ms:0,size:0}]}}async function readDirectorySignatures(pmRoot,folders){return Object.fromEntries(await Promise.all(folders.map(async folder=>await readDirectorySignature(pmRoot,folder))))}function directorySignaturesMatch(left,right){if(!left||Object.keys(left).length!==Object.keys(right).length){return false}return Object.entries(right).every(([folder,signature])=>{const previous=left[folder];return previous!==void 0&&previous.exists===signature.exists&&statMatches(previous,signature.mtime_ms,signature.ctime_ms,signature.size)})}function isItemDocumentFile(file){return ITEM_FILE_EXTENSIONS.some(ext=>file.toLowerCase().endsWith(ext))}function markDocumentCacheMisses(misses,includeBody,includeCollections,metadataCached,bodyCached,collectionsCached){if(!metadataCached){misses.metadata=true}if(includeBody&&!bodyCached){misses.body=true}if(includeCollections&&!collectionsCached){misses.collections=true}}async function dispatchCachedDocumentReadHooks(filePath,warnings,dispatchReadHooks){if(!dispatchReadHooks){return}for(const warning of await runActiveOnReadHooks({path:filePath,scope:"project"})){appendWarning(warnings,warning)}}function selectHeavyMetadata(includeCollections,collectionsCached,cachedCollections,parsedCollections){if(!includeCollections){return void 0}return collectionsCached&&cachedCollections?cachedCollections.collections:parsedCollections}async function readCachedDocumentParts(filePath,relativePath,context){const stat=await fs.stat(filePath);const mtimeMs=stat.mtimeMs;const ctimeMs=stat.ctimeMs;const{size}=stat;const itemFormat=getItemFormatFromPath(filePath);await dispatchCachedDocumentReadHooks(filePath,context.warnings,context.dispatchReadHooks);const cachedEntry=context.previousEntries[relativePath];const metadataCached=!context.forceSourceRead&&cachedEntry!==void 0&&statMatches(cachedEntry,mtimeMs,ctimeMs,size);const cachedBody=context.previousBodies[relativePath];const bodyCached=!context.forceSourceRead&&cachedBody!==void 0&&statMatches(cachedBody,mtimeMs,ctimeMs,size);const cachedCollections=context.previousCollections[relativePath];const collectionsCached=!context.forceSourceRead&&cachedCollections!==void 0&&statMatches(cachedCollections,mtimeMs,ctimeMs,size);const needRead=!metadataCached||context.includeBody&&!bodyCached||context.includeCollections&&!collectionsCached;if(!needRead){return{mtimeMs,ctimeMs,size,itemFormat,lightMetadata:cachedEntry.metadata,heavyMetadata:selectHeavyMetadata(context.includeCollections,collectionsCached,cachedCollections,void 0),bodyLength:cachedEntry.body_length,body:context.includeBody?cachedBody.body:void 0}}const raw=await fs.readFile(filePath,"utf8");const parsed=parseItemDocument(raw,{format:itemFormat,schema:context.schema,extensionFieldNames:context.extensionFieldNames,onWarning:warning=>appendWarning(context.warnings,warning)});const split=splitHeavyMetadata(parsed.metadata);markDocumentCacheMisses(context.state.misses,context.includeBody,context.includeCollections,metadataCached,bodyCached,collectionsCached);return{mtimeMs,ctimeMs,size,itemFormat,lightMetadata:metadataCached?cachedEntry.metadata:split.light,heavyMetadata:selectHeavyMetadata(context.includeCollections,collectionsCached,cachedCollections,split.heavy),bodyLength:metadataCached?cachedEntry.body_length:parsed.body.length,body:context.includeBody?parsed.body:void 0}}function recordCachedDocumentCandidate(filePath,relativePath,context,parts){context.state.newEntries[relativePath]={mtime_ms:parts.mtimeMs,ctime_ms:parts.ctimeMs,size:parts.size,metadata:parts.lightMetadata,body_length:parts.bodyLength};if(context.includeBody&&parts.body!==void 0){context.state.newBodies[relativePath]={mtime_ms:parts.mtimeMs,ctime_ms:parts.ctimeMs,size:parts.size,body:parts.body}}if(context.includeCollections&&parts.heavyMetadata!==void 0){context.state.newCollections[relativePath]={mtime_ms:parts.mtimeMs,ctime_ms:parts.ctimeMs,size:parts.size,collections:parts.heavyMetadata}}const metadata=context.includeCollections?mergeHeavyMetadata(parts.lightMetadata,parts.heavyMetadata):parts.lightMetadata;const existing=context.state.documentsById.get(metadata.id);const candidate={metadata,body:parts.body,item_format:parts.itemFormat,item_path:filePath};if(shouldRecordCachedDocumentCandidate(existing?.itemFormat,parts.itemFormat,context.preferredFormat)){context.state.documentsById.set(metadata.id,{candidate,itemFormat:parts.itemFormat})}}async function processCachedDocumentFile(folder,filePath,relativePath,context){try{const parts=await readCachedDocumentParts(filePath,relativePath,context);recordCachedDocumentCandidate(filePath,relativePath,context,parts)}catch{appendWarning(context.warnings,`item_list_item_read_failed:${folder}/${path.basename(filePath)}`)}}function selectPreviousMetadataEntries(existingCache,contextFingerprint){return existingCache&&existingCache.context_fingerprint===contextFingerprint?existingCache.entries:{}}function selectPreviousBodyEntries(existingBodyCache,contextFingerprint){return existingBodyCache&&existingBodyCache.context_fingerprint===contextFingerprint?existingBodyCache.bodies:{}}function selectPreviousCollectionEntries(existingCollectionsCache,contextFingerprint){return existingCollectionsCache&&existingCollectionsCache.context_fingerprint===contextFingerprint?existingCollectionsCache.collections:{}}function createDocumentCacheMutableState(){return{newEntries:{},newBodies:{},newCollections:{},documentsById:new Map,misses:{metadata:false,body:false,collections:false}}}async function processCachedDocumentFiles(dirResults,context){const parseTasks=[];for(const{folder,dirPath,files}of dirResults){for(const file of files){if(!isItemDocumentFile(file)){continue}const filePath=path.join(dirPath,file);const relativePath=path.relative(context.pmRoot,filePath);parseTasks.push(processCachedDocumentFile(folder,filePath,relativePath,context));if(parseTasks.length===32){await Promise.all(parseTasks);parseTasks.length=0}}}await Promise.all(parseTasks)}async function persistMetadataCacheIfNeeded(params){const metadataDirty=params.state.misses.metadata||Object.keys(params.previousEntries).length!==Object.keys(params.state.newEntries).length||!directorySignaturesMatch(params.existingCache?.directory_signatures,params.directorySignatures);if(!metadataDirty&&params.existingCache!==null&&params.existingCache.context_fingerprint===params.contextFingerprint){return}try{await persistCache(getCachePath(params.pmRoot),{version:CACHE_VERSION,context_fingerprint:params.contextFingerprint,source_cursor:params.sourceCursor,directory_signatures:params.directorySignatures,entries:params.state.newEntries});await persistCache(getManifestCachePath(params.pmRoot),{version:CACHE_VERSION,context_fingerprint:params.contextFingerprint,source_cursor:params.sourceCursor,entry_count:Object.keys(params.state.newEntries).length,directory_signatures:params.directorySignatures});const rows=[...params.state.documentsById.values()].map(({candidate})=>({relativePath:path.relative(params.pmRoot,candidate.item_path),metadata:splitHeavyMetadata(candidate.metadata).light,linkedFiles:candidate.metadata.files??[]}));if(rows.length>=params.minimumIndexedItems){await rebuildItemMetadataQueryIndex({pmRoot:params.pmRoot,contextFingerprint:params.contextFingerprint,sourceCursor:params.sourceCursor,rows})}else{await removeItemMetadataQueryIndex(params.pmRoot)}}catch{}}async function persistBodyCacheIfNeeded(params){const bodyDirty=params.state.misses.body||Object.keys(params.previousBodies).length!==Object.keys(params.state.newBodies).length;if(!bodyDirty&&params.existingBodyCache!==null&&params.existingBodyCache.context_fingerprint===params.contextFingerprint){return}await persistCache(getBodyCachePath(params.pmRoot),{version:CACHE_VERSION,context_fingerprint:params.contextFingerprint,source_cursor:params.sourceCursor,bodies:params.state.newBodies}).catch(()=>{})}async function persistCollectionsCacheIfNeeded(params){const collectionsDirty=params.state.misses.collections||Object.keys(params.previousCollections).length!==Object.keys(params.state.newCollections).length;if(!collectionsDirty&&params.existingCollectionsCache!==null&&params.existingCollectionsCache.context_fingerprint===params.contextFingerprint){return}await persistCache(getCollectionsCachePath(params.pmRoot),{version:CACHE_VERSION,context_fingerprint:params.contextFingerprint,source_cursor:params.sourceCursor,collections:params.state.newCollections}).catch(()=>{})}async function acquireItemMetadataDerivedIndexLock(pmRoot,author,options={}){const cache=await loadDerivedIndexManifest(pmRoot);if(options.required!==true&&(cache===null||cache.entry_count<DEFAULT_DERIVED_INDEX_MINIMUM_ITEMS)){return async()=>{}}return acquireLock(pmRoot,DERIVED_INDEX_LOCK_ID,30,author,false,false,3e3)}async function readItemMetadataDerivedIndexState(pmRoot,folders){const manifest=await loadDerivedIndexManifest(pmRoot);if(manifest===null)return null;const delta=await loadDerivedIndexDelta(pmRoot);if(delta.invalid){await removeDerivedIndexFiles(pmRoot);return null}const effectiveCursor=delta.envelope?.context_fingerprint===manifest.context_fingerprint&&delta.envelope.base_source_cursor===manifest.source_cursor?delta.envelope.source_cursor:manifest.source_cursor;const effectiveDirectorySignatures=delta.envelope?.context_fingerprint===manifest.context_fingerprint&&delta.envelope.base_source_cursor===manifest.source_cursor?delta.envelope.directory_signatures:manifest.directory_signatures;if(folders&&!directorySignaturesMatch(effectiveDirectorySignatures,await readDirectorySignatures(pmRoot,folders))){return null}return{source_cursor:effectiveCursor,entry_count:manifest.entry_count}}function relativeIndexPath(pmRoot,itemPath){const relative=path.relative(pmRoot,itemPath);return relative===""||relative===".."||relative.startsWith(`..${path.sep}`)||path.isAbsolute(relative)?null:relative}async function removeDerivedIndexFiles(pmRoot){await Promise.all([getCachePath(pmRoot),getBodyCachePath(pmRoot),getCollectionsCachePath(pmRoot),getDeltaCachePath(pmRoot),getManifestCachePath(pmRoot)].map(async cachePath=>{await fs.rm(cachePath,{force:true});envelopeMemo.delete(cachePath)}));await removeItemMetadataQueryIndex(pmRoot)}async function createDerivedIndexDeltaChange(params){if(params.mutation.document===null){return{entry:null,body:null,collections:null}}const stat=await fs.stat(params.mutation.itemPath);const split=splitHeavyMetadata(params.mutation.document.metadata);const signature={mtime_ms:stat.mtimeMs,ctime_ms:stat.ctimeMs,size:stat.size};return{entry:{...signature,metadata:split.light,body_length:params.mutation.document.body.length},body:{...signature,body:params.mutation.document.body},collections:{...signature,collections:split.heavy}}}function selectDerivedIndexDeltaChanges(delta,contextFingerprint,baseSourceCursor){return delta?.context_fingerprint===contextFingerprint&&delta.base_source_cursor===baseSourceCursor?structuredClone(delta.changes):{}}async function refreshItemMetadataDerivedIndex(mutation){const relativePath=relativeIndexPath(mutation.pmRoot,mutation.itemPath);const previousRelativePath=mutation.previousItemPath?relativeIndexPath(mutation.pmRoot,mutation.previousItemPath):void 0;if(relativePath===null||previousRelativePath===null){await removeDerivedIndexFiles(mutation.pmRoot);return["metadata_derived_index_path_invalidated"]}try{const contextFingerprint=computeContextFingerprint(mutation.preferredFormat,mutation.typeToFolder,mutation.schema,resolveActiveExtensionFieldNames());const existingCache=await loadDerivedIndexManifest(mutation.pmRoot);if(existingCache===null||existingCache.context_fingerprint!==contextFingerprint){return[]}const baseSourceCursor=existingCache.source_cursor;const delta=await loadDerivedIndexDelta(mutation.pmRoot);if(delta.invalid){await removeDerivedIndexFiles(mutation.pmRoot);return["metadata_derived_index_refresh_failed"]}const changes=selectDerivedIndexDeltaChanges(delta.envelope,contextFingerprint,baseSourceCursor);const expectedSourceCursor=delta.envelope?.context_fingerprint===contextFingerprint&&delta.envelope.base_source_cursor===baseSourceCursor?delta.envelope.source_cursor:baseSourceCursor;if(previousRelativePath!==void 0){changes[previousRelativePath]={entry:null,body:null,collections:null}}changes[relativePath]=await createDerivedIndexDeltaChange({mutation});const sourceCursor=randomUUID();await persistCache(getDeltaCachePath(mutation.pmRoot),{version:CACHE_VERSION,context_fingerprint:contextFingerprint,base_source_cursor:baseSourceCursor,source_cursor:sourceCursor,directory_signatures:await readDirectorySignatures(mutation.pmRoot,[...new Set(Object.values(mutation.typeToFolder))]),changes});const queryIndexUpdated=await updateItemMetadataQueryIndex({pmRoot:mutation.pmRoot,contextFingerprint,expectedSourceCursor,sourceCursor,row:mutation.document===null?null:{relativePath,metadata:splitHeavyMetadata(mutation.document.metadata).light,linkedFiles:mutation.document.metadata.files},deletedRelativePaths:[...previousRelativePath===void 0?[]:[previousRelativePath],...mutation.document===null?[relativePath]:[]]});if(!queryIndexUpdated){await removeItemMetadataQueryIndex(mutation.pmRoot)}return[]}catch{await removeDerivedIndexFiles(mutation.pmRoot).catch(()=>{});return["metadata_derived_index_refresh_failed"]}}function sortedCachedDocumentCandidates(state){return[...state.documentsById.values()].sort((left,right)=>left.candidate.metadata.id.localeCompare(right.candidate.metadata.id)).map(entry=>entry.candidate)}function cacheTierMatchesContext(envelope,contextFingerprint,sourceCursor){return envelope?.context_fingerprint===contextFingerprint&&envelope.source_cursor===sourceCursor}function hasEveryDerivedIndexPart(keys,includeBody,includeCollections,previousBodies,previousCollections){return keys.every(key=>(!includeBody||previousBodies[key]!==void 0)&&(!includeCollections||previousCollections[key]!==void 0))}function candidatesFromDerivedIndex(params){const candidatesById=new Map;for(const[relativePath,entry]of Object.entries(params.previousEntries)){const itemFormat=getItemFormatFromPath(relativePath);if(!itemFormat){continue}const metadata=params.includeCollections?mergeHeavyMetadata(entry.metadata,params.previousCollections[relativePath]?.collections):entry.metadata;const existing=candidatesById.get(metadata.id);if(shouldRecordCachedDocumentCandidate(existing?.itemFormat,itemFormat,params.preferredFormat)){candidatesById.set(metadata.id,{itemFormat,candidate:{metadata,body:params.includeBody?params.previousBodies[relativePath]?.body:void 0,item_format:itemFormat,item_path:path.join(params.pmRoot,relativePath)}})}}return[...candidatesById.values()].sort((left,right)=>left.candidate.metadata.id.localeCompare(right.candidate.metadata.id)).map(entry=>entry.candidate)}function canUseDerivedIndex(params){if(params.forceSourceScan||hasActiveOnReadHooks()||params.existingCache?.context_fingerprint!==params.contextFingerprint||params.entryKeys.length<params.minimumIndexedItems||!directorySignaturesMatch(params.existingCache?.directory_signatures,params.directorySignatures)){return false}const requiredTiersMatch=[!params.includeBody||cacheTierMatchesContext(params.existingBodyCache,params.contextFingerprint,params.existingCache.source_cursor),!params.includeCollections||cacheTierMatchesContext(params.existingCollectionsCache,params.contextFingerprint,params.existingCache.source_cursor)];return requiredTiersMatch.every(Boolean)&&hasEveryDerivedIndexPart(params.entryKeys,params.includeBody,params.includeCollections,params.previousBodies,params.previousCollections)}async function listAllDocumentCandidatesCached(pmRoot,preferredFormat,typeToFolder,warnings,schema,options={}){const includeBody=options.includeBody!==false;const includeCollections=options.includeCollections!==false;const extensionFieldNames=resolveActiveExtensionFieldNames();const contextFingerprint=computeContextFingerprint(preferredFormat,typeToFolder,schema,extensionFieldNames);const delta=await loadDerivedIndexDelta(pmRoot);if(delta.invalid)await removeDerivedIndexFiles(pmRoot);const existingCache=await loadCache(pmRoot,contextFingerprint,options.cacheDiagnostics);const existingBodyCache=includeBody?await loadBodyCache(pmRoot,contextFingerprint):null;const existingCollectionsCache=includeCollections?await loadCollectionsCache(pmRoot,contextFingerprint):null;applyDerivedIndexDelta(existingCache,existingBodyCache,existingCollectionsCache,delta.envelope);const previousEntries=selectPreviousMetadataEntries(existingCache,contextFingerprint);const previousBodies=selectPreviousBodyEntries(existingBodyCache,contextFingerprint);const previousCollections=selectPreviousCollectionEntries(existingCollectionsCache,contextFingerprint);const folders=[...new Set(Object.values(typeToFolder))];const directorySignaturesBefore=await readDirectorySignatures(pmRoot,folders);const entryKeys=Object.keys(previousEntries);const minimumIndexedItems=Math.max(1,Math.floor(options.derivedIndexMinimumItems??DEFAULT_DERIVED_INDEX_MINIMUM_ITEMS));if(canUseDerivedIndex({forceSourceScan:options.forceSourceScan===true,contextFingerprint,existingCache,existingBodyCache,existingCollectionsCache,directorySignatures:directorySignaturesBefore,entryKeys,minimumIndexedItems,includeBody,includeCollections,previousBodies,previousCollections})){return candidatesFromDerivedIndex({pmRoot,preferredFormat,includeBody,includeCollections,previousEntries,previousBodies,previousCollections})}const dirResults=await Promise.all(folders.map(folder=>readItemDirectoryFiles(pmRoot,folder,warnings)));const dispatchReadHooks=hasActiveOnReadHooks();const state=createDocumentCacheMutableState();const context={pmRoot,preferredFormat,warnings,schema,extensionFieldNames,includeBody,includeCollections,forceSourceRead:options.forceSourceScan===true,dispatchReadHooks,previousEntries,previousBodies,previousCollections,state};await processCachedDocumentFiles(dirResults,context);const directorySignaturesAfter=await readDirectorySignatures(pmRoot,folders);const stableDirectorySignatures=directorySignaturesMatch(directorySignaturesBefore,directorySignaturesAfter)?directorySignaturesAfter:{};const metadataChanged=state.misses.metadata||Object.keys(previousEntries).length!==Object.keys(state.newEntries).length||!directorySignaturesMatch(existingCache?.directory_signatures,stableDirectorySignatures);const sourceCursor=metadataChanged||existingCache===null?randomUUID():existingCache.source_cursor;await persistMetadataCacheIfNeeded({pmRoot,contextFingerprint,sourceCursor,existingCache,previousEntries,directorySignatures:stableDirectorySignatures,state,minimumIndexedItems});if(includeBody){await persistBodyCacheIfNeeded({pmRoot,contextFingerprint,sourceCursor,existingBodyCache,previousBodies,state})}if(includeCollections){await persistCollectionsCacheIfNeeded({pmRoot,contextFingerprint,sourceCursor,existingCollectionsCache,previousCollections,state})}return sortedCachedDocumentCandidates(state)}async function listAllDocumentsCached(pmRoot,preferredFormat,typeToFolder,warnings,schema){const candidates=await listAllDocumentCandidatesCached(pmRoot,preferredFormat,typeToFolder,warnings,schema,{includeBody:false});return candidates.map(candidate=>({metadata:candidate.metadata,body:candidate.body??""}))}async function listAllDocumentsCachedLight(pmRoot,preferredFormat,typeToFolder,warnings,schema){const candidates=await listAllDocumentCandidatesCached(pmRoot,preferredFormat,typeToFolder,warnings,schema,{includeBody:false,includeCollections:false});return candidates.map(candidate=>({metadata:candidate.metadata,body:candidate.body??""}))}export{DEFAULT_DERIVED_INDEX_MINIMUM_ITEMS,HEAVY_METADATA_KEYS,acquireItemMetadataDerivedIndexLock,clearItemMetadataEnvelopeMemo,listAllDocumentCandidatesCached,listAllDocumentsCached,listAllDocumentsCachedLight,readItemMetadataDerivedIndexState,refreshItemMetadataDerivedIndex,shouldRecordCachedDocumentCandidate,shouldReplaceCachedDocumentCandidate};
1116
2
  //# sourceMappingURL=item-metadata-cache.js.map
1117
- //# debugId=8b8c705a-8d80-576f-8642-f6f686cdbed9