akm-cli 0.9.15 → 0.9.16-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 (79) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/dist/assets/tasks/core/index-refresh.yml +1 -1
  3. package/dist/cli/retired-commands.js +2 -0
  4. package/dist/cli/unknown-flags.js +36 -3
  5. package/dist/commands/improve/collapse-detector.js +2 -2
  6. package/dist/commands/improve/consolidate.js +6 -4
  7. package/dist/commands/improve/improve-cli.js +1 -1
  8. package/dist/commands/proposal/repository.js +12 -3
  9. package/dist/commands/read/curate.js +34 -44
  10. package/dist/commands/read/search.js +50 -2
  11. package/dist/commands/sources/index-status.js +99 -0
  12. package/dist/commands/sources/info.js +8 -8
  13. package/dist/commands/sources/installed-stashes.js +33 -12
  14. package/dist/commands/sources/source-add.js +21 -6
  15. package/dist/commands/sources/stash-cli.js +119 -111
  16. package/dist/core/adapter/adapters/akm-adapter.js +35 -3
  17. package/dist/core/adapter/adapters/akm-metadata.js +11 -1
  18. package/dist/core/asset/asset-placement.js +35 -0
  19. package/dist/core/config/schema/embedding.js +7 -30
  20. package/dist/core/config/schema/search.js +11 -9
  21. package/dist/core/errors.js +5 -2
  22. package/dist/core/hash.js +18 -0
  23. package/dist/core/maintenance-barrier.js +8 -6
  24. package/dist/core/paths.js +0 -11
  25. package/dist/core/run-lock.js +5 -2
  26. package/dist/core/state/migrations.js +26 -1
  27. package/dist/core/state-db.js +63 -27
  28. package/dist/indexer/drain.js +306 -0
  29. package/dist/indexer/embedding-identity.js +20 -0
  30. package/dist/indexer/enrich.js +260 -0
  31. package/dist/indexer/ensure-index.js +5 -0
  32. package/dist/indexer/index-written-assets.js +133 -171
  33. package/dist/indexer/indexer.js +458 -1621
  34. package/dist/indexer/lookup/adapter-concept-owner.js +19 -5
  35. package/dist/indexer/passes/metadata.js +18 -1
  36. package/dist/indexer/reconcile.js +890 -0
  37. package/dist/indexer/scan/drain-dir.js +27 -70
  38. package/dist/indexer/scan/parse-file.js +66 -0
  39. package/dist/indexer/search/db-search.js +373 -89
  40. package/dist/indexer/search/ranking-contributors.js +21 -16
  41. package/dist/indexer/search/ranking.js +135 -57
  42. package/dist/indexer/units/unit.js +159 -0
  43. package/dist/llm/client.js +10 -1
  44. package/dist/llm/embedder.js +10 -3
  45. package/dist/llm/embedders/provider-limits.js +288 -0
  46. package/dist/llm/embedders/remote.js +133 -104
  47. package/dist/llm/feature-gate.js +4 -2
  48. package/dist/llm/rerank-client.js +3 -3
  49. package/dist/output/shapes/passthrough.js +1 -0
  50. package/dist/output/text/command-format.js +19 -13
  51. package/dist/output/text/helpers.js +1 -1
  52. package/dist/output/text/index.js +5 -2
  53. package/dist/scripts/akm-migrate-node.js +1141 -1237
  54. package/dist/scripts/akm-migrate.js +1141 -1237
  55. package/dist/setup/semantic-assets.js +2 -2
  56. package/dist/setup/steps/connection.js +3 -2
  57. package/dist/storage/repositories/files-repository.js +181 -0
  58. package/dist/storage/repositories/index-connection.js +1 -3
  59. package/dist/storage/repositories/index-entries-repository.js +77 -68
  60. package/dist/storage/repositories/index-entry-schema.js +16 -25
  61. package/dist/storage/repositories/index-fts-repository.js +29 -263
  62. package/dist/storage/repositories/index-meta-repository.js +0 -29
  63. package/dist/storage/repositories/index-schema.js +115 -122
  64. package/dist/storage/repositories/index-utility-repository.js +1 -1
  65. package/dist/storage/repositories/index-vec-repository.js +21 -334
  66. package/dist/storage/repositories/units-repository.js +510 -0
  67. package/docs/migration/release-notes/0.9.15.md +34 -36
  68. package/docs/migration/release-notes/0.9.16.md +110 -0
  69. package/docs/migration/release-notes/README.md +5 -0
  70. package/docs/reference/cli.md +93 -87
  71. package/docs/reference/configuration.md +128 -89
  72. package/docs/reference/data-and-telemetry.md +2 -1
  73. package/package.json +1 -1
  74. package/schemas/akm-config.json +2 -58
  75. package/dist/indexer/index-db-contention.js +0 -56
  76. package/dist/indexer/index-rebuild-lock.js +0 -73
  77. package/dist/indexer/materialize-embeddings.js +0 -771
  78. package/dist/indexer/passes/dir-staleness.js +0 -161
  79. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
