akm-cli 0.9.0-beta.6 → 0.9.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +663 -0
- package/README.md +12 -4
- package/dist/akm +38 -0
- package/dist/akm-migrate-storage +38 -0
- package/dist/assets/help/help-improve.md +9 -6
- package/dist/assets/hints/cli-hints-full.md +6 -5
- package/dist/assets/profiles/default.json +9 -4
- package/dist/assets/profiles/frequent.json +1 -1
- package/dist/assets/profiles/memory-focus.json +1 -1
- package/dist/assets/profiles/proactive-maintenance.json +25 -0
- package/dist/assets/profiles/quick.json +1 -1
- package/dist/assets/profiles/recombine-only.json +21 -0
- package/dist/assets/profiles/reflect-distill.json +30 -0
- package/dist/assets/profiles/synthesize.json +15 -0
- package/dist/assets/profiles/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +23 -0
- package/dist/assets/prompts/contradiction-judge.md +33 -0
- package/dist/assets/prompts/distill-knowledge-system.md +22 -0
- package/dist/assets/prompts/distill-lesson-system.md +36 -0
- package/dist/assets/prompts/extract-session.md +11 -3
- package/dist/assets/prompts/graph-extract-system.md +1 -0
- package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
- package/dist/assets/prompts/memory-infer-system.md +1 -0
- package/dist/assets/prompts/memory-infer-user.md +5 -0
- package/dist/assets/prompts/metadata-enhance-system.md +1 -0
- package/dist/assets/prompts/procedural-system.md +44 -0
- package/dist/assets/prompts/recombine-system.md +40 -0
- package/dist/assets/prompts/staleness-detect-system.md +6 -0
- package/dist/assets/prompts/validate-summary-judge.md +1 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
- package/dist/assets/templates/html/health.html +281 -111
- package/dist/assets/wiki/ingest-workflow-template.md +45 -16
- package/dist/assets/wiki/schema-template.md +4 -4
- package/dist/cli/clack.js +56 -0
- package/dist/cli/config-migrate.js +7 -1
- package/dist/cli/confirm.js +1 -1
- package/dist/cli/parse-args.js +46 -1
- package/dist/cli/shared.js +28 -0
- package/dist/cli.js +25 -14
- package/dist/commands/agent/agent-dispatch.js +3 -2
- package/dist/commands/agent/agent-support.js +0 -7
- package/dist/commands/agent/contribute-cli.js +26 -7
- package/dist/commands/config-cli.js +26 -13
- package/dist/commands/env/child-env.js +47 -0
- package/dist/commands/env/env-cli.js +220 -227
- package/dist/commands/env/env.js +14 -67
- package/dist/commands/env/secret-cli.js +140 -138
- package/dist/commands/feedback-cli.js +153 -147
- package/dist/commands/graph/graph-cli.js +5 -13
- package/dist/commands/graph/graph.js +76 -72
- package/dist/commands/health/advisories.js +151 -0
- package/dist/commands/health/checks.js +103 -16
- package/dist/commands/health/html-report.js +447 -81
- package/dist/commands/health/improve-metrics.js +771 -0
- package/dist/commands/health/llm-usage.js +65 -0
- package/dist/commands/health/md-report.js +103 -0
- package/dist/commands/health/metrics.js +278 -0
- package/dist/commands/health/stash-exposure.js +46 -0
- package/dist/commands/health/surfaces.js +216 -0
- package/dist/commands/health/task-runs.js +135 -0
- package/dist/commands/health/types.js +26 -0
- package/dist/commands/health/windows.js +195 -0
- package/dist/commands/health.js +91 -1083
- package/dist/commands/improve/anti-collapse.js +170 -0
- package/dist/commands/improve/calibration.js +161 -0
- package/dist/commands/improve/collapse-detector.js +421 -0
- package/dist/commands/improve/consolidate/chunking.js +141 -0
- package/dist/commands/improve/consolidate/eligibility.js +64 -0
- package/dist/commands/improve/consolidate/merge.js +145 -0
- package/dist/commands/improve/consolidate/sanitize.js +231 -0
- package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
- package/dist/commands/improve/consolidate.js +1313 -1278
- package/dist/commands/improve/dedup.js +482 -0
- package/dist/commands/improve/distill/content-repair.js +202 -0
- package/dist/commands/improve/distill/promote-memory.js +229 -0
- package/dist/commands/improve/distill/quality-gate.js +236 -0
- package/dist/commands/improve/distill-guards.js +127 -0
- package/dist/commands/improve/distill-promotion-policy.js +826 -167
- package/dist/commands/improve/distill.js +243 -599
- package/dist/commands/improve/eligibility.js +434 -0
- package/dist/commands/improve/encoding-salience.js +205 -0
- package/dist/commands/improve/extract-cli.js +179 -59
- package/dist/commands/improve/extract-prompt.js +55 -4
- package/dist/commands/improve/extract-watch.js +140 -0
- package/dist/commands/improve/extract.js +409 -43
- package/dist/commands/improve/feedback-valence.js +54 -0
- package/dist/commands/improve/hot-probation.js +45 -0
- package/dist/commands/improve/improve-auto-accept.js +160 -7
- package/dist/commands/improve/improve-cli.js +115 -73
- package/dist/commands/improve/improve-profiles.js +32 -8
- package/dist/commands/improve/improve-result-file.js +15 -25
- package/dist/commands/improve/improve-session.js +58 -0
- package/dist/commands/improve/improve.js +510 -2537
- package/dist/commands/improve/locks.js +154 -0
- package/dist/commands/improve/loop-stages.js +1100 -0
- package/dist/commands/improve/memory/memory-belief.js +14 -15
- package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
- package/dist/commands/improve/memory/memory-improve.js +27 -27
- package/dist/commands/improve/outcome-loop.js +270 -0
- package/dist/commands/improve/preparation.js +2002 -0
- package/dist/commands/improve/proactive-maintenance.js +115 -0
- package/dist/commands/improve/procedural.js +398 -0
- package/dist/commands/improve/recombine.js +818 -0
- package/dist/commands/improve/reflect-noise.js +0 -0
- package/dist/commands/improve/reflect.js +212 -45
- package/dist/commands/improve/salience.js +455 -0
- package/dist/commands/improve/schema-similarity-gate.js +168 -0
- package/dist/commands/improve/shared.js +51 -0
- package/dist/commands/improve/triage.js +93 -0
- package/dist/commands/lint/agent-linter.js +19 -24
- package/dist/commands/lint/base-linter.js +173 -60
- package/dist/commands/lint/command-linter.js +19 -24
- package/dist/commands/lint/env-key-rules.js +38 -1
- package/dist/commands/lint/fact-linter.js +39 -0
- package/dist/commands/lint/index.js +31 -13
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +7 -2
- package/dist/commands/lint/task-linter.js +3 -3
- package/dist/commands/lint/workflow-linter.js +26 -1
- package/dist/commands/observability-cli.js +4 -4
- package/dist/commands/proposal/drain-policies.js +13 -4
- package/dist/commands/proposal/drain.js +45 -51
- package/dist/commands/proposal/legacy-import.js +115 -0
- package/dist/commands/proposal/proposal-cli.js +24 -34
- package/dist/commands/proposal/proposal.js +7 -1
- package/dist/commands/proposal/propose.js +8 -3
- package/dist/commands/proposal/repository.js +829 -0
- package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
- package/dist/commands/proposal/validators/proposals.js +93 -882
- package/dist/commands/read/curate.js +419 -103
- package/dist/commands/read/knowledge.js +10 -3
- package/dist/commands/read/remember-cli.js +133 -138
- package/dist/commands/read/search-cli.js +15 -8
- package/dist/commands/read/search.js +22 -11
- package/dist/commands/read/show.js +106 -14
- package/dist/commands/registry-cli.js +76 -87
- package/dist/commands/remember.js +11 -12
- package/dist/commands/sources/add-cli.js +91 -95
- package/dist/commands/sources/history.js +1 -1
- package/dist/commands/sources/init.js +66 -18
- package/dist/commands/sources/installed-stashes.js +11 -3
- package/dist/commands/sources/schema-repair.js +44 -46
- package/dist/commands/sources/self-update.js +2 -2
- package/dist/commands/sources/source-add.js +7 -3
- package/dist/commands/sources/sources-cli.js +3 -3
- package/dist/commands/sources/stash-cli.js +29 -41
- package/dist/commands/sources/stash-skeleton.js +57 -8
- package/dist/commands/tasks/default-tasks.js +15 -2
- package/dist/commands/tasks/tasks-cli.js +20 -29
- package/dist/commands/tasks/tasks.js +39 -11
- package/dist/commands/wiki-cli.js +23 -38
- package/dist/commands/workflow-cli.js +15 -1
- package/dist/core/asset/asset-registry.js +3 -1
- package/dist/core/asset/asset-spec.js +21 -4
- package/dist/core/asset/frontmatter.js +188 -167
- package/dist/core/asset/markdown.js +8 -0
- package/dist/core/authoring-rules.js +92 -0
- package/dist/core/common.js +4 -23
- package/dist/core/concurrent.js +10 -1
- package/dist/core/config/config-io.js +10 -1
- package/dist/core/config/config-migration.js +18 -40
- package/dist/core/config/config-schema.js +389 -58
- package/dist/core/config/config-types.js +3 -3
- package/dist/core/config/config.js +67 -22
- package/dist/core/deep-merge.js +38 -0
- package/dist/core/errors.js +1 -0
- package/dist/core/eval/rank-metrics.js +113 -0
- package/dist/core/events.js +4 -7
- package/dist/core/improve-types.js +47 -8
- package/dist/core/logs-db.js +14 -75
- package/dist/core/parse.js +36 -16
- package/dist/core/paths.js +21 -18
- package/dist/core/standards/resolve-standards-context.js +87 -0
- package/dist/core/standards/resolve-stash-standards.js +99 -0
- package/dist/core/standards/resolve-type-conventions.js +66 -0
- package/dist/core/state/migrations.js +770 -0
- package/dist/core/state-db.js +142 -1091
- package/dist/core/structured.js +69 -0
- package/dist/core/time.js +53 -0
- package/dist/core/warn.js +21 -0
- package/dist/core/write-source.js +37 -0
- package/dist/indexer/db/db.js +356 -780
- package/dist/indexer/db/entry-mapper.js +41 -0
- package/dist/indexer/db/graph-db.js +129 -86
- package/dist/indexer/db/llm-cache.js +2 -2
- package/dist/indexer/db/schema.js +516 -0
- package/dist/indexer/ensure-index.js +103 -24
- package/dist/indexer/feedback/utility-policy.js +75 -0
- package/dist/indexer/graph/graph-boost.js +51 -41
- package/dist/indexer/graph/graph-extraction.js +207 -4
- package/dist/indexer/index-writer-lock.js +106 -0
- package/dist/indexer/index-written-assets.js +105 -0
- package/dist/indexer/indexer.js +291 -310
- package/dist/indexer/passes/dir-staleness.js +114 -0
- package/dist/indexer/passes/memory-inference.js +13 -5
- package/dist/indexer/passes/metadata.js +20 -0
- package/dist/indexer/read-preflight.js +23 -0
- package/dist/indexer/search/db-search.js +89 -13
- package/dist/indexer/search/fts-query.js +51 -0
- package/dist/indexer/search/ranking-contributors.js +95 -9
- package/dist/indexer/search/ranking.js +79 -3
- package/dist/indexer/search/search-fields.js +6 -0
- package/dist/indexer/search/search-source.js +32 -21
- package/dist/indexer/search/semantic-status.js +4 -0
- package/dist/indexer/walk/matchers.js +9 -0
- package/dist/indexer/walk/walker.js +21 -13
- package/dist/integrations/agent/builders.js +39 -13
- package/dist/integrations/agent/config.js +20 -59
- package/dist/integrations/agent/detect.js +9 -0
- package/dist/integrations/agent/index.js +3 -19
- package/dist/integrations/agent/model-aliases.js +7 -2
- package/dist/integrations/agent/profiles.js +7 -1
- package/dist/integrations/agent/prompts.js +75 -9
- package/dist/integrations/agent/runner-dispatch.js +59 -0
- package/dist/integrations/agent/runner.js +13 -9
- package/dist/integrations/agent/spawn.js +69 -67
- package/dist/integrations/harnesses/claude/agent-builder.js +1 -1
- package/dist/integrations/harnesses/claude/index.js +2 -0
- package/dist/integrations/harnesses/claude/session-log.js +11 -1
- package/dist/integrations/harnesses/index.js +2 -3
- package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
- package/dist/integrations/harnesses/opencode/index.js +2 -0
- package/dist/integrations/harnesses/opencode/session-log.js +173 -3
- package/dist/integrations/harnesses/opencode-sdk/index.js +2 -2
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +98 -17
- package/dist/integrations/harnesses/types.js +1 -0
- package/dist/integrations/session-logs/index.js +16 -0
- package/dist/llm/call-ai.js +2 -2
- package/dist/llm/client.js +57 -15
- package/dist/llm/embedder.js +67 -4
- package/dist/llm/embedders/cache.js +3 -1
- package/dist/llm/embedders/deterministic.js +66 -0
- package/dist/llm/embedders/local.js +73 -3
- package/dist/llm/feature-gate.js +16 -15
- package/dist/llm/graph-extract.js +67 -44
- package/dist/llm/memory-infer-impl.js +138 -0
- package/dist/llm/memory-infer.js +1 -127
- package/dist/llm/metadata-enhance.js +44 -31
- package/dist/llm/structured-call.js +49 -0
- package/dist/migrate-storage-node.mjs +8 -0
- package/dist/output/context.js +5 -5
- package/dist/output/renderers.js +85 -14
- package/dist/output/shapes/curate.js +14 -2
- package/dist/output/shapes/helpers.js +0 -3
- package/dist/output/shapes/passthrough.js +2 -1
- package/dist/output/text/helpers.js +29 -1
- package/dist/output/text/workflow.js +1 -0
- package/dist/registry/providers/skills-sh.js +21 -147
- package/dist/registry/providers/static-index.js +15 -157
- package/dist/registry/resolve.js +27 -9
- package/dist/runtime.js +25 -1
- package/dist/scripts/migrate-storage.js +2718 -2354
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +891 -597
- package/dist/setup/detect.js +9 -0
- package/dist/setup/legacy-config.js +106 -0
- package/dist/setup/prompt.js +57 -0
- package/dist/setup/providers.js +14 -0
- package/dist/setup/registry-stash-loader.js +12 -0
- package/dist/setup/semantic-assets.js +124 -0
- package/dist/setup/setup.js +52 -1614
- package/dist/setup/steps/connection.js +734 -0
- package/dist/setup/steps/output.js +31 -0
- package/dist/setup/steps/platforms.js +124 -0
- package/dist/setup/steps/semantic.js +27 -0
- package/dist/setup/steps/sources.js +222 -0
- package/dist/setup/steps/stashdir.js +42 -0
- package/dist/setup/steps/tasks.js +152 -0
- package/dist/sources/include.js +6 -2
- package/dist/sources/providers/filesystem.js +0 -1
- package/dist/sources/providers/git-install.js +210 -0
- package/dist/sources/providers/git-provider.js +234 -0
- package/dist/sources/providers/git-stash.js +248 -0
- package/dist/sources/providers/git.js +10 -661
- package/dist/sources/providers/npm.js +2 -6
- package/dist/sources/providers/provider-utils.js +13 -7
- package/dist/sources/providers/sync-from-ref.js +9 -1
- package/dist/sources/providers/tar-utils.js +16 -8
- package/dist/sources/providers/website.js +9 -5
- package/dist/sources/website-ingest.js +187 -29
- package/dist/sources/wiki-fetchers/registry.js +53 -0
- package/dist/sources/wiki-fetchers/youtube.js +239 -0
- package/dist/storage/database.js +45 -10
- package/dist/storage/managed-db.js +82 -0
- package/dist/storage/repositories/canaries-repository.js +107 -0
- package/dist/storage/repositories/consolidation-repository.js +38 -0
- package/dist/storage/repositories/embeddings-repository.js +72 -0
- package/dist/storage/repositories/events-repository.js +187 -0
- package/dist/storage/repositories/extract-sessions-repository.js +96 -0
- package/dist/storage/repositories/improve-runs-repository.js +146 -0
- package/dist/storage/repositories/index-db.js +14 -8
- package/dist/storage/repositories/proposals-repository.js +220 -0
- package/dist/storage/repositories/recombine-repository.js +213 -0
- package/dist/storage/repositories/registry-cache.js +93 -0
- package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
- package/dist/storage/repositories/task-history-repository.js +93 -0
- package/dist/storage/sqlite-pragmas.js +146 -0
- package/dist/tasks/backends/cron.js +1 -1
- package/dist/tasks/backends/index.js +9 -0
- package/dist/tasks/backends/launchd.js +1 -1
- package/dist/tasks/backends/schtasks.js +1 -1
- package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
- package/dist/tasks/runner.js +15 -13
- package/dist/text-import-hook.mjs +0 -0
- package/dist/wiki/wiki.js +52 -11
- package/dist/workflows/cli.js +1 -0
- package/dist/workflows/db.js +3 -4
- package/dist/workflows/runtime/runs.js +43 -118
- package/dist/workflows/runtime/workflow-asset-loader.js +125 -0
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/README.md +69 -18
- package/docs/data-and-telemetry.md +5 -4
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +39 -0
- package/package.json +10 -10
- package/dist/assets/tasks/core/update-stashes.yml +0 -4
- package/dist/commands/db-cli.js +0 -23
- package/dist/indexer/db/db-backup.js +0 -376
- package/dist/indexer/passes/staleness-detect.js +0 -488
|
@@ -6,23 +6,50 @@ Schema: {{SCHEMA_PATH}}
|
|
|
6
6
|
Follow these steps. akm commands handle the invariants; use your native
|
|
7
7
|
Read/Write/Edit tools for page edits.
|
|
8
8
|
|
|
9
|
+
This workflow is for ingesting sources that are ALREADY present under
|
|
10
|
+
`{{WIKI_DIR}}/raw/`. Do not ask the user for a source unless the raw queue is
|
|
11
|
+
empty and the caller explicitly asked for interactive ingest.
|
|
12
|
+
|
|
9
13
|
1. **Read the schema.** Open `{{SCHEMA_PATH}}`. It defines the voice, page
|
|
10
14
|
kinds, contradiction policy, and any wiki-specific conventions. Do not
|
|
11
15
|
skip this step even on familiar wikis — the schema may have changed.
|
|
12
16
|
|
|
13
|
-
2. **
|
|
17
|
+
2. **Discover the pending raw queue.**
|
|
14
18
|
```sh
|
|
15
|
-
akm wiki
|
|
16
|
-
# or: cat <source> | akm wiki stash {{WIKI_NAME}} -
|
|
19
|
+
akm wiki lint {{WIKI_NAME}}
|
|
17
20
|
```
|
|
18
|
-
|
|
21
|
+
Focus on `uncited-raw` findings: those raw files exist under `raw/` but are
|
|
22
|
+
not yet cited by any authored page. Treat each `uncited-raw` finding as a
|
|
23
|
+
pending ingest item, and sort the queue **oldest raw file first** (by
|
|
24
|
+
filename/mtime). Processing oldest-first keeps backlog age bounded even
|
|
25
|
+
when the queue is larger than one run can finish. If there are no
|
|
26
|
+
`uncited-raw` findings, exit cleanly after a final `akm index` +
|
|
27
|
+
`akm wiki lint {{WIKI_NAME}}` verification.
|
|
28
|
+
|
|
29
|
+
Do not read or classify the whole backlog upfront. Work the queue as a
|
|
30
|
+
bounded loop, one raw file at a time: fully finish a raw (read → decide →
|
|
31
|
+
edit → log entry, steps 3-7 below) before looking at the next one. If you
|
|
32
|
+
run low on time partway through a large backlog, stop after finishing your
|
|
33
|
+
current raw — do not start a new one you can't complete. This is expected
|
|
34
|
+
and fine: whatever you already merged is committed to the pages and
|
|
35
|
+
`log.md`, so the next scheduled run picks up where you left off instead of
|
|
36
|
+
redoing this run's work.
|
|
37
|
+
|
|
38
|
+
3. **For the current raw file, read the source and find related pages.**
|
|
39
|
+
Open the raw file directly from `{{WIKI_DIR}}/raw/`.
|
|
40
|
+
|
|
41
|
+
If the file does not read as text (binary content, garbled bytes, e.g. a
|
|
42
|
+
raw PDF byte-dump that was never text-extracted), do not attempt deep
|
|
43
|
+
forensic recovery (no web searches, no `strings`-style dumps). Append a
|
|
44
|
+
one-line `log.md` entry noting it as skipped/unprocessable with a short
|
|
45
|
+
reason, then move on to the next raw in the queue.
|
|
19
46
|
|
|
20
|
-
|
|
47
|
+
Otherwise, search for related pages:
|
|
21
48
|
```sh
|
|
22
|
-
akm wiki search {{WIKI_NAME}} "<key terms from the source>"
|
|
49
|
+
akm wiki search {{WIKI_NAME}} "<key terms from the raw source>"
|
|
23
50
|
```
|
|
24
|
-
Read the top hits with `akm show wiki:{{WIKI_NAME}}/<page>`. Use
|
|
25
|
-
`akm show wiki:{{WIKI_NAME}}/<page> toc` for large pages.
|
|
51
|
+
Read the top hits with `akm show wiki:{{WIKI_NAME}}/pages/<page>`. Use
|
|
52
|
+
`akm show wiki:{{WIKI_NAME}}/pages/<page> toc` for large pages.
|
|
26
53
|
|
|
27
54
|
4. **Decide for each candidate.** For each related page:
|
|
28
55
|
- **Append**: add a section or paragraph under the relevant heading.
|
|
@@ -31,16 +58,18 @@ Read/Write/Edit tools for page edits.
|
|
|
31
58
|
Follow the schema's contradiction policy.
|
|
32
59
|
- **Skip**: source doesn't add to this page — move on.
|
|
33
60
|
|
|
34
|
-
5. **Create new pages for concepts/entities the source introduces
|
|
35
|
-
|
|
36
|
-
`
|
|
37
|
-
|
|
61
|
+
5. **Create new pages for concepts/entities the source introduces**, under
|
|
62
|
+
`{{WIKI_DIR}}/pages/` (never at the wiki root — only `schema.md`,
|
|
63
|
+
`index.md`, and `log.md` belong there). Each new page must have
|
|
64
|
+
frontmatter with `description`, `pageKind`, `xrefs`, and `sources`.
|
|
65
|
+
Cross-reference with related pages both directions.
|
|
38
66
|
|
|
39
67
|
6. **Update xrefs both ways.** If page A now xrefs page B, page B must xref
|
|
40
68
|
page A. `akm wiki lint {{WIKI_NAME}}` will flag violations.
|
|
41
69
|
|
|
42
|
-
7. **Append to `log.md`.** One entry per
|
|
43
|
-
|
|
70
|
+
7. **Append to `log.md`.** One entry per processed raw source (ingested or
|
|
71
|
+
skipped-as-unprocessable): date, raw slug, one-line summary, refs to
|
|
72
|
+
created/edited pages. Newest at the top.
|
|
44
73
|
|
|
45
74
|
8. **Regenerate the index + verify.**
|
|
46
75
|
```sh
|
|
@@ -50,5 +79,5 @@ Read/Write/Edit tools for page edits.
|
|
|
50
79
|
Resolve any lint findings before calling the ingest done.
|
|
51
80
|
|
|
52
81
|
That's it. `akm` never calls an LLM — reasoning is your job; it just owns
|
|
53
|
-
the invariants (raw immutability,
|
|
54
|
-
|
|
82
|
+
the invariants (raw immutability, ref validation, index regeneration,
|
|
83
|
+
structural lint).
|
|
@@ -8,7 +8,7 @@ wikiRole: schema
|
|
|
8
8
|
This wiki follows the three-layer pattern:
|
|
9
9
|
|
|
10
10
|
- `raw/` — immutable ingested sources (never edit)
|
|
11
|
-
-
|
|
11
|
+
- `pages/<page>.md` and `pages/<topic>/<page>.md` — agent-authored pages
|
|
12
12
|
- `schema.md` (this file), `index.md`, `log.md` — wiki-level metadata
|
|
13
13
|
|
|
14
14
|
## Page frontmatter
|
|
@@ -20,7 +20,7 @@ Every page should carry frontmatter so akm can index and link it:
|
|
|
20
20
|
description: one-sentence summary used in search and lint
|
|
21
21
|
pageKind: entity | concept | question | note | <your-custom-kind>
|
|
22
22
|
xrefs:
|
|
23
|
-
- wiki:{{WIKI_NAME}}/other-page
|
|
23
|
+
- wiki:{{WIKI_NAME}}/pages/other-page
|
|
24
24
|
sources:
|
|
25
25
|
- raw/<slug>.md
|
|
26
26
|
---
|
|
@@ -36,14 +36,14 @@ will surface in `index.md` as new sections after the next `akm index` run.
|
|
|
36
36
|
1. Copy the new source into `raw/` with `akm wiki stash {{WIKI_NAME}} <path>`.
|
|
37
37
|
2. Find related pages: `akm wiki search {{WIKI_NAME}} "<terms>"`.
|
|
38
38
|
3. For each related page: append a section, note a contradiction, or create a
|
|
39
|
-
new page
|
|
39
|
+
new page under `pages/`. Update xrefs on both sides.
|
|
40
40
|
4. Cite the raw source in each touched page's `sources:` frontmatter.
|
|
41
41
|
5. Append one entry to `log.md` describing what was assimilated.
|
|
42
42
|
|
|
43
43
|
### Query
|
|
44
44
|
|
|
45
45
|
1. `akm wiki search {{WIKI_NAME}} "<question>"` — find candidate pages.
|
|
46
|
-
2. `akm show wiki:{{WIKI_NAME}}/<page>` — read the top hits.
|
|
46
|
+
2. `akm show wiki:{{WIKI_NAME}}/pages/<page>` — read the top hits.
|
|
47
47
|
3. Compose the answer from the wiki; cite raw sources only when the wiki
|
|
48
48
|
points at them.
|
|
49
49
|
|
|
@@ -0,0 +1,56 @@
|
|
|
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 { cancel as realCancel, confirm as realConfirm, intro as realIntro, isCancel as realIsCancel, log as realLog, multiselect as realMultiselect, note as realNote, outro as realOutro, select as realSelect, spinner as realSpinner, text as realText, } from "@clack/prompts";
|
|
5
|
+
// ── Test seam ────────────────────────────────────────────────────────────────
|
|
6
|
+
// Swap-and-restore override. Inert in production; only tests call the setter
|
|
7
|
+
// (via tests/_helpers/seams.ts `overrideSeam`, never directly).
|
|
8
|
+
let clackFake;
|
|
9
|
+
/** TEST-ONLY. Swap the clack prompt surface; pass undefined to restore. */
|
|
10
|
+
export function _setClackForTests(fake) {
|
|
11
|
+
clackFake = fake;
|
|
12
|
+
}
|
|
13
|
+
const realFns = {
|
|
14
|
+
intro: realIntro,
|
|
15
|
+
outro: realOutro,
|
|
16
|
+
cancel: realCancel,
|
|
17
|
+
confirm: realConfirm,
|
|
18
|
+
select: realSelect,
|
|
19
|
+
multiselect: realMultiselect,
|
|
20
|
+
text: realText,
|
|
21
|
+
spinner: realSpinner,
|
|
22
|
+
note: realNote,
|
|
23
|
+
isCancel: realIsCancel,
|
|
24
|
+
};
|
|
25
|
+
/** Delegator with the real export's exact type; reads the fake at call time. */
|
|
26
|
+
function bind(name) {
|
|
27
|
+
return ((...args) => {
|
|
28
|
+
const impl = (clackFake?.[name] ?? realFns[name]);
|
|
29
|
+
return impl(...args);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function bindLog(name) {
|
|
33
|
+
return ((...args) => {
|
|
34
|
+
const impl = (clackFake?.log?.[name] ?? realLog[name]);
|
|
35
|
+
return impl(...args);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export const intro = bind("intro");
|
|
39
|
+
export const outro = bind("outro");
|
|
40
|
+
export const cancel = bind("cancel");
|
|
41
|
+
export const confirm = bind("confirm");
|
|
42
|
+
export const select = bind("select");
|
|
43
|
+
export const multiselect = bind("multiselect");
|
|
44
|
+
export const text = bind("text");
|
|
45
|
+
export const spinner = bind("spinner");
|
|
46
|
+
export const note = bind("note");
|
|
47
|
+
export const isCancel = bind("isCancel");
|
|
48
|
+
export const log = {
|
|
49
|
+
message: bindLog("message"),
|
|
50
|
+
info: bindLog("info"),
|
|
51
|
+
success: bindLog("success"),
|
|
52
|
+
step: bindLog("step"),
|
|
53
|
+
warn: bindLog("warn"),
|
|
54
|
+
warning: bindLog("warning"),
|
|
55
|
+
error: bindLog("error"),
|
|
56
|
+
};
|
|
@@ -14,12 +14,18 @@ function backupConfigFile(configPath) {
|
|
|
14
14
|
if (!fs.existsSync(configPath))
|
|
15
15
|
return;
|
|
16
16
|
const backupDir = path.join(getCacheDir(), "config-backups");
|
|
17
|
-
|
|
17
|
+
// 08-F4: lock the backup dir owner-only (0700) — see config-io.ts.
|
|
18
|
+
fs.mkdirSync(backupDir, { recursive: true, mode: 0o700 });
|
|
19
|
+
fs.chmodSync(backupDir, 0o700);
|
|
18
20
|
const timestamp = new Date().toISOString().replace(/[.:]/g, "-");
|
|
19
21
|
const backupPath = path.join(backupDir, `config-${timestamp}.json`);
|
|
20
22
|
fs.copyFileSync(configPath, backupPath);
|
|
21
23
|
const latestPath = path.join(backupDir, "config.latest.json");
|
|
22
24
|
fs.copyFileSync(configPath, latestPath);
|
|
25
|
+
// 08-F4: config backups can carry secrets (endpoints/tokens) — keep them
|
|
26
|
+
// owner-only rather than inheriting the source file's (often 0644) mode.
|
|
27
|
+
fs.chmodSync(backupPath, 0o600);
|
|
28
|
+
fs.chmodSync(latestPath, 0o600);
|
|
23
29
|
}
|
|
24
30
|
function acquireMigrateLock(lockPath, noWait) {
|
|
25
31
|
const lockDir = path.dirname(lockPath);
|
package/dist/cli/confirm.js
CHANGED
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
* `--quiet` NEVER suppresses the confirmation prompt — it is safety-critical
|
|
36
36
|
* output. The auto-migration banner is similarly exempt from `--quiet`.
|
|
37
37
|
*/
|
|
38
|
-
import * as p from "@clack/prompts";
|
|
39
38
|
import { UsageError } from "../core/errors.js";
|
|
39
|
+
import * as p from "./clack.js";
|
|
40
40
|
/**
|
|
41
41
|
* Prompt the user to confirm a destructive action.
|
|
42
42
|
*
|
package/dist/cli/parse-args.js
CHANGED
|
@@ -8,7 +8,52 @@
|
|
|
8
8
|
* main CLI file focused on command definitions and routing.
|
|
9
9
|
*/
|
|
10
10
|
import { UsageError } from "../core/errors.js";
|
|
11
|
-
|
|
11
|
+
function cittyComparableName(name) {
|
|
12
|
+
return name.replace(/[-_]+([a-zA-Z0-9])/g, (_match, char) => char.toUpperCase());
|
|
13
|
+
}
|
|
14
|
+
function toAliasArray(alias) {
|
|
15
|
+
if (Array.isArray(alias))
|
|
16
|
+
return alias;
|
|
17
|
+
return typeof alias === "string" ? [alias] : [];
|
|
18
|
+
}
|
|
19
|
+
function isCittyValueFlag(flag, argsDef) {
|
|
20
|
+
const name = flag.replace(/^-{1,2}/, "");
|
|
21
|
+
const normalized = cittyComparableName(name);
|
|
22
|
+
for (const [key, def] of Object.entries(argsDef)) {
|
|
23
|
+
if (def.type !== "string" && def.type !== "enum")
|
|
24
|
+
continue;
|
|
25
|
+
if (normalized === cittyComparableName(key))
|
|
26
|
+
return true;
|
|
27
|
+
if (toAliasArray(def.alias).includes(name))
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Match citty's top-level subcommand scan (`findSubCommandIndex`).
|
|
34
|
+
*
|
|
35
|
+
* Citty does not assume `rawArgs[0]` is the command: global string flags may
|
|
36
|
+
* appear first and consume the following token. The CLI startup guard uses this
|
|
37
|
+
* to classify the requested command before any command handler can run.
|
|
38
|
+
*/
|
|
39
|
+
export function findCittyTopLevelCommandIndex(rawArgs, argsDef) {
|
|
40
|
+
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
41
|
+
const arg = rawArgs[i];
|
|
42
|
+
if (arg === "--")
|
|
43
|
+
return -1;
|
|
44
|
+
if (arg.startsWith("-")) {
|
|
45
|
+
if (!arg.includes("=") && isCittyValueFlag(arg, argsDef))
|
|
46
|
+
i += 1;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
return i;
|
|
50
|
+
}
|
|
51
|
+
return -1;
|
|
52
|
+
}
|
|
53
|
+
export function findCittyTopLevelCommand(rawArgs, argsDef) {
|
|
54
|
+
const index = findCittyTopLevelCommandIndex(rawArgs, argsDef);
|
|
55
|
+
return index >= 0 ? rawArgs[index] : undefined;
|
|
56
|
+
}
|
|
12
57
|
/**
|
|
13
58
|
* Return true when `args._[0]` is a member of `validSet`.
|
|
14
59
|
*
|
package/dist/cli/shared.js
CHANGED
|
@@ -15,6 +15,7 @@ import { getOutputMode } from "../output/context.js";
|
|
|
15
15
|
import { DEFAULT_TEMPLATE, deliverRendered, escapeHtml, renderHtml, resolveTemplatePath } from "../output/html-render.js";
|
|
16
16
|
import { shapeForCommand } from "../output/shapes.js";
|
|
17
17
|
import { formatPlain, outputJsonl } from "../output/text.js";
|
|
18
|
+
import { hasSubcommand } from "./parse-args.js";
|
|
18
19
|
// ── Exit codes ───────────────────────────────────────────────────────────────
|
|
19
20
|
/**
|
|
20
21
|
* Canonical process exit-code table for the akm CLI. Single source of truth —
|
|
@@ -111,6 +112,33 @@ export function defineJsonCommand(def) {
|
|
|
111
112
|
run: (context) => runWithJsonErrors(() => run(context)),
|
|
112
113
|
});
|
|
113
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Define a citty subcommand-group command (env, secret, proposal, tasks, wiki,
|
|
117
|
+
* graph, …) that shares one wiring shape: a `subCommands` map, a routing set
|
|
118
|
+
* DERIVED from that map's keys (so the set can never silently desync from the
|
|
119
|
+
* registered subcommands), and a default body that fires ONLY for the bare
|
|
120
|
+
* group invocation — citty still runs the group body after dispatching a
|
|
121
|
+
* subcommand, so the shared guard short-circuits when `args._[0]` names a
|
|
122
|
+
* registered subcommand.
|
|
123
|
+
*
|
|
124
|
+
* The `defaultRun` body is wrapped in `runWithJsonErrors`, so it emits a
|
|
125
|
+
* byte-identical JSON error envelope on throw — exactly the per-site
|
|
126
|
+
* `run() { return runWithJsonErrors(() => { if (hasSubcommand(...)) return; … }); }`
|
|
127
|
+
* boilerplate this replaces.
|
|
128
|
+
*/
|
|
129
|
+
export function defineGroupCommand(def) {
|
|
130
|
+
const subcommandSet = new Set(Object.keys(def.subCommands));
|
|
131
|
+
return defineCommand({
|
|
132
|
+
meta: def.meta,
|
|
133
|
+
...(def.args ? { args: def.args } : {}),
|
|
134
|
+
subCommands: def.subCommands,
|
|
135
|
+
run: (context) => runWithJsonErrors(() => {
|
|
136
|
+
if (hasSubcommand(context.args, subcommandSet))
|
|
137
|
+
return;
|
|
138
|
+
return def.defaultRun(context);
|
|
139
|
+
}),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
114
142
|
/**
|
|
115
143
|
* Render a command result according to the active output mode
|
|
116
144
|
* (json/jsonl/yaml/text/md/html). When `--output <path>` is set, the rendered
|
package/dist/cli.js
CHANGED
|
@@ -8,18 +8,21 @@
|
|
|
8
8
|
// `dist/cli-node.mjs` wrapper, which registers the text-import loader hook
|
|
9
9
|
// before this module graph loads; running `node dist/cli.js` directly still
|
|
10
10
|
// works for code paths that touch no embedded text asset, but the wrapper is
|
|
11
|
-
// the supported entry. The hard floor is Node 20: `@clack/core` (prompts) imports
|
|
11
|
+
// the supported entry. The hard floor is Node 20.12: `@clack/core` (prompts) imports
|
|
12
12
|
// `node:util`'s `styleText` (added in Node 20.12) — Node 18 (EOL) throws at import.
|
|
13
13
|
{
|
|
14
14
|
const isBun = typeof globalThis.Bun !== "undefined";
|
|
15
15
|
if (!isBun) {
|
|
16
|
-
const major =
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const [major = 0, minor = 0, patch = 0] = (process.versions.node ?? "0")
|
|
17
|
+
.split(".")
|
|
18
|
+
.map((part) => Number.parseInt(part, 10) || 0);
|
|
19
|
+
const nodeOk = major > 20 || (major === 20 && (minor > 12 || (minor === 12 && patch >= 0)));
|
|
20
|
+
if (!nodeOk) {
|
|
21
|
+
console.error("\n ERROR: akm-cli requires the Bun runtime (https://bun.sh) or Node.js >= 20.12.\n" +
|
|
19
22
|
` Detected Node.js ${process.versions.node ?? "unknown"}.\n` +
|
|
20
23
|
" Install options:\n" +
|
|
21
24
|
" 1. Bun: curl -fsSL https://bun.sh/install | bash && bun install -g akm-cli\n" +
|
|
22
|
-
" 2. Node: upgrade to Node.js 20 or newer (https://nodejs.org)\n" +
|
|
25
|
+
" 2. Node: upgrade to Node.js 20.12 or newer (https://nodejs.org)\n" +
|
|
23
26
|
" 3. Binary: curl -fsSL https://github.com/itlackey/akm/releases/latest/download/install.sh | bash\n");
|
|
24
27
|
process.exit(1);
|
|
25
28
|
}
|
|
@@ -57,6 +60,7 @@ process.on("uncaughtException", (err) => {
|
|
|
57
60
|
import fs from "node:fs";
|
|
58
61
|
import path from "node:path";
|
|
59
62
|
import { defineCommand, runMain } from "citty";
|
|
63
|
+
import { findCittyTopLevelCommand } from "./cli/parse-args.js";
|
|
60
64
|
import { EXIT_CODES, emitJsonError, output, parseAllFlagValues, runWithJsonErrors } from "./cli/shared.js";
|
|
61
65
|
import { agentCommand, lintCommand, proposeCommand } from "./commands/agent/contribute-cli.js";
|
|
62
66
|
import { generateBashCompletions, installBashCompletions } from "./commands/completions.js";
|
|
@@ -65,7 +69,9 @@ import { envCommand } from "./commands/env/env-cli.js";
|
|
|
65
69
|
import { secretCommand } from "./commands/env/secret-cli.js";
|
|
66
70
|
import { feedbackCommand } from "./commands/feedback-cli.js";
|
|
67
71
|
import { graphCommand } from "./commands/graph/graph-cli.js";
|
|
68
|
-
import { akmHealth
|
|
72
|
+
import { akmHealth } from "./commands/health.js";
|
|
73
|
+
import { renderRunsDetailMd, renderWindowCompareMd } from "./commands/health/md-report.js";
|
|
74
|
+
import { parseWindowSpec } from "./commands/health/windows.js";
|
|
69
75
|
import { extractCommand } from "./commands/improve/extract-cli.js";
|
|
70
76
|
import { improveCommand } from "./commands/improve/improve-cli.js";
|
|
71
77
|
import { hintsCommand, lessonsCommand, logCommand } from "./commands/observability-cli.js";
|
|
@@ -77,7 +83,7 @@ import { registryCommand } from "./commands/registry-cli.js";
|
|
|
77
83
|
import { addCommand } from "./commands/sources/add-cli.js";
|
|
78
84
|
import { renderMigrationHelp } from "./commands/sources/migration-help.js";
|
|
79
85
|
import { cloneCommand, historyCommand, listCommand, removeCommand, syncCommand, updateCommand, upgradeCommand, } from "./commands/sources/sources-cli.js";
|
|
80
|
-
import {
|
|
86
|
+
import { importKnowledgeCommand, indexCommand, infoCommand, initCommand } from "./commands/sources/stash-cli.js";
|
|
81
87
|
import { tasksCommand } from "./commands/tasks/tasks-cli.js";
|
|
82
88
|
import { wikiCommand } from "./commands/wiki-cli.js";
|
|
83
89
|
import { workflowCommand } from "./commands/workflow-cli.js";
|
|
@@ -208,8 +214,8 @@ const setupCommand = defineCommand({
|
|
|
208
214
|
async run({ args }) {
|
|
209
215
|
await runWithJsonErrors(async () => {
|
|
210
216
|
const noInit = getHyphenatedBoolean(args, "no-init");
|
|
211
|
-
const detectOnly =
|
|
212
|
-
const resetRecommended =
|
|
217
|
+
const detectOnly = args["detect-only"];
|
|
218
|
+
const resetRecommended = args["reset-recommended"];
|
|
213
219
|
if (detectOnly) {
|
|
214
220
|
// Detection only: no prompts, no writes.
|
|
215
221
|
const { runDetectOnly } = await import("./setup/setup.js");
|
|
@@ -320,10 +326,14 @@ const healthCommand = defineCommand({
|
|
|
320
326
|
// window-compare read for the trend deltas (defaults to 24h,
|
|
321
327
|
// overridable via --compare).
|
|
322
328
|
if (mode.format === "html") {
|
|
323
|
-
|
|
324
|
-
|
|
329
|
+
// Default the compare window to the report's own `--since` window so the
|
|
330
|
+
// trend deltas are like-for-like (e.g. last 7d vs the prior 7d). A fixed
|
|
331
|
+
// 24h default made a `--since 7d` report compare its 7-day totals against
|
|
332
|
+
// a 24-hour prior window, producing meaningless deltas.
|
|
333
|
+
const compare = args.compare ?? windowCompareRaw ?? args.since ?? "24h";
|
|
334
|
+
const result = akmHealth({ since: args.since, groupBy: "run", windowCompare: compare });
|
|
325
335
|
resultStatus = result.status;
|
|
326
|
-
const deltas =
|
|
336
|
+
const deltas = result.deltas;
|
|
327
337
|
const { buildHealthHtmlReplacements } = await import("./commands/health/html-report.js");
|
|
328
338
|
const { listPendingProposals } = await import("./commands/proposal/proposal.js");
|
|
329
339
|
const replacements = buildHealthHtmlReplacements(result, {
|
|
@@ -482,7 +492,6 @@ export const main = defineCommand({
|
|
|
482
492
|
health: healthCommand,
|
|
483
493
|
info: infoCommand,
|
|
484
494
|
graph: graphCommand,
|
|
485
|
-
db: dbCommand,
|
|
486
495
|
add: addCommand,
|
|
487
496
|
list: listCommand,
|
|
488
497
|
remove: removeCommand,
|
|
@@ -517,6 +526,7 @@ export const main = defineCommand({
|
|
|
517
526
|
tasks: tasksCommand,
|
|
518
527
|
},
|
|
519
528
|
});
|
|
529
|
+
const MAIN_TOP_LEVEL_ARGS = main.args;
|
|
520
530
|
// ── Exit codes ──────────────────────────────────────────────────────────────
|
|
521
531
|
// Canonical table lives in `src/cli/shared.ts` (EXIT_CODES). These aliases keep
|
|
522
532
|
// the local call sites terse. EXIT_HEALTH_WARN (4) is the `akm health` "warn"
|
|
@@ -557,7 +567,8 @@ if (import.meta.main || process.env.AKM_NODE_ENTRY === "1") {
|
|
|
557
567
|
// output-shaping time after the side effect has already happened. The
|
|
558
568
|
// shape-registry gate in shapeForCommand() remains as defense-in-depth (and
|
|
559
569
|
// covers the in-process test harness, which skips this startup block).
|
|
560
|
-
|
|
570
|
+
const topLevelCommand = findCittyTopLevelCommand(process.argv.slice(2), MAIN_TOP_LEVEL_ARGS);
|
|
571
|
+
if (getOutputMode().shape === "summary" && topLevelCommand !== "show") {
|
|
561
572
|
emitJsonError(new UsageError("'--shape summary' is only valid on 'akm show'.", "INVALID_SHAPE_VALUE"));
|
|
562
573
|
}
|
|
563
574
|
// One-time cleanup of stale 0.7.x index file at the old cache location.
|
|
@@ -18,7 +18,7 @@ import { parseAssetRef } from "../../core/asset/asset-ref.js";
|
|
|
18
18
|
import { NotFoundError, UsageError } from "../../core/errors.js";
|
|
19
19
|
import { requireAgentProfile } from "../../integrations/agent/config.js";
|
|
20
20
|
import { runAgent } from "../../integrations/agent/spawn.js";
|
|
21
|
-
import {
|
|
21
|
+
import { runOpencodeSdk } from "../../integrations/harnesses/opencode-sdk/index.js";
|
|
22
22
|
/**
|
|
23
23
|
* Fill `{{0}}`, `{{1}}`, ... placeholders in `template` with the
|
|
24
24
|
* corresponding entries in `args`. Any placeholder index that exceeds the
|
|
@@ -90,10 +90,11 @@ export async function akmAgentDispatch(options) {
|
|
|
90
90
|
parseOutput: "text",
|
|
91
91
|
...(options.args?.length && !options.commandRef && !options.workflowRef ? { args: options.args } : {}),
|
|
92
92
|
...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
|
|
93
|
+
...(options.cwd ? { cwd: options.cwd } : {}),
|
|
93
94
|
...(dispatchRequest !== undefined ? { dispatch: dispatchRequest } : {}),
|
|
94
95
|
};
|
|
95
96
|
const result = profile.sdkMode
|
|
96
|
-
? await
|
|
97
|
+
? await runOpencodeSdk(profile, prompt ?? "", runOptions, options.llmConfig)
|
|
97
98
|
: await runAgent(profile, prompt, runOptions);
|
|
98
99
|
return {
|
|
99
100
|
schemaVersion: 1,
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* Shared helpers for agent-based commands (reflect, propose, etc.).
|
|
6
|
-
*
|
|
7
|
-
* Consolidates utility functions that were duplicated byte-for-byte across
|
|
8
|
-
* `reflect.ts` and `propose.ts`. Any command that shells out to an agent
|
|
9
|
-
* profile can import from here rather than copy-pasting.
|
|
10
|
-
*/
|
|
11
4
|
import { loadConfig } from "../../core/config/config.js";
|
|
12
5
|
import { requireAgentProfile, } from "../../integrations/agent/index.js";
|
|
13
6
|
// ── Config helpers ───────────────────────────────────────────────────────────
|
|
@@ -28,8 +28,7 @@ import { EXIT_CODES, output, runWithJsonErrors } from "../../cli/shared.js";
|
|
|
28
28
|
import { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath } from "../../core/asset/asset-create.js";
|
|
29
29
|
import { loadConfig } from "../../core/config/config.js";
|
|
30
30
|
import { UsageError } from "../../core/errors.js";
|
|
31
|
-
import {
|
|
32
|
-
import { akmLint } from "../lint.js";
|
|
31
|
+
import { akmLint } from "../lint/index.js";
|
|
33
32
|
import { akmPropose } from "../proposal/propose.js";
|
|
34
33
|
import { akmAgentDispatch } from "./agent-dispatch.js";
|
|
35
34
|
const EXIT_GENERAL = EXIT_CODES.GENERAL;
|
|
@@ -57,13 +56,17 @@ export const agentCommand = defineCommand({
|
|
|
57
56
|
description: "Model override — accepts aliases (opus, sonnet, haiku) or exact platform model IDs. Overrides the model specified in the agent asset.",
|
|
58
57
|
},
|
|
59
58
|
"timeout-ms": { type: "string", description: "Override the agent CLI timeout in milliseconds" },
|
|
59
|
+
cwd: {
|
|
60
|
+
type: "string",
|
|
61
|
+
description: "Working directory for the spawned agent (defaults to the current directory)",
|
|
62
|
+
},
|
|
60
63
|
},
|
|
61
64
|
async run({ args }) {
|
|
62
65
|
await runWithJsonErrors(async () => {
|
|
63
66
|
if (!args.profile) {
|
|
64
67
|
throw new UsageError("Usage: akm agent <profile> [<agent-ref>] [--prompt <text>] [--model <model>]", "MISSING_REQUIRED_ARGUMENT", "Provide the agent profile name. Available profiles are listed in profiles.agent.");
|
|
65
68
|
}
|
|
66
|
-
const timeoutMs = parsePositiveIntFlag(
|
|
69
|
+
const timeoutMs = parsePositiveIntFlag(args["timeout-ms"], "--timeout-ms");
|
|
67
70
|
const config = loadConfig();
|
|
68
71
|
const { getDefaultLlmConfig } = await import("../../core/config/config.js");
|
|
69
72
|
// After 0.8.0 the agent block IS the loaded AkmConfig.
|
|
@@ -85,6 +88,7 @@ export const agentCommand = defineCommand({
|
|
|
85
88
|
const promptText = getStringArg(args, "prompt");
|
|
86
89
|
const commandRef = getStringArg(args, "command");
|
|
87
90
|
const workflowRef = getStringArg(args, "workflow");
|
|
91
|
+
const cwd = getStringArg(args, "cwd");
|
|
88
92
|
// Only build a dispatch request when there is something to dispatch — a
|
|
89
93
|
// prompt, an agent asset, or a model override. When none of these are
|
|
90
94
|
// present the agent is launched interactively (no injected prompt, no
|
|
@@ -104,9 +108,11 @@ export const agentCommand = defineCommand({
|
|
|
104
108
|
systemPrompt,
|
|
105
109
|
model,
|
|
106
110
|
tools: assetTools,
|
|
111
|
+
...(cwd ? { cwd } : {}),
|
|
107
112
|
},
|
|
108
113
|
}
|
|
109
114
|
: {}),
|
|
115
|
+
...(cwd ? { cwd } : {}),
|
|
110
116
|
...(timeoutMs !== undefined && Number.isFinite(timeoutMs) ? { timeoutMs } : {}),
|
|
111
117
|
});
|
|
112
118
|
output("agent-result", result);
|
|
@@ -122,23 +128,36 @@ export const lintCommand = defineCommand({
|
|
|
122
128
|
description: "Scan stash .md files for structural issues (unquoted colons, missing updated field, orphaned stubs, placeholder stubs, missing name/type, stale paths). Use --fix to auto-fix Tier 1 issues. Exits 0 on success regardless of findings; use --fail-on-flagged for CI fail-on-finding behavior.",
|
|
123
129
|
},
|
|
124
130
|
args: {
|
|
125
|
-
fix: {
|
|
131
|
+
fix: {
|
|
132
|
+
type: "boolean",
|
|
133
|
+
alias: "auto-fix",
|
|
134
|
+
description: "Apply auto-fixes in place (alias: --auto-fix)",
|
|
135
|
+
default: false,
|
|
136
|
+
},
|
|
126
137
|
dir: { type: "string", description: "Override stash root directory (default: from config)" },
|
|
127
138
|
"fail-on-flagged": {
|
|
128
139
|
type: "boolean",
|
|
129
140
|
description: "Exit non-zero when summary.flagged > 0 (CI-friendly). Default: exit 0 regardless of findings.",
|
|
130
141
|
default: false,
|
|
131
142
|
},
|
|
143
|
+
type: {
|
|
144
|
+
type: "string",
|
|
145
|
+
description: "Only lint assets of this type (e.g. workflows, tasks, memories)",
|
|
146
|
+
default: undefined,
|
|
147
|
+
},
|
|
132
148
|
},
|
|
133
149
|
async run({ args }) {
|
|
134
150
|
await runWithJsonErrors(async () => {
|
|
135
151
|
const result = akmLint({
|
|
136
152
|
fix: args.fix ?? false,
|
|
137
153
|
dir: getStringArg(args, "dir"),
|
|
154
|
+
typeFilter: getStringArg(args, "type"),
|
|
138
155
|
});
|
|
139
156
|
output("lint", result);
|
|
140
|
-
if (args["fail-on-flagged"] && result.summary.flagged > 0)
|
|
141
|
-
process.
|
|
157
|
+
if (args["fail-on-flagged"] && result.summary.flagged > 0) {
|
|
158
|
+
process.exitCode = EXIT_GENERAL;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
142
161
|
});
|
|
143
162
|
},
|
|
144
163
|
});
|
|
@@ -183,7 +202,7 @@ export const proposeCommand = defineCommand({
|
|
|
183
202
|
assertFlatAssetName(String(args.name));
|
|
184
203
|
const proposedName = combineCreatePath(normalizeCreateSubPath(getStringArg(args, "path")), String(args.name));
|
|
185
204
|
const taskText = fileFromFlag ? fs.readFileSync(path.resolve(fileFromFlag), "utf8") : (taskFromFlag ?? "");
|
|
186
|
-
const timeoutMs = parsePositiveIntFlag(
|
|
205
|
+
const timeoutMs = parsePositiveIntFlag(args["timeout-ms"], "--timeout-ms");
|
|
187
206
|
const result = await akmPropose({
|
|
188
207
|
type: String(args.type),
|
|
189
208
|
name: proposedName,
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
* - `parseConfigValue` returns a Partial<AkmConfig> so it can be merged with
|
|
17
17
|
* the runtime config object via `mergeConfigValue`.
|
|
18
18
|
*/
|
|
19
|
-
import {
|
|
20
|
-
import { defineJsonCommand, output } from "../cli/shared.js";
|
|
19
|
+
import { defineGroupCommand, defineJsonCommand, output } from "../cli/shared.js";
|
|
21
20
|
import { resolveStashDir } from "../core/common.js";
|
|
22
21
|
import { DEFAULT_CONFIG, getSources, loadConfig, loadUserConfig, saveConfig, } from "../core/config/config.js";
|
|
23
22
|
import { configGet, configSet, configUnset, unknownKeyHint } from "../core/config/config-walker.js";
|
|
@@ -64,7 +63,10 @@ function rewriteKey(config, key) {
|
|
|
64
63
|
// ── Public API ──────────────────────────────────────────────────────────────
|
|
65
64
|
export function getConfigValue(config, key) {
|
|
66
65
|
const k = rewriteKey(config, key);
|
|
67
|
-
|
|
66
|
+
const value = configGet(config, k);
|
|
67
|
+
if (k.split(".").at(-1) === "apiKey")
|
|
68
|
+
return null;
|
|
69
|
+
return omitApiKeysForOutput(value);
|
|
68
70
|
}
|
|
69
71
|
export function setConfigValue(config, key, rawValue) {
|
|
70
72
|
// #454: reject the legacy aliases up front so the error message names the
|
|
@@ -154,7 +156,20 @@ export function listConfig(config) {
|
|
|
154
156
|
result.archiveRetentionDays = config.archiveRetentionDays;
|
|
155
157
|
if (config.configVersion !== undefined)
|
|
156
158
|
result.configVersion = config.configVersion;
|
|
157
|
-
return result;
|
|
159
|
+
return omitApiKeysForOutput(result);
|
|
160
|
+
}
|
|
161
|
+
function omitApiKeysForOutput(value) {
|
|
162
|
+
if (Array.isArray(value))
|
|
163
|
+
return value.map(omitApiKeysForOutput);
|
|
164
|
+
if (!value || typeof value !== "object")
|
|
165
|
+
return value;
|
|
166
|
+
const out = {};
|
|
167
|
+
for (const [key, child] of Object.entries(value)) {
|
|
168
|
+
if (key === "apiKey")
|
|
169
|
+
continue;
|
|
170
|
+
out[key] = omitApiKeysForOutput(child);
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
158
173
|
}
|
|
159
174
|
export { unknownKeyHint };
|
|
160
175
|
// ── `akm config` command surface ────────────────────────────────────────────
|
|
@@ -202,7 +217,7 @@ function toggleComponent(targetRaw, enabled) {
|
|
|
202
217
|
// normalizeToggleTarget throws for any unsupported target; this is unreachable.
|
|
203
218
|
throw new UsageError(`Unsupported target "${targetRaw}". Supported targets: skills.sh`);
|
|
204
219
|
}
|
|
205
|
-
export const configCommand =
|
|
220
|
+
export const configCommand = defineGroupCommand({
|
|
206
221
|
meta: { name: "config", description: "Show and manage configuration" },
|
|
207
222
|
args: {
|
|
208
223
|
list: { type: "boolean", description: "List current configuration", default: false },
|
|
@@ -369,14 +384,12 @@ export const configCommand = defineJsonCommand({
|
|
|
369
384
|
},
|
|
370
385
|
}),
|
|
371
386
|
},
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
387
|
+
// The bare `akm config` invocation (and `akm config --list`) dumps the
|
|
388
|
+
// current config. defineGroupCommand short-circuits this body when a
|
|
389
|
+
// registered subcommand ran, so the routing set stays derived from the
|
|
390
|
+
// subCommands map and can never desync (previously validate/migrate were
|
|
391
|
+
// missing from a hand-maintained set, causing a spurious second dump).
|
|
392
|
+
defaultRun() {
|
|
379
393
|
output("config", listConfig(loadConfig()));
|
|
380
394
|
},
|
|
381
395
|
});
|
|
382
|
-
const CONFIG_SUBCOMMAND_SET = new Set(["path", "list", "show", "get", "set", "unset", "enable", "disable"]);
|