akm-cli 0.9.1 → 0.9.2-alpha.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 (341) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +3 -1
  3. package/SECURITY.md +1 -1
  4. package/STABILITY.md +1 -1
  5. package/dist/akm +2 -2
  6. package/dist/akm-migrate +2 -2
  7. package/dist/assets/hints/cli-hints-full.md +14 -9
  8. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
  9. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  10. package/dist/assets/models.json +35 -0
  11. package/dist/assets/tasks/core/extract.yml +6 -5
  12. package/dist/assets/tasks/core/improve.yml +6 -5
  13. package/dist/assets/tasks/core/index-refresh.yml +6 -5
  14. package/dist/assets/tasks/core/sync.yml +6 -5
  15. package/dist/assets/tasks/core/version-check.yml +6 -5
  16. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
  17. package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
  18. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
  19. package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
  20. package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
  21. package/dist/cli/confirm.js +2 -2
  22. package/dist/cli/parse-args.js +3 -24
  23. package/dist/cli/retired-commands.js +1 -1
  24. package/dist/cli/shared.js +2 -2
  25. package/dist/cli.js +11 -9
  26. package/dist/commands/agent/agent-dispatch.js +55 -89
  27. package/dist/commands/agent/contribute-cli.js +12 -45
  28. package/dist/commands/command/builtin-action.js +32 -0
  29. package/dist/commands/command/command-cli.js +99 -0
  30. package/dist/commands/command/command-execution.js +308 -0
  31. package/dist/commands/command/execution-source-loader.js +176 -0
  32. package/dist/commands/command/portable-template.js +60 -0
  33. package/dist/commands/config-cli.js +10 -4
  34. package/dist/commands/env/env.js +4 -2
  35. package/dist/commands/feedback-cli.js +1 -1
  36. package/dist/commands/health/checks.js +241 -29
  37. package/dist/commands/health/html-report.js +0 -14
  38. package/dist/commands/health/report-view-model.js +0 -1
  39. package/dist/commands/health/surfaces.js +6 -7
  40. package/dist/commands/health/types.js +0 -2
  41. package/dist/commands/health.js +63 -18
  42. package/dist/commands/improve/collapse-detector.js +2 -2
  43. package/dist/commands/improve/consolidate.js +251 -214
  44. package/dist/commands/improve/distill/promote-memory.js +71 -34
  45. package/dist/commands/improve/distill/quality-gate.js +17 -5
  46. package/dist/commands/improve/distill.js +232 -155
  47. package/dist/commands/improve/eligibility.js +112 -79
  48. package/dist/commands/improve/execution.js +57 -0
  49. package/dist/commands/improve/extract-cli.js +5 -5
  50. package/dist/commands/improve/extract.js +521 -342
  51. package/dist/commands/improve/improve-strategies.js +43 -14
  52. package/dist/commands/improve/improve.js +249 -29
  53. package/dist/commands/improve/loop-stages.js +11 -17
  54. package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
  55. package/dist/commands/improve/outcome-loop.js +22 -38
  56. package/dist/commands/improve/planner.js +134 -0
  57. package/dist/commands/improve/preparation.js +730 -409
  58. package/dist/commands/improve/reflect.js +386 -223
  59. package/dist/commands/improve/run-context.js +3 -4
  60. package/dist/commands/improve/salience.js +6 -58
  61. package/dist/commands/improve/session-asset.js +12 -12
  62. package/dist/commands/lint/index.js +101 -29
  63. package/dist/commands/migrate-cli.js +11 -69
  64. package/dist/commands/migration-tool.js +6 -9
  65. package/dist/commands/models-cli.js +27 -0
  66. package/dist/commands/proposal/drain.js +258 -186
  67. package/dist/commands/proposal/proposal-cli.js +32 -10
  68. package/dist/commands/proposal/proposal.js +2 -5
  69. package/dist/commands/proposal/propose.js +192 -172
  70. package/dist/commands/proposal/repository.js +54 -91
  71. package/dist/commands/proposal/validators/proposal-validators.js +9 -7
  72. package/dist/commands/read/curate.js +10 -0
  73. package/dist/commands/read/registry-search.js +25 -9
  74. package/dist/commands/read/remember-cli.js +14 -2
  75. package/dist/commands/read/search.js +10 -4
  76. package/dist/commands/read/show.js +139 -153
  77. package/dist/commands/registry-cli.js +16 -7
  78. package/dist/commands/remember.js +33 -18
  79. package/dist/commands/sources/add-cli.js +19 -178
  80. package/dist/commands/sources/bundle-cli.js +15 -3
  81. package/dist/commands/sources/dangerous-env-audit.js +135 -0
  82. package/dist/commands/sources/info.js +2 -1
  83. package/dist/commands/sources/installed-stashes.js +835 -152
  84. package/dist/commands/sources/schema-repair.js +174 -95
  85. package/dist/commands/sources/self-update.js +30 -74
  86. package/dist/commands/sources/source-add.js +3 -5
  87. package/dist/commands/sources/sources-cli.js +2 -15
  88. package/dist/commands/sources/update-transaction.js +220 -0
  89. package/dist/commands/tasks/tasks-cli.js +3 -3
  90. package/dist/commands/tasks/tasks.js +736 -317
  91. package/dist/commands/workflow-cli.js +2 -2
  92. package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
  93. package/dist/core/adapter/adapters/akm-adapter.js +83 -34
  94. package/dist/core/adapter/adapters/akm-lint.js +54 -39
  95. package/dist/core/adapter/adapters/akm-metadata.js +45 -45
  96. package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
  97. package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
  98. package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
  99. package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
  100. package/dist/core/adapter/adapters/index.js +0 -9
  101. package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
  102. package/dist/core/adapter/adapters/okf-adapter.js +4 -0
  103. package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
  104. package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
  105. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
  106. package/dist/core/adapter/execution-source.js +308 -0
  107. package/dist/core/adapter/recognize-match.js +36 -13
  108. package/dist/core/adapter/registry.js +0 -9
  109. package/dist/core/asset/stash-meta.js +94 -4
  110. package/dist/core/common.js +6 -11
  111. package/dist/core/config/config-io.js +3 -3
  112. package/dist/core/config/config-schema.js +18 -40
  113. package/dist/core/config/config-sources.js +11 -21
  114. package/dist/core/config/config-walker.js +31 -13
  115. package/dist/core/config/config.js +21 -20
  116. package/dist/core/config/schema/engines.js +8 -7
  117. package/dist/core/config/schema/improve-processes.js +29 -5
  118. package/dist/core/config/schema/primitives.js +1 -23
  119. package/dist/core/config/schema/sources-bundles.js +13 -16
  120. package/dist/core/errors.js +2 -0
  121. package/dist/core/events.js +68 -32
  122. package/dist/core/extra-params.js +1 -0
  123. package/dist/core/improve-result.js +315 -0
  124. package/dist/core/lesson-lint.js +0 -6
  125. package/dist/core/maintenance-barrier.js +4 -4
  126. package/dist/core/network-policy.js +152 -0
  127. package/dist/core/paths.js +1 -1
  128. package/dist/core/recognition-util.js +4 -4
  129. package/dist/core/registry-url.js +456 -0
  130. package/dist/core/state/migrations.js +161 -47
  131. package/dist/core/state-db.js +453 -80
  132. package/dist/core/system-error.js +32 -0
  133. package/dist/core/time.js +2 -12
  134. package/dist/core/write-source.js +0 -18
  135. package/dist/execution/directory-identity.js +52 -0
  136. package/dist/execution/executable-identity.js +107 -0
  137. package/dist/execution/guarded-source.js +398 -0
  138. package/dist/execution/json.js +95 -0
  139. package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
  140. package/dist/execution/record.js +55 -0
  141. package/dist/execution/resolved-request.js +730 -0
  142. package/dist/execution/source.js +320 -0
  143. package/dist/indexer/bundle-identity-guard.js +5 -4
  144. package/dist/indexer/db/graph-db.js +33 -0
  145. package/dist/indexer/graph/graph-boost.js +3 -4
  146. package/dist/indexer/graph/graph-extraction.js +562 -373
  147. package/dist/indexer/index-written-assets.js +65 -34
  148. package/dist/indexer/indexer.js +443 -222
  149. package/dist/indexer/installations.js +6 -0
  150. package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
  151. package/dist/indexer/passes/memory-inference.js +227 -174
  152. package/dist/indexer/scan/doc-to-entry.js +7 -9
  153. package/dist/indexer/scan/drain-dir.js +51 -23
  154. package/dist/indexer/search/db-search.js +98 -22
  155. package/dist/indexer/search/search-fields.js +1 -1
  156. package/dist/indexer/search/search-hit-enrichers.js +1 -1
  157. package/dist/indexer/search/search-source.js +7 -16
  158. package/dist/indexer/search/semantic-status.js +10 -1
  159. package/dist/indexer/usage/show-usage.js +105 -0
  160. package/dist/indexer/usage/usage-events.js +7 -2
  161. package/dist/indexer/walk/matchers.js +40 -10
  162. package/dist/indexer/walk/path-resolver.js +5 -2
  163. package/dist/indexer/walk/walker.js +20 -2
  164. package/dist/integrations/agent/builder-shared.js +3 -6
  165. package/dist/integrations/agent/conversation-fallback.js +16 -0
  166. package/dist/integrations/agent/engine-resolution.js +87 -87
  167. package/dist/integrations/agent/execution-cascade.js +566 -0
  168. package/dist/integrations/agent/execution-definitions.js +211 -0
  169. package/dist/integrations/agent/execution-lowering.js +811 -0
  170. package/dist/integrations/agent/execution-preparation.js +67 -0
  171. package/dist/integrations/agent/index.js +0 -2
  172. package/dist/integrations/agent/inline-execution.js +74 -0
  173. package/dist/integrations/agent/model-map.js +515 -0
  174. package/dist/integrations/agent/persona-fallback.js +30 -0
  175. package/dist/integrations/agent/request-lowering.js +186 -0
  176. package/dist/integrations/agent/runner-dispatch.js +230 -37
  177. package/dist/integrations/agent/runner.js +12 -83
  178. package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
  179. package/dist/integrations/harnesses/aider/index.js +0 -1
  180. package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
  181. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  182. package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
  183. package/dist/integrations/harnesses/claude/index.js +1 -5
  184. package/dist/integrations/harnesses/claude/session-log.js +3 -33
  185. package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
  186. package/dist/integrations/harnesses/codex/index.js +0 -1
  187. package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
  188. package/dist/integrations/harnesses/copilot/index.js +0 -1
  189. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
  190. package/dist/integrations/harnesses/gemini/index.js +0 -1
  191. package/dist/integrations/harnesses/index.js +4 -44
  192. package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
  193. package/dist/integrations/harnesses/opencode/index.js +0 -2
  194. package/dist/integrations/harnesses/opencode/session-log.js +14 -204
  195. package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
  196. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
  197. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
  198. package/dist/integrations/harnesses/openhands/index.js +0 -1
  199. package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
  200. package/dist/integrations/harnesses/pi/index.js +0 -1
  201. package/dist/integrations/harnesses/shared.js +0 -1
  202. package/dist/integrations/harnesses/types.js +1 -3
  203. package/dist/integrations/lockfile.js +82 -79
  204. package/dist/integrations/session-logs/index.js +6 -17
  205. package/dist/integrations/session-logs/provider-base.js +1 -29
  206. package/dist/llm/client.js +10 -5
  207. package/dist/llm/embedder.js +6 -7
  208. package/dist/llm/embedders/local.js +37 -88
  209. package/dist/llm/embedders/types.js +1 -1
  210. package/dist/llm/graph-extract.js +75 -50
  211. package/dist/llm/index-passes.js +43 -5
  212. package/dist/llm/memory-infer.js +8 -6
  213. package/dist/llm/metadata-enhance.js +5 -3
  214. package/dist/llm/structured-call.js +122 -25
  215. package/dist/output/format-exempt.js +1 -1
  216. package/dist/output/render-registry.js +0 -16
  217. package/dist/output/renderers.js +12 -7
  218. package/dist/output/shapes/curate.js +1 -0
  219. package/dist/output/shapes/helpers.js +10 -2
  220. package/dist/output/shapes/passthrough.js +2 -0
  221. package/dist/output/text/command-format.js +28 -32
  222. package/dist/output/text/health-format.js +1 -29
  223. package/dist/output/text/migrate.js +6 -56
  224. package/dist/output/text/proposal-format.js +16 -1
  225. package/dist/output/text/workflow-format.js +16 -0
  226. package/dist/registry/network.js +279 -0
  227. package/dist/registry/pinned-request-helper.js +247 -0
  228. package/dist/registry/pinned-transport.js +717 -0
  229. package/dist/registry/providers/skills-sh.js +18 -6
  230. package/dist/registry/providers/static-index.js +20 -7
  231. package/dist/registry/resolve.js +53 -28
  232. package/dist/scripts/akm-migrate-node.js +19122 -52218
  233. package/dist/scripts/akm-migrate.js +19064 -51567
  234. package/dist/setup/registry-stash-loader.js +64 -20
  235. package/dist/setup/semantic-assets.js +9 -34
  236. package/dist/setup/setup.js +12 -30
  237. package/dist/setup/source-identity.js +17 -0
  238. package/dist/setup/steps/sources.js +36 -15
  239. package/dist/setup/steps/tasks.js +39 -11
  240. package/dist/sources/providers/git-provider.js +3 -3
  241. package/dist/sources/providers/npm.js +2 -2
  242. package/dist/sources/providers/provider-utils.js +4 -3
  243. package/dist/sources/providers/website.js +11 -7
  244. package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
  245. package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
  246. package/dist/sources/website-url.js +73 -0
  247. package/dist/storage/engines/sqlite-migrations.js +81 -26
  248. package/dist/storage/managed-db.js +27 -24
  249. package/dist/storage/repositories/events-repository.js +3 -0
  250. package/dist/storage/repositories/index-connection.js +42 -10
  251. package/dist/storage/repositories/index-entries-repository.js +167 -207
  252. package/dist/storage/repositories/index-entry-mapper.js +8 -12
  253. package/dist/storage/repositories/index-entry-schema.js +255 -0
  254. package/dist/storage/repositories/index-fts-repository.js +10 -10
  255. package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
  256. package/dist/storage/repositories/index-meta-repository.js +0 -11
  257. package/dist/storage/repositories/index-schema.js +71 -342
  258. package/dist/storage/repositories/index-utility-repository.js +12 -17
  259. package/dist/storage/repositories/index-vec-repository.js +1 -1
  260. package/dist/storage/repositories/proposals-repository.js +4 -127
  261. package/dist/storage/repositories/registry-cache.js +2 -1
  262. package/dist/storage/repositories/task-history-repository.js +20 -40
  263. package/dist/storage/repositories/workflow-runs-repository.js +228 -129
  264. package/dist/storage/sqlite-read-snapshot.js +148 -0
  265. package/dist/tasks/backends/cron.js +170 -42
  266. package/dist/tasks/backends/index.js +1 -1
  267. package/dist/tasks/backends/launchd.js +787 -202
  268. package/dist/tasks/backends/schtasks.js +282 -83
  269. package/dist/tasks/embedded.js +7 -7
  270. package/dist/tasks/frozen-script.js +50 -0
  271. package/dist/tasks/resolve-akm-bin.js +5 -1
  272. package/dist/tasks/runner.js +239 -251
  273. package/dist/tasks/runtime-v3.js +281 -0
  274. package/dist/tasks/scheduler-binding.js +272 -0
  275. package/dist/tasks/scheduler-invocation.js +57 -43
  276. package/dist/tasks/scheduler-sync.js +654 -0
  277. package/dist/tasks/source-v3.js +752 -0
  278. package/dist/tasks/standalone-script-entry.js +5 -0
  279. package/dist/tasks/task-id.js +29 -0
  280. package/dist/workflows/authoring/authoring.js +15 -32
  281. package/dist/workflows/exec/dispatch-redaction.js +14 -8
  282. package/dist/workflows/exec/exec-unit.js +7 -28
  283. package/dist/workflows/exec/frozen-judge.js +57 -89
  284. package/dist/workflows/exec/lowering-notices.js +23 -0
  285. package/dist/workflows/exec/native-executor.js +301 -458
  286. package/dist/workflows/exec/param-secrets.js +4 -3
  287. package/dist/workflows/exec/run-workflow.js +26 -32
  288. package/dist/workflows/exec/step-work.js +105 -109
  289. package/dist/workflows/exec/unit-dispatch.js +103 -27
  290. package/dist/workflows/exec/unit-writer.js +3 -3
  291. package/dist/workflows/exec/worktree.js +2 -2
  292. package/dist/workflows/ir/compile.js +86 -72
  293. package/dist/workflows/ir/environment-v4.js +328 -0
  294. package/dist/workflows/ir/freeze-v4.js +122 -0
  295. package/dist/workflows/ir/plan-hash.js +13 -7
  296. package/dist/workflows/ir/schema-v4.js +525 -0
  297. package/dist/workflows/ir/schema.js +25 -284
  298. package/dist/workflows/ir/source-freeze-v4.js +506 -0
  299. package/dist/workflows/parser.js +27 -24
  300. package/dist/workflows/program/schema.js +1 -2
  301. package/dist/workflows/renderer.js +42 -29
  302. package/dist/workflows/resource-limits.js +4 -5
  303. package/dist/workflows/runtime/agent-identity.js +11 -13
  304. package/dist/workflows/runtime/plan-classifier.js +8 -8
  305. package/dist/workflows/runtime/runs.js +27 -43
  306. package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
  307. package/dist/workflows/source-files.js +373 -0
  308. package/dist/workflows/source-ir/compile.js +196 -0
  309. package/dist/workflows/source-ir/github-yaml.js +577 -0
  310. package/dist/workflows/source-ir/ordering.js +38 -0
  311. package/dist/workflows/source-ir/program.js +50 -0
  312. package/dist/workflows/source-ir/result.js +26 -0
  313. package/dist/workflows/source-ir/schema.js +772 -0
  314. package/dist/workflows/source-ir/semantics.js +242 -0
  315. package/dist/workflows/source-ir/uses.js +14 -0
  316. package/docs/README.md +2 -0
  317. package/docs/migration/README.md +3 -1
  318. package/docs/migration/release-notes/0.9.2.md +55 -0
  319. package/docs/migration/release-notes/README.md +5 -0
  320. package/docs/migration/v0.8-to-v0.9.md +76 -1077
  321. package/docs/migration/v0.9.0-troubleshooting.md +104 -516
  322. package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
  323. package/docs/reference/README.md +1 -0
  324. package/docs/reference/cli.md +230 -98
  325. package/docs/reference/configuration.md +153 -27
  326. package/docs/reference/data-and-telemetry.md +19 -1
  327. package/docs/reference/supported-formats.md +23 -3
  328. package/docs/reference/tasks.md +182 -0
  329. package/docs/reference/workflow-schema.md +91 -40
  330. package/docs/reference/workflows.md +33 -6
  331. package/package.json +10 -6
  332. package/schemas/akm-config.json +372 -216
  333. package/schemas/akm-task.json +324 -80
  334. package/schemas/akm-workflow.json +6 -9
  335. package/dist/core/migration-operation.js +0 -75
  336. package/dist/integrations/agent/model-aliases.js +0 -74
  337. package/dist/tasks/parser.js +0 -380
  338. package/dist/tasks/schema.js +0 -123
  339. package/dist/tasks/validator.js +0 -80
  340. package/dist/workflows/ir/freeze.js +0 -320
  341. package/dist/workflows/runtime/document-cache.js +0 -13
