akm-cli 0.9.0-rc.9 → 0.9.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1770 -44
- package/README.md +38 -47
- package/SECURITY.md +14 -1
- package/STABILITY.md +499 -0
- package/dist/akm +148 -35
- package/dist/{akm-migrate-storage → akm-migrate} +6 -9
- package/dist/assets/hints/cli-hints-full.md +223 -95
- package/dist/assets/hints/cli-hints-short.md +85 -22
- package/dist/assets/improve-strategies/default.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/stash-skeleton/README.md +6 -5
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
- package/dist/assets/tasks/core/extract.yml +1 -1
- package/dist/assets/tasks/core/version-check.yml +1 -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 +1 -3
- package/dist/assets/workflows/workflow-template.md +32 -15
- package/dist/cli/invocation.js +40 -15
- package/dist/cli/parse-args.js +0 -22
- package/dist/cli/retired-commands.js +121 -0
- package/dist/cli/shared.js +154 -22
- package/dist/cli/unknown-flags.js +236 -0
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +696 -258
- package/dist/commands/agent/agent-dispatch.js +14 -3
- package/dist/commands/agent/contribute-cli.js +74 -89
- package/dist/commands/completions.js +79 -22
- package/dist/commands/config-cli.js +17 -150
- package/dist/commands/env/env-cli.js +59 -143
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +36 -66
- package/dist/commands/env/secret.js +24 -57
- package/dist/commands/feedback-cli.js +148 -88
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +3 -4
- package/dist/commands/health/checks.js +85 -23
- package/dist/commands/health/html-report.js +7 -10
- package/dist/commands/health/improve-metrics.js +25 -83
- package/dist/commands/health/llm-usage.js +2 -1
- package/dist/commands/health/md-report.js +5 -9
- package/dist/commands/health/metrics.js +62 -20
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +4 -5
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +4 -122
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/commands/health/types-improve.js +7 -0
- package/dist/commands/health.js +160 -35
- package/dist/commands/improve/anti-collapse.js +2 -2
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +41 -40
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +140 -1000
- package/dist/commands/improve/distill/promote-memory.js +12 -12
- package/dist/commands/improve/distill/quality-gate.js +11 -6
- package/dist/commands/improve/distill.js +58 -69
- package/dist/commands/improve/eligibility.js +101 -55
- package/dist/commands/improve/extract-cli.js +14 -133
- package/dist/commands/improve/improve-cli.js +98 -114
- package/dist/commands/improve/improve-result-file.js +1 -28
- package/dist/commands/improve/improve-strategies.js +8 -5
- package/dist/commands/improve/improve.js +254 -101
- package/dist/commands/improve/locks.js +7 -0
- package/dist/commands/improve/loop-stages.js +182 -20
- package/dist/commands/improve/memory/derived-ref.js +45 -43
- package/dist/commands/improve/memory/memory-belief.js +1 -1
- package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
- package/dist/commands/improve/memory/memory-improve.js +14 -5
- package/dist/commands/improve/outcome-loop.js +22 -65
- package/dist/commands/improve/preparation.js +114 -123
- package/dist/commands/improve/proactive-maintenance.js +2 -5
- package/dist/commands/improve/reflect.js +56 -160
- package/dist/commands/improve/run-context.js +5 -0
- package/dist/commands/improve/salience.js +11 -122
- package/dist/commands/improve/session-asset.js +4 -0
- package/dist/commands/improve/source-identity.js +10 -38
- package/dist/commands/lint/base-linter.js +51 -131
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +444 -88
- package/dist/commands/lint/types.js +22 -1
- package/dist/commands/{events.js → log.js} +33 -38
- package/dist/commands/migrate-cli.js +92 -12
- package/dist/commands/migration-tool.js +46 -0
- package/dist/commands/observability-cli.js +70 -209
- package/dist/commands/proposal/drain.js +101 -29
- package/dist/commands/proposal/proposal-cli.js +76 -48
- package/dist/commands/proposal/proposal.js +54 -18
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +23 -15
- package/dist/commands/proposal/repository.js +718 -279
- package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
- package/dist/commands/proposal/validators/proposal-validators.js +55 -7
- package/dist/commands/proposal/validators/proposals.js +4 -7
- package/dist/commands/read/curate.js +34 -53
- package/dist/commands/read/knowledge.js +150 -95
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +42 -15
- package/dist/commands/read/search-cli.js +180 -78
- package/dist/commands/read/search.js +58 -43
- package/dist/commands/read/show.js +197 -141
- package/dist/commands/registry-cli.js +12 -51
- package/dist/commands/remember.js +14 -57
- package/dist/commands/sources/add-cli.js +100 -31
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +7 -2
- package/dist/commands/sources/info.js +30 -7
- package/dist/commands/sources/init.js +12 -12
- package/dist/commands/sources/installed-stashes.js +387 -98
- package/dist/commands/sources/schema-repair.js +3 -2
- package/dist/commands/sources/self-update.js +131 -38
- package/dist/commands/sources/source-add.js +72 -17
- package/dist/commands/sources/source-clone.js +129 -45
- package/dist/commands/sources/source-manage.js +43 -23
- package/dist/commands/sources/sources-cli.js +57 -208
- package/dist/commands/sources/stash-cli.js +46 -53
- package/dist/commands/tasks/tasks-cli.js +91 -97
- package/dist/commands/tasks/tasks.js +284 -423
- package/dist/commands/workflow-cli.js +181 -450
- package/dist/core/abort-deadline.js +28 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +67 -5
- package/dist/core/adapter/adapters/akm-adapter.js +60 -38
- package/dist/core/adapter/adapters/akm-lint.js +109 -42
- package/dist/core/adapter/adapters/akm-metadata.js +15 -44
- package/dist/core/adapter/adapters/akm-task-adapter.js +54 -31
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
- package/dist/core/adapter/adapters/index.js +6 -6
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
- package/dist/core/adapter/adapters/okf-adapter.js +187 -19
- package/dist/core/adapter/adapters/shared.js +3 -19
- package/dist/core/adapter/adapters/tool-dir-shared.js +13 -6
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +6 -4
- package/dist/core/adapter/validate-context.js +214 -0
- package/dist/core/asset/akm-markdown.js +63 -0
- package/dist/core/asset/asset-placement.js +20 -6
- package/dist/core/asset/asset-ref.js +11 -9
- package/dist/core/asset/frontmatter-lint.js +30 -0
- package/dist/core/asset/frontmatter.js +29 -9
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +89 -18
- package/dist/core/asset/stash-meta.js +1 -1
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +218 -44
- package/dist/core/concurrent.js +32 -0
- package/dist/core/config/config-io.js +12 -1
- package/dist/core/config/config-schema.js +35 -8
- package/dist/core/config/config-sources.js +55 -11
- package/dist/core/config/config-walker.js +25 -9
- package/dist/core/config/config.js +9 -48
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +5 -1
- package/dist/core/config/schema/experimental.js +30 -0
- package/dist/core/config/schema/improve-processes.js +0 -6
- package/dist/core/config/schema/improve.js +21 -3
- package/dist/core/config/schema/index-config.js +8 -15
- package/dist/core/config/schema/output.js +4 -1
- package/dist/core/config/schema/setup.js +9 -18
- package/dist/core/config/schema/sources-bundles.js +49 -33
- package/dist/core/config/schema/workflow.js +14 -3
- package/dist/core/env-secret-ref.js +76 -46
- package/dist/core/errors.js +43 -12
- package/dist/core/events.js +76 -152
- package/dist/core/file-change.js +6 -5
- package/dist/core/file-lock.js +7 -1
- package/dist/core/fs-txn.js +83 -7
- package/dist/core/git-message.js +2 -2
- package/dist/core/improve-result.js +6 -100
- package/dist/core/json-schema.js +327 -9
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +2 -1
- package/dist/core/loopback.js +89 -0
- package/dist/core/migration-operation.js +33 -2
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/parse.js +4 -1
- package/dist/core/path-access.js +107 -0
- package/dist/core/paths.js +17 -20
- package/dist/core/recognition-util.js +12 -14
- package/dist/core/redaction.js +98 -17
- package/dist/core/spawn-env.js +234 -0
- package/dist/core/standards/resolve-standards-context.js +2 -14
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +2 -2
- package/dist/core/state/migrations.js +41 -18
- package/dist/core/state-db-scope.js +134 -0
- package/dist/core/state-db.js +5 -14
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +182 -36
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/type-presentation.js +3 -3
- package/dist/core/warn.js +0 -3
- package/dist/core/write-provenance.js +85 -0
- package/dist/core/write-source.js +778 -95
- package/dist/indexer/bundle-identity-guard.js +3 -2
- package/dist/indexer/db/graph-db.js +17 -30
- package/dist/indexer/ensure-index.js +11 -3
- package/dist/indexer/graph/graph-boost.js +9 -34
- package/dist/indexer/graph/graph-extraction.js +8 -5
- package/dist/indexer/index-writer-lock.js +53 -17
- package/dist/indexer/index-written-assets.js +33 -24
- package/dist/indexer/indexer.js +551 -253
- package/dist/indexer/installations.js +14 -96
- package/dist/indexer/passes/dir-staleness.js +16 -9
- package/dist/indexer/passes/memory-inference.js +15 -9
- package/dist/indexer/passes/metadata.js +113 -47
- package/dist/indexer/scan/doc-to-entry.js +38 -1
- package/dist/indexer/scan/drain-dir.js +13 -23
- package/dist/indexer/search/db-search.js +107 -69
- package/dist/indexer/search/fts-query.js +47 -24
- package/dist/indexer/search/ranking-contributors.js +42 -20
- package/dist/indexer/search/ranking.js +18 -99
- package/dist/indexer/search/search-fields.js +7 -2
- package/dist/indexer/search/search-source.js +82 -93
- package/dist/indexer/usage/usage-events.js +0 -89
- package/dist/indexer/walk/file-context.js +2 -1
- package/dist/indexer/walk/matchers.js +30 -43
- package/dist/indexer/walk/path-resolver.js +7 -2
- package/dist/indexer/walk/walker.js +38 -12
- package/dist/integrations/agent/builders.js +0 -6
- package/dist/integrations/agent/config.js +2 -2
- package/dist/integrations/agent/detect.js +49 -19
- package/dist/integrations/agent/engine-fallback.js +76 -0
- package/dist/integrations/agent/engine-resolution.js +24 -11
- package/dist/integrations/agent/model-aliases.js +1 -1
- package/dist/integrations/agent/profiles.js +23 -1
- package/dist/integrations/agent/prompts.js +12 -8
- package/dist/integrations/agent/runner-dispatch.js +4 -2
- package/dist/integrations/agent/runner.js +0 -1
- package/dist/integrations/agent/spawn.js +20 -93
- package/dist/integrations/github.js +1 -1
- package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
- package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
- package/dist/integrations/harnesses/claude/session-log.js +0 -10
- package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
- package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
- package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
- package/dist/integrations/harnesses/index.js +3 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
- package/dist/integrations/harnesses/opencode/session-log.js +0 -15
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
- package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
- package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
- package/dist/integrations/lockfile.js +132 -8
- package/dist/integrations/session-logs/index.js +3 -28
- package/dist/llm/client.js +136 -100
- package/dist/llm/embedders/remote.js +13 -5
- package/dist/llm/feature-gate.js +4 -12
- package/dist/llm/graph-extract.js +5 -11
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +5 -7
- package/dist/llm/structured-call.js +1 -1
- package/dist/llm/usage-persist.js +26 -5
- package/dist/llm/usage-telemetry.js +25 -2
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +259 -0
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -36
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +56 -83
- package/dist/output/shapes/migrate.js +8 -0
- package/dist/output/shapes/passthrough.js +7 -41
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes.js +2 -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 +164 -96
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/health-format.js +103 -0
- package/dist/output/text/health.js +7 -0
- package/dist/output/text/helpers.js +10 -8
- package/dist/output/text/lint-format.js +56 -0
- package/dist/{migrate-storage-node.mjs → output/text/lint.js} +2 -5
- package/dist/output/text/migrate.js +88 -0
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +44 -72
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +15 -7
- package/dist/output/text/status-list.js +32 -0
- package/dist/output/text/{save.js → sync.js} +2 -2
- package/dist/output/text/workflow-format.js +24 -203
- package/dist/output/text/workflow.js +1 -7
- package/dist/output/text.js +16 -17
- 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 +13 -23
- package/dist/registry/resolve.js +42 -7
- package/dist/registry/semver.js +34 -84
- package/dist/runtime.js +2 -23
- package/dist/scripts/akm-migrate-node.js +60972 -0
- package/dist/scripts/akm-migrate.js +60310 -0
- package/dist/setup/detect.js +42 -15
- package/dist/setup/registry-stash-loader.js +2 -2
- package/dist/setup/setup.js +236 -136
- package/dist/setup/steps/connection.js +7 -9
- package/dist/setup/steps/platforms.js +9 -9
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +12 -13
- package/dist/setup/steps/stashdir.js +2 -3
- package/dist/setup/steps/tasks.js +237 -120
- package/dist/sources/freshness.js +1 -1
- 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 +25 -23
- package/dist/sources/providers/git-stash.js +414 -106
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +7 -4
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +6 -1
- package/dist/sources/resolve.js +6 -5
- package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
- package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
- package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
- package/dist/sources/snapshot-fetchers/github.js +100 -0
- package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
- package/dist/sources/snapshot-fetchers/registry.js +17 -1
- package/dist/sources/snapshot-fetchers/robots.js +348 -0
- package/dist/sources/snapshot-fetchers/rss.js +282 -0
- package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
- package/dist/sources/snapshot-fetchers/website-ingest.js +686 -282
- package/dist/sources/snapshot-fetchers/x.js +910 -0
- package/dist/storage/database.js +13 -1
- package/dist/storage/engines/sqlite-migrations.js +23 -111
- package/dist/storage/managed-db.js +21 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +27 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -12
- package/dist/storage/repositories/index-connection.js +44 -8
- package/dist/storage/repositories/index-entries-repository.js +157 -241
- package/dist/storage/repositories/index-entry-mapper.js +15 -11
- package/dist/storage/repositories/index-fts-repository.js +5 -2
- package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
- package/dist/storage/repositories/index-meta-repository.js +2 -3
- package/dist/storage/repositories/index-schema.js +10 -25
- package/dist/storage/repositories/index-utility-repository.js +15 -28
- package/dist/storage/repositories/index-vec-repository.js +6 -1
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +296 -59
- package/dist/storage/repositories/registry-cache.js +19 -0
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +15 -13
- package/dist/storage/repositories/workflow-runs-repository.js +118 -53
- package/dist/tasks/backends/cron.js +105 -15
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +85 -38
- package/dist/tasks/backends/schtasks.js +135 -15
- package/dist/tasks/embedded.js +56 -40
- package/dist/tasks/log-redaction.js +156 -0
- package/dist/tasks/parser.js +87 -160
- package/dist/tasks/resolve-akm-bin.js +137 -59
- package/dist/tasks/runner.js +209 -44
- package/dist/tasks/scheduler-invocation.js +220 -10
- package/dist/tasks/schema.js +89 -1
- package/dist/tasks/task-id.js +1 -3
- package/dist/tasks/validator.js +20 -6
- package/dist/workflows/authoring/authoring.js +94 -143
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/concurrency-policy.js +95 -1
- package/dist/workflows/exec/dispatch-redaction.js +114 -0
- package/dist/workflows/exec/exec-unit.js +542 -0
- package/dist/workflows/exec/frozen-judge.js +130 -32
- package/dist/workflows/exec/native-executor.js +513 -274
- package/dist/workflows/exec/param-secrets.js +12 -11
- package/dist/workflows/exec/run-workflow.js +496 -237
- package/dist/workflows/exec/step-work.js +616 -412
- package/dist/workflows/exec/unit-dispatch.js +34 -0
- package/dist/workflows/exec/unit-writer.js +53 -13
- package/dist/workflows/exec/worktree.js +454 -41
- package/dist/workflows/ir/compile.js +166 -271
- package/dist/workflows/ir/freeze.js +119 -42
- package/dist/workflows/ir/params.js +135 -11
- package/dist/workflows/ir/plan-hash.js +1 -1
- package/dist/workflows/ir/schema.js +129 -45
- package/dist/workflows/parser.js +1070 -307
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +31 -10
- package/dist/workflows/renderer.js +123 -68
- package/dist/workflows/resource-limits.js +184 -0
- package/dist/workflows/runtime/checkin.js +3 -3
- package/dist/workflows/runtime/plan-classifier.js +16 -75
- package/dist/workflows/runtime/runs.js +331 -132
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +2 -2
- package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +47 -38
- package/dist/workflows/validator.js +21 -62
- package/docs/README.md +110 -0
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.7.0.md +11 -11
- package/docs/migration/release-notes/0.9.0.md +209 -27
- package/docs/migration/v0.7-to-v0.8.md +48 -48
- package/docs/migration/v0.8-to-v0.9.md +567 -209
- package/docs/migration/v0.9.0-troubleshooting.md +561 -0
- package/docs/reference/README.md +19 -0
- package/docs/reference/bundle-types.md +19 -0
- package/docs/reference/cli.md +2342 -0
- package/docs/reference/configuration.md +371 -0
- package/docs/reference/data-and-telemetry.md +129 -46
- package/docs/reference/supported-formats.md +50 -0
- package/docs/reference/workflow-schema.md +1014 -0
- package/docs/reference/workflows.md +51 -0
- package/package.json +31 -13
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +89 -128
- package/schemas/akm-task.json +27 -5
- package/schemas/akm-workflow.json +157 -81
- package/dist/assets/tasks/core/backup.yml +0 -5
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/cli/config-migrate.js +0 -1878
- package/dist/cli/config-validate.js +0 -41
- package/dist/commands/backup-cli.js +0 -56
- package/dist/commands/bundle/bundle-cli.js +0 -68
- package/dist/commands/bundle/bundle.js +0 -219
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -489
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/mv-cli.js +0 -1221
- package/dist/commands/sources/history.js +0 -201
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/core/migration-backup.js +0 -1231
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/migrate/legacy/config-source-migration.js +0 -257
- package/dist/migrate/legacy/content-migration.js +0 -350
- package/dist/migrate/legacy/legacy-layout.js +0 -779
- package/dist/migrate/legacy/legacy-paths.js +0 -25
- package/dist/migrate/legacy/legacy-stash-json.js +0 -80
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -278
- package/dist/migrate/legacy/three-db-cutover.js +0 -845
- package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
- package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
- package/dist/migrate/legacy-ref-grammar.js +0 -214
- 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/registry/build-index.js +0 -382
- package/dist/schemas/akm-config.json +0 -4704
- package/dist/schemas/akm-task.json +0 -87
- package/dist/schemas/akm-workflow.json +0 -372
- package/dist/scripts/migrate-storage.js +0 -3816
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/cli.js +0 -53
- package/dist/workflows/exec/brief.js +0 -481
- package/dist/workflows/exec/report.js +0 -1460
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -813
- package/dist/workflows/program/project.js +0 -104
package/CHANGELOG.md
CHANGED
|
@@ -4,12 +4,721 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
-
## [
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.9.1-beta.1] - 2026-08-13
|
|
10
|
+
|
|
11
|
+
### Breaking changes & migration
|
|
12
|
+
|
|
13
|
+
The 0.9.x series carries breaking changes as it works toward the 0.10.x
|
|
14
|
+
stabilization line. Every item here is detailed further down; this section is
|
|
15
|
+
what an upgrader reads first.
|
|
16
|
+
|
|
17
|
+
- **A data directory akm cannot READ is now an error, not an empty result.**
|
|
18
|
+
Commands that previously returned `hits: []` / `entryCount: 0` / "nothing
|
|
19
|
+
eligible" at exit 0 for an index, lockfile or database they lacked permission
|
|
20
|
+
on now raise `DATA_DIR_UNREADABLE` (exit 78) naming the path, errno, mode,
|
|
21
|
+
owner and running uid. *Affected:* anyone whose data dir is partly unreadable
|
|
22
|
+
— most often a `$XDG_DATA_HOME` shared across uids. *Remedy:* fix the
|
|
23
|
+
ownership or mode the error names, or point `AKM_DATA_DIR` somewhere this
|
|
24
|
+
user owns. The old behaviour was a false success, so a script that treated
|
|
25
|
+
exit 0 as "no results" was already being lied to.
|
|
26
|
+
|
|
27
|
+
- **Lockfile writes refuse to run against an unreadable `akm.lock`.**
|
|
28
|
+
`akm bundle add` / `remove` / `update` now fail closed instead of reading the
|
|
29
|
+
lock as empty and writing the single incoming entry over the whole record.
|
|
30
|
+
*Remedy:* as above. This one prevented real data loss — see Fixed.
|
|
31
|
+
|
|
32
|
+
- **`akm workflow run` exits 1 when a run ends `blocked`.** Previously 0.
|
|
33
|
+
*Affected:* CI steps and scheduled wrappers that branched only on `failed`.
|
|
34
|
+
*Remedy:* treat nonzero as "not verified"; resume with
|
|
35
|
+
`akm workflow resume <id>`.
|
|
36
|
+
|
|
37
|
+
- **`akm index --clean` no longer deletes entries whose file it cannot read.**
|
|
38
|
+
It keeps and names them. *Affected:* anyone relying on `--clean` to prune
|
|
39
|
+
aggressively; it is now conservative where it cannot see.
|
|
40
|
+
|
|
41
|
+
- **Workflow documents are bounds-checked at authoring time.** `engine:` name
|
|
42
|
+
grammar, `retry.max` 0–100, `gate.max_loops` 1–100, `map.concurrency` and
|
|
43
|
+
`engines.<name>.concurrency` 1–64, and any `timeout:` ≤ 2 147 483 647 ms are
|
|
44
|
+
now enforced by the parser. *Affected:* documents that parsed at 0.9.0 but
|
|
45
|
+
could never actually run — the frozen-plan decoder already refused them.
|
|
46
|
+
*Remedy:* edit the offending field; the error is now line-anchored.
|
|
47
|
+
|
|
48
|
+
- **`akm health` no longer emits `secret-file-perms`, and no longer exits 4 for
|
|
49
|
+
it.** The check is gone. *Affected:* anything parsing health output for that
|
|
50
|
+
check name.
|
|
51
|
+
|
|
52
|
+
- **Command-target task logs are now redacted.** Output that previously
|
|
53
|
+
persisted verbatim may now contain `[REDACTED]`. *Affected:* anything
|
|
54
|
+
grepping task logs for values that are now recognised as secrets.
|
|
55
|
+
|
|
56
|
+
- **Leftover `isolation: worktree` trees are garbage-collected after 7 days.**
|
|
57
|
+
*Remedy:* copy anything you want to keep out of a retained worktree within a
|
|
58
|
+
week.
|
|
59
|
+
|
|
60
|
+
### Added
|
|
61
|
+
|
|
62
|
+
- **`exec` workflow units — run a shell command as a workflow step.** A step
|
|
63
|
+
whose `unit:` block declares `exec:` runs a command directly instead of
|
|
64
|
+
dispatching to an LLM or an agent, so deterministic work (test suites,
|
|
65
|
+
builds, lint, scripts) no longer costs a model dispatch, its latency, its
|
|
66
|
+
tokens, or its nondeterminism.
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
- id: test
|
|
70
|
+
unit:
|
|
71
|
+
exec:
|
|
72
|
+
command: ["bun", "run", "test:unit"]
|
|
73
|
+
pass_env: [CARGO_HOME] # optional: widen the default env allowlist
|
|
74
|
+
timeout: "10m"
|
|
75
|
+
retry: { max: 1, on: [timeout] }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- **`command:` is an argv array; there is no shell-string spelling.** The
|
|
79
|
+
child is spawned directly, so `;`, `|`, `&&`, `$(…)` and `*` inside an
|
|
80
|
+
argument are inert literal bytes — the quoting/injection class is
|
|
81
|
+
structurally absent, not defended against. Write `["bash", "-lc", "…"]`
|
|
82
|
+
when a pipeline is genuinely wanted, and own that choice in the diff.
|
|
83
|
+
- **An exec unit names no engine.** It rejects `engine`/`model`/`llm`, spends
|
|
84
|
+
no tokens, and a workflow made only of exec steps runs on an install with
|
|
85
|
+
no engine configured at all.
|
|
86
|
+
- **Everything else about a unit still applies:** `timeout`, `retry`,
|
|
87
|
+
`on_error`, `output`, `env`, `isolation: worktree`, `map` fan-out and its
|
|
88
|
+
concurrency limits, the unit journal, budget accounting, and replay/reuse
|
|
89
|
+
(a completed exec unit is never re-run on resume).
|
|
90
|
+
- **Output rule:** stdout is the promoted artifact with trailing newlines
|
|
91
|
+
stripped (like shell `$(…)`); with an `output:` schema on the unit, stdout
|
|
92
|
+
must be exactly one JSON value, strictly parsed and validated. stderr is a
|
|
93
|
+
diagnostic channel only. A schema miss is *not* re-prompted — a fixed argv
|
|
94
|
+
cannot answer feedback, but re-running it could deploy twice.
|
|
95
|
+
- **Exit codes:** non-zero → `non_zero_exit`, wall-clock expiry → `timeout`,
|
|
96
|
+
cancellation → `aborted`, failure to start → `spawn_failed`. Those are
|
|
97
|
+
pre-existing `retry.on` reasons. With the default `on_error: fail`, a
|
|
98
|
+
non-zero exit fails the step and the run, which is what makes a `test` step
|
|
99
|
+
a gate.
|
|
100
|
+
- **A partial capture is never promoted as the artifact.** Exiting 0 does not
|
|
101
|
+
prove stdout was read to the end: a pipe can error, and a background
|
|
102
|
+
descendant holding the stdout handle open after the command leader exits
|
|
103
|
+
keeps the pipe alive past the drain deadline. Both leave a *prefix* of the
|
|
104
|
+
real output, so the unit fails — with its own reason,
|
|
105
|
+
`exec_capture_incomplete`, which is deliberately **not** a `retry.on` value.
|
|
106
|
+
The command already ran; re-dispatching identical argv to fix a capture
|
|
107
|
+
problem would run its side effects a second time.
|
|
108
|
+
- **Everything the command can spend is bounded — without inventing failures.**
|
|
109
|
+
Alongside the wall-clock timeout, akm bounds the memory it spends on the
|
|
110
|
+
command's behalf and the environment it can hand the command. Both bounds are
|
|
111
|
+
built so that they only ever *explain* a failure that was going to happen
|
|
112
|
+
anyway; neither fails a run that would otherwise have succeeded.
|
|
113
|
+
|
|
114
|
+
**Retained output: 8 MiB per stream, drain-and-discard.** akm keeps at most
|
|
115
|
+
8 MiB of stdout and 8 MiB of stderr. Past the cap it keeps *reading* the pipe
|
|
116
|
+
and throws the extra bytes away, so the child never blocks on backpressure:
|
|
117
|
+
the command runs to completion and its real exit code decides the unit. A
|
|
118
|
+
verbose-but-passing test suite is not failed over its log volume. What
|
|
119
|
+
overflow costs is completeness of the artifact, and that is never hidden —
|
|
120
|
+
a step with **no** `output:` schema succeeds and its artifact is the retained
|
|
121
|
+
head with a `__akm_exec_output_truncated__` block appended (naming bytes
|
|
122
|
+
written vs bytes retained), so truncated data can never be mistaken for
|
|
123
|
+
complete data by `steps.<id>.output`, a gate judge, or a human. A step **with**
|
|
124
|
+
an `output:` schema still fails `exec_output_limit`: stdout must parse as
|
|
125
|
+
exactly one JSON value, a truncated prefix cannot, and promoting it would
|
|
126
|
+
corrupt every downstream reference to the typed artifact.
|
|
127
|
+
|
|
128
|
+
**Context environment: this platform's ceiling, not the smallest one.** The
|
|
129
|
+
engine-authored `AKM_*` context is capped at **96 KiB per variable / 128 KiB
|
|
130
|
+
total** on Linux, macOS and BSD, and at **32 767 bytes per variable / 64 000
|
|
131
|
+
bytes total** on Windows. The numbers cite their sources: Linux's
|
|
132
|
+
`MAX_ARG_STRLEN` (`32 * PAGE_SIZE` = 131 072 bytes per `argv`/`environ`
|
|
133
|
+
string), macOS's 256 KiB `ARG_MAX` over argv + environ combined, and Win32
|
|
134
|
+
`SetEnvironmentVariable`'s 32 767-character per-variable limit. Crossing the
|
|
135
|
+
bound fails `exec_context_too_large` *before* the spawn, with an error naming
|
|
136
|
+
the variable, its size, this platform's limit and where that limit comes from
|
|
137
|
+
— replacing a bare `E2BIG` from the spawn syscall that named neither the
|
|
138
|
+
variable nor the data behind it. Converting that inevitable failure into an
|
|
139
|
+
actionable one is the check's *only* job, so it uses the ceiling of the
|
|
140
|
+
platform the run is on: previously it applied Windows' limit everywhere and
|
|
141
|
+
refused spawns Linux and macOS would have accepted. Workflows that must also
|
|
142
|
+
run on Windows should stay under the smaller bound — that is documented
|
|
143
|
+
guidance now, not something a Linux host enforces.
|
|
144
|
+
|
|
145
|
+
`exec_output_limit` and `exec_context_too_large` keep their meanings and
|
|
146
|
+
their place outside the `retry.on` vocabulary, alongside `exec_cwd_escape`:
|
|
147
|
+
each is deterministic, so re-dispatching could only spend the budget again.
|
|
148
|
+
`PROGRAM_RETRY_REASONS` is unchanged.
|
|
149
|
+
- **A failing command's stderr survives to a durable surface.** The unit
|
|
150
|
+
journal now keeps each failed unit's redacted diagnostic (clipped to 2000
|
|
151
|
+
characters), and the step summary carries the first failure's. For an exec
|
|
152
|
+
unit that is the difference between `akm workflow status --units` saying
|
|
153
|
+
`non_zero_exit` and it saying *why* — a command that explains itself only on
|
|
154
|
+
stderr with empty stdout previously left no diagnostic anywhere durable.
|
|
155
|
+
This is an output surface only: the unit input hash is computed from
|
|
156
|
+
plan-frozen inputs, so no completed unit re-dispatches because of it.
|
|
157
|
+
- **The child's environment is an ALLOWLIST, not an inheritance.** The
|
|
158
|
+
command starts from an empty environment and receives `PATH`, `HOME`, the
|
|
159
|
+
identity/locale/temp/terminal variables, the Windows process-creation
|
|
160
|
+
essentials (`SystemRoot`, `SystemDrive`, `WINDIR`, `COMSPEC`, `PATHEXT`)
|
|
161
|
+
and the Windows home/config roots, plus `AKM_EVENT_SOURCE` — then the
|
|
162
|
+
unit's `env:` bindings, then the `AKM_*` context. `exec.pass_env: [NAME…]`
|
|
163
|
+
adds a few more names (for a per-machine toolchain variable like
|
|
164
|
+
`CARGO_HOME`, which a committed `env:` asset cannot express);
|
|
165
|
+
`exec.inherit_env: true` opts all the way back into akm's whole
|
|
166
|
+
environment. Both keys live inside `exec:` because the unit-level `env:`
|
|
167
|
+
key already means "env asset binding refs", and both are dispatch-
|
|
168
|
+
significant, so both are in the input hash.
|
|
169
|
+
|
|
170
|
+
This is not a claim to stop a determined attacker — a command that runs at
|
|
171
|
+
all can read the same credentials off disk. It bounds **accidental**
|
|
172
|
+
exposure (the invoking shell or CI job routinely exports tokens for
|
|
173
|
+
unrelated services), makes the environment surface **explicit and
|
|
174
|
+
reviewable**, and **matches the convention akm already applies** to
|
|
175
|
+
agent-harness children (`profile.envPassthrough`), which now share one
|
|
176
|
+
mechanism with exec units instead of two.
|
|
177
|
+
- **Security:** commands run inside the existing workflow trust model.
|
|
178
|
+
Secrets come from `env:` bindings by NAME — the frozen plan and the replay
|
|
179
|
+
hash carry only ref names, and resolved values are scrubbed from stdout,
|
|
180
|
+
stderr, and failure diagnostics by the same redaction contract every other
|
|
181
|
+
dispatch uses, before anything is journaled. `cwd:` is relative and
|
|
182
|
+
`..`-free, re-checked against the resolved base (symlinks included) before
|
|
183
|
+
spawning.
|
|
184
|
+
- **Cancellation is real:** the child is spawned in its own process group and
|
|
185
|
+
gets a SIGTERM→SIGKILL ladder on timeout or abort, so `--timeout` / Ctrl-C
|
|
186
|
+
stop a running command without orphaning its children.
|
|
187
|
+
- **No replay churn:** the exec spec was added to the unit input-hash preimage
|
|
188
|
+
as a key present only on exec units, so `hashVersion` stays 4 and every
|
|
189
|
+
previously-frozen llm/agent/sdk unit hashes byte-identically — runs already
|
|
190
|
+
in flight neither re-dispatch nor diverge. The env-scope keys are inside
|
|
191
|
+
that same spec and are frozen only in their non-default form (`inherit_env`
|
|
192
|
+
only when `true`, `pass_env` only when non-empty), so an exec unit that says
|
|
193
|
+
nothing about its environment hashes byte-identically too.
|
|
194
|
+
|
|
195
|
+
See [Workflow Schema: Exec (shell) units](docs/reference/workflow-schema.md#exec-shell-units)
|
|
196
|
+
and the worked example in
|
|
197
|
+
[Author's Guide](https://github.com/itlackey/akm/blob/main/docs/guides/author-workflows.md#deterministic-steps-run-a-command-gate-on-it).
|
|
198
|
+
|
|
199
|
+
### Changed
|
|
200
|
+
|
|
201
|
+
- **`akm workflow run` now exits non-zero when the run ends `blocked`.** A
|
|
202
|
+
verification judge that throws, cannot be resolved, or returns a malformed
|
|
203
|
+
verdict stops the run `blocked` — unverified, and resumable with `akm
|
|
204
|
+
workflow resume <id>`. That previously exited 0, so a CI step or scheduled
|
|
205
|
+
wrapper read an unverified run as a passing one. It now exits 1, matching
|
|
206
|
+
`failed` and gate rejections, and matching how the scheduled-task path
|
|
207
|
+
already reported it.
|
|
208
|
+
|
|
209
|
+
- **Workflow dispatch bounds are enforced at authoring time, not only by the
|
|
210
|
+
frozen-plan decoder.** `engine:` names must match the decoder's own grammar
|
|
211
|
+
(lowercase dash-separated letters/digits, starting with a letter, ≤63
|
|
212
|
+
chars); `retry.max` is 0–100; `gate.max_loops` is 1–100; `map.concurrency`
|
|
213
|
+
and `engines.<name>.concurrency` are 1–64; any `timeout:` must resolve to at
|
|
214
|
+
most 2 147 483 647 ms (~24.8 days, `setTimeout`'s 32-bit ceiling). Every one
|
|
215
|
+
of these was already refused by the frozen-plan decoder, so such a document
|
|
216
|
+
could never actually run — but it *parsed*, so `akm lint`, `akm workflow
|
|
217
|
+
show` and `akm workflow create` all reported it clean and the failure arrived
|
|
218
|
+
at `workflow run` as an unlocated "Invalid frozen workflow plan". The error is
|
|
219
|
+
now line-anchored at parse time. Nothing changes for a document already
|
|
220
|
+
inside the bounds.
|
|
221
|
+
|
|
222
|
+
- **`akm lint` gained an advisory channel.** The result envelope carries
|
|
223
|
+
`warnings: LintIssue[]` alongside `fixed`/`flagged`, `summary` gains a
|
|
224
|
+
`warnings` count, and text output prints a `warnings` section. Advisories
|
|
225
|
+
never route into `flagged`, so `--fail-on-flagged` cannot fail a run over
|
|
226
|
+
one. Workflow compile advisories (`workflow-warning`) are surfaced for the
|
|
227
|
+
first time — a step with no `output:` schema, a `params.<name>` reference to
|
|
228
|
+
an undeclared param, a `gate.max_loops` above 1 on an `exec` step — so a
|
|
229
|
+
bundle that linted clean at 0.9.0 may now report warnings without becoming a
|
|
230
|
+
failure. Findings that know a location carry `line` in `--format json` and
|
|
231
|
+
render as `file:line` in text. A new `lint-failed` code reports a file the
|
|
232
|
+
sweep reached but could not finish.
|
|
233
|
+
|
|
234
|
+
- **Leftover `isolation: worktree` trees are now garbage-collected.** A run
|
|
235
|
+
that crashed, or one whose worktree was retained after a dirty unit, used to
|
|
236
|
+
leave its tree under the worktrees root forever. akm now opportunistically
|
|
237
|
+
removes such trees once they are 7 days old, confined to the worktrees root,
|
|
238
|
+
symlinks skipped, containment re-checked. A worktree still in use is never
|
|
239
|
+
collected: every live tree carries a liveness marker (pid, host, resolved
|
|
240
|
+
path) in git's administrative directory for it, and the sweep skips a
|
|
241
|
+
candidate whose holder is still running here.
|
|
242
|
+
|
|
243
|
+
- **The workflow JSON Schema subset now enforces `allOf`/`anyOf`/`oneOf`/`not`.**
|
|
244
|
+
A step `output:` or `params:` schema may use the combinators, and the runtime
|
|
245
|
+
now evaluates them. Previously it ignored them: a schema using one was
|
|
246
|
+
accepted and simply constrained less than it appeared to. Evaluation stays
|
|
247
|
+
bounded — nesting is capped at 64 levels and one validation at 100 000 checks,
|
|
248
|
+
and exhausting either is reported as an error rather than a truncated pass.
|
|
249
|
+
|
|
250
|
+
**This one reaches runs already in flight.** The combinators live in the
|
|
251
|
+
frozen plan, which the decoder still accepts unchanged, so a run frozen before
|
|
252
|
+
the upgrade is resumed against the *new* evaluation: an artifact that passed
|
|
253
|
+
when the combinators were ignored can fail validation now. There is no
|
|
254
|
+
`irVersion` bump to gate it, because the plan bytes did not change — only what
|
|
255
|
+
they mean. Runs whose schemas use no combinators are unaffected, as is every
|
|
256
|
+
step already completed.
|
|
257
|
+
|
|
258
|
+
`pattern` is **not** part of the subset. It is a recognized-but-unsupported
|
|
259
|
+
keyword like `format` or `const`: using one is a loud, line-anchored authoring
|
|
260
|
+
error naming the keyword, so no schema silently fails to constrain what it
|
|
261
|
+
looks like it constrains. Enforcing it would mean screening every author
|
|
262
|
+
regex for catastrophic backtracking before the match — and any such screen
|
|
263
|
+
also refuses regexes authors legitimately write (the usual hand-rolled email
|
|
264
|
+
pattern among them), which is authoring friction with no workflow asking for
|
|
265
|
+
it. Where a string's shape matters, `enum` lists the allowed values,
|
|
266
|
+
`minLength`/`maxLength` bound the size, and a step's `### gate` rubric can
|
|
267
|
+
check a shape and explain a mismatch. The `format` hint now points at `enum`
|
|
268
|
+
rather than at `pattern`.
|
|
269
|
+
|
|
270
|
+
**Existing workflows that use one of these keywords must be edited before
|
|
271
|
+
they load again.** They previously parsed — the keyword was silently
|
|
272
|
+
non-constraining — so a workflow carrying `format: date-time` or `pattern:`
|
|
273
|
+
ran fine and now fails to parse for every caller: `workflow run`, `workflow
|
|
274
|
+
show`, `workflow create`, and `akm lint`. The quietest surface is `akm index`,
|
|
275
|
+
which skips an asset it cannot parse with a scan warning, so the workflow
|
|
276
|
+
simply stops appearing in the stash index. A run already frozen from such an
|
|
277
|
+
asset still resumes — the frozen-plan decoder does not re-screen keywords —
|
|
278
|
+
so resuming works while re-creating the same workflow errors until it is
|
|
279
|
+
edited.
|
|
280
|
+
|
|
281
|
+
- **A document-level `defaults.llm` is now rejected at freeze when any step
|
|
282
|
+
resolves onto an agent engine**, naming the step and the engine. The guard
|
|
283
|
+
existed before but was unreachable: overrides were computed only for `llm`
|
|
284
|
+
engines, so `defaults.llm` on a document with an agent step was silently
|
|
285
|
+
DROPPED for that step — the run proceeded with the author's sampling settings
|
|
286
|
+
quietly discarded. Failing loudly is the point, but it means a document that
|
|
287
|
+
mixes `defaults.llm` with any agent-engine step no longer freezes.
|
|
288
|
+
|
|
289
|
+
There is no per-step opt-out: `llm: {}` is a no-op, `llm: null` is a parse
|
|
290
|
+
error, and the layer merge is additive. Move the `llm:` block from
|
|
291
|
+
`defaults:` onto the `unit:` of each LLM step that wants it.
|
|
292
|
+
|
|
293
|
+
- **A scheduled workflow task now gets a 6-hour whole-run timeout by default.**
|
|
294
|
+
This applies to task files that declare no `timeoutMs:` — which is every task
|
|
295
|
+
file written before this release, since the key was previously rejected on
|
|
296
|
+
workflow targets. An unattended run that legitimately takes longer will be
|
|
297
|
+
aborted and the attempt reported failed on every firing until the task is
|
|
298
|
+
edited. `timeoutMs: null` opts out entirely, and any number overrides the
|
|
299
|
+
default. The abort itself is graceful: it lands at a step boundary, the
|
|
300
|
+
journal and lease are kept, and the run stays resumable with
|
|
301
|
+
`akm workflow resume <id>` — which the failure message names.
|
|
302
|
+
|
|
303
|
+
- **Workflow `map` steps now fan out in parallel by default.** A `map` step
|
|
304
|
+
that declares no `concurrency:` freezes a width of **4** instead of 1, and an
|
|
305
|
+
LLM engine that declares no `engines.<name>.concurrency` freezes **4** for a
|
|
306
|
+
remote endpoint (loopback endpoints stay at **1** — a local model server holds
|
|
307
|
+
one loaded model and returns HTTP 500 under concurrent inference). Both
|
|
308
|
+
defaults previously froze 1, which made every fan-out serial unless the author
|
|
309
|
+
opted in at two independent layers, and left `workflow.maxConcurrency` and the
|
|
310
|
+
host CPU cap binding on nothing.
|
|
311
|
+
|
|
312
|
+
This is a behavior change on a patch release, so every escape hatch is
|
|
313
|
+
explicit:
|
|
314
|
+
- `map.concurrency: 1` on a step is honored exactly as before — an authored
|
|
315
|
+
`1` is kept distinct from an unset field and always wins.
|
|
316
|
+
- New config key **`workflow.defaultMapConcurrency`** sets the default for
|
|
317
|
+
every workflow on the machine. `akm config set workflow.defaultMapConcurrency 1`
|
|
318
|
+
restores the pre-0.9.1 serial default wholesale.
|
|
319
|
+
- `engines.<name>.concurrency` pins any engine's own limit (and is now clamped
|
|
320
|
+
to `1..64` at freeze time instead of freezing a plan the decoder would then
|
|
321
|
+
refuse to load).
|
|
322
|
+
- **Runs already in flight are unaffected.** Both values are frozen into
|
|
323
|
+
`plan_json` when a run starts and the frozen-plan decoder requires them, so
|
|
324
|
+
a resumed run keeps the widths it began with. The new defaults apply only to
|
|
325
|
+
runs started after the upgrade.
|
|
326
|
+
|
|
327
|
+
The effective width remains the minimum of the step's `concurrency`, the run's
|
|
328
|
+
frozen `workflow.maxConcurrency`, the selected engine's concurrency, and the
|
|
329
|
+
current host's CPU cap.
|
|
330
|
+
|
|
331
|
+
- **`--max-steps` now counts steps, not engine-loop iterations.** The budget is
|
|
332
|
+
spent by the DISTINCT spine steps that finished — completed, failed, or
|
|
333
|
+
gate-rejected with the loop budget spent. It was previously spent by entries
|
|
334
|
+
in the `executed` report,
|
|
335
|
+
which gains one per gate-loop iteration and one per route-skip, so
|
|
336
|
+
`--max-steps 3` against a step with `gate.max_loops: 3` could stop after a
|
|
337
|
+
single step had finished, and an unselected branch target consumed budget for
|
|
338
|
+
work that was never dispatched. Three steps now means three steps, which is
|
|
339
|
+
what the flag has always said (`Stop after executing this many steps`). A step
|
|
340
|
+
the invocation left unfinished — an abort, a judge outage — still consumes
|
|
341
|
+
nothing, because the work is still owed. The same accounting is what a
|
|
342
|
+
`--max-retries` reopen subtracts, so loops and skips no longer shrink a
|
|
343
|
+
retry's remaining budget either, and `maxSteps:` in a workflow task file is
|
|
344
|
+
the same knob and moves with it. The count is now reported: `akm workflow run`
|
|
345
|
+
carries a `stepsProcessed` field alongside `executed`, so the number the
|
|
346
|
+
budget is spent on is visible rather than inferred from a list that counts
|
|
347
|
+
something else.
|
|
348
|
+
|
|
349
|
+
**This loosens the dispatch exposure of one invocation, and the loosening is
|
|
350
|
+
cumulative across steps.** A step's whole bounded gate loop now costs one step
|
|
351
|
+
instead of one per iteration, so the rounds a single `akm workflow run` can
|
|
352
|
+
dispatch go from roughly `N + max_loops` to `N × max_loops`.
|
|
353
|
+
|
|
354
|
+
What did **not** change is what the flag bounds within one step. `--max-steps`
|
|
355
|
+
was never a cap on total dispatch rounds on either version: the budget is
|
|
356
|
+
tested only BETWEEN steps, so a single step's gate loop could always run out
|
|
357
|
+
its full `gate.max_loops` no matter how little budget was left. The per-step
|
|
358
|
+
ceiling is `gate.max_loops` (1–100); the whole-run ceilings are
|
|
359
|
+
`budget.max_units` and `budget.max_tokens`, which are seeded from the unit
|
|
360
|
+
journal and hold across resumes.
|
|
361
|
+
|
|
362
|
+
### Fixed
|
|
363
|
+
|
|
364
|
+
- **akm's Node fallback no longer aborts at teardown on Node 24.** On Node
|
|
365
|
+
24.19.0 and later, any command that opened a database could intermittently
|
|
366
|
+
die with `node::RemoveEnvironmentCleanupHook … Assertion (env) != nullptr`
|
|
367
|
+
and exit 134 — after its work was done, so the failure looked random and
|
|
368
|
+
depended on garbage-collection timing.
|
|
369
|
+
|
|
370
|
+
The cause was upstream and nothing to do with akm's own code.
|
|
371
|
+
`better-sqlite3` ships one prebuilt binary per Node ABI and falls back to
|
|
372
|
+
`node-gyp rebuild` when none matches, and the 11.x line publishes no prebuild
|
|
373
|
+
for Node 24 — so installing it there silently compiled the driver from source.
|
|
374
|
+
Node 24.19.0 had just changed the public `node_object_wrap.h` so that
|
|
375
|
+
`ObjectWrap`'s constructor and destructor register and unregister an
|
|
376
|
+
environment cleanup hook; a binding compiled against those headers
|
|
377
|
+
unregisters the hook after the environment is already gone, and aborts from
|
|
378
|
+
V8's teardown path. Only the Node 24 line was affected, and only from that
|
|
379
|
+
release on.
|
|
380
|
+
|
|
381
|
+
akm now pins `better-sqlite3` to `12.11.1`, which publishes prebuilt binaries
|
|
382
|
+
for Node 22, 24, 25 and 26 — so no Node version akm supports compiles the
|
|
383
|
+
driver at all. This affected real installs, not just CI: an npm user on Node
|
|
384
|
+
24 LTS was getting the same crash-prone from-source build.
|
|
385
|
+
|
|
386
|
+
The Node-fallback CI job now installs the exact spec `package.json` declares
|
|
387
|
+
instead of carrying a range of its own, and both that job and the smoke
|
|
388
|
+
script fail loudly on a native crash banner — previously an abort was
|
|
389
|
+
reported only as missing output, and the one step that tolerates a non-zero
|
|
390
|
+
exit would not have failed at all.
|
|
391
|
+
|
|
392
|
+
- **A website source interrupted mid-refresh no longer loses the snapshot it
|
|
393
|
+
already had.** A refresh deleted the whole mirror and then rebuilt it page by
|
|
394
|
+
page, so a process killed inside that loop left an empty or partial directory
|
|
395
|
+
with the old content already gone — and the freshness marker still looked
|
|
396
|
+
recent, so the next `sync()` served the wreckage instead of rebuilding. The
|
|
397
|
+
new snapshot is built in a dot-prefixed sibling directory and swapped in with
|
|
398
|
+
renames: an interrupted refresh leaves the PREVIOUS complete snapshot
|
|
399
|
+
untouched. Abandoned staging directories are dot-prefixed so the indexer's
|
|
400
|
+
walk skips them, and are swept by the next refresh once an hour old.
|
|
401
|
+
|
|
402
|
+
- **A resumed workflow run no longer re-dispatches work that already ran.** The
|
|
403
|
+
single-driver guard was checked at the run level, so a run whose lease had
|
|
404
|
+
been stolen left its still-owned unit row `running` and discarded the real
|
|
405
|
+
outcome — the resume then re-dispatched a unit that had already executed its
|
|
406
|
+
side effects and already spent its tokens. The guard now lives on the row, so
|
|
407
|
+
a stale driver's finish matches nothing and a live outcome is never dropped.
|
|
408
|
+
|
|
409
|
+
- **Lowering `retry.max` no longer re-runs finished work.** The completed-attempt
|
|
410
|
+
scan matched only attempts the *current* retry policy could have produced, so
|
|
411
|
+
reducing `retry.max` between invocations hid a journaled `~rN` row and the
|
|
412
|
+
unit was dispatched again. It now matches any journaled attempt of the unit.
|
|
413
|
+
|
|
414
|
+
- **A scheduled `command` task no longer writes your secrets into its log.**
|
|
415
|
+
Task logs were scrubbed for credential *shapes* — `Bearer …`, `sk-…`, webhook
|
|
416
|
+
URLs — but only prompt- and workflow-target runs also scrubbed exact secret
|
|
417
|
+
*values*. A command that echoed a configured secret shaped like nothing in
|
|
418
|
+
particular persisted it verbatim into both the run `.log` and `logs.db`, for
|
|
419
|
+
the whole retention window. Exact-value redaction now runs in the one sink all
|
|
420
|
+
three target kinds share, so every task kind is covered.
|
|
421
|
+
|
|
422
|
+
akm treats a value as secret when your config declares it
|
|
423
|
+
(`engines.<name>.apiKey`, `embedding.apiKey`, and the
|
|
424
|
+
`AKM_ENGINE_<NAME>_API_KEY` / `AKM_LLM_API_KEY` / `AKM_EMBED_API_KEY`
|
|
425
|
+
recipes), and infers others from the variable name (`*_TOKEN`, `*_SECRET`,
|
|
426
|
+
`*_API_KEY`, `*_PASSWORD`, …) when the value is at least 8 characters. The
|
|
427
|
+
floor applies only to the *guesses*: a declared secret is redacted at any
|
|
428
|
+
length. Redaction replaces substrings, so an over-eager rule does real damage
|
|
429
|
+
— treating every non-allowlisted variable in the inherited environment as a
|
|
430
|
+
secret classified 127 of 132 variables as credentials, 25 of them one
|
|
431
|
+
character long, and turned `3 tests passed, 0 failed` into `[REDACTED] tests
|
|
432
|
+
passed, [REDACTED] failed`.
|
|
433
|
+
|
|
434
|
+
For a secret exported under a name none of those rules recognise, any task may
|
|
435
|
+
name it:
|
|
436
|
+
|
|
437
|
+
```yaml
|
|
438
|
+
command: ./deploy.sh
|
|
439
|
+
redact: [ACME_DEPLOY_TOKEN] # NAMES, never values — max 32
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Names only, and a name that is unset at run time contributes nothing. A
|
|
443
|
+
literal secret in a task file would leak far more widely than the redaction
|
|
444
|
+
closes: task files are indexed into the search database, can be sent to an
|
|
445
|
+
embedding provider, are printed verbatim by `akm show`, and ship inside
|
|
446
|
+
bundles over git and npm — the same rule exec units' `pass_env:` follows.
|
|
447
|
+
|
|
448
|
+
- **Redacting a log can no longer explode it.** Exact-value redaction took a
|
|
449
|
+
fast path that rewrote the text once per secret, over an accumulator it had
|
|
450
|
+
already rewritten — so a secret containing any of the letters in `[REDACTED]`
|
|
451
|
+
matched the tokens it had just inserted, and the output grew geometrically.
|
|
452
|
+
Fifty characters against six single-letter values produced 32,450 characters,
|
|
453
|
+
a 649x blowup reachable from ordinary command output. Matches are now found
|
|
454
|
+
against the original text and the result emitted once. Overlapping matches
|
|
455
|
+
merge into a single `[REDACTED]`, and the two redaction paths no longer
|
|
456
|
+
disagree about output shape depending on whether the text happened to contain
|
|
457
|
+
a `%`.
|
|
458
|
+
|
|
459
|
+
- **Redacting a structured value no longer drops fields.** When two distinct
|
|
460
|
+
object keys redacted to the same string, the rebuilt object silently kept only
|
|
461
|
+
the last — `{a, b, ab}` came back with two entries, one of them simply gone
|
|
462
|
+
rather than redacted. Colliding keys are now suffixed, so the value survives
|
|
463
|
+
with its key still hidden. This affected persisted improve results and
|
|
464
|
+
journaled workflow outcomes.
|
|
465
|
+
|
|
466
|
+
- **`akm improve` auto-sync now commits exactly the files the run wrote.**
|
|
467
|
+
Every akm write path records the file it mutated into a run-scoped
|
|
468
|
+
write-provenance journal, and the end-of-run (and crash-path) commit stages
|
|
469
|
+
precisely those paths. A managed-directory file someone else edits while a
|
|
470
|
+
long run is in flight is left dirty for its author instead of being swept into
|
|
471
|
+
akm's commit, and a file that was already dirty when the run started and was
|
|
472
|
+
then rewritten by the run is now committed instead of being silently skipped.
|
|
473
|
+
Deletions are journaled like writes, so a path written and then reverted or
|
|
474
|
+
purged stages its final on-disk state — or produces no commit at all. The run
|
|
475
|
+
reports its journal as `writtenPaths` on the improve result, and the
|
|
476
|
+
`stash_synced` event gains `attributed` / `unattributed` counts. `akm sync` /
|
|
477
|
+
`akm push`, which supply no explicit path list, keep the managed-pathspec
|
|
478
|
+
fallback unchanged. (#652)
|
|
479
|
+
|
|
480
|
+
- **`akm lint` no longer reports a clean scan for a task file that cannot run.**
|
|
481
|
+
A `tasks/*.yml` whose YAML does not parse (bad indentation, an unterminated
|
|
482
|
+
quote, tab characters) produced `flagged: 0`: every task reader collapsed a
|
|
483
|
+
parse failure onto an empty mapping, and every task rule short-circuits on
|
|
484
|
+
one — so a CI gate on `--fail-on-flagged` passed a task that would die at
|
|
485
|
+
schedule time. The parse failure is now its own `invalid-task-yaml` finding.
|
|
486
|
+
A `tasks/*.yaml` file — a spelling akm never indexes and never schedules —
|
|
487
|
+
used to be skipped by the directory walk entirely; it is now collected and
|
|
488
|
+
flagged for the extension, with the rename in the message. Fixed on all three
|
|
489
|
+
task-lint surfaces (the CLI sweep, the `akm` adapter's `validate`, and the
|
|
490
|
+
`akm-task` format adapter) from one shared parse, so they cannot disagree.
|
|
491
|
+
|
|
492
|
+
- **`akm lint --fix` refuses a bundle configured `writable: false`.** Every
|
|
493
|
+
other mutating command checks the flag before touching disk; `--fix` wrote
|
|
494
|
+
directly and never consulted it, so it rewrote frontmatter in a bundle
|
|
495
|
+
explicitly marked read-only. It is now a usage error raised before any file
|
|
496
|
+
is modified.
|
|
497
|
+
|
|
498
|
+
- **A `--fix` write failure no longer aborts the run and hides the fixes that
|
|
499
|
+
already landed.** One unwritable file (read-only file, full disk) threw
|
|
500
|
+
straight out of `akm lint`, so the caller got an exception instead of a
|
|
501
|
+
result — with no way to tell which earlier files in the same sweep had
|
|
502
|
+
already been rewritten. A failed fix is now reported in-band on its own file
|
|
503
|
+
as `fixed: "failed"`, and the sweep continues through the rest of the bundle.
|
|
504
|
+
|
|
505
|
+
- **`akm lint --type` says so when it does nothing.** For a non-akm bundle the
|
|
506
|
+
adapter validates the whole bundle regardless of `--type`, so scoping a run
|
|
507
|
+
silently had no effect. It now warns, naming the flag and the adapter.
|
|
508
|
+
Findings are unchanged (full-bundle validation was already a superset), and
|
|
509
|
+
it is deliberately a warning, not an error, so scripts passing one `--type`
|
|
510
|
+
across mixed-adapter bundle sets keep working.
|
|
511
|
+
|
|
512
|
+
- **`missing-skill-md` fires again for an `agent-skills` package with no
|
|
513
|
+
manifest.** The check iterated pending CHANGES, and a change is always a
|
|
514
|
+
file — so a package directory holding resources but no `SKILL.md`
|
|
515
|
+
contributed nothing it could see, and a skills pack with a broken package
|
|
516
|
+
linted clean. It is now a real directory pass over the bundle root. Related:
|
|
517
|
+
under opencode's supported singular `skill/` alias the same package went
|
|
518
|
+
unflagged while an identical one under `skills/` was caught; both spellings
|
|
519
|
+
are now checked.
|
|
520
|
+
|
|
521
|
+
- **An index akm cannot read no longer reports as an index that does not
|
|
522
|
+
exist.** `fs.existsSync()` answers `false` for a permission error exactly as
|
|
523
|
+
it does for a missing file, and the read path used it as its "is there an
|
|
524
|
+
index?" gate — so `akm search` and `akm curate` returned no hits at **exit 0**
|
|
525
|
+
with the tip *"No search index available. Run 'akm index' to build one."* for
|
|
526
|
+
a populated index sitting right there on disk, and `akm info` reported
|
|
527
|
+
`entryCount: 0, vecAvailable: false` for the same index. Nothing said
|
|
528
|
+
"permission". A consuming agent had no way to tell that from a genuine empty
|
|
529
|
+
result, so it relayed the false answer to its user with an explanation it had
|
|
530
|
+
invented.
|
|
531
|
+
|
|
532
|
+
Absent and inaccessible are now distinct everywhere it matters:
|
|
533
|
+
|
|
534
|
+
- `search` / `curate` / the index openers raise a `ConfigError`
|
|
535
|
+
(`DATA_DIR_UNREADABLE`, exit 78) naming the path, the errno, the mode and
|
|
536
|
+
owner, and the uid actually running — instead of an empty success.
|
|
537
|
+
- `akm info` reports an `indexStats.unreadable` diagnostic rather than zeros
|
|
538
|
+
that look healthy. The field is absent on every healthy run.
|
|
539
|
+
- `akm health` now *diagnoses* an unreadable `state.db` as a failing
|
|
540
|
+
`state-db-readable` check instead of dying on the open before it could
|
|
541
|
+
report anything — it is the command you reach for when this happens.
|
|
542
|
+
- `probeLock` returns a distinct `inaccessible` state instead of classifying a
|
|
543
|
+
permission error as a stale lock. "I cannot read this lock" and "the holder
|
|
544
|
+
is dead" are opposite facts, and `akm improve` now stops rather than
|
|
545
|
+
reclaiming a lease that may be genuinely held.
|
|
546
|
+
|
|
547
|
+
The same conflation existed on the write paths, where the consequence was
|
|
548
|
+
worse than a wrong answer:
|
|
549
|
+
|
|
550
|
+
- **An unreadable `akm.lock` could destroy every bundle record in it.** The
|
|
551
|
+
lockfile read that exists specifically so a write path never sees `[]`
|
|
552
|
+
returned `[]` for *any* read failure, permission errors included — and
|
|
553
|
+
every lockfile write is read-modify-write, so the next atomic write
|
|
554
|
+
replaced the operator's whole lock record with the single entry being
|
|
555
|
+
added. Verified by probe: the symlink was replaced by a regular file
|
|
556
|
+
holding one entry. Lockfile writes now refuse to run against a lock they
|
|
557
|
+
cannot read.
|
|
558
|
+
- **The migration recovery gate failed open.** "I cannot tell whether a
|
|
559
|
+
recovery is pending" cleared the gate exactly as "no recovery is pending"
|
|
560
|
+
did, so akm would open the canonical databases on top of a half-applied
|
|
561
|
+
migration. It now fails closed.
|
|
562
|
+
- **`akm index --clean` deleted rows for files it merely could not look at**,
|
|
563
|
+
and reported the deletions as a clean success. Unreadable entries are now
|
|
564
|
+
kept and named.
|
|
565
|
+
- `indexWrittenAssets` returned `true` — "the index is as you expect" — for
|
|
566
|
+
an index it could not open, on the strength of which `acceptProposal`
|
|
567
|
+
advanced its journal to `index-finalized`.
|
|
568
|
+
- `akm improve` eligibility, `akm feedback`, `akm bundle list` and the graph
|
|
569
|
+
loaders each turned a permission fault into an empty result, a zero count,
|
|
570
|
+
or the advice to "Run `akm index` first".
|
|
571
|
+
|
|
572
|
+
- **akm no longer manages permissions on your data directory, its databases, or
|
|
573
|
+
your task logs — and no longer reports on them either.** Those take your
|
|
574
|
+
process umask; their mode is yours to set, and `chmod`/`umask` are your
|
|
575
|
+
levers.
|
|
576
|
+
|
|
577
|
+
This is scoped, not blanket: akm still creates a handful of files at
|
|
578
|
+
restrictive modes *at creation time*, as it always has — `env` and `secret`
|
|
579
|
+
assets and config backups at `0600`, their directories at `0700`, and the
|
|
580
|
+
scheduler invocation files it writes for cron/launchd/schtasks. Those are
|
|
581
|
+
files akm authors itself and whose contents are credentials; setting their
|
|
582
|
+
mode when creating them is not the same as re-permissioning a directory you
|
|
583
|
+
already owned.
|
|
584
|
+
|
|
585
|
+
Two 0.9.1 pre-release changes are gone. The first chmodded akm's databases
|
|
586
|
+
and task logs to `0600`/`0700` on every open — reverted because
|
|
587
|
+
re-permissioning a directory akm did not create silently broke installs that
|
|
588
|
+
share `$XDG_DATA_HOME` between two uids (agent sandboxes, containers, service
|
|
589
|
+
accounts). If a pre-release tightened your data directory, `chmod` it back.
|
|
590
|
+
The second was an `akm health` advisory (`secret-file-perms`) that reported
|
|
591
|
+
group/other-readable `env`, `secrets` and `config-backups` paths — removed
|
|
592
|
+
too: it is meaningless on Windows, and nagging about modes akm does not set
|
|
593
|
+
is not health reporting. `akm health` no longer emits this check, and no
|
|
594
|
+
longer exits `4` on account of it.
|
|
595
|
+
|
|
596
|
+
- **`timeout: none` on an exec unit is genuinely unbounded again.** The
|
|
597
|
+
stream-drain safety net — a one-hour bound on a pipe still being read after
|
|
598
|
+
the child is gone — was armed when capture STARTED, so a command that ran
|
|
599
|
+
past an hour had its output reader cancelled mid-run and was then failed for
|
|
600
|
+
an incomplete capture even though it exited 0. It is now armed from the
|
|
601
|
+
child's exit, which is the only window it was ever meant to bound.
|
|
602
|
+
|
|
603
|
+
- **A bounded exec unit no longer waits out its whole `timeout` after the
|
|
604
|
+
command has already exited.** The drain deadline for a unit WITH a wall budget
|
|
605
|
+
ran from the moment capture started — budget plus a 2 s grace — so a command
|
|
606
|
+
that exited in milliseconds while a background descendant held a pipe open
|
|
607
|
+
kept the unit, and with it a fan-out slot, occupied for the entire declared
|
|
608
|
+
timeout before reporting. It now runs from the moment nothing living owns the
|
|
609
|
+
pipe: the child's exit, or (for a child that outlived its own kill ladder) the
|
|
610
|
+
budget's expiry, plus the same 2 s grace. A command that really does spend its
|
|
611
|
+
whole budget sees the identical ceiling it saw before; only the case that used
|
|
612
|
+
to stall stopped stalling.
|
|
613
|
+
|
|
614
|
+
- **A stderr drain that never finished no longer fails an exec unit whose
|
|
615
|
+
command succeeded.** `exec_capture_incomplete` was raised when EITHER pipe
|
|
616
|
+
failed to drain, so a command that exited 0 with its stdout captured whole was
|
|
617
|
+
failed — and a valid artifact thrown away — because a background descendant
|
|
618
|
+
was still holding STDERR open. stderr is a diagnostic channel that never
|
|
619
|
+
contributes to the artifact, so only an incomplete STDOUT capture fails the
|
|
620
|
+
unit now; an incomplete stderr drain is reported on the warn stream instead,
|
|
621
|
+
naming the unit and warning that any stderr shown for it may be missing its
|
|
622
|
+
tail.
|
|
623
|
+
|
|
624
|
+
- **A step artifact larger than 1 MiB no longer breaks the next step of the run
|
|
625
|
+
that produced it.** Step evidence is clipped to bound one SQLite row, and the
|
|
626
|
+
engine rebuilt each downstream `steps.<id>.output` scope by re-reading those
|
|
627
|
+
rows — so a large artifact (an exec unit's stdout retains up to 8 MiB) reached
|
|
628
|
+
the very next step as a truncation marker: a path reference failed with a
|
|
629
|
+
missing-property error that never mentioned truncation, and a whole-value
|
|
630
|
+
reference silently handed the marker to the unit as its input. The run now
|
|
631
|
+
carries its own complete values forward; the row stays clipped for resume,
|
|
632
|
+
where a reference into a clipped artifact fails by name.
|
|
633
|
+
|
|
634
|
+
- **A workflow run that completed is no longer reported as timed out.** The
|
|
635
|
+
deadline is observed between steps, so one landing during a run's final
|
|
636
|
+
bookkeeping set the timed-out flag on a run that then finished. On a scheduled
|
|
637
|
+
workflow task that recorded the attempt as failed, with a hint to resume a run
|
|
638
|
+
that had nothing left to resume; under `akm workflow run --timeout` it
|
|
639
|
+
rendered a `timedOut` marker on a `completed` run and exited nonzero. Both
|
|
640
|
+
surfaces now drop the marker once the run reached `completed` — a deadline
|
|
641
|
+
that lands with nothing left to abort has nothing to report.
|
|
642
|
+
|
|
643
|
+
- **A rejected gate on an `exec` step no longer re-runs the command.** A gate
|
|
644
|
+
loop earns its re-dispatch by handing the judge's feedback to a unit that can
|
|
645
|
+
answer it. An exec unit cannot: its argv is frozen and never interpolated, and
|
|
646
|
+
the exec context environment carries no feedback variable — so the loop could
|
|
647
|
+
only re-run the byte-identical command, performing a deploy, a publish, or a
|
|
648
|
+
migration a second time for a verdict that could not change. The gate still
|
|
649
|
+
EVALUATES on an exec step and can still fail it: a rejection is final on the
|
|
650
|
+
first evaluation, carrying the judge's missing criteria and feedback exactly
|
|
651
|
+
as in the one-shot case. What an author sees is
|
|
652
|
+
that `gate.max_loops` is capped at 1 on a step whose unit is `exec:` — not an
|
|
653
|
+
authoring error, and no change at all to an engine step, where a declared
|
|
654
|
+
`max_loops` is still honored in full. This is the same reasoning that already
|
|
655
|
+
makes an exec unit's `output:` schema miss fail without a corrective
|
|
656
|
+
re-dispatch.
|
|
657
|
+
|
|
658
|
+
- **The stale-worktree sweep no longer collects a worktree that is still in
|
|
659
|
+
use.** The opportunistic age-based GC of leftover `isolation: worktree` trees
|
|
660
|
+
judged staleness from the worktree root's mtime, which a unit writing only
|
|
661
|
+
inside subdirectories never touches — so another akm process minting a
|
|
662
|
+
worktree could delete the tree a long-running unit was working in. Every live
|
|
663
|
+
worktree now carries a liveness marker (pid, host, resolved path) in git's own
|
|
664
|
+
administrative directory for it, and the sweep skips a candidate whose holder
|
|
665
|
+
is still running here. A marker from a dead pid, from another host, or for a
|
|
666
|
+
different path is not liveness: crashed runs and retained dirty trees stay
|
|
667
|
+
collectible, which is what the sweep exists for.
|
|
668
|
+
|
|
669
|
+
- On Windows, an agent CLI, gate judge, or prompt task was spawned into an
|
|
670
|
+
environment the loader cannot start from: the shared passthrough allowlist
|
|
671
|
+
named no `SystemRoot`/`SystemDrive`/`WINDIR`, and without `PATHEXT` a
|
|
672
|
+
`bin: "bun"` profile was unresolvable — while an exec unit on the same host
|
|
673
|
+
worked, because its own allowlist names them. Those variables are now added
|
|
674
|
+
when any allowlisted child environment is built.
|
|
675
|
+
|
|
676
|
+
- Scheduler PATH repair skipped itself in the environments it exists for. It
|
|
677
|
+
decided a PATH was "interactive" by testing whether any entry began with the
|
|
678
|
+
user's home directory as a *string*, so a home of `/` — system crontab,
|
|
679
|
+
launchd, service accounts — matched every absolute entry, and a sibling home
|
|
680
|
+
(`/home/alice/bin` against `/home/al`) matched too.
|
|
681
|
+
|
|
682
|
+
- A directory whose name merely begins with two dots (`..data`) was treated as
|
|
683
|
+
a path escape. For a workflow exec `cwd` that meant the parser and the frozen
|
|
684
|
+
plan accepted a spelling the executor then failed as tampering, with a reason
|
|
685
|
+
no retry can clear.
|
|
686
|
+
|
|
687
|
+
- `appendEvent` resolved the state.db path outside its own error handling, and
|
|
688
|
+
did so even when the caller supplied an open connection — so a caller holding
|
|
689
|
+
a perfectly good handle could take a configuration error from a function whose
|
|
690
|
+
contract is that it never propagates one.
|
|
691
|
+
|
|
692
|
+
- Workflow freeze attributed per-step `engine`/`model`/`timeout`/`llm` overrides
|
|
693
|
+
by matching the compiled draft step list against the source document
|
|
694
|
+
**positionally**. That was correct only because compilation happens to be 1:1
|
|
695
|
+
and order-preserving; a compile pass that filtered or reordered steps would
|
|
696
|
+
have silently applied one step's overrides to another. Attribution is now
|
|
697
|
+
keyed by `stepId`.
|
|
698
|
+
|
|
699
|
+
### Security
|
|
700
|
+
|
|
701
|
+
- **A gate judge's response is now scrubbed before it is journaled.** The judge
|
|
702
|
+
verdict is written into the gate row's `result_json`, and a judge failure's
|
|
703
|
+
message becomes the blocked step's notes — but the judge dispatch bypassed
|
|
704
|
+
the redaction contract every unit dispatch goes through, so a judge that
|
|
705
|
+
echoed a credential out of the promoted artifact persisted it unredacted into
|
|
706
|
+
the workflow journal. Both judge paths (agent and llm) now wrap their
|
|
707
|
+
dispatch in the same scrub, with the sensitive-value set collected per
|
|
708
|
+
dispatch rather than at build time, so a credential rotated between the two
|
|
709
|
+
reads is still caught. The dispatch also carries the real run/step/gate ids
|
|
710
|
+
instead of a synthetic `"gate"` placeholder, so a gate row and its telemetry
|
|
711
|
+
describe the same thing.
|
|
712
|
+
|
|
713
|
+
- **Command-target task logs are scrubbed of exact secret values**, closing the
|
|
714
|
+
last redaction lane — see the `### Fixed` entry above for the full account.
|
|
715
|
+
|
|
716
|
+
## [0.9.0] - 2026-08-06
|
|
8
717
|
|
|
9
718
|
0.9.0 is the format-neutral **bundle / adapter** refactor: it replaces the flat
|
|
10
719
|
asset-type registry with per-format adapters, adopts one canonical ref grammar,
|
|
11
|
-
and consolidates the durable databases and config. This section
|
|
12
|
-
|
|
720
|
+
and consolidates the durable databases and config. This section consolidates and
|
|
721
|
+
supersedes the `0.9.0-rc.*` / `0.9.0-beta.*` development entries below.
|
|
13
722
|
|
|
14
723
|
### Breaking changes & migration
|
|
15
724
|
|
|
@@ -28,17 +737,18 @@ earlier `0.9.0-rc.1` / `0.9.0-beta.*` development entries below.
|
|
|
28
737
|
fully-qualified `bundle//conceptId`; the short bundle-omitted form is accepted
|
|
29
738
|
input only (resolved against `defaultBundle`, then installation-priority
|
|
30
739
|
order). The pre-0.9.0 `[origin//]type:name` grammar is removed — there is no
|
|
31
|
-
compatibility parser; the frozen migrator in `
|
|
32
|
-
place it survives.
|
|
33
|
-
- **Explicit,
|
|
740
|
+
compatibility parser; the frozen migrator in `scripts/akm-migrate/migrate/`
|
|
741
|
+
is the only place it survives.
|
|
742
|
+
- **Explicit, crash-resumable cutover (`akm migrate apply`).** The
|
|
34
743
|
migrator re-keys all durable state to the new spelling, folds the former
|
|
35
744
|
`workflow.db` into `state.db` (four databases down to three: `state.db` /
|
|
36
745
|
`index.db` / a separate `logs.db`), and migrates config from the flat
|
|
37
746
|
`stashDir` / `sources` / `installed` / `wikiName` keys to `bundles` /
|
|
38
|
-
`defaultBundle`. A verified, installation-scoped **backup manifest
|
|
39
|
-
(covering the pre-rescue `index.db`) is taken before
|
|
40
|
-
|
|
41
|
-
|
|
747
|
+
`defaultBundle`. A semantically verified, installation-scoped **backup manifest v4**
|
|
748
|
+
(covering the pre-rescue `index.db`) is taken before mutation. One phase-free
|
|
749
|
+
incomplete sentinel retains that backup and target; expected orphans are
|
|
750
|
+
quarantined, integrity failures fail closed, and the whole cutover reruns
|
|
751
|
+
idempotently after a crash. Normal commands refuse an
|
|
42
752
|
un-migrated or divergent durable schema rather than migrating as a side effect.
|
|
43
753
|
The retired `stashDir` / `sources` / `installed` keys are **hard-rejected** by
|
|
44
754
|
the 0.9.0 config schema whenever present (the error names `akm migrate apply`);
|
|
@@ -52,7 +762,7 @@ earlier `0.9.0-rc.1` / `0.9.0-beta.*` development entries below.
|
|
|
52
762
|
index (and renamed by the content migration when they hold a real concept).
|
|
53
763
|
- **`vault` asset type removed.** Use `env` (a whole `.env` group; key names
|
|
54
764
|
surfaced, values never) and `secret` (a single sensitive value), addressed as
|
|
55
|
-
`env/<name>` and `secrets/<name>`. `akm-migrate
|
|
765
|
+
`env/<name>` and `secrets/<name>`. `akm-migrate storage` performs the
|
|
56
766
|
non-destructive `vaults/` → `env/` copy for older stashes.
|
|
57
767
|
- **0.8-era CLI aliases removed.** The flat proposal verbs (`akm proposals`,
|
|
58
768
|
`akm accept`, `akm reject`, `akm diff`, `akm revert`, `akm show proposal`),
|
|
@@ -64,8 +774,95 @@ earlier `0.9.0-rc.1` / `0.9.0-beta.*` development entries below.
|
|
|
64
774
|
See `docs/migration/v0.8-to-v0.9.md` and
|
|
65
775
|
`docs/migration/release-notes/0.9.0.md` for the full upgrade procedure.
|
|
66
776
|
|
|
777
|
+
### Removed
|
|
778
|
+
|
|
779
|
+
- **The experimental `akm workflow brief` / `akm workflow report`
|
|
780
|
+
external-driver protocol is removed**, along with the
|
|
781
|
+
`experimental.workflowEngine` config key that gated it, its
|
|
782
|
+
`WORKFLOW_ENGINE_NOT_ENABLED` error code, and the `workflowEngine` block in
|
|
783
|
+
`akm task doctor`. `akm workflow run` is now the single execution surface.
|
|
784
|
+
|
|
785
|
+
The protocol let a calling agent session execute a run's units itself
|
|
786
|
+
instead of akm dispatching them. Its stated justification was harness
|
|
787
|
+
neutrality, which measurement did not support: native dispatch already
|
|
788
|
+
covers **ten** harnesses (opencode, claude, opencode-sdk, codex, copilot,
|
|
789
|
+
pi, gemini, aider, amazonq, openhands) in 2,214 LOC total, while the
|
|
790
|
+
protocol cost 2,690 LOC on its own — more than supporting every harness
|
|
791
|
+
natively — and an eleventh harness is ~220 lines, not a protocol. Removing
|
|
792
|
+
it also drops the second consumer of `workflow_run_units` and the
|
|
793
|
+
cross-surface parity obligation on `step-work.ts`, both of which
|
|
794
|
+
constrained every future engine change. The analysis is recorded in
|
|
795
|
+
`docs/architecture/specs/driver-protocol-keep-or-cut.md`.
|
|
796
|
+
|
|
797
|
+
Legacy configs setting `experimental.workflowEngine` remain valid — the
|
|
798
|
+
config schema is `.passthrough()`, so the key is accepted and ignored.
|
|
799
|
+
|
|
67
800
|
### Added
|
|
68
801
|
|
|
802
|
+
- **`akm workflow run` and prompt tasks fall back to `opencode-sdk` instead of
|
|
803
|
+
refusing when no engine is configured.** A clean install that never ran
|
|
804
|
+
`akm setup` — a bare container, a CI image, an agent-operated session — used
|
|
805
|
+
to fail closed with `INVALID_CONFIG_FILE` (exit 78). When the `opencode`
|
|
806
|
+
binary is on PATH, akm now synthesizes a **config-free** `opencode-sdk`
|
|
807
|
+
engine: it carries no model, endpoint, or credential, so provider, model,
|
|
808
|
+
and auth all resolve from opencode's own configuration and akm never mirrors
|
|
809
|
+
or validates it. With `opencode` absent the failure is unchanged, and its
|
|
810
|
+
remedy now names both routes. An operator-configured `opencode-sdk` engine
|
|
811
|
+
always wins over the synthesized one.
|
|
812
|
+
|
|
813
|
+
The requirement is the **binary**, not the npm package: `@opencode-ai/sdk`
|
|
814
|
+
is an HTTP client that declares no dependencies and whose own
|
|
815
|
+
`createOpencodeServer` spawns `opencode serve`, so a host with the package
|
|
816
|
+
and no binary has no server to reach. Install it with `npm i -g opencode-ai`
|
|
817
|
+
or opencode's own installer.
|
|
818
|
+
|
|
819
|
+
The fallback is **announced, never silent** on every surface that applies
|
|
820
|
+
it: a workflow run surfaces it once at run creation in the result's
|
|
821
|
+
`warnings`, a prompt task writes it to the task run log, `akm agent`
|
|
822
|
+
carries it in its result `warnings` and on stderr, and `propose` and
|
|
823
|
+
`improve` reflect warn on stderr. The frozen plan records the engine
|
|
824
|
+
actually used, so a resume never re-announces a decision it did not make.
|
|
825
|
+
|
|
826
|
+
- **RSS, Bluesky, and X sources.** `akm bundle add` now recognizes three new
|
|
827
|
+
kinds of URL and snapshots them as knowledge assets instead of crawling
|
|
828
|
+
them as ordinary web pages:
|
|
829
|
+
|
|
830
|
+
```sh
|
|
831
|
+
akm bundle add https://blog.example/feed # RSS 2.0 / Atom / RDF
|
|
832
|
+
akm bundle add https://bsky.app/profile/<handle> # public, no auth
|
|
833
|
+
akm bundle add https://x.com/<user> # see token note below
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
Any of these falling through — a `/feed` URL that actually serves HTML, an
|
|
837
|
+
unresolvable Bluesky handle — degrades to the normal website crawl rather
|
|
838
|
+
than failing the command.
|
|
839
|
+
|
|
840
|
+
X needs credentials: set `X_BEARER_TOKEN` for the X API v2, or
|
|
841
|
+
`X_RSS_TEMPLATE` to an RSS bridge URL containing `{username}`. To keep the
|
|
842
|
+
token out of your shell history, store it as an akm secret and inject it
|
|
843
|
+
per-invocation:
|
|
844
|
+
|
|
845
|
+
```sh
|
|
846
|
+
akm secret set x-bearer-token
|
|
847
|
+
akm secret run secrets/x-bearer-token X_BEARER_TOKEN -- akm bundle add https://x.com/<user>
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
With neither set, the X fetcher emits one warning and falls through.
|
|
851
|
+
|
|
852
|
+
- **`akm-migrate` derives the 0.9 config from your 0.8 keys instead of
|
|
853
|
+
demanding one.** Upgrading used to require hand-authoring a complete 0.9
|
|
854
|
+
config before `migrate apply` would act. The first `apply` with no
|
|
855
|
+
`--config` now writes a validated starter config — `bundles`/`defaultBundle`
|
|
856
|
+
derived from the 0.8 `stashDir` / `sources` / `installed` keys — to a
|
|
857
|
+
predictable path under the backup root and stops, with config and durable
|
|
858
|
+
state byte-for-byte untouched; a second `apply` picks it up and performs the
|
|
859
|
+
cutover. Engine settings are never guessed: `profiles.*` and
|
|
860
|
+
`defaults.llm|agent|improve` are stripped and reported individually in
|
|
861
|
+
`droppedKeys` by their exact 0.8 dotted path. `status` and `apply --dry-run`
|
|
862
|
+
preview the same plan, and an explicit `--config` always wins and is never
|
|
863
|
+
overwritten. `akm migrate --format` now renders text/md/html/yaml through
|
|
864
|
+
the normal output pipeline instead of warning and printing JSON anyway.
|
|
865
|
+
|
|
69
866
|
- **Local downstream value attribution for memory inference and graph
|
|
70
867
|
extraction.** Private search-hit sidecars now write versioned, source-qualified
|
|
71
868
|
per-entry `usage_events.metadata` for emitted MI direct/surface value and the
|
|
@@ -79,33 +876,25 @@ See `docs/migration/v0.8-to-v0.9.md` and
|
|
|
79
876
|
migration, dashboard, or health schema was added.
|
|
80
877
|
- **Explicit, crash-resumable 0.9 migration coordination.** `akm migrate
|
|
81
878
|
status` classifies config, `state.db`, and `workflow.db` independently;
|
|
82
|
-
`akm migrate apply [--config <prepared>]` creates a verified,
|
|
83
|
-
installation-scoped backup before
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Routine reads and current database opens no longer depend on a
|
|
88
|
-
cutover bundle. See `docs/migration/release-notes/0.9.0.md`.
|
|
879
|
+
`akm migrate apply [--config <prepared>]` creates a semantically verified,
|
|
880
|
+
installation-scoped config/database backup before applying pending migrations.
|
|
881
|
+
Apply and restore use one phase-free incomplete sentinel, bounded control-file
|
|
882
|
+
reads, SQLite integrity and ordered-ledger checks, active-writer barriers,
|
|
883
|
+
WAL/SHM-safe publication, and idempotent replay. Legacy checksum columns are
|
|
884
|
+
inert. Routine reads and current database opens no longer depend on a
|
|
885
|
+
historical cutover bundle. See `docs/migration/release-notes/0.9.0.md`.
|
|
89
886
|
- **Workflow orchestration engine (experimental).** akm can now execute
|
|
90
|
-
multi-step workflows
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
once into an AST) wires steps together. `validate` also surfaces non-fatal
|
|
102
|
-
**warnings** (a step with no typed `output:` schema; a `${{ params.<name> }}`
|
|
103
|
-
reference to a param the declared `params:` block omits) that never change
|
|
104
|
-
the frozen plan or its hash. Creating a workflow whose canonical name
|
|
105
|
-
collides with an existing asset of a **different** extension (`foo.yaml`
|
|
106
|
-
while `foo.md` exists, or vice-versa) is refused, since the two would
|
|
107
|
-
silently shadow each other.
|
|
108
|
-
- **Compilation + frozen plans.** `akm workflow start` compiles the program
|
|
887
|
+
multi-step workflows through a native engine or any agent session. Workflow
|
|
888
|
+
assets use the unified markdown format described above; the stable manual
|
|
889
|
+
CLI contract (`start`/`next`/`complete`/`status`/`list`) and the experimental
|
|
890
|
+
engine consume the same asset. What ships:
|
|
891
|
+
- **Authoring.** A workflow is a markdown asset whose frontmatter graph is
|
|
892
|
+
validated against `schemas/akm-workflow.json` and whose `## <step-id>` body
|
|
893
|
+
sections carry instructions and gate rubrics. `akm workflow create`
|
|
894
|
+
scaffolds that format; `akm lint --type workflows` parses and compiles it.
|
|
895
|
+
Bare references (`params.<name>` and `steps.<id>.output.<path>`) wire
|
|
896
|
+
`map.over`, `route.input`, and `inputs`; prose is never interpolated.
|
|
897
|
+
- **Compilation + frozen plans.** `akm workflow start` compiles the workflow
|
|
109
898
|
into a backend-agnostic Workflow Plan Graph IR (`src/workflows/ir/`) and
|
|
110
899
|
freezes it on the run row (`plan_json` + `plan_hash`); a run executes the
|
|
111
900
|
plan compiled at start, and edits to the source file require a new run.
|
|
@@ -114,8 +903,7 @@ See `docs/migration/v0.8-to-v0.9.md` and
|
|
|
114
903
|
reducer), a typed `output` JSON Schema (validated via a `runStructured`
|
|
115
904
|
retry-with-feedback loop), `env` bindings (resolved through the existing
|
|
116
905
|
`akm env run` machinery — secret tokens, dangerous-key policy, keys-only
|
|
117
|
-
audit events), classify-and-dispatch `route` steps
|
|
118
|
-
ordering.
|
|
906
|
+
audit events), and classify-and-dispatch `route` steps.
|
|
119
907
|
- **Determinism + replay.** Journaled unit identity is content-derived
|
|
120
908
|
(`<step>:<sha256(item)[:12]>`, `:solo` for a single unit), so cached
|
|
121
909
|
results survive item-list reordering; a completed unit whose recorded
|
|
@@ -137,9 +925,9 @@ See `docs/migration/v0.8-to-v0.9.md` and
|
|
|
137
925
|
criteria-bearing gate judges that **artifact** (canonical JSON, clipped)
|
|
138
926
|
rather than machine prose, and each engine-driven evaluation is journaled
|
|
139
927
|
as a gate unit row. `gate.max_loops` bounds an evaluator-optimizer retry
|
|
140
|
-
loop (feedback threaded into re-dispatched unit prompts)
|
|
141
|
-
|
|
142
|
-
|
|
928
|
+
loop (feedback threaded into re-dispatched unit prompts). Gates are
|
|
929
|
+
optional validation: omitted/empty rubrics and unavailable or malformed
|
|
930
|
+
judges skip validation.
|
|
143
931
|
- **Failure policy.** Per-unit `on_error: fail | continue` (fail-fast
|
|
144
932
|
default) plus bounded `retry: { max, on: [<failure_reason>…] }` keyed on
|
|
145
933
|
the persisted failure taxonomy.
|
|
@@ -370,6 +1158,62 @@ See `docs/migration/v0.8-to-v0.9.md` and
|
|
|
370
1158
|
|
|
371
1159
|
### Changed
|
|
372
1160
|
|
|
1161
|
+
- **X source tokens now resolve from the secret store during bundle update.**
|
|
1162
|
+
The `secrets/x-bearer-token` akm secret is honored on the provider
|
|
1163
|
+
`sync()` / bundle-update path, not just when adding or importing a URL —
|
|
1164
|
+
closing a gap where a refresh saw only the `X_BEARER_TOKEN` environment
|
|
1165
|
+
variable. Implemented as a `SecretResolver` capability injected from above
|
|
1166
|
+
the source-provider import cycle; internals are documented in
|
|
1167
|
+
`docs/architecture/reviews/env-secret-access.md`.
|
|
1168
|
+
|
|
1169
|
+
- **`website` crawls now have a hard time limit.** `crawlTimeoutMs` (default
|
|
1170
|
+
600000 — 10 minutes) bounds the entire crawl, and unlike the previous
|
|
1171
|
+
between-page check it aborts work already in flight: a `Retry-After` sleep
|
|
1172
|
+
could previously park `akm bundle add` for as long as a rate-limiting server
|
|
1173
|
+
asked, well past the advertised cap. Raise it for a large site, or set
|
|
1174
|
+
`"crawlTimeoutMs": 0` to disable the cap. Relatedly, `fetchWithRetry` now
|
|
1175
|
+
honors its caller's `AbortSignal` during retry backoff, so any operation that
|
|
1176
|
+
passes a signal can actually interrupt a long wait.
|
|
1177
|
+
|
|
1178
|
+
- **Website snapshots now extract the page's main content.** Conversion moved
|
|
1179
|
+
from a hand-rolled regex converter to a DOM parse plus Turndown, scoped to
|
|
1180
|
+
the page's content region (`<main>`, `<article>`, `[role=main]`, then common
|
|
1181
|
+
content ids/classes, falling back to `<body>` minus nav/header/footer/aside).
|
|
1182
|
+
Navigation, ads, and boilerplate no longer land in snapshots, and tables,
|
|
1183
|
+
nested lists, and fenced code blocks with language hints now survive
|
|
1184
|
+
conversion. **Existing website snapshots will change on their next refresh**
|
|
1185
|
+
— expect them to get shorter and cleaner. Link discovery still scans the
|
|
1186
|
+
whole page, so crawl coverage is unchanged.
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
- **`website` sources now respect `robots.txt` by default.** Before crawling
|
|
1190
|
+
an origin, akm fetches and parses that origin's `/robots.txt` and skips
|
|
1191
|
+
paths disallowed for the `akm`/`akm-cli` product tokens (or `*`), honoring
|
|
1192
|
+
`Crawl-delay` (clamped to 10s) between page fetches. This is a deliberate
|
|
1193
|
+
behavior change: **existing website sources may return fewer pages, or
|
|
1194
|
+
fail with an error if the start URL itself is disallowed, after
|
|
1195
|
+
upgrading.** Re-running `akm bundle update` on a website source is what
|
|
1196
|
+
surfaces it. Opt out with `"respectRobots": false` on the website
|
|
1197
|
+
descriptor to restore the exact pre-upgrade behavior (no `/robots.txt`
|
|
1198
|
+
request at all):
|
|
1199
|
+
|
|
1200
|
+
```json
|
|
1201
|
+
{ "bundles": { "docs": { "website": { "url": "https://docs.example.com", "respectRobots": false } } } }
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
- **`akm lint` now routes through each bundle adapter's own `validate()`.**
|
|
1205
|
+
`validate()` was a required member of the adapter interface that nothing
|
|
1206
|
+
called: `akm lint` branched on adapter id and re-implemented OKF's checks
|
|
1207
|
+
inline (with drifted semantics for `missing-type`), OKF's `missing-ref`
|
|
1208
|
+
never ran at all (a bundle with a dangling link reported nothing), and
|
|
1209
|
+
llm-wiki's `uncited-raw` / `broken-xref` / `broken-source` /
|
|
1210
|
+
`missing-description` checks were unreachable dead code. **Existing OKF and
|
|
1211
|
+
llm-wiki bundles may surface new lint findings after upgrading.** akm-bundle
|
|
1212
|
+
lint output is byte-identical. Proposal promotion also runs the adapter
|
|
1213
|
+
check immediately before the write — advisory-only: it warns and never
|
|
1214
|
+
rejects, because the adapter resolver and the legacy promotion gate still
|
|
1215
|
+
disagree on foreign-typed cross-bundle refs.
|
|
1216
|
+
|
|
373
1217
|
- **Improve-stage extraction and proactive maintenance now ship opt-in.** The
|
|
374
1218
|
built-in `default` and `frequent` strategies resolve extract off, while
|
|
375
1219
|
`default` and `reflect-distill` resolve `proactiveMaintenance` off. The
|
|
@@ -440,6 +1284,61 @@ See `docs/migration/v0.8-to-v0.9.md` and
|
|
|
440
1284
|
|
|
441
1285
|
### Fixed
|
|
442
1286
|
|
|
1287
|
+
- **Fresh 0.8 installs can actually upgrade.** A config that 0.8.x wrote
|
|
1288
|
+
itself carries no `configVersion` key at all (0.8 stamped it only when a
|
|
1289
|
+
0.7-era migration did substantive work), and the migrator read the absent
|
|
1290
|
+
key as `inconsistent` — an unconditional blocker. `migrate status` reported
|
|
1291
|
+
`blocked` and `migrate apply` refused with exit 78 for every fresh 0.8
|
|
1292
|
+
install; reproduced end to end against the published `akm-cli@0.8.14`. An
|
|
1293
|
+
absent `configVersion` on a positively pre-cutover-shaped config now
|
|
1294
|
+
classifies as `old`; a present-but-unparseable version still fails closed.
|
|
1295
|
+
Relatedly, `migrate` reports `not-applicable` (exit 0) instead of `blocked`
|
|
1296
|
+
when there is no akm installation to migrate at all, and `apply` warns when
|
|
1297
|
+
an active workflow run targets an asset that fails 0.9 structural
|
|
1298
|
+
validation, naming the asset and `akm workflow abandon <run-id>`.
|
|
1299
|
+
|
|
1300
|
+
- **`akm lint` fails closed on mistyped invocations.** A nonexistent `--dir`,
|
|
1301
|
+
or an unknown `--type` on an akm bundle (the classic singular/plural typo,
|
|
1302
|
+
`--type workflow`), used to scan nothing and report a clean
|
|
1303
|
+
`ok:true, flagged:0` — silently passing scripted `--fail-on-flagged`
|
|
1304
|
+
gates. Both are now usage errors (exit 2), the `--type` error listing the
|
|
1305
|
+
valid values.
|
|
1306
|
+
- **Registry search survives a briefly unreachable registry.** Once the
|
|
1307
|
+
cached registry index aged past its refresh TTL, a failed fetch
|
|
1308
|
+
hard-failed the command even though a serviceable index sat in the cache.
|
|
1309
|
+
A failed fetch now serves the last cached index — past its TTL — with a
|
|
1310
|
+
warning naming the fetch error.
|
|
1311
|
+
- **`akm upgrade` verifies the package manager actually delivered the new
|
|
1312
|
+
version.** A lagging `@latest` dist-tag (partial publish, registry mirror
|
|
1313
|
+
lag) exits 0 while leaving the old version on PATH; upgrade used to report
|
|
1314
|
+
success anyway — and then run `migrate apply` against the old binary. It
|
|
1315
|
+
now re-reads `akm --version` after the install: a confirmed mismatch
|
|
1316
|
+
reports `upgraded: false` with an exact-version pin command, and a
|
|
1317
|
+
verified match is named in the success message.
|
|
1318
|
+
- **`akm info` no longer overstates semantic-search health.** After a run
|
|
1319
|
+
with partial sqlite-vec fast-path insert failures, the verification
|
|
1320
|
+
reported `ready-vec` ("sqlite-vec active") even though search had already
|
|
1321
|
+
routed to the slower JS-cosine fallback. The status now reflects the path
|
|
1322
|
+
search actually takes, with an `akm index --full` hint when the fast path
|
|
1323
|
+
is degraded. Relatedly, `embedding.dimension` is now bounded to the
|
|
1324
|
+
vec table's own 1–4096 limit at config validation, so an out-of-range
|
|
1325
|
+
value fails at `akm config set` with a clear message instead of crashing
|
|
1326
|
+
`akm index` mid-run.
|
|
1327
|
+
- **Standalone `akm remember --enrich` actually enriches.** With no other
|
|
1328
|
+
metadata flag, `--enrich` fell through to the zero-flag raw-write hot path
|
|
1329
|
+
and never attempted the LLM call — an unenriched memory with no warning.
|
|
1330
|
+
`--enrich` now routes to the enrichment dispatch exactly like `--auto`;
|
|
1331
|
+
the fail-soft contract is unchanged (no configured LLM still warns and
|
|
1332
|
+
writes without enrichment).
|
|
1333
|
+
- **Read paths no longer plant a broken `index.db` on a fresh install.**
|
|
1334
|
+
The fire-and-forget usage telemetry behind `search` / `show` / `curate`
|
|
1335
|
+
opened `index.db` with create-on-open: with no index built yet, the open
|
|
1336
|
+
itself left an empty, schema-less `index.db` behind, and every later
|
|
1337
|
+
command then saw an existing-but-broken index ("no such table: entries") —
|
|
1338
|
+
hard-failing proposal acceptance among others. `openExistingDatabase` now
|
|
1339
|
+
refuses to create the file (a missing index throws, naming `akm index` as
|
|
1340
|
+
the remedy) and the telemetry paths skip cleanly instead.
|
|
1341
|
+
|
|
443
1342
|
- **Improve RC stabilization.** Restored one ownership-safe whole-run lock from
|
|
444
1343
|
triage through final sync; `--skip-if-locked` is a true no-op; the run deadline
|
|
445
1344
|
now starts before indexing and reaches index waits, generation, reindexing, and
|
|
@@ -465,6 +1364,833 @@ See `docs/migration/v0.8-to-v0.9.md` and
|
|
|
465
1364
|
keys (`name`, `updated` were missing); removed the documented-but-nonexistent
|
|
466
1365
|
`akm workflow step` alias from `docs/features/workflows.md`.
|
|
467
1366
|
|
|
1367
|
+
## [0.9.0-rc.13] - 2026-07-31
|
|
1368
|
+
|
|
1369
|
+
### Security
|
|
1370
|
+
|
|
1371
|
+
- **`akm update` no longer deletes a previous install directory without
|
|
1372
|
+
confirmation.** When a managed source's resolved content location moves,
|
|
1373
|
+
`update` removed the old directory outright, while `akm remove` had always
|
|
1374
|
+
required `--yes` in non-interactive mode. Only that destructive branch is
|
|
1375
|
+
gated — a normal refresh, where the location does not move, still needs no
|
|
1376
|
+
prompt and no flag, so existing CI invocations are unaffected. Pass
|
|
1377
|
+
`-y`/`--yes` to allow the deletion non-interactively. A cleanup that fails
|
|
1378
|
+
now warns instead of failing silently.
|
|
1379
|
+
|
|
1380
|
+
- **The dangerous-env-key install gate now scans `env/` recursively.** It
|
|
1381
|
+
previously read only the top level, so a stash carrying `LD_PRELOAD` in
|
|
1382
|
+
`env/nested/inner.env` installed cleanly with no warning. Files without a
|
|
1383
|
+
`.env` suffix are still not scanned — no akm code path loads them as
|
|
1384
|
+
environment variables.
|
|
1385
|
+
|
|
1386
|
+
### Added
|
|
1387
|
+
|
|
1388
|
+
- **The `okf` adapter reads OKF v0.2's trust/provenance and lifecycle
|
|
1389
|
+
frontmatter families.** `generated: {by, at}` (with `generated.at` taking
|
|
1390
|
+
precedence over the legacy `timestamp` field, which remains a valid
|
|
1391
|
+
fallback), `verified` (a list, or v0.2's permitted single-mapping
|
|
1392
|
+
shorthand), `sources` (an object list — `resource` required; `id`/`title`/
|
|
1393
|
+
`author`/`usage_count`/`last_modified` optional), `status`
|
|
1394
|
+
(`draft`/`stable`/`deprecated`), and `stale_after` are now parsed leniently
|
|
1395
|
+
from any OKF concept's frontmatter and surfaced on new, namespaced
|
|
1396
|
+
`IndexDocument` fields (`provenance`, `lifecycleStatus`, `staleAfter`,
|
|
1397
|
+
`okfVersion`) that never overload the pre-existing AKM-native `sources`
|
|
1398
|
+
(wiki citation strings), `generation` (consolidation depth), or `quality`
|
|
1399
|
+
fields. As with every other optional OKF field, a missing or malformed
|
|
1400
|
+
value never rejects the document. The `okf` adapter remains consumer-only.
|
|
1401
|
+
|
|
1402
|
+
- **Accepting a proposal now stamps OKF v0.2 provenance onto the written
|
|
1403
|
+
asset's frontmatter**, for AKM-native writes only (never through the `okf`
|
|
1404
|
+
adapter, which stays consumer-only and unaffected by this). `promoteProposal`
|
|
1405
|
+
projects the proposal system's own `source`/`sourceRun`/`gateDecision`/
|
|
1406
|
+
`review` bookkeeping — already tracked in `state.db` but previously never
|
|
1407
|
+
written to disk. `generated: {by, at}` and `verified: [{by, at}]` are written
|
|
1408
|
+
**bare at the top level**, exactly as OKF v0.2 spells them, so a third-party
|
|
1409
|
+
OKF v0.2 reader pointed at an AKM stash sees conformant trust metadata;
|
|
1410
|
+
`sources` alone is namespaced as `provenance: {sources}`, because a bare
|
|
1411
|
+
`sources:` collides with the pre-existing wiki citation-string convention.
|
|
1412
|
+
`generated.by` records whether the content came from an automated pipeline
|
|
1413
|
+
(`akm/<version>`) or a human-initiated source (`human:<id>`); `verified`
|
|
1414
|
+
records whether the promotion itself was an automated gate decision or a
|
|
1415
|
+
direct human accept, and accumulates rather than overwriting across
|
|
1416
|
+
re-promotions; `evidenceSources`, when present, projects as
|
|
1417
|
+
`provenance.sources`. AKM's own adapter rereads what it wrote, so `akm show`
|
|
1418
|
+
surfaces it. Every AKM-native markdown type is stamped, `workflow` included.
|
|
1419
|
+
|
|
1420
|
+
Two consequences worth knowing: promotion re-serializes the whole frontmatter
|
|
1421
|
+
block, so YAML **comments** in a hand-written proposal's frontmatter are not
|
|
1422
|
+
preserved (values and body bytes are); and for a human-attributed promotion
|
|
1423
|
+
with no configured actor id, `by` falls back to `human:<OS username>`, which
|
|
1424
|
+
puts that username into content you may later commit and share.
|
|
1425
|
+
|
|
1426
|
+
- **Internal: a `capturedAtHead` integrity guard**
|
|
1427
|
+
(`scripts/lint-golden-captured-at-head.ts`, wired into `bun run lint`) now
|
|
1428
|
+
checks every golden fixture's recorded `capturedAtHead` commit SHA — it must
|
|
1429
|
+
exist in the local object database and be reachable from at least one known
|
|
1430
|
+
branch. Post-hoc review of this PR found all four new OKF format-family
|
|
1431
|
+
goldens pointed at a commit that existed locally but was unreachable from
|
|
1432
|
+
any ref (a pre-amend duplicate left behind by an interrupted git operation),
|
|
1433
|
+
which would have 404'd on GitHub and vanished under a local `git gc`; a
|
|
1434
|
+
human fixed that one by hand because nothing caught it. This guard is that
|
|
1435
|
+
catch, going forward. In CI's shallow (`fetch-depth: 1`) checkout, a merely
|
|
1436
|
+
*absent* commit object is inconclusive (indistinguishable from "just not
|
|
1437
|
+
fetched") and only warns; a commit that *exists but is unreachable from any
|
|
1438
|
+
branch* — the actual bug class above — still fails there too, since a
|
|
1439
|
+
shallow clone can tell presence apart from absence just fine.
|
|
1440
|
+
|
|
1441
|
+
- **`akm log list --limit <n>`** returns the most recent N events. The flag was
|
|
1442
|
+
documented but silently ignored, and there was no limiting mechanism at all
|
|
1443
|
+
in the read path — the command returned the entire events table regardless of
|
|
1444
|
+
history size. The default remains unlimited.
|
|
1445
|
+
|
|
1446
|
+
- **`--track-usage` (default on) on `akm search`, `akm curate`, and `akm show`.**
|
|
1447
|
+
Pass `--no-track-usage` for a read-only lookup that does not feed usage
|
|
1448
|
+
telemetry or the utility-score ranking signal. Previously a bare `akm search`
|
|
1449
|
+
silently wrote a `utility_scores` row that influenced future ranking, with no
|
|
1450
|
+
disclosure and no way to opt out.
|
|
1451
|
+
|
|
1452
|
+
- **`akm show` returns the canonical `ref` in every shape.** It was present only
|
|
1453
|
+
under `--shape agent`, so a `--shape summary` consumer had to make a second
|
|
1454
|
+
call at a different shape just to learn which asset it was looking at.
|
|
1455
|
+
|
|
1456
|
+
- **`akm info` gained `stashDir`, `defaultBundle`, and `indexStats.byType`.**
|
|
1457
|
+
Answering "which stash is primary" previously required a separate
|
|
1458
|
+
`akm sources list`.
|
|
1459
|
+
|
|
1460
|
+
- **`instruction` is a stash-resident asset type.** It was already in
|
|
1461
|
+
`KNOWN_TYPES` and had a presentation entry, but had no placement spec — so
|
|
1462
|
+
there was nowhere to put one and the indexer never recognized one. `akm bundle create`
|
|
1463
|
+
now creates an `instructions/` directory, `.md` files under it index as
|
|
1464
|
+
`instruction`, and `--type instruction` is accepted and tab-completable
|
|
1465
|
+
everywhere `--type` is. A compile-time assertion now pins
|
|
1466
|
+
`placementTypes() ⊆ KnownType`, so the half-registered state this fixes
|
|
1467
|
+
cannot recur silently.
|
|
1468
|
+
|
|
1469
|
+
- **Schedule tasks from any configured bundle via `--bundle <bundle>`** (#711).
|
|
1470
|
+
`akm task add`, `run`, `sync`, and `history` accept `--bundle` to
|
|
1471
|
+
operate on a non-default bundle instead of only the primary stash. `add`
|
|
1472
|
+
resolves through the normal writable-target rules; `run --bundle X` resolves
|
|
1473
|
+
the task file and relative asset refs from bundle X. A non-default bundle is
|
|
1474
|
+
recorded in the scheduler entry as `--bundle <bundle>`, so scheduled
|
|
1475
|
+
`akm task run` resolves the right bundle. Scheduler ids stay bare and a
|
|
1476
|
+
collision with another bundle is a hard error rather than a silent clobber.
|
|
1477
|
+
|
|
1478
|
+
- **Orphan-GC pass for unresolvable `asset_salience` / `asset_outcome` state
|
|
1479
|
+
rows** (#733). A new improve maintenance pass (`runOrphanStateGcPass`, run
|
|
1480
|
+
next to the existing orphan-proposal purge) stamps `missing_since` on any
|
|
1481
|
+
state row whose ref no longer resolves against `entries.item_ref`, clears
|
|
1482
|
+
the stamp the moment the ref resolves again, and — only when
|
|
1483
|
+
`improve.stateGc.collect` is set to `true` (**default `false`**) — deletes
|
|
1484
|
+
rows whose stamp is older than a fixed 7-day grace window
|
|
1485
|
+
(`STATE_GC_GRACE_MS`). The pass always runs and always reports counts via
|
|
1486
|
+
the new `asset_state_gc` event (`{pending, collected, byTable}`), emitted
|
|
1487
|
+
only when there is something to report, so live data can prove the report
|
|
1488
|
+
clean before `collect` is ever turned on. Additive migration
|
|
1489
|
+
`021-asset-state-missing-since` adds the `missing_since` column to both
|
|
1490
|
+
tables. Deliberately lean by design (Workstream C): no quarantine archive,
|
|
1491
|
+
no circuit breaker, no health-advisory plumbing, no new tables — "ref not
|
|
1492
|
+
present in `entries.item_ref`" is trusted as the authoritative-deletion
|
|
1493
|
+
predicate because the indexer already preserves a source's last-known-good
|
|
1494
|
+
rows when its scan is incomplete, so a temporarily unreachable source never
|
|
1495
|
+
contributes false candidates. `usage_events` is out of scope (already
|
|
1496
|
+
covered by cascade-on-delete plus its own 90-day retention purge).
|
|
1497
|
+
|
|
1498
|
+
### Changed
|
|
1499
|
+
|
|
1500
|
+
- **Workflow execution is consolidated on stable `akm workflow run`.** The
|
|
1501
|
+
public `workflow start`, `next`, and `complete` commands are removed with
|
|
1502
|
+
explicit `UNKNOWN_COMMAND` migration hints; `run <ref|run-id>` now owns
|
|
1503
|
+
creation, active-run continuation, native dispatch, completion, and durable
|
|
1504
|
+
replay. It is no longer gated by `experimental.workflowEngine`; only the
|
|
1505
|
+
experimental `brief`/`report` external-driver protocol retains that opt-in.
|
|
1506
|
+
Workflow parameters move from the opaque `--params '<json>'` bag to exact
|
|
1507
|
+
declared flags (`--version 1.2.3`, repeated array flags, JSON object/array
|
|
1508
|
+
values) coerced through the frozen parameter schemas. New invocation controls
|
|
1509
|
+
add bounded failed-step retries (`--max-retries`) and a whole-run timeout
|
|
1510
|
+
(`--timeout N|Nms|Ns|Nm`); failures, gate rejection, timeout, and signals now
|
|
1511
|
+
produce non-zero process statuses while leaving interrupted work resumable.
|
|
1512
|
+
|
|
1513
|
+
Criteria-bearing gates now require `workflow.judgeEngine`, which may name a
|
|
1514
|
+
configured LLM or agent engine and is frozen into the run. Verification is
|
|
1515
|
+
fail-closed: a missing/failing verifier or malformed verdict rejects instead
|
|
1516
|
+
of silently advancing. Scheduled workflow tasks now execute through the same
|
|
1517
|
+
native orchestrator rather than stopping after run creation. Migration:
|
|
1518
|
+
replace `workflow start/next/complete` loops with `workflow run`, replace
|
|
1519
|
+
`--params` with exact declared flags, and configure `workflow.judgeEngine`
|
|
1520
|
+
before running a workflow with a non-empty `### gate` rubric.
|
|
1521
|
+
|
|
1522
|
+
- **The two workflow authoring formats — markdown documents and YAML
|
|
1523
|
+
orchestration programs — are unified into one format**, per
|
|
1524
|
+
`docs/architecture/specs/workflow-format-unification.md`. A workflow is
|
|
1525
|
+
now always a single markdown asset: the standard AKM frontmatter envelope
|
|
1526
|
+
carries the whole orchestration graph (`params`, `steps` with
|
|
1527
|
+
`unit`/`map`/`route`, `inputs`, `output`, `gate`, `defaults`, `budget`),
|
|
1528
|
+
and the body carries each step's instructions under a bare `## <step-id>`
|
|
1529
|
+
heading, joined to the frontmatter by step id. `.yaml`/`.yml` workflow
|
|
1530
|
+
files, the `# Workflow:` / `## Step:` / `Step ID:` markdown headings, and
|
|
1531
|
+
`akm workflow create <name>.yaml` are all gone; `akm workflow create`
|
|
1532
|
+
always writes the one unified template
|
|
1533
|
+
(`src/assets/workflows/workflow-template.md`).
|
|
1534
|
+
|
|
1535
|
+
**Prose is never interpolated.** The YAML program's `${{ … }}` template
|
|
1536
|
+
language, and the markdown format's decorative — and never
|
|
1537
|
+
substituted — `{{ … }}` moustaches, are both removed. Data reaches a
|
|
1538
|
+
dispatched unit as *attached context* instead: the run's params, its
|
|
1539
|
+
item and index for a map unit, and the artifacts its step's new
|
|
1540
|
+
`inputs:` key declares. Instructions refer to that context in plain
|
|
1541
|
+
language ("clone the repository named by the `repo` parameter") rather
|
|
1542
|
+
than splicing a value into the instruction string. Bare reference
|
|
1543
|
+
strings (two roots, `params.<name>` and `steps.<id>.output…`) now appear
|
|
1544
|
+
only in three frontmatter positions: `map.over`, `route.input`, and
|
|
1545
|
+
`inputs:`.
|
|
1546
|
+
|
|
1547
|
+
**Gate rubrics move to the body.** A step's completion criteria are no
|
|
1548
|
+
longer a frontmatter `gate.criteria` list or a `### Completion Criteria`
|
|
1549
|
+
bullet section — they live under a step's `### gate` sub-heading, the
|
|
1550
|
+
format's one reserved marker, as full prose a judge receives byte-exact.
|
|
1551
|
+
Frontmatter `gate:` now carries only optional `max_loops` configuration.
|
|
1552
|
+
Omitted or empty rubric text skips validation; a non-empty rubric requires
|
|
1553
|
+
the frozen `workflow.judgeEngine`, and unavailable or malformed judges reject
|
|
1554
|
+
the gate.
|
|
1555
|
+
|
|
1556
|
+
This is a **pre-1.0 format change**. The ten example workflows under
|
|
1557
|
+
`scripts/akm-eval/example-stash/workflows/` are rewritten to the unified
|
|
1558
|
+
format in this change; existing user-authored workflow assets must be updated
|
|
1559
|
+
manually before execution.
|
|
1560
|
+
|
|
1561
|
+
- **akm is described as a knowledge toolkit, not a package manager** (R-048).
|
|
1562
|
+
The npm one-liner, the README lede, and the `concepts.md` opener all led with
|
|
1563
|
+
"a package manager for AI agent capabilities", which misstates the product to
|
|
1564
|
+
its distribution channel and sets package-manager expectations for verbs
|
|
1565
|
+
(`update` / `upgrade` / `sync`) that don't mean what a package manager's do.
|
|
1566
|
+
|
|
1567
|
+
- **BREAKING: a command group invoked with no subcommand is now always a usage
|
|
1568
|
+
error, exit 2** (owner ruling 12). The eleven `akm <group>` groups did three
|
|
1569
|
+
different things when invoked bare: `graph`, `config`, `env`, `secret`,
|
|
1570
|
+
`task`, `workflow`, and `proposal` ran an implicit default action and exited
|
|
1571
|
+
0 (bare `akm graph` silently rendered `graph summary`); `registry`, `log`, and
|
|
1572
|
+
`lessons` printed citty's human usage banner to stdout; only `migrate` raised
|
|
1573
|
+
a structured error. All eleven now emit the same
|
|
1574
|
+
`MISSING_REQUIRED_ARGUMENT` envelope on stderr, naming the available
|
|
1575
|
+
subcommands, and exit 2 — matching STABILITY.md's exit-code table (2 =
|
|
1576
|
+
usage) and the exit code already used for unknown commands. Matching exit
|
|
1577
|
+
codes alone was not enough: a script could not parse the failure uniformly
|
|
1578
|
+
while three groups answered on stdout in prose.
|
|
1579
|
+
|
|
1580
|
+
Migration: name the subcommand. `akm graph` → `akm graph summary`,
|
|
1581
|
+
`akm config` → `akm config list`, `akm env` → `akm env list`, `akm secret` →
|
|
1582
|
+
`akm secret list`, `akm task` → `akm task doctor`, `akm workflow` →
|
|
1583
|
+
`akm workflow list --active`, `akm proposal` → `akm proposal list` (which
|
|
1584
|
+
takes the same `--status`/`--queue`/`--ref`/`--type` flags the bare form did).
|
|
1585
|
+
|
|
1586
|
+
- **BREAKING: `akm sync` persists `eventType: "sync"`, not the legacy
|
|
1587
|
+
`"save"`.** The event name now matches the command name. Historical
|
|
1588
|
+
`state.db` rows are left as-is — `akm log` and `akm log tail` treat `"save"`
|
|
1589
|
+
and `"sync"` as synonyms on **read**, so `akm log --type save` keeps
|
|
1590
|
+
returning both old and new rows. Only newly written events use `"sync"`.
|
|
1591
|
+
|
|
1592
|
+
Migration: none for `akm log --type save`. A script matching raw event rows
|
|
1593
|
+
by `eventType === "save"` — reading state.db directly, bypassing `akm log` —
|
|
1594
|
+
should also match `"sync"` to see new syncs.
|
|
1595
|
+
|
|
1596
|
+
- **BREAKING: dropped the dead `installedKitCount` field from the `add`,
|
|
1597
|
+
`remove`, and `update` JSON envelopes.** It was a raw lockfile-entry count
|
|
1598
|
+
that nothing — internal code or test — ever read.
|
|
1599
|
+
|
|
1600
|
+
Migration: a script parsing `.config.installedKitCount` should stop; the
|
|
1601
|
+
field is gone, not renamed. `config.sourceCount` remains and is unaffected.
|
|
1602
|
+
|
|
1603
|
+
- **BREAKING: dropped the dead `graphPath` field from every `akm graph *` JSON
|
|
1604
|
+
envelope** (`summary`, `entities`, `relations`, `export`, `related`, `entity`,
|
|
1605
|
+
`orphans`). It always resolved to the shared state.db path, never a
|
|
1606
|
+
per-graph artifact, and carried nothing `stashPath` did not already provide.
|
|
1607
|
+
|
|
1608
|
+
Migration: a script reading `.graphPath` from any `akm graph` subcommand
|
|
1609
|
+
should stop; `stashPath` remains.
|
|
1610
|
+
|
|
1611
|
+
- **BREAKING: `semanticSearchMode` now defaults to `"off"`.** A bare or
|
|
1612
|
+
headless install (`akm init`, `akm setup --yes`, `akm setup --config`) was
|
|
1613
|
+
silently downloading the ~130 MB local embedding model on its first `akm
|
|
1614
|
+
index`, because the fallback used when the key is absent was `"auto"`. The
|
|
1615
|
+
interactive `akm setup` wizard still pre-selects semantic search **on** — a
|
|
1616
|
+
human is present to decide — and now shows the asset/download warning
|
|
1617
|
+
*before* the prompt rather than after, so the pre-checked box is an informed
|
|
1618
|
+
choice. When a remote `embedding.endpoint` is configured, enabling semantic
|
|
1619
|
+
search downloads nothing.
|
|
1620
|
+
|
|
1621
|
+
Migration: existing saved configs are unaffected — the flip only changes the
|
|
1622
|
+
fallback used when the key is absent. To keep semantic search on for a
|
|
1623
|
+
headless or CI install, set `semanticSearchMode: "auto"` explicitly, or point
|
|
1624
|
+
`embedding.endpoint` at a remote embedder.
|
|
1625
|
+
|
|
1626
|
+
- **BREAKING: `akm workflow run|brief|report` refuse to run until
|
|
1627
|
+
`experimental.workflowEngine` is set** (0.9.0 decision Q-05). The native
|
|
1628
|
+
workflow executor — including fan-out scheduling and worktree isolation —
|
|
1629
|
+
is experimental, and shipping it enabled by default would have made an
|
|
1630
|
+
unreviewed execution engine reachable from a plain `akm workflow run`. The
|
|
1631
|
+
gated surfaces now exit `78` with a `ConfigError` naming the exact key, and
|
|
1632
|
+
`akm task doctor` reports the gate's state. Authoring and linting the unified
|
|
1633
|
+
markdown format, along with every other `akm workflow` subcommand, remain
|
|
1634
|
+
ungated.
|
|
1635
|
+
|
|
1636
|
+
Migration: `akm config set experimental.workflowEngine true`.
|
|
1637
|
+
|
|
1638
|
+
- **BREAKING: the `env:<name>` / `secret:<name>` colon ref spelling is
|
|
1639
|
+
rejected** (0.9.0 decision Q-08). Refs are slash conceptIds only — `env/foo`,
|
|
1640
|
+
`secrets/deploy-key`. The colon form previously resolved as an undocumented
|
|
1641
|
+
alias in some places and fell through as a literal filename in others. It now
|
|
1642
|
+
fails with a usage error naming the slash replacement, rather than silently
|
|
1643
|
+
doing the wrong thing.
|
|
1644
|
+
|
|
1645
|
+
Migration: rewrite `env:<name>` as `env/<name>` and `secret:<name>` as
|
|
1646
|
+
`secrets/<name>`. The error message prints the exact replacement.
|
|
1647
|
+
|
|
1648
|
+
- **`akm improve` is review-first by default; autonomy is opt-in** (0.9.0
|
|
1649
|
+
decision D8). The command stays ON — schedules, reflect/distill proposals, and
|
|
1650
|
+
graph extraction are unchanged — but the lanes that mutate assets *without*
|
|
1651
|
+
review now require `akm config set experimental.improveAutonomy true`:
|
|
1652
|
+
memory-inference writes, the memory-cleanup pass, and triage
|
|
1653
|
+
`applyMode: "promote"` (which downgrades to `queue` rather than disabling
|
|
1654
|
+
triage). Consolidation remains review-oriented and is not gated.
|
|
1655
|
+
|
|
1656
|
+
A gated lane is never a silent no-op: it warns on stderr naming the lane and
|
|
1657
|
+
the key, appends an `improve_skipped` event with `reason: "autonomy_gated"`,
|
|
1658
|
+
and is counted in `akm health`'s improve skip-reason summary.
|
|
1659
|
+
|
|
1660
|
+
Migration: set `experimental.improveAutonomy: true` to restore the previous
|
|
1661
|
+
behavior. `sync.push` is **not** affected — it keeps its `true` default and its
|
|
1662
|
+
own `sync.push: false` / `--no-push` controls. Two other direct writes stay
|
|
1663
|
+
ungated by design: `extract`'s additive session indexing and distill's
|
|
1664
|
+
encoding-salience frontmatter stamp. Because the gate is applied before the LLM
|
|
1665
|
+
preflight, a review-first workspace may now need fewer engines configured than
|
|
1666
|
+
before.
|
|
1667
|
+
|
|
1668
|
+
Also: `akm improve` no longer rejects the global `--format`. It emits an
|
|
1669
|
+
envelope through `output()` (always under `--dry-run`, otherwise under
|
|
1670
|
+
`--json-to-stdout`), so `--format` applies to that envelope; progress output
|
|
1671
|
+
stays on stderr. Previously it exited 2 with `INVALID_FLAG_VALUE`, which made
|
|
1672
|
+
it the one command that rejected a valid global flag.
|
|
1673
|
+
|
|
1674
|
+
- **`akm health --report` replaces the html-only full report** (D7
|
|
1675
|
+
follow-through). The full health report — per-run rows, trend deltas vs the
|
|
1676
|
+
prior window, and the pending proposal queue — is now a **data** flag, not a
|
|
1677
|
+
side effect of asking for html: `akm health --report --format html` renders
|
|
1678
|
+
the rich report, and the identical dataset comes back under `--format json`
|
|
1679
|
+
(previously that data was reachable only as html). The registered md/html
|
|
1680
|
+
renderers fire on the shape of the result, and `akm health` no longer reads
|
|
1681
|
+
`--format` at all.
|
|
1682
|
+
|
|
1683
|
+
Migration: `akm health --format html` → `akm health --report --format html`
|
|
1684
|
+
(the bare form now renders the plain check generically); the html-only
|
|
1685
|
+
`--compare` flag is removed — use `--window-compare`, which with `--report`
|
|
1686
|
+
defaults to the `--since` window so trend deltas stay like-for-like.
|
|
1687
|
+
|
|
1688
|
+
- **Global output flags parse correctly next to positionals.** citty parses
|
|
1689
|
+
each command level against only its own declared args, so a root-declared
|
|
1690
|
+
global flag was unknown at the leaf and its space-separated value fell
|
|
1691
|
+
through as a positional — `akm sync --format json` synced a bundle named
|
|
1692
|
+
"json", and `akm env unset env:x KEY --format json` tried to unset a key
|
|
1693
|
+
named "json". The global output flags (`--format`, `--detail`, `--shape`,
|
|
1694
|
+
`--output`) are now declared on every leaf command so their values are
|
|
1695
|
+
consumed by the parser; the two bespoke argv-inspection workarounds this
|
|
1696
|
+
replaces are deleted. Three more non-exempt commands (`akm health`, `akm
|
|
1697
|
+
index`, `akm lint`) now declare these flags too, purely for `--help`
|
|
1698
|
+
visibility — all three already parsed `--format`/`--detail`/`--shape`/
|
|
1699
|
+
`--output` correctly, since none of them has a positional a stray value
|
|
1700
|
+
could fall into.
|
|
1701
|
+
|
|
1702
|
+
- **BREAKING: unknown commands and missing required arguments now exit `2`
|
|
1703
|
+
(usage), not `1`.** citty's own command-dispatch wrapper unconditionally
|
|
1704
|
+
called `process.exit(1)` for any error it raised before a command's own
|
|
1705
|
+
body ever ran — `akm totally-bogus` (unknown command), bare `akm log` /
|
|
1706
|
+
`akm lessons` (a subcommand group invoked with no subcommand), and a
|
|
1707
|
+
command missing a required positional (e.g. bare `akm import`) all exited
|
|
1708
|
+
`1`, contradicting the documented exit-code table (`1` = general error /
|
|
1709
|
+
not found, `2` = usage / bad input). The CLI now drives command dispatch
|
|
1710
|
+
directly instead of going through that wrapper, so it can reclassify this
|
|
1711
|
+
one error family as `2` while leaving `--help`, `--version`, and every
|
|
1712
|
+
other exit code unchanged.
|
|
1713
|
+
|
|
1714
|
+
Migration: a script that treated exit `1` as "something went wrong" for a
|
|
1715
|
+
mistyped command or missing argument should check for `2` instead (or
|
|
1716
|
+
keep treating any non-zero exit as failure, which was already correct).
|
|
1717
|
+
|
|
1718
|
+
- **BREAKING: `akm completions --shell <unsupported>` now exits `2` with the
|
|
1719
|
+
standard JSON error envelope, not `1` with a raw stack trace.**
|
|
1720
|
+
`completions` stays format-exempt (its own output is shell-script source,
|
|
1721
|
+
not a result envelope — see STABILITY.md), but its body is now wrapped in
|
|
1722
|
+
the same error-classification path every other command uses.
|
|
1723
|
+
|
|
1724
|
+
Migration: a script parsing this failure should now expect
|
|
1725
|
+
`{"ok":false,"error":"...","code":"INVALID_FLAG_VALUE","hint":...}` on
|
|
1726
|
+
stderr and exit code `2` in place of a stack trace and exit code `1`.
|
|
1727
|
+
|
|
1728
|
+
- **BREAKING: `akm index --dry-run` without `--clean` now exits `2` instead
|
|
1729
|
+
of running a real index.** The flag only ever gated the `--clean`
|
|
1730
|
+
stale-entry removal pass — every other phase (walk, LLM enrichment,
|
|
1731
|
+
embeddings, FTS, the adapter-detection config write) ran for real
|
|
1732
|
+
regardless, so `akm index --dry-run` alone silently performed a full index
|
|
1733
|
+
despite its name. The combination is now rejected with the standard usage
|
|
1734
|
+
envelope instead of quietly doing something other than what "dry run"
|
|
1735
|
+
promised.
|
|
1736
|
+
|
|
1737
|
+
Migration: a script or cron invoking bare `akm index --dry-run` was
|
|
1738
|
+
already getting a real index, so nothing there needs to change in effect —
|
|
1739
|
+
but it will now fail loudly instead. Pass `akm index --clean --dry-run` to
|
|
1740
|
+
preview the stale-entry removal pass, or `akm index --clean` to apply it;
|
|
1741
|
+
drop `--dry-run` entirely to keep running a plain real index.
|
|
1742
|
+
|
|
1743
|
+
- **BREAKING: a corrupt or unparseable `akm.lock` now makes lockfile WRITES
|
|
1744
|
+
throw, instead of silently destroying every entry.** The previous lenient
|
|
1745
|
+
reader returned `[]` on unparseable JSON; a write path that upserted a
|
|
1746
|
+
single entry onto that `[]` then overwrote the file, permanently deleting
|
|
1747
|
+
every other tracked bundle's lock entry. Install/update/remove write paths
|
|
1748
|
+
now use a strict reader that throws on the same corruption instead of
|
|
1749
|
+
reaching the destructive overwrite.
|
|
1750
|
+
|
|
1751
|
+
Migration: if a write now fails with a lockfile-parse error, `akm.lock` is
|
|
1752
|
+
genuinely corrupt — inspect and repair it by hand, or restore it from a
|
|
1753
|
+
backup (e.g. git history), before retrying the write. Reads elsewhere are
|
|
1754
|
+
unaffected; the lenient read contract is unchanged.
|
|
1755
|
+
|
|
1756
|
+
- **BREAKING: `AKM_NPM_REGISTRY` now redirects npm package METADATA lookups,
|
|
1757
|
+
not just the trusted-tarball allowlist.** Previously the override only
|
|
1758
|
+
widened which tarball hosts were trusted for download while metadata
|
|
1759
|
+
queries stayed hardcoded to `registry.npmjs.org`, so a configured private
|
|
1760
|
+
mirror was never actually consulted for package info — the error hint that
|
|
1761
|
+
points users at this variable was false. The override now also replaces
|
|
1762
|
+
the metadata registry base, matching how a private npm registry is meant
|
|
1763
|
+
to work (like npm's own `--registry` flag: wholesale replacement, not a
|
|
1764
|
+
merge with the public registry).
|
|
1765
|
+
|
|
1766
|
+
Migration: an operator who set `AKM_NPM_REGISTRY` expecting only tarball
|
|
1767
|
+
downloads to be redirected, with metadata still served from the public
|
|
1768
|
+
registry, should confirm the mirror actually serves equivalent package
|
|
1769
|
+
metadata — `akm add`/`akm update` for npm-sourced bundles now resolve
|
|
1770
|
+
entirely against the configured mirror when it is set.
|
|
1771
|
+
|
|
1772
|
+
- **`akm remember --show-similar` and `akm migrate apply --dry-run` are the
|
|
1773
|
+
documented, canonical spellings** (previously `--showSimilar` /
|
|
1774
|
+
`--dryRun`), matching every other multi-word flag in the CLI. Not a
|
|
1775
|
+
breaking change: citty registers both the camelCase and kebab-case
|
|
1776
|
+
spelling of any declared flag name automatically, so `--showSimilar` /
|
|
1777
|
+
`--dryRun` keep working — they're now explicit, documented aliases instead
|
|
1778
|
+
of an undocumented accident.
|
|
1779
|
+
|
|
1780
|
+
- **`--detail` and `--shape` help text is scoped honestly.** The per-command
|
|
1781
|
+
`--detail` description now names `info`, `list`, and `remember` as the
|
|
1782
|
+
commands where it has no effect (verified byte-identical output at every
|
|
1783
|
+
level — `akm show` is not one of these; it has three distinct
|
|
1784
|
+
brief/normal/full payloads). `--shape`'s per-command help now repeats the
|
|
1785
|
+
"`summary` is only valid on `akm show`" caveat the root help already
|
|
1786
|
+
documented.
|
|
1787
|
+
|
|
1788
|
+
- **All six `--format` values work on every command** (0.9.0 decision D7).
|
|
1789
|
+
`json|jsonl|yaml|text|md|html` are now universal. Previously there were three
|
|
1790
|
+
inconsistent behaviours: `md` silently emitted the JSON envelope everywhere
|
|
1791
|
+
except `akm health`, `html` was rejected with exit 2 everywhere except
|
|
1792
|
+
`akm health`, and `akm health` reached neither because it intercepted the
|
|
1793
|
+
format itself. Rendering is now registry-driven — a command may register a
|
|
1794
|
+
renderer for a document format, and anything unregistered falls back to a real
|
|
1795
|
+
rendering of its own envelope (headings, tables for arrays of uniform objects,
|
|
1796
|
+
lists otherwise). `akm health` keeps its per-run/window-compare tables and its
|
|
1797
|
+
full HTML report by registering them; the output is unchanged.
|
|
1798
|
+
|
|
1799
|
+
Migration: none required for `json|jsonl|yaml|text`. `--format md` on a
|
|
1800
|
+
non-health command previously returned JSON and now returns Markdown; a script
|
|
1801
|
+
that parsed that JSON should ask for `--format json` explicitly. `--format
|
|
1802
|
+
html` previously exited 2 on non-health commands and now succeeds.
|
|
1803
|
+
|
|
1804
|
+
Also: `akm graph export --format` is **removed** — it declared `--format`
|
|
1805
|
+
locally as well as globally (one token, two parsers). The artifact payload
|
|
1806
|
+
now follows the `--out` extension (`--out g.jsonl` writes JSONL, anything
|
|
1807
|
+
else JSON); the global flag only renders the command's own envelope. A dead
|
|
1808
|
+
local `--format` declaration on `akm history` was removed too (it was never
|
|
1809
|
+
read). Commands
|
|
1810
|
+
whose output is not an envelope (`completions`, `setup`, `env run`,
|
|
1811
|
+
`secret run`, `agent`, `workflow template`, `help migrate`) are declared
|
|
1812
|
+
format-exempt in `src/output/format-exempt.ts` and now warn when given
|
|
1813
|
+
`--format` instead of ignoring it silently. `output.format` in config accepts
|
|
1814
|
+
all six values.
|
|
1815
|
+
|
|
1816
|
+
- **Subtree browse is a conceptId prefix, not `<type>:`** (0.9.0 decision D4).
|
|
1817
|
+
`akm search` enumerates on `memories/`, `memories/projecta/`, `bundle//`, and
|
|
1818
|
+
`bundle//skills/`; a trailing `/` is still required. The prefix now matches the
|
|
1819
|
+
**conceptId** rather than the item name, so a ref copied out of search output
|
|
1820
|
+
can be truncated to a prefix and pasted straight back in — previously that
|
|
1821
|
+
round-trip degraded silently into a keyword search. Enumeration no longer
|
|
1822
|
+
validates against the `akm` adapter's placement types, so items from every
|
|
1823
|
+
adapter browse the same way, and `bundle//` lists a whole bundle (the
|
|
1824
|
+
replacement for the removed `akm bundle items`).
|
|
1825
|
+
|
|
1826
|
+
Migration: `akm search "memory:"` → `akm search "memories/"`;
|
|
1827
|
+
`akm search "memory:projectA/"` → `akm search "memories/projectA/"`;
|
|
1828
|
+
`akm search "session:"` → `akm search "sessions/"`. The retired spelling is
|
|
1829
|
+
now an ordinary keyword search; when it returns nothing, the tip names the
|
|
1830
|
+
conceptId spelling that replaces it. `scripts/lint-shipped-assets.ts` no
|
|
1831
|
+
longer exempts the old spelling, so it is an offense in agent-facing assets.
|
|
1832
|
+
|
|
1833
|
+
- **`akm task sync [--bundle <bundle>]` reconciles a single bundle.** Sync now
|
|
1834
|
+
attributes each installed scheduler entry to its bundle (parsed from the
|
|
1835
|
+
`--bundle` token; absent ⇒ primary) and reconciles only the entries for the
|
|
1836
|
+
bundle being synced. A plain (primary) sync never installs from, updates, or
|
|
1837
|
+
removes another bundle's entries, and sync never scans all bundles — task
|
|
1838
|
+
activation stays explicit (`add --bundle` or `sync --bundle`), so registering a bundle
|
|
1839
|
+
still never activates code. When the target is the default bundle (or omitted),
|
|
1840
|
+
installed scheduler entries are byte-identical to before, so upgrading shows no
|
|
1841
|
+
spurious drift.
|
|
1842
|
+
|
|
1843
|
+
- **The R2 salience ranking boost no longer applies to default `search`/`curate`
|
|
1844
|
+
ranking** (#692). `asset_salience.rank_score` (an encoding + outcome +
|
|
1845
|
+
retrieval projection, recomputed every `improve` run) previously composed
|
|
1846
|
+
into every default search as a bounded multiplicative boost
|
|
1847
|
+
(`salience-ranking`, ×[1.0–1.2]), loaded best-effort from `state.db` on the
|
|
1848
|
+
hot path. On live data it measured as noise (max observed multiplier
|
|
1849
|
+
×1.071, mean ×1.016): the boost was retrieval-dominated with no source
|
|
1850
|
+
filter — double-counting the same `usage_events` the utility-score
|
|
1851
|
+
contributor already reinforces — warm-started non-zero with no outcome
|
|
1852
|
+
evidence, and had zero pack coverage, so it could only ever favor
|
|
1853
|
+
self-generated personal assets over an equally-relevant pack asset.
|
|
1854
|
+
Removing the default `state.db` load also fixes a confirmed hot-path
|
|
1855
|
+
defect: whenever `state.db` already existed, every default search
|
|
1856
|
+
synchronously waited on the maintenance-activity barrier before ranking
|
|
1857
|
+
could even start — up to a 5-second stall on a blocking wait loop, plus a
|
|
1858
|
+
lock-file create, before the load's own 250ms SQLite `busy_timeout` ever
|
|
1859
|
+
applied. No config gate was added: a key for a term being removed would be
|
|
1860
|
+
dead surface for the upcoming 1.0 contract freeze to carry forever.
|
|
1861
|
+
`rank_score` itself, and everything `improve` computes and does with it
|
|
1862
|
+
internally, are unchanged — only its promotion into user-facing ranking is
|
|
1863
|
+
removed. The contributor stays in the codebase (unwired) for a future
|
|
1864
|
+
gated, outcome-backed experiment.
|
|
1865
|
+
|
|
1866
|
+
- **Internal: `asset_salience` / `asset_outcome` state.db access moved behind
|
|
1867
|
+
`src/storage/repositories/{salience,outcome}-repository.ts`** (#672 part 2).
|
|
1868
|
+
Mirrors the existing state.db repository precedents
|
|
1869
|
+
(`proposals-repository.ts`, `improve-runs-repository.ts`,
|
|
1870
|
+
`events-repository.ts`): the raw SQL, row-mapping, and the #644
|
|
1871
|
+
encoding-provenance CASE guards are extracted verbatim, only relocated —
|
|
1872
|
+
`commands/improve/salience.ts` and `outcome-loop.ts` re-export the moved
|
|
1873
|
+
functions, so no importer or test churns. A new `state-table-sql` rule in
|
|
1874
|
+
`scripts/lint-repository-sql.ts` now fails the build if raw
|
|
1875
|
+
`asset_salience`/`asset_outcome` SQL reappears outside the repository
|
|
1876
|
+
directory (or `core/state/migrations.ts`). Not a user-visible behavior
|
|
1877
|
+
change: `rank_score`, `outcome_score`, and everything `improve`/`health`
|
|
1878
|
+
compute from them are identical.
|
|
1879
|
+
|
|
1880
|
+
### Fixed
|
|
1881
|
+
|
|
1882
|
+
- **The compiled standalone binary can run `akm migrate`.** Release binaries
|
|
1883
|
+
compiled only `src/cli.ts`, and the migrator was resolved as a sibling file
|
|
1884
|
+
and spawned — neither candidate exists inside a compiled executable, so the
|
|
1885
|
+
documented `./akm-0.9 migrate status/apply` upgrade path always failed with
|
|
1886
|
+
`FILE_NOT_FOUND`. Standalone builds now compile `scripts/akm-standalone.ts`,
|
|
1887
|
+
a wrapper that embeds both the CLI and the migrator (src never imports
|
|
1888
|
+
scripts/ — the dist build's tsc forbids it); `akm migrate` re-execs the
|
|
1889
|
+
binary with an `AKM_MIGRATE_ENTRY` marker the wrapper dispatches on. The
|
|
1890
|
+
repo and npm layouts keep the subprocess path.
|
|
1891
|
+
|
|
1892
|
+
- **Quarantined migration rows are retained in full, not reduced to a count.**
|
|
1893
|
+
When the 0.8→0.9 cutover met a durable ref it could not map, it recorded
|
|
1894
|
+
surface/ref/count in `legacy_state` and then deleted the rows — destroying
|
|
1895
|
+
proposal payloads, event and task history, fingerprints, and canary anchors,
|
|
1896
|
+
contrary to the migration guide's "quarantined, not dropped". Complete rows
|
|
1897
|
+
are now preserved as JSON in `legacy_state_rows` before leaving the live
|
|
1898
|
+
tables.
|
|
1899
|
+
|
|
1900
|
+
- **A failed content migration fails the apply instead of reporting success.**
|
|
1901
|
+
Root discovery, sidecar folding, or the legacy-proposal import throwing was
|
|
1902
|
+
swallowed and logged; the apply then advanced and cleared its journal, and —
|
|
1903
|
+
because 0.9 removed the live `.stash.json` and filesystem-proposal readers —
|
|
1904
|
+
the affected metadata and pending proposals became permanently inaccessible
|
|
1905
|
+
behind an apparently successful upgrade. The step now fails the apply with
|
|
1906
|
+
the journal intact; the committed cutover is untouched and the next apply
|
|
1907
|
+
retries.
|
|
1908
|
+
|
|
1909
|
+
- **Sidecar provenance survives the fold.** Folding a `.stash.json` into
|
|
1910
|
+
frontmatter dropped `xrefs` and `sources` entirely and mapped legacy
|
|
1911
|
+
`sourceRefs` to a `source_refs` key that could never fire (the validator
|
|
1912
|
+
stopped copying the field) and that 0.9 never reads — then deleted the only
|
|
1913
|
+
copy. `xrefs`/`sources` now fold through, and legacy `sourceRefs` merge into
|
|
1914
|
+
`xrefs`.
|
|
1915
|
+
|
|
1916
|
+
- **A reserved-filename rename re-keys durable state.** The D-R6 rename of a
|
|
1917
|
+
mis-named `index.md`/`log.md` concept ran after the cutover had keyed usage,
|
|
1918
|
+
salience, and proposal rows to the old conceptId, stranding that learned
|
|
1919
|
+
state. The rename now feeds the same re-key engine the cutover uses, with
|
|
1920
|
+
the pairs persisted before re-keying so a crash between the two stays
|
|
1921
|
+
retryable.
|
|
1922
|
+
|
|
1923
|
+
- **v1 tasks in a read-only bundle are surfaced with a remedy instead of being
|
|
1924
|
+
silently skipped.** The 0.9 runtime removed the v1 task parser, so silently
|
|
1925
|
+
skipping a `writable: false` bundle left tasks that would start failing after
|
|
1926
|
+
an upgrade that reported current. The preflight now warns per bundle and
|
|
1927
|
+
lists the stranded files in the plan (`readOnlyLegacyTasks`). It does not
|
|
1928
|
+
block the apply: the migration deliberately never rewrites a read-only
|
|
1929
|
+
bundle, and the fix for a lock-materialized git/npm bundle belongs upstream.
|
|
1930
|
+
|
|
1931
|
+
- **Lock resolution metadata survives migration.** Merging the migrator's
|
|
1932
|
+
sparse lock entries replaced whole rows by id, discarding
|
|
1933
|
+
`resolvedVersion`/`resolvedRevision`/`integrity`/`installedAt` recorded by a
|
|
1934
|
+
real install. Merge now preserves existing fields the incoming entry does
|
|
1935
|
+
not define.
|
|
1936
|
+
|
|
1937
|
+
- **Migrating a pre-0.9 config no longer silently changes source policy.**
|
|
1938
|
+
Three settings were dropped by the config-shape migration: an explicit
|
|
1939
|
+
`writable: false` (an omitted filesystem `writable` reads as `true` in the
|
|
1940
|
+
new shape, so a source the user deliberately protected became writable), an
|
|
1941
|
+
explicit `enabled: false` (resuming refreshes and indexing for content the
|
|
1942
|
+
operator had turned off), and a website source's `maxDepth` (silently
|
|
1943
|
+
resetting crawl depth). All three now round-trip to the runtime source entry;
|
|
1944
|
+
`bundles.<id>.enabled` is a supported key.
|
|
1945
|
+
|
|
1946
|
+
- **`akm mv` refuses a bundle marked `writable: false`.** It renamed the file
|
|
1947
|
+
and rewrote citers anyway, because its preflight checked adapter
|
|
1948
|
+
compatibility rather than writability — every other write command already
|
|
1949
|
+
refused.
|
|
1950
|
+
|
|
1951
|
+
- **Memory belief edges written by `--supersedes` are no longer ignored.**
|
|
1952
|
+
`writeSupersededEdge` persists a fully-qualified conceptId, but the belief
|
|
1953
|
+
analyzer accepted only the internal `memory:<name>` spelling, so every edge
|
|
1954
|
+
from `akm remember --supersedes` / `akm import --supersedes` was dropped and
|
|
1955
|
+
a superseded memory read back as active.
|
|
1956
|
+
|
|
1957
|
+
- **`akm env run <ref> -- <cmd> --help` runs the command.** The builtin
|
|
1958
|
+
help-flag scan read the child tail after `--` and printed akm's own usage
|
|
1959
|
+
instead.
|
|
1960
|
+
|
|
1961
|
+
- **`akm mv` works under an `AKM_STASH_DIR` override again.** A valid override
|
|
1962
|
+
not owned by a configured bundle failed with `No configured bundle owns move
|
|
1963
|
+
source`.
|
|
1964
|
+
|
|
1965
|
+
- **An unexpected internal error exits 70 with the JSON failure envelope.** The
|
|
1966
|
+
residual dispatch boundary exited 1 with an unstructured message, so
|
|
1967
|
+
automation could not tell an internal defect from an ordinary failure.
|
|
1968
|
+
|
|
1969
|
+
- **Concurrent `akm config set` processes no longer give up prematurely.** The
|
|
1970
|
+
contended-lock wait budget was 500ms total, so several concurrent writers on
|
|
1971
|
+
a loaded machine could exhaust it and fail with "Timed out waiting for config
|
|
1972
|
+
lock" against a healthy but busy lock. Abandoned locks are still reclaimed by
|
|
1973
|
+
the stale probe, which this budget does not gate.
|
|
1974
|
+
|
|
1975
|
+
- **Config keys named in indexer output and comments now exist.** Four sites
|
|
1976
|
+
pointed at a top-level `llm.*` namespace that the config schema has no such
|
|
1977
|
+
key for — including the user-facing "Increase llm.timeoutMs" warning on an
|
|
1978
|
+
exceeded enrichment budget. The enrichment budget lives at
|
|
1979
|
+
`index.enrichment.timeoutMs` (or `index.defaults.timeoutMs`). Indexing
|
|
1980
|
+
concurrency is auto-derived (2 remote / 1 local) and currently has no config
|
|
1981
|
+
override on that path: `engines.<name>.concurrency` is a valid schema field
|
|
1982
|
+
but the engine resolver does not forward it (documented in
|
|
1983
|
+
`docs/architecture/internals/indexing.md`).
|
|
1984
|
+
|
|
1985
|
+
- **The bundle-identity-drift warning stops naming a command that doesn't
|
|
1986
|
+
exist.** It told users to "rekey it atomically via the bundle-rename
|
|
1987
|
+
command"; 0.9.0 ships no such command. It now gives the two remedies that
|
|
1988
|
+
work: restore the previous bundle id in `config.json`, or keep the new id and
|
|
1989
|
+
`akm index --full` to re-mint, accepting the loss of learned state keyed to
|
|
1990
|
+
the old id.
|
|
1991
|
+
|
|
1992
|
+
- **The scaffolded `organization.md` convention no longer contradicts `akm
|
|
1993
|
+
mv`.** It told authoring agents "there is no command that preserves an
|
|
1994
|
+
asset's identity or learned state" across a rename and showed a raw `mv`.
|
|
1995
|
+
`akm mv` does exactly that — it rewrites inbound refs and re-keys the index
|
|
1996
|
+
row, usage history, and state.db salience/outcome rows. The convention now
|
|
1997
|
+
points at it, flagged Experimental.
|
|
1998
|
+
|
|
1999
|
+
- **`setup.taskSchedules` is no longer documented.** The key was removed from
|
|
2000
|
+
the schema in 0.9.0 (nothing ever read or wrote it), but
|
|
2001
|
+
`docs/reference/configuration.md` still described its two sub-keys.
|
|
2002
|
+
|
|
2003
|
+
- **A freshly scaffolded stash passes its own `akm lint`.** All 12 shipped
|
|
2004
|
+
`facts/conventions/**` convention templates carry frontmatter but none
|
|
2005
|
+
carried an `updated` field, so the first `akm lint` after `akm init` flagged
|
|
2006
|
+
12 `missing-updated` issues on files the user never wrote. The templates now
|
|
2007
|
+
ship the field, and a regression test lints a freshly scaffolded stash and
|
|
2008
|
+
requires nothing flagged.
|
|
2009
|
+
|
|
2010
|
+
- **`akm show akm//meta` is the documented spelling for the primary stash.**
|
|
2011
|
+
`docs/reference/cli.md` and `docs/guides/concepts.md` showed
|
|
2012
|
+
`akm show local//meta`, which errors with `ASSET_NOT_FOUND` — `local//` is no
|
|
2013
|
+
longer a scoping prefix, so it reads as a bundle named `local`.
|
|
2014
|
+
|
|
2015
|
+
- **`akm sync` emits `shape: "sync"`.** The envelope kept the `"save"` shape
|
|
2016
|
+
from the command's pre-rename name even after the persisted `eventType` was
|
|
2017
|
+
renamed. Unlike the event log, the shape is per-invocation and never
|
|
2018
|
+
persisted, so it needs no read-side synonym.
|
|
2019
|
+
|
|
2020
|
+
- **`akm add <pkg> --provider npm` adds an npm source instead of a broken
|
|
2021
|
+
filesystem bundle.** `--provider` was only read inside the remote-URL branch,
|
|
2022
|
+
so any non-URL target fell through to the filesystem path with the flag
|
|
2023
|
+
ignored, producing a bundle pointed at `<cwd>/<pkg>`. A URL target with
|
|
2024
|
+
`--provider npm` is now rejected at add time rather than storing the URL as a
|
|
2025
|
+
package spec and failing much later at first sync.
|
|
2026
|
+
|
|
2027
|
+
- **`akm add --provider` no longer prints `Installed undefined`.** Two
|
|
2028
|
+
incompatible result shapes reached one text formatter; each is now rendered
|
|
2029
|
+
honestly, including whether a follow-up `akm update` or `akm index` is needed.
|
|
2030
|
+
|
|
2031
|
+
- **`akm update --all` accounts for every configured source.** It previously
|
|
2032
|
+
considered only registry-managed installs and reported `nothing to update`
|
|
2033
|
+
for a stash full of plain sources — nothing was updated because nothing was
|
|
2034
|
+
looked at. Plain git and npm sources are now synced (npm is promoted to a
|
|
2035
|
+
lock-backed install on first sync) and website/filesystem sources are
|
|
2036
|
+
reported through a new `skipped` field with the reason. A successful update of
|
|
2037
|
+
a plain source no longer renders as `nothing to update` either.
|
|
2038
|
+
|
|
2039
|
+
- **`akm search` with no query browses**, as `--help` has always documented,
|
|
2040
|
+
instead of exiting 2.
|
|
2041
|
+
|
|
2042
|
+
- **`akm curate --type <t>` curates within the type instead of bypassing
|
|
2043
|
+
curation.** The filter skipped ranking, intent nudges, the score floor, and
|
|
2044
|
+
family collapse entirely — and could return a hit of the *wrong* type while
|
|
2045
|
+
dropping a higher-scoring correct one.
|
|
2046
|
+
|
|
2047
|
+
- **`akm curate` respects `--limit` for registry hits**, which were capped at a
|
|
2048
|
+
hard-coded 2 regardless.
|
|
2049
|
+
|
|
2050
|
+
- **`akm search --no-project-context` works.** citty strips a leading `--no-`
|
|
2051
|
+
before consulting declared args, so a flag *declared* as `no-project-context`
|
|
2052
|
+
could never be set — the ranking boost was identical with and without it. The
|
|
2053
|
+
flag users type is unchanged.
|
|
2054
|
+
|
|
2055
|
+
- **`akm env run`, `akm secret run`, `akm migrate`, `akm agent`, `akm proposal new`,
|
|
2056
|
+
`akm task run`, and `akm improve` no longer skip cleanup on exit.** They
|
|
2057
|
+
called `process.exit()` directly — in two cases even on success — bypassing
|
|
2058
|
+
teardown of spawned subprocesses. Exit codes, including forwarded non-zero
|
|
2059
|
+
child codes, are unchanged.
|
|
2060
|
+
|
|
2061
|
+
- **The `blocked` semantic-search warning names the cause.** It emitted one
|
|
2062
|
+
fixed string for every failure and discarded the status ledger's reason, so
|
|
2063
|
+
"no embedding provider configured" and "the configured endpoint is failing"
|
|
2064
|
+
read identically.
|
|
2065
|
+
|
|
2066
|
+
- **Shell completion for `--source` no longer suggests `stash|registry|both`
|
|
2067
|
+
on commands where that enum doesn't apply.** `--source` means a closed
|
|
2068
|
+
`stash|registry|both` enum on `akm search`/`akm curate`, but a free-form
|
|
2069
|
+
stash name/path on every `akm graph` subcommand and a free-form URL/ref/
|
|
2070
|
+
path on `akm remember`. The generated completion script keyed its value
|
|
2071
|
+
list by flag name only, so the search/curate enum leaked onto `akm graph
|
|
2072
|
+
--source <TAB>` and `akm remember --source <TAB>`. Value completion is now
|
|
2073
|
+
scoped per command path; commands without a fixed value set get no
|
|
2074
|
+
suggestion instead of the wrong one.
|
|
2075
|
+
|
|
2076
|
+
- **`akm setup --config <file>` / `--from <file>` no longer silently drops
|
|
2077
|
+
six valid config keys** (`index`, `search`, `feedback`,
|
|
2078
|
+
`archiveRetentionDays`, `workflow`, `experimental`). The allowlist was a
|
|
2079
|
+
hand-copied set that had drifted out of sync with the config schema; a
|
|
2080
|
+
user handing setup a config containing any of these keys got a different,
|
|
2081
|
+
silently truncated config written back, with only a warning and exit `0`.
|
|
2082
|
+
The allowlist is now derived from the schema's own key list so it cannot
|
|
2083
|
+
drift again. Keys that remain genuinely retired (`profiles`, `llm`,
|
|
2084
|
+
`agent`, `features`, `stashes`, `bindings`, `writable`) still warn-and-drop
|
|
2085
|
+
as before.
|
|
2086
|
+
|
|
2087
|
+
Note: a config that previously relied on one of these six keys being
|
|
2088
|
+
ignored (because the drop was silent) will now have it applied — re-check
|
|
2089
|
+
`--config`/`--from` inputs if you were unknowingly depending on that gap.
|
|
2090
|
+
|
|
2091
|
+
- **`akm index` no longer persists adapter auto-detection to `config.json`
|
|
2092
|
+
with zero disclosure.** Detecting and writing a bundle component's adapter
|
|
2093
|
+
(`bundles.<id>.components.<component>.adapter`) previously happened
|
|
2094
|
+
silently on every index run. It is now reported in the result envelope as
|
|
2095
|
+
an additive `configUpdated.detectedAdapters` map and on stderr, and only
|
|
2096
|
+
when a write actually happened.
|
|
2097
|
+
|
|
2098
|
+
- **`akm add owner/repo` now resolves as GitHub shorthand instead of failing
|
|
2099
|
+
with "Local path not found".** Any ref containing a `/` was treated as an
|
|
2100
|
+
explicit local path, so the local-ref resolver threw before the
|
|
2101
|
+
GitHub-shorthand fallback ever ran, making the advertised `owner/repo` form
|
|
2102
|
+
unreachable. A bare two-segment `owner/repo` (or `owner/repo#ref`) now
|
|
2103
|
+
falls through to the registry resolver when no such directory exists on
|
|
2104
|
+
disk; `./`, `../`, absolute, and three-or-more-segment paths still resolve
|
|
2105
|
+
as explicit local paths exactly as before.
|
|
2106
|
+
|
|
2107
|
+
- **Internal output-shape command keys renamed `events-list`/`events-tail` →
|
|
2108
|
+
`log-list`/`log-tail`**, matching the `akm log` command they back (the
|
|
2109
|
+
command group used to be `akm events`, removed in 0.9.0). Internal-only:
|
|
2110
|
+
the shape name is a registry lookup key that never reaches the wire (no
|
|
2111
|
+
output field, no schema change), so this is not a user-visible behavior
|
|
2112
|
+
change and carries no `schemaVersion` bump. The documented `[events-tail]`
|
|
2113
|
+
stderr trailer text is deliberately left as-is pending a separate ruling.
|
|
2114
|
+
|
|
2115
|
+
### Removed
|
|
2116
|
+
|
|
2117
|
+
- **BREAKING: `akm upgrade --skip-checksum` is removed.** STABILITY.md has
|
|
2118
|
+
always said checksum verification is not optional and that the recovery hatch
|
|
2119
|
+
is an environment variable — but the flag shipped anyway, tab-completable,
|
|
2120
|
+
while the documented variable existed nowhere in the source. The code now
|
|
2121
|
+
matches the spec: set `AKM_UPGRADE_SKIP_CHECKSUM=1` if you must bypass a
|
|
2122
|
+
genuinely broken `checksums.txt`. It is deliberately undiscoverable.
|
|
2123
|
+
|
|
2124
|
+
- **BREAKING: `akm config enable|disable` is removed.** It was a hard-coded
|
|
2125
|
+
toggle for one target, the skills.sh registry, and the bare `akm enable` /
|
|
2126
|
+
`akm disable` aliases were already removed in 0.9.0. Use
|
|
2127
|
+
`akm registry add|remove`.
|
|
2128
|
+
|
|
2129
|
+
- **BREAKING: `akm mv` is removed.** No alias, no stub — `akm mv …` fails with
|
|
2130
|
+
the standard unknown-command error. It claimed to preserve identity across a
|
|
2131
|
+
rename, but its inbound-ref rewrite matched bare conceptIds rather than the
|
|
2132
|
+
anchored `bundle//conceptId` prose form, so it could rewrite ordinary prose
|
|
2133
|
+
while leaving real refs dangling. Renames are delete + create per
|
|
2134
|
+
`STABILITY.md`: move the file, `akm index`, `akm lint`. The one capability
|
|
2135
|
+
nothing else covered — carrying an asset's earned signal across the rename —
|
|
2136
|
+
moves to `bun scripts/rekey-asset-ref.ts <old-ref> <new-ref>` (maintainer
|
|
2137
|
+
tooling, `--dry-run` supported, idempotent), which re-keys the index
|
|
2138
|
+
`entries` row in place plus the `asset_salience` / `asset_outcome` /
|
|
2139
|
+
`usage_events` rows. The `mv` event type and output shape are gone; the
|
|
2140
|
+
script emits a `rekey` event instead. A leftover `kind:"mv"` transaction
|
|
2141
|
+
journal from an rc build is now swept by the recovery scanner rather than
|
|
2142
|
+
failing it — an unregistered journal kind no longer bricks index refresh or
|
|
2143
|
+
proposal accept/reject.
|
|
2144
|
+
|
|
2145
|
+
- **The CHURN alert class is removed from the collapse detector.** Its input was
|
|
2146
|
+
a hard-coded `0` from the 0.9.0 confidence-gate deletion onward, so the alert
|
|
2147
|
+
could never fire. The other three alert classes are unaffected. The
|
|
2148
|
+
`improve_cycle_metrics.accepted_actions` column stays and is written as `0`
|
|
2149
|
+
because deployed 0.8 `state.db` files already contain it.
|
|
2150
|
+
|
|
2151
|
+
- **`IndexResponse.graphQuality` is removed** from the `akm index` envelope — it
|
|
2152
|
+
was declared but never assigned in any code path, so it was always absent.
|
|
2153
|
+
|
|
2154
|
+
- **`akm secret path` and `akm secret remove` are removed.** The two resolved a
|
|
2155
|
+
secret ref through *different* stash-selection logic — `path` through the
|
|
2156
|
+
read-side, all-sources resolver and `remove` through the write-target
|
|
2157
|
+
resolver — so for a ref present in more than one stash they could name
|
|
2158
|
+
different files: you could inspect one secret and delete another. Rather than
|
|
2159
|
+
reconcile the resolvers, both subcommands are gone; `akm secret` now exposes
|
|
2160
|
+
only `list`, `run`, and `set`. Both spellings exit 2 with `Unknown command`.
|
|
2161
|
+
|
|
2162
|
+
Migration: a ref's file lives at `<stash>/secrets/<name>` (run `akm sources
|
|
2163
|
+
list` for stash roots) — locate or delete it directly, or use `akm secret run
|
|
2164
|
+
<ref> <VAR> -- <command>` to consume the value without it touching disk. `akm
|
|
2165
|
+
env path` and `akm env remove` are unaffected.
|
|
2166
|
+
|
|
2167
|
+
- Removed the dead `"backup"` output-shape registration left over from the
|
|
2168
|
+
removed `akm backup` command (superseded by `akm-migrate backup`). Already
|
|
2169
|
+
unreachable; no user-visible effect.
|
|
2170
|
+
|
|
2171
|
+
- **`akm task list`, `akm task show`, and `akm task remove` are removed** as
|
|
2172
|
+
redundant with the generic asset commands. List and inspect tasks with `akm
|
|
2173
|
+
search` / `akm show <bundle//tasks/id>` (both already cross-bundle); to remove a
|
|
2174
|
+
scheduled task, delete its file in the owning bundle and run `akm task sync`
|
|
2175
|
+
(sync uninstalls the orphaned scheduler entry). Run `akm task doctor` for
|
|
2176
|
+
scheduler diagnostics — bare `akm task` is a usage error, see the canonical
|
|
2177
|
+
bare-group change above.
|
|
2178
|
+
|
|
2179
|
+
- **The `akm show <ref> toc|section|lines|frontmatter|full` view-mode grammar is
|
|
2180
|
+
removed** (0.9.0 decision D2). `#fragment` is now the only section selector,
|
|
2181
|
+
and a positional after the ref is a usage error that names it. Migration:
|
|
2182
|
+
|
|
2183
|
+
| Old | New |
|
|
2184
|
+
| --- | --- |
|
|
2185
|
+
| `akm show knowledge/guide section "Auth"` | `akm show knowledge/guide#auth` |
|
|
2186
|
+
| `akm show knowledge/guide full` | `akm show knowledge/guide` |
|
|
2187
|
+
| `akm show knowledge/guide toc` | `akm show knowledge/guide#<unmatched>` — the error lists the available fragment slugs |
|
|
2188
|
+
| `akm show knowledge/guide lines 10 30` | no replacement — every response carries `path`, so slice the file yourself |
|
|
2189
|
+
| `akm show knowledge/guide frontmatter` | no replacement — if a raw-YAML projection proves necessary it returns as a `--shape` value |
|
|
2190
|
+
|
|
2191
|
+
The undocumented `--akmView` / `--akmHeading` / `--akmStart` / `--akmEnd`
|
|
2192
|
+
flags the grammar injected into argv are gone with it.
|
|
2193
|
+
|
|
468
2194
|
## [0.9.0-rc.1] - 2026-06-30
|
|
469
2195
|
|
|
470
2196
|
### Fixed
|
|
@@ -1948,7 +3674,7 @@ behind an interactive prompt (or `-y` / `--yes` in non-interactive use).
|
|
|
1948
3674
|
|
|
1949
3675
|
### Changed
|
|
1950
3676
|
|
|
1951
|
-
- **Rebrand**: the full name "Agent Kit Manager" is now **Agent Knowledge
|
|
3677
|
+
- **Rebrand**: the full name "Agent Kit Manager" is now **Agent Knowledge Manager** — `akm` stands for Agent Knowledge Manager going forward. The binary name, npm package (`akm-cli`), and all APIs remain unchanged.
|
|
1952
3678
|
|
|
1953
3679
|
- **Config layer rewrite** — single-source-of-truth Zod schema in
|
|
1954
3680
|
`src/core/config-schema.ts` replaces the per-field parse switch AND
|
|
@@ -2136,7 +3862,7 @@ See `docs/migration/v0.7-to-v0.8.md` for the user-facing migration guide.
|
|
|
2136
3862
|
|
|
2137
3863
|
### Migration
|
|
2138
3864
|
|
|
2139
|
-
- See [`docs/migration/release-notes/0.7.0.md`](docs/migration/release-notes/0.7.0.md) for the operator summary and the [archived pre-1.0 plan](docs/archive/pre-1.0-migration.md) for the historical per-surface delta from any 0.6.x baseline.
|
|
3865
|
+
- See [`docs/migration/release-notes/0.7.0.md`](docs/migration/release-notes/0.7.0.md) for the operator summary and the [archived pre-1.0 plan](https://github.com/itlackey/akm/blob/be3a6a632b0cbe7a63ce71b7d093d8ac266e857c/docs/archive/pre-1.0-migration.md) for the historical per-surface delta from any 0.6.x baseline.
|
|
2140
3866
|
|
|
2141
3867
|
## [0.6.0] - 2026-04-23
|
|
2142
3868
|
|