@@ -5,19 +5,18 @@
5
5
  * Per-directory document drain — akm 0.9.0 Chunk 5, milestone F4a M-core-2 (the
6
6
  * engine swap). Replaces the live indexer's per-dir flat-walk matcher-pass
7
7
  * `IndexDocument` stream with the `akm` adapter's `recognize` `IndexDocument`
8
- * stream, reconstructing the durable `IndexDocument` via {@link
9
- * indexDocumentToStashEntry} (proven lossless by the shadow-parity gate).
8
+ * stream, reconstructing the durable `IndexDocument` via {@link parseFileDocument}
9
+ * (proven lossless by the shadow-parity gate).
10
10
  *
11
- * Two behaviors the adapter fold does NOT carry, restored here at the drain
12
- * layer (spec §14.2 "drain the full document stream"):
11
+ * One directory-scoped behavior the per-file parse does NOT carry, restored
12
+ * here at the drain layer (spec §14.2 "drain the full document stream"):
13
13
  *
14
- * - **Broken-workflow drop (item 3).** The live path dropped a broken workflow
15
- * via the renderer contributor's throw metadata-pass skip-with-warning; the
16
- * `akm` adapter's synchronous `foldRecognizedMetadata` SWALLOWS the parse
17
- * error, so a broken workflow would otherwise silently index. We run the
18
- * shared source-IR compiler on drained workflow docs and DROP
19
- * the entry with the same `Skipped workflow …` warning
20
- * ({@link buildMetadataSkipWarning}), so the workflow-skip summary counts it.
14
+ * - **Peer-workflow-format ownership arbitration.** A full directory drain
15
+ * may contain both peer workflow formats for one canonical ref; resolving
16
+ * which one owns the ref requires seeing every file in the directory at
17
+ * once, so it stays here rather than in the single-file
18
+ * {@link parseFileDocument} (index-redesign B1 also calls that function to
19
+ * parse one already-known-changed file, with no peer files in view).
21
20
  *
22
21
  * `doc.hash` (= sha256 of the file content) is surfaced per recognized file so
23
22
  * the persist layer can populate the `content_hash` column (item 2). It is keyed
@@ -31,12 +30,8 @@ import { akmAdapter } from "../../core/adapter/adapters/akm-adapter.js";
31
30
  import { compareCodePoints } from "../../core/common.js";
32
31
  import { canonicalizeWorkflowName } from "../../core/recognition-util.js";
33
32
  import { resolveWorkflowSourceDomains, workflowNameForSourcePath } from "../../workflows/source-files.js";
34
- import { compileWorkflowSource } from "../../workflows/source-ir/compile.js";
35
- import { buildMetadataSkipWarning } from "../passes/metadata.js";
36
33
  import { buildFileContext } from "../walk/file-context.js";
