akm-cli 0.9.17-alpha.4 → 0.9.17-alpha.6

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.
@@ -174,12 +174,11 @@ export function getBaseBeliefStatesForDerivedTwins(db, twinIds) {
174
174
  /**
175
175
  * Re-key an entries row in place for the opt-in source-maintenance script.
176
176
  *
177
- * The row id is preserved on purpose — `utility_scores`,
178
- * `utility_scores_scoped`, and `embeddings` are keyed by `entry_id`, so an
179
- * UPDATE (rather than a delete + insert under the new `item_ref`) is what
180
- * keeps the asset's accumulated usage-ranking history attached across a
181
- * rename. (`asset_salience` / `asset_outcome` live in state.db keyed by
182
- * `asset_ref` TEXT and are re-keyed separately by `akm mv` — see
177
+ * The row id is preserved on purpose — `utility_scores` and `embeddings` are
178
+ * keyed by `entry_id`, so an UPDATE (rather than a delete + insert under the
179
+ * new `item_ref`) is what keeps the asset's accumulated usage-ranking history
180
+ * attached across a rename. (`asset_salience` / `asset_outcome` live in
181
+ * state.db keyed by `asset_ref` TEXT and are re-keyed separately by `akm mv` — see
183
182
  * the state rekey helper.) `document_json.name` (and `filename`, when
184
183
  * present) is patched and `embed_hash` recomputed so search reflects the new
185
184
  * name. Its FTS projection and stale vector are updated in the same
@@ -407,7 +406,6 @@ function deleteRelatedRows(db, ids, options = {}) {
407
406
  bestEffort(() => db.prepare(`DELETE FROM embeddings WHERE id IN (${placeholders})`).run(...chunk), "delete embeddings for entries");
408
407
  // Clean up utility scores before deleting entries
409
408
  bestEffort(() => db.prepare(`DELETE FROM utility_scores WHERE entry_id IN (${placeholders})`).run(...chunk), "delete utility_scores for entries");
410
- bestEffort(() => db.prepare(`DELETE FROM utility_scores_scoped WHERE entry_id IN (${placeholders})`).run(...chunk), "delete utility_scores_scoped for entries");
411
409
  }
412
410
  // usage_events lives in state.db, outside this transaction. Index persistence
413
411
  // disables this cleanup and runs it only after its index.db transaction
@@ -10,8 +10,9 @@
10
10
  * for columns added after a table first shipped, drops of retired derived
11
11
  * tables and columns, and one in-place rebuild of the (derived, cheap) FTS
12
12
  * table when its layout is older than this release's. It never drops
13
- * `entries`, `embeddings`, `utility_scores*`, `graph_*`, or
14
- * `llm_enrichment_cache` to cross a version boundary; the only from-scratch
13
+ * `entries`, `embeddings`, `utility_scores`, the extracted graph
14
+ * (`graph_meta`, `graph_files`, `graph_file_*`), or `llm_enrichment_cache`
15
+ * to cross a version boundary; the only from-scratch
15
16
  * rebuild is the SQLITE_CORRUPT path in `index-connection.ts`. A layout newer
16
17
  * than this release's is refused, naming the upgrade
17
18
  * ({@link newerIndexLayoutError}).
@@ -27,7 +28,11 @@ import { getMeta, setMeta } from "./index-meta-repository.js";
27
28
  export const DB_VERSION = CANONICAL_INDEX_DB_VERSION;
28
29
  /** `index_meta` key set when the writable opener migrated the layout; cleared once `akm index` VACUUMs. */
29
30
  export const VACUUM_PENDING_META = "vacuumPending";
30
- // #624-P1: graph_files is keyed to (stash_root, file_path, body_hash).
31
+ /**
32
+ * The value written to `graph_meta.schema_version`, a NOT NULL column in every
33
+ * released layout. Releases up to 0.9.17-alpha.5 write 4 and nothing ever
34
+ * compares it; the index layout version gates the graph tables' shape.
35
+ */
31
36
  export const GRAPH_SCHEMA_VERSION = 4;
32
37
  /**
33
38
  * The refusal for an index a newer akm wrote. Readers and the writable opener
@@ -62,7 +67,7 @@ const REGISTRY_INDEX_CACHE_DDL = `
62
67
  `;
63
68
  /**
64
69
  * Create the graph-extraction tables (`graph_meta`/`graph_files`/`graph_file_entities`/
65
- * `graph_file_relations`/`graph_extraction_queue`).
70
+ * `graph_file_relations`).
66
71
  *
67
72
  * graph_files is self-keyed on (stash_root, file_path, body_hash) and is not
68
73
  * tied to entries.id (#624-P1): re-upserting an entries row never disturbs the
@@ -141,21 +146,6 @@ function ensureGraphTables(db) {
141
146
  FOREIGN KEY (stash_root, file_path, body_hash)
142
147
  REFERENCES graph_files(stash_root, file_path, body_hash) ON DELETE CASCADE
143
148
  );
144
-
145
- -- #624-P3: lazy graph-extraction queue. Standalone table (NO FK to
146
- -- graph_files — a queued file by definition has no graph row yet).
147
- -- Idempotent on (stash_root, file_path); drained highest-priority-first.
148
- CREATE TABLE IF NOT EXISTS graph_extraction_queue (
149
- stash_root TEXT NOT NULL,
150
- file_path TEXT NOT NULL,
151
- body_hash TEXT NOT NULL,
152
- queued_at TEXT NOT NULL DEFAULT (datetime('now')),
153
- priority INTEGER NOT NULL DEFAULT 0,
154
- PRIMARY KEY (stash_root, file_path)
155
- );
156
-
157
- CREATE INDEX IF NOT EXISTS idx_graph_extraction_queue_drain
158
- ON graph_extraction_queue(stash_root, priority DESC, queued_at);
159
149
  `);
160
150
  }
161
151
  /**
@@ -286,12 +276,17 @@ export function ensureSchema(db) {
286
276
  replaceSearchTextWithHash(db);
287
277
  // Retired derived tables: the workflow IR cache, the pre-v22 FTS dirty
288
278
  // queue, the #955 embedding salvage staging table (embeddings now carry
289
- // their model per row, so nothing is copied aside and reused), and the
290
- // fragment FTS table search stopped reading (layout 24 and earlier).
279
+ // their model per row, so nothing is copied aside and reused), the
280
+ // fragment FTS table search stopped reading (layout 24 and earlier), the
281
+ // per-project scoped utility table (IR-7a: it shipped, but no code ever read
282
+ // or wrote a row), and the lazy graph-extraction queue (extraction runs only
283
+ // in improve).
291
284
  db.exec("DROP TABLE IF EXISTS workflow_documents");
292
285
  db.exec("DROP TABLE IF EXISTS entries_fts_dirty");
293
286
  db.exec("DROP TABLE IF EXISTS embedding_salvage");
294
287
  db.exec("DROP TABLE IF EXISTS entry_fragments_fts");
288
+ db.exec("DROP TABLE IF EXISTS utility_scores_scoped");
289
+ db.exec("DROP TABLE IF EXISTS graph_extraction_queue");
295
290
  // One float32 BLOB per entry, searched by an exact scan
296
291
  // (index-vec-repository.ts). `model` is the provider fingerprint the vector was generated under
297
292
  // (`deriveSemanticProviderFingerprint`); the embedding pass re-embeds only
@@ -326,19 +321,6 @@ export function ensureSchema(db) {
326
321
  updated_at TEXT NOT NULL DEFAULT (datetime('now')),
327
322
  FOREIGN KEY (entry_id) REFERENCES entries(id) ON DELETE CASCADE
328
323
  );
329
- `);
330
- // Per-project scoped utility scores — tracks usage per (entry, cwd-anchor)
331
- // so assets useful in project A don't pollute rankings in project B.
332
- db.exec(`
333
- CREATE TABLE IF NOT EXISTS utility_scores_scoped (
334
- entry_id INTEGER NOT NULL,
335
- scope_key TEXT NOT NULL,
336
- utility REAL NOT NULL DEFAULT 0,
337
- last_used_at INTEGER NOT NULL,
338
- PRIMARY KEY (entry_id, scope_key)
339
- );
340
- CREATE INDEX IF NOT EXISTS idx_utility_scores_scoped_entry_id
341
- ON utility_scores_scoped(entry_id);
342
324
  `);
343
325
  db.exec(`
344
326
  CREATE TABLE IF NOT EXISTS index_dir_state (
@@ -503,7 +503,9 @@ embedded with the model's query template (see `embedding.queryTemplate` in
503
503
  keyword ranking alone with `fts-fallback` and a warning. Filters (`--type`,
504
504
  `--from`, `--filter`, `--belief`, the default session exclusion, proposed
505
505
  quality) and one-hit-per-file deduplication narrow the fused list without
506
- reordering it.
506
+ reordering it. Of entries with identical indexed content (the same body
507
+ saved under another name or in another bundle), only the highest-ranked is
508
+ kept.
507
509
 
508
510
  | Flag | Values | Default | Description |
509
511
  | --- | --- | --- | --- |
@@ -607,6 +609,12 @@ only for read-only items. Their `followUp` remains `akm show <ref>` rather than
607
609
  being replaced by clone guidance.
608
610
  Use `--type workflow` when you want curated step-by-step procedures instead of
609
611
  individual scripts, skills, or docs.
612
+ Curate returns no items, on purpose, when the input is not a task: a harness
613
+ or tool envelope (input that starts with an XML-style tag and contains a
614
+ closing tag, such as `<task-notification>…</task-notification>`) or the stash
615
+ README boilerplate. The `summary` then starts with `Curate abstained` and
616
+ names the reason, and `tip` says how to curate the task instead. Long input is
617
+ curated like any other.
610
618
  `akm curate` is safe to call frequently, including from a hook that fires on
611
619
  every prompt: it only ever reads the index as it currently stands (the same
612
620
  non-blocking `ensureIndex()` path `search` uses) and never waits on or
@@ -327,6 +327,13 @@ incompatible engine never falls back to another engine. Built-in strategies
327
327
  are complete presets. User-defined strategies inherit omitted fields from the
328
328
  built-in `default` strategy before applying their own overrides.
329
329
 
330
+ Graph extraction also reads `index.graph`. Its `engine`, `model`, `timeoutMs`
331
+ and `llm` apply over the strategy-wide values, and `processes.graphExtraction`
332
+ overrides them. `processes.graphExtraction.batchSize` and `includeTypes` win
333
+ over `index.graph.graphExtractionBatchSize` and `graphExtractionIncludeTypes`;
334
+ with neither set, the batch size is 4 and the types are `memory` and
335
+ `knowledge`.
336
+
330
337
  `processes.triage.judgment` explicitly controls the optional judgment tier.
331
338
  Use `true` to enable it, `false` to disable it, or an object with `enabled`,
332
339
  `engine`, `model`, `timeoutMs`, and/or `llm` overrides. Existing object values
@@ -840,3 +847,8 @@ profile identities.
840
847
  `embedding.chunkSize` was never read by anything under `src/` (#954), so a
841
848
  config that still sets it is simply ignored — it still loads, unvalidated
842
849
  and without warning.
850
+
851
+ `index.graph.lazyGraphExtraction` is retired in 0.9.17: `akm show` and
852
+ `akm curate` no longer extract or queue graph work, and graph extraction runs
853
+ only in `akm improve`. A config that still sets it loads; the key is named
854
+ once as unknown, and `akm migrate apply` removes it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-cli",
3
- "version": "0.9.17-alpha.4",
3
+ "version": "0.9.17-alpha.6",
4
4
  "type": "module",
5
5
  "description": "akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cursor.",
6
6
  "keywords": [
@@ -413,9 +413,6 @@
413
413
  "minLength": 1
414
414
  },
415
415
  "minItems": 1
416
- },
417
- "lazyGraphExtraction": {
418
- "type": "boolean"
419
416
  }
420
417
  },
421
418
  "additionalProperties": true
@@ -2077,9 +2074,6 @@
2077
2074
  "minLength": 1
2078
2075
  },
2079
2076
  "minItems": 1
2080
- },
2081
- "lazyGraphExtraction": {
2082
- "type": "boolean"
2083
2077
  }
2084
2078
  },
2085
2079
  "additionalProperties": true