akm-cli 0.9.0-beta.9 → 0.9.0-rc.1

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 (381) hide show
  1. package/CHANGELOG.md +715 -0
  2. package/README.md +12 -4
  3. package/dist/akm +38 -0
  4. package/dist/akm-migrate-storage +38 -0
  5. package/dist/assets/help/help-improve.md +9 -6
  6. package/dist/assets/hints/cli-hints-full.md +6 -5
  7. package/dist/assets/profiles/default.json +9 -4
  8. package/dist/assets/profiles/frequent.json +1 -1
  9. package/dist/assets/profiles/memory-focus.json +1 -1
  10. package/dist/assets/profiles/proactive-maintenance.json +25 -0
  11. package/dist/assets/profiles/quick.json +1 -1
  12. package/dist/assets/profiles/recombine-only.json +21 -0
  13. package/dist/assets/profiles/reflect-distill.json +30 -0
  14. package/dist/assets/profiles/synthesize.json +15 -0
  15. package/dist/assets/profiles/thorough.json +1 -1
  16. package/dist/assets/prompts/consolidate-system.md +23 -0
  17. package/dist/assets/prompts/contradiction-judge.md +33 -0
  18. package/dist/assets/prompts/distill-knowledge-system.md +22 -0
  19. package/dist/assets/prompts/distill-lesson-system.md +36 -0
  20. package/dist/assets/prompts/extract-session.md +11 -3
  21. package/dist/assets/prompts/graph-extract-system.md +1 -0
  22. package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
  23. package/dist/assets/prompts/memory-infer-system.md +1 -0
  24. package/dist/assets/prompts/memory-infer-user.md +5 -0
  25. package/dist/assets/prompts/metadata-enhance-system.md +1 -0
  26. package/dist/assets/prompts/procedural-system.md +44 -0
  27. package/dist/assets/prompts/recombine-system.md +40 -0
  28. package/dist/assets/prompts/staleness-detect-system.md +6 -0
  29. package/dist/assets/prompts/validate-summary-judge.md +1 -0
  30. package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
  39. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
  40. package/dist/assets/templates/html/health.html +281 -111
  41. package/dist/assets/wiki/ingest-workflow-template.md +45 -16
  42. package/dist/assets/wiki/schema-template.md +4 -4
  43. package/dist/cli/clack.js +56 -0
  44. package/dist/cli/config-migrate.js +7 -1
  45. package/dist/cli/confirm.js +1 -1
  46. package/dist/cli/parse-args.js +46 -1
  47. package/dist/cli/shared.js +28 -0
  48. package/dist/cli.js +25 -21
  49. package/dist/commands/agent/agent-dispatch.js +3 -2
  50. package/dist/commands/agent/agent-support.js +0 -7
  51. package/dist/commands/agent/contribute-cli.js +26 -7
  52. package/dist/commands/config-cli.js +26 -13
  53. package/dist/commands/env/child-env.js +47 -0
  54. package/dist/commands/env/env-binding.js +95 -0
  55. package/dist/commands/env/env-cli.js +228 -292
  56. package/dist/commands/env/env.js +14 -67
  57. package/dist/commands/env/secret-cli.js +140 -138
  58. package/dist/commands/feedback-cli.js +156 -155
  59. package/dist/commands/graph/graph-cli.js +5 -13
  60. package/dist/commands/graph/graph.js +3 -3
  61. package/dist/commands/health/advisories.js +151 -0
  62. package/dist/commands/health/checks.js +103 -16
  63. package/dist/commands/health/html-report.js +447 -81
  64. package/dist/commands/health/improve-metrics.js +771 -0
  65. package/dist/commands/health/llm-usage.js +65 -0
  66. package/dist/commands/health/md-report.js +103 -0
  67. package/dist/commands/health/metrics.js +278 -0
  68. package/dist/commands/health/stash-exposure.js +46 -0
  69. package/dist/commands/health/surfaces.js +216 -0
  70. package/dist/commands/health/task-runs.js +135 -0
  71. package/dist/commands/health/types.js +26 -0
  72. package/dist/commands/health/windows.js +195 -0
  73. package/dist/commands/health.js +91 -1091
  74. package/dist/commands/improve/anti-collapse.js +170 -0
  75. package/dist/commands/improve/calibration.js +161 -0
  76. package/dist/commands/improve/collapse-detector.js +421 -0
  77. package/dist/commands/improve/consolidate/chunking.js +141 -0
  78. package/dist/commands/improve/consolidate/eligibility.js +64 -0
  79. package/dist/commands/improve/consolidate/merge.js +145 -0
  80. package/dist/commands/improve/consolidate/sanitize.js +231 -0
  81. package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
  82. package/dist/commands/improve/consolidate.js +1295 -1277
  83. package/dist/commands/improve/dedup.js +482 -0
  84. package/dist/commands/improve/distill/content-repair.js +202 -0
  85. package/dist/commands/improve/distill/promote-memory.js +229 -0
  86. package/dist/commands/improve/distill/quality-gate.js +236 -0
  87. package/dist/commands/improve/distill-guards.js +127 -0
  88. package/dist/commands/improve/distill-promotion-policy.js +826 -167
  89. package/dist/commands/improve/distill.js +228 -605
  90. package/dist/commands/improve/eligibility.js +434 -0
  91. package/dist/commands/improve/encoding-salience.js +205 -0
  92. package/dist/commands/improve/extract-cli.js +179 -59
  93. package/dist/commands/improve/extract-prompt.js +54 -3
  94. package/dist/commands/improve/extract-watch.js +140 -0
  95. package/dist/commands/improve/extract.js +409 -43
  96. package/dist/commands/improve/feedback-valence.js +54 -0
  97. package/dist/commands/improve/hot-probation.js +45 -0
  98. package/dist/commands/improve/improve-auto-accept.js +157 -10
  99. package/dist/commands/improve/improve-cli.js +115 -73
  100. package/dist/commands/improve/improve-profiles.js +28 -8
  101. package/dist/commands/improve/improve-result-file.js +15 -25
  102. package/dist/commands/improve/improve-session.js +58 -0
  103. package/dist/commands/improve/improve.js +485 -2764
  104. package/dist/commands/improve/locks.js +154 -0
  105. package/dist/commands/improve/loop-stages.js +1100 -0
  106. package/dist/commands/improve/memory/memory-belief.js +14 -15
  107. package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
  108. package/dist/commands/improve/memory/memory-improve.js +27 -27
  109. package/dist/commands/improve/outcome-loop.js +270 -0
  110. package/dist/commands/improve/preparation.js +2002 -0
  111. package/dist/commands/improve/proactive-maintenance.js +37 -35
  112. package/dist/commands/improve/procedural.js +398 -0
  113. package/dist/commands/improve/recombine.js +818 -0
  114. package/dist/commands/improve/reflect-noise.js +0 -0
  115. package/dist/commands/improve/reflect.js +206 -45
  116. package/dist/commands/improve/salience.js +455 -0
  117. package/dist/commands/improve/schema-similarity-gate.js +168 -0
  118. package/dist/commands/improve/shared.js +51 -0
  119. package/dist/commands/improve/triage.js +93 -0
  120. package/dist/commands/lint/agent-linter.js +19 -24
  121. package/dist/commands/lint/base-linter.js +173 -60
  122. package/dist/commands/lint/command-linter.js +19 -24
  123. package/dist/commands/lint/env-key-rules.js +38 -1
  124. package/dist/commands/lint/fact-linter.js +39 -0
  125. package/dist/commands/lint/index.js +31 -13
  126. package/dist/commands/lint/memory-linter.js +1 -1
  127. package/dist/commands/lint/registry.js +7 -2
  128. package/dist/commands/lint/task-linter.js +3 -3
  129. package/dist/commands/lint/workflow-linter.js +26 -1
  130. package/dist/commands/observability-cli.js +4 -4
  131. package/dist/commands/proposal/drain-policies.js +13 -4
  132. package/dist/commands/proposal/drain.js +45 -51
  133. package/dist/commands/proposal/legacy-import.js +115 -0
  134. package/dist/commands/proposal/proposal-cli.js +24 -34
  135. package/dist/commands/proposal/proposal.js +2 -1
  136. package/dist/commands/proposal/propose.js +8 -3
  137. package/dist/commands/proposal/repository.js +829 -0
  138. package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
  139. package/dist/commands/proposal/validators/proposals.js +93 -895
  140. package/dist/commands/read/curate.js +410 -111
  141. package/dist/commands/read/knowledge.js +10 -3
  142. package/dist/commands/read/remember-cli.js +133 -138
  143. package/dist/commands/read/search-cli.js +15 -8
  144. package/dist/commands/read/search.js +22 -11
  145. package/dist/commands/read/show.js +106 -14
  146. package/dist/commands/registry-cli.js +76 -87
  147. package/dist/commands/remember.js +11 -12
  148. package/dist/commands/sources/add-cli.js +91 -95
  149. package/dist/commands/sources/history.js +1 -1
  150. package/dist/commands/sources/init.js +66 -18
  151. package/dist/commands/sources/installed-stashes.js +11 -3
  152. package/dist/commands/sources/migration-help.js +7 -4
  153. package/dist/commands/sources/schema-repair.js +44 -46
  154. package/dist/commands/sources/self-update.js +2 -2
  155. package/dist/commands/sources/source-add.js +7 -3
  156. package/dist/commands/sources/sources-cli.js +3 -3
  157. package/dist/commands/sources/stash-cli.js +19 -39
  158. package/dist/commands/sources/stash-skeleton.js +57 -8
  159. package/dist/commands/tasks/default-tasks.js +15 -2
  160. package/dist/commands/tasks/tasks-cli.js +20 -29
  161. package/dist/commands/tasks/tasks.js +39 -11
  162. package/dist/commands/wiki-cli.js +23 -38
  163. package/dist/commands/workflow-cli.js +291 -13
  164. package/dist/core/asset/asset-registry.js +3 -1
  165. package/dist/core/asset/asset-spec.js +79 -5
  166. package/dist/core/asset/frontmatter.js +188 -167
  167. package/dist/core/asset/markdown.js +8 -0
  168. package/dist/core/authoring-rules.js +92 -0
  169. package/dist/core/common.js +4 -23
  170. package/dist/core/concurrent.js +10 -1
  171. package/dist/core/config/config-io.js +10 -1
  172. package/dist/core/config/config-migration.js +18 -40
  173. package/dist/core/config/config-schema.js +403 -62
  174. package/dist/core/config/config-types.js +3 -3
  175. package/dist/core/config/config.js +67 -22
  176. package/dist/core/deep-merge.js +38 -0
  177. package/dist/core/errors.js +1 -0
  178. package/dist/core/eval/rank-metrics.js +113 -0
  179. package/dist/core/events.js +4 -7
  180. package/dist/core/improve-types.js +47 -8
  181. package/dist/core/json-schema.js +142 -0
  182. package/dist/core/logs-db.js +14 -75
  183. package/dist/core/parse.js +36 -16
  184. package/dist/core/paths.js +18 -18
  185. package/dist/core/standards/resolve-standards-context.js +87 -0
  186. package/dist/core/standards/resolve-stash-standards.js +99 -0
  187. package/dist/core/standards/resolve-type-conventions.js +66 -0
  188. package/dist/core/state/migrations.js +770 -0
  189. package/dist/core/state-db.js +132 -1126
  190. package/dist/core/structured.js +69 -0
  191. package/dist/core/time.js +53 -0
  192. package/dist/core/warn.js +21 -0
  193. package/dist/core/write-source.js +37 -0
  194. package/dist/indexer/db/db.js +261 -770
  195. package/dist/indexer/db/entry-mapper.js +41 -0
  196. package/dist/indexer/db/graph-db.js +129 -86
  197. package/dist/indexer/db/llm-cache.js +2 -2
  198. package/dist/indexer/db/schema.js +516 -0
  199. package/dist/indexer/ensure-index.js +36 -92
  200. package/dist/indexer/feedback/utility-policy.js +75 -0
  201. package/dist/indexer/graph/graph-boost.js +51 -41
  202. package/dist/indexer/graph/graph-extraction.js +207 -4
  203. package/dist/indexer/index-writer-lock.js +18 -11
  204. package/dist/indexer/index-written-assets.js +105 -0
  205. package/dist/indexer/indexer.js +182 -204
  206. package/dist/indexer/passes/dir-staleness.js +114 -0
  207. package/dist/indexer/passes/memory-inference.js +13 -5
  208. package/dist/indexer/passes/metadata.js +20 -0
  209. package/dist/indexer/read-preflight.js +23 -0
  210. package/dist/indexer/search/db-search.js +89 -13
  211. package/dist/indexer/search/fts-query.js +51 -0
  212. package/dist/indexer/search/ranking-contributors.js +95 -9
  213. package/dist/indexer/search/ranking.js +79 -3
  214. package/dist/indexer/search/search-fields.js +6 -0
  215. package/dist/indexer/search/search-source.js +32 -21
  216. package/dist/indexer/search/semantic-status.js +4 -0
  217. package/dist/indexer/walk/matchers.js +48 -0
  218. package/dist/indexer/walk/walker.js +21 -13
  219. package/dist/integrations/agent/builders.js +41 -13
  220. package/dist/integrations/agent/config.js +20 -59
  221. package/dist/integrations/agent/detect.js +9 -0
  222. package/dist/integrations/agent/index.js +3 -19
  223. package/dist/integrations/agent/model-aliases.js +16 -2
  224. package/dist/integrations/agent/profiles.js +79 -6
  225. package/dist/integrations/agent/prompts.js +75 -9
  226. package/dist/integrations/agent/runner-dispatch.js +83 -0
  227. package/dist/integrations/agent/runner.js +13 -9
  228. package/dist/integrations/agent/spawn.js +206 -81
  229. package/dist/integrations/harnesses/aider/agent-builder.js +113 -0
  230. package/dist/integrations/harnesses/aider/index.js +58 -0
  231. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  232. package/dist/integrations/harnesses/amazonq/agent-builder.js +153 -0
  233. package/dist/integrations/harnesses/amazonq/index.js +59 -0
  234. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  235. package/dist/integrations/harnesses/claude/agent-builder.js +46 -7
  236. package/dist/integrations/harnesses/claude/index.js +27 -23
  237. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  238. package/dist/integrations/harnesses/claude/session-log.js +10 -0
  239. package/dist/integrations/harnesses/codex/agent-builder.js +137 -0
  240. package/dist/integrations/harnesses/codex/index.js +63 -0
  241. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  242. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  243. package/dist/integrations/harnesses/copilot/index.js +60 -0
  244. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  245. package/dist/integrations/harnesses/gemini/agent-builder.js +121 -0
  246. package/dist/integrations/harnesses/gemini/index.js +60 -0
  247. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  248. package/dist/integrations/harnesses/index.js +28 -7
  249. package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
  250. package/dist/integrations/harnesses/opencode/index.js +17 -16
  251. package/dist/integrations/harnesses/opencode/session-log.js +173 -3
  252. package/dist/integrations/harnesses/opencode-sdk/harness.js +65 -0
  253. package/dist/integrations/harnesses/opencode-sdk/index.js +10 -34
  254. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +642 -71
  255. package/dist/integrations/harnesses/openhands/agent-builder.js +126 -0
  256. package/dist/integrations/harnesses/openhands/index.js +58 -0
  257. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  258. package/dist/integrations/harnesses/pi/agent-builder.js +104 -0
  259. package/dist/integrations/harnesses/pi/index.js +58 -0
  260. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  261. package/dist/integrations/harnesses/types.js +8 -0
  262. package/dist/integrations/session-logs/index.js +40 -11
  263. package/dist/llm/call-ai.js +2 -2
  264. package/dist/llm/client.js +34 -11
  265. package/dist/llm/embedder.js +67 -4
  266. package/dist/llm/embedders/cache.js +3 -1
  267. package/dist/llm/embedders/deterministic.js +66 -0
  268. package/dist/llm/embedders/local.js +73 -3
  269. package/dist/llm/feature-gate.js +16 -15
  270. package/dist/llm/graph-extract.js +67 -44
  271. package/dist/llm/memory-infer-impl.js +138 -0
  272. package/dist/llm/memory-infer.js +1 -127
  273. package/dist/llm/metadata-enhance.js +44 -31
  274. package/dist/llm/structured-call.js +49 -0
  275. package/dist/migrate-storage-node.mjs +8 -0
  276. package/dist/output/context.js +5 -5
  277. package/dist/output/renderers.js +87 -15
  278. package/dist/output/shapes/curate.js +14 -2
  279. package/dist/output/shapes/helpers.js +0 -3
  280. package/dist/output/shapes/passthrough.js +6 -1
  281. package/dist/output/text/helpers.js +241 -2
  282. package/dist/output/text/workflow.js +4 -1
  283. package/dist/registry/providers/skills-sh.js +21 -147
  284. package/dist/registry/providers/static-index.js +15 -157
  285. package/dist/registry/resolve.js +27 -9
  286. package/dist/runtime.js +25 -1
  287. package/dist/schemas/akm-config.json +14225 -0
  288. package/dist/schemas/akm-workflow.json +328 -0
  289. package/dist/scripts/migrate-storage.js +2743 -8390
  290. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +1652 -607
  291. package/dist/setup/detect.js +9 -0
  292. package/dist/setup/legacy-config.js +106 -0
  293. package/dist/setup/prompt.js +57 -0
  294. package/dist/setup/providers.js +14 -0
  295. package/dist/setup/registry-stash-loader.js +12 -0
  296. package/dist/setup/semantic-assets.js +124 -0
  297. package/dist/setup/setup.js +52 -1614
  298. package/dist/setup/steps/connection.js +734 -0
  299. package/dist/setup/steps/output.js +31 -0
  300. package/dist/setup/steps/platforms.js +124 -0
  301. package/dist/setup/steps/semantic.js +27 -0
  302. package/dist/setup/steps/sources.js +222 -0
  303. package/dist/setup/steps/stashdir.js +42 -0
  304. package/dist/setup/steps/tasks.js +152 -0
  305. package/dist/sources/include.js +6 -2
  306. package/dist/sources/providers/filesystem.js +0 -1
  307. package/dist/sources/providers/git-install.js +210 -0
  308. package/dist/sources/providers/git-provider.js +234 -0
  309. package/dist/sources/providers/git-stash.js +248 -0
  310. package/dist/sources/providers/git.js +10 -661
  311. package/dist/sources/providers/npm.js +2 -6
  312. package/dist/sources/providers/provider-utils.js +13 -7
  313. package/dist/sources/providers/sync-from-ref.js +9 -1
  314. package/dist/sources/providers/website.js +9 -5
  315. package/dist/sources/website-ingest.js +187 -29
  316. package/dist/sources/wiki-fetchers/registry.js +53 -0
  317. package/dist/sources/wiki-fetchers/youtube.js +239 -0
  318. package/dist/storage/database.js +45 -10
  319. package/dist/storage/managed-db.js +82 -0
  320. package/dist/storage/repositories/canaries-repository.js +107 -0
  321. package/dist/storage/repositories/consolidation-repository.js +38 -0
  322. package/dist/storage/repositories/embeddings-repository.js +72 -0
  323. package/dist/storage/repositories/events-repository.js +187 -0
  324. package/dist/storage/repositories/extract-sessions-repository.js +96 -0
  325. package/dist/storage/repositories/improve-runs-repository.js +146 -0
  326. package/dist/storage/repositories/index-db.js +14 -8
  327. package/dist/storage/repositories/proposals-repository.js +220 -0
  328. package/dist/storage/repositories/recombine-repository.js +213 -0
  329. package/dist/storage/repositories/registry-cache.js +93 -0
  330. package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
  331. package/dist/storage/repositories/task-history-repository.js +93 -0
  332. package/dist/storage/repositories/workflow-runs-repository.js +189 -1
  333. package/dist/storage/sqlite-pragmas.js +146 -0
  334. package/dist/tasks/backends/cron.js +1 -1
  335. package/dist/tasks/backends/index.js +9 -0
  336. package/dist/tasks/backends/launchd.js +1 -1
  337. package/dist/tasks/backends/schtasks.js +1 -1
  338. package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
  339. package/dist/tasks/runner.js +15 -13
  340. package/dist/text-import-hook.mjs +1 -1
  341. package/dist/wiki/wiki.js +52 -11
  342. package/dist/workflows/authoring/authoring.js +123 -10
  343. package/dist/workflows/authoring/workflow-program-template.yaml +31 -0
  344. package/dist/workflows/cli.js +5 -0
  345. package/dist/workflows/db.js +138 -4
  346. package/dist/workflows/exec/brief.js +484 -0
  347. package/dist/workflows/exec/native-executor.js +975 -0
  348. package/dist/workflows/exec/param-secrets.js +115 -0
  349. package/dist/workflows/exec/report.js +1295 -0
  350. package/dist/workflows/exec/run-workflow.js +596 -0
  351. package/dist/workflows/exec/scheduler.js +100 -0
  352. package/dist/workflows/exec/step-work.js +1156 -0
  353. package/dist/workflows/exec/unit-writer.js +23 -0
  354. package/dist/workflows/exec/watch.js +116 -0
  355. package/dist/workflows/exec/worktree.js +171 -0
  356. package/dist/workflows/ir/compile.js +388 -0
  357. package/dist/workflows/ir/params.js +54 -0
  358. package/dist/workflows/ir/plan-hash.js +33 -0
  359. package/dist/workflows/ir/schema.js +4 -0
  360. package/dist/workflows/parser.js +3 -1
  361. package/dist/workflows/program/expressions.js +369 -0
  362. package/dist/workflows/program/parser.js +760 -0
  363. package/dist/workflows/program/project.js +105 -0
  364. package/dist/workflows/program/schema.js +54 -0
  365. package/dist/workflows/renderer.js +82 -5
  366. package/dist/workflows/runtime/agent-identity.js +59 -14
  367. package/dist/workflows/runtime/runs.js +248 -153
  368. package/dist/workflows/runtime/unit-checkin.js +45 -0
  369. package/dist/workflows/runtime/workflow-asset-loader.js +188 -0
  370. package/dist/workflows/validate-summary.js +26 -10
  371. package/dist/workflows/validator.js +1 -1
  372. package/docs/README.md +69 -18
  373. package/docs/data-and-telemetry.md +7 -5
  374. package/docs/migration/release-notes/0.7.0.md +1 -1
  375. package/docs/migration/release-notes/0.9.0-beta.60.md +19 -0
  376. package/docs/migration/release-notes/0.9.0.md +39 -0
  377. package/package.json +10 -10
  378. package/dist/assets/tasks/core/update-stashes.yml +0 -4
  379. package/dist/commands/db-cli.js +0 -23
  380. package/dist/indexer/db/db-backup.js +0 -376
  381. package/dist/indexer/passes/staleness-detect.js +0 -488