@@ -113,6 +113,12 @@ export function deriveInstallations(sources) {
113
113
  }
114
114
  return installations;
115
115
  }
116
+ /** Canonical bundle ids whose configured component policy permits mutation. */
117
+ export function deriveWritableBundleIds(sources) {
118
+ return new Set(deriveInstallations(sources)
119
+ .filter((installation) => installation.components.some((component) => component.writable === true))
120
+ .map((installation) => installation.id));
121
+ }
116
122
  /**
117
123
  * Derive the durable `EntryProvenance` for an indexed entry (Chunk-5 flip
118
124
  * §14.4): `conceptId` is the D-R2 qualified `<stash-subdir>/<name>` spelling
@@ -0,0 +1,283 @@
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
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { adapterForId } from "../../core/adapter/registry.js";
7
+ import { isWithin } from "../../core/common.js";
8
+ import { UsageError } from "../../core/errors.js";
9
+ import { canonicalizeWorkflowName } from "../../core/recognition-util.js";
10
+ import { resolveUniqueWorkflowSource, workflowNameForConceptId, } from "../../workflows/source-files.js";
11
+ import { buildFileContext } from "../walk/file-context.js";
12
+ const CONTENT_READ_REQUIRED = Symbol("adapter ownership probe requires content");
13
+ const OWNER_SCAN_MAX_DIRECTORIES = 4_096;
14
+ const OWNER_SCAN_MAX_FILES = 16_384;
15
+ const OWNER_SCAN_SKIP_DIRECTORIES = new Set([".git", "node_modules", "bin", ".cache"]);
16
+ const OWNER_SCAN_SKIP_FILES = new Set([".stash.json", ".gitignore", ".gitattributes"]);
17
+ export class AdapterConceptOwnershipError extends UsageError {
18
+ }
19
+ export class AdapterConceptCollisionError extends AdapterConceptOwnershipError {
20
+ constructor(adapterId, conceptId, paths) {
21
+ const sorted = [...paths].sort(comparePaths);
22
+ super(`Adapter "${adapterId}" has multiple physical owners for "${conceptId}": ${sorted.join(", ")}.`, "RESOURCE_ALREADY_EXISTS");
23
+ this.name = "AdapterConceptCollisionError";
24
+ Object.setPrototypeOf(this, new.target.prototype);
25
+ }
26
+ }
27
+ export class AdapterConceptScanError extends AdapterConceptOwnershipError {
28
+ constructor(adapterId, sourcePath, detail) {
29
+ super(`Adapter "${adapterId}" could not safely enumerate ${sourcePath}: ${detail}.`, "INVALID_FLAG_VALUE");
30
+ this.name = "AdapterConceptScanError";
31
+ Object.setPrototypeOf(this, new.target.prototype);
32
+ }
33
+ }
34
+ function normalizedConceptId(conceptId) {
35
+ const normalized = conceptId.replaceAll("\\", "/");
36
+ if (!normalized ||
37
+ path.posix.isAbsolute(normalized) ||
38
+ normalized === ".." ||
39
+ normalized.startsWith("../") ||
40
+ path.posix.normalize(normalized) !== normalized) {
41
+ return undefined;
42
+ }
43
+ return normalized;
44
+ }
45
+ function componentFor(sourcePath, adapterId) {
46
+ return { id: adapterId, adapter: adapterId, root: sourcePath, writable: false };
47
+ }
48
+ function lexicallyWithin(candidate, root) {
49
+ const relative = path.relative(path.resolve(root), path.resolve(candidate));
50
+ return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative));
51
+ }
52
+ /** Add case-only suffix spellings beside an adapter-authored read candidate. */
53
+ function candidateSpellings(candidate, sourcePath, realRoot) {
54
+ const authored = path.resolve(candidate.path);
55
+ if (!lexicallyWithin(authored, sourcePath))
56
+ return [{ ...candidate, path: authored }];
57
+ const parent = path.dirname(authored);
58
+ let realParent;
59
+ let entries;
60
+ try {
61
+ realParent = fs.realpathSync(parent);
62
+ entries = fs.readdirSync(parent, { withFileTypes: true });
63
+ }
64
+ catch {
65
+ return [{ ...candidate, path: authored }];
66
+ }
67
+ if (!isWithin(realParent, realRoot))
68
+ return [{ ...candidate, path: authored }];
69
+ const extension = path.extname(authored);
70
+ if (!extension)
71
+ return [{ ...candidate, path: authored }];
72
+ const stem = path.basename(authored, extension);
73
+ return entries
74
+ .filter((entry) => {
75
+ const entryExtension = path.extname(entry.name);
76
+ return (path.basename(entry.name, entryExtension) === stem && entryExtension.toLowerCase() === extension.toLowerCase());
77
+ })
78
+ .map((entry) => ({ ...candidate, path: path.join(parent, entry.name) }));
79
+ }
80
+ function inspectCandidate(sourcePath, realRoot, adapterId, candidate) {
81
+ const authoredPath = path.resolve(candidate.path);
82
+ if (!lexicallyWithin(authoredPath, sourcePath))
83
+ return undefined;
84
+ let authoredStat;
85
+ try {
86
+ authoredStat = fs.lstatSync(authoredPath);
87
+ }
88
+ catch {
89
+ return undefined;
90
+ }
91
+ if (!authoredStat.isFile() && !authoredStat.isSymbolicLink())
92
+ return undefined;
93
+ let realPath;
94
+ try {
95
+ realPath = fs.realpathSync(authoredPath);
96
+ }
97
+ catch {
98
+ return undefined;
99
+ }
100
+ if (!isWithin(realPath, realRoot))
101
+ return undefined;
102
+ try {
103
+ if (!fs.statSync(realPath).isFile())
104
+ return undefined;
105
+ }
106
+ catch {
107
+ return undefined;
108
+ }
109
+ return { path: authoredPath, realPath, conceptId: candidate.conceptId, adapterId };
110
+ }
111
+ function claimsWithoutContent(adapter, component, owner) {
112
+ const file = buildFileContext(component.root, owner.path);
113
+ let requestedBytes = false;
114
+ const denyBytes = () => {
115
+ requestedBytes = true;
116
+ throw CONTENT_READ_REQUIRED;
117
+ };
118
+ const noContentFile = { ...file, content: denyBytes, frontmatter: denyBytes };
119
+ try {
120
+ const document = adapter.recognize(component, noContentFile);
121
+ if (requestedBytes)
122
+ return true;
123
+ return document?.conceptId === owner.conceptId;
124
+ }
125
+ catch (error) {
126
+ if (error === CONTENT_READ_REQUIRED)
127
+ return true;
128
+ throw error;
129
+ }
130
+ }
131
+ function adapterPathContext(root, authoredPath) {
132
+ const file = buildFileContext(root, authoredPath);
133
+ return {
134
+ absPath: file.absPath,
135
+ relPath: file.relPath,
136
+ ext: file.ext,
137
+ fileName: file.fileName,
138
+ parentDir: file.parentDir,
139
+ parentDirAbs: file.parentDirAbs,
140
+ ancestorDirs: file.ancestorDirs,
141
+ stashRoot: file.stashRoot,
142
+ };
143
+ }
144
+ function scanRegularAuthoredPaths(sourcePath, realRoot, adapterId) {
145
+ const paths = [];
146
+ const stack = [path.resolve(sourcePath)];
147
+ let directories = 0;
148
+ let files = 0;
149
+ while (stack.length > 0) {
150
+ const current = stack.pop();
151
+ if (!current)
152
+ continue;
153
+ directories++;
154
+ if (directories > OWNER_SCAN_MAX_DIRECTORIES) {
155
+ throw new AdapterConceptScanError(adapterId, sourcePath, `directory limit ${OWNER_SCAN_MAX_DIRECTORIES} exceeded`);
156
+ }
157
+ let entries;
158
+ try {
159
+ entries = fs
160
+ .readdirSync(current, { withFileTypes: true })
161
+ .sort((left, right) => comparePaths(left.name, right.name));
162
+ }
163
+ catch (error) {
164
+ throw new AdapterConceptScanError(adapterId, sourcePath, `cannot read ${current}: ${String(error)}`);
165
+ }
166
+ for (let index = entries.length - 1; index >= 0; index--) {
167
+ const entry = entries[index];
168
+ if (!entry)
169
+ continue;
170
+ const authoredPath = path.join(current, entry.name);
171
+ if (entry.isSymbolicLink())
172
+ continue;
173
+ if (entry.isDirectory()) {
174
+ if (OWNER_SCAN_SKIP_DIRECTORIES.has(entry.name) || entry.name.startsWith("."))
175
+ continue;
176
+ stack.push(authoredPath);
177
+ continue;
178
+ }
179
+ if (!entry.isFile() || OWNER_SCAN_SKIP_FILES.has(entry.name))
180
+ continue;
181
+ files++;
182
+ if (files > OWNER_SCAN_MAX_FILES) {
183
+ throw new AdapterConceptScanError(adapterId, sourcePath, `file limit ${OWNER_SCAN_MAX_FILES} exceeded`);
184
+ }
185
+ let realPath;
186
+ try {
187
+ realPath = fs.realpathSync(authoredPath);
188
+ }
189
+ catch {
190
+ continue;
191
+ }
192
+ if (isWithin(realPath, realRoot))
193
+ paths.push(authoredPath);
194
+ }
195
+ }
196
+ return paths.sort(comparePaths);
197
+ }
198
+ function scannedReadCandidates(adapter, component, sourcePath, realRoot, conceptId) {
199
+ const recognizePathCandidates = adapter.recognizePathCandidates;
200
+ if (!recognizePathCandidates)
201
+ return [];
202
+ return scanRegularAuthoredPaths(sourcePath, realRoot, adapter.id).flatMap((authoredPath) => recognizePathCandidates(component, adapterPathContext(sourcePath, authoredPath)).flatMap((candidateConceptId) => candidateConceptId === conceptId ? [{ path: authoredPath, conceptId: candidateConceptId }] : []));
203
+ }
204
+ /**
205
+ * Resolve one adapter/component's exact physical concept owner without reading
206
+ * authored bytes. Native workflow arbitration is reused verbatim; every other
207
+ * adapter supplies its own read placements and is probed with a byte-denying
208
+ * FileContext so path-level abstention remains authoritative.
209
+ */
210
+ export function resolveAdapterConceptOwner(sourcePath, adapterId, conceptId) {
211
+ const adapter = adapterForId(adapterId);
212
+ const normalized = normalizedConceptId(conceptId);
213
+ if (!adapter || !normalized)
214
+ return undefined;
215
+ let realRoot;
216
+ try {
217
+ realRoot = fs.realpathSync(sourcePath);
218
+ }
219
+ catch {
220
+ return undefined;
221
+ }
222
+ const component = componentFor(sourcePath, adapterId);
223
+ const ownersByIdentity = new Map();
224
+ const workflowName = workflowNameForConceptId(adapterId, normalized);
225
+ const resolutionConceptId = workflowName === undefined
226
+ ? normalized
227
+ : adapterId === "akm"
228
+ ? `workflows/${canonicalizeWorkflowName(workflowName)}`
229
+ : canonicalizeWorkflowName(workflowName);
230
+ if (workflowName !== undefined) {
231
+ const workflowSource = resolveUniqueWorkflowSource(sourcePath, adapterId, workflowName);
232
+ if (workflowSource) {
233
+ const workflowOwner = {
234
+ path: workflowSource.path,
235
+ realPath: workflowSource.realPath,
236
+ conceptId: resolutionConceptId,
237
+ adapterId,
238
+ workflowSource,
239
+ };
240
+ ownersByIdentity.set(`${path.resolve(workflowOwner.path)}\0${resolutionConceptId}`, workflowOwner);
241
+ }
242
+ }
243
+ const directSpellings = (adapter.readCandidates?.(component, resolutionConceptId) ?? []).flatMap((candidate) => candidateSpellings(candidate, sourcePath, realRoot));
244
+ const spellings = [
245
+ ...directSpellings,
246
+ ...scannedReadCandidates(adapter, component, sourcePath, realRoot, resolutionConceptId),
247
+ ];
248
+ const inspected = [
249
+ ...new Map(spellings.map((candidate) => [`${path.resolve(candidate.path)}\0${candidate.conceptId}`, candidate])).values(),
250
+ ]
251
+ .sort((left, right) => comparePaths(left.path, right.path))
252
+ .flatMap((candidate) => {
253
+ const owner = inspectCandidate(sourcePath, realRoot, adapterId, candidate);
254
+ return owner ? [owner] : [];
255
+ });
256
+ for (const candidate of inspected) {
257
+ if (candidate.conceptId !== resolutionConceptId)
258
+ continue;
259
+ const identity = `${path.resolve(candidate.path)}\0${candidate.conceptId}`;
260
+ if (ownersByIdentity.has(identity))
261
+ continue;
262
+ if (claimsWithoutContent(adapter, component, candidate))
263
+ ownersByIdentity.set(identity, candidate);
264
+ }
265
+ const owners = [...ownersByIdentity.values()].filter((owner) => owner.conceptId === resolutionConceptId);
266
+ if (owners.length > 1) {
267
+ throw new AdapterConceptCollisionError(adapterId, resolutionConceptId, owners.map((owner) => path.relative(sourcePath, owner.path).replaceAll("\\", "/")));
268
+ }
269
+ return owners[0];
270
+ }
271
+ export function indexedPathMatchesOwner(indexedPath, owner) {
272
+ if (path.resolve(indexedPath) !== path.resolve(owner.path))
273
+ return false;
274
+ try {
275
+ return path.resolve(fs.realpathSync(indexedPath)) === path.resolve(owner.realPath);
276
+ }
277
+ catch {
278
+ return false;
279
+ }
280
+ }
281
+ function comparePaths(left, right) {
282
+ return left < right ? -1 : left > right ? 1 : 0;
283
+ }