akm-cli 0.9.0-beta.9 → 0.9.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +715 -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/prompts/workflow-unit-preamble.md +26 -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 -21
- 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-binding.js +95 -0
- package/dist/commands/env/env-cli.js +228 -292
- package/dist/commands/env/env.js +14 -67
- package/dist/commands/env/secret-cli.js +140 -138
- package/dist/commands/feedback-cli.js +156 -155
- package/dist/commands/graph/graph-cli.js +5 -13
- package/dist/commands/graph/graph.js +3 -3
- 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 -1091
- 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 +1295 -1277
- 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 +228 -605
- 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 +54 -3
- 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 +157 -10
- package/dist/commands/improve/improve-cli.js +115 -73
- package/dist/commands/improve/improve-profiles.js +28 -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 +485 -2764
- 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 +37 -35
- 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 +206 -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 +2 -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 -895
- package/dist/commands/read/curate.js +410 -111
- 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/migration-help.js +7 -4
- 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 +19 -39
- 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 +291 -13
- package/dist/core/asset/asset-registry.js +3 -1
- package/dist/core/asset/asset-spec.js +79 -5
- 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 +403 -62
- 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/json-schema.js +142 -0
- package/dist/core/logs-db.js +14 -75
- package/dist/core/parse.js +36 -16
- package/dist/core/paths.js +18 -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 +132 -1126
- 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 +261 -770
- 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 +36 -92
- 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 +18 -11
- package/dist/indexer/index-written-assets.js +105 -0
- package/dist/indexer/indexer.js +182 -204
- 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 +48 -0
- package/dist/indexer/walk/walker.js +21 -13
- package/dist/integrations/agent/builders.js +41 -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 +16 -2
- package/dist/integrations/agent/profiles.js +79 -6
- package/dist/integrations/agent/prompts.js +75 -9
- package/dist/integrations/agent/runner-dispatch.js +83 -0
- package/dist/integrations/agent/runner.js +13 -9
- package/dist/integrations/agent/spawn.js +206 -81
- package/dist/integrations/harnesses/aider/agent-builder.js +113 -0
- package/dist/integrations/harnesses/aider/index.js +58 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +153 -0
- package/dist/integrations/harnesses/amazonq/index.js +59 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -7
- package/dist/integrations/harnesses/claude/index.js +27 -23
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +10 -0
- package/dist/integrations/harnesses/codex/agent-builder.js +137 -0
- package/dist/integrations/harnesses/codex/index.js +63 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +60 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +121 -0
- package/dist/integrations/harnesses/gemini/index.js +60 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/index.js +28 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
- package/dist/integrations/harnesses/opencode/index.js +17 -16
- package/dist/integrations/harnesses/opencode/session-log.js +173 -3
- package/dist/integrations/harnesses/opencode-sdk/harness.js +65 -0
- package/dist/integrations/harnesses/opencode-sdk/index.js +10 -34
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +642 -71
- package/dist/integrations/harnesses/openhands/agent-builder.js +126 -0
- package/dist/integrations/harnesses/openhands/index.js +58 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +104 -0
- package/dist/integrations/harnesses/pi/index.js +58 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/types.js +8 -0
- package/dist/integrations/session-logs/index.js +40 -11
- package/dist/llm/call-ai.js +2 -2
- package/dist/llm/client.js +34 -11
- 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 +87 -15
- package/dist/output/shapes/curate.js +14 -2
- package/dist/output/shapes/helpers.js +0 -3
- package/dist/output/shapes/passthrough.js +6 -1
- package/dist/output/text/helpers.js +241 -2
- package/dist/output/text/workflow.js +4 -1
- 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/schemas/akm-config.json +14225 -0
- package/dist/schemas/akm-workflow.json +328 -0
- package/dist/scripts/migrate-storage.js +2743 -8390
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +1652 -607
- 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/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/repositories/workflow-runs-repository.js +189 -1
- 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 +1 -1
- package/dist/wiki/wiki.js +52 -11
- package/dist/workflows/authoring/authoring.js +123 -10
- package/dist/workflows/authoring/workflow-program-template.yaml +31 -0
- package/dist/workflows/cli.js +5 -0
- package/dist/workflows/db.js +138 -4
- package/dist/workflows/exec/brief.js +484 -0
- package/dist/workflows/exec/native-executor.js +975 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1295 -0
- package/dist/workflows/exec/run-workflow.js +596 -0
- package/dist/workflows/exec/scheduler.js +100 -0
- package/dist/workflows/exec/step-work.js +1156 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/watch.js +116 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +388 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +33 -0
- package/dist/workflows/ir/schema.js +4 -0
- package/dist/workflows/parser.js +3 -1
- package/dist/workflows/program/expressions.js +369 -0
- package/dist/workflows/program/parser.js +760 -0
- package/dist/workflows/program/project.js +105 -0
- package/dist/workflows/program/schema.js +54 -0
- package/dist/workflows/renderer.js +82 -5
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/runs.js +248 -153
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +188 -0
- package/dist/workflows/validate-summary.js +26 -10
- package/dist/workflows/validator.js +1 -1
- package/docs/README.md +69 -18
- package/docs/data-and-telemetry.md +7 -5
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0-beta.60.md +19 -0
- 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
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* `looksLikeWorkflowRunId` and `resolveWorkflowFilePath` move with the family.
|
|
13
13
|
*/
|
|
14
14
|
import { defineCommand } from "citty";
|
|
15
|
+
import { getStringArg } from "../cli/parse-args.js";
|
|
15
16
|
import { defineJsonCommand, output, runWithJsonErrors } from "../cli/shared.js";
|
|
16
17
|
import { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath } from "../core/asset/asset-create.js";
|
|
17
18
|
import { parseAssetRef } from "../core/asset/asset-ref.js";
|
|
@@ -22,9 +23,10 @@ import { resolveSourceEntries } from "../indexer/search/search-source.js";
|
|
|
22
23
|
import { hasBooleanFlag } from "../output/context.js";
|
|
23
24
|
import { resolveSourcesForOrigin } from "../registry/origin-resolve.js";
|
|
24
25
|
import { resolveAssetPath } from "../sources/resolve.js";
|
|
25
|
-
import { createWorkflowAsset, formatWorkflowErrors, getWorkflowTemplate, validateWorkflowSource, } from "../workflows/authoring/authoring.js";
|
|
26
|
+
import { createWorkflowAsset, formatWorkflowErrors, getWorkflowProgramTemplate, getWorkflowTemplate, validateWorkflowProgramSource, validateWorkflowSource, } from "../workflows/authoring/authoring.js";
|
|
26
27
|
import { hasWorkflowSubcommand, parseWorkflowJsonObject, parseWorkflowStepState, WORKFLOW_STEP_STATES, } from "../workflows/cli.js";
|
|
27
|
-
import {
|
|
28
|
+
import { isWorkflowProgramPath } from "../workflows/program/project.js";
|
|
29
|
+
import { abandonWorkflowRun, completeWorkflowStep, getNextWorkflowStep, getWorkflowStatus, listWorkflowRuns, resumeWorkflowRun, startWorkflowRun, } from "../workflows/runtime/runs.js";
|
|
28
30
|
const workflowStartCommand = defineJsonCommand({
|
|
29
31
|
meta: {
|
|
30
32
|
name: "start",
|
|
@@ -140,9 +142,16 @@ const workflowStatusCommand = defineJsonCommand({
|
|
|
140
142
|
},
|
|
141
143
|
args: {
|
|
142
144
|
target: { type: "positional", description: "Workflow run id or workflow ref (workflow:<name>)", required: true },
|
|
145
|
+
units: {
|
|
146
|
+
type: "boolean",
|
|
147
|
+
description: "Also list per-unit rows from the run journal (unit id, status, failure_reason, and any result/error " +
|
|
148
|
+
"diagnostic text). Diagnostics only — step evidence stays deterministic and is unaffected (#22).",
|
|
149
|
+
default: false,
|
|
150
|
+
},
|
|
143
151
|
},
|
|
144
152
|
async run({ args }) {
|
|
145
153
|
const target = args.target;
|
|
154
|
+
const includeUnits = args.units === true;
|
|
146
155
|
// Check if target looks like a workflow ref
|
|
147
156
|
const parsed = (() => {
|
|
148
157
|
try {
|
|
@@ -161,11 +170,11 @@ const workflowStatusCommand = defineJsonCommand({
|
|
|
161
170
|
const mostRecent = runs[0];
|
|
162
171
|
if (!mostRecent)
|
|
163
172
|
throw new NotFoundError(`No workflow runs found for ${ref}`, "WORKFLOW_NOT_FOUND");
|
|
164
|
-
const result = await getWorkflowStatus(mostRecent.id);
|
|
173
|
+
const result = await getWorkflowStatus(mostRecent.id, { includeUnits });
|
|
165
174
|
output("workflow-status", result);
|
|
166
175
|
}
|
|
167
176
|
else {
|
|
168
|
-
const result = await getWorkflowStatus(target);
|
|
177
|
+
const result = await getWorkflowStatus(target, { includeUnits });
|
|
169
178
|
output("workflow-status", result);
|
|
170
179
|
}
|
|
171
180
|
},
|
|
@@ -187,19 +196,22 @@ const workflowListCommand = defineJsonCommand({
|
|
|
187
196
|
const workflowCreateCommand = defineJsonCommand({
|
|
188
197
|
meta: {
|
|
189
198
|
name: "create",
|
|
190
|
-
description: "Create a workflow markdown document
|
|
199
|
+
description: "Create a workflow in the working stash (markdown document by default; a .yaml/.yml name writes a YAML program)",
|
|
191
200
|
},
|
|
192
201
|
args: {
|
|
193
202
|
name: {
|
|
194
203
|
type: "positional",
|
|
195
|
-
description: "Workflow name (flat, no '/'; use --path for a subdirectory)",
|
|
204
|
+
description: "Workflow name (flat, no '/'; use --path for a subdirectory). A .yaml/.yml suffix creates a YAML program.",
|
|
196
205
|
required: true,
|
|
197
206
|
},
|
|
198
207
|
path: {
|
|
199
208
|
type: "string",
|
|
200
209
|
description: "Relative subdirectory under workflows/ to place the workflow in (e.g. 'release'). The filename comes from the name.",
|
|
201
210
|
},
|
|
202
|
-
from: {
|
|
211
|
+
from: {
|
|
212
|
+
type: "string",
|
|
213
|
+
description: "Import and validate content from an existing file (parsed per the destination extension)",
|
|
214
|
+
},
|
|
203
215
|
force: {
|
|
204
216
|
type: "boolean",
|
|
205
217
|
description: "Overwrite an existing workflow (requires --from or --reset)",
|
|
@@ -237,26 +249,54 @@ const workflowCreateCommand = defineJsonCommand({
|
|
|
237
249
|
const workflowTemplateCommand = defineCommand({
|
|
238
250
|
meta: {
|
|
239
251
|
name: "template",
|
|
240
|
-
description: "Print a valid workflow markdown
|
|
252
|
+
description: "Print a valid workflow template (markdown by default, --yaml for a YAML program)",
|
|
241
253
|
},
|
|
242
|
-
|
|
243
|
-
|
|
254
|
+
args: {
|
|
255
|
+
yaml: {
|
|
256
|
+
type: "boolean",
|
|
257
|
+
description: "Print a minimal valid YAML workflow program instead of the markdown template",
|
|
258
|
+
default: false,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
run({ args }) {
|
|
262
|
+
process.stdout.write(args.yaml ? getWorkflowProgramTemplate() : getWorkflowTemplate());
|
|
244
263
|
},
|
|
245
264
|
});
|
|
246
265
|
const workflowValidateCommand = defineJsonCommand({
|
|
247
266
|
meta: {
|
|
248
267
|
name: "validate",
|
|
249
|
-
description: "Validate a workflow
|
|
268
|
+
description: "Validate a workflow file or ref (markdown document or YAML program) and print any errors",
|
|
250
269
|
},
|
|
251
270
|
args: {
|
|
252
271
|
target: {
|
|
253
272
|
type: "positional",
|
|
254
|
-
description: "Workflow ref (workflow:<name>) or filesystem path to a workflow .md",
|
|
273
|
+
description: "Workflow ref (workflow:<name>) or filesystem path to a workflow .md/.yaml",
|
|
255
274
|
required: true,
|
|
256
275
|
},
|
|
257
276
|
},
|
|
258
277
|
async run({ args }) {
|
|
259
278
|
const filePath = await resolveWorkflowFilePath(args.target);
|
|
279
|
+
// YAML programs (redesign addendum, R1) validate through the program
|
|
280
|
+
// parser AND compiler so expression/reference errors surface at lint
|
|
281
|
+
// time; both error lists carry line numbers. Markdown is unchanged.
|
|
282
|
+
if (isWorkflowProgramPath(filePath)) {
|
|
283
|
+
const { result } = validateWorkflowProgramSource(filePath);
|
|
284
|
+
if (!result.ok) {
|
|
285
|
+
throw new UsageError(formatWorkflowErrors(filePath, result.errors));
|
|
286
|
+
}
|
|
287
|
+
// Non-fatal WARNINGS ride the envelope additively — `ok` stays true. The
|
|
288
|
+
// text formatter renders them clearly marked for humans; the JSON key is
|
|
289
|
+
// the machine channel. Empty array when the program is fully typed/declared.
|
|
290
|
+
output("workflow-validate", {
|
|
291
|
+
ok: true,
|
|
292
|
+
path: filePath,
|
|
293
|
+
format: "program",
|
|
294
|
+
title: result.program.name,
|
|
295
|
+
stepCount: result.program.steps.length,
|
|
296
|
+
warnings: result.warnings.map((w) => ({ line: w.line, message: w.message })),
|
|
297
|
+
});
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
260
300
|
const { parse } = validateWorkflowSource(filePath);
|
|
261
301
|
if (parse.ok) {
|
|
262
302
|
output("workflow-validate", {
|
|
@@ -271,7 +311,15 @@ const workflowValidateCommand = defineJsonCommand({
|
|
|
271
311
|
},
|
|
272
312
|
});
|
|
273
313
|
async function resolveWorkflowFilePath(target) {
|
|
274
|
-
|
|
314
|
+
// A bare (`workflow:<name>`) OR origin-qualified (`<origin>//workflow:<name>`)
|
|
315
|
+
// ref resolves through the source search, exactly like `workflow start` /
|
|
316
|
+
// `status` / `next`. Anything else is treated as a filesystem path. Detecting
|
|
317
|
+
// the origin-qualified form here (not just the bare prefix) keeps `validate`'s
|
|
318
|
+
// ref contract in lockstep with the rest of the workflow command family — an
|
|
319
|
+
// `extra//workflow:foo` ref validates the file that `extra//workflow:foo`
|
|
320
|
+
// starts, rather than being mistaken for a relative path that does not exist.
|
|
321
|
+
const looksLikeWorkflowRef = target.startsWith("workflow:") || target.includes("//workflow:");
|
|
322
|
+
if (!looksLikeWorkflowRef)
|
|
275
323
|
return target;
|
|
276
324
|
const parsed = parseAssetRef(target);
|
|
277
325
|
if (parsed.type !== "workflow") {
|
|
@@ -290,6 +338,231 @@ async function resolveWorkflowFilePath(target) {
|
|
|
290
338
|
}
|
|
291
339
|
throw new UsageError(`Workflow not found for ref: workflow:${parsed.name}`);
|
|
292
340
|
}
|
|
341
|
+
const workflowRunCommand = defineJsonCommand({
|
|
342
|
+
meta: {
|
|
343
|
+
name: "run",
|
|
344
|
+
description: "EXPERIMENTAL: execute a workflow's steps with the native engine — akm dispatches each step's units " +
|
|
345
|
+
"(fan-out, schema output) to the configured runner and advances the run through the normal completion gates",
|
|
346
|
+
},
|
|
347
|
+
args: {
|
|
348
|
+
target: { type: "positional", description: "Workflow run id or workflow ref (auto-starts a run)", required: true },
|
|
349
|
+
params: { type: "string", description: "Workflow parameters as a JSON object (only for auto-started runs)" },
|
|
350
|
+
"max-steps": { type: "string", description: "Stop after executing this many steps" },
|
|
351
|
+
"require-gates": {
|
|
352
|
+
type: "boolean",
|
|
353
|
+
description: "Treat every criteria-bearing completion gate as required: if no LLM judge is available, BLOCK the step " +
|
|
354
|
+
"(for a human to resolve via `akm workflow resume`) instead of failing open. A per-step `gate.required: true` " +
|
|
355
|
+
"in the workflow does the same on every surface; this is the run-wide override (#18).",
|
|
356
|
+
default: false,
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
async run({ args }) {
|
|
360
|
+
const { runWorkflowSteps } = await import("../workflows/exec/run-workflow.js");
|
|
361
|
+
const rawMaxSteps = getStringArg(args, "max-steps");
|
|
362
|
+
let maxSteps;
|
|
363
|
+
if (rawMaxSteps !== undefined) {
|
|
364
|
+
maxSteps = Number.parseInt(rawMaxSteps, 10);
|
|
365
|
+
if (!/^\d+$/.test(rawMaxSteps) || maxSteps <= 0) {
|
|
366
|
+
throw new UsageError(`--max-steps must be a positive integer, got "${rawMaxSteps}".`, "INVALID_FLAG_VALUE");
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
const result = await runWorkflowSteps({
|
|
370
|
+
target: args.target,
|
|
371
|
+
...(args.params ? { params: parseWorkflowJsonObject(args.params, "--params") } : {}),
|
|
372
|
+
...(maxSteps !== undefined ? { maxSteps } : {}),
|
|
373
|
+
...(args["require-gates"] === true ? { requireGates: true } : {}),
|
|
374
|
+
});
|
|
375
|
+
output("workflow-run", result);
|
|
376
|
+
},
|
|
377
|
+
});
|
|
378
|
+
const workflowBriefCommand = defineJsonCommand({
|
|
379
|
+
meta: {
|
|
380
|
+
name: "brief",
|
|
381
|
+
description: "EXPERIMENTAL: describe a run's active step as an executable work-list for ANY agent session (the " +
|
|
382
|
+
"harness-neutral driver protocol) — read-only, takes no engine lease, mutates nothing; prints per-unit " +
|
|
383
|
+
"instructions, output schema, env binding names, and the exact `akm workflow report` command lines",
|
|
384
|
+
},
|
|
385
|
+
args: {
|
|
386
|
+
target: {
|
|
387
|
+
type: "positional",
|
|
388
|
+
description: "Workflow run id (or a workflow ref with an active run)",
|
|
389
|
+
required: true,
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
async run({ args }) {
|
|
393
|
+
const { buildWorkflowBrief } = await import("../workflows/exec/brief.js");
|
|
394
|
+
const result = await buildWorkflowBrief(args.target);
|
|
395
|
+
output("workflow-brief", result);
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
const WORKFLOW_REPORT_STATES = ["completed", "failed", "running"];
|
|
399
|
+
const workflowReportCommand = defineJsonCommand({
|
|
400
|
+
meta: {
|
|
401
|
+
name: "report",
|
|
402
|
+
description: "EXPERIMENTAL: report a unit's result back into a run (the mutating half of the harness-neutral driver " +
|
|
403
|
+
"protocol) — ingested through the SAME shared step semantics the engine uses. --status running claims/" +
|
|
404
|
+
"heartbeats a unit; completed/failed records it and, when the step's work-list is fully terminal, runs the " +
|
|
405
|
+
"engine's completion path (reducer, artifact + schema validation, gate). --settle (no --unit) advances a run " +
|
|
406
|
+
"parked on a route-only/empty step. Refused while a live engine lease exists",
|
|
407
|
+
},
|
|
408
|
+
args: {
|
|
409
|
+
target: {
|
|
410
|
+
type: "positional",
|
|
411
|
+
description: "Workflow run id (or a workflow ref with an active run)",
|
|
412
|
+
required: true,
|
|
413
|
+
},
|
|
414
|
+
unit: {
|
|
415
|
+
type: "string",
|
|
416
|
+
description: "Content-derived unit id from `akm workflow brief` (copy it verbatim). Omit with --settle.",
|
|
417
|
+
},
|
|
418
|
+
settle: {
|
|
419
|
+
type: "boolean",
|
|
420
|
+
description: "Advance/finalize a run whose active step has NO unit left to report: a non-dispatching step (params-based route, empty fan-out, all-unresolvable) OR a fully-terminal step still needing finalization (every unit ran but the gate never judged — e.g. after resuming a required-gate block). Runs the deterministic completion path. Mutually exclusive with --unit; refused when the step still has genuinely pending units",
|
|
421
|
+
default: false,
|
|
422
|
+
},
|
|
423
|
+
"expect-step": {
|
|
424
|
+
type: "string",
|
|
425
|
+
description: "Guard: the step id you briefed against. Refuses the report if the run's active step has since moved (from the `brief` report/settle command line)",
|
|
426
|
+
},
|
|
427
|
+
status: { type: "string", description: `Unit status: ${WORKFLOW_REPORT_STATES.join(", ")}` },
|
|
428
|
+
result: { type: "string", description: "Result payload (JSON for a schema unit, else text). completed only." },
|
|
429
|
+
"result-file": { type: "string", description: "Read the result payload from this file instead of --result/stdin" },
|
|
430
|
+
tokens: { type: "string", description: "Tokens spent on this unit (counts against a declared budget)" },
|
|
431
|
+
"session-id": { type: "string", description: "Harness-native session id revealed while executing the unit" },
|
|
432
|
+
"failure-reason": { type: "string", description: "Structured failure vocabulary for a --status failed report" },
|
|
433
|
+
note: { type: "string", description: "Short progress note for a --status running heartbeat (not persisted)" },
|
|
434
|
+
rerun: {
|
|
435
|
+
type: "boolean",
|
|
436
|
+
description: "Re-run an already-FAILED unit: record a NEW attempt (re-applies budget) instead of refusing a differing re-report",
|
|
437
|
+
default: false,
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
async run({ args }) {
|
|
441
|
+
// --settle: the unit-less verb that advances a run parked on a
|
|
442
|
+
// non-dispatching step. Mutually exclusive with the per-unit report flags.
|
|
443
|
+
if (args.settle === true) {
|
|
444
|
+
if (getStringArg(args, "unit") !== undefined || getStringArg(args, "status") !== undefined) {
|
|
445
|
+
throw new UsageError("--settle advances a route-only/empty step and takes no --unit or --status. Drop them, or report a " +
|
|
446
|
+
"specific unit with `--unit <id> --status <state>` instead.", "INVALID_FLAG_VALUE");
|
|
447
|
+
}
|
|
448
|
+
const { settleWorkflowSpine } = await import("../workflows/exec/report.js");
|
|
449
|
+
const result = await settleWorkflowSpine({
|
|
450
|
+
target: args.target,
|
|
451
|
+
...(getStringArg(args, "expect-step") !== undefined ? { expectStep: getStringArg(args, "expect-step") } : {}),
|
|
452
|
+
});
|
|
453
|
+
output("workflow-report", result);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const status = args.status;
|
|
457
|
+
if (!status) {
|
|
458
|
+
throw new UsageError("--status is required (completed | failed | running), or pass --settle to advance a non-dispatching step.", "MISSING_REQUIRED_ARGUMENT");
|
|
459
|
+
}
|
|
460
|
+
if (!WORKFLOW_REPORT_STATES.includes(status)) {
|
|
461
|
+
throw new UsageError(`Invalid --status "${status}". Expected one of: ${WORKFLOW_REPORT_STATES.join(", ")}.`, "INVALID_FLAG_VALUE");
|
|
462
|
+
}
|
|
463
|
+
const unitId = getStringArg(args, "unit");
|
|
464
|
+
if (!unitId) {
|
|
465
|
+
throw new UsageError("--unit is required (the content-derived unit id from `akm workflow brief`), or pass --settle for a route-only/empty step.", "MISSING_REQUIRED_ARGUMENT");
|
|
466
|
+
}
|
|
467
|
+
let tokens;
|
|
468
|
+
const rawTokens = getStringArg(args, "tokens");
|
|
469
|
+
if (rawTokens !== undefined) {
|
|
470
|
+
tokens = Number.parseInt(rawTokens, 10);
|
|
471
|
+
if (!/^\d+$/.test(rawTokens)) {
|
|
472
|
+
throw new UsageError(`--tokens must be a non-negative integer, got "${rawTokens}".`, "INVALID_FLAG_VALUE");
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
// Result payload precedence: --result, then --result-file, then stdin
|
|
476
|
+
// (completed/failed only; a running heartbeat carries no result).
|
|
477
|
+
let resultRaw;
|
|
478
|
+
if (status !== "running") {
|
|
479
|
+
const resultFile = getStringArg(args, "result-file");
|
|
480
|
+
if (args.result !== undefined && resultFile !== undefined) {
|
|
481
|
+
throw new UsageError("Pass at most one of --result or --result-file.", "INVALID_FLAG_VALUE");
|
|
482
|
+
}
|
|
483
|
+
if (args.result !== undefined) {
|
|
484
|
+
resultRaw = String(args.result);
|
|
485
|
+
}
|
|
486
|
+
else if (resultFile !== undefined) {
|
|
487
|
+
const fs = await import("node:fs");
|
|
488
|
+
resultRaw = fs.readFileSync(resultFile, "utf8");
|
|
489
|
+
}
|
|
490
|
+
else if (!process.stdin.isTTY) {
|
|
491
|
+
resultRaw = await readStdin();
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const { reportWorkflowUnit } = await import("../workflows/exec/report.js");
|
|
495
|
+
const result = await reportWorkflowUnit({
|
|
496
|
+
target: args.target,
|
|
497
|
+
unitId,
|
|
498
|
+
status: status,
|
|
499
|
+
...(getStringArg(args, "expect-step") !== undefined ? { expectStep: getStringArg(args, "expect-step") } : {}),
|
|
500
|
+
...(resultRaw !== undefined ? { resultRaw } : {}),
|
|
501
|
+
...(tokens !== undefined ? { tokens } : {}),
|
|
502
|
+
...(args.rerun === true ? { rerun: true } : {}),
|
|
503
|
+
...(getStringArg(args, "session-id") !== undefined ? { sessionId: getStringArg(args, "session-id") } : {}),
|
|
504
|
+
...(getStringArg(args, "failure-reason") !== undefined
|
|
505
|
+
? { failureReason: getStringArg(args, "failure-reason") }
|
|
506
|
+
: {}),
|
|
507
|
+
...(getStringArg(args, "note") !== undefined ? { note: getStringArg(args, "note") } : {}),
|
|
508
|
+
});
|
|
509
|
+
output("workflow-report", result);
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
async function readStdin() {
|
|
513
|
+
const chunks = [];
|
|
514
|
+
for await (const chunk of process.stdin)
|
|
515
|
+
chunks.push(chunk);
|
|
516
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
517
|
+
}
|
|
518
|
+
const workflowWatchCommand = defineJsonCommand({
|
|
519
|
+
meta: {
|
|
520
|
+
name: "watch",
|
|
521
|
+
description: "Print a run's workflow_* events (state.db events table) as NDJSON and exit; --stream polls in the " +
|
|
522
|
+
"foreground until the run reaches a terminal status (no daemon)",
|
|
523
|
+
},
|
|
524
|
+
args: {
|
|
525
|
+
runId: { type: "positional", description: "Workflow run id", required: true },
|
|
526
|
+
stream: {
|
|
527
|
+
type: "boolean",
|
|
528
|
+
description: "Keep polling for new events until the run leaves 'active' (completed/failed/blocked)",
|
|
529
|
+
default: false,
|
|
530
|
+
},
|
|
531
|
+
"interval-ms": { type: "string", description: "Poll interval in milliseconds for --stream (default: 1000)" },
|
|
532
|
+
},
|
|
533
|
+
async run({ args }) {
|
|
534
|
+
const rawInterval = getStringArg(args, "interval-ms");
|
|
535
|
+
let intervalMs;
|
|
536
|
+
if (rawInterval !== undefined) {
|
|
537
|
+
intervalMs = Number.parseInt(rawInterval, 10);
|
|
538
|
+
if (!/^\d+$/.test(rawInterval) || intervalMs <= 0) {
|
|
539
|
+
throw new UsageError(`--interval-ms must be a positive integer, got "${rawInterval}".`, "INVALID_FLAG_VALUE");
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
const { watchWorkflowRun } = await import("../workflows/exec/watch.js");
|
|
543
|
+
const result = await watchWorkflowRun({
|
|
544
|
+
runId: args.runId,
|
|
545
|
+
stream: args.stream === true,
|
|
546
|
+
...(intervalMs !== undefined ? { intervalMs } : {}),
|
|
547
|
+
});
|
|
548
|
+
// The event lines above are raw NDJSON on stdout; this trailing envelope
|
|
549
|
+
// is the machine-readable command result (counts + terminal status).
|
|
550
|
+
output("workflow-watch", { ok: true, ...result });
|
|
551
|
+
},
|
|
552
|
+
});
|
|
553
|
+
const workflowAbandonCommand = defineJsonCommand({
|
|
554
|
+
meta: {
|
|
555
|
+
name: "abandon",
|
|
556
|
+
description: "Give up on a workflow run: mark it failed so it stops counting as active (resume can reopen it)",
|
|
557
|
+
},
|
|
558
|
+
args: {
|
|
559
|
+
runId: { type: "positional", description: "Workflow run id", required: true },
|
|
560
|
+
},
|
|
561
|
+
async run({ args }) {
|
|
562
|
+
const result = await abandonWorkflowRun(args.runId);
|
|
563
|
+
output("workflow-abandon", result);
|
|
564
|
+
},
|
|
565
|
+
});
|
|
293
566
|
const workflowResumeCommand = defineJsonCommand({
|
|
294
567
|
meta: {
|
|
295
568
|
name: "resume",
|
|
@@ -317,7 +590,12 @@ export const workflowCommand = defineCommand({
|
|
|
317
590
|
create: workflowCreateCommand,
|
|
318
591
|
template: workflowTemplateCommand,
|
|
319
592
|
resume: workflowResumeCommand,
|
|
593
|
+
abandon: workflowAbandonCommand,
|
|
320
594
|
validate: workflowValidateCommand,
|
|
595
|
+
run: workflowRunCommand,
|
|
596
|
+
brief: workflowBriefCommand,
|
|
597
|
+
report: workflowReportCommand,
|
|
598
|
+
watch: workflowWatchCommand,
|
|
321
599
|
},
|
|
322
600
|
run({ args }) {
|
|
323
601
|
return runWithJsonErrors(async () => {
|
|
@@ -29,6 +29,7 @@ export const TYPE_TO_RENDERER = {
|
|
|
29
29
|
wiki: "wiki-md",
|
|
30
30
|
task: "task-yaml",
|
|
31
31
|
session: "session-md",
|
|
32
|
+
fact: "fact-md",
|
|
32
33
|
};
|
|
33
34
|
/** Map asset types to action builder functions for search results. */
|
|
34
35
|
export const ACTION_BUILDERS = {
|
|
@@ -40,11 +41,12 @@ export const ACTION_BUILDERS = {
|
|
|
40
41
|
lesson: (ref) => `akm show ${ref} -> read the lesson and apply when_to_use`,
|
|
41
42
|
memory: (ref) => `akm show ${ref} -> recall context`,
|
|
42
43
|
workflow: (ref) => buildWorkflowAction(ref),
|
|
43
|
-
env: (ref) => `akm show ${ref} -> inspect key names; akm env run ${ref} -- <command> -> run with the whole .env injected (
|
|
44
|
+
env: (ref) => `akm show ${ref} -> inspect key names; akm env run ${ref} -- <command> -> run with the whole .env injected (prefer --clean to minimize inherited parent env; child stdout is not redacted). akm env export ${ref} --out <file> writes a sourceable script (values to a file, not stdout).`,
|
|
44
45
|
secret: (ref) => `akm show ${ref} -> name only (value never shown); akm secret path ${ref} -> file path; akm secret run ${ref} <VAR> -- <command> -> run with value injected into $VAR`,
|
|
45
46
|
wiki: (ref) => `akm show ${ref} -> read the wiki page`,
|
|
46
47
|
task: (ref) => `akm tasks show ${ref.replace(/^task:/, "")} -> inspect; akm tasks run <id> -> run now; akm tasks remove <id> -> unschedule`,
|
|
47
48
|
session: (ref) => `akm show ${ref} -> read the session summary; follow the \`access\` frontmatter to open the raw log at \`log_path\``,
|
|
49
|
+
fact: (ref) => `akm show ${ref} -> read the stash fact and apply it as durable context`,
|
|
48
50
|
};
|
|
49
51
|
/**
|
|
50
52
|
* Register a type-to-renderer mapping.
|
|
@@ -1,11 +1,67 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import fs from "node:fs";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { buildWorkflowAction } from "../../output/renderers.js";
|
|
6
|
-
import { toPosix } from "../common.js";
|
|
7
7
|
import { registerActionBuilder, registerTypeRenderer } from "./asset-registry.js";
|
|
8
|
+
function toPosix(input) {
|
|
9
|
+
return input.replace(/\\/g, "/");
|
|
10
|
+
}
|
|
8
11
|
const buildTaskAction = (ref) => `akm tasks show ${ref.replace(/^task:/, "")} -> inspect; akm tasks run <id> -> run now; akm tasks remove <id> -> unschedule`;
|
|
12
|
+
/**
|
|
13
|
+
* Recognized workflow asset extensions, in resolution-priority order.
|
|
14
|
+
* `.md` (classic linear markdown workflows — the stable contract) stays
|
|
15
|
+
* FIRST for back-compat; `.yaml`/`.yml` hold YAML workflow *programs*
|
|
16
|
+
* (redesign addendum, R1). `workflow:<name>` refs resolve against this list.
|
|
17
|
+
*/
|
|
18
|
+
export const WORKFLOW_EXTENSIONS = [".md", ".yaml", ".yml"];
|
|
19
|
+
/**
|
|
20
|
+
* Strip a recognized workflow extension (`.md`/`.yaml`/`.yml`) from a workflow
|
|
21
|
+
* asset *name* so `foo`, `foo.yaml`, `foo.yml`, and `foo.md` collapse to one
|
|
22
|
+
* canonical identity — the same collapse `workflowSpec.toCanonicalName`
|
|
23
|
+
* performs on a resolved file path. Callers that turn a `workflow:<name>` ref
|
|
24
|
+
* into run identity (the active-run guard, list/status filters) MUST route the
|
|
25
|
+
* name through this so an aliased spelling (`workflow:foo.yaml`) and the
|
|
26
|
+
* canonical `workflow:foo` cannot start or hide parallel runs of the same
|
|
27
|
+
* workflow. Names without a recognized workflow extension pass through
|
|
28
|
+
* unchanged.
|
|
29
|
+
*/
|
|
30
|
+
export function canonicalizeWorkflowName(name) {
|
|
31
|
+
const lower = name.toLowerCase();
|
|
32
|
+
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
33
|
+
if (lower.endsWith(ext))
|
|
34
|
+
return name.slice(0, -ext.length);
|
|
35
|
+
}
|
|
36
|
+
return name;
|
|
37
|
+
}
|
|
38
|
+
const workflowSpec = {
|
|
39
|
+
isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS.includes(path.extname(fileName).toLowerCase()),
|
|
40
|
+
toCanonicalName: (typeRoot, filePath) => {
|
|
41
|
+
const rel = toPosix(path.relative(typeRoot, filePath));
|
|
42
|
+
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
43
|
+
if (rel.toLowerCase().endsWith(ext))
|
|
44
|
+
return rel.slice(0, -ext.length);
|
|
45
|
+
}
|
|
46
|
+
return rel;
|
|
47
|
+
},
|
|
48
|
+
toAssetPath: (typeRoot, name) => {
|
|
49
|
+
// Explicit extension wins (accepts refs like "release/ship.yaml").
|
|
50
|
+
const lower = name.toLowerCase();
|
|
51
|
+
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
52
|
+
if (lower.endsWith(ext))
|
|
53
|
+
return path.join(typeRoot, name);
|
|
54
|
+
}
|
|
55
|
+
// Probe in priority order — `.md` first for back-compat — and fall back
|
|
56
|
+
// to the markdown path so error messages keep naming the canonical file.
|
|
57
|
+
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
58
|
+
const candidate = path.join(typeRoot, `${name}${ext}`);
|
|
59
|
+
if (fs.existsSync(candidate))
|
|
60
|
+
return candidate;
|
|
61
|
+
}
|
|
62
|
+
return path.join(typeRoot, `${name}.md`);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
9
65
|
const markdownSpec = {
|
|
10
66
|
isRelevantFile: (fileName) => path.extname(fileName).toLowerCase() === ".md",
|
|
11
67
|
toCanonicalName: (typeRoot, filePath) => {
|
|
@@ -60,15 +116,19 @@ const ASSET_SPECS_INTERNAL = {
|
|
|
60
116
|
knowledge: { stashDir: "knowledge", ...markdownSpec },
|
|
61
117
|
workflow: {
|
|
62
118
|
stashDir: "workflows",
|
|
63
|
-
...
|
|
119
|
+
...workflowSpec,
|
|
120
|
+
// Type-level renderer for markdown workflows; YAML programs are claimed by
|
|
121
|
+
// the dedicated `workflowProgramMatcher`, which names the
|
|
122
|
+
// "workflow-program-yaml" renderer directly on its MatchResult.
|
|
64
123
|
rendererName: "workflow-md",
|
|
65
124
|
actionBuilder: (ref) => buildWorkflowAction(ref),
|
|
66
125
|
},
|
|
67
126
|
script: { stashDir: "scripts", ...scriptSpec },
|
|
68
127
|
memory: { stashDir: "memories", ...markdownSpec },
|
|
69
128
|
// Environment assets — whole `.env` files sourced/injected wholesale. Replaced
|
|
70
|
-
// the deprecated `vault` type (removed in 0.9.0).
|
|
71
|
-
//
|
|
129
|
+
// the deprecated `vault` type (removed in 0.9.0). Only key NAMES are surfaced
|
|
130
|
+
// as metadata; values and comment text are never read for indexing (comments
|
|
131
|
+
// routinely contain commented-out credentials).
|
|
72
132
|
env: {
|
|
73
133
|
stashDir: "env",
|
|
74
134
|
isRelevantFile: (fileName) => fileName === ".env" || fileName.endsWith(".env"),
|
|
@@ -89,7 +149,7 @@ const ASSET_SPECS_INTERNAL = {
|
|
|
89
149
|
return path.join(typeRoot, name.endsWith(".env") ? name : `${name}.env`);
|
|
90
150
|
},
|
|
91
151
|
rendererName: "env-file",
|
|
92
|
-
actionBuilder: (ref) => `akm show ${ref} -> inspect key names; akm env run ${ref} -- <command> -> run with the whole .env injected (
|
|
152
|
+
actionBuilder: (ref) => `akm show ${ref} -> inspect key names; akm env run ${ref} -- <command> -> run with the whole .env injected (prefer --clean to minimize inherited parent env; child stdout is not redacted); akm env export ${ref} --out <file> -> write a sourceable script to a file`,
|
|
93
153
|
},
|
|
94
154
|
// Secrets — a single sensitive value used on its own for authentication (a
|
|
95
155
|
// PEM key, API token, TLS cert). Unlike `env` (a group of related .env
|
|
@@ -154,6 +214,20 @@ const ASSET_SPECS_INTERNAL = {
|
|
|
154
214
|
rendererName: "session-md",
|
|
155
215
|
actionBuilder: (ref) => `akm show ${ref} -> read the session summary; follow the \`access\` frontmatter to open the raw log at \`log_path\``,
|
|
156
216
|
},
|
|
217
|
+
// Durable stash-level semantic knowledge — facts about the user, team, or
|
|
218
|
+
// project (personal details, team tool stacks, coding conventions /
|
|
219
|
+
// "constitution", and stash-meta like naming conventions or the active
|
|
220
|
+
// projects list). Unlike `memory` (episodic, recency-decayed) these are
|
|
221
|
+
// mostly-static declarations meant to be reliably surfaced as context. A
|
|
222
|
+
// plain markdown spec; `category` frontmatter scopes the fact and
|
|
223
|
+
// `pinned: true` marks the small always-injected core. See
|
|
224
|
+
// docs/design/fact-asset-type.md.
|
|
225
|
+
fact: {
|
|
226
|
+
stashDir: "facts",
|
|
227
|
+
...markdownSpec,
|
|
228
|
+
rendererName: "fact-md",
|
|
229
|
+
actionBuilder: (ref) => `akm show ${ref} -> read the stash fact and apply it as durable context`,
|
|
230
|
+
},
|
|
157
231
|
};
|
|
158
232
|
export const ASSET_SPECS = ASSET_SPECS_INTERNAL;
|
|
159
233
|
/**
|