37
- import { indexDocumentToStashEntry } from "./doc-to-entry.js";
38
- /** The markdown-workflow renderer name the `akm` adapter carries on `documentJson.renderer`. */
39
- const WORKFLOW_MD_RENDERER = "workflow-md";
34
+ import { parseFileDocument } from "./parse-file.js";
40
35
  /**
41
36
  * Drain one directory's recognized documents into durable entries.
42
37
  *
@@ -88,26 +83,24 @@ export function drainDirDocuments(adapter, component, fileContexts) {
88
83
  continue;
89
84
  }
90
85
  }
91
- const doc = adapter.recognize(component, file);
92
- if (doc === null)
93
- continue;
94
- if (!doc.conceptId) {
95
- warnings.push(`Skipped ${file.absPath}: adapter "${adapter.id}" returned no conceptId.`);
96
- continue;
97
- }
98
- const entry = indexDocumentToStashEntry(doc);
99
- // Workflow docs: drop-with-warning if broken; otherwise cache a lossless
100
- // runtime projection when the current executor can represent the source.
101
- const dropWarning = handleWorkflowDoc(doc, file, component.root);
102
- if (dropWarning !== null) {
103
- warnings.push(dropWarning);
104
- if (workflowName !== undefined)
105
- invalidWorkflowOwnerNames.add(canonicalizeWorkflowName(workflowName));
86
+ // The recognize → conceptId check → workflow-validity fold is the SAME
87
+ // per-file parse the reconcile engine uses for a single changed file
88
+ // (index-redesign B1) — extracted to `parse-file.ts` so the two never
89
+ // drift apart.
90
+ const outcome = parseFileDocument(adapter, component, file);
91
+ if (outcome.parsed === null) {
92
+ if (outcome.warning !== null) {
93
+ warnings.push(outcome.warning);
94
+ if (outcome.isWorkflowDrop && workflowName !== undefined) {
95
+ invalidWorkflowOwnerNames.add(canonicalizeWorkflowName(workflowName));
96
+ }
97
+ }
106
98
  continue;
107
99
  }
108
- if (doc.hash !== undefined)
109
- hashByFile.set(file.absPath, doc.hash);
110
- conceptIdByFile.set(file.absPath, doc.conceptId);
100
+ const { entry, hash, conceptId } = outcome.parsed;
101
+ if (hash !== undefined)
102
+ hashByFile.set(file.absPath, hash);
103
+ conceptIdByFile.set(file.absPath, conceptId);
111
104
  entries.push(entry);
112
105
  }
113
106
  return { entries, warnings, hashByFile, conceptIdByFile, rejectedPaths, rejectedConceptIds };
@@ -133,39 +126,3 @@ export function recognizeStashEntries(stashRoot, files) {
133
126
  ? { entries: drained.entries, warnings: drained.warnings }
134
127
  : { entries: drained.entries };
135
128
  }
136
- /**
137
- * If `doc` is a workflow, compile it through source IR: return a
138
- * `Skipped workflow …` drop warning when it is broken, or return `null` when
139
- * it compiles. Non-workflow docs return `null` immediately.
140
- */
141
- function handleWorkflowDoc(doc, file, workspaceRoot) {
142
- if (doc.type !== "workflow" ||
143
- (doc.adapterId !== "akm" && doc.adapterId !== "akm-workflow") ||
144
- (docRenderer(doc) !== WORKFLOW_MD_RENDERER && doc.adapterId !== "akm-workflow")) {
145
- return null;
146
- }
147
- const result = compileWorkflowSource(file.content(), { path: file.relPath, workspaceRoot });
148
- if (!result.ok)
149
- return workflowDropWarning(file, result.errors);
150
- return null;
151
- }
152
- /** The winning renderer name the `akm` adapter carries on `documentJson.renderer`, or `undefined`. */
153
- function docRenderer(doc) {
154
- const dj = doc.documentJson;
155
- if (dj !== null && typeof dj === "object" && "renderer" in dj) {
156
- const renderer = dj.renderer;
157
- return typeof renderer === "string" ? renderer : undefined;
158
- }
159
- return undefined;
160
- }
161
- /**
162
- * Build the `Skipped workflow <path>:\n…` warning byte-for-byte the way the live
163
- * pipeline did: the workflow parser's `path:line — message` summary wrapped in
164
- * the `Workflow has errors:` prefix (the string `loadDocument`/`loadProgram`
165
- * threw), then {@link buildMetadataSkipWarning}'s workflow branch. `startsWith
166
- * "Skipped workflow "` so `isWorkflowSkipWarning` counts it for the summary.
167
- */
168
- function workflowDropWarning(file, errors) {
169
- const summary = errors.map((e) => `${file.relPath}:${e.line} — ${e.message}`).join("\n");
170
- return buildMetadataSkipWarning(file.absPath, "workflow", `Workflow has errors:\n${summary}`);
171
- }
@@ -0,0 +1,66 @@
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 { compileWorkflowSource } from "../../workflows/source-ir/compile.js";
5
+ import { buildMetadataSkipWarning } from "../passes/metadata.js";
6
+ import { indexDocumentToStashEntry } from "./doc-to-entry.js";
7
+ /** The markdown-workflow renderer name the `akm` adapter carries on `documentJson.renderer`. */
8
+ const WORKFLOW_MD_RENDERER = "workflow-md";
9
+ /**
10
+ * Parse one file through `adapter.recognize`, reconstruct its durable entry,
11
+ * and drop it with a warning when it names no conceptId or is a workflow
12
+ * document that fails to compile. Pure of DB/global state.
13
+ */
14
+ export function parseFileDocument(adapter, component, file) {
15
+ const doc = adapter.recognize(component, file);
16
+ if (doc === null)
17
+ return { parsed: null, warning: null, isWorkflowDrop: false };
18
+ if (!doc.conceptId) {
19
+ return {
20
+ parsed: null,
21
+ warning: `Skipped ${file.absPath}: adapter "${adapter.id}" returned no conceptId.`,
22
+ isWorkflowDrop: false,
23
+ };
24
+ }
25
+ const entry = indexDocumentToStashEntry(doc);
26
+ const dropWarning = handleWorkflowDoc(doc, file, component.root);
27
+ if (dropWarning !== null) {
28
+ return { parsed: null, warning: dropWarning, isWorkflowDrop: true };
29
+ }
30
+ return { parsed: { entry, hash: doc.hash, conceptId: doc.conceptId }, warning: null, isWorkflowDrop: false };
31
+ }
32
+ /**
33
+ * If `doc` is a workflow, compile it through source IR: return a
34
+ * `Skipped workflow …` drop warning when it is broken, or return `null` when
35
+ * it compiles. Non-workflow docs return `null` immediately.
36
+ */
37
+ function handleWorkflowDoc(doc, file, workspaceRoot) {
38
+ if (doc.type !== "workflow" ||
39
+ (doc.adapterId !== "akm" && doc.adapterId !== "akm-workflow") ||
40
+ (docRenderer(doc) !== WORKFLOW_MD_RENDERER && doc.adapterId !== "akm-workflow")) {
41
+ return null;
42
+ }
43
+ const result = compileWorkflowSource(file.content(), { path: file.relPath, workspaceRoot });
44
+ if (!result.ok)
45
+ return workflowDropWarning(file, result.errors);
46
+ return null;
47
+ }
48
+ /** The winning renderer name the `akm` adapter carries on `documentJson.renderer`, or `undefined`. */
49
+ function docRenderer(doc) {
50
+ const dj = doc.documentJson;
51
+ if (dj !== null && typeof dj === "object" && "renderer" in dj) {
52
+ const renderer = dj.renderer;
53
+ return typeof renderer === "string" ? renderer : undefined;
54
+ }
55
+ return undefined;
56
+ }
57
+ /**
58
+ * Build the `Skipped workflow <path>:\n…` warning byte-for-byte the way the live
59
+ * pipeline did: the workflow parser's `path:line — message` summary wrapped in
60
+ * the `Workflow has errors:` prefix (the string `loadDocument`/`loadProgram`
61
+ * threw), then {@link buildMetadataSkipWarning}'s workflow branch.
62
+ */
63
+ function workflowDropWarning(file, errors) {
64
+ const summary = errors.map((e) => `${file.relPath}:${e.line} — ${e.message}`).join("\n");
65
+ return buildMetadataSkipWarning(file.absPath, "workflow", `Workflow has errors:\n${summary}`);
66
+ }