akm-cli 0.9.31 → 0.10.261002-beta
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 +420 -0
- package/STABILITY.md +99 -57
- package/dist/api-node.mjs +20 -0
- package/dist/api.d.ts +23 -0
- package/dist/api.js +45 -0
- package/dist/assets/hints/cli-hints-full.md +15 -29
- package/dist/assets/hints/cli-hints-short.md +2 -2
- package/dist/assets/improve-strategies/default.json +3 -3
- package/dist/assets/prompts/consolidate-pair.md +9 -7
- package/dist/assets/stash-skeleton/README.md +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/cli/shared.js +31 -48
- package/dist/cli/unknown-flags.js +6 -43
- package/dist/cli.js +8 -34
- package/dist/commands/agent/contribute-cli.js +1 -1
- package/dist/commands/completions.js +1 -2
- package/dist/commands/config-cli.js +5 -28
- package/dist/commands/env/env-cli.js +5 -5
- package/dist/commands/env/secret-cli.js +2 -2
- package/dist/commands/feedback-cli.js +75 -49
- package/dist/commands/health/checks.js +41 -16
- package/dist/commands/health/plugin-staleness.js +52 -22
- package/dist/commands/improve/autonomy-gate.js +5 -3
- package/dist/commands/improve/consolidate/chunking.js +3 -10
- package/dist/commands/improve/consolidate/continuity-check.js +4 -4
- package/dist/commands/improve/consolidate/pair-pass.js +29 -10
- package/dist/commands/improve/consolidate.js +10 -65
- package/dist/commands/improve/distill/lesson-update.js +91 -0
- package/dist/commands/improve/distill-guards.js +1 -43
- package/dist/commands/improve/distill.js +148 -21
- package/dist/commands/improve/eligibility.js +14 -1
- package/dist/commands/improve/extract-cli.js +1 -1
- package/dist/commands/improve/extract-prompt.js +17 -7
- package/dist/commands/improve/extract.js +5 -7
- package/dist/commands/improve/improve-cli.js +92 -106
- package/dist/commands/improve/improve-strategies.js +8 -12
- package/dist/commands/improve/improve.js +134 -52
- package/dist/commands/improve/loop-stages.js +18 -5
- package/dist/commands/improve/planner.js +0 -1
- package/dist/commands/improve/preparation.js +40 -99
- package/dist/commands/improve/proactive-maintenance.js +2 -2
- package/dist/commands/improve/reflect-noise.js +3 -55
- package/dist/commands/improve/reflect.js +29 -34
- package/dist/commands/improve/retrieval-queries.js +37 -0
- package/dist/commands/improve/retrieval-scope.js +2 -2
- package/dist/commands/improve/salience.js +2 -9
- package/dist/commands/improve/session-asset.js +4 -1
- package/dist/commands/improve/stage.js +23 -12
- package/dist/commands/lint/index.js +5 -20
- package/dist/commands/observability-cli.js +3 -9
- package/dist/commands/proposal/drain.js +43 -6
- package/dist/commands/proposal/proposal-cli.js +11 -31
- package/dist/commands/proposal/repository.js +20 -14
- package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -3
- package/dist/commands/read/knowledge.js +3 -3
- package/dist/commands/read/remember-cli.js +0 -13
- package/dist/commands/read/search-cli.js +29 -97
- package/dist/commands/read/search.js +0 -11
- package/dist/commands/read/show.js +0 -19
- package/dist/commands/sources/plugin-upgrade.js +164 -101
- package/dist/commands/sources/sources-cli.js +1 -15
- package/dist/commands/sources/stash-cli.js +6 -14
- package/dist/commands/tasks/tasks-cli.js +4 -115
- package/dist/commands/workflow/plan.js +11 -33
- package/dist/commands/workflow-cli.js +2 -7
- package/dist/core/adapter/adapter-ids.js +1 -2
- package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
- package/dist/core/adapter/adapters/akm-adapter.js +9 -48
- package/dist/core/adapter/adapters/akm-lint.js +10 -26
- package/dist/core/adapter/adapters/akm-metadata.js +2 -72
- package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
- package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
- package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
- package/dist/core/adapter/recognize-match.js +3 -4
- package/dist/core/common.js +18 -2
- package/dist/core/config/config-schema.js +12 -15
- package/dist/core/config/config-types.js +6 -15
- package/dist/core/config/config-walker.js +6 -23
- package/dist/core/config/config.js +17 -80
- package/dist/core/config/engine-semantics.js +7 -3
- package/dist/core/config/schema/engines.js +7 -7
- package/dist/core/config/schema/improve-processes.js +10 -63
- package/dist/core/config/schema/improve.js +2 -21
- package/dist/core/config/schema/index-config.js +6 -39
- package/dist/core/env-secret-ref.js +2 -45
- package/dist/core/errors.js +1 -2
- package/dist/core/extra-params.js +2 -86
- package/dist/core/file-lock.js +2 -6
- package/dist/core/improve-result.js +13 -1
- package/dist/core/mutation-target.js +2 -2
- package/dist/core/paths.js +4 -0
- package/dist/core/recognition-util.js +4 -5
- package/dist/core/run-lock.js +1 -1
- package/dist/core/subprocess.js +49 -0
- package/dist/core/warn.js +21 -4
- package/dist/core/write-source.js +3 -3
- package/dist/execution/target-ref.js +1 -2
- package/dist/indexer/indexer.js +15 -6
- package/dist/indexer/passes/memory-inference.js +15 -6
- package/dist/indexer/search/db-search.js +49 -36
- package/dist/indexer/search/fts-query.js +0 -19
- package/dist/indexer/search/ranking.js +29 -1
- package/dist/indexer/usage/usage-events.js +21 -16
- package/dist/integrations/agent/engine-resolution.js +5 -2
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +41 -98
- package/dist/integrations/agent/request-lowering.js +3 -3
- package/dist/integrations/harnesses/aider/index.js +5 -0
- package/dist/integrations/harnesses/amazonq/index.js +1 -0
- package/dist/integrations/harnesses/claude/config-import.js +2 -3
- package/dist/integrations/harnesses/claude/index.js +5 -0
- package/dist/integrations/harnesses/codex/index.js +1 -0
- package/dist/integrations/harnesses/copilot/index.js +1 -0
- package/dist/integrations/harnesses/gemini/index.js +1 -0
- package/dist/integrations/harnesses/index.js +18 -39
- package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
- package/dist/integrations/harnesses/opencode/config-import.js +121 -52
- package/dist/integrations/harnesses/opencode/index.js +22 -0
- package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
- package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
- package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
- package/dist/integrations/harnesses/opencode/session-log.js +104 -115
- package/dist/integrations/harnesses/opencode/version.js +98 -0
- package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +254 -0
- package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
- package/dist/integrations/harnesses/openhands/index.js +1 -0
- package/dist/integrations/harnesses/pi/index.js +1 -0
- package/dist/integrations/harnesses/shared.js +2 -0
- package/dist/integrations/harnesses/types.js +2 -0
- package/dist/llm/client.js +41 -11
- package/dist/output/cli-hints.js +1 -1
- package/dist/output/context.js +10 -19
- package/dist/output/format-exempt.js +5 -8
- package/dist/output/shapes/helpers.js +1 -22
- package/dist/output/shapes/passthrough.js +0 -1
- package/dist/output/shapes.js +3 -31
- package/dist/output/stdout.js +5 -1
- package/dist/output/text/command-format.js +6 -1
- package/dist/output/text/workflow-format.js +4 -22
- package/dist/scripts/akm-migrate-node.js +15745 -16711
- package/dist/scripts/akm-migrate.js +16318 -17280
- package/dist/setup/detect.js +10 -4
- package/dist/setup/harness-config-import.js +5 -14
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/tasks.js +12 -13
- package/dist/sources/providers/git-stash.js +113 -16
- package/dist/storage/repositories/index-utility-repository.js +2 -32
- package/dist/storage/repositories/index-vec-repository.js +4 -0
- package/dist/storage/repositories/task-history-repository.js +0 -5
- package/dist/storage/repositories/workflow-runs-repository.js +5 -15
- package/dist/tasks/embedded.js +2 -1
- package/dist/tasks/run/run-command-task.js +9 -1
- package/dist/tasks/run/run-workflow-task.js +4 -3
- package/dist/tasks/run/task-history.js +0 -2
- package/dist/tasks/run/task-log.js +38 -1
- package/dist/tasks/schedule-gates.js +39 -0
- package/dist/tasks/scheduler-binding.js +0 -16
- package/dist/tasks/scheduler-sync.js +3 -97
- package/dist/tasks/source/bounded-document.js +1 -1
- package/dist/tasks/source/task-source-v4.js +2 -12
- package/dist/tasks/task-run-reserved-flags.js +2 -31
- package/dist/workflows/authoring/authoring.js +6 -6
- package/dist/workflows/compile.js +8 -65
- package/dist/workflows/exec/child-workflow.js +22 -3
- package/dist/workflows/exec/native-executor.js +12 -147
- package/dist/workflows/exec/run-workflow.js +31 -103
- package/dist/workflows/exec/step-work.js +9 -178
- package/dist/workflows/exec/unit-dispatch.js +0 -10
- package/dist/workflows/freeze/environment.js +3 -44
- package/dist/workflows/freeze/freeze.js +8 -41
- package/dist/workflows/freeze/targets/child-workflow.js +27 -63
- package/dist/workflows/freeze/targets/command.js +2 -16
- package/dist/workflows/freeze/targets/shell.js +0 -2
- package/dist/workflows/freeze/task-bindings.js +2 -28
- package/dist/workflows/ir/params.js +12 -2
- package/dist/workflows/parser.js +82 -232
- package/dist/workflows/plan.js +1 -1
- package/dist/workflows/renderer.js +10 -19
- package/dist/workflows/runtime/run-plan.js +11 -53
- package/dist/workflows/runtime/runs.js +4 -27
- package/dist/workflows/source-files.js +12 -16
- package/dist/workflows/source-semantics.js +1 -93
- package/docs/README.md +1 -1
- package/docs/agents/README.md +3 -3
- package/docs/agents/agent-install.md +1 -1
- package/docs/architecture/0.10-process-rules.md +827 -0
- package/docs/architecture/adapters.md +17 -31
- package/docs/architecture/architecture.md +4 -5
- package/docs/architecture/improvement.md +115 -76
- package/docs/architecture/internals/improve-workflow.md +22 -16
- package/docs/architecture/internals/indexing.md +1 -1
- package/docs/architecture/internals/search.md +1 -2
- package/docs/architecture/internals/storage-locations.md +6 -6
- package/docs/architecture/persisted-data-compat.md +13 -4
- package/docs/architecture/specs/0.9.0-decisions.md +6 -2
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +2 -2
- package/docs/architecture/specs/workflow-format-unification.md +1 -6
- package/docs/architecture/testing/manual-testing-checklist.md +21 -30
- package/docs/architecture/testing/task-workflow-manual-tests.md +106 -203
- package/docs/architecture/testing/testing-workflow.md +1 -1
- package/docs/architecture/workflow-engine.md +5 -56
- package/docs/guides/author-workflows.md +39 -69
- package/docs/guides/bundles.md +3 -1
- package/docs/guides/capture-knowledge.md +1 -1
- package/docs/guides/claude-code-vs-akm-workflows.md +1 -2
- package/docs/guides/discover-and-load.md +4 -4
- package/docs/guides/getting-started.md +1 -1
- package/docs/guides/improve-the-library.md +10 -9
- package/docs/guides/recipes/headless-install.md +2 -2
- package/docs/guides/run-workflows.md +1 -1
- package/docs/guides/scheduling.md +9 -1
- package/docs/guides/use-with-any-agent.md +49 -4
- package/docs/integration/bundling-akm.md +7 -6
- package/docs/maintainers/curate-workmap.md +1 -2
- package/docs/maintainers/release-checklist.md +33 -1
- package/docs/migration/README.md +2 -0
- package/docs/migration/release-notes/0.10.0.md +201 -0
- package/docs/migration/release-notes/README.md +1 -0
- package/docs/migration/v0.9-to-v0.10.md +507 -0
- package/docs/posts/akm-command-tour.md +3 -3
- package/docs/product-surface.md +1 -1
- package/docs/reference/README.md +1 -0
- package/docs/reference/api.md +65 -0
- package/docs/reference/asset-types.md +3 -5
- package/docs/reference/bundle-types.md +2 -4
- package/docs/reference/cli.md +160 -188
- package/docs/reference/configuration.md +101 -20
- package/docs/reference/data-and-telemetry.md +2 -2
- package/docs/reference/env-and-secrets.md +2 -2
- package/docs/reference/supported-formats.md +3 -4
- package/docs/reference/tasks.md +12 -19
- package/docs/reference/website-sources.md +1 -1
- package/docs/reference/workflow-schema.md +89 -317
- package/docs/reference/workflows.md +20 -48
- package/package.json +12 -2
- package/schemas/akm-config.json +2 -243
- package/schemas/akm-task.json +2 -3
- package/schemas/akm-workflow.json +47 -84
- package/dist/assets/improve-strategies/catchup.json +0 -41
- package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
- package/dist/assets/improve-strategies/quick.json +0 -17
- package/dist/assets/improve-strategies/reflect-distill.json +0 -29
- package/dist/assets/improve-strategies/thorough.json +0 -49
- package/dist/assets/prompts/retrieval-relevance-judge.md +0 -6
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
- package/dist/cli/retired-commands.js +0 -118
- package/dist/commands/improve/retrieval-gate.js +0 -132
- package/dist/commands/tasks/validate.js +0 -176
- package/dist/core/config/legacy-source-shape-shim.js +0 -117
- package/dist/indexer/feedback/utility-policy.js +0 -75
- package/dist/integrations/harnesses/ids.js +0 -28
- package/dist/tasks/source/task-source-v3-frozen.js +0 -424
- package/dist/tasks/source/task-to-v4.js +0 -863
- package/dist/workflows/exec/worktree.js +0 -372
- package/dist/workflows/freeze/child-output-references.js +0 -83
- package/dist/workflows/freeze/identity.js +0 -22
- package/dist/workflows/freeze/targets/script.js +0 -50
- package/dist/workflows/freeze/targets/task.js +0 -124
- package/dist/workflows/github-yaml.js +0 -506
- package/dist/workflows/runtime/run-outputs.js +0 -80
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* The retrieval regression gate (#722): a reflect rewrite of an existing asset
|
|
6
|
-
* must not grade lower on the queries that actually retrieved it.
|
|
7
|
-
*
|
|
8
|
-
* Measured before it was built: of 60 accepted reflect rewrites judged against
|
|
9
|
-
* their own queries, 14 graded lower (23%, 95% CI 14–35%) and 12 higher. The
|
|
10
|
-
* old and new content are graded one query at a time, blind, with the
|
|
11
|
-
* retrieval-eval judge's prompt (kappa 0.83 against human grades) and its
|
|
12
|
-
* document shape: type, ref, name, description and the first 1,500 characters
|
|
13
|
-
* of the body.
|
|
14
|
-
*/
|
|
15
|
-
import relevanceJudgePrompt from "../../assets/prompts/retrieval-relevance-judge.md" with { type: "text" };
|
|
16
|
-
import { parseFrontmatter } from "../../core/asset/frontmatter.js";
|
|
17
|
-
import { parseRefInput } from "../../core/asset/resolve-ref.js";
|
|
18
|
-
import { nonTaskInput } from "../../core/non-task-input.js";
|
|
19
|
-
import { parseEmbeddedJsonResponse } from "../../core/parse.js";
|
|
20
|
-
import { listRetrievalQueries } from "../../indexer/usage/usage-events.js";
|
|
21
|
-
import { readLedgerDb, stripBundle } from "./ledger.js";
|
|
22
|
-
import { callStage } from "./stage.js";
|
|
23
|
-
/** Queries graded per rewrite, as measured. */
|
|
24
|
-
const MAX_QUERIES = 5;
|
|
25
|
-
/** The retrieval suite treats a longer input as a paste, not a query; the measurement did the same. */
|
|
26
|
-
const MAX_QUERY_CHARS = 2000;
|
|
27
|
-
/** The judge sees this much of the body, as in the retrieval eval. */
|
|
28
|
-
const MAX_DOC_CHARS = 1500;
|
|
29
|
-
export const GRADE_SCHEMA = {
|
|
30
|
-
type: "object",
|
|
31
|
-
required: ["grade", "reason"],
|
|
32
|
-
additionalProperties: false,
|
|
33
|
-
properties: { grade: { type: "integer", minimum: 0, maximum: 3 }, reason: { type: "string" } },
|
|
34
|
-
};
|
|
35
|
-
function parseGrade(raw) {
|
|
36
|
-
const grade = parseEmbeddedJsonResponse(raw)?.grade;
|
|
37
|
-
return typeof grade === "number" && Number.isInteger(grade) && grade >= 0 && grade <= 3 ? grade : undefined;
|
|
38
|
-
}
|
|
39
|
-
/** Up to five distinct task queries, in the given order, whitespace collapsed. */
|
|
40
|
-
export function usableRetrievalQueries(raw) {
|
|
41
|
-
const out = [];
|
|
42
|
-
for (const text of raw) {
|
|
43
|
-
const query = text.replace(/\s+/g, " ").trim();
|
|
44
|
-
if (!query || query.length > MAX_QUERY_CHARS || nonTaskInput(query) || out.includes(query))
|
|
45
|
-
continue;
|
|
46
|
-
out.push(query);
|
|
47
|
-
if (out.length === MAX_QUERIES)
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
return out;
|
|
51
|
-
}
|
|
52
|
-
/** The asset's own retrieval queries from the usage log (none when state.db cannot be read). */
|
|
53
|
-
export function loadRetrievalQueries(access, ref) {
|
|
54
|
-
try {
|
|
55
|
-
return usableRetrievalQueries(readLedgerDb(access, (db) => listRetrievalQueries(db, stripBundle(ref))) ?? []);
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
return [];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function judgeDocument(ref, raw) {
|
|
62
|
-
const conceptId = stripBundle(ref);
|
|
63
|
-
const parsed = parseRefInput(conceptId);
|
|
64
|
-
const { data, content } = parseFrontmatter(raw);
|
|
65
|
-
const text = content
|
|
66
|
-
.replace(/\n{3,}/g, "\n\n")
|
|
67
|
-
.trim()
|
|
68
|
-
.slice(0, MAX_DOC_CHARS);
|
|
69
|
-
const name = typeof data.name === "string" && data.name ? data.name : parsed.name;
|
|
70
|
-
const description = typeof data.description === "string" ? data.description : "";
|
|
71
|
-
return [
|
|
72
|
-
"Candidate asset:",
|
|
73
|
-
`Type: ${parsed.type}`,
|
|
74
|
-
`Ref: ${conceptId}`,
|
|
75
|
-
`Name: ${name}`,
|
|
76
|
-
`Description: ${description}`,
|
|
77
|
-
"",
|
|
78
|
-
"Content:",
|
|
79
|
-
text,
|
|
80
|
-
].join("\n");
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Grade `before` and `after` on each query; refuse the rewrite when the new
|
|
84
|
-
* content's mean grade is lower. Fails closed, like the quality judge: a grade
|
|
85
|
-
* that cannot be obtained refuses the rewrite.
|
|
86
|
-
*/
|
|
87
|
-
export async function runRetrievalRegressionGate(args) {
|
|
88
|
-
if (args.queries.length === 0)
|
|
89
|
-
return { pass: true, queries: 0, reason: "no retrieval queries to compare on" };
|
|
90
|
-
const documents = { old: judgeDocument(args.ref, args.before), new: judgeDocument(args.ref, args.after) };
|
|
91
|
-
const totals = { old: 0, new: 0 };
|
|
92
|
-
for (const query of args.queries) {
|
|
93
|
-
for (const version of ["old", "new"]) {
|
|
94
|
-
const outcome = await callStage({
|
|
95
|
-
feature: "proposal_quality_gate",
|
|
96
|
-
runner: args.runner,
|
|
97
|
-
system: relevanceJudgePrompt.trim(),
|
|
98
|
-
prompt: `Query: ${query}\n\n${documents[version]}`,
|
|
99
|
-
request: {
|
|
100
|
-
enableThinking: false,
|
|
101
|
-
temperature: 0,
|
|
102
|
-
responseSchema: GRADE_SCHEMA,
|
|
103
|
-
...(args.timeoutMs !== undefined ? { timeoutMs: args.timeoutMs } : {}),
|
|
104
|
-
...(args.signal ? { signal: args.signal } : {}),
|
|
105
|
-
...(args.chat ? { chat: args.chat } : {}),
|
|
106
|
-
},
|
|
107
|
-
parse: parseGrade,
|
|
108
|
-
...(args.onNotices ? { onNotices: args.onNotices } : {}),
|
|
109
|
-
});
|
|
110
|
-
const grade = outcome.ok ? parseGrade(outcome.raw) : undefined;
|
|
111
|
-
if (grade === undefined) {
|
|
112
|
-
return {
|
|
113
|
-
pass: false,
|
|
114
|
-
queries: args.queries.length,
|
|
115
|
-
reason: `retrieval check could not grade the ${version} content${outcome.ok ? "" : ` (${outcome.reason})`}`,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
totals[version] += grade;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
const oldMean = totals.old / args.queries.length;
|
|
122
|
-
const newMean = totals.new / args.queries.length;
|
|
123
|
-
const pass = newMean >= oldMean;
|
|
124
|
-
const grades = `${oldMean.toFixed(2)} -> ${newMean.toFixed(2)} over ${args.queries.length} retrieval ${args.queries.length === 1 ? "query" : "queries"}`;
|
|
125
|
-
return {
|
|
126
|
-
pass,
|
|
127
|
-
queries: args.queries.length,
|
|
128
|
-
oldMean,
|
|
129
|
-
newMean,
|
|
130
|
-
reason: pass ? `retrieval grade ${grades}` : `retrieval regression: grade ${grades}`,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* `akm task validate <path>` (#907) — parse ONE task file by filesystem
|
|
6
|
-
* path, not a concept ref/id, and report the same diagnostic `akm task
|
|
7
|
-
* sync` would produce for it. The file need not live in any configured
|
|
8
|
-
* bundle: unlike every other `akm task` subcommand, this one never resolves
|
|
9
|
-
* a bundle/adapter/concept id at all — it reads exactly the path it was
|
|
10
|
-
* given and classifies it.
|
|
11
|
-
*
|
|
12
|
-
* Reuses the exact version router `parseTaskSource`
|
|
13
|
-
* (`src/tasks/source/parse-task-source.ts`) every other task-source reader
|
|
14
|
-
* uses (`akm task sync`'s `compileTaskSources` included) — this module never
|
|
15
|
-
* forks a second parser. `readBoundedTaskSourceYaml` /
|
|
16
|
-
* `peekTaskSourceVersion` / `own` are the SAME front-end helpers the router
|
|
17
|
-
* calls first; they are used here only to recover the file's DECLARED schema
|
|
18
|
-
* version for the report and to tell `blocked` from `invalid`.
|
|
19
|
-
*
|
|
20
|
-
* Beyond parsing, this module also runs the SAME two per-source gates
|
|
21
|
-
* `akm task sync`'s `compileTaskSources` runs before it ever installs a
|
|
22
|
-
* schedule — `assertTaskScheduleInputsSatisfyContract` and
|
|
23
|
-
* `assertTaskScheduleCronValid` (both extracted from `scheduler-sync.ts` for
|
|
24
|
-
* exactly this reuse) — so a file `sync` would reject can never
|
|
25
|
-
* be reported `valid` here. Cron dialect is checked against
|
|
26
|
-
* `backendNameForPlatform()`, the same platform default `sync` falls back
|
|
27
|
-
* to whenever it has no injected/native-inspected backend to hand (see
|
|
28
|
-
* `akmTasksAdd`, `src/commands/tasks/tasks.ts`); a bare file was never
|
|
29
|
-
* installed anywhere; there is no native scheduler state to inspect for it.
|
|
30
|
-
*
|
|
31
|
-
* Deliberately DOES NOT call `prepareTaskV3Execution` (the function
|
|
32
|
-
* `compileTaskSources` calls between those two gates) or resolve an
|
|
33
|
-
* execution engine: that path resolves a composed command/persona ref
|
|
34
|
-
* against the local index and lowers the task's cascade-composed
|
|
35
|
-
* engine/model — both of which assume a real, indexed bundle and a
|
|
36
|
-
* configured engine. A bare file passed to `validate` has neither, so
|
|
37
|
-
* running that step would make an otherwise-valid command-kind task report
|
|
38
|
-
* `invalid` on any machine with no engine configured. `resolved`
|
|
39
|
-
* is therefore the compiled task shape `sync` itself would build a
|
|
40
|
-
* scheduler binding from — id, the compiled v4 `version`, `target`
|
|
41
|
-
* (`uses`/`run`), the declared `inputs` contract, and `schedule` bindings —
|
|
42
|
-
* never an execution-lowered plan.
|
|
43
|
-
*
|
|
44
|
-
* Outcome classification (mirrors `parse-task-source.ts`'s own routing
|
|
45
|
-
* table in its header, extended for the two gates above):
|
|
46
|
-
* - `valid` — parses as task source v4 and passes both sync gates.
|
|
47
|
-
* - `blocked` — declared `version: 2` or `3`, or a `version: 4`
|
|
48
|
-
* document still carrying the retired
|
|
49
|
-
* `schedule[].enabled`: what `akm migrate apply`
|
|
50
|
-
* rewrites. The runtime reads only v4 (#987), so the
|
|
51
|
-
* reason names that command.
|
|
52
|
-
* - `invalid` — the document declares SOME version (`4`, or anything
|
|
53
|
-
* other than 2/3/4) but fails to parse/validate, OR it
|
|
54
|
-
* parsed but fails one of the two sync gates above, OR
|
|
55
|
-
* the YAML itself does not parse at all (a genuine
|
|
56
|
-
* syntax error, not merely a non-task shape) — reported
|
|
57
|
-
* with the parser's own reason.
|
|
58
|
-
* - `not-a-task` — the document parses as YAML but never declares a
|
|
59
|
-
* `version:` field at all (or isn't a YAML mapping) —
|
|
60
|
-
* the strongest signal available that the file was
|
|
61
|
-
* never intended as a task source in the first place.
|
|
62
|
-
*/
|
|
63
|
-
import fs from "node:fs";
|
|
64
|
-
import path from "node:path";
|
|
65
|
-
import { UsageError } from "../../core/errors.js";
|
|
66
|
-
import { backendNameForPlatform } from "../../tasks/backends/index.js";
|
|
67
|
-
import { assertTaskScheduleCronValid, assertTaskScheduleInputsSatisfyContract } from "../../tasks/scheduler-sync.js";
|
|
68
|
-
import { own, readBoundedTaskSourceYaml } from "../../tasks/source/bounded-document.js";
|
|
69
|
-
import { parseTaskSource, peekTaskSourceVersion, v4ScheduleHasRetiredEnabledKey, } from "../../tasks/source/parse-task-source.js";
|
|
70
|
-
/** True when `root` is a YAML mapping that itself declares a `version:` key, regardless of that key's type/value. */
|
|
71
|
-
function declaresVersionKey(root) {
|
|
72
|
-
return root !== null && typeof root === "object" && !Array.isArray(root) && own(root, "version");
|
|
73
|
-
}
|
|
74
|
-
function buildResolved(id, v4) {
|
|
75
|
-
return {
|
|
76
|
-
id,
|
|
77
|
-
version: v4.version,
|
|
78
|
-
...(v4.name !== undefined ? { name: v4.name } : {}),
|
|
79
|
-
...(v4.description !== undefined ? { description: v4.description } : {}),
|
|
80
|
-
target: v4.target,
|
|
81
|
-
inputs: v4.inputs ?? {},
|
|
82
|
-
schedule: v4.schedule,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
export async function akmTaskValidate(filePath) {
|
|
86
|
-
const resolvedPath = path.resolve(filePath);
|
|
87
|
-
let stat;
|
|
88
|
-
try {
|
|
89
|
-
stat = fs.statSync(resolvedPath);
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
throw new UsageError(`Task file not found: ${JSON.stringify(filePath)}.`, "INVALID_FLAG_VALUE");
|
|
93
|
-
}
|
|
94
|
-
if (!stat.isFile()) {
|
|
95
|
-
throw new UsageError(`${JSON.stringify(filePath)} is not a regular file.`, "INVALID_FLAG_VALUE");
|
|
96
|
-
}
|
|
97
|
-
let yaml;
|
|
98
|
-
try {
|
|
99
|
-
yaml = fs.readFileSync(resolvedPath, "utf8");
|
|
100
|
-
}
|
|
101
|
-
catch (cause) {
|
|
102
|
-
throw new UsageError(`Task file ${JSON.stringify(filePath)} could not be read: ${cause instanceof Error ? cause.message : String(cause)}`, "INVALID_FLAG_VALUE");
|
|
103
|
-
}
|
|
104
|
-
// Peek the declared version BEFORE the real parse, using the identical
|
|
105
|
-
// bounded YAML front end `parseTaskSource` calls internally — never a
|
|
106
|
-
// second/looser YAML reader. A front-end failure here (unparseable YAML,
|
|
107
|
-
// not a mapping, exceeds a resource bound) means the document itself does
|
|
108
|
-
// not parse at all — tracked as `peekFailed` so that case reports
|
|
109
|
-
// `invalid`, never `not-a-task` (`not-a-task` is reserved for
|
|
110
|
-
// YAML that DOES parse but never declared a task shape). The real parse
|
|
111
|
-
// below throws the identical error either way, so nothing is lost by
|
|
112
|
-
// swallowing it here.
|
|
113
|
-
let root;
|
|
114
|
-
let peekFailed = false;
|
|
115
|
-
try {
|
|
116
|
-
root = readBoundedTaskSourceYaml({ yaml, filePath: resolvedPath }, { sourceLabel: "task source" }).root;
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
peekFailed = true;
|
|
120
|
-
}
|
|
121
|
-
const declaredVersion = peekFailed ? undefined : peekTaskSourceVersion(root);
|
|
122
|
-
const hasVersionKey = !peekFailed && declaresVersionKey(root);
|
|
123
|
-
const workspaceRoot = path.dirname(resolvedPath);
|
|
124
|
-
const backend = backendNameForPlatform();
|
|
125
|
-
let parsed;
|
|
126
|
-
try {
|
|
127
|
-
parsed = parseTaskSource({ yaml, filePath: resolvedPath, workspaceRoot });
|
|
128
|
-
}
|
|
129
|
-
catch (cause) {
|
|
130
|
-
if (!(cause instanceof UsageError))
|
|
131
|
-
throw cause;
|
|
132
|
-
const reason = cause.message;
|
|
133
|
-
// What `akm migrate apply` rewrites is the only refusal for these
|
|
134
|
-
// shapes (`parse-task-source.ts`), so no message-text sniffing is needed.
|
|
135
|
-
if (declaredVersion === 2 ||
|
|
136
|
-
declaredVersion === 3 ||
|
|
137
|
-
(declaredVersion === 4 && v4ScheduleHasRetiredEnabledKey(root))) {
|
|
138
|
-
return { ok: false, path: resolvedPath, sourceVersion: declaredVersion, outcome: "blocked", reason };
|
|
139
|
-
}
|
|
140
|
-
if (peekFailed) {
|
|
141
|
-
return { ok: false, path: resolvedPath, outcome: "invalid", reason };
|
|
142
|
-
}
|
|
143
|
-
if (!hasVersionKey) {
|
|
144
|
-
return { ok: false, path: resolvedPath, outcome: "not-a-task", reason };
|
|
145
|
-
}
|
|
146
|
-
return {
|
|
147
|
-
ok: false,
|
|
148
|
-
path: resolvedPath,
|
|
149
|
-
...(declaredVersion !== undefined ? { sourceVersion: declaredVersion } : {}),
|
|
150
|
-
outcome: "invalid",
|
|
151
|
-
reason,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
// Success is unreachable from any path that leaves `declaredVersion`
|
|
155
|
-
// undefined — the router requires a numeric version 4 to reach here.
|
|
156
|
-
const sourceVersion = declaredVersion ?? 4;
|
|
157
|
-
// The document itself parsed — now the two gates `compileTaskSources`
|
|
158
|
-
// runs before accepting it. A violation here is `invalid`.
|
|
159
|
-
try {
|
|
160
|
-
assertTaskScheduleInputsSatisfyContract(parsed.v4, resolvedPath);
|
|
161
|
-
assertTaskScheduleCronValid(parsed.v4, backend);
|
|
162
|
-
}
|
|
163
|
-
catch (cause) {
|
|
164
|
-
if (!(cause instanceof UsageError))
|
|
165
|
-
throw cause;
|
|
166
|
-
return { ok: false, path: resolvedPath, sourceVersion, outcome: "invalid", reason: cause.message };
|
|
167
|
-
}
|
|
168
|
-
const id = path.parse(resolvedPath).name;
|
|
169
|
-
return {
|
|
170
|
-
ok: true,
|
|
171
|
-
path: resolvedPath,
|
|
172
|
-
sourceVersion,
|
|
173
|
-
outcome: "valid",
|
|
174
|
-
resolved: buildResolved(id, parsed.v4),
|
|
175
|
-
};
|
|
176
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { isBundleSlug } from "../asset/asset-ref.js";
|
|
3
|
-
import { warnOnce } from "../warn.js";
|
|
4
|
-
function isPlainRecord(value) {
|
|
5
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
-
}
|
|
7
|
-
const DEFAULT_WRITABLE_BY_TYPE = {
|
|
8
|
-
filesystem: true,
|
|
9
|
-
git: false,
|
|
10
|
-
website: false,
|
|
11
|
-
npm: false,
|
|
12
|
-
};
|
|
13
|
-
function bundleFromLegacySource(entry, index) {
|
|
14
|
-
if (!isPlainRecord(entry))
|
|
15
|
-
return undefined;
|
|
16
|
-
const type = typeof entry.type === "string" ? entry.type : undefined;
|
|
17
|
-
const bundle = {};
|
|
18
|
-
switch (type) {
|
|
19
|
-
case "filesystem":
|
|
20
|
-
if (typeof entry.path !== "string" || !entry.path)
|
|
21
|
-
return undefined;
|
|
22
|
-
bundle.path = entry.path;
|
|
23
|
-
break;
|
|
24
|
-
case "git":
|
|
25
|
-
if (typeof entry.url !== "string" || !entry.url)
|
|
26
|
-
return undefined;
|
|
27
|
-
bundle.git = entry.url;
|
|
28
|
-
break;
|
|
29
|
-
case "website":
|
|
30
|
-
if (typeof entry.url !== "string" || !entry.url)
|
|
31
|
-
return undefined;
|
|
32
|
-
bundle.website = { url: entry.url };
|
|
33
|
-
break;
|
|
34
|
-
case "npm": {
|
|
35
|
-
const spec = typeof entry.url === "string" && entry.url ? entry.url : entry.path;
|
|
36
|
-
if (typeof spec !== "string" || !spec)
|
|
37
|
-
return undefined;
|
|
38
|
-
bundle.npm = spec;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
default:
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
|
-
const writable = typeof entry.writable === "boolean" ? entry.writable : DEFAULT_WRITABLE_BY_TYPE[type ?? ""];
|
|
45
|
-
if (writable !== undefined)
|
|
46
|
-
bundle.writable = writable;
|
|
47
|
-
if (typeof entry.enabled === "boolean")
|
|
48
|
-
bundle.enabled = entry.enabled;
|
|
49
|
-
const name = typeof entry.name === "string" ? entry.name : undefined;
|
|
50
|
-
const key = name && isBundleSlug(name) ? name : `source-${index + 1}`;
|
|
51
|
-
return [key, bundle];
|
|
52
|
-
}
|
|
53
|
-
function filesystemLocator(bundle) {
|
|
54
|
-
if (!isPlainRecord(bundle) || typeof bundle.path !== "string" || bundle.path.length === 0)
|
|
55
|
-
return undefined;
|
|
56
|
-
return path.resolve(bundle.path);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Pure legacy `stashDir`/`sources[]`/`installed` -> `bundles`/`defaultBundle`
|
|
60
|
-
* conversion. Triggers on key *presence* (not on the value being usable), so
|
|
61
|
-
* an unusable value — `stashDir: ""`, `sources: []` — is still removed along
|
|
62
|
-
* with the rest of the legacy shape; only a usable `stashDir` or `sources[]`
|
|
63
|
-
* entry is actually folded into `bundles`. Never warns — see
|
|
64
|
-
* {@link migrateLegacySourceShape} for the warn-once wrapper callers use.
|
|
65
|
-
*/
|
|
66
|
-
export function convertLegacySourceShape(raw) {
|
|
67
|
-
const hasStashDir = "stashDir" in raw;
|
|
68
|
-
const hasSources = "sources" in raw;
|
|
69
|
-
const hasInstalled = "installed" in raw && raw.installed !== undefined;
|
|
70
|
-
if (!hasStashDir && !hasSources && !hasInstalled)
|
|
71
|
-
return { config: raw, converted: [] };
|
|
72
|
-
const { stashDir: _stashDir, sources: _sources, installed: _installed, ...rest } = raw;
|
|
73
|
-
const bundles = isPlainRecord(rest.bundles) ? { ...rest.bundles } : {};
|
|
74
|
-
let defaultBundle = typeof rest.defaultBundle === "string" ? rest.defaultBundle : undefined;
|
|
75
|
-
const usableStashDir = typeof raw.stashDir === "string" && raw.stashDir.trim().length > 0;
|
|
76
|
-
if (usableStashDir) {
|
|
77
|
-
bundles.stash = { path: raw.stashDir, writable: true };
|
|
78
|
-
defaultBundle ??= "stash";
|
|
79
|
-
}
|
|
80
|
-
if (Array.isArray(raw.sources)) {
|
|
81
|
-
raw.sources.forEach((entry, index) => {
|
|
82
|
-
const converted = bundleFromLegacySource(entry, index);
|
|
83
|
-
if (!converted)
|
|
84
|
-
return;
|
|
85
|
-
const [key, bundle] = converted;
|
|
86
|
-
const locator = filesystemLocator(bundle);
|
|
87
|
-
if (locator && Object.values(bundles).some((candidate) => filesystemLocator(candidate) === locator))
|
|
88
|
-
return;
|
|
89
|
-
bundles[key] = bundle;
|
|
90
|
-
defaultBundle ??= key;
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
const converted = [hasStashDir && "stashDir", hasSources && "sources", hasInstalled && "installed"].filter((key) => typeof key === "string");
|
|
94
|
-
// Only add a `bundles` key when there is something to say: either a
|
|
95
|
-
// legacy entry actually converted into one, or the config already had a
|
|
96
|
-
// `bundles` map (preserved as-is). An unusable `stashDir: ""` / `sources: []`
|
|
97
|
-
// with no pre-existing `bundles` should just disappear, not leave behind
|
|
98
|
-
// an empty `bundles: {}`.
|
|
99
|
-
const hasBundles = Object.keys(bundles).length > 0 || isPlainRecord(rest.bundles);
|
|
100
|
-
return {
|
|
101
|
-
config: { ...rest, ...(hasBundles ? { bundles } : {}), ...(defaultBundle !== undefined ? { defaultBundle } : {}) },
|
|
102
|
-
converted,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Warn-once wrapper around {@link convertLegacySourceShape} for the
|
|
107
|
-
* in-memory read path: converts the legacy shape and, when it removed
|
|
108
|
-
* anything, warns once that `akm migrate apply` will persist the rewrite.
|
|
109
|
-
*/
|
|
110
|
-
export function migrateLegacySourceShape(raw, sourcePath) {
|
|
111
|
-
const { config, converted } = convertLegacySourceShape(raw);
|
|
112
|
-
if (converted.length === 0)
|
|
113
|
-
return config;
|
|
114
|
-
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
115
|
-
warnOnce(`legacy-source-shape${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired ${converted.join("/")} shape — auto-migrated in memory to \`bundles\`/\`defaultBundle\`. Run \`akm migrate apply\` to rewrite the config file and silence this warning.`);
|
|
116
|
-
return config;
|
|
117
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* MemRL feedback → utility policy, extracted from indexer/db/db.ts.
|
|
6
|
-
*
|
|
7
|
-
* This is the domain/policy math (arXiv:2601.03192) that decides how a batch of
|
|
8
|
-
* positive/negative feedback signals moves an asset's utility score. It is pure
|
|
9
|
-
* — no database access — so the bounded-step behaviour is unit-testable in
|
|
10
|
-
* isolation; the DB read/write stays with `applyFeedbackToUtilityScore` in db.ts.
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* MemRL learning rate for feedback-driven utility updates (F-5 / #386).
|
|
14
|
-
*
|
|
15
|
-
* Follows the bounded-step formula from MemRL (arXiv:2601.03192):
|
|
16
|
-
* next = clamp(current + lr × (reward − current), 0, 1)
|
|
17
|
-
*
|
|
18
|
-
* This replaces the unbounded `-0.03 × negativeCount` delta that could
|
|
19
|
-
* silently remove high-utility assets from the improvement loop.
|
|
20
|
-
*/
|
|
21
|
-
export const FEEDBACK_LR = 0.1;
|
|
22
|
-
/**
|
|
23
|
-
* Positive reward signal for a single positive feedback event.
|
|
24
|
-
* Reward 1.0 means "fully correct / helpful".
|
|
25
|
-
*/
|
|
26
|
-
const FEEDBACK_REWARD_POSITIVE = 1.0;
|
|
27
|
-
/**
|
|
28
|
-
* Negative reward signal for a single negative feedback event.
|
|
29
|
-
* Reward 0.0 means "not helpful" (lowest MemRL signal).
|
|
30
|
-
*/
|
|
31
|
-
const FEEDBACK_REWARD_NEGATIVE = 0.0;
|
|
32
|
-
/**
|
|
33
|
-
* Utility threshold below which a review-needed escalation is triggered.
|
|
34
|
-
* When a previously high-utility asset (≥ HIGH_UTILITY_THRESHOLD) drops
|
|
35
|
-
* below this value, the caller should create an escalation proposal.
|
|
36
|
-
*/
|
|
37
|
-
export const UTILITY_REVIEW_THRESHOLD = 0.5;
|
|
38
|
-
/**
|
|
39
|
-
* Utility level considered "high" — assets above this are tracked for
|
|
40
|
-
* threshold-crossing escalation.
|
|
41
|
-
*/
|
|
42
|
-
export const HIGH_UTILITY_THRESHOLD = 0.5;
|
|
43
|
-
/**
|
|
44
|
-
* Compute the next utility from accumulated feedback counts using the MemRL
|
|
45
|
-
* bounded-step EMA formula (F-5 / #386, arXiv:2601.03192):
|
|
46
|
-
*
|
|
47
|
-
* reward = weighted average of positive and negative signals
|
|
48
|
-
* nextUtil = clamp(currentUtil + lr × (reward − currentUtil), 0, 1)
|
|
49
|
-
*
|
|
50
|
-
* The step is inherently bounded: reward ∈ [0, 1] and currentUtil ∈ [0, 1], so
|
|
51
|
-
* a single call moves utility by at most {@link FEEDBACK_LR} in either
|
|
52
|
-
* direction. `reward` is a proportion of the counts, not their magnitude, so
|
|
53
|
-
* with no positive signals the number of negatives is irrelevant (reward is 0
|
|
54
|
-
* whether there is 1 negative or 100). Mixing in positives shifts reward and so
|
|
55
|
-
* the step, but never past the learning-rate bound.
|
|
56
|
-
*
|
|
57
|
-
* Pure: no DB access. When both counts are zero, utility is unchanged.
|
|
58
|
-
*/
|
|
59
|
-
export function computeNextUtility(previousUtility, positiveCount, negativeCount) {
|
|
60
|
-
if (positiveCount === 0 && negativeCount === 0) {
|
|
61
|
-
return { previousUtility, nextUtility: previousUtility, crossedReviewThreshold: false };
|
|
62
|
-
}
|
|
63
|
-
const total = positiveCount + negativeCount;
|
|
64
|
-
// Weighted reward: proportion of positive signals.
|
|
65
|
-
const reward = positiveCount > 0 && negativeCount === 0
|
|
66
|
-
? FEEDBACK_REWARD_POSITIVE
|
|
67
|
-
: negativeCount > 0 && positiveCount === 0
|
|
68
|
-
? FEEDBACK_REWARD_NEGATIVE
|
|
69
|
-
: (positiveCount * FEEDBACK_REWARD_POSITIVE + negativeCount * FEEDBACK_REWARD_NEGATIVE) / total;
|
|
70
|
-
// MemRL bounded-step EMA: lr × (reward − current). |delta| ≤ FEEDBACK_LR.
|
|
71
|
-
const delta = FEEDBACK_LR * (reward - previousUtility);
|
|
72
|
-
const nextUtility = Math.max(0, Math.min(1, previousUtility + delta));
|
|
73
|
-
const crossedReviewThreshold = previousUtility >= HIGH_UTILITY_THRESHOLD && nextUtility < UTILITY_REVIEW_THRESHOLD;
|
|
74
|
-
return { previousUtility, nextUtility, crossedReviewThreshold };
|
|
75
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
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
|
-
export const HARNESS_ID_TABLE = [
|
|
5
|
-
{ id: "opencode", agentDispatch: true, enforcesModelWorkTools: true, nativeAgentSelector: true },
|
|
6
|
-
{ id: "claude", agentDispatch: true, enforcesModelWorkTools: true, nativeAgentSelector: true },
|
|
7
|
-
{ id: "opencode-sdk", agentDispatch: true, enforcesModelWorkTools: true, nativeAgentSelector: true },
|
|
8
|
-
{ id: "codex", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
|
|
9
|
-
{ id: "copilot", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
|
|
10
|
-
{ id: "pi", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
|
|
11
|
-
{ id: "gemini", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
|
|
12
|
-
{ id: "aider", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
|
|
13
|
-
{ id: "amazonq", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
|
|
14
|
-
{ id: "openhands", agentDispatch: true, enforcesModelWorkTools: false, nativeAgentSelector: false },
|
|
15
|
-
];
|
|
16
|
-
/**
|
|
17
|
-
* Canonical, ordered list of valid harness / platform ids — the
|
|
18
|
-
* dependency-free counterpart of `./index.ts`'s `VALID_HARNESS_IDS` (which
|
|
19
|
-
* remains the barrel's own derivation for its own consumers). Both are
|
|
20
|
-
* asserted equal at `HARNESS_REGISTRY` construction time.
|
|
21
|
-
*/
|
|
22
|
-
export const VALID_HARNESS_IDS = Object.freeze(HARNESS_ID_TABLE.map((h) => h.id));
|
|
23
|
-
/** Harness ids whose `capabilities.agentDispatch` is `true`. */
|
|
24
|
-
export const HARNESS_AGENT_DISPATCH_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.agentDispatch).map((h) => h.id));
|
|
25
|
-
/** Harness ids that confine the model-work tool policy, so unattended model work may run on them. */
|
|
26
|
-
export const HARNESS_MODEL_WORK_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.enforcesModelWorkTools).map((h) => h.id));
|
|
27
|
-
/** Harness ids that can run a named native agent, so an engine may name a default `agent`. */
|
|
28
|
-
export const HARNESS_NATIVE_AGENT_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.nativeAgentSelector).map((h) => h.id));
|