akm-cli 0.8.1 → 0.9.0-beta.0
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 +258 -0
- package/dist/assets/help/help-proposals.md +1 -2
- package/dist/assets/hints/cli-hints-full.md +34 -19
- package/dist/assets/hints/cli-hints-short.md +1 -1
- package/dist/assets/profiles/catchup.json +13 -0
- package/dist/assets/profiles/consolidate.json +13 -0
- package/dist/assets/profiles/frequent.json +13 -0
- package/dist/assets/stash-skeleton/README.md +76 -0
- package/dist/assets/tasks/core/backup.yml +4 -0
- package/dist/assets/tasks/core/extract.yml +4 -0
- package/dist/assets/tasks/core/improve.yml +4 -0
- package/dist/assets/tasks/core/index-refresh.yml +4 -0
- package/dist/assets/tasks/core/sync.yml +4 -0
- package/dist/assets/tasks/core/update-stashes.yml +4 -0
- package/dist/assets/tasks/core/version-check.yml +4 -0
- package/dist/cli/config-migrate.js +6 -6
- package/dist/cli/config-validate.js +4 -4
- package/dist/cli/confirm.js +3 -3
- package/dist/cli/parse-args.js +1 -1
- package/dist/cli/shared.js +51 -14
- package/dist/cli-node.mjs +26 -0
- package/dist/cli.js +171 -3857
- package/dist/commands/{agent-dispatch.js → agent/agent-dispatch.js} +6 -6
- package/dist/commands/{agent-support.js → agent/agent-support.js} +2 -2
- package/dist/commands/agent/contribute-cli.js +200 -0
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +240 -3
- package/dist/commands/config-edit.js +344 -0
- package/dist/commands/db-cli.js +2 -2
- package/dist/commands/env/env-cli.js +529 -0
- package/dist/commands/env/env.js +410 -0
- package/dist/commands/env/secret-cli.js +259 -0
- package/dist/commands/{secret.js → env/secret.js} +6 -47
- package/dist/commands/events.js +4 -4
- package/dist/commands/feedback-cli.js +18 -34
- package/dist/commands/graph/graph-cli.js +132 -0
- package/dist/commands/{graph.js → graph/graph.js} +22 -16
- package/dist/commands/health/checks.js +279 -0
- package/dist/commands/health.js +101 -249
- package/dist/commands/{consolidate.js → improve/consolidate.js} +52 -40
- package/dist/commands/{distill-promotion-policy.js → improve/distill-promotion-policy.js} +3 -3
- package/dist/commands/{distill.js → improve/distill.js} +39 -18
- package/dist/commands/{eval-cases.js → improve/eval-cases.js} +1 -1
- package/dist/commands/{extract-cli.js → improve/extract-cli.js} +4 -4
- package/dist/commands/{extract-prompt.js → improve/extract-prompt.js} +2 -2
- package/dist/commands/{extract.js → improve/extract.js} +185 -26
- package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +4 -4
- package/dist/commands/{improve-cli.js → improve/improve-cli.js} +45 -23
- package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
- package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +10 -5
- package/dist/commands/{improve.js → improve/improve.js} +536 -248
- package/dist/{core → commands/improve/memory}/memory-belief.js +2 -2
- package/dist/{core → commands/improve/memory}/memory-contradiction-detect.js +5 -5
- package/dist/{core → commands/improve/memory}/memory-improve.js +4 -4
- package/dist/commands/{reflect.js → improve/reflect.js} +33 -28
- package/dist/commands/improve/session-asset.js +248 -0
- package/dist/commands/lint/agent-linter.js +1 -1
- package/dist/commands/lint/base-linter.js +55 -37
- package/dist/commands/lint/command-linter.js +1 -1
- package/dist/commands/lint/default-linter.js +1 -1
- package/dist/commands/lint/env-key-rules.js +1 -1
- package/dist/commands/lint/index.js +19 -25
- package/dist/commands/lint/knowledge-linter.js +1 -1
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +8 -8
- package/dist/commands/lint/skill-linter.js +1 -1
- package/dist/commands/lint/task-linter.js +1 -1
- package/dist/commands/lint/workflow-linter.js +1 -1
- package/dist/commands/lint.js +1 -1
- package/dist/commands/observability-cli.js +244 -0
- package/dist/commands/{proposal-drain-policies.js → proposal/drain-policies.js} +3 -3
- package/dist/commands/{proposal-drain.js → proposal/drain.js} +15 -10
- package/dist/commands/proposal/proposal-cli.js +478 -0
- package/dist/commands/{proposal.js → proposal/proposal.js} +5 -5
- package/dist/commands/{propose.js → proposal/propose.js} +11 -11
- package/dist/{core → commands/proposal/validators}/proposal-quality-validators.js +8 -3
- package/dist/{core → commands/proposal/validators}/proposal-validators.js +5 -5
- package/dist/{core → commands/proposal/validators}/proposals.js +13 -7
- package/dist/commands/{curate.js → read/curate.js} +7 -7
- package/dist/commands/{knowledge.js → read/knowledge.js} +22 -9
- package/dist/commands/{registry-search.js → read/registry-search.js} +5 -5
- package/dist/commands/{remember-cli.js → read/remember-cli.js} +15 -7
- package/dist/commands/read/search-cli.js +207 -0
- package/dist/commands/{search.js → read/search.js} +22 -27
- package/dist/commands/{show.js → read/show.js} +77 -44
- package/dist/commands/registry-cli.js +8 -8
- package/dist/commands/remember.js +8 -8
- package/dist/commands/sources/add-cli.js +293 -0
- package/dist/commands/{history.js → sources/history.js} +27 -25
- package/dist/commands/{info.js → sources/info.js} +6 -6
- package/dist/commands/{init.js → sources/init.js} +10 -5
- package/dist/commands/{installed-stashes.js → sources/installed-stashes.js} +12 -12
- package/dist/commands/{migration-help.js → sources/migration-help.js} +3 -2
- package/dist/commands/{schema-repair.js → sources/schema-repair.js} +8 -8
- package/dist/commands/{self-update.js → sources/self-update.js} +10 -9
- package/dist/commands/{source-add.js → sources/source-add.js} +10 -10
- package/dist/commands/{source-clone.js → sources/source-clone.js} +7 -7
- package/dist/commands/{source-manage.js → sources/source-manage.js} +4 -4
- package/dist/commands/sources/sources-cli.js +305 -0
- package/dist/commands/sources/stash-cli.js +219 -0
- package/dist/commands/sources/stash-skeleton.js +79 -0
- package/dist/commands/tasks/default-tasks.js +173 -0
- package/dist/commands/tasks/tasks-cli.js +210 -0
- package/dist/commands/{tasks.js → tasks/tasks.js} +14 -14
- package/dist/commands/wiki-cli.js +307 -0
- package/dist/commands/workflow-cli.js +329 -0
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/assert.js +40 -0
- package/dist/core/asset/asset-create.js +54 -0
- package/dist/core/{asset-ref.js → asset/asset-ref.js} +21 -4
- package/dist/core/{asset-registry.js → asset/asset-registry.js} +3 -3
- package/dist/core/{asset-spec.js → asset/asset-spec.js} +17 -31
- package/dist/core/{markdown.js → asset/markdown.js} +1 -1
- package/dist/core/asset/stash-meta.js +110 -0
- package/dist/core/best-effort.js +64 -0
- package/dist/core/common.js +32 -18
- package/dist/core/{config-io.js → config/config-io.js} +29 -19
- package/dist/core/{config-migration.js → config/config-migration.js} +11 -9
- package/dist/core/{config-schema.js → config/config-schema.js} +45 -1
- package/dist/core/config/config-types.js +16 -0
- package/dist/core/{config-walker.js → config/config-walker.js} +2 -2
- package/dist/core/{config.js → config/config.js} +10 -8
- package/dist/core/env-secret-ref.js +90 -0
- package/dist/core/errors.js +13 -3
- package/dist/core/events.js +27 -4
- package/dist/core/file-lock.js +1 -1
- package/dist/core/improve-types.js +48 -0
- package/dist/core/lesson-lint.js +2 -2
- package/dist/core/paths.js +2 -2
- package/dist/{setup/ripgrep-install.js → core/ripgrep/install.js} +2 -2
- package/dist/{setup/ripgrep-resolve.js → core/ripgrep/resolve.js} +2 -2
- package/dist/core/state-db.js +88 -46
- package/dist/core/text-truncation.js +148 -0
- package/dist/core/time.js +1 -1
- package/dist/core/write-source.js +98 -85
- package/dist/indexer/{db-backup.js → db/db-backup.js} +9 -24
- package/dist/indexer/{db.js → db/db.js} +126 -116
- package/dist/indexer/{graph-db.js → db/graph-db.js} +9 -4
- package/dist/indexer/{llm-cache.js → db/llm-cache.js} +15 -12
- package/dist/indexer/ensure-index.js +4 -4
- package/dist/indexer/{graph-boost.js → graph/graph-boost.js} +1 -1
- package/dist/indexer/{graph-extraction.js → graph/graph-extraction.js} +55 -13
- package/dist/indexer/indexer.js +37 -30
- package/dist/indexer/init.js +54 -0
- package/dist/indexer/manifest.js +10 -10
- package/dist/indexer/{memory-inference.js → passes/memory-inference.js} +92 -23
- package/dist/indexer/{metadata-contributors.js → passes/metadata-contributors.js} +10 -8
- package/dist/indexer/{metadata.js → passes/metadata.js} +15 -19
- package/dist/indexer/{staleness-detect.js → passes/staleness-detect.js} +53 -12
- package/dist/indexer/{db-search.js → search/db-search.js} +28 -16
- package/dist/indexer/{ranking-contributors.js → search/ranking-contributors.js} +1 -1
- package/dist/indexer/{ranking.js → search/ranking.js} +2 -2
- package/dist/indexer/{search-hit-enrichers.js → search/search-hit-enrichers.js} +3 -3
- package/dist/indexer/{search-source.js → search/search-source.js} +8 -8
- package/dist/indexer/{semantic-status.js → search/semantic-status.js} +3 -3
- package/dist/indexer/usage/unmigrated-vaults-guard.js +94 -0
- package/dist/indexer/{usage-events.js → usage/usage-events.js} +32 -0
- package/dist/indexer/{file-context.js → walk/file-context.js} +10 -15
- package/dist/indexer/{matchers.js → walk/matchers.js} +13 -9
- package/dist/indexer/{path-resolver.js → walk/path-resolver.js} +6 -6
- package/dist/indexer/{project-context.js → walk/project-context.js} +1 -1
- package/dist/indexer/{walker.js → walk/walker.js} +4 -3
- package/dist/integrations/agent/builder-shared.js +39 -0
- package/dist/integrations/agent/builders.js +14 -81
- package/dist/integrations/agent/config.js +6 -4
- package/dist/integrations/agent/detect.js +1 -1
- package/dist/integrations/agent/index.js +23 -8
- package/dist/integrations/agent/prompts.js +2 -3
- package/dist/integrations/agent/runner.js +22 -3
- package/dist/integrations/agent/spawn.js +9 -10
- package/dist/integrations/harnesses/claude/agent-builder.js +48 -0
- package/dist/integrations/harnesses/claude/config-import.js +70 -0
- package/dist/integrations/harnesses/claude/index.js +64 -0
- package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js} +16 -1
- package/dist/integrations/harnesses/index.js +144 -0
- package/dist/integrations/harnesses/opencode/agent-builder.js +43 -0
- package/dist/integrations/harnesses/opencode/config-import.js +82 -0
- package/dist/integrations/harnesses/opencode/index.js +59 -0
- package/dist/integrations/{session-logs/providers/opencode.js → harnesses/opencode/session-log.js} +1 -1
- package/dist/integrations/harnesses/opencode-sdk/index.js +49 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +234 -0
- package/dist/integrations/harnesses/types.js +43 -0
- package/dist/integrations/lockfile.js +7 -16
- package/dist/integrations/session-logs/index.js +82 -9
- package/dist/llm/call-ai.js +4 -4
- package/dist/llm/client.js +131 -6
- package/dist/llm/embedder.js +6 -6
- package/dist/llm/embedders/local.js +9 -22
- package/dist/llm/embedders/remote.js +2 -2
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +31 -12
- package/dist/llm/index-passes.js +1 -1
- package/dist/llm/memory-infer.js +12 -5
- package/dist/llm/metadata-enhance.js +2 -2
- package/dist/output/context.js +6 -44
- package/dist/output/renderers.js +88 -58
- package/dist/output/shapes/curate.js +7 -3
- package/dist/output/shapes/distill.js +7 -3
- package/dist/output/shapes/env-list.js +18 -16
- package/dist/output/shapes/events.js +5 -4
- package/dist/output/shapes/helpers.js +2 -4
- package/dist/output/shapes/history.js +7 -3
- package/dist/output/shapes/passthrough.js +8 -11
- package/dist/output/shapes/{proposal-accept.js → proposal/accept.js} +7 -3
- package/dist/output/shapes/{proposal-diff.js → proposal/diff.js} +7 -3
- package/dist/output/shapes/{proposal-list.js → proposal/list.js} +7 -3
- package/dist/output/shapes/{proposal-producer.js → proposal/producer.js} +5 -4
- package/dist/output/shapes/{proposal-reject.js → proposal/reject.js} +7 -3
- package/dist/output/shapes/{proposal-show.js → proposal/show.js} +7 -3
- package/dist/output/shapes/registry-search.js +7 -3
- package/dist/output/shapes/registry.js +12 -0
- package/dist/output/shapes/search.js +7 -3
- package/dist/output/shapes/secret-list.js +18 -16
- package/dist/output/shapes/show.js +7 -3
- package/dist/output/shapes.js +55 -30
- package/dist/output/text/add.js +2 -3
- package/dist/output/text/clone.js +2 -3
- package/dist/output/text/config.js +2 -3
- package/dist/output/text/curate.js +4 -3
- package/dist/output/text/distill.js +2 -3
- package/dist/output/text/enable-disable.js +5 -4
- package/dist/output/text/env.js +13 -0
- package/dist/output/text/events.js +5 -4
- package/dist/output/text/feedback.js +4 -3
- package/dist/output/text/helpers.js +54 -39
- package/dist/output/text/history.js +2 -3
- package/dist/output/text/import.js +2 -3
- package/dist/output/text/index.js +2 -3
- package/dist/output/text/info.js +2 -3
- package/dist/output/text/init.js +2 -3
- package/dist/output/text/list.js +2 -3
- package/dist/output/text/proposal/producer.js +9 -0
- package/dist/output/text/proposal/proposal.js +13 -0
- package/dist/output/text/registry-commands.js +8 -7
- package/dist/output/text/registry.js +12 -0
- package/dist/output/text/remember.js +4 -3
- package/dist/output/text/remove.js +2 -3
- package/dist/output/text/save.js +2 -3
- package/dist/output/text/search.js +4 -3
- package/dist/output/text/show.js +4 -3
- package/dist/output/text/update.js +2 -3
- package/dist/output/text/upgrade.js +2 -3
- package/dist/output/text/wiki.js +12 -11
- package/dist/output/text/workflow.js +12 -10
- package/dist/output/text.js +66 -32
- package/dist/registry/build-index.js +11 -10
- package/dist/registry/factory.js +1 -1
- package/dist/registry/origin-resolve.js +1 -1
- package/dist/registry/providers/index.js +2 -2
- package/dist/registry/providers/skills-sh.js +91 -72
- package/dist/registry/providers/static-index.js +75 -52
- package/dist/registry/resolve.js +3 -3
- package/dist/runtime.js +242 -0
- package/dist/scripts/migrate-storage.js +1594 -673
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +240 -166
- package/dist/setup/detect.js +338 -9
- package/dist/setup/harness-config-import.js +56 -0
- package/dist/setup/registry-stash-loader.js +99 -0
- package/dist/setup/setup.js +664 -96
- package/dist/sources/include.js +1 -1
- package/dist/sources/provider-factory.js +2 -2
- package/dist/sources/providers/filesystem.js +3 -3
- package/dist/sources/providers/git.js +9 -9
- package/dist/sources/providers/index.js +4 -4
- package/dist/sources/providers/npm.js +6 -6
- package/dist/sources/providers/provider-utils.js +13 -20
- package/dist/sources/providers/sync-from-ref.js +5 -5
- package/dist/sources/providers/tar-utils.js +2 -2
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +5 -5
- package/dist/sources/website-ingest.js +5 -5
- package/dist/storage/database.js +102 -0
- package/dist/storage/engines/sqlite-migrations.js +42 -0
- package/dist/storage/locations.js +25 -0
- package/dist/storage/repositories/index-db.js +43 -0
- package/dist/storage/repositories/workflow-runs-repository.js +141 -0
- package/dist/tasks/backends/cron.js +4 -4
- package/dist/tasks/backends/exec-utils.js +32 -0
- package/dist/tasks/backends/index.js +3 -3
- package/dist/tasks/backends/launchd.js +7 -14
- package/dist/tasks/backends/schtasks.js +7 -16
- package/dist/tasks/embedded.js +71 -0
- package/dist/tasks/parser.js +2 -2
- package/dist/tasks/resolveAkmBin.js +1 -1
- package/dist/tasks/runner.js +28 -15
- package/dist/tasks/schedule.js +1 -1
- package/dist/tasks/validator.js +7 -7
- package/dist/text-import-hook.mjs +51 -0
- package/dist/version.js +2 -1
- package/dist/wiki/wiki.js +7 -7
- package/dist/workflows/{authoring.js → authoring/authoring.js} +6 -6
- package/dist/workflows/{scope-key.js → authoring/scope-key.js} +1 -1
- package/dist/workflows/cli.js +1 -1
- package/dist/workflows/db.js +50 -32
- package/dist/workflows/parser.js +4 -4
- package/dist/workflows/renderer.js +5 -5
- package/dist/workflows/runtime/agent-identity.js +56 -0
- package/dist/workflows/runtime/checkin.js +57 -0
- package/dist/workflows/{runs.js → runtime/runs.js} +197 -101
- package/dist/workflows/validate-summary.js +82 -0
- package/docs/README.md +1 -1
- package/docs/data-and-telemetry.md +6 -6
- package/package.json +16 -8
- package/dist/commands/add-cli.js +0 -279
- package/dist/commands/env.js +0 -213
- package/dist/integrations/agent/sdk-runner.js +0 -126
- package/dist/output/shapes/vault-list.js +0 -19
- package/dist/output/text/proposal-producer.js +0 -8
- package/dist/output/text/proposal.js +0 -12
- package/dist/output/text/vault.js +0 -16
- /package/dist/core/{asset-serialize.js → asset/asset-serialize.js} +0 -0
- /package/dist/core/{frontmatter.js → asset/frontmatter.js} +0 -0
- /package/dist/core/{config-sources.js → config/config-sources.js} +0 -0
- /package/dist/indexer/{graph-dedup.js → graph/graph-dedup.js} +0 -0
- /package/dist/{core/config-types.js → indexer/passes/pass-context.js} +0 -0
- /package/dist/indexer/{search-fields.js → search/search-fields.js} +0 -0
- /package/dist/indexer/{index-context.js → walk/index-context.js} +0 -0
- /package/dist/workflows/{document-cache.js → runtime/document-cache.js} +0 -0
package/dist/indexer/indexer.js
CHANGED
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { SCRIPT_EXTENSIONS } from "../core/asset-spec";
|
|
7
|
-
import { isHttpUrl, resolveStashDir, toErrorMessage } from "../core/common";
|
|
8
|
-
import { concurrentMap } from "../core/concurrent";
|
|
9
|
-
import { getDbPath } from "../core/paths";
|
|
10
|
-
import { isVerbose, warn, warnVerbose } from "../core/warn";
|
|
11
|
-
import { resolveIndexPassLLM } from "../llm/index-passes";
|
|
12
|
-
import { takeWorkflowDocument } from "../workflows/document-cache";
|
|
13
|
-
import { clearStaleCacheEntries, closeDatabase, deleteEntriesByDir, deleteEntriesByIds, deleteEntriesByStashDir, deleteIndexDirStatesByStashDir, getAllEntriesForEmbedding, getEmbeddingCount, getEntriesByDir, getEntryCount, getIndexDirState, getMeta, isVecAvailable, openDatabase, openExistingDatabase, rebuildFts, relinkUsageEvents, setMeta, upsertEmbedding, upsertEntry, upsertIndexDirState, upsertUtilityScore, upsertWorkflowDocument, warnIfVecMissing, } from "./db";
|
|
14
|
-
import { deleteStoredGraph } from "./graph-db";
|
|
15
|
-
import { applyCuratedFrontmatter, applyWikiFrontmatter, generateMetadataFlat, isEnrichmentComplete, isWorkflowSkipWarning, loadStashFile, shouldIndexStashFile, } from "./metadata";
|
|
16
|
-
import { buildSearchText } from "./search-fields";
|
|
17
|
-
import { classifySemanticFailure, clearSemanticStatus, deriveSemanticProviderFingerprint, writeSemanticStatus, } from "./semantic-status";
|
|
18
|
-
import { ensureUsageEventsSchema, purgeOldUsageEvents } from "./usage-events";
|
|
19
|
-
import { walkStashFlat } from "./walker";
|
|
6
|
+
import { SCRIPT_EXTENSIONS } from "../core/asset/asset-spec.js";
|
|
7
|
+
import { isHttpUrl, resolveStashDir, toErrorMessage } from "../core/common.js";
|
|
8
|
+
import { concurrentMap } from "../core/concurrent.js";
|
|
9
|
+
import { getDbPath } from "../core/paths.js";
|
|
10
|
+
import { isVerbose, warn, warnVerbose } from "../core/warn.js";
|
|
11
|
+
import { resolveIndexPassLLM } from "../llm/index-passes.js";
|
|
12
|
+
import { takeWorkflowDocument } from "../workflows/runtime/document-cache.js";
|
|
13
|
+
import { clearStaleCacheEntries, closeDatabase, deleteEntriesByDir, deleteEntriesByIds, deleteEntriesByStashDir, deleteIndexDirStatesByStashDir, getAllEntriesForEmbedding, getEmbeddableEntryCount, getEmbeddingCount, getEntriesByDir, getEntryCount, getIndexDirState, getMeta, isVecAvailable, openDatabase, openExistingDatabase, rebuildFts, relinkUsageEvents, setMeta, upsertEmbedding, upsertEntry, upsertIndexDirState, upsertUtilityScore, upsertWorkflowDocument, warnIfVecMissing, } from "./db/db.js";
|
|
14
|
+
import { deleteStoredGraph } from "./db/graph-db.js";
|
|
15
|
+
import { applyCuratedFrontmatter, applyWikiFrontmatter, generateMetadataFlat, isEnrichmentComplete, isWorkflowSkipWarning, loadStashFile, shouldIndexStashFile, } from "./passes/metadata.js";
|
|
16
|
+
import { buildSearchText } from "./search/search-fields.js";
|
|
17
|
+
import { classifySemanticFailure, clearSemanticStatus, deriveSemanticProviderFingerprint, writeSemanticStatus, } from "./search/semantic-status.js";
|
|
18
|
+
import { ensureUsageEventsSchema, purgeOldUsageEvents } from "./usage/usage-events.js";
|
|
19
|
+
import { walkStashFlat } from "./walk/walker.js";
|
|
20
20
|
function throwIfAborted(signal) {
|
|
21
21
|
if (signal?.aborted) {
|
|
22
22
|
throw signal.reason instanceof Error ? signal.reason : new Error("index interrupted");
|
|
@@ -177,7 +177,8 @@ async function runFinalizePhase(ctx) {
|
|
|
177
177
|
setMeta(db, "hasEmbeddings", embeddingResult.success ? "1" : "0");
|
|
178
178
|
warnIfVecMissing(db);
|
|
179
179
|
const totalEntries = getEntryCount(db);
|
|
180
|
-
const
|
|
180
|
+
const semanticEntryCount = getEmbeddableEntryCount(db);
|
|
181
|
+
const verification = verifyIndexState(db, config, semanticEntryCount, embeddingResult);
|
|
181
182
|
if (config.semanticSearchMode === "off") {
|
|
182
183
|
clearSemanticStatus();
|
|
183
184
|
}
|
|
@@ -232,11 +233,17 @@ export async function akmIndex(options) {
|
|
|
232
233
|
const clean = options?.clean === true;
|
|
233
234
|
const dryRun = options?.dryRun === true;
|
|
234
235
|
// Load config and resolve all stash sources
|
|
235
|
-
const { loadConfig } = await import("../core/config.js");
|
|
236
|
+
const { loadConfig } = await import("../core/config/config.js");
|
|
236
237
|
const config = loadConfig();
|
|
238
|
+
// One-time, read-only guard: warn if the writable stash still holds an
|
|
239
|
+
// un-migrated `vaults/` directory. In 0.9.0 the indexer skips `vaults/`
|
|
240
|
+
// entirely, so an unmigrated vault's `.env` data would silently never be
|
|
241
|
+
// indexed. Non-destructive — only stats, never reads/writes/deletes.
|
|
242
|
+
const { warnOnUnmigratedVaults } = await import("./usage/unmigrated-vaults-guard.js");
|
|
243
|
+
warnOnUnmigratedVaults(stashDir);
|
|
237
244
|
// Ensure git stash caches are extracted before resolving stash dirs,
|
|
238
245
|
// so their content directories exist on disk for the walker to discover.
|
|
239
|
-
const { ensureSourceCaches, resolveSourceEntries } = await import("./search-source.js");
|
|
246
|
+
const { ensureSourceCaches, resolveSourceEntries } = await import("./search/search-source.js");
|
|
240
247
|
await ensureSourceCaches(config, { force: full });
|
|
241
248
|
const allSourceEntries = resolveSourceEntries(stashDir, config);
|
|
242
249
|
const allSourceDirs = allSourceEntries.map((s) => s.path);
|
|
@@ -995,11 +1002,11 @@ function getSemanticSearchLabel(semanticSearchMode, embeddingProvider, vecAvaila
|
|
|
995
1002
|
return "disabled";
|
|
996
1003
|
return `${embeddingProvider} embeddings, ${vecAvailable ? "sqlite-vec" : "JS fallback"}`;
|
|
997
1004
|
}
|
|
998
|
-
function verifyIndexState(db, config,
|
|
1005
|
+
function verifyIndexState(db, config, embeddableEntries, embeddingResult) {
|
|
999
1006
|
const embeddingCount = getEmbeddingCount(db);
|
|
1000
1007
|
const vecAvailable = isVecAvailable(db);
|
|
1001
1008
|
const embeddingProvider = getEmbeddingProvider(config.embedding);
|
|
1002
|
-
if (
|
|
1009
|
+
if (embeddableEntries === 0) {
|
|
1003
1010
|
return {
|
|
1004
1011
|
ok: true,
|
|
1005
1012
|
message: "Index ready. No assets were found yet.",
|
|
@@ -1007,7 +1014,7 @@ function verifyIndexState(db, config, totalEntries, embeddingResult) {
|
|
|
1007
1014
|
semanticSearchMode: config.semanticSearchMode,
|
|
1008
1015
|
semanticStatus: config.semanticSearchMode === "off" ? "disabled" : "pending",
|
|
1009
1016
|
embeddingProvider,
|
|
1010
|
-
entryCount:
|
|
1017
|
+
entryCount: embeddableEntries,
|
|
1011
1018
|
embeddingCount,
|
|
1012
1019
|
vecAvailable,
|
|
1013
1020
|
};
|
|
@@ -1020,20 +1027,20 @@ function verifyIndexState(db, config, totalEntries, embeddingResult) {
|
|
|
1020
1027
|
semanticSearchMode: config.semanticSearchMode,
|
|
1021
1028
|
semanticStatus: "disabled",
|
|
1022
1029
|
embeddingProvider,
|
|
1023
|
-
entryCount:
|
|
1030
|
+
entryCount: embeddableEntries,
|
|
1024
1031
|
embeddingCount,
|
|
1025
1032
|
vecAvailable,
|
|
1026
1033
|
};
|
|
1027
1034
|
}
|
|
1028
|
-
if (embeddingCount >=
|
|
1035
|
+
if (embeddingCount >= embeddableEntries) {
|
|
1029
1036
|
return {
|
|
1030
1037
|
ok: true,
|
|
1031
|
-
message: `Semantic search ready (${embeddingCount}/${
|
|
1038
|
+
message: `Semantic search ready (${embeddingCount}/${embeddableEntries} embeddings, ${vecAvailable ? "sqlite-vec active" : "JS fallback active"}).`,
|
|
1032
1039
|
semanticSearchEnabled: true,
|
|
1033
1040
|
semanticSearchMode: config.semanticSearchMode,
|
|
1034
1041
|
semanticStatus: vecAvailable ? "ready-vec" : "ready-js",
|
|
1035
1042
|
embeddingProvider,
|
|
1036
|
-
entryCount:
|
|
1043
|
+
entryCount: embeddableEntries,
|
|
1037
1044
|
embeddingCount,
|
|
1038
1045
|
vecAvailable,
|
|
1039
1046
|
};
|
|
@@ -1041,7 +1048,7 @@ function verifyIndexState(db, config, totalEntries, embeddingResult) {
|
|
|
1041
1048
|
return {
|
|
1042
1049
|
ok: false,
|
|
1043
1050
|
message: embeddingResult.message ??
|
|
1044
|
-
`Semantic search verification failed (${embeddingCount}/${
|
|
1051
|
+
`Semantic search verification failed (${embeddingCount}/${embeddableEntries} embeddings available).`,
|
|
1045
1052
|
guidance: embeddingProvider === "remote"
|
|
1046
1053
|
? "Check your embedding endpoint and credentials, then retry `akm index --full --verbose`."
|
|
1047
1054
|
: "Retry `akm index --full --verbose`. If it still fails, confirm local model downloads are permitted and see docs/configuration.md for local embedding dependency setup.",
|
|
@@ -1049,7 +1056,7 @@ function verifyIndexState(db, config, totalEntries, embeddingResult) {
|
|
|
1049
1056
|
semanticSearchMode: config.semanticSearchMode,
|
|
1050
1057
|
semanticStatus: "blocked",
|
|
1051
1058
|
embeddingProvider,
|
|
1052
|
-
entryCount:
|
|
1059
|
+
entryCount: embeddableEntries,
|
|
1053
1060
|
embeddingCount,
|
|
1054
1061
|
vecAvailable,
|
|
1055
1062
|
};
|
|
@@ -1075,8 +1082,8 @@ function resolveIndexedFiles(dirPath, files, stash) {
|
|
|
1075
1082
|
return resolved.size > 0 ? [...resolved] : files;
|
|
1076
1083
|
}
|
|
1077
1084
|
async function enhanceStashWithLlm(llmConfig, stash, files, summary, signal, db, entryKeys, reEnrich, akmConfig, onEntryDone) {
|
|
1078
|
-
const { enhanceMetadata } = await import("../llm/metadata-enhance");
|
|
1079
|
-
const { computeBodyHash, getLlmCacheEntry, upsertLlmCacheEntry } = await import("./db.js");
|
|
1085
|
+
const { enhanceMetadata } = await import("../llm/metadata-enhance.js");
|
|
1086
|
+
const { computeBodyHash, getLlmCacheEntry, upsertLlmCacheEntry } = await import("./db/db.js");
|
|
1080
1087
|
const results = await concurrentMap(stash.entries, async (entry, idx) => {
|
|
1081
1088
|
if (signal?.aborted)
|
|
1082
1089
|
return entry;
|
|
@@ -1233,8 +1240,8 @@ function mergeLegacyEntry(entry, legacyEntries) {
|
|
|
1233
1240
|
* `NotFoundError` with their own messaging.
|
|
1234
1241
|
*/
|
|
1235
1242
|
export async function lookup(ref) {
|
|
1236
|
-
const { loadConfig } = await import("../core/config.js");
|
|
1237
|
-
const { resolveSourceEntries } = await import("./search-source.js");
|
|
1243
|
+
const { loadConfig } = await import("../core/config/config.js");
|
|
1244
|
+
const { resolveSourceEntries } = await import("./search/search-source.js");
|
|
1238
1245
|
const config = loadConfig();
|
|
1239
1246
|
const sources = resolveSourceEntries(undefined, config);
|
|
1240
1247
|
if (sources.length === 0)
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Explicit composition root for the indexer's built-in registrations.
|
|
6
|
+
*
|
|
7
|
+
* Historically two independent lazy gates (`ensureBuiltinsRegistered` in
|
|
8
|
+
* `walk/file-context.ts` and `ensureBuiltinMetadataContributorsRegistered` in
|
|
9
|
+
* `passes/metadata-contributors.ts`) each registered a different built-in set
|
|
10
|
+
* on first use. That implicit, order-dependent wiring is the M1/M2 finding in
|
|
11
|
+
* `docs/technical/code-health-brittleness-audit.md`.
|
|
12
|
+
*
|
|
13
|
+
* `initIndexer()` folds both into a single deterministic, idempotent entry
|
|
14
|
+
* point. It registers, exactly once:
|
|
15
|
+
*
|
|
16
|
+
* 1. Built-in matchers — `registerBuiltinMatchers()` (`walk/matchers.ts`).
|
|
17
|
+
* 2. Built-in renderers — `registerBuiltinRenderers()` (`output/renderers.ts`).
|
|
18
|
+
* 3. Metadata contributors — top-level registration side-effects that run when
|
|
19
|
+
* `output/renderers.ts` and `workflows/renderer.ts` are imported.
|
|
20
|
+
*
|
|
21
|
+
* Importing `output/renderers.ts` satisfies both (2) and the renderer-owned
|
|
22
|
+
* metadata contributors; `workflows/renderer.ts` is imported explicitly for the
|
|
23
|
+
* workflow contributor (it is already transitively pulled in by renderers, but
|
|
24
|
+
* the explicit import preserves the original gate's import set and keeps the
|
|
25
|
+
* wiring self-documenting).
|
|
26
|
+
*
|
|
27
|
+
* Timing is preserved: this stays a *lazy* gate. It is awaited from the same
|
|
28
|
+
* accessor call sites the old gates were awaited from, so no startup work is
|
|
29
|
+
* forced eagerly. The shared promise makes concurrent and repeat calls safe —
|
|
30
|
+
* the registrations run at most once per process.
|
|
31
|
+
*/
|
|
32
|
+
let initPromise;
|
|
33
|
+
/**
|
|
34
|
+
* Idempotently register every built-in indexer contributor (matchers,
|
|
35
|
+
* renderers, and metadata contributors).
|
|
36
|
+
*
|
|
37
|
+
* Safe to call repeatedly and concurrently: the registration work runs at most
|
|
38
|
+
* once; subsequent calls await the same resolved promise.
|
|
39
|
+
*/
|
|
40
|
+
export function initIndexer() {
|
|
41
|
+
if (!initPromise) {
|
|
42
|
+
initPromise = (async () => {
|
|
43
|
+
const { registerBuiltinMatchers } = await import("./walk/matchers.js");
|
|
44
|
+
// Importing renderers registers the built-in metadata contributors as a
|
|
45
|
+
// load-time side-effect and exposes registerBuiltinRenderers().
|
|
46
|
+
const { registerBuiltinRenderers } = await import("../output/renderers.js");
|
|
47
|
+
// Imported for the workflow metadata contributor's load-time side-effect.
|
|
48
|
+
await import("../workflows/renderer.js");
|
|
49
|
+
registerBuiltinMatchers();
|
|
50
|
+
registerBuiltinRenderers();
|
|
51
|
+
})();
|
|
52
|
+
}
|
|
53
|
+
return initPromise;
|
|
54
|
+
}
|
package/dist/indexer/manifest.js
CHANGED
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import fs from "node:fs";
|
|
13
13
|
import path from "node:path";
|
|
14
|
-
import { makeAssetRef } from "../core/asset-ref";
|
|
15
|
-
import { deriveCanonicalAssetNameFromStashRoot } from "../core/asset-spec";
|
|
16
|
-
import { resolveStashDir } from "../core/common";
|
|
17
|
-
import { loadConfig } from "../core/config";
|
|
18
|
-
import { getDbPath } from "../core/paths";
|
|
19
|
-
import { warn } from "../core/warn";
|
|
20
|
-
import { closeDatabase, getAllEntries, getEntryCount, getMeta, openExistingDatabase } from "./db";
|
|
21
|
-
import { generateMetadataFlat, loadStashFile } from "./metadata";
|
|
22
|
-
import { resolveSourceEntries } from "./search-source";
|
|
23
|
-
import { walkStashFlat } from "./walker";
|
|
14
|
+
import { makeAssetRef } from "../core/asset/asset-ref.js";
|
|
15
|
+
import { deriveCanonicalAssetNameFromStashRoot } from "../core/asset/asset-spec.js";
|
|
16
|
+
import { resolveStashDir } from "../core/common.js";
|
|
17
|
+
import { loadConfig } from "../core/config/config.js";
|
|
18
|
+
import { getDbPath } from "../core/paths.js";
|
|
19
|
+
import { warn } from "../core/warn.js";
|
|
20
|
+
import { closeDatabase, getAllEntries, getEntryCount, getMeta, openExistingDatabase } from "./db/db.js";
|
|
21
|
+
import { generateMetadataFlat, loadStashFile } from "./passes/metadata.js";
|
|
22
|
+
import { resolveSourceEntries } from "./search/search-source.js";
|
|
23
|
+
import { walkStashFlat } from "./walk/walker.js";
|
|
24
24
|
const MAX_DESCRIPTION_LENGTH = 80;
|
|
25
25
|
/**
|
|
26
26
|
* Truncate a description string to a maximum length, appending "..." if truncated.
|
|
@@ -1,19 +1,52 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Memory inference pass for `akm index` (#201).
|
|
6
|
+
*
|
|
7
|
+
* Detects memories pending inference, asks the configured LLM to compress each
|
|
8
|
+
* into one higher-signal derived memory, and writes the result back as a new
|
|
9
|
+
* memory file with frontmatter `inferred: true` + a `source:` backref to the
|
|
10
|
+
* parent memory.
|
|
11
|
+
*
|
|
12
|
+
* Pending predicate (see {@link isPendingMemory}):
|
|
13
|
+
* - File lives under `<stashRoot>/memories/` and ends in `.md`.
|
|
14
|
+
* - Frontmatter does NOT have `inferenceProcessed: true` (parent already split).
|
|
15
|
+
* - Frontmatter does NOT have `inferred: true` (this is itself a child fact).
|
|
16
|
+
*
|
|
17
|
+
* Idempotency: after a successful split the parent's frontmatter is rewritten
|
|
18
|
+
* with `inferenceProcessed: true`. A subsequent `akm index` therefore skips
|
|
19
|
+
* the parent without re-running the LLM.
|
|
20
|
+
*
|
|
21
|
+
* Disabling — two orthogonal gates:
|
|
22
|
+
* 1. `profiles.improve.default.processes.memoryInference.enabled = false`
|
|
23
|
+
* blocks the pass at the feature-flag layer (no network call may ever
|
|
24
|
+
* issue). Historically the v1 spec §14 gate, superseded by the 0.8.0
|
|
25
|
+
* profile shape.
|
|
26
|
+
* 2. `index.memory.llm = false` (or no resolvable LLM profile) opts the
|
|
27
|
+
* pass out at the per-pass layer (#208).
|
|
28
|
+
* A pass runs iff both layers allow it. Existing inferred children are
|
|
29
|
+
* NEVER deleted — the user keeps what was already produced.
|
|
30
|
+
*
|
|
31
|
+
* Locked v1 contract:
|
|
32
|
+
* - LLM access is exclusively via `resolveIndexPassLLM("memory", config)`.
|
|
33
|
+
* - All child memory writes go through `writeAssetToSource` in
|
|
34
|
+
* `src/core/write-source.ts`. The parent's frontmatter rewrite is an
|
|
35
|
+
* explicit narrow exception — see {@link markParentProcessed}.
|
|
36
|
+
*/
|
|
4
37
|
import fs from "node:fs";
|
|
5
38
|
import path from "node:path";
|
|
6
|
-
import { parseAssetRef } from "
|
|
7
|
-
import { assembleAsset } from "
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { warn } from "
|
|
11
|
-
import { writeAssetToSource } from "
|
|
12
|
-
import { isProcessEnabled } from "
|
|
13
|
-
import { resolveIndexPassLLM } from "
|
|
14
|
-
import * as memoryInfer from "
|
|
15
|
-
import { withLlmCache } from "
|
|
16
|
-
import { walkMarkdownFiles } from "
|
|
39
|
+
import { parseAssetRef } from "../../core/asset/asset-ref.js";
|
|
40
|
+
import { assembleAsset } from "../../core/asset/asset-serialize.js";
|
|
41
|
+
import { parseFrontmatter, parseFrontmatterBlock } from "../../core/asset/frontmatter.js";
|
|
42
|
+
import { concurrentMap } from "../../core/concurrent.js";
|
|
43
|
+
import { warn } from "../../core/warn.js";
|
|
44
|
+
import { writeAssetToSource } from "../../core/write-source.js";
|
|
45
|
+
import { isProcessEnabled } from "../../llm/feature-gate.js";
|
|
46
|
+
import { resolveIndexPassLLM } from "../../llm/index-passes.js";
|
|
47
|
+
import * as memoryInfer from "../../llm/memory-infer.js";
|
|
48
|
+
import { withLlmCache } from "../db/llm-cache.js";
|
|
49
|
+
import { walkMarkdownFiles } from "../walk/walker.js";
|
|
17
50
|
/**
|
|
18
51
|
* Frontmatter keys this pass cares about. Constants so a future rename only
|
|
19
52
|
* needs to touch one site.
|
|
@@ -37,17 +70,24 @@ const FM_CAPTURE_MODE = "captureMode";
|
|
|
37
70
|
* Both must allow the call for the pass to run. Either set to `false`
|
|
38
71
|
* short-circuits to a no-op result.
|
|
39
72
|
*/
|
|
40
|
-
export async function runMemoryInferencePass(
|
|
73
|
+
export async function runMemoryInferencePass(ctx) {
|
|
74
|
+
const { config, sources, signal, db, reEnrich, onProgress, options = {} } = ctx;
|
|
41
75
|
const result = {
|
|
42
76
|
considered: 0,
|
|
43
77
|
cacheHits: 0,
|
|
78
|
+
retryAttempts: 0,
|
|
44
79
|
splitParents: 0,
|
|
45
80
|
writtenFacts: 0,
|
|
46
81
|
skippedNoFacts: 0,
|
|
47
82
|
skippedChildExists: 0,
|
|
48
83
|
skippedAborted: 0,
|
|
49
84
|
unaccounted: 0,
|
|
85
|
+
htmlErrorCount: 0,
|
|
50
86
|
};
|
|
87
|
+
// Mutable sink threaded into compressMemoryToDerivedMemory so the per-call
|
|
88
|
+
// HTML-error categorization (which is otherwise swallowed inside the feature
|
|
89
|
+
// gate) bubbles up into the pass result.
|
|
90
|
+
const inferTelemetry = {};
|
|
51
91
|
// Gate 1 — feature gate via isProcessEnabled, which reads the 0.8.0 path
|
|
52
92
|
// (profiles.improve.default.processes.memoryInference.enabled). Defaults to
|
|
53
93
|
// enabled when the key is absent.
|
|
@@ -103,31 +143,51 @@ export async function runMemoryInferencePass(config, sources, signal, db, reEnri
|
|
|
103
143
|
// the hit count separately so the operational yield rate
|
|
104
144
|
// (writtenFacts / freshAttempts) is interpretable as the cache warms.
|
|
105
145
|
let fromCache = false;
|
|
146
|
+
// Count single bounded retries for transient LLM failures on this
|
|
147
|
+
// candidate. Bumped via the `onRetryAttempt` callback threaded into
|
|
148
|
+
// `chatCompletion`; surfaced as `retryAttempts` telemetry, never as a
|
|
149
|
+
// failure for the same call.
|
|
150
|
+
let retryAttempts = 0;
|
|
151
|
+
const onRetryAttempt = () => {
|
|
152
|
+
retryAttempts += 1;
|
|
153
|
+
};
|
|
106
154
|
const derived = db
|
|
107
155
|
? await withLlmCache(db, record.filePath, record.body, reEnrich ?? false, () => memoryInfer.compressMemoryToDerivedMemory(llmConfig, record.body, signal, config, (evt) => {
|
|
108
156
|
warn(`[akm] LLM fallback for ${evt.feature}: ${evt.reason}`);
|
|
109
|
-
}), validate, undefined, "", {
|
|
157
|
+
}, inferTelemetry, onRetryAttempt), validate, undefined, "", {
|
|
110
158
|
onCacheHit: () => {
|
|
111
159
|
fromCache = true;
|
|
112
160
|
},
|
|
113
161
|
})
|
|
114
162
|
: await memoryInfer.compressMemoryToDerivedMemory(llmConfig, record.body, signal, config, (evt) => {
|
|
115
163
|
warn(`[akm] LLM fallback for ${evt.feature}: ${evt.reason}`);
|
|
116
|
-
});
|
|
164
|
+
}, inferTelemetry, onRetryAttempt);
|
|
117
165
|
if (!derived) {
|
|
118
|
-
return { skipped: true, fromCache };
|
|
166
|
+
return { skipped: true, fromCache, retryAttempts };
|
|
119
167
|
}
|
|
120
|
-
const
|
|
121
|
-
if (written > 0) {
|
|
168
|
+
const writeOutcome = await writeDerivedMemory(record, derived);
|
|
169
|
+
if (writeOutcome.written > 0) {
|
|
122
170
|
markParentProcessed(record);
|
|
123
|
-
return { skipped: false, splitParent: true, written, fromCache };
|
|
171
|
+
return { skipped: false, splitParent: true, written: writeOutcome.written, fromCache, retryAttempts };
|
|
124
172
|
}
|
|
125
173
|
// LLM produced a valid derived draft but no file was written — either
|
|
126
174
|
// because `<parent>.derived.md` already exists on disk or
|
|
127
175
|
// `writeAssetToSource` threw. Categorise as `childExists` so the
|
|
128
176
|
// attempt is accounted for in health metrics rather than vanishing
|
|
129
177
|
// into the freshAttempts denominator.
|
|
130
|
-
|
|
178
|
+
//
|
|
179
|
+
// When the child already exists on disk the inference is, by definition,
|
|
180
|
+
// already complete — so mark the parent processed here too (#550).
|
|
181
|
+
// Without this, `isPendingMemory()` re-queues the same parent every run
|
|
182
|
+
// (the `written > 0` path was previously the only site that marks it),
|
|
183
|
+
// causing permanent re-queueing and wasted LLM calls. A genuine write
|
|
184
|
+
// *failure* (`writeAssetToSource` threw) must NOT mark the parent — it
|
|
185
|
+
// should be retried next run — so we key off the explicit `childExists`
|
|
186
|
+
// outcome rather than the conflated `written === 0`.
|
|
187
|
+
if (writeOutcome.childExists) {
|
|
188
|
+
markParentProcessed(record);
|
|
189
|
+
}
|
|
190
|
+
return { skipped: false, splitParent: false, written: 0, fromCache, retryAttempts, childExists: true };
|
|
131
191
|
},
|
|
132
192
|
// Default concurrency of 4 for cloud APIs. Set `llm.concurrency: 1`
|
|
133
193
|
// in config.json for local model servers (LM Studio, Ollama).
|
|
@@ -151,6 +211,9 @@ export async function runMemoryInferencePass(config, sources, signal, db, reEnri
|
|
|
151
211
|
if (res.fromCache) {
|
|
152
212
|
result.cacheHits += 1;
|
|
153
213
|
}
|
|
214
|
+
if ("retryAttempts" in res) {
|
|
215
|
+
result.retryAttempts += res.retryAttempts;
|
|
216
|
+
}
|
|
154
217
|
if (res.skipped) {
|
|
155
218
|
result.skippedNoFacts += 1;
|
|
156
219
|
// Intentionally NOT marked processed — a transient LLM failure should
|
|
@@ -183,6 +246,7 @@ export async function runMemoryInferencePass(config, sources, signal, db, reEnri
|
|
|
183
246
|
currentRef: pending[i]?.ref,
|
|
184
247
|
});
|
|
185
248
|
}
|
|
249
|
+
result.htmlErrorCount = inferTelemetry.htmlErrorCount ?? 0;
|
|
186
250
|
return result;
|
|
187
251
|
}
|
|
188
252
|
// ── Pending detection ───────────────────────────────────────────────────────
|
|
@@ -260,7 +324,6 @@ function toMemoryName(memoriesDir, filePath) {
|
|
|
260
324
|
// user has organised under memories/.
|
|
261
325
|
return rel.replace(/\\/g, "/").replace(/\.md$/i, "");
|
|
262
326
|
}
|
|
263
|
-
// ── Writing derived memories + marking parent ───────────────────────────────
|
|
264
327
|
async function writeDerivedMemory(parent, derived) {
|
|
265
328
|
const writeTarget = {
|
|
266
329
|
kind: "filesystem",
|
|
@@ -277,17 +340,23 @@ async function writeDerivedMemory(parent, derived) {
|
|
|
277
340
|
const childRefStr = `memory:${childName}`;
|
|
278
341
|
const childPath = path.join(parent.stashRoot, "memories", `${childName}.md`);
|
|
279
342
|
if (fs.existsSync(childPath)) {
|
|
280
|
-
|
|
343
|
+
// The derived child is already on disk — inference for this parent is
|
|
344
|
+
// complete. Report `childExists` so the caller marks the parent processed
|
|
345
|
+
// (#550) instead of re-queueing it forever.
|
|
346
|
+
return { written: 0, childExists: true };
|
|
281
347
|
}
|
|
282
348
|
try {
|
|
283
349
|
const content = renderDerivedMemory(parent, derived);
|
|
284
350
|
const childRef = parseAssetRef(childRefStr);
|
|
285
351
|
await writeAssetToSource(writeTarget, writeConfig, childRef, content);
|
|
286
|
-
return 1;
|
|
352
|
+
return { written: 1, childExists: false };
|
|
287
353
|
}
|
|
288
354
|
catch (err) {
|
|
289
355
|
warn(`memory inference: failed to write derived memory ${childName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
290
|
-
|
|
356
|
+
// A genuine write failure — the parent must remain pending so it is
|
|
357
|
+
// retried on the next run. `childExists: false` keeps it from being
|
|
358
|
+
// marked processed.
|
|
359
|
+
return { written: 0, childExists: false };
|
|
291
360
|
}
|
|
292
361
|
}
|
|
293
362
|
function renderDerivedMemory(parent, derived) {
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
const contributors = [];
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Ensure that all built-in indexer contributors are registered.
|
|
7
|
+
*
|
|
8
|
+
* Delegates to the single `initIndexer()` composition root (see
|
|
9
|
+
* `src/indexer/init.ts`). Imported dynamically to keep this a lazy gate and to
|
|
10
|
+
* avoid a static import cycle (init -> renderers -> metadata-contributors).
|
|
11
|
+
* Called on first use of getMetadataContributors; idempotent.
|
|
12
|
+
*/
|
|
6
13
|
async function ensureBuiltinMetadataContributorsRegistered() {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
await import("../output/renderers.js");
|
|
10
|
-
await import("../workflows/renderer.js");
|
|
11
|
-
})();
|
|
12
|
-
}
|
|
13
|
-
return builtinsPromise;
|
|
14
|
+
const { initIndexer } = await import("../init.js");
|
|
15
|
+
await initIndexer();
|
|
14
16
|
}
|
|
15
17
|
export function registerMetadataContributor(contributor) {
|
|
16
18
|
contributors.push(contributor);
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { deriveCanonicalAssetName, deriveCanonicalAssetNameFromStashRoot, isRelevantAssetFile, } from "
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { isVerbose, warn } from "
|
|
10
|
-
import { buildFileContext, buildRenderContext, getRenderer, runMatchers } from "
|
|
11
|
-
import { applyMetadataContributors } from "./metadata-contributors";
|
|
6
|
+
import { deriveCanonicalAssetName, deriveCanonicalAssetNameFromStashRoot, isRelevantAssetFile, } from "../../core/asset/asset-spec.js";
|
|
7
|
+
import { parseFrontmatter } from "../../core/asset/frontmatter.js";
|
|
8
|
+
import { asNonEmptyString, isAssetType, writeFileAtomic } from "../../core/common.js";
|
|
9
|
+
import { isVerbose, warn } from "../../core/warn.js";
|
|
10
|
+
import { buildFileContext, buildRenderContext, getRenderer, runMatchers } from "../walk/file-context.js";
|
|
11
|
+
import { applyMetadataContributors } from "./metadata-contributors.js";
|
|
12
12
|
export const SCOPE_KEYS = ["user", "agent", "run", "channel"];
|
|
13
13
|
// ── Load / Write ────────────────────────────────────────────────────────────
|
|
14
14
|
const STASH_FILENAME = ".stash.json";
|
|
@@ -480,18 +480,15 @@ export function shouldIndexStashFile(stashRoot, file, options) {
|
|
|
480
480
|
const segments = relPath.split(/[\\/]+/).filter(Boolean);
|
|
481
481
|
if (segments.length === 0)
|
|
482
482
|
return true;
|
|
483
|
-
// Skip env
|
|
484
|
-
if (
|
|
485
|
-
(file.endsWith(".env") || path.basename(file) === ".env")) {
|
|
483
|
+
// Skip env .env files that have a sibling .sensitive marker file.
|
|
484
|
+
if (segments[0] === "env" && (file.endsWith(".env") || path.basename(file) === ".env")) {
|
|
486
485
|
const markerPath = file.replace(/\.env$/, ".sensitive");
|
|
487
486
|
if (fs.existsSync(markerPath))
|
|
488
487
|
return false;
|
|
489
488
|
}
|
|
490
|
-
//
|
|
491
|
-
//
|
|
492
|
-
|
|
493
|
-
// with no `env/` dir still index `vaults/` normally.)
|
|
494
|
-
if (segments[0] === "vaults" && fs.existsSync(path.join(stashRoot, "env"))) {
|
|
489
|
+
// The legacy `vaults/` directory (frozen copy left by the 0.8 migration) is
|
|
490
|
+
// never indexed — the `vault` asset type was removed in 0.9.0.
|
|
491
|
+
if (segments[0] === "vaults") {
|
|
495
492
|
return false;
|
|
496
493
|
}
|
|
497
494
|
// Skip secret files that are themselves a `.sensitive` marker, or that have a
|
|
@@ -853,11 +850,10 @@ async function buildEntryFromFile(file, assetType, canonicalName, dirPath, pkgMe
|
|
|
853
850
|
}
|
|
854
851
|
}
|
|
855
852
|
// Extract @param from script files.
|
|
856
|
-
// Env
|
|
857
|
-
//
|
|
858
|
-
//
|
|
859
|
-
|
|
860
|
-
if (ext !== ".md" && assetType !== "env" && assetType !== "vault" && assetType !== "secret") {
|
|
853
|
+
// Env files (.env) and secret files (whole-file secrets) are deliberately
|
|
854
|
+
// excluded — their contents are secrets and must never be parsed for @param
|
|
855
|
+
// or any other metadata that could embed a value into the entry.
|
|
856
|
+
if (ext !== ".md" && assetType !== "env" && assetType !== "secret") {
|
|
861
857
|
const content = ctx.content();
|
|
862
858
|
const scriptParams = extractScriptParameters(file, content);
|
|
863
859
|
if (scriptParams)
|
|
@@ -1,19 +1,59 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Staleness-detection pass for `akm improve` (Phase 4A,
|
|
6
|
+
* `.plans/0.8.0/self-improvement-enhancements-plan.md` lines 132-145).
|
|
7
|
+
*
|
|
8
|
+
* Activates the `deprecated` belief-state machinery shipped in Phase 1A
|
|
9
|
+
* (commit 7b6fffe). Without this pass, nothing in the pipeline ever wrote
|
|
10
|
+
* `beliefState: deprecated`, so the -0.15 ranking penalty and the
|
|
11
|
+
* `matchBeliefFilter("historical")` inclusion were dormant.
|
|
12
|
+
*
|
|
13
|
+
* Pipeline
|
|
14
|
+
* --------
|
|
15
|
+
* 1. Walk every memory under `<stash>/memories/` and select candidates
|
|
16
|
+
* whose belief state is NOT already excluded
|
|
17
|
+
* ({contradicted, archived, deprecated}) AND whose `lastConfirmedAt`
|
|
18
|
+
* is absent or older than the configured threshold (default 90 days).
|
|
19
|
+
* Files without `lastConfirmedAt` fall back to file `mtime`.
|
|
20
|
+
* 2. For each candidate, ask the configured validation-tier LLM
|
|
21
|
+
* (`resolveValidationRunner`) whether the candidate is still current
|
|
22
|
+
* given the top-K most-similar memories from the stash.
|
|
23
|
+
* Strict response contract: `YES\nSUPERSEDED_BY: <ref>` or `NO`.
|
|
24
|
+
* Anything else is treated as a parse error and the candidate is skipped.
|
|
25
|
+
* 3. YES → write `beliefState: "deprecated"`, `supersededBy: [<ref>]`,
|
|
26
|
+
* `lastConfirmedAt: <now>`. The supersededBy ref MUST exist in the
|
|
27
|
+
* stash (DB lookup); if it doesn't, treat as NO.
|
|
28
|
+
* NO → write only `lastConfirmedAt: <now>` (refreshes the staleness
|
|
29
|
+
* window). All other frontmatter fields stay untouched.
|
|
30
|
+
*
|
|
31
|
+
* Caching
|
|
32
|
+
* -------
|
|
33
|
+
* Uses the standard `withLlmCache` wrapper with cacheVariant
|
|
34
|
+
* `"staleness_detect"`, so re-running the pass on an unchanged file is a
|
|
35
|
+
* no-op (no LLM call).
|
|
36
|
+
*
|
|
37
|
+
* Feature gate
|
|
38
|
+
* ------------
|
|
39
|
+
* Default OFF. Enable via `features.index.staleness_detection.enabled` (or
|
|
40
|
+
* the boolean shorthand `features.index.staleness_detection = true`).
|
|
41
|
+
* Threshold-days knob lives at
|
|
42
|
+
* `features.index.staleness_detection.options.thresholdDays` (default 90).
|
|
43
|
+
*/
|
|
4
44
|
import { createHash } from "node:crypto";
|
|
5
45
|
import fs from "node:fs";
|
|
6
46
|
import path from "node:path";
|
|
7
|
-
import { assembleAsset } from "
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { warn } from "
|
|
11
|
-
import { resolveValidationRunner } from "
|
|
12
|
-
import { chatCompletion } from "
|
|
13
|
-
import { isProcessEnabled } from "
|
|
14
|
-
import { findEntryIdByRef } from "
|
|
15
|
-
import { withLlmCache } from "
|
|
16
|
-
import { walkMarkdownFiles } from "
|
|
47
|
+
import { assembleAsset } from "../../core/asset/asset-serialize.js";
|
|
48
|
+
import { parseFrontmatter, parseFrontmatterBlock } from "../../core/asset/frontmatter.js";
|
|
49
|
+
import { concurrentMap } from "../../core/concurrent.js";
|
|
50
|
+
import { warn } from "../../core/warn.js";
|
|
51
|
+
import { resolveValidationRunner, runnerIsLlm } from "../../integrations/agent/runner.js";
|
|
52
|
+
import { chatCompletion } from "../../llm/client.js";
|
|
53
|
+
import { isProcessEnabled } from "../../llm/feature-gate.js";
|
|
54
|
+
import { findEntryIdByRef } from "../db/db.js";
|
|
55
|
+
import { withLlmCache } from "../db/llm-cache.js";
|
|
56
|
+
import { walkMarkdownFiles } from "../walk/walker.js";
|
|
17
57
|
/** Frontmatter keys this pass touches. Constants so a future rename only needs to touch one site. */
|
|
18
58
|
const FM_BELIEF_STATE = "beliefState";
|
|
19
59
|
const FM_SUPERSEDED_BY = "supersededBy";
|
|
@@ -30,7 +70,8 @@ const TOP_K_SIMILAR = 5;
|
|
|
30
70
|
* Top-level entry point. Returns a zero-counters result when the feature is
|
|
31
71
|
* disabled or no validation-tier runner is configured.
|
|
32
72
|
*/
|
|
33
|
-
export async function runStalenessDetectionPass(
|
|
73
|
+
export async function runStalenessDetectionPass(ctx) {
|
|
74
|
+
const { config, sources, signal, db } = ctx;
|
|
34
75
|
const start = Date.now();
|
|
35
76
|
const result = {
|
|
36
77
|
considered: 0,
|
|
@@ -58,7 +99,7 @@ export async function runStalenessDetectionPass(config, sources, signal, db) {
|
|
|
58
99
|
result.durationMs = Date.now() - start;
|
|
59
100
|
return result;
|
|
60
101
|
}
|
|
61
|
-
if (runner
|
|
102
|
+
if (!runnerIsLlm(runner)) {
|
|
62
103
|
// MVP scope: only the LLM runner kind is supported. Agent/SDK runners
|
|
63
104
|
// would require a different prompt-dispatch path that is out of scope
|
|
64
105
|
// for the initial Phase 4A implementation.
|