akm-cli 0.9.17-alpha.2 → 0.9.17-alpha.4
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.
- package/CHANGELOG.md +756 -0
- package/dist/akm +94 -196
- package/dist/cli/shared.js +6 -2
- package/dist/cli.js +22 -9
- package/dist/commands/agent/agent-dispatch.js +1 -1
- package/dist/commands/command/command-execution.js +24 -62
- package/dist/commands/feedback-cli.js +0 -1
- package/dist/commands/health/accept-rate.js +2 -2
- package/dist/commands/health/checks.js +30 -75
- package/dist/commands/health/config-skew.js +38 -0
- package/dist/commands/health/egress.js +54 -0
- package/dist/commands/health/html-report.js +0 -38
- package/dist/commands/health/improve-metrics.js +123 -562
- package/dist/commands/health/plugin-staleness.js +53 -3
- package/dist/commands/health/renderers.js +12 -4
- package/dist/commands/health/report-view-model.js +11 -106
- package/dist/commands/health/types-improve.js +4 -19
- package/dist/commands/health/windows.js +64 -73
- package/dist/commands/health.js +122 -143
- package/dist/commands/improve/consolidate/chunking.js +25 -100
- package/dist/commands/improve/consolidate/sanitize.js +54 -149
- package/dist/commands/improve/consolidate.js +538 -1075
- package/dist/commands/improve/content-hash.js +16 -24
- package/dist/commands/improve/distill/content-repair.js +18 -100
- package/dist/commands/improve/distill-guards.js +20 -81
- package/dist/commands/improve/distill-promotion-policy.js +23 -243
- package/dist/commands/improve/distill.js +608 -1075
- package/dist/commands/improve/eligibility.js +126 -400
- package/dist/commands/improve/execution.js +3 -5
- package/dist/commands/improve/extract.js +487 -1046
- package/dist/commands/improve/feedback-valence.js +0 -25
- package/dist/commands/improve/improve-cli.js +29 -166
- package/dist/commands/improve/improve-result-file.js +10 -66
- package/dist/commands/improve/improve-strategies.js +12 -7
- package/dist/commands/improve/improve-usage-report.js +18 -64
- package/dist/commands/improve/improve.js +443 -1063
- package/dist/commands/improve/ledger.js +114 -0
- package/dist/commands/improve/locks.js +2 -8
- package/dist/commands/improve/loop-stages.js +459 -1172
- package/dist/commands/improve/memory/derived-ref.js +12 -77
- package/dist/commands/improve/memory/memory-belief.js +14 -118
- package/dist/commands/improve/memory/memory-improve.js +4 -3
- package/dist/commands/improve/outcome-loop.js +28 -156
- package/dist/commands/improve/planner.js +5 -10
- package/dist/commands/improve/preparation.js +851 -2339
- package/dist/commands/improve/proactive-maintenance.js +34 -101
- package/dist/commands/improve/reflect-noise.js +104 -280
- package/dist/commands/improve/reflect.js +621 -1367
- package/dist/commands/improve/salience.js +46 -232
- package/dist/commands/improve/session-asset.js +19 -100
- package/dist/commands/improve/stage.js +323 -0
- package/dist/commands/proposal/drain.js +251 -644
- package/dist/commands/proposal/proposal-cli.js +3 -18
- package/dist/commands/proposal/proposal-types.js +20 -41
- package/dist/commands/proposal/proposal.js +1 -2
- package/dist/commands/proposal/propose.js +134 -160
- package/dist/commands/proposal/repository.js +502 -1487
- package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
- package/dist/commands/proposal/validators/proposal-validators.js +1 -1
- package/dist/commands/proposal/validators/proposals.js +13 -89
- package/dist/commands/read/curate.js +63 -413
- package/dist/commands/read/search-cli.js +16 -33
- package/dist/commands/read/search.js +17 -23
- package/dist/commands/read/show.js +2 -13
- package/dist/commands/sources/bundle-cli.js +25 -2
- package/dist/commands/sources/bundle-config-ops.js +7 -0
- package/dist/commands/sources/dangerous-env-audit.js +1 -2
- package/dist/commands/sources/info.js +2 -11
- package/dist/commands/sources/installed-stashes.js +197 -746
- package/dist/commands/sources/schema-repair.js +98 -129
- package/dist/commands/sources/source-add.js +62 -12
- package/dist/commands/sources/stash-cli.js +1 -1
- package/dist/commands/tasks/explain.js +10 -13
- package/dist/commands/tasks/tasks-cli.js +9 -8
- package/dist/commands/tasks/tasks.js +326 -930
- package/dist/commands/tasks/validate.js +42 -21
- package/dist/commands/workflow/plan.js +22 -29
- package/dist/commands/workflow-cli.js +4 -4
- package/dist/core/adapter/adapters/akm-adapter.js +0 -1
- package/dist/core/adapter/adapters/akm-lint.js +2 -3
- package/dist/core/adapter/adapters/akm-metadata.js +11 -12
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +17 -29
- package/dist/core/asset/resolve-ref.js +1 -1
- package/dist/core/bundle-id.js +42 -5
- package/dist/core/bundle-rename.js +291 -0
- package/dist/core/config/config-io.js +1 -2
- package/dist/core/config/config-schema.js +1 -33
- package/dist/core/config/config-walker.js +1 -1
- package/dist/core/config/config.js +163 -68
- package/dist/core/config/legacy-source-shape-shim.js +38 -9
- package/dist/core/config/schema/embedding.js +20 -5
- package/dist/core/config/schema/engines.js +5 -0
- package/dist/core/config/schema/execution.js +1 -1
- package/dist/core/config/schema/experimental.js +1 -1
- package/dist/core/config/schema/improve-processes.js +21 -95
- package/dist/core/config/schema/improve.js +4 -42
- package/dist/core/config/schema/scheduler.js +12 -12
- package/dist/core/config/schema/search.js +6 -22
- package/dist/core/env-secret-ref.js +0 -1
- package/dist/core/errors.js +8 -9
- package/dist/core/file-lock.js +76 -173
- package/dist/core/logs-db.js +2 -2
- package/dist/core/paths.js +0 -27
- package/dist/core/redaction.js +109 -2
- package/dist/core/run-lock.js +2 -5
- package/dist/core/spawn-env.js +1 -1
- package/dist/core/state/migrations.js +108 -61
- package/dist/core/state-db-scope.js +2 -4
- package/dist/core/state-db.js +126 -692
- package/dist/core/type-presentation.js +1 -9
- package/dist/core/write-source.js +293 -1012
- package/dist/execution/input-contract.js +1 -1
- package/dist/execution/resolved-request.js +135 -689
- package/dist/execution/source.js +63 -257
- package/dist/execution/target-ref.js +1 -1
- package/dist/indexer/bundle-identity-guard.js +2 -2
- package/dist/indexer/db/graph-db.js +106 -46
- package/dist/indexer/ensure-index.js +44 -85
- package/dist/indexer/graph/graph-extraction.js +340 -562
- package/dist/indexer/graph/graph-related.js +130 -0
- package/dist/indexer/index-rebuild-lock.js +3 -11
- package/dist/indexer/index-writer-lock.js +8 -17
- package/dist/indexer/index-written-assets.js +139 -151
- package/dist/indexer/indexer.js +524 -846
- package/dist/indexer/materialize-embeddings.js +60 -397
- package/dist/indexer/passes/memory-inference.js +81 -90
- package/dist/indexer/passes/metadata.js +132 -200
- package/dist/indexer/read-preflight.js +0 -7
- package/dist/indexer/scan/doc-to-entry.js +1 -3
- package/dist/indexer/scan/drain-dir.js +1 -1
- package/dist/indexer/search/db-search.js +181 -590
- package/dist/indexer/search/fts-query.js +30 -41
- package/dist/indexer/search/ranking.js +28 -154
- package/dist/indexer/search/search-attribution.js +12 -32
- package/dist/indexer/search/search-fields.js +11 -15
- package/dist/indexer/search/search-hit-enrichers.js +54 -85
- package/dist/indexer/search/search-source.js +1 -4
- package/dist/indexer/usage/usage-events.js +2 -7
- package/dist/integrations/agent/engine-fallback.js +23 -40
- package/dist/integrations/agent/engine-resolution.js +93 -183
- package/dist/integrations/agent/execution.js +507 -0
- package/dist/integrations/agent/model-map.js +28 -156
- package/dist/integrations/agent/request-lowering.js +66 -141
- package/dist/integrations/agent/runner-dispatch.js +143 -321
- package/dist/integrations/agent/runner.js +54 -14
- package/dist/integrations/lockfile.js +53 -101
- package/dist/llm/embedders/deterministic.js +2 -3
- package/dist/llm/embedders/profile.js +71 -0
- package/dist/llm/embedders/remote.js +10 -15
- package/dist/llm/graph-extract.js +3 -12
- package/dist/llm/index-passes.js +3 -5
- package/dist/llm/memory-infer.js +1 -2
- package/dist/llm/metadata-enhance.js +1 -2
- package/dist/llm/structured-call.js +5 -24
- package/dist/output/generic-render.js +23 -11
- package/dist/output/html-render.js +13 -10
- package/dist/output/render-registry.js +3 -32
- package/dist/output/shapes/helpers.js +2 -34
- package/dist/output/shapes/passthrough.js +1 -9
- package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
- package/dist/output/text/command-format.js +60 -23
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +5 -14
- package/dist/output/text/proposal-format.js +1 -2
- package/dist/output/text/workflow-format.js +0 -32
- package/dist/output/text.js +2 -0
- package/dist/registry/factory.js +4 -19
- package/dist/registry/network.js +66 -220
- package/dist/registry/providers/index.js +0 -2
- package/dist/registry/providers/skills-sh.js +3 -14
- package/dist/registry/providers/static-index.js +24 -26
- package/dist/registry/resolve.js +55 -131
- package/dist/scripts/akm-migrate-node.js +43937 -93313
- package/dist/scripts/akm-migrate.js +43697 -93071
- package/dist/setup/registry-stash-loader.js +4 -13
- package/dist/setup/semantic-assets.js +3 -44
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/tasks.js +25 -15
- package/dist/sources/provider-factory.js +17 -18
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +7 -1
- package/dist/sources/providers/git-provider.js +0 -3
- package/dist/sources/providers/git-stash.js +0 -17
- package/dist/sources/providers/npm.js +2 -4
- package/dist/sources/providers/provider-utils.js +5 -10
- package/dist/sources/providers/website.js +0 -2
- package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
- package/dist/sources/website-url.js +2 -2
- package/dist/storage/database.js +9 -35
- package/dist/storage/repositories/improve-ledger-repository.js +168 -0
- package/dist/storage/repositories/index-connection.js +34 -70
- package/dist/storage/repositories/index-entries-repository.js +69 -111
- package/dist/storage/repositories/index-entry-mapper.js +1 -2
- package/dist/storage/repositories/index-entry-schema.js +83 -269
- package/dist/storage/repositories/index-fts-repository.js +86 -256
- package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
- package/dist/storage/repositories/index-meta-repository.js +6 -4
- package/dist/storage/repositories/index-schema.js +192 -220
- package/dist/storage/repositories/index-utility-repository.js +8 -29
- package/dist/storage/repositories/index-vec-repository.js +133 -414
- package/dist/storage/repositories/outcome-repository.js +2 -1
- package/dist/storage/repositories/proposals-repository.js +35 -0
- package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
- package/dist/storage/repositories/task-history-repository.js +26 -4
- package/dist/storage/repositories/workflow-runs-repository.js +53 -244
- package/dist/storage/sqlite-migrations.js +136 -0
- package/dist/storage/sqlite-pragmas.js +11 -9
- package/dist/storage/sqlite-transaction.js +170 -0
- package/dist/storage/state-db-integrity.js +34 -27
- package/dist/tasks/activation-config.js +134 -62
- package/dist/tasks/backends/cron.js +129 -277
- package/dist/tasks/backends/exec-utils.js +2 -5
- package/dist/tasks/backends/launchd.js +125 -745
- package/dist/tasks/backends/schtasks.js +101 -620
- package/dist/tasks/prepare/prepare-support.js +5 -15
- package/dist/tasks/prepare/prepare.js +0 -2
- package/dist/tasks/resolve-akm-bin.js +20 -79
- package/dist/tasks/run/attempt-lifecycle.js +0 -1
- package/dist/tasks/scheduler-binding.js +18 -238
- package/dist/tasks/scheduler-invocation.js +52 -52
- package/dist/tasks/scheduler-lock.js +53 -0
- package/dist/tasks/scheduler-sync.js +363 -679
- package/dist/tasks/source/parse-task-source.js +160 -10
- package/dist/tasks/source/task-source-v3-frozen.js +3 -4
- package/dist/tasks/source/task-to-v4.js +2 -2
- package/dist/workflows/authoring/authoring.js +3 -12
- package/dist/workflows/compile.js +211 -0
- package/dist/workflows/concurrency-policy.js +13 -74
- package/dist/workflows/exec/child-invocation.js +3 -17
- package/dist/workflows/exec/child-workflow.js +32 -141
- package/dist/workflows/exec/dispatch-redaction.js +13 -53
- package/dist/workflows/exec/environment.js +98 -0
- package/dist/workflows/exec/exec-unit.js +33 -140
- package/dist/workflows/exec/frozen-judge.js +7 -59
- package/dist/workflows/exec/native-executor.js +82 -341
- package/dist/workflows/exec/param-secrets.js +29 -47
- package/dist/workflows/exec/run-workflow.js +154 -387
- package/dist/workflows/exec/scheduler.js +9 -36
- package/dist/workflows/exec/step-work.js +127 -430
- package/dist/workflows/exec/unit-dispatch.js +11 -63
- package/dist/workflows/exec/unit-writer.js +8 -52
- package/dist/workflows/exec/worktree.js +39 -273
- package/dist/workflows/freeze/child-output-references.js +4 -15
- package/dist/workflows/freeze/environment.js +99 -92
- package/dist/workflows/freeze/freeze.js +172 -0
- package/dist/workflows/freeze/step-values.js +19 -21
- package/dist/workflows/freeze/targets/child-workflow.js +23 -92
- package/dist/workflows/freeze/targets/command.js +10 -33
- package/dist/workflows/freeze/targets/script.js +5 -12
- package/dist/workflows/freeze/targets/shell.js +3 -6
- package/dist/workflows/freeze/targets/task.js +25 -80
- package/dist/workflows/freeze/task-bindings.js +20 -67
- package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
- package/dist/workflows/ir/params.js +6 -51
- package/dist/workflows/ir/plan-hash.js +2 -34
- package/dist/workflows/parser.js +140 -43
- package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
- package/dist/workflows/renderer.js +36 -69
- package/dist/workflows/resource-limits.js +12 -120
- package/dist/workflows/runtime/agent-identity.js +8 -40
- package/dist/workflows/runtime/run-outputs.js +3 -6
- package/dist/workflows/runtime/run-plan.js +316 -0
- package/dist/workflows/runtime/runs.js +48 -200
- package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
- package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/integration/bundling-akm.md +49 -42
- package/docs/migration/README.md +1 -0
- package/docs/migration/release-notes/0.9.17.md +41 -0
- package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
- package/docs/reference/cli.md +182 -125
- package/docs/reference/configuration.md +49 -56
- package/docs/reference/data-and-telemetry.md +19 -20
- package/docs/reference/tasks.md +86 -38
- package/docs/reference/workflow-schema.md +14 -18
- package/docs/reference/workflows.md +6 -9
- package/package.json +1 -1
- package/schemas/akm-config.json +87 -406
- package/dist/commands/health/advisories.js +0 -150
- package/dist/commands/health/metrics.js +0 -329
- package/dist/commands/health/surfaces.js +0 -102
- package/dist/commands/improve/anti-collapse.js +0 -83
- package/dist/commands/improve/collapse-detector.js +0 -432
- package/dist/commands/improve/consolidate/eligibility.js +0 -48
- package/dist/commands/improve/consolidate/merge.js +0 -146
- package/dist/commands/improve/distill/promote-memory.js +0 -329
- package/dist/commands/improve/distill/quality-gate.js +0 -500
- package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
- package/dist/commands/improve/proposal-envelope.js +0 -31
- package/dist/commands/improve/run-context.js +0 -123
- package/dist/commands/improve/shared.js +0 -21
- package/dist/commands/improve/source-identity.js +0 -28
- package/dist/commands/improve/triage.js +0 -96
- package/dist/commands/proposal/drain-policies.js +0 -151
- package/dist/commands/sources/update-transaction.js +0 -220
- package/dist/core/action-contributors.js +0 -28
- package/dist/core/config/config-version-shim.js +0 -101
- package/dist/core/config/retired-experimental-keys-shim.js +0 -62
- package/dist/core/fs-txn.js +0 -405
- package/dist/core/lexical-score.js +0 -25
- package/dist/core/maintenance-barrier.js +0 -167
- package/dist/execution/executable-identity.js +0 -105
- package/dist/execution/guarded-source.js +0 -427
- package/dist/indexer/graph/graph-boost.js +0 -427
- package/dist/indexer/graph/graph-dedup.js +0 -95
- package/dist/indexer/search/name-match.js +0 -35
- package/dist/indexer/search/ranking-contributors.js +0 -515
- package/dist/indexer/walk/project-context.js +0 -192
- package/dist/integrations/agent/execution-cascade.js +0 -566
- package/dist/integrations/agent/execution-definitions.js +0 -202
- package/dist/integrations/agent/execution-lowering.js +0 -841
- package/dist/integrations/agent/execution-preparation.js +0 -98
- package/dist/integrations/agent/inline-execution.js +0 -74
- package/dist/registry/create-provider-registry.js +0 -29
- package/dist/registry/pinned-request-helper.js +0 -247
- package/dist/registry/pinned-transport.js +0 -717
- package/dist/sources/providers/index.js +0 -14
- package/dist/storage/engines/sqlite-migrations.js +0 -271
- package/dist/storage/repositories/canaries-repository.js +0 -107
- package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
- package/dist/storage/repositories/registry-cache.js +0 -113
- package/dist/tasks/scheduler-sync-preview.js +0 -52
- package/dist/workflows/freeze/resolve-steps.js +0 -86
- package/dist/workflows/freeze/source-freeze.js +0 -64
- package/dist/workflows/ir/compile.js +0 -321
- package/dist/workflows/ir/environment-v4.js +0 -330
- package/dist/workflows/ir/freeze-v4.js +0 -153
- package/dist/workflows/ir/schema-v4.js +0 -745
- package/dist/workflows/ir/schema.js +0 -354
- package/dist/workflows/program/schema.js +0 -78
- package/dist/workflows/runtime/checkin.js +0 -57
- package/dist/workflows/runtime/plan-classifier.js +0 -196
- package/dist/workflows/runtime/unit-checkin.js +0 -45
- package/dist/workflows/runtime/unit-phases.js +0 -20
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/source-ir/compile.js +0 -200
- package/dist/workflows/source-ir/program.js +0 -50
- package/dist/workflows/source-ir/result.js +0 -26
- package/dist/workflows/source-ir/schema.js +0 -786
- package/dist/workflows/source-ir/triggers.js +0 -79
- package/dist/workflows/source-ir/uses.js +0 -40
- package/dist/workflows/validator.js +0 -60
|
@@ -18,11 +18,20 @@ import { getStateDbPath, withStateDb } from "../../core/state-db.js";
|
|
|
18
18
|
import { warn } from "../../core/warn.js";
|
|
19
19
|
import { getMarkdownFragmentContent, hasMarkdownFragmentContent, } from "../../indexer/passes/metadata.js";
|
|
20
20
|
import { buildSearchText } from "../../indexer/search/search-fields.js";
|
|
21
|
+
import { sha256Hex } from "../../runtime.js";
|
|
21
22
|
import { ENTRY_COLUMNS, rowToIndexedEntry } from "./index-entry-mapper.js";
|
|
22
23
|
import { deleteFtsEntries, replaceFtsEntry } from "./index-fts-repository.js";
|
|
23
24
|
import { SQLITE_CHUNK_SIZE } from "./index-sql.js";
|
|
24
|
-
import { deleteEntryVectors
|
|
25
|
+
import { deleteEntryVectors } from "./index-vec-repository.js";
|
|
25
26
|
// ── Entry operations ────────────────────────────────────────────────────────
|
|
27
|
+
/**
|
|
28
|
+
* Hash of the text an entry's vector is embedded from (`buildSearchText`),
|
|
29
|
+
* stored as `entries.embed_hash`: a change deletes the entry's vector, and the
|
|
30
|
+
* next embedding pass re-embeds it.
|
|
31
|
+
*/
|
|
32
|
+
function embedHash(entry) {
|
|
33
|
+
return sha256Hex(buildSearchText(entry));
|
|
34
|
+
}
|
|
26
35
|
/**
|
|
27
36
|
* Insert or update one canonical entry and all synchronously derived search
|
|
28
37
|
* state. Returns the stable row id.
|
|
@@ -31,7 +40,7 @@ import { deleteEntryVectors, isVecAvailable } from "./index-vec-repository.js";
|
|
|
31
40
|
* SQLite transaction. Callers therefore cannot publish an entry and forget a
|
|
32
41
|
* second FTS maintenance step.
|
|
33
42
|
*/
|
|
34
|
-
export function upsertEntry(db, filePath, entry,
|
|
43
|
+
export function upsertEntry(db, filePath, entry, provenance, contentHash) {
|
|
35
44
|
// Hot path during indexing — cache prepared statements per database
|
|
36
45
|
// connection so we don't pay the SQL parse/compile cost on every call.
|
|
37
46
|
const stmts = getUpsertStmts(db);
|
|
@@ -39,14 +48,15 @@ export function upsertEntry(db, filePath, entry, searchText, provenance, content
|
|
|
39
48
|
// dedicated `derived_from` column so retrieval-time lookup (parent→child)
|
|
40
49
|
// does not have to scan + JSON-decode every memory row.
|
|
41
50
|
const derivedFrom = typeof entry.derivedFrom === "string" && entry.derivedFrom.trim() ? entry.derivedFrom.trim() : null;
|
|
51
|
+
const hash = embedHash(entry);
|
|
42
52
|
// `content_hash` is optional on the LLM-enrichment re-upsert; a missing hash
|
|
43
53
|
// preserves the scan writer's current value.
|
|
44
54
|
const apply = () => {
|
|
45
55
|
const previous = stmts.findByItemRef.get(provenance.itemRef);
|
|
46
|
-
const result = stmts.upsert.get(provenance.itemRef, provenance.bundleId, provenance.componentId, provenance.conceptId, provenance.adapterId, entry.type, filePath, contentHash ?? null, JSON.stringify(entry),
|
|
56
|
+
const result = stmts.upsert.get(provenance.itemRef, provenance.bundleId, provenance.componentId, provenance.conceptId, provenance.adapterId, entry.type, filePath, contentHash ?? null, JSON.stringify(entry), derivedFrom, hash);
|
|
47
57
|
if (!result)
|
|
48
58
|
throw new Error("upsertEntry: item_ref not found after upsert");
|
|
49
|
-
if (previous?.id === result.id && previous.
|
|
59
|
+
if (previous?.id === result.id && previous.embed_hash !== hash)
|
|
50
60
|
deleteEntryVectors(db, result.id);
|
|
51
61
|
replaceFtsEntry(db, result.id, entry, hasMarkdownFragmentContent(entry) ? (getMarkdownFragmentContent(entry) ?? null) : undefined);
|
|
52
62
|
return result.id;
|
|
@@ -68,8 +78,8 @@ const UPSERT_SET_CLAUSE = `SET
|
|
|
68
78
|
type = excluded.type,
|
|
69
79
|
file_path = excluded.file_path,
|
|
70
80
|
document_json = excluded.document_json,
|
|
71
|
-
search_text = excluded.search_text,
|
|
72
81
|
derived_from = excluded.derived_from,
|
|
82
|
+
embed_hash = excluded.embed_hash,
|
|
73
83
|
content_hash = COALESCE(excluded.content_hash, content_hash)`;
|
|
74
84
|
function getUpsertStmts(db) {
|
|
75
85
|
const existing = upsertStmtsByDb.get(db);
|
|
@@ -82,13 +92,13 @@ function getUpsertStmts(db) {
|
|
|
82
92
|
upsert: db.prepare(`
|
|
83
93
|
INSERT INTO entries (
|
|
84
94
|
item_ref, bundle_id, component_id, concept_id, adapter_id, type,
|
|
85
|
-
file_path, content_hash, document_json,
|
|
95
|
+
file_path, content_hash, document_json, derived_from, embed_hash
|
|
86
96
|
)
|
|
87
97
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
88
98
|
ON CONFLICT(item_ref) DO UPDATE ${UPSERT_SET_CLAUSE}
|
|
89
99
|
RETURNING id
|
|
90
100
|
`),
|
|
91
|
-
findByItemRef: db.prepare("SELECT id,
|
|
101
|
+
findByItemRef: db.prepare("SELECT id, embed_hash FROM entries WHERE item_ref = ?"),
|
|
92
102
|
};
|
|
93
103
|
upsertStmtsByDb.set(db, stmts);
|
|
94
104
|
return stmts;
|
|
@@ -171,7 +181,7 @@ export function getBaseBeliefStatesForDerivedTwins(db, twinIds) {
|
|
|
171
181
|
* rename. (`asset_salience` / `asset_outcome` live in state.db keyed by
|
|
172
182
|
* `asset_ref` TEXT and are re-keyed separately by `akm mv` — see
|
|
173
183
|
* the state rekey helper.) `document_json.name` (and `filename`, when
|
|
174
|
-
* present) is patched and `
|
|
184
|
+
* present) is patched and `embed_hash` recomputed so search reflects the new
|
|
175
185
|
* name. Its FTS projection and stale vector are updated in the same
|
|
176
186
|
* transaction as the canonical identity.
|
|
177
187
|
*
|
|
@@ -187,7 +197,7 @@ export function getBaseBeliefStatesForDerivedTwins(db, twinIds) {
|
|
|
187
197
|
* A stale row already occupying the new item ref (the caller has verified no
|
|
188
198
|
* FILE exists at the target, so such a row can only be a leftover for a
|
|
189
199
|
* deleted file) is evicted first — through {@link deleteRelatedRows}, so its
|
|
190
|
-
* child rows (embeddings,
|
|
200
|
+
* child rows (embeddings, utility scores, usage events) go with
|
|
191
201
|
* it. A bare `DELETE FROM entries` would trip the non-CASCADE `embeddings`
|
|
192
202
|
* FK under `PRAGMA foreign_keys = ON` and roll back the whole re-key.
|
|
193
203
|
* The moved row keeps its id.
|
|
@@ -199,7 +209,7 @@ export function getBaseBeliefStatesForDerivedTwins(db, twinIds) {
|
|
|
199
209
|
export function rekeyEntryInPlace(db, opts) {
|
|
200
210
|
const oldItemRef = `${opts.sourceName}//${opts.oldRef}`;
|
|
201
211
|
const row = db
|
|
202
|
-
.prepare("SELECT id, file_path, document_json,
|
|
212
|
+
.prepare("SELECT id, file_path, document_json, embed_hash, type FROM entries WHERE item_ref = ?")
|
|
203
213
|
.get(oldItemRef);
|
|
204
214
|
if (!row)
|
|
205
215
|
return null;
|
|
@@ -211,7 +221,7 @@ export function rekeyEntryInPlace(db, opts) {
|
|
|
211
221
|
// Patch the JSON payload. On corrupt document_json still re-key identity/path so
|
|
212
222
|
// the utility history survives; the next full index heals the JSON.
|
|
213
223
|
let documentJson = row.document_json;
|
|
214
|
-
let
|
|
224
|
+
let hash = row.embed_hash;
|
|
215
225
|
let document;
|
|
216
226
|
try {
|
|
217
227
|
const entry = JSON.parse(row.document_json);
|
|
@@ -221,7 +231,7 @@ export function rekeyEntryInPlace(db, opts) {
|
|
|
221
231
|
if (opts.newDerivedFrom !== undefined)
|
|
222
232
|
entry.derivedFrom = opts.newDerivedFrom;
|
|
223
233
|
documentJson = JSON.stringify(entry);
|
|
224
|
-
|
|
234
|
+
hash = embedHash(entry);
|
|
225
235
|
document = entry;
|
|
226
236
|
}
|
|
227
237
|
catch {
|
|
@@ -235,7 +245,7 @@ export function rekeyEntryInPlace(db, opts) {
|
|
|
235
245
|
db.transaction(() => {
|
|
236
246
|
const stale = db.prepare("SELECT id FROM entries WHERE item_ref = ?").get(newItemRef);
|
|
237
247
|
if (stale && stale.id !== row.id) {
|
|
238
|
-
// Full child-row cleanup (embeddings,
|
|
248
|
+
// Full child-row cleanup (embeddings, utility scores,
|
|
239
249
|
// usage events, FTS + dirty marks) BEFORE the entries delete: the
|
|
240
250
|
// `embeddings` FK is non-CASCADE and `foreign_keys = ON`, so a bare
|
|
241
251
|
// entries delete would throw and roll back the entire re-key; and
|
|
@@ -243,11 +253,11 @@ export function rekeyEntryInPlace(db, opts) {
|
|
|
243
253
|
deleteRelatedRows(db, [{ id: stale.id }]);
|
|
244
254
|
db.prepare("DELETE FROM entries WHERE id = ?").run(stale.id);
|
|
245
255
|
}
|
|
246
|
-
db.prepare("UPDATE entries SET file_path = ?, document_json = ?,
|
|
256
|
+
db.prepare("UPDATE entries SET file_path = ?, document_json = ?, embed_hash = ?, item_ref = ?, concept_id = ? WHERE id = ?").run(opts.newFilePath, documentJson, hash, newItemRef, opts.newRef, row.id);
|
|
247
257
|
if (opts.newDerivedFrom !== undefined) {
|
|
248
258
|
db.prepare("UPDATE entries SET derived_from = ? WHERE id = ?").run(opts.newDerivedFrom, row.id);
|
|
249
259
|
}
|
|
250
|
-
if (row.
|
|
260
|
+
if (row.embed_hash !== hash)
|
|
251
261
|
deleteEntryVectors(db, row.id);
|
|
252
262
|
if (document)
|
|
253
263
|
replaceFtsEntry(db, row.id, document, hasMarkdownFragmentContent(document) ? (getMarkdownFragmentContent(document) ?? null) : undefined);
|
|
@@ -293,50 +303,6 @@ function rewriteUsageEventRefForMove(opts) {
|
|
|
293
303
|
throw new Error(`Failed to rewrite usage events for move: ${message}`, { cause: error });
|
|
294
304
|
}
|
|
295
305
|
}
|
|
296
|
-
/**
|
|
297
|
-
* Phase 2A / Rec 5: bulk-load positive feedback event counts for the given
|
|
298
|
-
* entry ids. Used by the utility-decay forgetting curve to stabilize
|
|
299
|
-
* (extend the half-life of) memories that have repeatedly proven useful.
|
|
300
|
-
*
|
|
301
|
-
* Returns a `Map<entryId, count>` containing only entries with at least one
|
|
302
|
-
* positive feedback event — missing ids implicitly map to `0`. Chunks at
|
|
303
|
-
* `SQLITE_CHUNK_SIZE` (500) to respect `SQLITE_MAX_VARIABLE_NUMBER`.
|
|
304
|
-
*
|
|
305
|
-
* Cheap when called with zero ids, and silently empty when state.db (or its
|
|
306
|
-
* `usage_events` table) is absent.
|
|
307
|
-
*
|
|
308
|
-
* Chunk-8 WI-8.3: usage_events lives in state.db — this reads it there (no
|
|
309
|
-
* entries join needed; the ids are supplied by the caller). Gated by the caller
|
|
310
|
-
* (`shouldQueryPositiveFeedbackCounts`) so the state.db open is not on the
|
|
311
|
-
* default search hot path.
|
|
312
|
-
*/
|
|
313
|
-
export function getPositiveFeedbackCountsByIds(ids) {
|
|
314
|
-
const result = new Map();
|
|
315
|
-
if (ids.length === 0 || !fs.existsSync(getStateDbPath()))
|
|
316
|
-
return result;
|
|
317
|
-
bestEffort(() => {
|
|
318
|
-
withStateDb((stateDb) => {
|
|
319
|
-
for (let i = 0; i < ids.length; i += SQLITE_CHUNK_SIZE) {
|
|
320
|
-
const chunk = ids.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
321
|
-
const placeholders = chunk.map(() => "?").join(",");
|
|
322
|
-
const rows = stateDb
|
|
323
|
-
.prepare(`SELECT entry_id, COUNT(*) AS cnt
|
|
324
|
-
FROM usage_events
|
|
325
|
-
WHERE event_type = 'feedback'
|
|
326
|
-
AND signal = 'positive'
|
|
327
|
-
AND entry_id IN (${placeholders})
|
|
328
|
-
GROUP BY entry_id`)
|
|
329
|
-
.all(...chunk);
|
|
330
|
-
for (const row of rows) {
|
|
331
|
-
if (row.entry_id !== null && row.cnt > 0) {
|
|
332
|
-
result.set(row.entry_id, row.cnt);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
}, "positive feedback counts are best-effort");
|
|
338
|
-
return result;
|
|
339
|
-
}
|
|
340
306
|
/**
|
|
341
307
|
* Rows whose `file_path` sits directly in `dirPath`. A half-open byte range
|
|
342
308
|
* over `idx_entries_file_path` (`[dir + sep, dir + sep + 1)`) turns the lookup
|
|
@@ -382,14 +348,30 @@ export function deleteEntriesByBundle(db, bundleId) {
|
|
|
382
348
|
})();
|
|
383
349
|
}
|
|
384
350
|
/**
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
351
|
+
* The `file_path` of every entry indexed under one bundle — used by
|
|
352
|
+
* `akm bundle rename` (D6) to find bundle CONTENT that still spells the old
|
|
353
|
+
* `<bundle>//` prefix (xrefs, `supersededBy`, task `uses:`), which the rename
|
|
354
|
+
* reports rather than rewrites.
|
|
388
355
|
*/
|
|
389
|
-
export function
|
|
356
|
+
export function getFilePathsByBundle(db, bundleId) {
|
|
357
|
+
const rows = db.prepare("SELECT DISTINCT file_path FROM entries WHERE bundle_id = ?").all(bundleId);
|
|
358
|
+
return rows.map((row) => row.file_path);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Re-key every entry row's `bundle_id`/`item_ref` from `oldBundleId` to
|
|
362
|
+
* `newBundleId` in place (`akm bundle rename`, D6). Unlike
|
|
363
|
+
* {@link rekeyEntryInPlace} (one asset, `akm mv`), this is a bulk identity
|
|
364
|
+
* change with no content move: `concept_id`/`file_path`/`document_json` are
|
|
365
|
+
* untouched, so no FTS/vector rebuild is needed (FTS and `embeddings` key on
|
|
366
|
+
* the entry's row `id`, which this preserves, not on `item_ref`). Returns the
|
|
367
|
+
* number of rows renamed.
|
|
368
|
+
*/
|
|
369
|
+
export function renameEntriesBundleId(db, oldBundleId, newBundleId) {
|
|
390
370
|
return db.transaction(() => {
|
|
391
|
-
const
|
|
392
|
-
|
|
371
|
+
const result = db
|
|
372
|
+
.prepare("UPDATE entries SET bundle_id = ?, item_ref = ? || '//' || concept_id WHERE bundle_id = ?")
|
|
373
|
+
.run(newBundleId, newBundleId, oldBundleId);
|
|
374
|
+
return Number(result.changes);
|
|
393
375
|
})();
|
|
394
376
|
}
|
|
395
377
|
/**
|
|
@@ -415,7 +397,6 @@ function deleteRelatedRows(db, ids, options = {}) {
|
|
|
415
397
|
if (ids.length === 0)
|
|
416
398
|
return;
|
|
417
399
|
const numericIds = ids.map((r) => r.id);
|
|
418
|
-
const vecAvail = isVecAvailable(db);
|
|
419
400
|
// FTS is part of the canonical mutation boundary, not a caller-maintained
|
|
420
401
|
// dirty queue. Delete it before the parent row inside this transaction.
|
|
421
402
|
deleteFtsEntries(db, numericIds);
|
|
@@ -424,47 +405,18 @@ function deleteRelatedRows(db, ids, options = {}) {
|
|
|
424
405
|
const chunk = numericIds.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
425
406
|
const placeholders = chunk.map(() => "?").join(",");
|
|
426
407
|
bestEffort(() => db.prepare(`DELETE FROM embeddings WHERE id IN (${placeholders})`).run(...chunk), "delete embeddings for entries");
|
|
427
|
-
if (vecAvail) {
|
|
428
|
-
bestEffort(() => db.prepare(`DELETE FROM entries_vec WHERE id IN (${placeholders})`).run(...chunk), "delete entries_vec for entries");
|
|
429
|
-
}
|
|
430
408
|
// Clean up utility scores before deleting entries
|
|
431
409
|
bestEffort(() => db.prepare(`DELETE FROM utility_scores WHERE entry_id IN (${placeholders})`).run(...chunk), "delete utility_scores for entries");
|
|
432
410
|
bestEffort(() => db.prepare(`DELETE FROM utility_scores_scoped WHERE entry_id IN (${placeholders})`).run(...chunk), "delete utility_scores_scoped for entries");
|
|
433
411
|
}
|
|
434
|
-
// Graph rows are independently keyed and intentionally survive entry
|
|
435
|
-
// deletion. Resolve their owning roots through the canonical physical path
|
|
436
|
-
// before entries disappear, then refresh the derived summary counts.
|
|
437
|
-
const affectedGraphRoots = new Set();
|
|
438
|
-
for (let i = 0; i < numericIds.length; i += SQLITE_CHUNK_SIZE) {
|
|
439
|
-
const chunk = numericIds.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
440
|
-
const placeholders = chunk.map(() => "?").join(",");
|
|
441
|
-
bestEffort(() => {
|
|
442
|
-
const rows = db
|
|
443
|
-
.prepare(`SELECT DISTINCT gf.stash_root
|
|
444
|
-
FROM graph_files gf
|
|
445
|
-
JOIN entries e ON e.file_path = gf.file_path
|
|
446
|
-
WHERE e.id IN (${placeholders})`)
|
|
447
|
-
.all(...chunk);
|
|
448
|
-
for (const row of rows)
|
|
449
|
-
affectedGraphRoots.add(row.stash_root);
|
|
450
|
-
}, "resolve graph roots for graph_meta recompute");
|
|
451
|
-
}
|
|
452
|
-
for (const stashRoot of affectedGraphRoots) {
|
|
453
|
-
bestEffort(() => db
|
|
454
|
-
.prepare(`UPDATE graph_meta
|
|
455
|
-
SET extracted_files = (SELECT COUNT(*) FROM graph_files WHERE stash_root = ?),
|
|
456
|
-
entity_count = (SELECT COUNT(*) FROM graph_file_entities WHERE stash_root = ?),
|
|
457
|
-
relation_count = (SELECT COUNT(*) FROM graph_file_relations WHERE stash_root = ?)
|
|
458
|
-
WHERE stash_root = ?`)
|
|
459
|
-
.run(stashRoot, stashRoot, stashRoot, stashRoot), "sync graph_meta counts after entries delete");
|
|
460
|
-
}
|
|
461
412
|
// usage_events lives in state.db, outside this transaction. Index persistence
|
|
462
413
|
// disables this cleanup and runs it only after its index.db transaction
|
|
463
414
|
// commits; standalone delete callers retain the immediate behavior.
|
|
464
415
|
if (options.cleanupUsageEvents !== false)
|
|
465
416
|
deleteUsageEventsByEntryIds(numericIds);
|
|
466
417
|
// graph_files is keyed by its own stash_root/file_path/body_hash identity,
|
|
467
|
-
// so deleting an entry row intentionally leaves extracted graph data intact
|
|
418
|
+
// so deleting an entry row intentionally leaves extracted graph data intact,
|
|
419
|
+
// and with it the graph_meta counts the graph writer derives from those rows.
|
|
468
420
|
}
|
|
469
421
|
export function deleteUsageEventsByEntryIds(entryIds) {
|
|
470
422
|
if (entryIds.length === 0 || !fs.existsSync(getStateDbPath()))
|
|
@@ -481,7 +433,7 @@ export function deleteUsageEventsByEntryIds(entryIds) {
|
|
|
481
433
|
}
|
|
482
434
|
/**
|
|
483
435
|
* Delete entries by their primary key IDs, along with all related rows
|
|
484
|
-
* (embeddings,
|
|
436
|
+
* (embeddings, entries_fts, utility scores, usage_events).
|
|
485
437
|
*
|
|
486
438
|
* Used by explicit `--clean` reconciliation before embeddings and final
|
|
487
439
|
* verification to remove stale entries whose source files no longer exist.
|
|
@@ -645,6 +597,20 @@ export function getEntryById(db, id) {
|
|
|
645
597
|
adapterId: row.adapter_id,
|
|
646
598
|
};
|
|
647
599
|
}
|
|
600
|
+
/** The `item_ref` and `type` of every id that has an entry row. */
|
|
601
|
+
export function getEntryRefsAndTypes(db, ids) {
|
|
602
|
+
const out = new Map();
|
|
603
|
+
for (let i = 0; i < ids.length; i += SQLITE_CHUNK_SIZE) {
|
|
604
|
+
const chunk = ids.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
605
|
+
const placeholders = chunk.map(() => "?").join(",");
|
|
606
|
+
const rows = db
|
|
607
|
+
.prepare(`SELECT id, item_ref, type FROM entries WHERE id IN (${placeholders})`)
|
|
608
|
+
.all(...chunk);
|
|
609
|
+
for (const row of rows)
|
|
610
|
+
out.set(row.id, { itemRef: row.item_ref, type: row.type });
|
|
611
|
+
}
|
|
612
|
+
return out;
|
|
613
|
+
}
|
|
648
614
|
export function getEntriesByDir(db, dirPath) {
|
|
649
615
|
return parseEntryRows(selectRowsInDirectory(db, dirPath, ENTRY_COLUMNS), "getEntriesByDir");
|
|
650
616
|
}
|
|
@@ -809,15 +775,7 @@ function resolveUsageEventEntryId(db, ref) {
|
|
|
809
775
|
* distinct linked entry_ids in usage_events is small — and the re-resolution
|
|
810
776
|
* reads `entries` from `indexDb`.
|
|
811
777
|
*/
|
|
812
|
-
function
|
|
813
|
-
if (stateSchema === undefined)
|
|
814
|
-
return "usage_events";
|
|
815
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(stateSchema))
|
|
816
|
-
throw new Error("Invalid attached state schema name.");
|
|
817
|
-
return `"${stateSchema}".usage_events`;
|
|
818
|
-
}
|
|
819
|
-
export function relinkUsageEvents(indexDb, stateDb, options = {}) {
|
|
820
|
-
const usageEvents = qualifiedUsageEventsTable(options.stateSchema);
|
|
778
|
+
export function relinkUsageEvents(indexDb, stateDb) {
|
|
821
779
|
bestEffort(() => {
|
|
822
780
|
// Step 1: null out stale entry_ids (entry was deleted, re-keyed, etc).
|
|
823
781
|
// Leaving them in place would let `recomputeUtilityScores` aggregate by an
|
|
@@ -826,7 +784,7 @@ export function relinkUsageEvents(indexDb, stateDb, options = {}) {
|
|
|
826
784
|
// transaction. Nulled rows can be re-resolved by step 2 below; events whose
|
|
827
785
|
// entry is permanently gone simply stay null and age out via retention.
|
|
828
786
|
const linkedRows = stateDb
|
|
829
|
-
.prepare(
|
|
787
|
+
.prepare("SELECT DISTINCT entry_id AS id, entry_ref AS ref FROM usage_events WHERE entry_id IS NOT NULL")
|
|
830
788
|
.all();
|
|
831
789
|
const entryIdentity = indexDb.prepare("SELECT item_ref AS itemRef FROM entries WHERE id = ?");
|
|
832
790
|
const staleLinks = linkedRows.filter(({ id, ref }) => {
|
|
@@ -834,7 +792,7 @@ export function relinkUsageEvents(indexDb, stateDb, options = {}) {
|
|
|
834
792
|
return live == null || (ref !== null && live.itemRef !== ref);
|
|
835
793
|
});
|
|
836
794
|
if (staleLinks.length > 0) {
|
|
837
|
-
const nullOut = stateDb.prepare(
|
|
795
|
+
const nullOut = stateDb.prepare("UPDATE usage_events SET entry_id = NULL WHERE entry_id = ? AND entry_ref IS ?");
|
|
838
796
|
const nullTx = stateDb.transaction(() => {
|
|
839
797
|
for (const { id, ref } of staleLinks)
|
|
840
798
|
nullOut.run(id, ref);
|
|
@@ -844,9 +802,9 @@ export function relinkUsageEvents(indexDb, stateDb, options = {}) {
|
|
|
844
802
|
// Step 2: re-resolve each fully-qualified ref. Bare rows are not current
|
|
845
803
|
// durable identities and remain detached.
|
|
846
804
|
const refs = stateDb
|
|
847
|
-
.prepare(
|
|
805
|
+
.prepare("SELECT DISTINCT entry_ref AS ref FROM usage_events WHERE entry_id IS NULL AND entry_ref IS NOT NULL")
|
|
848
806
|
.all();
|
|
849
|
-
const update = stateDb.prepare(
|
|
807
|
+
const update = stateDb.prepare("UPDATE usage_events SET entry_id = ? WHERE entry_ref = ? AND entry_id IS NULL");
|
|
850
808
|
const relinkTx = stateDb.transaction(() => {
|
|
851
809
|
for (const { ref } of refs) {
|
|
852
810
|
let id;
|
|
@@ -23,7 +23,7 @@ import { warn } from "../../core/warn.js";
|
|
|
23
23
|
* Durable identity columns are surfaced here so every mapped entry carries
|
|
24
24
|
* current indexed provenance.
|
|
25
25
|
*/
|
|
26
|
-
export const ENTRY_COLUMNS = "id, item_ref, bundle_id, component_id, concept_id, adapter_id, type, file_path, content_hash, document_json
|
|
26
|
+
export const ENTRY_COLUMNS = "id, item_ref, bundle_id, component_id, concept_id, adapter_id, type, file_path, content_hash, document_json";
|
|
27
27
|
/**
|
|
28
28
|
* Map one raw `entries` row to a {@link DbIndexedEntry}, parsing `document_json`.
|
|
29
29
|
* Returns `null` (and warns, tagged with `context`) when the JSON is corrupt so
|
|
@@ -42,7 +42,6 @@ export function rowToIndexedEntry(row, context) {
|
|
|
42
42
|
id: row.id,
|
|
43
43
|
filePath: row.file_path,
|
|
44
44
|
entry,
|
|
45
|
-
searchText: row.search_text,
|
|
46
45
|
itemRef: row.item_ref,
|
|
47
46
|
conceptId: row.concept_id,
|
|
48
47
|
bundleId: row.bundle_id,
|