akm-cli 0.8.0-rc2 → 0.8.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/{.github/CHANGELOG.md → CHANGELOG.md} +238 -3
- package/README.md +22 -6
- package/SECURITY.md +93 -0
- package/dist/assets/help/help-accept.md +12 -0
- package/dist/assets/help/help-improve.md +81 -0
- package/dist/{commands → assets}/help/help-proposals.md +7 -4
- package/dist/assets/help/help-reject.md +11 -0
- package/dist/{output → assets/hints}/cli-hints-full.md +60 -32
- package/dist/{output → assets/hints}/cli-hints-short.md +10 -7
- package/dist/assets/profiles/default.json +15 -0
- package/dist/assets/profiles/graph-refresh.json +13 -0
- package/dist/assets/profiles/memory-focus.json +12 -0
- package/dist/assets/profiles/quick.json +15 -0
- package/dist/assets/profiles/thorough.json +15 -0
- package/dist/assets/prompts/extract-session.md +80 -0
- package/dist/assets/prompts/graph-extract-user-prompt.md +35 -0
- package/dist/assets/tasks/graph-refresh-weekly.yml +10 -0
- package/dist/cli/config-migrate.js +144 -0
- package/dist/cli/config-validate.js +39 -0
- package/dist/cli/confirm.js +73 -0
- package/dist/cli/parse-args.js +93 -3
- package/dist/cli/shared.js +129 -0
- package/dist/cli.js +2141 -1268
- package/dist/commands/add-cli.js +279 -0
- package/dist/commands/agent-dispatch.js +20 -12
- package/dist/commands/agent-support.js +11 -5
- package/dist/commands/completions.js +3 -0
- package/dist/commands/config-cli.js +129 -517
- package/dist/commands/consolidate.js +1557 -147
- package/dist/commands/curate.js +44 -3
- package/dist/commands/db-cli.js +23 -0
- package/dist/commands/distill-promotion-policy.js +5 -3
- package/dist/commands/distill.js +906 -100
- package/dist/commands/env.js +213 -0
- package/dist/commands/eval-cases.js +3 -0
- package/dist/commands/events.js +3 -0
- package/dist/commands/extract-cli.js +127 -0
- package/dist/commands/extract-prompt.js +217 -0
- package/dist/commands/extract.js +477 -0
- package/dist/commands/feedback-cli.js +331 -0
- package/dist/commands/graph.js +260 -5
- package/dist/commands/health.js +1042 -55
- package/dist/commands/history.js +51 -16
- package/dist/commands/improve-auto-accept.js +97 -0
- package/dist/commands/improve-cli.js +236 -0
- package/dist/commands/improve-profiles.js +138 -0
- package/dist/commands/improve-result-file.js +167 -0
- package/dist/commands/improve.js +1736 -346
- package/dist/commands/info.js +26 -28
- package/dist/commands/init.js +49 -1
- package/dist/commands/installed-stashes.js +6 -23
- package/dist/commands/knowledge.js +3 -0
- package/dist/commands/lint/agent-linter.js +3 -0
- package/dist/commands/lint/base-linter.js +199 -5
- package/dist/commands/lint/command-linter.js +3 -0
- package/dist/commands/lint/default-linter.js +3 -0
- package/dist/commands/lint/env-key-rules.js +154 -0
- package/dist/commands/lint/index.js +92 -3
- package/dist/commands/lint/knowledge-linter.js +3 -0
- package/dist/commands/lint/markdown-insertion.js +343 -0
- package/dist/commands/lint/memory-linter.js +3 -0
- package/dist/commands/lint/registry.js +3 -0
- package/dist/commands/lint/skill-linter.js +3 -0
- package/dist/commands/lint/task-linter.js +15 -12
- package/dist/commands/lint/types.js +3 -0
- package/dist/commands/lint/workflow-linter.js +3 -0
- package/dist/commands/lint.js +3 -0
- package/dist/commands/migration-help.js +5 -2
- package/dist/commands/proposal-drain-policies.js +128 -0
- package/dist/commands/proposal-drain.js +477 -0
- package/dist/commands/proposal.js +60 -6
- package/dist/commands/propose.js +24 -19
- package/dist/commands/reflect.js +1004 -94
- package/dist/commands/registry-cli.js +150 -0
- package/dist/commands/registry-search.js +3 -0
- package/dist/commands/remember-cli.js +257 -0
- package/dist/commands/remember.js +15 -6
- package/dist/commands/schema-repair.js +88 -15
- package/dist/commands/search.js +99 -14
- package/dist/commands/secret.js +173 -0
- package/dist/commands/self-update.js +3 -0
- package/dist/commands/show.js +32 -13
- package/dist/commands/source-add.js +7 -35
- package/dist/commands/source-clone.js +3 -0
- package/dist/commands/source-manage.js +3 -0
- package/dist/commands/tasks.js +161 -95
- package/dist/commands/url-checker.js +3 -0
- package/dist/core/action-contributors.js +3 -0
- package/dist/core/asset-ref.js +13 -2
- package/dist/core/asset-registry.js +9 -2
- package/dist/core/asset-serialize.js +88 -0
- package/dist/core/asset-spec.js +61 -5
- package/dist/core/common.js +93 -5
- package/dist/core/concurrent.js +3 -0
- package/dist/core/config-io.js +347 -0
- package/dist/core/config-migration.js +622 -0
- package/dist/core/config-schema.js +558 -0
- package/dist/core/config-sources.js +108 -0
- package/dist/core/config-types.js +4 -0
- package/dist/core/config-walker.js +337 -0
- package/dist/core/config.js +366 -1077
- package/dist/core/errors.js +42 -20
- package/dist/core/events.js +31 -25
- package/dist/core/file-lock.js +104 -0
- package/dist/core/frontmatter.js +75 -10
- package/dist/core/lesson-lint.js +3 -0
- package/dist/core/markdown.js +3 -0
- package/dist/core/memory-belief.js +62 -0
- package/dist/core/memory-contradiction-detect.js +274 -0
- package/dist/core/memory-improve.js +142 -14
- package/dist/core/parse.js +3 -0
- package/dist/core/paths.js +218 -50
- package/dist/core/proposal-quality-validators.js +380 -0
- package/dist/core/proposal-validators.js +11 -3
- package/dist/core/proposals.js +464 -5
- package/dist/core/state-db.js +349 -56
- package/dist/core/text-truncation.js +107 -0
- package/dist/core/time.js +3 -0
- package/dist/core/tty.js +59 -0
- package/dist/core/warn.js +7 -2
- package/dist/core/write-source.js +12 -0
- package/dist/indexer/db-backup.js +391 -0
- package/dist/indexer/db-search.js +136 -28
- package/dist/indexer/db.js +661 -166
- package/dist/indexer/ensure-index.js +3 -0
- package/dist/indexer/file-context.js +3 -0
- package/dist/indexer/graph-boost.js +162 -40
- package/dist/indexer/graph-db.js +241 -51
- package/dist/indexer/graph-dedup.js +3 -7
- package/dist/indexer/graph-extraction.js +242 -149
- package/dist/indexer/index-context.js +3 -9
- package/dist/indexer/indexer.js +86 -16
- package/dist/indexer/llm-cache.js +24 -19
- package/dist/indexer/manifest.js +3 -0
- package/dist/indexer/matchers.js +184 -11
- package/dist/indexer/memory-inference.js +94 -50
- package/dist/indexer/metadata-contributors.js +3 -0
- package/dist/indexer/metadata.js +110 -50
- package/dist/indexer/path-resolver.js +3 -0
- package/dist/indexer/project-context.js +192 -0
- package/dist/indexer/ranking-contributors.js +134 -7
- package/dist/indexer/ranking.js +8 -1
- package/dist/indexer/search-fields.js +5 -9
- package/dist/indexer/search-hit-enrichers.js +91 -2
- package/dist/indexer/search-source.js +20 -1
- package/dist/indexer/semantic-status.js +4 -1
- package/dist/indexer/staleness-detect.js +447 -0
- package/dist/indexer/usage-events.js +12 -9
- package/dist/indexer/walker.js +3 -0
- package/dist/integrations/agent/builders.js +135 -0
- package/dist/integrations/agent/config.js +121 -401
- package/dist/integrations/agent/detect.js +3 -0
- package/dist/integrations/agent/index.js +6 -14
- package/dist/integrations/agent/model-aliases.js +55 -0
- package/dist/integrations/agent/profiles.js +3 -0
- package/dist/integrations/agent/prompts.js +137 -8
- package/dist/integrations/agent/runner.js +208 -0
- package/dist/integrations/agent/sdk-runner.js +8 -2
- package/dist/integrations/agent/spawn.js +54 -14
- package/dist/integrations/github.js +3 -0
- package/dist/integrations/lockfile.js +22 -51
- package/dist/integrations/session-logs/index.js +4 -0
- package/dist/integrations/session-logs/inline-refs.js +35 -0
- package/dist/integrations/session-logs/pre-filter.js +152 -0
- package/dist/integrations/session-logs/providers/claude-code.js +226 -0
- package/dist/integrations/session-logs/providers/opencode.js +231 -25
- package/dist/integrations/session-logs/types.js +3 -0
- package/dist/llm/call-ai.js +14 -26
- package/dist/llm/client.js +16 -2
- package/dist/llm/embedder.js +20 -29
- package/dist/llm/embedders/cache.js +3 -7
- package/dist/llm/embedders/local.js +42 -1
- package/dist/llm/embedders/remote.js +20 -8
- package/dist/llm/embedders/types.js +3 -7
- package/dist/llm/feature-gate.js +92 -56
- package/dist/llm/graph-extract.js +402 -31
- package/dist/llm/index-passes.js +44 -29
- package/dist/llm/memory-infer.js +30 -2
- package/dist/llm/metadata-enhance.js +3 -7
- package/dist/output/cli-hints.js +7 -4
- package/dist/output/context.js +60 -8
- package/dist/output/renderers.js +170 -194
- package/dist/output/shapes/curate.js +56 -0
- package/dist/output/shapes/distill.js +10 -0
- package/dist/output/shapes/env-list.js +19 -0
- package/dist/output/shapes/events.js +11 -0
- package/dist/output/shapes/helpers.js +424 -0
- package/dist/output/shapes/history.js +7 -0
- package/dist/output/shapes/passthrough.js +105 -0
- package/dist/output/shapes/proposal-accept.js +7 -0
- package/dist/output/shapes/proposal-diff.js +7 -0
- package/dist/output/shapes/proposal-list.js +7 -0
- package/dist/output/shapes/proposal-producer.js +11 -0
- package/dist/output/shapes/proposal-reject.js +7 -0
- package/dist/output/shapes/proposal-show.js +7 -0
- package/dist/output/shapes/registry-search.js +6 -0
- package/dist/output/shapes/registry.js +30 -0
- package/dist/output/shapes/search.js +6 -0
- package/dist/output/shapes/secret-list.js +19 -0
- package/dist/output/shapes/show.js +6 -0
- package/dist/output/shapes/vault-list.js +19 -0
- package/dist/output/shapes.js +51 -549
- package/dist/output/text/add.js +6 -0
- package/dist/output/text/clone.js +6 -0
- package/dist/output/text/config.js +6 -0
- package/dist/output/text/curate.js +6 -0
- package/dist/output/text/distill.js +7 -0
- package/dist/output/text/enable-disable.js +7 -0
- package/dist/output/text/events.js +10 -0
- package/dist/output/text/feedback.js +6 -0
- package/dist/output/text/helpers.js +1059 -0
- package/dist/output/text/history.js +7 -0
- package/dist/output/text/import.js +6 -0
- package/dist/output/text/index.js +6 -0
- package/dist/output/text/info.js +6 -0
- package/dist/output/text/init.js +6 -0
- package/dist/output/text/list.js +6 -0
- package/dist/output/text/proposal-producer.js +8 -0
- package/dist/output/text/proposal.js +12 -0
- package/dist/output/text/registry-commands.js +11 -0
- package/dist/output/text/registry.js +30 -0
- package/dist/output/text/remember.js +6 -0
- package/dist/output/text/remove.js +6 -0
- package/dist/output/text/save.js +6 -0
- package/dist/output/text/search.js +6 -0
- package/dist/output/text/show.js +6 -0
- package/dist/output/text/update.js +6 -0
- package/dist/output/text/upgrade.js +6 -0
- package/dist/output/text/vault.js +16 -0
- package/dist/output/text/wiki.js +15 -0
- package/dist/output/text/workflow.js +14 -0
- package/dist/output/text.js +44 -1329
- package/dist/registry/build-index.js +3 -0
- package/dist/registry/create-provider-registry.js +3 -0
- package/dist/registry/factory.js +4 -1
- package/dist/registry/origin-resolve.js +3 -0
- package/dist/registry/providers/index.js +3 -0
- package/dist/registry/providers/skills-sh.js +11 -2
- package/dist/registry/providers/static-index.js +10 -1
- package/dist/registry/providers/types.js +3 -24
- package/dist/registry/resolve.js +11 -16
- package/dist/registry/types.js +3 -0
- package/dist/scripts/migrate-storage.js +17767 -0
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +9031 -0
- package/dist/scripts/migrations/v16-to-v17.js +141 -0
- package/dist/setup/detect.js +3 -0
- package/dist/setup/ripgrep-install.js +3 -0
- package/dist/setup/ripgrep-resolve.js +3 -0
- package/dist/setup/setup.js +306 -67
- package/dist/setup/steps.js +3 -15
- package/dist/sources/include.js +3 -0
- package/dist/sources/provider-factory.js +3 -11
- package/dist/sources/provider.js +3 -20
- package/dist/sources/providers/filesystem.js +19 -23
- package/dist/sources/providers/git.js +171 -21
- package/dist/sources/providers/index.js +3 -0
- package/dist/sources/providers/install-types.js +3 -13
- package/dist/sources/providers/npm.js +3 -4
- package/dist/sources/providers/provider-utils.js +3 -0
- package/dist/sources/providers/sync-from-ref.js +3 -11
- package/dist/sources/providers/tar-utils.js +3 -0
- package/dist/sources/providers/website.js +18 -22
- package/dist/sources/resolve.js +3 -0
- package/dist/sources/types.js +3 -0
- package/dist/sources/website-ingest.js +3 -0
- package/dist/tasks/backends/cron.js +3 -0
- package/dist/tasks/backends/exec-utils.js +3 -0
- package/dist/tasks/backends/index.js +3 -11
- package/dist/tasks/backends/launchd.js +4 -1
- package/dist/tasks/backends/schtasks.js +4 -1
- package/dist/tasks/parser.js +51 -38
- package/dist/tasks/resolveAkmBin.js +3 -0
- package/dist/tasks/runner.js +35 -9
- package/dist/tasks/schedule.js +20 -1
- package/dist/tasks/schema.js +5 -3
- package/dist/tasks/validator.js +6 -3
- package/dist/version.js +3 -0
- package/dist/wiki/wiki-templates.js +6 -3
- package/dist/wiki/wiki.js +4 -1
- package/dist/workflows/authoring.js +4 -1
- package/dist/workflows/cli.js +3 -0
- package/dist/workflows/db.js +140 -10
- package/dist/workflows/document-cache.js +3 -10
- package/dist/workflows/parser.js +3 -0
- package/dist/workflows/renderer.js +3 -0
- package/dist/workflows/runs.js +18 -1
- package/dist/workflows/schema.js +3 -0
- package/dist/workflows/scope-key.js +3 -0
- package/dist/workflows/validator.js +5 -9
- package/docs/README.md +7 -2
- package/docs/data-and-telemetry.md +225 -0
- package/docs/migration/release-notes/0.7.5.md +2 -2
- package/docs/migration/release-notes/0.8.0.md +57 -5
- package/docs/migration/v0.7-to-v0.8.md +1378 -0
- package/package.json +28 -11
- package/.github/LICENSE +0 -374
- package/dist/commands/help/help-accept.md +0 -9
- package/dist/commands/help/help-improve.md +0 -53
- package/dist/commands/help/help-reject.md +0 -8
- package/dist/commands/install-audit.js +0 -385
- package/dist/commands/vault.js +0 -310
- package/dist/indexer/match-contributors.js +0 -141
- package/dist/integrations/agent/pipeline.js +0 -39
- package/dist/integrations/agent/runners.js +0 -31
- package/dist/llm/prompts/graph-extract-user-prompt.md +0 -12
- /package/dist/{tasks → assets}/backends/launchd-template.xml +0 -0
- /package/dist/{tasks → assets}/backends/schtasks-template.xml +0 -0
- /package/dist/{commands → assets}/help/help-propose.md +0 -0
- /package/dist/{wiki → assets/wiki}/index-template.md +0 -0
- /package/dist/{wiki → assets/wiki}/ingest-workflow-template.md +0 -0
- /package/dist/{wiki → assets/wiki}/log-template.md +0 -0
- /package/dist/{wiki → assets/wiki}/schema-template.md +0 -0
- /package/dist/{workflows → assets/workflows}/workflow-template.md +0 -0
|
@@ -16,12 +16,13 @@ akm search "<query>" --detail full # Include scores, paths, timing
|
|
|
16
16
|
|
|
17
17
|
| Flag | Values | Default |
|
|
18
18
|
| --- | --- | --- |
|
|
19
|
-
| `--type` | `skill`, `command`, `agent`, `knowledge`, `workflow`, `script`, `memory`, `
|
|
19
|
+
| `--type` | `skill`, `command`, `agent`, `knowledge`, `workflow`, `script`, `memory`, `env`, `secret`, `wiki`, `any` | `any` |
|
|
20
20
|
| `--source` | `stash`, `registry`, `both` | `stash` |
|
|
21
21
|
| `--limit` | number | `20` |
|
|
22
22
|
| `--format` | `json`, `jsonl`, `text`, `yaml` | `json` |
|
|
23
|
-
| `--detail` | `brief`, `normal`, `full
|
|
24
|
-
| `--
|
|
23
|
+
| `--detail` | `brief`, `normal`, `full` | `brief` |
|
|
24
|
+
| `--shape` | `human`, `agent`, `summary` (`summary` only on `show`) | `human` |
|
|
25
|
+
| `--for-agent` | boolean (deprecated — use `--shape agent`) | `false` |
|
|
25
26
|
|
|
26
27
|
## Curate
|
|
27
28
|
|
|
@@ -59,7 +60,7 @@ akm show knowledge:my-doc # Show content (local or remote)
|
|
|
59
60
|
| workflow | `workflowTitle`, `workflowParameters`, `steps` |
|
|
60
61
|
| memory | `content` (recalled context) |
|
|
61
62
|
| vault | `keys`, `comments` |
|
|
62
|
-
| wiki | `content` (same view modes as knowledge). For any wiki task, run `akm wiki list
|
|
63
|
+
| wiki | `content` (same view modes as knowledge). For any wiki task, run `akm wiki list`. To ingest sources, `akm wiki ingest <name>` dispatches the configured agent (defaults.agent or `--profile`) to execute the ingest workflow. |
|
|
63
64
|
|
|
64
65
|
## Capture Knowledge While You Work
|
|
65
66
|
|
|
@@ -102,13 +103,17 @@ akm wiki stash research https://example.com/paper # Fetch one URL into raw/<slug
|
|
|
102
103
|
akm wiki stash research ./paper.md --target my-stash # Route write to a named writable stash source
|
|
103
104
|
echo "..." | akm wiki stash research - # stdin form
|
|
104
105
|
akm wiki lint research # Structural checks: orphans, broken xrefs, uncited raws, stale index
|
|
105
|
-
akm wiki ingest research #
|
|
106
|
-
akm wiki
|
|
107
|
-
akm wiki
|
|
106
|
+
akm wiki ingest research # Dispatch defaults.agent to run the ingest workflow on this wiki
|
|
107
|
+
akm wiki ingest research --profile claude --model sonnet # Override profile and model
|
|
108
|
+
akm wiki ingest research --timeout-ms 600000 # Override agent CLI timeout (default: profile setting)
|
|
109
|
+
akm wiki remove research -y # Delete pages/schema/index/log; preserves raw/ (--force is a deprecated alias for -y)
|
|
110
|
+
akm wiki remove research -y --with-sources # Full nuke, including raw/
|
|
108
111
|
```
|
|
109
112
|
|
|
110
|
-
**For any wiki task, start with `akm wiki list
|
|
111
|
-
|
|
113
|
+
**For any wiki task, start with `akm wiki list`. Then `akm wiki ingest <name>`
|
|
114
|
+
dispatches the configured agent (defaults.agent or `--profile`) to execute
|
|
115
|
+
the wiki's ingest workflow end-to-end — schema read, source dedup, search,
|
|
116
|
+
page create/update, log entry, lint, reindex.** Wiki pages are also addressable as
|
|
112
117
|
`wiki:<name>/<page-path>` and show up in stash-wide `akm search` as
|
|
113
118
|
`type: wiki`. Files under `raw/` and the wiki root infrastructure files
|
|
114
119
|
`schema.md`, `index.md`, and `log.md` are not indexed and do not appear in
|
|
@@ -163,23 +168,40 @@ akm clone "npm:@scope/pkg//script:deploy.sh" # Clone from remote package
|
|
|
163
168
|
|
|
164
169
|
When `--dest` is provided, `akm init` is not required first.
|
|
165
170
|
|
|
166
|
-
##
|
|
171
|
+
## Sync
|
|
167
172
|
|
|
168
|
-
Commit local changes in a git-backed stash. Behaviour adapts automatically
|
|
173
|
+
Commit local changes in a git-backed stash. Behaviour adapts automatically.
|
|
174
|
+
(`akm save` is the deprecated 0.7 spelling — it still works but warns; removed
|
|
175
|
+
in 0.9.0.)
|
|
169
176
|
|
|
170
|
-
- **
|
|
177
|
+
- **No `.git` directory** — no-op (silent skip)
|
|
171
178
|
- **Git repo, no remote** — stage and commit only (the default stash always falls here)
|
|
172
179
|
- **Git repo, has remote, not writable** — stage and commit only
|
|
173
180
|
- **Git repo, has remote, `writable: true`** — stage, commit, and push
|
|
181
|
+
- **Any writable repo with `--no-push`** — stage and commit only
|
|
174
182
|
|
|
175
183
|
```sh
|
|
176
|
-
akm
|
|
177
|
-
akm
|
|
178
|
-
akm
|
|
179
|
-
akm
|
|
184
|
+
akm sync # Sync primary stash (timestamp message)
|
|
185
|
+
akm sync -m "Add deploy skill" # Sync with explicit message
|
|
186
|
+
akm sync --no-push # Commit only; never push
|
|
187
|
+
akm sync my-skills # Sync a named writable git stash
|
|
188
|
+
akm sync my-skills -m "Update patterns" # Sync named stash with message
|
|
180
189
|
```
|
|
181
190
|
|
|
182
|
-
|
|
191
|
+
`akm improve` also performs an end-of-run batch commit for git-backed stashes.
|
|
192
|
+
The `--sync` / `--no-sync` and `--push` / `--no-push` flags control this:
|
|
193
|
+
|
|
194
|
+
```sh
|
|
195
|
+
akm improve # auto-sync per profile default (default/thorough: on; quick/memory-focus: off)
|
|
196
|
+
akm improve --no-sync # skip the end-of-run commit
|
|
197
|
+
akm improve --no-push # commit but skip push for this run
|
|
198
|
+
akm improve --sync # force sync even on profiles that disable it
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Profile sync defaults: `default` and `thorough` auto-commit + push; `quick` and
|
|
202
|
+
`memory-focus` skip sync entirely. Override with `--sync` / `--no-sync` flags.
|
|
203
|
+
|
|
204
|
+
The `--writable` flag on `akm add` opts a remote git stash into push-on-sync:
|
|
183
205
|
|
|
184
206
|
```sh
|
|
185
207
|
akm add git@github.com:org/skills.git --provider git --name my-skills --writable
|
|
@@ -193,8 +215,8 @@ akm add @scope/stash # From npm (managed)
|
|
|
193
215
|
akm add owner/repo # From GitHub (managed)
|
|
194
216
|
akm add ./path/to/local/stash # Local directory
|
|
195
217
|
akm add git@github.com:org/repo.git --provider git --name my-skills --writable
|
|
196
|
-
akm enable skills.sh
|
|
197
|
-
akm disable skills.sh
|
|
218
|
+
akm config enable skills.sh # Enable the skills.sh registry
|
|
219
|
+
akm config disable skills.sh # Disable the skills.sh registry
|
|
198
220
|
akm list # List all sources
|
|
199
221
|
akm list --kind managed # List managed sources only
|
|
200
222
|
akm remove <target> # Remove by id, ref, path, or name
|
|
@@ -244,24 +266,29 @@ akm completions --install # Install completions
|
|
|
244
266
|
## Proposals & Improvement (0.8.0+)
|
|
245
267
|
|
|
246
268
|
```sh
|
|
247
|
-
akm improve <ref>
|
|
248
|
-
akm
|
|
249
|
-
akm show
|
|
250
|
-
akm diff <ref-or-id> # Diff by ref, UUID, or 8-char prefix
|
|
251
|
-
akm diff skill:akm-dream # Diff by asset ref
|
|
252
|
-
akm accept 7c115132 # Accept by UUID prefix
|
|
253
|
-
akm accept <id> --target team-stash # Accept to a named writable stash source
|
|
254
|
-
akm reject skill:my-skill --reason "not ready" # Reject by asset ref
|
|
255
|
-
akm reject <id> --reason "..." # Archive with a reason
|
|
269
|
+
akm improve <ref> # Propose improvement for an asset
|
|
270
|
+
akm proposal list # List pending proposals
|
|
271
|
+
akm proposal show <id> # Render the proposal body
|
|
272
|
+
akm proposal diff <ref-or-id> # Diff by ref, UUID, or 8-char prefix
|
|
273
|
+
akm proposal diff skill:akm-dream # Diff by asset ref
|
|
274
|
+
akm proposal accept 7c115132 # Accept by UUID prefix
|
|
275
|
+
akm proposal accept <id> --target team-stash # Accept to a named writable stash source
|
|
276
|
+
akm proposal reject skill:my-skill --reason "not ready" # Reject by asset ref
|
|
277
|
+
akm proposal reject <id> --reason "..." # Archive with a reason
|
|
278
|
+
akm proposal revert <id> # Restore the pre-promotion content
|
|
256
279
|
```
|
|
257
280
|
|
|
281
|
+
The flat verbs `akm proposals` / `akm show proposal` / `akm accept` /
|
|
282
|
+
`akm reject` / `akm diff` / `akm revert` still work as deprecated aliases
|
|
283
|
+
(warn on stderr; removed in 0.9.0).
|
|
284
|
+
|
|
258
285
|
Per-task `timeoutMs`: task markdown frontmatter may set `timeoutMs: null` to
|
|
259
286
|
disable the agent kill timer for long-running local-model tasks, or a number
|
|
260
287
|
(milliseconds) to override `config.agent.timeoutMs` for that task only.
|
|
261
288
|
|
|
262
289
|
## Output Control
|
|
263
290
|
|
|
264
|
-
All commands accept `--format
|
|
291
|
+
All commands accept `--format`, `--detail`, and `--shape` flags:
|
|
265
292
|
|
|
266
293
|
- `--format json` (default) — structured JSON
|
|
267
294
|
- `--format jsonl` — one JSON object per line (streaming-friendly)
|
|
@@ -270,8 +297,9 @@ All commands accept `--format` and `--detail` flags:
|
|
|
270
297
|
- `--detail brief` (default) — compact output
|
|
271
298
|
- `--detail normal` — adds tags, refs, origins
|
|
272
299
|
- `--detail full` — includes scores, paths, timing, debug info
|
|
273
|
-
- `--
|
|
274
|
-
- `--
|
|
275
|
-
- `--
|
|
300
|
+
- `--shape human` (default) — standard projection
|
|
301
|
+
- `--shape agent` — agent-optimized output: strips non-actionable fields
|
|
302
|
+
- `--shape summary` — metadata only (no content/template/prompt), under 200 tokens; only valid on `akm show`
|
|
303
|
+
- `--for-agent` — deprecated alias for `--shape agent` (removed 0.9.0)
|
|
276
304
|
|
|
277
305
|
Run `akm -h` or `akm <command> -h` for per-command help.
|
|
@@ -33,15 +33,17 @@ akm remember "note" --target my-stash # Route write to a named writable
|
|
|
33
33
|
akm import ./notes/release-checklist.md # Import a knowledge doc into your stash
|
|
34
34
|
akm import ./doc.md --target my-stash # Route import to a named writable stash source
|
|
35
35
|
akm wiki list # List available wikis
|
|
36
|
-
akm wiki ingest <name> #
|
|
36
|
+
akm wiki ingest <name> # Dispatch an agent to run the ingest workflow (uses defaults.agent or --profile)
|
|
37
37
|
akm wiki stash <name> ./paper.md --target my-stash # Route wiki stash write to a named source
|
|
38
|
-
akm diff skill:akm-dream
|
|
39
|
-
akm accept 7c115132
|
|
40
|
-
akm reject skill:my-skill --reason "..."
|
|
38
|
+
akm proposal diff skill:akm-dream # Diff proposal by ref, UUID, or 8-char prefix
|
|
39
|
+
akm proposal accept 7c115132 # Accept by UUID prefix
|
|
40
|
+
akm proposal reject skill:my-skill --reason "..." # Reject by ref
|
|
41
41
|
akm feedback <ref> --positive|--negative # Record whether an asset helped
|
|
42
42
|
akm add <ref> # Add a source (npm, GitHub, git, local dir)
|
|
43
43
|
akm clone <ref> # Copy an asset to the working stash (optional --dest arg to clone to specific location)
|
|
44
|
-
akm
|
|
44
|
+
akm sync # Commit (and push if writable remote) changes in the primary stash (--no-push to commit only)
|
|
45
|
+
akm improve --no-sync # Run improve without the end-of-run auto-commit
|
|
46
|
+
akm improve --no-push # Auto-commit but skip push for this run
|
|
45
47
|
akm registry search "<query>" # Search all registries
|
|
46
48
|
```
|
|
47
49
|
|
|
@@ -56,8 +58,9 @@ akm registry search "<query>" # Search all registries
|
|
|
56
58
|
| knowledge | A reference doc (use `toc` or `section "..."` to navigate) |
|
|
57
59
|
| workflow | Parsed steps plus workflow-specific execution commands |
|
|
58
60
|
| memory | Recalled context (read the content for background information) |
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
+
| env | A `.env` file of related CONFIGURATION (many vars; sensitive or not — all protected); key names only. Inject with `akm env run <ref> -- <cmd>` (the agent-safe path — values stay on disk). `vault` is the deprecated alias. |
|
|
62
|
+
| secret | A single sensitive value for AUTHENTICATION (token, key, cert); name only. Use `akm secret path` / `akm secret run`. |
|
|
63
|
+
| wiki | A page in a multi-wiki knowledge base. For any wiki task, start with `akm wiki list`. To ingest sources, run `akm wiki ingest <name>` — it dispatches the configured agent profile to execute the ingest workflow against the wiki's `raw/` directory. Run `akm wiki -h` for the full surface. |
|
|
61
64
|
|
|
62
65
|
When an asset meaningfully helps or fails, record that with `akm feedback` so
|
|
63
66
|
future search ranking can learn from real usage.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Standard improve pass — all sub-processes, markdown asset types.",
|
|
3
|
+
"processes": {
|
|
4
|
+
"reflect": {
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"allowedTypes": ["agent", "command", "knowledge", "lesson", "memory", "skill", "wiki", "workflow"]
|
|
7
|
+
},
|
|
8
|
+
"distill": { "enabled": true, "allowedTypes": ["memory"] },
|
|
9
|
+
"consolidate": { "enabled": true, "allowedTypes": ["memory"] },
|
|
10
|
+
"memoryInference": { "enabled": true },
|
|
11
|
+
"graphExtraction": { "enabled": true },
|
|
12
|
+
"triage": { "enabled": false, "applyMode": "queue", "policy": "personal-stash" }
|
|
13
|
+
},
|
|
14
|
+
"sync": { "enabled": true, "push": true }
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Full-corpus graph extraction pass — rebuilds graph relationships across all stash files. Disables all other sub-processes. Use via `akm improve --profile graph-refresh` or the embedded `graph-refresh-weekly` task.",
|
|
3
|
+
"processes": {
|
|
4
|
+
"reflect": { "enabled": false },
|
|
5
|
+
"distill": { "enabled": false },
|
|
6
|
+
"consolidate": { "enabled": false },
|
|
7
|
+
"memoryInference": { "enabled": false },
|
|
8
|
+
"graphExtraction": { "enabled": true, "fullScan": true },
|
|
9
|
+
"extract": { "enabled": false },
|
|
10
|
+
"triage": { "enabled": false }
|
|
11
|
+
},
|
|
12
|
+
"sync": { "enabled": true, "push": true }
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Memory and lesson improvement only — no distill, consolidate, or graphExtraction.",
|
|
3
|
+
"processes": {
|
|
4
|
+
"reflect": { "enabled": true, "allowedTypes": ["memory", "lesson"] },
|
|
5
|
+
"distill": { "enabled": false },
|
|
6
|
+
"consolidate": { "enabled": false },
|
|
7
|
+
"memoryInference": { "enabled": true },
|
|
8
|
+
"graphExtraction": { "enabled": false },
|
|
9
|
+
"triage": { "enabled": false }
|
|
10
|
+
},
|
|
11
|
+
"sync": { "enabled": false }
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Reflect-only pass — no distill, consolidate, memoryInference, or graphExtraction.",
|
|
3
|
+
"processes": {
|
|
4
|
+
"reflect": {
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"allowedTypes": ["agent", "command", "knowledge", "lesson", "memory", "skill", "wiki", "workflow"]
|
|
7
|
+
},
|
|
8
|
+
"distill": { "enabled": false },
|
|
9
|
+
"consolidate": { "enabled": false },
|
|
10
|
+
"memoryInference": { "enabled": false },
|
|
11
|
+
"graphExtraction": { "enabled": false },
|
|
12
|
+
"triage": { "enabled": false }
|
|
13
|
+
},
|
|
14
|
+
"sync": { "enabled": false }
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "All sub-processes enabled (currently identical to default; reserved for future divergence).",
|
|
3
|
+
"processes": {
|
|
4
|
+
"reflect": {
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"allowedTypes": ["agent", "command", "knowledge", "lesson", "memory", "skill", "wiki", "workflow"]
|
|
7
|
+
},
|
|
8
|
+
"distill": { "enabled": true, "allowedTypes": ["memory"] },
|
|
9
|
+
"consolidate": { "enabled": true, "allowedTypes": ["memory"] },
|
|
10
|
+
"memoryInference": { "enabled": true },
|
|
11
|
+
"graphExtraction": { "enabled": true },
|
|
12
|
+
"triage": { "enabled": true, "applyMode": "queue" }
|
|
13
|
+
},
|
|
14
|
+
"sync": { "enabled": true, "push": true }
|
|
15
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
You are extracting durable engineering insights from a software session transcript. Most sessions produce zero new durable insights — the agent already captures what's worth keeping via explicit `akm remember` / `akm feedback` calls during the session. Your job is to identify learnings that slipped through.
|
|
2
|
+
|
|
3
|
+
## What counts as "durable insight"
|
|
4
|
+
|
|
5
|
+
Things worth extracting:
|
|
6
|
+
- Recovery patterns ("X fails when Y; the fix is Z")
|
|
7
|
+
- Hidden constraints discovered mid-task ("this codebase requires X before deploy")
|
|
8
|
+
- Architecture observations ("module A is consumed by B and C via the D bus")
|
|
9
|
+
- Non-obvious workarounds for real defects
|
|
10
|
+
- Domain knowledge the agent learned and would benefit a future session
|
|
11
|
+
|
|
12
|
+
Things NOT to extract:
|
|
13
|
+
- Successful command sequences (already in git history / shell history)
|
|
14
|
+
- Tool counts / aggregates
|
|
15
|
+
- The agent's own narrative about what it was doing
|
|
16
|
+
- Restatements of what the user asked for
|
|
17
|
+
- Generic platitudes ("test your code", "be careful with X")
|
|
18
|
+
- Anything already preserved via the agent's explicit calls (see below)
|
|
19
|
+
|
|
20
|
+
## Already preserved by the agent — DO NOT re-extract
|
|
21
|
+
|
|
22
|
+
{{ALREADY_PRESERVED}}
|
|
23
|
+
|
|
24
|
+
## Session metadata
|
|
25
|
+
|
|
26
|
+
- Harness: {{HARNESS}}
|
|
27
|
+
- Title: {{TITLE}}
|
|
28
|
+
- Started: {{STARTED_AT}}
|
|
29
|
+
- Ended: {{ENDED_AT}}
|
|
30
|
+
- Project hint: {{PROJECT_HINT}}
|
|
31
|
+
|
|
32
|
+
## Filtered session transcript
|
|
33
|
+
|
|
34
|
+
The transcript below has already had read-only `akm` meta-ops and platform boilerplate stripped. Only content that might carry signal remains.
|
|
35
|
+
|
|
36
|
+
{{TRANSCRIPT}}
|
|
37
|
+
|
|
38
|
+
## Output contract
|
|
39
|
+
|
|
40
|
+
Respond with EXACTLY one JSON object matching this shape:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
{
|
|
44
|
+
"candidates": [
|
|
45
|
+
{
|
|
46
|
+
"type": "memory" | "lesson" | "knowledge",
|
|
47
|
+
"name": "<kebab-case-slug>",
|
|
48
|
+
"description": "<one sentence 20-400 chars>",
|
|
49
|
+
"when_to_use": "<one sentence 15-400 chars; REQUIRED only when type=lesson>",
|
|
50
|
+
"body": "<markdown body, 200-3000 chars typical>",
|
|
51
|
+
"confidence": <number 0.0-1.0>,
|
|
52
|
+
"evidence": "<one-line pointer to the moment in the session>"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"rationale_if_empty": "<one sentence; REQUIRED when candidates is empty>"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Rules
|
|
60
|
+
|
|
61
|
+
1. **Zero candidates is a valid and frequent answer.** Most sessions yield no new durable insight. When that's the case, return `{"candidates": [], "rationale_if_empty": "..."}` explaining what you saw and why it didn't rise to durable-knowledge level. Do not fabricate.
|
|
62
|
+
|
|
63
|
+
2. **Pick the right type per candidate:**
|
|
64
|
+
- `memory` — a fact or short observation. Use for "X works on this codebase", "auth uses Y library version Z".
|
|
65
|
+
- `lesson` — a "do X / avoid Y" pattern, ALWAYS with `when_to_use`. Use for hard-won learnings about pitfalls, recovery patterns, or non-obvious gotchas.
|
|
66
|
+
- `knowledge` — substantive multi-section reference doc. Rare from one session.
|
|
67
|
+
|
|
68
|
+
3. **Calibrate `confidence` honestly:**
|
|
69
|
+
- `0.9+` — high certainty this is a real durable insight a reviewer would clearly accept
|
|
70
|
+
- `0.7-0.89` — clear improvement, but a reviewer might prefer different framing or scope
|
|
71
|
+
- `0.5-0.69` — marginal / judgment call
|
|
72
|
+
- `<0.5` — don't include; prefer fewer-but-better candidates
|
|
73
|
+
|
|
74
|
+
4. **`evidence` must reference the session** — a brief pointer like "agent's tool failure at ts=...", "user's correction at ...", "after the recovery in the Bash sequence around ...". Without evidence the candidate is hard to validate; default to lower confidence when evidence is vague.
|
|
75
|
+
|
|
76
|
+
5. **Do not duplicate already-preserved content.** If a candidate substantively overlaps with anything in the "Already preserved" list above, skip it.
|
|
77
|
+
|
|
78
|
+
6. **No speculation.** Only extract things the session genuinely demonstrates. If the agent struggled and didn't resolve, that may itself be a lesson (`when_to_use: "When attempting X, expect Y to fail"`) — but only if the failure mode is concrete enough to be useful next time.
|
|
79
|
+
|
|
80
|
+
7. Respond with the JSON object only. No prose before or after. No code fences.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Extract entities and relations from the asset body below.
|
|
2
|
+
|
|
3
|
+
Rules:
|
|
4
|
+
- Output ONLY a JSON object: {"entities": ["Entity One", ...], "relations": [{"from": "A", "to": "B", "type": "uses"}, ...]}.
|
|
5
|
+
- Entities are short, canonical noun phrases (project names, services, tools, people, file/dir names, technical concepts).
|
|
6
|
+
- Relations connect two entities that both appear in the entities array.
|
|
7
|
+
- "type" is a short verb phrase (e.g. "uses", "depends on", "owns", "documents"). Optional; omit when unsure.
|
|
8
|
+
- Drop pleasantries, meta-commentary, and timestamps.
|
|
9
|
+
- Limit to at most {{MAX_ENTITIES}} entities and {{MAX_RELATIONS}} relations per asset.
|
|
10
|
+
- Return {"entities": [], "relations": []} if the body has no extractable graph content.
|
|
11
|
+
- DO NOT return markdown code blocks, ONLY valid JSON objects.
|
|
12
|
+
|
|
13
|
+
Examples:
|
|
14
|
+
|
|
15
|
+
Input:
|
|
16
|
+
## Deployment Notes
|
|
17
|
+
The auth-service uses PostgreSQL for user sessions. It depends on the redis-cache
|
|
18
|
+
for rate limiting. The terraform-provisioner deploys everything to the prod cluster.
|
|
19
|
+
Owner: @alice.
|
|
20
|
+
|
|
21
|
+
Output:
|
|
22
|
+
{"entities":["auth-service","PostgreSQL","redis-cache","terraform-provisioner","prod cluster","@alice"],"relations":[{"from":"auth-service","to":"PostgreSQL","type":"uses"},{"from":"auth-service","to":"redis-cache","type":"depends on"},{"from":"terraform-provisioner","to":"prod cluster","type":"deploys"},{"from":"terraform-provisioner","to":"auth-service","type":"deploys"},{"from":"@alice","to":"auth-service","type":"owns"}]}
|
|
23
|
+
|
|
24
|
+
Input:
|
|
25
|
+
## Meeting: API Redesign
|
|
26
|
+
Discussed moving from REST to GraphQL. The frontend team will use Apollo Client.
|
|
27
|
+
Backend needs to implement resolvers. Timeline: Q2.
|
|
28
|
+
|
|
29
|
+
Output:
|
|
30
|
+
{"entities":["REST","GraphQL","Apollo Client","frontend team","backend","resolvers","Q2"],"relations":[{"from":"frontend team","to":"Apollo Client","type":"uses"},{"from":"backend","to":"resolvers","type":"implements"},{"from":"frontend team","to":"GraphQL","type":"migrates to"}]}
|
|
31
|
+
|
|
32
|
+
===============
|
|
33
|
+
|
|
34
|
+
Request:
|
|
35
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
id: graph-refresh-weekly
|
|
2
|
+
description: >
|
|
3
|
+
Weekly full-corpus graph extraction pass. Rebuilds entity and relation
|
|
4
|
+
indexes across all stash files using the graph-refresh improve profile.
|
|
5
|
+
Complements the per-run improve pipeline which only extracts graph data
|
|
6
|
+
for files touched by actionable refs.
|
|
7
|
+
command: akm improve --profile graph-refresh
|
|
8
|
+
schedule: "0 3 * * 0"
|
|
9
|
+
enabled: false
|
|
10
|
+
timeout: 3600000
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { stripJsonComments } from "../core/config";
|
|
7
|
+
import { unifiedDiff, withConfigLock, writeConfigAtomic } from "../core/config-io";
|
|
8
|
+
import { migrateConfigShape } from "../core/config-migration";
|
|
9
|
+
import { getCacheDir, getConfigPath } from "../core/paths";
|
|
10
|
+
import { warn } from "../core/warn";
|
|
11
|
+
export { migrateConfigShape } from "../core/config-migration";
|
|
12
|
+
const PROJECT_CONFIG_RELATIVE_PATH = path.join(".akm", "config.json");
|
|
13
|
+
function backupConfigFile(configPath) {
|
|
14
|
+
if (!fs.existsSync(configPath))
|
|
15
|
+
return;
|
|
16
|
+
const backupDir = path.join(getCacheDir(), "config-backups");
|
|
17
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
18
|
+
const timestamp = new Date().toISOString().replace(/[.:]/g, "-");
|
|
19
|
+
const backupPath = path.join(backupDir, `config-${timestamp}.json`);
|
|
20
|
+
fs.copyFileSync(configPath, backupPath);
|
|
21
|
+
const latestPath = path.join(backupDir, "config.latest.json");
|
|
22
|
+
fs.copyFileSync(configPath, latestPath);
|
|
23
|
+
}
|
|
24
|
+
function acquireMigrateLock(lockPath, noWait) {
|
|
25
|
+
const lockDir = path.dirname(lockPath);
|
|
26
|
+
fs.mkdirSync(lockDir, { recursive: true });
|
|
27
|
+
const maxAttempts = noWait ? 1 : 20;
|
|
28
|
+
const delayMs = 200;
|
|
29
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
30
|
+
try {
|
|
31
|
+
fs.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
32
|
+
return () => {
|
|
33
|
+
try {
|
|
34
|
+
fs.unlinkSync(lockPath);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// ignore
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
if (noWait) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
// Simple busy-wait — synchronous since this is a one-shot CLI action
|
|
46
|
+
const deadline = Date.now() + delayMs;
|
|
47
|
+
while (Date.now() < deadline) {
|
|
48
|
+
// spin
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
export async function migrateConfigFile(filePath, opts) {
|
|
55
|
+
if (!fs.existsSync(filePath)) {
|
|
56
|
+
return { changed: false, result: {} };
|
|
57
|
+
}
|
|
58
|
+
const text = fs.readFileSync(filePath, "utf8");
|
|
59
|
+
let raw;
|
|
60
|
+
try {
|
|
61
|
+
const stripped = stripJsonComments(text);
|
|
62
|
+
const parsed = JSON.parse(stripped);
|
|
63
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
64
|
+
warn(`[akm] config-migrate: ${filePath} is not a valid JSON object, skipping.`);
|
|
65
|
+
return { changed: false, result: {} };
|
|
66
|
+
}
|
|
67
|
+
raw = parsed;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
warn(`[akm] config-migrate: failed to parse ${filePath}, skipping.`);
|
|
71
|
+
return { changed: false, result: {} };
|
|
72
|
+
}
|
|
73
|
+
const { changed, result } = migrateConfigShape(raw);
|
|
74
|
+
if (!changed) {
|
|
75
|
+
return { changed: false, result };
|
|
76
|
+
}
|
|
77
|
+
const migratedText = `${JSON.stringify(result, null, 2)}\n`;
|
|
78
|
+
// WS-2: compute a diff when requested (always computed for --print-diff;
|
|
79
|
+
// never requires a write so safe in --dry-run).
|
|
80
|
+
const diff = opts.printDiff ? unifiedDiff(text, migratedText, filePath) : undefined;
|
|
81
|
+
if (opts.dryRun) {
|
|
82
|
+
return { changed: true, result, diff };
|
|
83
|
+
}
|
|
84
|
+
// WS-3: acquire config write lock + use atomic write (tmp → rename).
|
|
85
|
+
withConfigLock(() => {
|
|
86
|
+
backupConfigFile(filePath);
|
|
87
|
+
writeConfigAtomic(filePath, result);
|
|
88
|
+
});
|
|
89
|
+
return { changed: true, result, diff };
|
|
90
|
+
}
|
|
91
|
+
function discoverProjectConfigPaths(startDir) {
|
|
92
|
+
const paths = [];
|
|
93
|
+
let currentDir = path.resolve(startDir);
|
|
94
|
+
while (true) {
|
|
95
|
+
const configPath = path.join(currentDir, PROJECT_CONFIG_RELATIVE_PATH);
|
|
96
|
+
if (fs.existsSync(configPath) && fs.statSync(configPath).isFile()) {
|
|
97
|
+
paths.unshift(configPath);
|
|
98
|
+
}
|
|
99
|
+
const parentDir = path.dirname(currentDir);
|
|
100
|
+
if (parentDir === currentDir)
|
|
101
|
+
break;
|
|
102
|
+
currentDir = parentDir;
|
|
103
|
+
}
|
|
104
|
+
return paths;
|
|
105
|
+
}
|
|
106
|
+
export async function runConfigMigrate(opts) {
|
|
107
|
+
const userConfigPath = getConfigPath();
|
|
108
|
+
const projectPaths = discoverProjectConfigPaths(process.cwd());
|
|
109
|
+
const allPaths = [userConfigPath, ...projectPaths].filter((p, i, arr) => arr.indexOf(p) === i && fs.existsSync(p));
|
|
110
|
+
if (allPaths.length === 0) {
|
|
111
|
+
console.log("No config files found to migrate.");
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const lockPath = path.join(getCacheDir(), "config-migrate.lock");
|
|
115
|
+
const releaseLock = acquireMigrateLock(lockPath, opts.noWait ?? false);
|
|
116
|
+
if (!releaseLock) {
|
|
117
|
+
warn("[akm] config-migrate: another migration is already in progress, skipping.");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
let anyChanged = false;
|
|
122
|
+
for (const filePath of allPaths) {
|
|
123
|
+
const { changed, diff } = await migrateConfigFile(filePath, { dryRun: opts.dryRun, printDiff: opts.printDiff });
|
|
124
|
+
if (changed) {
|
|
125
|
+
const action = opts.dryRun ? "would migrate" : "migrated";
|
|
126
|
+
console.log(`[akm] ${action}: ${filePath}`);
|
|
127
|
+
// WS-2: print the unified diff to stdout when --print-diff is set.
|
|
128
|
+
if (diff) {
|
|
129
|
+
console.log(diff);
|
|
130
|
+
}
|
|
131
|
+
anyChanged = true;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(`[akm] already up to date: ${filePath}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (!anyChanged) {
|
|
138
|
+
console.log("All config files are already at the current version.");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
releaseLock();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* `akm config validate` — verify the on-disk config matches the schema.
|
|
6
|
+
*
|
|
7
|
+
* Reads the user config file, validates against AkmConfigSchema, and either
|
|
8
|
+
* prints "All checks passed." or a list of structured errors (path + message).
|
|
9
|
+
* Exits non-zero on errors so it composes well in CI hooks.
|
|
10
|
+
*/
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import { parseConfigText } from "../core/config-io";
|
|
13
|
+
import { validateConfigShape } from "../core/config-schema";
|
|
14
|
+
import { ConfigError } from "../core/errors";
|
|
15
|
+
import { getConfigPath } from "../core/paths";
|
|
16
|
+
export async function runConfigValidate() {
|
|
17
|
+
const configPath = getConfigPath();
|
|
18
|
+
if (!fs.existsSync(configPath)) {
|
|
19
|
+
console.log(`No config file at ${configPath} — nothing to validate.`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
let text;
|
|
23
|
+
try {
|
|
24
|
+
text = fs.readFileSync(configPath, "utf8");
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
28
|
+
throw new ConfigError(`Could not read config at ${configPath}: ${detail}`, "INVALID_CONFIG_FILE");
|
|
29
|
+
}
|
|
30
|
+
// parseConfigText throws ConfigError on malformed JSON (#458). Surface as-is.
|
|
31
|
+
const raw = parseConfigText(text, configPath);
|
|
32
|
+
const result = validateConfigShape(raw);
|
|
33
|
+
if (result.ok) {
|
|
34
|
+
console.log(`All checks passed. (${configPath})`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const lines = result.errors.map((e) => ` - ${e.path || "(root)"}: ${e.message}`).join("\n");
|
|
38
|
+
throw new ConfigError(`Config at ${configPath} has ${result.errors.length} validation error${result.errors.length === 1 ? "" : "s"}:\n${lines}`, "INVALID_CONFIG_FILE", "Fix the listed fields, or run `akm config migrate` if the errors look like legacy-shape leftovers.");
|
|
39
|
+
}
|