akm-cli 0.9.16 → 0.9.17-alpha.10

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 (403) hide show
  1. package/CHANGELOG.md +2101 -0
  2. package/STABILITY.md +11 -10
  3. package/dist/akm +124 -193
  4. package/dist/akm-migrate +38 -19
  5. package/dist/assets/hints/cli-hints-full.md +6 -7
  6. package/dist/assets/improve-strategies/catchup.json +0 -3
  7. package/dist/assets/improve-strategies/consolidate.json +0 -1
  8. package/dist/assets/improve-strategies/default.json +1 -2
  9. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
  10. package/dist/assets/improve-strategies/quick.json +1 -2
  11. package/dist/assets/improve-strategies/reflect-distill.json +1 -2
  12. package/dist/assets/improve-strategies/thorough.json +0 -3
  13. package/dist/assets/prompts/consolidate-pair.md +20 -0
  14. package/dist/assets/prompts/consolidate-system.md +4 -11
  15. package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
  17. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
  18. package/dist/assets/templates/html/health.html +3 -5
  19. package/dist/cli/retired-commands.js +1 -1
  20. package/dist/cli/shared.js +6 -2
  21. package/dist/cli/unknown-flags.js +24 -1
  22. package/dist/cli.js +68 -10
  23. package/dist/commands/agent/agent-dispatch.js +1 -1
  24. package/dist/commands/command/command-execution.js +24 -62
  25. package/dist/commands/feedback-cli.js +0 -1
  26. package/dist/commands/health/accept-rate.js +6 -0
  27. package/dist/commands/health/archive-usage.js +92 -0
  28. package/dist/commands/health/checks.js +83 -74
  29. package/dist/commands/health/config-skew.js +38 -0
  30. package/dist/commands/health/data-dir-usage.js +25 -13
  31. package/dist/commands/health/egress.js +54 -0
  32. package/dist/commands/health/html-report.js +1 -42
  33. package/dist/commands/health/improve-metrics.js +136 -591
  34. package/dist/commands/health/md-report.js +1 -6
  35. package/dist/commands/health/plugin-staleness.js +53 -3
  36. package/dist/commands/health/renderers.js +12 -4
  37. package/dist/commands/health/report-view-model.js +14 -120
  38. package/dist/commands/health/types-improve.js +4 -19
  39. package/dist/commands/health/windows.js +64 -74
  40. package/dist/commands/health.js +145 -143
  41. package/dist/commands/improve/consolidate/chunking.js +26 -117
  42. package/dist/commands/improve/consolidate/continuity-check.js +137 -0
  43. package/dist/commands/improve/consolidate/pair-pass.js +791 -0
  44. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  45. package/dist/commands/improve/consolidate.js +589 -1127
  46. package/dist/commands/improve/content-hash.js +16 -24
  47. package/dist/commands/improve/distill/content-repair.js +18 -100
  48. package/dist/commands/improve/distill-guards.js +20 -81
  49. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  50. package/dist/commands/improve/distill.js +608 -1041
  51. package/dist/commands/improve/eligibility.js +126 -390
  52. package/dist/commands/improve/execution.js +8 -10
  53. package/dist/commands/improve/extract-prompt.js +1 -2
  54. package/dist/commands/improve/extract.js +487 -1046
  55. package/dist/commands/improve/feedback-valence.js +0 -25
  56. package/dist/commands/improve/improve-cli.js +75 -169
  57. package/dist/commands/improve/improve-result-file.js +10 -66
  58. package/dist/commands/improve/improve-strategies.js +52 -4
  59. package/dist/commands/improve/improve-usage-report.js +18 -64
  60. package/dist/commands/improve/improve.js +480 -1074
  61. package/dist/commands/improve/ledger.js +119 -0
  62. package/dist/commands/improve/locks.js +2 -8
  63. package/dist/commands/improve/loop-stages.js +415 -1073
  64. package/dist/commands/improve/memory/derived-ref.js +12 -77
  65. package/dist/commands/improve/memory/memory-belief.js +16 -118
  66. package/dist/commands/improve/memory/memory-improve.js +266 -14
  67. package/dist/commands/improve/outcome-loop.js +28 -156
  68. package/dist/commands/improve/planner.js +5 -15
  69. package/dist/commands/improve/preparation.js +779 -2319
  70. package/dist/commands/improve/proactive-maintenance.js +34 -101
  71. package/dist/commands/improve/reflect-noise.js +104 -280
  72. package/dist/commands/improve/reflect.js +642 -1353
  73. package/dist/commands/improve/retrieval-gate.js +127 -0
  74. package/dist/commands/improve/retrieval-scope.js +92 -0
  75. package/dist/commands/improve/salience.js +41 -240
  76. package/dist/commands/improve/session-asset.js +19 -100
  77. package/dist/commands/improve/stage.js +322 -0
  78. package/dist/commands/lint/base-linter.js +37 -15
  79. package/dist/commands/proposal/drain.js +261 -578
  80. package/dist/commands/proposal/proposal-cli.js +19 -20
  81. package/dist/commands/proposal/proposal-types.js +31 -24
  82. package/dist/commands/proposal/proposal.js +38 -8
  83. package/dist/commands/proposal/propose.js +134 -160
  84. package/dist/commands/proposal/repository.js +1097 -1394
  85. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  86. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  87. package/dist/commands/proposal/validators/proposals.js +22 -89
  88. package/dist/commands/read/curate.js +105 -462
  89. package/dist/commands/read/knowledge.js +3 -2
  90. package/dist/commands/read/search-cli.js +16 -33
  91. package/dist/commands/read/search.js +17 -23
  92. package/dist/commands/read/show.js +57 -108
  93. package/dist/commands/sources/bundle-cli.js +25 -2
  94. package/dist/commands/sources/bundle-config-ops.js +4 -0
  95. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  96. package/dist/commands/sources/info.js +127 -29
  97. package/dist/commands/sources/installed-stashes.js +197 -746
  98. package/dist/commands/sources/schema-repair.js +98 -129
  99. package/dist/commands/sources/source-add.js +62 -12
  100. package/dist/commands/sources/source-manage.js +9 -2
  101. package/dist/commands/sources/stash-cli.js +24 -4
  102. package/dist/commands/tasks/explain.js +10 -13
  103. package/dist/commands/tasks/tasks-cli.js +12 -13
  104. package/dist/commands/tasks/tasks.js +350 -936
  105. package/dist/commands/tasks/validate.js +26 -24
  106. package/dist/commands/workflow/plan.js +22 -29
  107. package/dist/commands/workflow-cli.js +4 -4
  108. package/dist/core/adapter/adapters/akm-adapter.js +2 -1
  109. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  110. package/dist/core/adapter/adapters/akm-metadata.js +42 -12
  111. package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
  112. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  113. package/dist/core/adapter/execution-source.js +17 -29
  114. package/dist/core/asset/asset-placement.js +4 -13
  115. package/dist/core/asset/frontmatter.js +106 -1
  116. package/dist/core/asset/resolve-ref.js +1 -1
  117. package/dist/core/bundle-id.js +42 -5
  118. package/dist/core/bundle-rename.js +285 -0
  119. package/dist/core/config/config-io.js +1 -2
  120. package/dist/core/config/config-schema.js +9 -34
  121. package/dist/core/config/config-walker.js +1 -1
  122. package/dist/core/config/config.js +184 -111
  123. package/dist/core/config/engine-semantics.js +0 -2
  124. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  125. package/dist/core/config/schema/embedding.js +20 -5
  126. package/dist/core/config/schema/engines.js +5 -0
  127. package/dist/core/config/schema/execution.js +1 -1
  128. package/dist/core/config/schema/experimental.js +1 -1
  129. package/dist/core/config/schema/improve-processes.js +54 -125
  130. package/dist/core/config/schema/improve.js +4 -42
  131. package/dist/core/config/schema/index-config.js +9 -48
  132. package/dist/core/config/schema/scheduler.js +12 -12
  133. package/dist/core/config/schema/search.js +6 -22
  134. package/dist/core/env-secret-ref.js +0 -1
  135. package/dist/core/errors.js +8 -9
  136. package/dist/core/file-change.js +13 -5
  137. package/dist/core/file-lock.js +76 -173
  138. package/dist/core/improve-result.js +35 -7
  139. package/dist/core/improve-types.js +0 -1
  140. package/dist/core/logs-db.js +2 -2
  141. package/dist/core/loopback.js +7 -12
  142. package/dist/core/non-task-input.js +20 -0
  143. package/dist/core/parse.js +13 -16
  144. package/dist/core/paths.js +0 -24
  145. package/dist/core/redaction.js +109 -2
  146. package/dist/core/run-lock.js +2 -5
  147. package/dist/core/spawn-env.js +1 -1
  148. package/dist/core/state/migrations.js +123 -61
  149. package/dist/core/state-db-scope.js +2 -4
  150. package/dist/core/state-db.js +126 -692
  151. package/dist/core/time.js +0 -20
  152. package/dist/core/type-presentation.js +1 -9
  153. package/dist/core/write-source.js +294 -1005
  154. package/dist/execution/input-contract.js +1 -1
  155. package/dist/execution/resolved-request.js +135 -689
  156. package/dist/execution/source.js +63 -257
  157. package/dist/execution/target-ref.js +1 -1
  158. package/dist/indexer/bundle-identity-guard.js +2 -2
  159. package/dist/indexer/db/llm-cache.js +2 -2
  160. package/dist/indexer/ensure-index.js +77 -73
  161. package/dist/indexer/index-rebuild-lock.js +3 -11
  162. package/dist/indexer/index-writer-lock.js +8 -17
  163. package/dist/indexer/index-written-assets.js +141 -154
  164. package/dist/indexer/indexer.js +400 -1124
  165. package/dist/indexer/links/declared-links.js +90 -0
  166. package/dist/indexer/materialize-embeddings.js +60 -397
  167. package/dist/indexer/passes/memory-inference.js +96 -90
  168. package/dist/indexer/passes/metadata.js +132 -219
  169. package/dist/indexer/read-preflight.js +0 -7
  170. package/dist/indexer/scan/doc-to-entry.js +2 -3
  171. package/dist/indexer/scan/drain-dir.js +1 -1
  172. package/dist/indexer/search/db-search.js +190 -590
  173. package/dist/indexer/search/fts-query.js +30 -41
  174. package/dist/indexer/search/ranking.js +28 -154
  175. package/dist/indexer/search/search-attribution.js +12 -32
  176. package/dist/indexer/search/search-fields.js +11 -15
  177. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  178. package/dist/indexer/search/search-source.js +1 -4
  179. package/dist/indexer/usage/usage-events.js +36 -7
  180. package/dist/indexer/walk/walker.js +3 -4
  181. package/dist/integrations/agent/engine-fallback.js +23 -40
  182. package/dist/integrations/agent/engine-resolution.js +93 -183
  183. package/dist/integrations/agent/execution.js +507 -0
  184. package/dist/integrations/agent/model-map.js +28 -156
  185. package/dist/integrations/agent/request-lowering.js +66 -141
  186. package/dist/integrations/agent/runner-dispatch.js +143 -321
  187. package/dist/integrations/agent/runner.js +54 -14
  188. package/dist/integrations/lockfile.js +53 -101
  189. package/dist/llm/client.js +18 -6
  190. package/dist/llm/embedders/deterministic.js +2 -3
  191. package/dist/llm/embedders/profile.js +71 -0
  192. package/dist/llm/embedders/remote.js +11 -17
  193. package/dist/llm/feature-gate.js +0 -8
  194. package/dist/llm/index-passes.js +3 -5
  195. package/dist/llm/memory-infer.js +1 -2
  196. package/dist/llm/structured-call.js +5 -24
  197. package/dist/output/generic-render.js +23 -11
  198. package/dist/output/html-render.js +13 -10
  199. package/dist/output/render-registry.js +3 -32
  200. package/dist/output/shapes/helpers.js +25 -38
  201. package/dist/output/shapes/passthrough.js +1 -9
  202. package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
  203. package/dist/output/text/command-format.js +69 -31
  204. package/dist/output/text/helpers.js +1 -1
  205. package/dist/output/text/migrate.js +5 -14
  206. package/dist/output/text/proposal-format.js +48 -3
  207. package/dist/output/text/show-format.js +13 -17
  208. package/dist/output/text/workflow-format.js +0 -32
  209. package/dist/output/text.js +2 -0
  210. package/dist/registry/factory.js +4 -19
  211. package/dist/registry/network.js +66 -220
  212. package/dist/registry/providers/index.js +0 -2
  213. package/dist/registry/providers/skills-sh.js +3 -14
  214. package/dist/registry/providers/static-index.js +24 -26
  215. package/dist/registry/resolve.js +55 -131
  216. package/dist/scripts/akm-migrate-node.js +42948 -92369
  217. package/dist/scripts/akm-migrate.js +42935 -92354
  218. package/dist/setup/registry-stash-loader.js +4 -13
  219. package/dist/setup/semantic-assets.js +3 -44
  220. package/dist/setup/setup.js +1 -1
  221. package/dist/setup/steps/connection.js +5 -6
  222. package/dist/setup/steps/platforms.js +2 -2
  223. package/dist/setup/steps/tasks.js +25 -15
  224. package/dist/sources/provider-factory.js +17 -18
  225. package/dist/sources/providers/filesystem.js +2 -3
  226. package/dist/sources/providers/git-install.js +7 -1
  227. package/dist/sources/providers/git-provider.js +0 -3
  228. package/dist/sources/providers/git-stash.js +83 -21
  229. package/dist/sources/providers/npm.js +2 -4
  230. package/dist/sources/providers/provider-utils.js +5 -10
  231. package/dist/sources/providers/website.js +0 -2
  232. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  233. package/dist/sources/website-url.js +2 -2
  234. package/dist/storage/database.js +9 -35
  235. package/dist/storage/repositories/improve-ledger-repository.js +209 -0
  236. package/dist/storage/repositories/index-connection.js +39 -72
  237. package/dist/storage/repositories/index-entries-repository.js +131 -129
  238. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  239. package/dist/storage/repositories/index-entry-schema.js +101 -268
  240. package/dist/storage/repositories/index-fts-repository.js +86 -256
  241. package/dist/storage/repositories/index-links-repository.js +143 -0
  242. package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
  243. package/dist/storage/repositories/index-meta-repository.js +6 -4
  244. package/dist/storage/repositories/index-schema.js +257 -325
  245. package/dist/storage/repositories/index-utility-repository.js +8 -29
  246. package/dist/storage/repositories/index-vec-repository.js +133 -414
  247. package/dist/storage/repositories/outcome-repository.js +2 -1
  248. package/dist/storage/repositories/proposals-repository.js +104 -1
  249. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  250. package/dist/storage/repositories/salience-repository.js +1 -19
  251. package/dist/storage/repositories/task-history-repository.js +26 -4
  252. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  253. package/dist/storage/sqlite-migrations.js +136 -0
  254. package/dist/storage/sqlite-pragmas.js +11 -9
  255. package/dist/storage/sqlite-transaction.js +170 -0
  256. package/dist/storage/state-db-integrity.js +130 -0
  257. package/dist/tasks/activation-config.js +134 -62
  258. package/dist/tasks/backends/cron.js +191 -302
  259. package/dist/tasks/backends/exec-utils.js +2 -5
  260. package/dist/tasks/backends/launchd.js +141 -748
  261. package/dist/tasks/backends/schtasks.js +119 -623
  262. package/dist/tasks/prepare/prepare-support.js +5 -15
  263. package/dist/tasks/prepare/prepare.js +0 -2
  264. package/dist/tasks/resolve-akm-bin.js +20 -79
  265. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  266. package/dist/tasks/run/load-task.js +1 -1
  267. package/dist/tasks/scheduler-binding.js +20 -238
  268. package/dist/tasks/scheduler-invocation.js +136 -244
  269. package/dist/tasks/scheduler-lock.js +53 -0
  270. package/dist/tasks/scheduler-sync.js +368 -679
  271. package/dist/tasks/source/parse-task-source.js +55 -9
  272. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  273. package/dist/tasks/source/task-to-v4.js +464 -88
  274. package/dist/workflows/authoring/authoring.js +3 -12
  275. package/dist/workflows/compile.js +211 -0
  276. package/dist/workflows/concurrency-policy.js +13 -74
  277. package/dist/workflows/exec/child-invocation.js +3 -17
  278. package/dist/workflows/exec/child-workflow.js +32 -141
  279. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  280. package/dist/workflows/exec/environment.js +98 -0
  281. package/dist/workflows/exec/exec-unit.js +33 -140
  282. package/dist/workflows/exec/frozen-judge.js +7 -59
  283. package/dist/workflows/exec/native-executor.js +82 -341
  284. package/dist/workflows/exec/param-secrets.js +29 -47
  285. package/dist/workflows/exec/run-workflow.js +154 -387
  286. package/dist/workflows/exec/scheduler.js +9 -36
  287. package/dist/workflows/exec/step-work.js +127 -430
  288. package/dist/workflows/exec/unit-dispatch.js +11 -63
  289. package/dist/workflows/exec/unit-writer.js +8 -52
  290. package/dist/workflows/exec/worktree.js +39 -273
  291. package/dist/workflows/freeze/child-output-references.js +4 -15
  292. package/dist/workflows/freeze/environment.js +99 -92
  293. package/dist/workflows/freeze/freeze.js +172 -0
  294. package/dist/workflows/freeze/step-values.js +19 -21
  295. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  296. package/dist/workflows/freeze/targets/command.js +10 -33
  297. package/dist/workflows/freeze/targets/script.js +5 -12
  298. package/dist/workflows/freeze/targets/shell.js +3 -6
  299. package/dist/workflows/freeze/targets/task.js +25 -80
  300. package/dist/workflows/freeze/task-bindings.js +20 -67
  301. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  302. package/dist/workflows/ir/params.js +6 -51
  303. package/dist/workflows/ir/plan-hash.js +2 -34
  304. package/dist/workflows/parser.js +140 -43
  305. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  306. package/dist/workflows/renderer.js +36 -69
  307. package/dist/workflows/resource-limits.js +12 -120
  308. package/dist/workflows/runtime/agent-identity.js +8 -40
  309. package/dist/workflows/runtime/run-outputs.js +3 -6
  310. package/dist/workflows/runtime/run-plan.js +316 -0
  311. package/dist/workflows/runtime/runs.js +48 -200
  312. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  313. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  314. package/dist/workflows/validate-summary.js +2 -7
  315. package/docs/integration/bundling-akm.md +49 -42
  316. package/docs/migration/README.md +1 -0
  317. package/docs/migration/release-notes/0.9.17.md +43 -0
  318. package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
  319. package/docs/reference/cli.md +232 -135
  320. package/docs/reference/configuration.md +71 -57
  321. package/docs/reference/data-and-telemetry.md +20 -21
  322. package/docs/reference/tasks.md +105 -39
  323. package/docs/reference/workflow-schema.md +14 -18
  324. package/docs/reference/workflows.md +6 -9
  325. package/package.json +1 -1
  326. package/schemas/akm-config.json +115 -738
  327. package/schemas/akm-workflow.json +1 -0
  328. package/dist/assets/improve-strategies/graph-refresh.json +0 -15
  329. package/dist/assets/prompts/contradiction-judge.md +0 -33
  330. package/dist/assets/prompts/graph-extract-system.md +0 -1
  331. package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
  332. package/dist/assets/prompts/metadata-enhance-system.md +0 -1
  333. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
  334. package/dist/commands/health/advisories.js +0 -150
  335. package/dist/commands/health/metrics.js +0 -329
  336. package/dist/commands/health/surfaces.js +0 -102
  337. package/dist/commands/improve/anti-collapse.js +0 -83
  338. package/dist/commands/improve/collapse-detector.js +0 -432
  339. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  340. package/dist/commands/improve/consolidate/merge.js +0 -149
  341. package/dist/commands/improve/distill/promote-memory.js +0 -291
  342. package/dist/commands/improve/distill/quality-gate.js +0 -337
  343. package/dist/commands/improve/eval-cases.js +0 -52
  344. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  345. package/dist/commands/improve/proposal-envelope.js +0 -31
  346. package/dist/commands/improve/run-context.js +0 -123
  347. package/dist/commands/improve/shared.js +0 -31
  348. package/dist/commands/improve/source-identity.js +0 -28
  349. package/dist/commands/improve/triage.js +0 -96
  350. package/dist/commands/proposal/drain-policies.js +0 -151
  351. package/dist/commands/sources/update-transaction.js +0 -220
  352. package/dist/core/action-contributors.js +0 -28
  353. package/dist/core/config/config-version-shim.js +0 -101
  354. package/dist/core/fs-txn.js +0 -405
  355. package/dist/core/lexical-score.js +0 -25
  356. package/dist/core/maintenance-barrier.js +0 -167
  357. package/dist/execution/executable-identity.js +0 -105
  358. package/dist/execution/guarded-source.js +0 -427
  359. package/dist/indexer/db/graph-db.js +0 -444
  360. package/dist/indexer/graph/graph-boost.js +0 -427
  361. package/dist/indexer/graph/graph-dedup.js +0 -95
  362. package/dist/indexer/graph/graph-extraction.js +0 -1108
  363. package/dist/indexer/search/name-match.js +0 -35
  364. package/dist/indexer/search/ranking-contributors.js +0 -515
  365. package/dist/indexer/search/ranking-types.js +0 -4
  366. package/dist/indexer/walk/project-context.js +0 -192
  367. package/dist/integrations/agent/execution-cascade.js +0 -566
  368. package/dist/integrations/agent/execution-definitions.js +0 -202
  369. package/dist/integrations/agent/execution-lowering.js +0 -841
  370. package/dist/integrations/agent/execution-preparation.js +0 -98
  371. package/dist/integrations/agent/inline-execution.js +0 -74
  372. package/dist/llm/graph-extract.js +0 -728
  373. package/dist/llm/metadata-enhance.js +0 -96
  374. package/dist/registry/create-provider-registry.js +0 -29
  375. package/dist/registry/pinned-request-helper.js +0 -247
  376. package/dist/registry/pinned-transport.js +0 -717
  377. package/dist/sources/providers/index.js +0 -14
  378. package/dist/storage/engines/sqlite-migrations.js +0 -271
  379. package/dist/storage/repositories/canaries-repository.js +0 -107
  380. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  381. package/dist/storage/repositories/registry-cache.js +0 -113
  382. package/dist/tasks/scheduler-sync-preview.js +0 -52
  383. package/dist/tasks/source/task-to-v3.js +0 -507
  384. package/dist/workflows/freeze/resolve-steps.js +0 -86
  385. package/dist/workflows/freeze/source-freeze.js +0 -64
  386. package/dist/workflows/ir/compile.js +0 -321
  387. package/dist/workflows/ir/environment-v4.js +0 -330
  388. package/dist/workflows/ir/freeze-v4.js +0 -153
  389. package/dist/workflows/ir/schema-v4.js +0 -745
  390. package/dist/workflows/ir/schema.js +0 -354
  391. package/dist/workflows/program/schema.js +0 -77
  392. package/dist/workflows/runtime/checkin.js +0 -57
  393. package/dist/workflows/runtime/plan-classifier.js +0 -196
  394. package/dist/workflows/runtime/unit-checkin.js +0 -45
  395. package/dist/workflows/runtime/unit-phases.js +0 -20
  396. package/dist/workflows/schema.js +0 -4
  397. package/dist/workflows/source-ir/compile.js +0 -200
  398. package/dist/workflows/source-ir/program.js +0 -50
  399. package/dist/workflows/source-ir/result.js +0 -26
  400. package/dist/workflows/source-ir/schema.js +0 -786
  401. package/dist/workflows/source-ir/triggers.js +0 -79
  402. package/dist/workflows/source-ir/uses.js +0 -40
  403. package/dist/workflows/validator.js +0 -60