@@ -0,0 +1,369 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * The deterministic expression language for YAML orchestration programs
6
+ * (R1 redesign addendum). `${{ ... }}` delimits references; everything else
7
+ * is literal text that passes through byte-exact.
8
+ *
9
+ * The grammar is CLOSED — exactly four roots, nothing else parses:
10
+ *
11
+ * params.<ident>
12
+ * steps.<ident>.output( .<ident> | [<non-negative int>] )*
13
+ * item
14
+ * item_index
15
+ *
16
+ * where <ident> is `[A-Za-z_][A-Za-z0-9_-]*`. No functions, no clock, no
17
+ * randomness, no ambient lookup — orchestration decisions stay pure
18
+ * functions of (frozen plan, params, journaled unit results).
19
+ *
20
+ * Templates are parsed ONCE into literal/reference segments; resolution is a
21
+ * single pass over that AST. Substituted content is data, never re-scanned,
22
+ * so a value containing `${{ params.x }}` is inserted literally — the P1
23
+ * re-scan injection bug class is structurally impossible.
24
+ *
25
+ * There is deliberately NO escape syntax in v1: a literal `${{` cannot
26
+ * appear in instructions. Authors who write one get a parse error from the
27
+ * validator (unterminated or invalid reference) telling them so.
28
+ *
29
+ * Pure module: no IO, no engine imports.
30
+ */
31
+ const OPEN = "${{";
32
+ const CLOSE = "}}";
33
+ // ── Template parsing ─────────────────────────────────────────────────────────
34
+ /**
35
+ * Split a template into literal and reference segments. Literal text passes
36
+ * through byte-exact, including `$`, `{`, `}`, `${`, `{{`, and `}}` sequences
37
+ * that do not form the exact `${{` opener. Errors are returned, not thrown.
38
+ */
39
+ export function parseTemplate(template) {
40
+ const segments = [];
41
+ const errors = [];
42
+ let cursor = 0;
43
+ while (cursor < template.length) {
44
+ const open = template.indexOf(OPEN, cursor);
45
+ if (open === -1)
46
+ break;
47
+ if (open > cursor)
48
+ segments.push({ kind: "literal", text: template.slice(cursor, open) });
49
+ const close = template.indexOf(CLOSE, open + OPEN.length);
50
+ const nested = template.indexOf(OPEN, open + OPEN.length);
51
+ if (close === -1) {
52
+ errors.push({
53
+ index: open,
54
+ message: `Unterminated ${OPEN} reference (no matching ${CLOSE}). ` +
55
+ `Note: there is no escape syntax — a literal ${OPEN} cannot appear in this text.`,
56
+ });
57
+ cursor = template.length;
58
+ break;
59
+ }
60
+ if (nested !== -1 && nested < close) {
61
+ errors.push({
62
+ index: nested,
63
+ message: `Nested ${OPEN} inside a reference — references cannot contain other references.`,
64
+ });
65
+ cursor = close + CLOSE.length;
66
+ continue;
67
+ }
68
+ const inner = template.slice(open + OPEN.length, close);
69
+ const parsed = parseExpression(inner);
70
+ if (parsed.ok) {
71
+ segments.push({
72
+ kind: "reference",
73
+ expr: parsed.expr,
74
+ raw: template.slice(open, close + CLOSE.length),
75
+ index: open,
76
+ });
77
+ }
78
+ else {
79
+ errors.push({ index: open, message: parsed.message });
80
+ }
81
+ cursor = close + CLOSE.length;
82
+ }
83
+ if (cursor < template.length)
84
+ segments.push({ kind: "literal", text: template.slice(cursor) });
85
+ return errors.length > 0 ? { ok: false, errors } : { ok: true, segments };
86
+ }
87
+ const GRAMMAR_HINT = "allowed forms: params.<name>, steps.<id>.output[...], item, item_index";
88
+ /**
89
+ * Parse a single expression (the text between `${{` and `}}`, or a bare
90
+ * whole-value field such as `map.over` after delimiter stripping).
91
+ */
92
+ export function parseExpression(source) {
93
+ const text = source.trim();
94
+ if (text === "")
95
+ return { ok: false, message: `Empty expression inside ${OPEN} ${CLOSE}; ${GRAMMAR_HINT}.` };
96
+ const root = readIdent(text, 0);
97
+ if (!root) {
98
+ return { ok: false, message: `Invalid expression "${text}" — must start with an identifier; ${GRAMMAR_HINT}.` };
99
+ }
100
+ switch (root.name) {
101
+ case "item":
102
+ case "item_index": {
103
+ if (root.end !== text.length) {
104
+ return { ok: false, message: `"${root.name}" takes no path — found trailing "${text.slice(root.end)}".` };
105
+ }
106
+ return { ok: true, expr: root.name === "item" ? { kind: "item" } : { kind: "itemIndex" } };
107
+ }
108
+ case "params": {
109
+ if (text[root.end] !== ".") {
110
+ return { ok: false, message: `"params" requires a name: params.<name> (got "${text}").` };
111
+ }
112
+ const name = readIdent(text, root.end + 1);
113
+ if (!name) {
114
+ return { ok: false, message: `Invalid param name after "params." in "${text}".` };
115
+ }
116
+ if (name.end !== text.length) {
117
+ return {
118
+ ok: false,
119
+ message: `"params.${name.name}" takes exactly one name — found trailing "${text.slice(name.end)}".`,
120
+ };
121
+ }
122
+ return { ok: true, expr: { kind: "param", name: name.name } };
123
+ }
124
+ case "steps": {
125
+ if (text[root.end] !== ".") {
126
+ return { ok: false, message: `"steps" requires a step id: steps.<id>.output (got "${text}").` };
127
+ }
128
+ const stepId = readIdent(text, root.end + 1);
129
+ if (!stepId) {
130
+ return { ok: false, message: `Invalid step id after "steps." in "${text}".` };
131
+ }
132
+ if (text[stepId.end] !== ".") {
133
+ return { ok: false, message: `"steps.${stepId.name}" must be followed by ".output" (got "${text}").` };
134
+ }
135
+ const output = readIdent(text, stepId.end + 1);
136
+ if (!output || output.name !== "output") {
137
+ return { ok: false, message: `Expected ".output" after "steps.${stepId.name}" in "${text}".` };
138
+ }
139
+ const path = parsePath(text, output.end);
140
+ if (!path.ok)
141
+ return { ok: false, message: path.message };
142
+ return { ok: true, expr: { kind: "stepOutput", stepId: stepId.name, path: path.path } };
143
+ }
144
+ default:
145
+ return { ok: false, message: `Unknown root "${root.name}" in "${text}"; ${GRAMMAR_HINT}.` };
146
+ }
147
+ }
148
+ /** `<ident>` is `[A-Za-z_][A-Za-z0-9_-]*`. Returns null when no ident starts at `start`. */
149
+ function readIdent(text, start) {
150
+ if (start >= text.length || !/[A-Za-z_]/.test(text[start]))
151
+ return null;
152
+ let end = start + 1;
153
+ while (end < text.length && /[A-Za-z0-9_-]/.test(text[end]))
154
+ end++;
155
+ return { name: text.slice(start, end), end };
156
+ }
157
+ /** Parse `( .<ident> | [<non-negative int>] )*` from `start` to end of text. */
158
+ function parsePath(text, start) {
159
+ const path = [];
160
+ let i = start;
161
+ while (i < text.length) {
162
+ const char = text[i];
163
+ if (char === ".") {
164
+ const ident = readIdent(text, i + 1);
165
+ if (!ident) {
166
+ return { ok: false, message: `Invalid path segment after "." at position ${i} in "${text}".` };
167
+ }
168
+ path.push(ident.name);
169
+ i = ident.end;
170
+ }
171
+ else if (char === "[") {
172
+ let j = i + 1;
173
+ while (j < text.length && /[0-9]/.test(text[j]))
174
+ j++;
175
+ if (j === i + 1 || text[j] !== "]") {
176
+ return {
177
+ ok: false,
178
+ message: `Invalid indexer at position ${i} in "${text}" — expected [<non-negative integer>].`,
179
+ };
180
+ }
181
+ path.push(Number.parseInt(text.slice(i + 1, j), 10));
182
+ i = j + 1;
183
+ }
184
+ else {
185
+ return { ok: false, message: `Unexpected character "${char}" at position ${i} in "${text}".` };
186
+ }
187
+ }
188
+ return { ok: true, path };
189
+ }
190
+ // ── Resolution ───────────────────────────────────────────────────────────────
191
+ /**
192
+ * Resolve parsed segments against a scope in a SINGLE pass — resolved values
193
+ * are concatenated as data and never re-scanned for further references.
194
+ * Strings insert verbatim; numbers/booleans via String(); objects/arrays as
195
+ * canonical JSON (recursively sorted keys); null/undefined/missing paths are
196
+ * resolution errors naming the reference.
197
+ */
198
+ export function resolveTemplate(segments, scope) {
199
+ const parts = [];
200
+ const errors = [];
201
+ for (const segment of segments) {
202
+ if (segment.kind === "literal") {
203
+ parts.push(segment.text);
204
+ continue;
205
+ }
206
+ const resolved = resolveReference(segment.expr, scope);
207
+ if (!resolved.ok) {
208
+ errors.push(resolved.error);
209
+ continue;
210
+ }
211
+ const value = resolved.value;
212
+ if (typeof value === "string") {
213
+ parts.push(value);
214
+ }
215
+ else if (typeof value === "number" || typeof value === "boolean") {
216
+ parts.push(String(value));
217
+ }
218
+ else if (typeof value === "object" && value !== null) {
219
+ parts.push(canonicalJson(value));
220
+ }
221
+ else {
222
+ errors.push({
223
+ reference: formatReference(segment.expr),
224
+ message: `${formatReference(segment.expr)} resolved to an unsupported value type (${typeof value}).`,
225
+ });
226
+ }
227
+ }
228
+ return errors.length > 0 ? { ok: false, errors } : { ok: true, text: parts.join("") };
229
+ }
230
+ /**
231
+ * Resolve a whole-value field (`map.over`, `route.input`) from its RAW
232
+ * template string: the text must be exactly one `${{ … }}` reference with no
233
+ * surrounding literal text (the compiler enforces this for YAML programs;
234
+ * frozen plans are re-checked here so a tampered/legacy plan fails loudly
235
+ * instead of string-splicing). The reference resolves to its RAW value —
236
+ * arrays stay arrays, objects stay objects.
237
+ */
238
+ export function resolveWholeValue(template, scope) {
239
+ const parsed = parseTemplate(template);
240
+ if (!parsed.ok) {
241
+ return {
242
+ ok: false,
243
+ error: { reference: template, message: parsed.errors.map((e) => e.message).join(" ") },
244
+ };
245
+ }
246
+ const [first] = parsed.segments;
247
+ if (parsed.segments.length !== 1 || first?.kind !== "reference") {
248
+ return {
249
+ ok: false,
250
+ error: {
251
+ reference: template,
252
+ message: `expected a single whole-value \${{ … }} reference with no surrounding text ` +
253
+ `(e.g. "\${{ steps.discover.output.files }}"), got ${JSON.stringify(template)}.`,
254
+ },
255
+ };
256
+ }
257
+ return resolveReference(first.expr, scope);
258
+ }
259
+ /**
260
+ * Resolve a single reference to its RAW value for whole-value contexts
261
+ * (`map.over`, `route.input`): arrays stay arrays, objects stay objects.
262
+ * null/undefined values and missing paths are errors, same as in templates.
263
+ */
264
+ export function resolveReference(expr, scope) {
265
+ const reference = formatReference(expr);
266
+ const fail = (message) => ({ ok: false, error: { reference, message } });
267
+ switch (expr.kind) {
268
+ case "param": {
269
+ if (!Object.hasOwn(scope.params, expr.name)) {
270
+ return fail(`${reference} is not defined in the run's params.`);
271
+ }
272
+ return finish(scope.params[expr.name], reference, fail);
273
+ }
274
+ case "item": {
275
+ if (scope.item === undefined)
276
+ return fail("item is only available inside a map unit.");
277
+ return finish(scope.item, reference, fail);
278
+ }
279
+ case "itemIndex": {
280
+ if (typeof scope.itemIndex !== "number")
281
+ return fail("item_index is only available inside a map unit.");
282
+ return { ok: true, value: scope.itemIndex };
283
+ }
284
+ case "stepOutput": {
285
+ if (!Object.hasOwn(scope.stepOutputs, expr.stepId)) {
286
+ return fail(`steps.${expr.stepId}.output is not available — step "${expr.stepId}" has no recorded output.`);
287
+ }
288
+ let current = scope.stepOutputs[expr.stepId];
289
+ let walked = `steps.${expr.stepId}.output`;
290
+ for (const segment of expr.path) {
291
+ if (typeof segment === "number") {
292
+ if (!Array.isArray(current)) {
293
+ return fail(`${walked} is not an array — cannot resolve index [${segment}].`);
294
+ }
295
+ if (segment >= current.length) {
296
+ return fail(`${walked}[${segment}] is out of bounds (array length ${current.length}).`);
297
+ }
298
+ current = current[segment];
299
+ walked += `[${segment}]`;
300
+ }
301
+ else {
302
+ if (typeof current !== "object" || current === null || Array.isArray(current)) {
303
+ return fail(`${walked} is not an object — cannot resolve property "${segment}".`);
304
+ }
305
+ if (!Object.hasOwn(current, segment)) {
306
+ return fail(`${walked}.${segment} is missing (no such property, resolving ${reference}).`);
307
+ }
308
+ current = current[segment];
309
+ walked += `.${segment}`;
310
+ }
311
+ }
312
+ return finish(current, reference, fail);
313
+ }
314
+ }
315
+ }
316
+ function finish(value, reference, fail) {
317
+ if (value === undefined)
318
+ return fail(`${reference} resolved to undefined.`);
319
+ if (value === null)
320
+ return fail(`${reference} resolved to null.`);
321
+ return { ok: true, value };
322
+ }
323
+ // ── Introspection helpers ────────────────────────────────────────────────────
324
+ /** The reference ASTs of a parsed template, in document order — for validator edge checking. */
325
+ export function listReferences(segments) {
326
+ const references = [];
327
+ for (const segment of segments) {
328
+ if (segment.kind === "reference")
329
+ references.push(segment.expr);
330
+ }
331
+ return references;
332
+ }
333
+ /** Canonical source spelling of a reference, e.g. `steps.review.output.files[2].name`. */
334
+ export function formatReference(expr) {
335
+ switch (expr.kind) {
336
+ case "param":
337
+ return `params.${expr.name}`;
338
+ case "item":
339
+ return "item";
340
+ case "itemIndex":
341
+ return "item_index";
342
+ case "stepOutput": {
343
+ let text = `steps.${expr.stepId}.output`;
344
+ for (const segment of expr.path) {
345
+ text += typeof segment === "number" ? `[${segment}]` : `.${segment}`;
346
+ }
347
+ return text;
348
+ }
349
+ }
350
+ }
351
+ // ── Canonical JSON ───────────────────────────────────────────────────────────
352
+ /**
353
+ * Stable stringify with recursively sorted object keys, so equal values
354
+ * render identically regardless of key insertion order. Same pattern as the
355
+ * module-private helper in exec/native-executor.ts (not exported there).
356
+ */
357
+ function canonicalJson(value) {
358
+ return JSON.stringify(sortKeys(value));
359
+ }
360
+ function sortKeys(value) {
361
+ if (Array.isArray(value))
362
+ return value.map(sortKeys);
363
+ if (value && typeof value === "object") {
364
+ return Object.fromEntries(Object.entries(value)
365
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
366
+ .map(([k, v]) => [k, sortKeys(v)]));
367
+ }
368
+ return value;
369
+ }