akm-cli 0.9.0 → 0.9.1-beta.2
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 +724 -0
- package/README.md +28 -63
- package/STABILITY.md +4 -2
- package/dist/cli/parse-args.js +7 -1
- package/dist/commands/agent/contribute-cli.js +1 -1
- package/dist/commands/env/child-env.js +14 -0
- package/dist/commands/feedback-cli.js +7 -1
- package/dist/commands/health/llm-usage.js +2 -1
- package/dist/commands/health/surfaces.js +4 -77
- package/dist/commands/health.js +65 -11
- package/dist/commands/improve/distill/quality-gate.js +6 -1
- package/dist/commands/improve/eligibility.js +7 -1
- package/dist/commands/improve/eval-cases.js +2 -0
- package/dist/commands/improve/improve.js +126 -10
- package/dist/commands/improve/locks.js +7 -0
- package/dist/commands/improve/memory/memory-improve.js +9 -0
- package/dist/commands/improve/run-context.js +5 -0
- package/dist/commands/improve/session-asset.js +4 -0
- package/dist/commands/lint/base-linter.js +31 -7
- package/dist/commands/lint/index.js +205 -51
- package/dist/commands/lint/types.js +22 -1
- package/dist/commands/proposal/repository.js +17 -1
- package/dist/commands/sources/add-cli.js +8 -2
- package/dist/commands/sources/info.js +12 -2
- package/dist/commands/sources/installed-stashes.js +6 -1
- package/dist/commands/sources/migration-help.js +12 -3
- package/dist/commands/sources/self-update.js +9 -1
- package/dist/commands/tasks/tasks.js +8 -2
- package/dist/commands/workflow-cli.js +17 -11
- package/dist/core/abort-deadline.js +28 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +83 -5
- package/dist/core/adapter/adapters/akm-adapter.js +13 -10
- package/dist/core/adapter/adapters/akm-lint.js +78 -22
- package/dist/core/adapter/adapters/akm-task-adapter.js +43 -20
- package/dist/core/adapter/adapters/dotenv-adapter.js +21 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +5 -3
- package/dist/core/asset/frontmatter.js +10 -1
- package/dist/core/common.js +147 -9
- package/dist/core/concurrent.js +32 -0
- package/dist/core/config/config-io.js +5 -45
- package/dist/core/config/schema/engines.js +14 -3
- package/dist/core/config/schema/workflow.js +11 -0
- package/dist/core/errors.js +25 -0
- package/dist/core/events.js +30 -24
- package/dist/core/extra-params.js +11 -0
- package/dist/core/file-lock.js +7 -1
- package/dist/core/fs-txn.js +15 -2
- package/dist/core/improve-result.js +5 -0
- package/dist/core/json-schema.js +344 -9
- package/dist/core/loopback.js +89 -0
- package/dist/core/migration-operation.js +17 -2
- package/dist/core/path-access.js +107 -0
- package/dist/core/paths.js +16 -2
- package/dist/core/redaction.js +86 -18
- package/dist/core/spawn-env.js +234 -0
- package/dist/core/state-db-scope.js +134 -0
- package/dist/core/state-db.js +1 -0
- package/dist/core/subprocess.js +181 -37
- package/dist/core/write-provenance.js +85 -0
- package/dist/core/write-source.js +33 -2
- package/dist/indexer/db/graph-db.js +17 -6
- package/dist/indexer/ensure-index.js +10 -3
- package/dist/indexer/index-written-assets.js +17 -2
- package/dist/indexer/indexer.js +86 -21
- package/dist/indexer/passes/memory-inference.js +4 -0
- package/dist/indexer/search/db-search.js +25 -17
- package/dist/indexer/walk/walker.js +6 -1
- package/dist/integrations/agent/detect.js +13 -1
- package/dist/integrations/agent/engine-resolution.js +24 -11
- package/dist/integrations/agent/model-aliases.js +1 -1
- package/dist/integrations/agent/profiles.js +9 -1
- package/dist/integrations/agent/spawn.js +15 -87
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +21 -0
- package/dist/integrations/lockfile.js +55 -2
- package/dist/llm/client.js +14 -19
- package/dist/llm/embedder.js +23 -3
- package/dist/llm/embedders/remote.js +27 -2
- package/dist/output/html-render.js +40 -1
- package/dist/output/text/lint-format.js +17 -4
- package/dist/runtime.js +23 -1
- package/dist/scripts/akm-migrate-node.js +1714 -836
- package/dist/scripts/akm-migrate.js +1682 -804
- package/dist/setup/setup.js +22 -7
- package/dist/sources/providers/git-install.js +25 -2
- package/dist/sources/providers/git-stash.js +19 -0
- package/dist/sources/providers/git.js +1 -1
- package/dist/sources/snapshot-fetchers/content-extract.js +63 -1
- package/dist/sources/snapshot-fetchers/website-ingest.js +126 -20
- package/dist/storage/database.js +71 -7
- package/dist/storage/engines/sqlite-migrations.js +61 -2
- package/dist/storage/managed-db.js +19 -0
- package/dist/storage/repositories/index-connection.js +39 -4
- package/dist/storage/repositories/index-entries-repository.js +6 -1
- package/dist/storage/repositories/index-meta-repository.js +11 -0
- package/dist/storage/repositories/index-schema.js +17 -2
- package/dist/storage/repositories/index-vec-repository.js +43 -5
- package/dist/storage/repositories/workflow-runs-repository.js +66 -13
- package/dist/storage/sqlite-pragmas.js +12 -1
- package/dist/tasks/log-redaction.js +156 -0
- package/dist/tasks/parser.js +82 -5
- package/dist/tasks/runner.js +222 -17
- package/dist/tasks/scheduler-invocation.js +19 -0
- package/dist/tasks/schema.js +86 -1
- package/dist/text-import-hook.mjs +1 -1
- package/dist/workflows/concurrency-policy.js +95 -1
- package/dist/workflows/exec/dispatch-redaction.js +114 -0
- package/dist/workflows/exec/exec-unit.js +542 -0
- package/dist/workflows/exec/frozen-judge.js +114 -42
- package/dist/workflows/exec/native-executor.js +465 -238
- package/dist/workflows/exec/param-secrets.js +4 -3
- package/dist/workflows/exec/run-workflow.js +424 -219
- package/dist/workflows/exec/step-work.js +506 -167
- package/dist/workflows/exec/unit-dispatch.js +31 -1
- package/dist/workflows/exec/unit-writer.js +53 -13
- package/dist/workflows/exec/worktree.js +454 -41
- package/dist/workflows/ir/compile.js +26 -2
- package/dist/workflows/ir/freeze.js +82 -15
- package/dist/workflows/ir/schema.js +105 -20
- package/dist/workflows/parser.js +242 -19
- package/dist/workflows/program/schema.js +24 -0
- package/dist/workflows/renderer.js +32 -4
- package/dist/workflows/resource-limits.js +182 -0
- package/dist/workflows/runtime/runs.js +146 -6
- package/dist/workflows/validate-summary.js +17 -2
- package/docs/README.md +74 -32
- package/docs/migration/release-notes/0.9.0.md +2 -1
- package/docs/migration/v0.7-to-v0.8.md +2 -1
- package/docs/migration/v0.8-to-v0.9.md +3 -1
- package/docs/reference/README.md +11 -4
- package/docs/reference/bundle-types.md +19 -0
- package/docs/reference/cli.md +105 -16
- package/docs/reference/configuration.md +15 -2
- package/docs/reference/data-and-telemetry.md +30 -10
- package/docs/reference/supported-formats.md +50 -0
- package/docs/reference/workflow-schema.md +1014 -0
- package/docs/reference/workflows.md +37 -633
- package/package.json +13 -6
- package/schemas/akm-config.json +18 -5
- package/schemas/akm-task.json +27 -5
- package/schemas/akm-workflow.json +92 -13
|
@@ -1,10 +1,57 @@
|
|
|
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
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The gate judge built from a frozen v3 engine catalog.
|
|
6
|
+
*
|
|
7
|
+
* Two contracts this module owns, both of which the rest of the engine already
|
|
8
|
+
* enforces for ordinary units and neither of which the judge may opt out of:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Redaction.** A judge response IS journaled — `journalGateEvaluationFinish`
|
|
11
|
+
* (exec/step-work.ts) writes the parsed verdict into the gate row's
|
|
12
|
+
* `result_json`, and a judge failure's message becomes the blocked step's
|
|
13
|
+
* notes. So the judge outcome goes through the SAME scrub every unit outcome
|
|
14
|
+
* goes through: {@link collectWorkflowDispatchSensitiveValues} +
|
|
15
|
+
* {@link withDispatchRedaction} (exec/dispatch-redaction.ts). Nothing about
|
|
16
|
+
* a judge call reaches durable state before that scrub. BOTH branches below
|
|
17
|
+
* state it that way — the agent branch wrapping the injected dispatcher, the
|
|
18
|
+
* llm branch wrapping its own chatCompletion call — so a change to that one
|
|
19
|
+
* contract cannot reach only one of the two judge paths.
|
|
20
|
+
*
|
|
21
|
+
* 2. **Identity.** The dispatch request carries the REAL run/step and the gate's
|
|
22
|
+
* real node/unit ids — the same ids `journalGateEvaluationStart/Finish` write
|
|
23
|
+
* (`<stepId>.gate` / `<stepId>.gate:l<loop>`) — so per-dispatch telemetry and
|
|
24
|
+
* harness-side correlation describe the same thing the gate row describes.
|
|
25
|
+
* The identity is threaded in from the caller that writes the row
|
|
26
|
+
* ({@link SummaryJudge}'s `identity` argument); it is never synthesized here.
|
|
27
|
+
*
|
|
28
|
+
* A judge dispatch carries NO `env` bindings: a gate judge is an
|
|
29
|
+
* {@link IrInvocation} (`IrGateNode.judge`), which has no `env` key, so there is
|
|
30
|
+
* nothing authored to thread — and a step's unit `env` is scoped to the WORK,
|
|
31
|
+
* not to the verifier. Redaction is unaffected: the sensitive-value set below
|
|
32
|
+
* still covers the judge engine's credential and unsafe passthrough values.
|
|
33
|
+
*
|
|
34
|
+
* @module workflows/exec/frozen-judge
|
|
35
|
+
*/
|
|
5
36
|
import { ConfigError } from "../../core/errors.js";
|
|
37
|
+
import { collectWorkflowDispatchSensitiveValues, withDispatchRedaction } from "./dispatch-redaction.js";
|
|
38
|
+
import { materializeFrozenLlm } from "./unit-dispatch.js";
|
|
39
|
+
/** The gate's node id — identical to what `journalGateEvaluationStart` writes. */
|
|
40
|
+
export function gateNodeId(stepId) {
|
|
41
|
+
return `${stepId}.gate`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Identity for one judge dispatch: the journaling caller's exact row identity
|
|
45
|
+
* when it supplied one, else the owning run/step with the gate's node id as the
|
|
46
|
+
* unit id. Either way the request names the REAL run — never a synthetic
|
|
47
|
+
* `"gate"` placeholder, which made every judge dispatch indistinguishable from
|
|
48
|
+
* every other one.
|
|
49
|
+
*/
|
|
50
|
+
function dispatchIdentity(owner, identity) {
|
|
51
|
+
return identity ?? { ...owner, unitId: gateNodeId(owner.stepId) };
|
|
52
|
+
}
|
|
6
53
|
/** Build a gate judge from a v3 catalog entry without consulting live config. */
|
|
7
|
-
export function frozenSummaryJudge(plan, invocation, signal, dispatcher) {
|
|
54
|
+
export function frozenSummaryJudge(plan, invocation, signal, dispatcher, owner) {
|
|
8
55
|
if (!invocation)
|
|
9
56
|
return null;
|
|
10
57
|
const engine = plan.execution?.engines[invocation.engine];
|
|
@@ -14,60 +61,85 @@ export function frozenSummaryJudge(plan, invocation, signal, dispatcher) {
|
|
|
14
61
|
if (!dispatcher) {
|
|
15
62
|
throw new ConfigError(`Frozen agent gate engine "${invocation.engine}" has no unit dispatcher.`, "INVALID_CONFIG_FILE");
|
|
16
63
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
64
|
+
const fallbackEngine = engine.fallbackLlmEngine ? plan.execution.engines[engine.fallbackLlmEngine] : undefined;
|
|
65
|
+
const fallback = fallbackEngine?.kind === "llm" ? fallbackEngine : undefined;
|
|
66
|
+
// Scrub at the seam: every outcome this judge's dispatcher returns — and
|
|
67
|
+
// every error it throws — is redacted BEFORE the verdict (or the failure
|
|
68
|
+
// message) can reach the gate row / the blocked step's notes. Identical
|
|
69
|
+
// contract to the llm branch below and to the unit path, including the
|
|
70
|
+
// failureReason downgrade when redaction altered it.
|
|
71
|
+
const dispatch = withDispatchRedaction(dispatcher);
|
|
72
|
+
return async ({ system, user }, identity) => {
|
|
73
|
+
const id = dispatchIdentity(owner, identity);
|
|
74
|
+
// Collected per dispatch, not once per judge: the engine PAIR is fixed at
|
|
75
|
+
// build time but its secrets are not — they are read from `process.env`,
|
|
76
|
+
// which the dispatch itself re-reads, so a build-time set would miss a
|
|
77
|
+
// credential set or rotated between the two reads. Same collector the unit
|
|
78
|
+
// path uses; see the module doc on why `env` is absent here but the
|
|
79
|
+
// credential/passthrough values are still collected.
|
|
80
|
+
const sensitiveValues = collectWorkflowDispatchSensitiveValues({ engine, ...(fallback ? { fallbackEngine: fallback } : {}) }, undefined);
|
|
81
|
+
const outcome = await dispatch({
|
|
82
|
+
runId: id.runId,
|
|
83
|
+
stepId: id.stepId,
|
|
84
|
+
unitId: id.unitId,
|
|
85
|
+
nodeId: gateNodeId(id.stepId),
|
|
24
86
|
prompt: user,
|
|
25
87
|
systemPrompt: system,
|
|
26
88
|
engine,
|
|
27
|
-
...(
|
|
89
|
+
...(fallback ? { fallbackEngine: fallback } : {}),
|
|
28
90
|
invocation,
|
|
29
91
|
timeoutMs: invocation.timeoutMs,
|
|
92
|
+
...(sensitiveValues.length > 0 ? { sensitiveValues } : {}),
|
|
30
93
|
...(signal ? { signal } : {}),
|
|
31
94
|
});
|
|
32
|
-
if (!
|
|
33
|
-
throw new Error(
|
|
95
|
+
if (!outcome.ok) {
|
|
96
|
+
throw new Error(outcome.error || `Verification engine "${invocation.engine}" failed.`);
|
|
34
97
|
}
|
|
35
|
-
return
|
|
98
|
+
return outcome.text ?? "";
|
|
36
99
|
};
|
|
37
100
|
}
|
|
38
|
-
|
|
101
|
+
// The llm judge's ONE call, shaped as a {@link UnitDispatcher} so this branch
|
|
102
|
+
// states its redaction through the SAME {@link withDispatchRedaction} contract
|
|
103
|
+
// the agent branch above uses — including the throw, which a transport error
|
|
104
|
+
// takes and which becomes the blocked step's notes (`judgeFailure` in
|
|
105
|
+
// step-work.ts).
|
|
106
|
+
//
|
|
107
|
+
// Inline chatCompletion rather than the injected unit dispatcher ON PURPOSE:
|
|
108
|
+
// the manual completion path (`runtime/runs.ts`) builds an llm judge with no
|
|
109
|
+
// dispatcher, and a static runs → native-executor edge would close an import
|
|
110
|
+
// cycle. The materialization itself is the shared {@link materializeFrozenLlm},
|
|
111
|
+
// so the two llm dispatch paths cannot drift.
|
|
112
|
+
const dispatch = withDispatchRedaction(async (request) => {
|
|
39
113
|
const { chatCompletion } = await import("../../llm/client.js");
|
|
40
|
-
|
|
41
|
-
{ role: "system", content:
|
|
42
|
-
{ role: "user", content:
|
|
114
|
+
const text = await chatCompletion(materializeFrozenLlm(engine, invocation), [
|
|
115
|
+
{ role: "system", content: request.systemPrompt ?? "" },
|
|
116
|
+
{ role: "user", content: request.prompt },
|
|
43
117
|
], {
|
|
118
|
+
timeoutMs: request.timeoutMs,
|
|
119
|
+
...(signal ? { signal } : {}),
|
|
120
|
+
});
|
|
121
|
+
return { ok: true, text };
|
|
122
|
+
});
|
|
123
|
+
return async ({ system, user }, identity) => {
|
|
124
|
+
const id = dispatchIdentity(owner, identity);
|
|
125
|
+
// An llm judge's only secret is its own credential, which
|
|
126
|
+
// `materializeFrozenLlm` resolves out of `process.env` inside the dispatch
|
|
127
|
+
// below — so the set is collected here, per dispatch, and cannot predate the
|
|
128
|
+
// value the call actually authenticates with.
|
|
129
|
+
const sensitiveValues = collectWorkflowDispatchSensitiveValues({ engine }, undefined);
|
|
130
|
+
const outcome = await dispatch({
|
|
131
|
+
runId: id.runId,
|
|
132
|
+
stepId: id.stepId,
|
|
133
|
+
unitId: id.unitId,
|
|
134
|
+
nodeId: gateNodeId(id.stepId),
|
|
135
|
+
prompt: user,
|
|
136
|
+
systemPrompt: system,
|
|
137
|
+
engine,
|
|
138
|
+
invocation,
|
|
44
139
|
timeoutMs: invocation.timeoutMs,
|
|
140
|
+
...(sensitiveValues.length > 0 ? { sensitiveValues } : {}),
|
|
45
141
|
...(signal ? { signal } : {}),
|
|
46
142
|
});
|
|
143
|
+
return outcome.text;
|
|
47
144
|
};
|
|
48
145
|
}
|
|
49
|
-
function materialize(engine, invocation) {
|
|
50
|
-
let apiKey;
|
|
51
|
-
for (const name of engine.credential?.names ?? []) {
|
|
52
|
-
const value = process.env[name]?.trim();
|
|
53
|
-
if (value) {
|
|
54
|
-
apiKey = value;
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
if (engine.credential?.required && !apiKey)
|
|
59
|
-
throw new ConfigError(`Required engine credential ${engine.credential.names[0]} is not set.`, "INVALID_CONFIG_FILE");
|
|
60
|
-
const base = {
|
|
61
|
-
provider: engine.provider,
|
|
62
|
-
endpoint: engine.endpoint,
|
|
63
|
-
model: invocation.model ?? engine.model,
|
|
64
|
-
...(engine.temperature !== undefined ? { temperature: engine.temperature } : {}),
|
|
65
|
-
...(engine.maxTokens !== undefined ? { maxTokens: engine.maxTokens } : {}),
|
|
66
|
-
...(engine.supportsJsonSchema !== undefined ? { supportsJsonSchema: engine.supportsJsonSchema } : {}),
|
|
67
|
-
...(engine.extraParams ? { extraParams: engine.extraParams } : {}),
|
|
68
|
-
...(engine.contextLength !== undefined ? { contextLength: engine.contextLength } : {}),
|
|
69
|
-
...(engine.enableThinking !== undefined ? { enableThinking: engine.enableThinking } : {}),
|
|
70
|
-
...(apiKey ? { apiKey } : {}),
|
|
71
|
-
};
|
|
72
|
-
return (invocation.llm ? deepMergeConfig(base, invocation.llm) : base);
|
|
73
|
-
}
|