akm-cli 0.9.0-rc.1 → 0.9.0-rc.13
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 +1190 -52
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/stash-skeleton/README.md +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +13 -9
- package/dist/commands/env/env-cli.js +76 -159
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +75 -228
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -855
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -73
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -58
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +8 -3
- package/dist/integrations/agent/profiles.js +6 -99
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +78 -13
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +48 -279
- package/dist/integrations/harnesses/aider/agent-builder.js +9 -8
- package/dist/integrations/harnesses/aider/index.js +2 -12
- package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -16
- package/dist/integrations/harnesses/amazonq/index.js +3 -17
- package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +1 -14
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +8 -7
- package/dist/integrations/harnesses/codex/index.js +2 -13
- package/dist/integrations/harnesses/copilot/agent-builder.js +9 -9
- package/dist/integrations/harnesses/copilot/index.js +1 -13
- package/dist/integrations/harnesses/gemini/agent-builder.js +8 -9
- package/dist/integrations/harnesses/gemini/index.js +1 -13
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +31 -33
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +1 -18
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +3 -17
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
- package/dist/integrations/harnesses/openhands/agent-builder.js +12 -10
- package/dist/integrations/harnesses/openhands/index.js +2 -12
- package/dist/integrations/harnesses/pi/agent-builder.js +11 -18
- package/dist/integrations/harnesses/pi/index.js +3 -16
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +38 -34
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +24 -40
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +15 -281
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +8 -40
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1375
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +1 -2
- package/dist/output/text.js +10 -19
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +68 -35
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/workflows/authoring/authoring.js +96 -148
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -20
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +25 -59
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +157 -94
- package/dist/workflows/exec/report.js +365 -200
- package/dist/workflows/exec/run-workflow.js +46 -40
- package/dist/workflows/exec/scheduler.js +12 -41
- package/dist/workflows/exec/step-work.js +239 -205
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/ir/compile.js +141 -283
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/plan-hash.js +40 -5
- package/dist/workflows/ir/schema.js +537 -1
- package/dist/workflows/parser.js +878 -306
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +99 -121
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +200 -113
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +235 -97
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +4 -26
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/{dist/schemas → schemas}/akm-workflow.json +127 -82
- package/dist/akm-migrate-storage +0 -38
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -316
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1414
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/schemas/akm-config.json +0 -14225
- package/dist/scripts/migrate-storage.js +0 -13169
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -10169
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1012
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/db.js +0 -350
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -760
- package/dist/workflows/program/project.js +0 -105
- package/docs/data-and-telemetry.md +0 -227
- package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
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
|
+
* Upsert salience scores for one asset into state.db.
|
|
6
|
+
*
|
|
7
|
+
* Idempotent: safe to call every run; updates the outcome / retrieval / rank
|
|
8
|
+
* columns on conflict.
|
|
9
|
+
*
|
|
10
|
+
* #644 — encoding provenance guard: the `encoding_salience` + `encoding_source`
|
|
11
|
+
* columns are NOT lowered from a real content-derived score to a type-weight
|
|
12
|
+
* stub. When the stored row is `encoding_source = 'content'` and the incoming
|
|
13
|
+
* vector is a `type-stub` fallback, the stored encoding score and its provenance
|
|
14
|
+
* are preserved (only the other sub-scores and `rank_score` advance). A `content`
|
|
15
|
+
* write always wins; a `type-stub` write only seeds a row that has no content
|
|
16
|
+
* score yet. This stops the improve loop's type-weight fallback re-asserting the
|
|
17
|
+
* stub over a distill-written score on every run.
|
|
18
|
+
*
|
|
19
|
+
* NOTE: when the guard preserves the stored encoding score, the incoming
|
|
20
|
+
* `vector.rankScore` (computed from the stub encoding) is still written. Callers
|
|
21
|
+
* that want the rank_score to reflect the preserved content score should pass the
|
|
22
|
+
* stored content score back in as `inputs.encodingSalience` to `computeSalience`
|
|
23
|
+
* — which the improve loop does. The guard here is the defensive backstop.
|
|
24
|
+
*/
|
|
25
|
+
export function upsertAssetSalience(db, ref, vector, now) {
|
|
26
|
+
const ts = now ?? Date.now();
|
|
27
|
+
db.prepare(`INSERT INTO asset_salience
|
|
28
|
+
(asset_ref, encoding_salience, outcome_salience, retrieval_salience, rank_score, consecutive_no_ops, updated_at, encoding_source)
|
|
29
|
+
VALUES (?, ?, ?, ?, ?, 0, ?, ?)
|
|
30
|
+
ON CONFLICT(asset_ref) DO UPDATE SET
|
|
31
|
+
-- #644: never lower a real content-derived score to a type-weight stub.
|
|
32
|
+
-- Keep the stored encoding score + provenance when the stored row is
|
|
33
|
+
-- 'content' and the incoming write is a 'type-stub' fallback.
|
|
34
|
+
encoding_salience = CASE
|
|
35
|
+
WHEN asset_salience.encoding_source = 'content' AND excluded.encoding_source = 'type-stub'
|
|
36
|
+
THEN asset_salience.encoding_salience
|
|
37
|
+
ELSE excluded.encoding_salience
|
|
38
|
+
END,
|
|
39
|
+
encoding_source = CASE
|
|
40
|
+
WHEN asset_salience.encoding_source = 'content' AND excluded.encoding_source = 'type-stub'
|
|
41
|
+
THEN asset_salience.encoding_source
|
|
42
|
+
ELSE excluded.encoding_source
|
|
43
|
+
END,
|
|
44
|
+
outcome_salience = excluded.outcome_salience,
|
|
45
|
+
retrieval_salience = excluded.retrieval_salience,
|
|
46
|
+
rank_score = excluded.rank_score,
|
|
47
|
+
updated_at = excluded.updated_at`).run(ref, vector.encoding, vector.outcome, vector.retrieval, vector.rankScore, ts, vector.encodingSource ?? "type-stub");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Load the salience row for one asset, or undefined if not yet computed.
|
|
51
|
+
*/
|
|
52
|
+
export function getAssetSalience(db, ref) {
|
|
53
|
+
const row = db
|
|
54
|
+
.prepare(`SELECT asset_ref, encoding_salience, outcome_salience, retrieval_salience,
|
|
55
|
+
rank_score, consecutive_no_ops, updated_at, encoding_source
|
|
56
|
+
FROM asset_salience WHERE asset_ref = ?`)
|
|
57
|
+
.get(ref);
|
|
58
|
+
// Bun SQLite returns null (not undefined) when no row found.
|
|
59
|
+
return row == null ? undefined : row;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Load ALL rank scores from the asset_salience table (full-stash query).
|
|
63
|
+
*
|
|
64
|
+
* Used by the forgetting-safety report (plan §WS-1 step 7) to compute stash-wide
|
|
65
|
+
* rank positions rather than pool-relative positions. Returns an empty Map when the
|
|
66
|
+
* table is empty (first WS-1 run = no pre-existing rows).
|
|
67
|
+
*
|
|
68
|
+
* Order is unspecified; callers must sort before assigning 1-indexed positions.
|
|
69
|
+
*/
|
|
70
|
+
export function getAllRankScores(db) {
|
|
71
|
+
const rows = db.prepare("SELECT asset_ref, rank_score FROM asset_salience").all();
|
|
72
|
+
const result = new Map();
|
|
73
|
+
for (const row of rows) {
|
|
74
|
+
result.set(row.asset_ref, row.rank_score);
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
// ── Plasticity helpers ────────────────────────────────────────────────────────
|
|
79
|
+
/**
|
|
80
|
+
* Increment `consecutive_no_ops` for an asset. Called after a no-op reflect/distill.
|
|
81
|
+
* Has NO effect on `rank_score` — the plasticity counter only dampens consolidation
|
|
82
|
+
* selection, not retrieval ranking. See plan §WS-1 step 8.
|
|
83
|
+
*
|
|
84
|
+
* Invariant: recordNoOp must never originate rank_score semantics. If the asset has
|
|
85
|
+
* no salience row yet (persistence's best-effort try/catch may have swallowed an
|
|
86
|
+
* error), we do nothing — a no-op counter is meaningless without a rank_score row,
|
|
87
|
+
* and a synthetic INSERT would fabricate a rank_score=0 entry that could produce
|
|
88
|
+
* false catastrophic-forgetting signals in buildRankChangeReport.
|
|
89
|
+
*/
|
|
90
|
+
export function recordNoOp(db, ref) {
|
|
91
|
+
db.prepare(`UPDATE asset_salience SET consecutive_no_ops = consecutive_no_ops + 1, updated_at = ? WHERE asset_ref = ?`).run(Date.now(), ref);
|
|
92
|
+
// If changes === 0 the asset has no salience row yet — leave the table unchanged.
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Reset `consecutive_no_ops` to 0 when an asset produces an accepted change.
|
|
96
|
+
* Call after a successful proposal acceptance or detected mutation.
|
|
97
|
+
*/
|
|
98
|
+
export function resetConsecutiveNoOps(db, ref) {
|
|
99
|
+
db.prepare(`UPDATE asset_salience SET consecutive_no_ops = 0, updated_at = ? WHERE asset_ref = ?`).run(Date.now(), ref);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Return the `consecutive_no_ops` count for one asset. 0 when unknown.
|
|
103
|
+
*/
|
|
104
|
+
export function getConsecutiveNoOps(db, ref) {
|
|
105
|
+
const row = db.prepare(`SELECT consecutive_no_ops FROM asset_salience WHERE asset_ref = ?`).get(ref);
|
|
106
|
+
return row?.consecutive_no_ops ?? 0;
|
|
107
|
+
}
|
|
108
|
+
// ── New in #672 part 2 ────────────────────────────────────────────────────────
|
|
109
|
+
/**
|
|
110
|
+
* Load the `retrieval_salience` column for the top `limit` assets ordered by
|
|
111
|
+
* `rank_score` descending.
|
|
112
|
+
*
|
|
113
|
+
* Absorbs the health read formerly inlined in `commands/health/metrics.ts`
|
|
114
|
+
* (`computeDegradationMetrics`'s corpus-diversity Gini calculation) — same
|
|
115
|
+
* query, now parameterised on `limit` instead of a hardcoded 100. This is new
|
|
116
|
+
* behavior (a named, parameterised repository entry point), not a verbatim
|
|
117
|
+
* move; callers that need fail-open behaviour on a missing table (pre-WS-1
|
|
118
|
+
* installs) must wrap the call in their own try/catch, matching the existing
|
|
119
|
+
* call site.
|
|
120
|
+
*/
|
|
121
|
+
export function getTopRetrievalSalience(db, limit) {
|
|
122
|
+
return db
|
|
123
|
+
.prepare(`SELECT retrieval_salience FROM asset_salience ORDER BY rank_score DESC LIMIT ?`)
|
|
124
|
+
.all(limit);
|
|
125
|
+
}
|
|
126
|
+
/** List every `asset_salience` ref with its current `missing_since` marker. */
|
|
127
|
+
export function listAssetSalienceMissingState(db) {
|
|
128
|
+
return db.prepare(`SELECT asset_ref, missing_since FROM asset_salience`).all();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Stamp `missing_since = now` for the given refs, but ONLY where it is
|
|
132
|
+
* currently NULL — a ref already stamped keeps its original timestamp so the
|
|
133
|
+
* grace window measures from first sighting, not last. Refs with no row at
|
|
134
|
+
* all are silently skipped (0 rows affected). Returns the number of rows
|
|
135
|
+
* actually stamped.
|
|
136
|
+
*/
|
|
137
|
+
export function stampAssetSalienceMissing(db, refs, now) {
|
|
138
|
+
if (refs.length === 0)
|
|
139
|
+
return 0;
|
|
140
|
+
const stmt = db.prepare(`UPDATE asset_salience SET missing_since = ? WHERE asset_ref = ? AND missing_since IS NULL`);
|
|
141
|
+
let changed = 0;
|
|
142
|
+
for (const ref of refs)
|
|
143
|
+
changed += Number(stmt.run(now, ref).changes);
|
|
144
|
+
return changed;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Clear `missing_since` for refs that resolved again. Returns the number of
|
|
148
|
+
* rows actually cleared.
|
|
149
|
+
*/
|
|
150
|
+
export function clearAssetSalienceMissing(db, refs) {
|
|
151
|
+
if (refs.length === 0)
|
|
152
|
+
return 0;
|
|
153
|
+
const stmt = db.prepare(`UPDATE asset_salience SET missing_since = NULL WHERE asset_ref = ? AND missing_since IS NOT NULL`);
|
|
154
|
+
let changed = 0;
|
|
155
|
+
for (const ref of refs)
|
|
156
|
+
changed += Number(stmt.run(ref).changes);
|
|
157
|
+
return changed;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Delete `asset_salience` rows whose `missing_since` is older than
|
|
161
|
+
* `cutoffMs`. A single DELETE — SQLite runs it as one implicit transaction.
|
|
162
|
+
* Returns the number of rows deleted.
|
|
163
|
+
*/
|
|
164
|
+
export function deleteAssetSalienceMissingBefore(db, cutoffMs) {
|
|
165
|
+
return Number(db.prepare(`DELETE FROM asset_salience WHERE missing_since IS NOT NULL AND missing_since < ?`).run(cutoffMs)
|
|
166
|
+
.changes);
|
|
167
|
+
}
|
|
168
|
+
/** Count `asset_salience` rows currently marked missing (the live backlog size). */
|
|
169
|
+
export function countAssetSalienceMissing(db) {
|
|
170
|
+
const row = db.prepare(`SELECT COUNT(*) AS n FROM asset_salience WHERE missing_since IS NOT NULL`).get();
|
|
171
|
+
return row.n;
|
|
172
|
+
}
|
|
@@ -1,6 +1,110 @@
|
|
|
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
|
+
function metadataError(message) {
|
|
5
|
+
throw new Error(`invalid task_history metadata_json: ${message}`);
|
|
6
|
+
}
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function validateDetail(value) {
|
|
11
|
+
if (value === undefined || value === null)
|
|
12
|
+
return;
|
|
13
|
+
if (!isRecord(value))
|
|
14
|
+
metadataError("detail must be an object or null");
|
|
15
|
+
const allowed = new Set(["runId", "reason", "error", "exitCode"]);
|
|
16
|
+
const unknown = Object.keys(value).filter((key) => !allowed.has(key));
|
|
17
|
+
if (unknown.length > 0)
|
|
18
|
+
metadataError(`unknown detail fields: ${unknown.sort().join(", ")}`);
|
|
19
|
+
for (const field of ["runId", "reason", "error"]) {
|
|
20
|
+
if (value[field] !== undefined && typeof value[field] !== "string")
|
|
21
|
+
metadataError(`detail.${field} must be a string`);
|
|
22
|
+
}
|
|
23
|
+
if (value.exitCode !== undefined && value.exitCode !== null && typeof value.exitCode !== "number") {
|
|
24
|
+
metadataError("detail.exitCode must be a number or null");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Decode supported historical and current task-history metadata. */
|
|
28
|
+
export function decodeTaskHistoryMetadata(input) {
|
|
29
|
+
let parsed = input;
|
|
30
|
+
if (typeof input === "string") {
|
|
31
|
+
try {
|
|
32
|
+
parsed = JSON.parse(input);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
metadataError("not valid JSON");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!isRecord(parsed))
|
|
39
|
+
metadataError("root must be an object");
|
|
40
|
+
if (parsed.metadataVersion === undefined || parsed.metadataVersion === 1) {
|
|
41
|
+
const allowed = new Set(["metadataVersion", "durationMs", "detail", "profile"]);
|
|
42
|
+
const unknown = Object.keys(parsed).filter((key) => !allowed.has(key));
|
|
43
|
+
if (unknown.length > 0)
|
|
44
|
+
metadataError(`unknown v1 fields: ${unknown.sort().join(", ")}`);
|
|
45
|
+
if (parsed.durationMs !== undefined && typeof parsed.durationMs !== "number") {
|
|
46
|
+
metadataError("durationMs must be a number");
|
|
47
|
+
}
|
|
48
|
+
if (parsed.profile !== undefined && typeof parsed.profile !== "string") {
|
|
49
|
+
metadataError("profile must be a string");
|
|
50
|
+
}
|
|
51
|
+
validateDetail(parsed.detail);
|
|
52
|
+
return {
|
|
53
|
+
metadataVersion: 1,
|
|
54
|
+
durationMs: parsed.durationMs ?? 0,
|
|
55
|
+
detail: parsed.detail ?? null,
|
|
56
|
+
...(parsed.profile !== undefined ? { legacyProfile: parsed.profile } : {}),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (parsed.metadataVersion === 2) {
|
|
60
|
+
const allowed = new Set(["metadataVersion", "durationMs", "detail", "engine"]);
|
|
61
|
+
const unknown = Object.keys(parsed).filter((key) => !allowed.has(key));
|
|
62
|
+
if (unknown.length > 0)
|
|
63
|
+
metadataError(`unknown v2 fields: ${unknown.sort().join(", ")}`);
|
|
64
|
+
if (typeof parsed.durationMs !== "number")
|
|
65
|
+
metadataError("durationMs must be a number");
|
|
66
|
+
if (!("detail" in parsed))
|
|
67
|
+
metadataError("detail is required in v2");
|
|
68
|
+
if (parsed.engine !== undefined && parsed.engine !== null && typeof parsed.engine !== "string") {
|
|
69
|
+
metadataError("engine must be a string or null");
|
|
70
|
+
}
|
|
71
|
+
validateDetail(parsed.detail);
|
|
72
|
+
return {
|
|
73
|
+
metadataVersion: 2,
|
|
74
|
+
durationMs: parsed.durationMs,
|
|
75
|
+
detail: parsed.detail ?? null,
|
|
76
|
+
...(parsed.engine !== undefined ? { engine: parsed.engine } : {}),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
metadataError(`unsupported metadataVersion: ${String(parsed.metadataVersion)}`);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Atomically reserve one task-attempt identity.
|
|
83
|
+
*
|
|
84
|
+
* The existing unique `(task_id, started_at)` index arbitrates concurrent
|
|
85
|
+
* processes: exactly one caller receives `true` for a candidate timestamp.
|
|
86
|
+
* Callers can advance by one millisecond and retry without a schema change.
|
|
87
|
+
*/
|
|
88
|
+
export function reserveTaskHistoryAttempt(db, row) {
|
|
89
|
+
const result = db
|
|
90
|
+
.prepare(`INSERT OR IGNORE INTO task_history
|
|
91
|
+
(task_id, status, started_at, completed_at, failed_at, log_path,
|
|
92
|
+
target_kind, target_ref, metadata_json)
|
|
93
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
94
|
+
.run(row.task_id, row.status, row.started_at, row.completed_at ?? null, row.failed_at ?? null, row.log_path ?? null, row.target_kind ?? null, row.target_ref ?? null, row.metadata_json);
|
|
95
|
+
return Number(result.changes) === 1;
|
|
96
|
+
}
|
|
97
|
+
/** Finalize a row previously created by {@link reserveTaskHistoryAttempt}. */
|
|
98
|
+
export function finalizeTaskHistoryAttempt(db, row) {
|
|
99
|
+
const result = db
|
|
100
|
+
.prepare(`UPDATE task_history
|
|
101
|
+
SET status = ?, completed_at = ?, failed_at = ?, log_path = ?,
|
|
102
|
+
target_kind = ?, target_ref = ?, metadata_json = ?
|
|
103
|
+
WHERE task_id = ? AND started_at = ?
|
|
104
|
+
AND status = 'active' AND completed_at IS NULL`)
|
|
105
|
+
.run(row.status, row.completed_at ?? null, row.failed_at ?? null, row.log_path ?? null, row.target_kind ?? null, row.target_ref ?? null, row.metadata_json, row.task_id, row.started_at);
|
|
106
|
+
return Number(result.changes) === 1;
|
|
107
|
+
}
|
|
4
108
|
/**
|
|
5
109
|
* Upsert a task history row.
|
|
6
110
|
*/
|
|
@@ -24,7 +128,7 @@ export function getTaskHistory(db, taskId) {
|
|
|
24
128
|
return db
|
|
25
129
|
.prepare(`SELECT id, task_id, status, started_at, completed_at, failed_at, log_path,
|
|
26
130
|
target_kind, target_ref, metadata_json
|
|
27
|
-
FROM task_history WHERE task_id = ? ORDER BY started_at DESC LIMIT 1`)
|
|
131
|
+
FROM task_history WHERE task_id = ? ORDER BY started_at DESC, id DESC LIMIT 1`)
|
|
28
132
|
.get(taskId);
|
|
29
133
|
}
|
|
30
134
|
/**
|
|
@@ -34,7 +138,7 @@ export function getTaskHistoryRuns(db, taskId, limit = 50) {
|
|
|
34
138
|
return db
|
|
35
139
|
.prepare(`SELECT id, task_id, status, started_at, completed_at, failed_at, log_path,
|
|
36
140
|
target_kind, target_ref, metadata_json
|
|
37
|
-
FROM task_history WHERE task_id = ? ORDER BY started_at DESC LIMIT ?`)
|
|
141
|
+
FROM task_history WHERE task_id = ? ORDER BY started_at DESC, id DESC LIMIT ?`)
|
|
38
142
|
.all(taskId, limit);
|
|
39
143
|
}
|
|
40
144
|
/**
|
|
@@ -64,10 +168,13 @@ export function queryTaskHistory(db, options = {}) {
|
|
|
64
168
|
params.push(options.targetRef);
|
|
65
169
|
}
|
|
66
170
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
171
|
+
const limit = options.limit !== undefined ? "LIMIT ?" : "";
|
|
172
|
+
if (options.limit !== undefined)
|
|
173
|
+
params.push(options.limit);
|
|
67
174
|
return db
|
|
68
175
|
.prepare(`SELECT task_id, status, started_at, completed_at, failed_at, log_path,
|
|
69
176
|
target_kind, target_ref, metadata_json
|
|
70
|
-
FROM task_history ${where} ORDER BY started_at DESC`)
|
|
177
|
+
FROM task_history ${where} ORDER BY started_at DESC, id DESC ${limit}`)
|
|
71
178
|
.all(...params);
|
|
72
179
|
}
|
|
73
180
|
/**
|
|
@@ -1,13 +1,15 @@
|
|
|
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
|
-
import {
|
|
4
|
+
import { openStateDatabase, withImmediateTransaction } from "../../core/state-db.js";
|
|
5
5
|
import { resolveStorageLocations } from "../locations.js";
|
|
6
6
|
/**
|
|
7
7
|
* Repository owning every raw SQL statement against `workflow_runs` and
|
|
8
8
|
* `workflow_run_steps`. It is DB-location-agnostic: the lifecycle helper
|
|
9
|
-
* {@link withWorkflowRunsRepo} binds it to {@link StorageLocations.
|
|
10
|
-
*
|
|
9
|
+
* {@link withWorkflowRunsRepo} binds it to {@link StorageLocations.stateDb}
|
|
10
|
+
* (the three-DB cutover folded workflow.db into state.db; the tables exist via
|
|
11
|
+
* state migration `020-three-db-cutover`) so a future storage move (#489)
|
|
12
|
+
* changes only `locations.ts`.
|
|
11
13
|
*
|
|
12
14
|
* ## Connection-lifetime contract (WS5)
|
|
13
15
|
*
|
|
@@ -28,19 +30,28 @@ export class WorkflowRunsRepository {
|
|
|
28
30
|
transaction(fn) {
|
|
29
31
|
return this.db.transaction(fn)();
|
|
30
32
|
}
|
|
33
|
+
immediateTransaction(fn) {
|
|
34
|
+
return withImmediateTransaction(this.db, () => fn(this.db));
|
|
35
|
+
}
|
|
31
36
|
// ── reads (fully materialised) ─────────────────────────────────────────────
|
|
32
|
-
findActiveRunForScope(
|
|
37
|
+
findActiveRunForScope(workflowRefs, scopeKey) {
|
|
38
|
+
const refs = typeof workflowRefs === "string" ? [workflowRefs] : [...workflowRefs];
|
|
39
|
+
if (refs.length === 0)
|
|
40
|
+
return undefined;
|
|
33
41
|
return this.db
|
|
34
|
-
.prepare(
|
|
35
|
-
.get(
|
|
42
|
+
.prepare(`SELECT id, current_step_id FROM workflow_runs WHERE workflow_ref IN (${refs.map(() => "?").join(", ")}) AND scope_key = ? AND status = 'active' ORDER BY updated_at DESC, created_at DESC LIMIT 1`)
|
|
43
|
+
.get(...refs, scopeKey);
|
|
36
44
|
}
|
|
37
45
|
getRunById(runId) {
|
|
38
46
|
return this.db.prepare("SELECT * FROM workflow_runs WHERE id = ?").get(runId);
|
|
39
47
|
}
|
|
40
|
-
getActiveRunRowForScope(
|
|
48
|
+
getActiveRunRowForScope(workflowRefs, scopeKey) {
|
|
49
|
+
const refs = typeof workflowRefs === "string" ? [workflowRefs] : [...workflowRefs];
|
|
50
|
+
if (refs.length === 0)
|
|
51
|
+
return undefined;
|
|
41
52
|
return this.db
|
|
42
|
-
.prepare(
|
|
43
|
-
.get(
|
|
53
|
+
.prepare(`SELECT * FROM workflow_runs WHERE workflow_ref IN (${refs.map(() => "?").join(", ")}) AND scope_key = ? AND status = 'active' ORDER BY updated_at DESC, created_at DESC LIMIT 1`)
|
|
54
|
+
.get(...refs, scopeKey);
|
|
44
55
|
}
|
|
45
56
|
hasRun(runId) {
|
|
46
57
|
const row = this.db.prepare("SELECT 1 FROM workflow_runs WHERE id = ? LIMIT 1").get(runId);
|
|
@@ -55,6 +66,10 @@ export class WorkflowRunsRepository {
|
|
|
55
66
|
filters.push("workflow_ref = ?");
|
|
56
67
|
params.push(filter.workflowRef);
|
|
57
68
|
}
|
|
69
|
+
else if (filter.workflowRefs && filter.workflowRefs.length > 0) {
|
|
70
|
+
filters.push(`workflow_ref IN (${filter.workflowRefs.map(() => "?").join(", ")})`);
|
|
71
|
+
params.push(...filter.workflowRefs);
|
|
72
|
+
}
|
|
58
73
|
if (filter.activeOnly) {
|
|
59
74
|
// `activeOnly` means EXACTLY status='active' — a run currently
|
|
60
75
|
// executable. A `blocked` run is NOT active (it is parked awaiting a
|
|
@@ -111,7 +126,9 @@ export class WorkflowRunsRepository {
|
|
|
111
126
|
.run(runId, currentStepId);
|
|
112
127
|
}
|
|
113
128
|
markRunActive(runId, updatedAt) {
|
|
114
|
-
this.db
|
|
129
|
+
this.db
|
|
130
|
+
.prepare("UPDATE workflow_runs SET status = 'active', updated_at = ?, engine_lease_holder = NULL, engine_lease_until = NULL WHERE id = ?")
|
|
131
|
+
.run(updatedAt, runId);
|
|
115
132
|
}
|
|
116
133
|
updateStepCompletion(input) {
|
|
117
134
|
this.db
|
|
@@ -127,6 +144,14 @@ export class WorkflowRunsRepository {
|
|
|
127
144
|
WHERE id = ?`)
|
|
128
145
|
.run(input.status, input.currentStepId, input.updatedAt, input.completedAt, input.checkinArmedAt, input.runId);
|
|
129
146
|
}
|
|
147
|
+
markRunAbandoned(runId, updatedAt) {
|
|
148
|
+
const result = this.db
|
|
149
|
+
.prepare(`UPDATE workflow_runs
|
|
150
|
+
SET status = 'failed', updated_at = ?, completed_at = ?, checkin_armed_at = ?
|
|
151
|
+
WHERE id = ? AND status IN ('active', 'blocked')`)
|
|
152
|
+
.run(updatedAt, updatedAt, updatedAt, runId);
|
|
153
|
+
return Number(result.changes) === 1;
|
|
154
|
+
}
|
|
130
155
|
rearmCheckin(runId, checkinArmedAt) {
|
|
131
156
|
this.db.prepare("UPDATE workflow_runs SET checkin_armed_at = ? WHERE id = ?").run(checkinArmedAt, runId);
|
|
132
157
|
}
|
|
@@ -137,10 +162,10 @@ export class WorkflowRunsRepository {
|
|
|
137
162
|
* `insertRun`, so a run row never exists without its frozen plan. Read back
|
|
138
163
|
* via {@link getRunById} (`plan_json` / `plan_hash` on the row).
|
|
139
164
|
*/
|
|
140
|
-
setRunPlan(runId, planJson, planHash) {
|
|
165
|
+
setRunPlan(runId, planJson, planHash, planIrVersion = 3) {
|
|
141
166
|
this.db
|
|
142
|
-
.prepare("UPDATE workflow_runs SET plan_json = ?, plan_hash = ? WHERE id = ?")
|
|
143
|
-
.run(planJson, planHash, runId);
|
|
167
|
+
.prepare("UPDATE workflow_runs SET plan_json = ?, plan_hash = ?, plan_ir_version = ? WHERE id = ?")
|
|
168
|
+
.run(planJson, planHash, planIrVersion, runId);
|
|
144
169
|
}
|
|
145
170
|
// ── engine run lease (migration 006 columns, R2 enforcement) ──────────────
|
|
146
171
|
//
|
|
@@ -159,7 +184,8 @@ export class WorkflowRunsRepository {
|
|
|
159
184
|
const result = this.db
|
|
160
185
|
.prepare(`UPDATE workflow_runs
|
|
161
186
|
SET engine_lease_holder = ?, engine_lease_until = ?
|
|
162
|
-
WHERE id = ? AND
|
|
187
|
+
WHERE id = ? AND status = 'active'
|
|
188
|
+
AND (engine_lease_holder IS NULL OR engine_lease_until IS NULL OR engine_lease_until < ?)`)
|
|
163
189
|
.run(holder, until, runId, now);
|
|
164
190
|
return Number(result.changes) > 0;
|
|
165
191
|
}
|
|
@@ -170,18 +196,18 @@ export class WorkflowRunsRepository {
|
|
|
170
196
|
*/
|
|
171
197
|
renewEngineLease(runId, holder, until) {
|
|
172
198
|
const result = this.db
|
|
173
|
-
.prepare("UPDATE workflow_runs SET engine_lease_until = ? WHERE id = ? AND engine_lease_holder = ?")
|
|
199
|
+
.prepare("UPDATE workflow_runs SET engine_lease_until = ? WHERE id = ? AND engine_lease_holder = ? AND status = 'active'")
|
|
174
200
|
.run(until, runId, holder);
|
|
175
201
|
return Number(result.changes) > 0;
|
|
176
202
|
}
|
|
177
203
|
/**
|
|
178
|
-
* Clear the lease
|
|
179
|
-
*
|
|
180
|
-
*
|
|
204
|
+
* Clear the lease only while `holder` still owns a non-failed run. Failed
|
|
205
|
+
* runs retain the final holder/expiry for forensics until explicit resume.
|
|
206
|
+
* Releasing an already-lost lease is a harmless no-op.
|
|
181
207
|
*/
|
|
182
208
|
releaseEngineLease(runId, holder) {
|
|
183
209
|
this.db
|
|
184
|
-
.prepare("UPDATE workflow_runs SET engine_lease_holder = NULL, engine_lease_until = NULL WHERE id = ? AND engine_lease_holder = ?")
|
|
210
|
+
.prepare("UPDATE workflow_runs SET engine_lease_holder = NULL, engine_lease_until = NULL WHERE id = ? AND engine_lease_holder = ? AND status <> 'failed'")
|
|
185
211
|
.run(runId, holder);
|
|
186
212
|
}
|
|
187
213
|
// ── unit rows (migration 004) ──────────────────────────────────────────────
|
|
@@ -238,15 +264,16 @@ export class WorkflowRunsRepository {
|
|
|
238
264
|
insertUnit(input) {
|
|
239
265
|
this.db
|
|
240
266
|
.prepare(`INSERT INTO workflow_run_units (
|
|
241
|
-
run_id, unit_id, step_id, node_id, parent_unit_id, phase, runner, model,
|
|
267
|
+
run_id, unit_id, step_id, node_id, parent_unit_id, phase, runner, engine, model,
|
|
242
268
|
status, input_hash, worktree_path, started_at, claim_holder, claim_expires_at
|
|
243
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'running', ?, ?, ?, ?, ?)
|
|
269
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'running', ?, ?, ?, ?, ?)
|
|
244
270
|
ON CONFLICT(run_id, unit_id) DO UPDATE SET
|
|
245
271
|
step_id = excluded.step_id,
|
|
246
272
|
node_id = excluded.node_id,
|
|
247
273
|
parent_unit_id = excluded.parent_unit_id,
|
|
248
|
-
|
|
249
|
-
|
|
274
|
+
phase = excluded.phase,
|
|
275
|
+
runner = excluded.runner,
|
|
276
|
+
engine = excluded.engine,
|
|
250
277
|
model = excluded.model,
|
|
251
278
|
status = excluded.status,
|
|
252
279
|
input_hash = excluded.input_hash,
|
|
@@ -261,7 +288,7 @@ export class WorkflowRunsRepository {
|
|
|
261
288
|
finished_at = NULL,
|
|
262
289
|
last_checkin_at = NULL,
|
|
263
290
|
attempts = workflow_run_units.attempts + 1`)
|
|
264
|
-
.run(input.runId, input.unitId, input.stepId, input.nodeId, input.parentUnitId, input.phase, input.runner, input.model, input.inputHash, input.worktreePath ?? null, input.startedAt, input.claimHolder ?? null, input.claimExpiresAt ?? null);
|
|
291
|
+
.run(input.runId, input.unitId, input.stepId, input.nodeId, input.parentUnitId, input.phase, input.runner, input.engine ?? null, input.model, input.inputHash, input.worktreePath ?? null, input.startedAt, input.claimHolder ?? null, input.claimExpiresAt ?? null);
|
|
265
292
|
}
|
|
266
293
|
/**
|
|
267
294
|
* Stamp a `--status running` claim + heartbeat on a unit row (migration 009,
|
|
@@ -273,11 +300,13 @@ export class WorkflowRunsRepository {
|
|
|
273
300
|
* marker set by {@link insertUnit}).
|
|
274
301
|
*/
|
|
275
302
|
updateUnitClaim(runId, unitId, holder, expiresAt, lastCheckinAt) {
|
|
276
|
-
this.db
|
|
303
|
+
const result = this.db
|
|
277
304
|
.prepare(`UPDATE workflow_run_units
|
|
278
305
|
SET status = 'running', last_checkin_at = ?, claim_holder = ?, claim_expires_at = ?
|
|
279
|
-
WHERE run_id = ? AND unit_id =
|
|
280
|
-
|
|
306
|
+
WHERE run_id = ? AND unit_id = ?
|
|
307
|
+
AND EXISTS (SELECT 1 FROM workflow_runs WHERE id = ? AND status = 'active')`)
|
|
308
|
+
.run(lastCheckinAt, holder, expiresAt, runId, unitId, runId);
|
|
309
|
+
return Number(result.changes) === 1;
|
|
281
310
|
}
|
|
282
311
|
/**
|
|
283
312
|
* Record a unit's terminal state (completed / failed / skipped).
|
|
@@ -310,20 +339,24 @@ export class WorkflowRunsRepository {
|
|
|
310
339
|
}
|
|
311
340
|
}
|
|
312
341
|
/**
|
|
313
|
-
* Open
|
|
314
|
-
*
|
|
315
|
-
*
|
|
342
|
+
* Open state.db (bound to {@link StorageLocations.stateDb}, the post-cutover
|
|
343
|
+
* home of the `workflow_runs` / `workflow_run_steps` / `workflow_run_units`
|
|
344
|
+
* tables), run `fn` against a {@link WorkflowRunsRepository}, and close the
|
|
345
|
+
* connection exactly once when `fn` settles.
|
|
316
346
|
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
347
|
+
* Fresh-connection-per-call, mirroring the former workflow.db loan pattern:
|
|
348
|
+
* `openStateDatabase` acquires its own maintenance activity + asserts the
|
|
349
|
+
* current ledger, and the repository owns all table-scoped SQL, so the merge
|
|
350
|
+
* into state.db is a zero-SQL-rewrite repoint. Repository read methods fully
|
|
351
|
+
* materialise their results, so closing here never truncates lazy iteration
|
|
352
|
+
* (WS5 connection-lifetime rule).
|
|
320
353
|
*/
|
|
321
354
|
export async function withWorkflowRunsRepo(fn) {
|
|
322
|
-
const db =
|
|
355
|
+
const db = openStateDatabase(resolveStorageLocations().stateDb);
|
|
323
356
|
try {
|
|
324
357
|
return await Promise.resolve(fn(new WorkflowRunsRepository(db)));
|
|
325
358
|
}
|
|
326
359
|
finally {
|
|
327
|
-
|
|
360
|
+
db.close();
|
|
328
361
|
}
|
|
329
362
|
}
|