@@ -12,9 +12,8 @@
12
12
  * target below so a configured registry cannot preselect a different source
13
13
  * merely by reusing a trusted display ID.
14
14
  */
15
- import { jsonWithByteCap } from "../core/common.js";
16
15
  import { hasRegistryUrlCredentials } from "../core/registry-url.js";
17
- import { allowPrivateRegistryFixtureForTests, cancelRegistryResponse, fetchRegistryResponse, } from "../registry/network.js";
16
+ import { fetchRegistryJson } from "../registry/network.js";
18
17
  import { parseRegistryRef } from "../registry/resolve.js";
19
18
  // ── Default selections ──────────────────────────────────────────────────────
20
19
  const AUTHENTICATED_DEFAULT_TARGETS = {
@@ -74,20 +73,12 @@ export async function loadSetupStashes(registryUrl, timeoutMs = 4000) {
74
73
  }
75
74
  async function loadSetupStashesReal(registryUrl, timeoutMs = 4000) {
76
75
  try {
77
- const response = await fetchRegistryResponse(registryUrl, { headers: { Accept: "application/json" } }, {
78
- policy: { kind: "public-registry" },
76
+ const raw = await fetchRegistryJson(registryUrl, {
77
+ headers: { Accept: "application/json" },
79
78
  timeoutMs,
80
79
  retries: 0,
81
- allowPrivateHostsForTesting: allowPrivateRegistryFixtureForTests(registryUrl),
82
80
  });
83
- if (!response.ok) {
84
- await cancelRegistryResponse(response);
85
- return FALLBACK_STASHES;
86
- }
87
- const raw = await jsonWithByteCap(response, 10 * 1024 * 1024, {
88
- bodyTimeoutMs: timeoutMs,
89
- });
90
- if (!Array.isArray(raw.stashes) || raw.stashes.length === 0)
81
+ if (!Array.isArray(raw?.stashes) || raw.stashes.length === 0)
91
82
  return FALLBACK_STASHES;
92
83
  const entries = raw.stashes.flatMap((item) => {
93
84
  if (!item || typeof item !== "object")
@@ -4,21 +4,13 @@
4
4
  /**
5
5
  * Semantic-search asset preparation for the setup wizard. Transformers.js is
6
6
  * a normal external package dependency; setup never mutates the installed CLI.
7
- * This module only prepares the model and probes sqlite-vec.
7
+ * This module only prepares the model.
8
8
  */
9
- import fs from "node:fs";
10
- import os from "node:os";
11
- import path from "node:path";
12
9
  import * as p from "../cli/clack.js";
13
10
  import { isHttpUrl } from "../core/common.js";
14
11
  import { checkEmbeddingAvailability, DEFAULT_LOCAL_MODEL, isTransformersAvailable } from "../llm/embedder.js";
15
- import { closeDatabase, openIndexDatabase } from "../storage/repositories/index-connection.js";
16
- import { isVecAvailable } from "../storage/repositories/index-vec-repository.js";
17
- // Approximate first-download sizes used in the setup note.
18
- // LOCAL_MODEL_APPROX_SIZE_MB tracks the default local model (DEFAULT_LOCAL_MODEL).
12
+ // Approximate first-download size of the default local model (DEFAULT_LOCAL_MODEL), used in the setup note.
19
13
  const LOCAL_MODEL_APPROX_SIZE_MB = 130;
20
- // SQLITE_VEC_APPROX_SIZE_MB reflects the optional sqlite-vec install footprint.
21
- const SQLITE_VEC_APPROX_SIZE_MB = 5;
22
14
  export function isRemoteEmbeddingConfig(embedding) {
23
15
  return isHttpUrl(embedding?.endpoint);
24
16
  }
@@ -27,14 +19,10 @@ export function isRemoteEmbeddingConfig(embedding) {
27
19
  */
28
20
  export function describeSemanticSearchAssets(embedding) {
29
21
  if (isRemoteEmbeddingConfig(embedding)) {
30
- return [
31
- `• Embedding endpoint: ${embedding?.provider ?? "custom"} / ${embedding?.model} (no local model download)`,
32
- `• sqlite-vec acceleration: optional native extension (~${SQLITE_VEC_APPROX_SIZE_MB} MB when installed separately)`,
33
- ];
22
+ return [`• Embedding endpoint: ${embedding?.provider ?? "custom"} / ${embedding?.model} (no local model download)`];
34
23
  }
35
24
  return [
36
25
  `• Local embedding model: ${embedding?.localModel ?? DEFAULT_LOCAL_MODEL} (~${LOCAL_MODEL_APPROX_SIZE_MB} MB download on first use)`,
37
- `• sqlite-vec acceleration: optional native extension (~${SQLITE_VEC_APPROX_SIZE_MB} MB when installed separately)`,
38
26
  ];
39
27
  }
40
28
  export async function prepareSemanticSearchAssets(config) {
@@ -69,34 +57,5 @@ export async function prepareSemanticSearchAssets(config) {
69
57
  }
70
58
  }
71
59
  spin.stop(remote ? "Remote embedding endpoint is ready." : "Local embedding model downloaded and ready.");
72
- let db;
73
- let probeDir;
74
- try {
75
- probeDir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-setup-vec-probe-"));
76
- db = openIndexDatabase(path.join(probeDir, "probe.db"), config.embedding?.dimension ? { embeddingDim: config.embedding.dimension } : undefined);
77
- if (isVecAvailable(db)) {
78
- p.log.info("sqlite-vec is available for fast vector search.");
79
- }
80
- else {
81
- p.log.info("sqlite-vec is not available. Semantic search will use the JS fallback until the optional extension is installed.");
82
- }
83
- }
84
- catch (error) {
85
- const message = error instanceof Error ? error.message : String(error);
86
- p.log.warn(`Could not open the local database or check for sqlite-vec. Semantic search will use the JS fallback. (${message})\n` +
87
- "Check file permissions and available disk space in the cache directory, or run `akm index --full --verbose` to diagnose.");
88
- }
89
- finally {
90
- if (db)
91
- closeDatabase(db);
92
- if (probeDir) {
93
- try {
94
- fs.rmSync(probeDir, { recursive: true, force: true });
95
- }
96
- catch {
97
- /* ignore cleanup failure */
98
- }
99
- }
100
- }
101
60
  return { ok: true };
102
61
  }
@@ -117,7 +117,7 @@ export function assertSetupConfigPreflight() {
117
117
  catch (error) {
118
118
  if (!(error instanceof ConfigError))
119
119
  throw error;
120
- if (error.code !== "UNSUPPORTED_CONFIG_VERSION" && error.code !== "INVALID_CONFIG_FILE")
120
+ if (error.code !== "INVALID_CONFIG_FILE")
121
121
  throw error;
122
122
  throw new ConfigError(`\`akm setup\` cannot run: the config at ${configPath} did not load (${error.message}). ` +
123
123
  "It was left untouched — setup never writes over a config it cannot first read cleanly.", error.code, "Rewrite the file using the current config schema, or move it aside to start fresh " +
@@ -122,7 +122,8 @@ const LLM_PRESETS = [
122
122
  },
123
123
  ];
124
124
  /**
125
- * Step 3a: pick an LLM provider. Used for indexing-time metadata enhancement.
125
+ * Step 3a: pick an LLM provider. Used for LLM-gated background features
126
+ * (e.g. memory inference).
126
127
  *
127
128
  * @internal Exported for testing only.
128
129
  */
@@ -151,14 +152,14 @@ export async function stepLlm(current, ollamaEndpoint, ollamaChatModels, lmStudi
151
152
  }
152
153
  options.push({ value: "lmstudio", label: "LM Studio / local server", hint: lmStudioOptionHint(lmStudio) });
153
154
  options.push({ value: "custom", label: "Custom OpenAI-compatible endpoint" });
154
- options.push({ value: "none", label: "Skip LLM", hint: "no metadata enhancement during indexing" });
155
+ options.push({ value: "none", label: "Skip LLM", hint: "LLM-gated background features stay disabled" });
155
156
  const currentLlm = readCurrentLlmEngine(current);
156
157
  if (currentLlm) {
157
158
  options.push(keepCurrentOption(currentLlm));
158
159
  }
159
160
  const initialValue = currentLlm ? "keep" : ollamaAvailable ? "ollama" : (LLM_PRESETS[0]?.value ?? "none");
160
161
  const choice = await prompt(() => p.select({
161
- message: "Configure an LLM for richer metadata during indexing:",
162
+ message: "Configure an LLM for background features:",
162
163
  options,
163
164
  initialValue,
164
165
  }));
@@ -251,7 +252,7 @@ export async function stepLlm(current, ollamaEndpoint, ollamaChatModels, lmStudi
251
252
  return llm;
252
253
  }
253
254
  /**
254
- * Step 1/2: Configure the small model connection used for metadata and bounded LLM features.
255
+ * Step 1/2: Configure the small model connection used for bounded LLM features.
255
256
  *
256
257
  * Detects Ollama automatically and pre-selects it. The user may also choose
257
258
  * OpenAI, LM Studio, a custom endpoint, or skip the step entirely.
@@ -260,7 +261,6 @@ export async function stepSmallModelConnection(current) {
260
261
  p.log.step("Step 1/2: Configure your small model connection");
261
262
  p.note([
262
263
  "This connection is used for background processing:",
263
- " • akm index (metadata enhancement)",
264
264
  " • akm improve (lesson distillation)",
265
265
  " • akm remember --enrich (memory compression)",
266
266
  ].join("\n"));
@@ -301,7 +301,6 @@ export async function stepSmallModelConnection(current) {
301
301
  if (providerChoice === "skip") {
302
302
  p.note([
303
303
  "Enrichment features disabled:",
304
- " • akm index — metadata enhancement disabled",
305
304
  " • akm improve — lesson generation",
306
305
  " • akm remember --enrich",
307
306
  "",
@@ -53,10 +53,10 @@ export function printCapabilitySummary(smallModelSkipped, agentConfigured) {
53
53
  const lines = ["Setup complete. Here's what's enabled:", ""];
54
54
  lines.push(" ✓ akm search, akm curate, akm show, akm index, akm remember — always available");
55
55
  if (!smallModelSkipped) {
56
- lines.push(" ✓ index metadata enhancement, akm improve, akm remember --enrich — small model configured");
56
+ lines.push(" ✓ akm improve, akm remember --enrich — small model configured");
57
57
  }
58
58
  else {
59
- lines.push(" ✗ index metadata enhancement, akm improve, akm remember --enrich — run `akm setup` to enable");
59
+ lines.push(" ✗ akm improve, akm remember --enrich — run `akm setup` to enable");
60
60
  }
61
61
  if (agentConfigured) {
62
62
  lines.push(" ✓ akm proposal new, akm improve, akm task — agent configured");
@@ -9,11 +9,11 @@ import { parse as yamlParse, stringify as yamlStringify } from "yaml";
9
9
  import * as p from "../../cli/clack.js";
10
10
  import { akmTasksSync } from "../../commands/tasks/tasks.js";
11
11
  import { makeBundleRef } from "../../core/asset/asset-ref.js";
12
- import { loadConfig, mutateConfig } from "../../core/config/config.js";
12
+ import { loadConfig, mutateConfig, resetConfigCache } from "../../core/config/config.js";
13
13
  import { UsageError } from "../../core/errors.js";
14
14
  import { commitWriteTargetBoundary, deleteAssetFromSource, prepareWriteTargetForMutation, resolveWriteTarget, writeAssetToSource, } from "../../core/write-source.js";
15
- import { schedulerActivationSourceId, schedulerActivations } from "../../tasks/activation-config.js";
16
- import { backendNameForPlatform } from "../../tasks/backends/index.js";
15
+ import { enabledRefsFromInstalled, isSchedulerBundleActive, schedulerEnabledRefs } from "../../tasks/activation-config.js";
16
+ import { backendNameForPlatform, selectBackend } from "../../tasks/backends/index.js";
17
17
  import { listEmbeddedTasks } from "../../tasks/embedded.js";
18
18
  import { parseSchedule } from "../../tasks/schedule.js";
19
19
  import { parseTaskSource } from "../../tasks/source/parse-task-source.js";
@@ -77,9 +77,7 @@ export function listSetupTaskDefinitions() {
77
77
  const config = loadConfig();
78
78
  const target = resolveWriteTarget(config, config.defaultBundle, { requireWritable: false });
79
79
  const taskDir = path.join(target.source.path, "tasks");
80
- const enabledRefs = new Set(schedulerActivations(config)
81
- .filter((activation) => activation.kind === "task")
82
- .map((activation) => activation.ref));
80
+ const enabledRefs = new Set(schedulerEnabledRefs(config) ?? []);
83
81
  if (!fs.existsSync(taskDir))
84
82
  return [];
85
83
  const tasks = [];
@@ -178,17 +176,14 @@ export async function prepareSetupTaskDefinitions(tasks, deps = {}) {
178
176
  const selected = new Set(tasks.filter((plan) => plan.enabled).map((plan) => makeBundleRef(target.source.name, `tasks/${plan.task.id}`)));
179
177
  const managed = new Set(tasks.map((plan) => makeBundleRef(target.source.name, `tasks/${plan.task.id}`)));
180
178
  mutateConfig((current) => {
181
- const existing = schedulerActivations(current);
182
- const next = existing.filter((activation) => activation.kind !== "task" || !managed.has(activation.ref));
183
- const sourceId = schedulerActivationSourceId(current, target.source.name);
184
- if (selected.size > 0 && !sourceId) {
179
+ const existing = schedulerEnabledRefs(current) ?? [];
180
+ const next = existing.filter((ref) => !managed.has(ref));
181
+ if (selected.size > 0 && !isSchedulerBundleActive(current, target.source.name)) {
185
182
  throw new UsageError(`Cannot activate setup tasks from disabled bundle ${JSON.stringify(target.source.name)}.`);
186
183
  }
187
- for (const ref of selected) {
188
- next.push({ kind: "task", ref, sourceId: sourceId });
189
- }
190
- next.sort((left, right) => left.ref.localeCompare(right.ref) || left.kind.localeCompare(right.kind));
191
- if (JSON.stringify(existing) === JSON.stringify(next))
184
+ next.push(...selected);
185
+ next.sort((left, right) => left.localeCompare(right));
186
+ if (current.scheduler?.enabled !== undefined && JSON.stringify([...existing]) === JSON.stringify(next))
192
187
  return current;
193
188
  return { ...current, scheduler: { ...current.scheduler, enabled: next } };
194
189
  });
@@ -198,6 +193,7 @@ const DEFAULT_SCHEDULED_TASKS_DEPS = {
198
193
  list: listSetupTaskDefinitions,
199
194
  prepare: prepareSetupTaskDefinitions,
200
195
  sync: akmTasksSync,
196
+ inspectInstalled: async () => ({ installed: await selectBackend().list() }),
201
197
  };
202
198
  export async function stepScheduledTasks(deps = DEFAULT_SCHEDULED_TASKS_DEPS, options = {}) {
203
199
  if (options.nonInteractive || isCiEnvironment()) {
@@ -212,6 +208,20 @@ export async function stepScheduledTasks(deps = DEFAULT_SCHEDULED_TASKS_DEPS, op
212
208
  const embedded = listEmbeddedTasks();
213
209
  if (embedded.length === 0)
214
210
  return;
211
+ // A config that predates `scheduler.enabled` means "keep what is installed":
212
+ // make that explicit before the review below reads and edits the list.
213
+ if (schedulerEnabledRefs(loadConfig()) === undefined) {
214
+ try {
215
+ const inspection = await deps.inspectInstalled();
216
+ const refs = enabledRefsFromInstalled(inspection.installed, loadConfig());
217
+ mutateConfig((current) => ({ ...current, scheduler: { ...current.scheduler, enabled: [...refs] } }));
218
+ resetConfigCache();
219
+ }
220
+ catch (cause) {
221
+ const message = cause instanceof Error ? cause.message : String(cause);
222
+ p.log.warn(`Native scheduler bindings could not be inspected: ${message}`);
223
+ }
224
+ }
215
225
  const installed = await deps.list();
216
226
  const byId = new Map();
217
227
  for (const task of installed)
@@ -1,23 +1,22 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * Source provider factory map.
6
- *
7
- * Maps source kind identifiers (e.g. "filesystem", "git", "website", "npm")
8
- * to factory functions that build {@link SourceProvider} instances from a
9
- * {@link SourceConfigEntry}.
10
- *
11
- * Distinct from the registry-discovery factory (`registry/factory.ts`).
12
- * Both share `create-provider-registry.ts` for the underlying string→factory
13
- * map.
14
- */
15
- import { createProviderRegistry } from "../registry/create-provider-registry.js";
16
- // ── Factory map ─────────────────────────────────────────────────────────────
17
- const registry = createProviderRegistry();
18
- export function registerSourceProvider(type, factory) {
19
- registry.register(type, factory);
20
- }
4
+ import { createFilesystemProvider } from "./providers/filesystem.js";
5
+ import { GitSourceProvider } from "./providers/git-provider.js";
6
+ import { NpmSourceProvider } from "./providers/npm.js";
7
+ import { createWebsiteProvider } from "./providers/website.js";
8
+ /** The factory for a configured source kind, or null for a kind akm does not support. */
21
9
  export function resolveSourceProviderFactory(type) {
22
- return registry.resolve(type);
10
+ switch (type) {
11
+ case "filesystem":
12
+ return createFilesystemProvider;
13
+ case "git":
14
+ return (config) => new GitSourceProvider(config);
15
+ case "npm":
16
+ return (config) => new NpmSourceProvider(config);
17
+ case "website":
18
+ return createWebsiteProvider;
19
+ default:
20
+ return null;
21
+ }
23
22
  }
@@ -3,14 +3,13 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { resolveStashDir } from "../../core/common.js";
5
5
  import { ConfigError } from "../../core/errors.js";
6
- import { registerSourceProvider } from "../provider-factory.js";
7
6
  /**
8
7
  * Filesystem source — points at a directory the user already manages.
9
8
  *
10
9
  * Implements {@link SourceProvider} with `{ name, kind, path }`. No `sync()`:
11
10
  * content is the user's own directory, never refreshed by akm.
12
11
  */
13
- registerSourceProvider("filesystem", (entry) => {
12
+ export function createFilesystemProvider(entry) {
14
13
  if (entry.type !== "filesystem") {
15
14
  throw new ConfigError(`filesystem source invoked with type="${entry.type}"`);
16
15
  }
@@ -26,4 +25,4 @@ registerSourceProvider("filesystem", (entry) => {
26
25
  return stashDir;
27
26
  },
28
27
  };
29
- });
28
+ }
@@ -114,8 +114,14 @@ function normalizeRemoteUrl(value) {
114
114
  .replace(/\/+$/, "")
115
115
  .replace(/\.git$/i, "");
116
116
  }
117
- function replaceDirectory(stagedDir, destination) {
117
+ /**
118
+ * Move a fully materialized directory into place. POSIX cannot rename over a
119
+ * non-empty directory, so the old one is renamed aside first and restored if
120
+ * the second rename fails; the destination is missing for one syscall at most.
121
+ */
122
+ export function replaceDirectory(stagedDir, destination) {
118
123
  const backup = `${destination}.backup-${randomBytes(4).toString("hex")}`;
124
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
119
125
  const hadDestination = fs.existsSync(destination);
120
126
  if (hadDestination)
121
127
  fs.renameSync(destination, backup);
@@ -11,7 +11,6 @@ import { ConfigError, UsageError } from "../../core/errors.js";
11
11
  import { getRegistryIndexCacheDir } from "../../core/paths.js";
12
12
  import { validateGitUrl } from "../../registry/resolve.js";
13
13
  import { withFreshnessCache } from "../freshness.js";
14
- import { registerSourceProvider } from "../provider-factory.js";
15
14
  import { assertNoIgnoredPathOverwrite, cloneRepo, inspectGitUpstream, runGit } from "./git-install.js";
16
15
  import { sanitizeString } from "./provider-utils.js";
17
16
  /** Cache TTL before refreshing the mirrored repo (12 hours). */
@@ -60,8 +59,6 @@ function resolveGitContentDir(config) {
60
59
  }
61
60
  throw new ConfigError("git source entry must have either `path` or `url`");
62
61
  }
63
- // ── Self-register ───────────────────────────────────────────────────────────
64
- registerSourceProvider("git", (config) => new GitSourceProvider(config));
65
62
  // ── Cache management ────────────────────────────────────────────────────────
66
63
  export function getCachePaths(repoUrl, cacheRootOverride) {
67
64
  const key = createHash("sha256").update(repoUrl).digest("hex").slice(0, 16);
@@ -25,11 +25,18 @@ import { getCachePaths, parseGitRepoUrl } from "./git-provider.js";
25
25
  export function isGitBackedStash(stashDir) {
26
26
  return fs.existsSync(path.join(stashDir, ".git"));
27
27
  }
28
- /** Return repo-relative dirty/staged paths without changing the index. */
29
- export function listGitChangedPaths(repoDir) {
28
+ /**
29
+ * Return repo-relative dirty/staged paths without changing the index, and
30
+ * whether `git status` itself succeeded. A broken submodule, a detached
31
+ * `GIT_DIR`, or git simply not being on `PATH` all exit nonzero here — a
32
+ * caller that would otherwise read the empty `paths` as "nothing is dirty"
33
+ * must check `ok` first (see {@link listGitChangedPaths}'s callers that
34
+ * cannot, and the archive purge sweep, which can and does).
35
+ */
36
+ export function tryListGitChangedPaths(repoDir) {
30
37
  const result = runGit(["-C", repoDir, "status", "--porcelain", "-z", "--untracked-files=all"]);
31
38
  if (result.status !== 0)
32
- return [];
39
+ return { paths: [], ok: false };
33
40
  const records = result.stdout.split("\0");
34
41
  const paths = [];
35
42
  for (let i = 0; i < records.length; i++) {
@@ -44,7 +51,79 @@ export function listGitChangedPaths(repoDir) {
44
51
  paths.push(previousPath);
45
52
  }
46
53
  }
47
- return paths;
54
+ return { paths, ok: true };
55
+ }
56
+ /** Return repo-relative dirty/staged paths without changing the index. `[]` on any git failure — see {@link tryListGitChangedPaths} for a caller that must tell that apart from "nothing is dirty". */
57
+ export function listGitChangedPaths(repoDir) {
58
+ return tryListGitChangedPaths(repoDir).paths;
59
+ }
60
+ /**
61
+ * Return repo-relative paths git tracks at HEAD/index under `pathspec` (or
62
+ * the whole repo when omitted), and whether `git ls-files` itself
63
+ * succeeded — see {@link tryListGitChangedPaths}, the same contract.
64
+ */
65
+ export function tryListGitTrackedPaths(repoDir, pathspec) {
66
+ const args = ["-C", repoDir, "ls-files", "-z"];
67
+ if (pathspec)
68
+ args.push("--", pathspec);
69
+ const result = runGit(args);
70
+ if (result.status !== 0)
71
+ return { paths: [], ok: false };
72
+ return { paths: result.stdout.split("\0").filter((record) => record.length > 0), ok: true };
73
+ }
74
+ /**
75
+ * Return repo-relative paths under `pathspec` that `git ls-files -v` tags as
76
+ * NOT verifiable against the worktree: `assume-unchanged` (a lowercase tag —
77
+ * `ls-files -v` lowercases a file's normal tag letter when that bit is set)
78
+ * or `skip-worktree` (the literal `S`). `git status` silently omits an edit
79
+ * to either kind of file — the index is telling git not to compare it — so a
80
+ * caller that trusts {@link tryListGitChangedPaths} alone would read a
81
+ * genuinely modified file as clean.
82
+ */
83
+ export function tryListGitUnverifiablePaths(repoDir, pathspec) {
84
+ const args = ["-C", repoDir, "ls-files", "-v", "-z"];
85
+ if (pathspec)
86
+ args.push("--", pathspec);
87
+ const result = runGit(args);
88
+ if (result.status !== 0)
89
+ return { paths: [], ok: false };
90
+ const paths = [];
91
+ for (const record of result.stdout.split("\0")) {
92
+ if (!record)
93
+ continue;
94
+ const tag = record.slice(0, 1);
95
+ if (tag === "S" || (tag >= "a" && tag <= "z"))
96
+ paths.push(record.slice(2));
97
+ }
98
+ return { paths, ok: true };
99
+ }
100
+ /**
101
+ * The three-part git cleanliness check shared by the archive purge sweep
102
+ * (`purgeGracedArchive` in `commands/improve/memory/memory-improve.ts`) and
103
+ * the `memory-cleanup-archive` health advisory (`collectArchiveUsageAdvisory`
104
+ * in `commands/health/archive-usage.ts`): a path is safe to treat as
105
+ * committed only if it is tracked ({@link tryListGitTrackedPaths}), not dirty
106
+ * ({@link tryListGitChangedPaths}), and not assume-unchanged/skip-worktree
107
+ * ({@link tryListGitUnverifiablePaths} — those hide their own edits from
108
+ * `git status`, so an unverifiable file is never trusted as clean either).
109
+ *
110
+ * Each of the three git calls can fail independently (a broken submodule, or
111
+ * git missing from `PATH`); `ok` is `false` if any one does, and `isSafe`
112
+ * then returns `false` for every path rather than guessing — callers that
113
+ * need to short-circuit before doing other work still check `ok` themselves.
114
+ */
115
+ export function checkGitPathSafety(repoDir, pathspec) {
116
+ const dirtyQuery = tryListGitChangedPaths(repoDir);
117
+ const trackedQuery = tryListGitTrackedPaths(repoDir, pathspec);
118
+ const unverifiableQuery = tryListGitUnverifiablePaths(repoDir, pathspec);
119
+ const ok = dirtyQuery.ok && trackedQuery.ok && unverifiableQuery.ok;
120
+ const dirty = new Set(dirtyQuery.paths);
121
+ const tracked = new Set(trackedQuery.paths);
122
+ const unverifiable = new Set(unverifiableQuery.paths);
123
+ return {
124
+ ok,
125
+ isSafe: (repoRelativePath) => ok && tracked.has(repoRelativePath) && !dirty.has(repoRelativePath) && !unverifiable.has(repoRelativePath),
126
+ };
48
127
  }
49
128
  export class GitStashPushError extends Error {
50
129
  commit;
@@ -204,9 +283,6 @@ export function saveGitStash(name, message, writableOverride, options) {
204
283
  }
205
284
  assertNoIgnoredExactPaths(repoDir, requestedPaths);
206
285
  const baseHead = readOptionalHead(repoDir);
207
- if (options?.expectedBaseHead !== undefined && (baseHead ?? null) !== options.expectedBaseHead) {
208
- throw new Error(`Git target advanced before its exact-path commit could be created.`);
209
- }
210
286
  const remoteResult = runGit(["-C", repoDir, "remote"]);
211
287
  if (remoteResult.status !== 0) {
212
288
  throw new Error(`git remote failed: ${remoteResult.stderr?.trim() || "unknown error"}`);
@@ -300,20 +376,6 @@ export function assertNoIgnoredExactPaths(repoDir, paths) {
300
376
  throw new UsageError(`Exact Git publication path is ignored: ${ignored[0]}. Update .gitignore or choose a tracked destination before writing.`);
301
377
  }
302
378
  }
303
- /** Reject exact staged/unstaged paths before an AKM filesystem mutation. */
304
- export function assertGitExactPathsClean(repoDir, paths) {
305
- const normalized = normalizeExactPaths(repoDir, paths);
306
- assertNoIgnoredExactPaths(repoDir, normalized);
307
- for (const result of runExactPathChunks(repoDir, ["status", "--porcelain=v1", "-z", "--untracked-files=all"], normalized)) {
308
- if (result.status !== 0) {
309
- throw new Error(`git status failed: ${result.stderr.trim() || "unknown error"}`);
310
- }
311
- if (result.stdout.length > 0) {
312
- const record = result.stdout.split("\0").find(Boolean) ?? "";
313
- throw new UsageError(`Exact Git operation path has staged or unstaged work: ${record.slice(3)}. Commit, stash, or discard that path before retrying.`);
314
- }
315
- }
316
- }
317
379
  function readOptionalHead(repoDir) {
318
380
  const result = runGit(["-C", repoDir, "rev-parse", "--verify", "HEAD"]);
319
381
  return result.status === 0 && result.stdout.trim() ? result.stdout.trim() : undefined;
@@ -13,8 +13,7 @@ import fs from "node:fs";
13
13
  import path from "node:path";
14
14
  import { ConfigError, UsageError } from "../../core/errors.js";
15
15
  import { getRegistryCacheDir } from "../../core/paths.js";
16
- import { npmArtifactNetworkPolicy, parseRegistryRef, resolveRegistryArtifact } from "../../registry/resolve.js";
17
- import { registerSourceProvider } from "../provider-factory.js";
16
+ import { parseRegistryRef, resolveRegistryArtifact } from "../../registry/resolve.js";
18
17
  import { applyAkmIncludeConfig, buildInstallCacheDir, computeFileHash, detectStashRoot, downloadArchive, isDirectory, } from "./provider-utils.js";
19
18
  import { extractTarGzSecure, verifyArchiveIntegrity } from "./tar-utils.js";
20
19
  /**
@@ -45,7 +44,6 @@ class NpmSourceProvider {
45
44
  await syncNpmRef(ref, { force: options?.force });
46
45
  }
47
46
  }
48
- registerSourceProvider("npm", (config) => new NpmSourceProvider(config));
49
47
  function npmRefFromConfig(config) {
50
48
  const candidate = config.path;
51
49
  if (typeof candidate !== "string" || !candidate) {
@@ -108,7 +106,7 @@ async function doSyncNpm(parsed, options) {
108
106
  let installRoot;
109
107
  let stashRoot;
110
108
  try {
111
- await downloadArchive(resolved.artifactUrl, archivePath, npmArtifactNetworkPolicy(resolved));
109
+ await downloadArchive(resolved.artifactUrl, archivePath);
112
110
  verifyArchiveIntegrity(archivePath, resolved.resolvedRevision, resolved.source);
113
111
  integrity = await computeFileHash(archivePath);
114
112
  extractTarGzSecure(archivePath, extractedDir);
@@ -6,7 +6,7 @@ import fs from "node:fs";
6
6
  import path from "node:path";
7
7
  import { getAdapters } from "../../core/adapter/registry.js";
8
8
  import { stashDirNames } from "../../core/asset/asset-placement.js";
9
- import { cancelRegistryResponse, fetchRegistryResponse } from "../../registry/network.js";
9
+ import { fetchRegistry } from "../../registry/network.js";
10
10
  import { writeResponseToFileCapped } from "../../runtime.js";
11
11
  import { copyIncludedPaths, findNearestIncludeConfig } from "../include.js";
12
12
  const REGISTRY_STASH_DIR_NAMES = new Set(stashDirNames());
@@ -99,15 +99,10 @@ export function applyAkmIncludeConfig(sourceRoot, cacheDir, searchRoot = sourceR
99
99
  return selectedDir;
100
100
  }
101
101
  /** Stream a remote archive to disk via the runtime boundary's response writer. */
102
- export async function downloadArchive(url, destination, networkPolicy) {
103
- const response = await fetchRegistryResponse(url, undefined, { policy: networkPolicy, timeoutMs: 120_000 });
104
- if (!response.ok) {
105
- await cancelRegistryResponse(response);
106
- throw new Error(`Failed to download archive (${response.status}) from ${url}`);
107
- }
108
- // Stream to disk with an explicit byte cap + body-read deadline: the fetch
109
- // timeout above bounds only the connection/header phase, so an unbounded or
110
- // dribbling body could otherwise fill the disk or hang the install forever.
102
+ export async function downloadArchive(url, destination) {
103
+ const response = await fetchRegistry(url, { timeoutMs: 120_000 });
104
+ // Stream to disk with an explicit byte cap + body-read deadline so an
105
+ // unbounded or dribbling body cannot fill the disk or hang the install.
111
106
  await writeResponseToFileCapped(destination, response);
112
107
  }
113
108
  /** SHA-256 of a file, returned as `sha256:<hex>`. */
@@ -2,7 +2,6 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { ConfigError } from "../../core/errors.js";
5
- import { registerSourceProvider } from "../provider-factory.js";
6
5
  import { getWebsiteCachePaths, shouldAllowPrivateWebsiteUrlForTests, validateWebsiteUrl } from "../website-url.js";
7
6
  /** Website source provider — URL-derived path plus an injected mirror refresh. */
8
7
  export function createWebsiteProvider(config) {
@@ -33,4 +32,3 @@ export function createWebsiteProvider(config) {
33
32
  },
34
33
  };
35
34
  }
36
- registerSourceProvider("website", createWebsiteProvider);
@@ -76,7 +76,7 @@ function resolveFetcherStashDir(explicitStashDir) {
76
76
  export async function ensureWebsiteMirror(config, options) {
77
77
  const rawUrl = config.url ?? "";
78
78
  const normalizedUrl = validateWebsiteUrl(rawUrl, { allowPrivateHosts: options?.allowPrivateHosts });
79
- const cachePaths = getWebsiteCachePaths(normalizedUrl, options?.cacheRootDir);
79
+ const cachePaths = getWebsiteCachePaths(normalizedUrl);
80
80
  const requireStashDir = options?.requireStashDir === true;
81
81
  await withFreshnessCache({
82
82
  markerPath: cachePaths.manifestPath,
@@ -35,9 +35,9 @@ export function shouldAllowPrivateWebsiteUrlForTests(rawUrl) {
35
35
  }
36
36
  return true;
37
37
  }
38
- export function getWebsiteCachePaths(siteUrl, cacheRootOverride) {
38
+ export function getWebsiteCachePaths(siteUrl) {
39
39
  const key = createHash("sha256").update(normalizeSiteUrl(siteUrl)).digest("hex").slice(0, 16);
40
- const rootDir = path.join(cacheRootOverride ?? getRegistryIndexCacheDir(), `website-${key}`);
40
+ const rootDir = path.join(getRegistryIndexCacheDir(), `website-${key}`);
41
41
  return {
42
42
  rootDir,
43
43
  stashDir: path.join(rootDir, "stash"),