akm-cli 0.9.17-alpha.3 → 0.9.17-alpha.4
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 +731 -0
- package/dist/akm +94 -196
- package/dist/cli/shared.js +6 -2
- package/dist/cli.js +22 -9
- package/dist/commands/agent/agent-dispatch.js +1 -1
- package/dist/commands/command/command-execution.js +24 -62
- package/dist/commands/feedback-cli.js +0 -1
- package/dist/commands/health/accept-rate.js +2 -2
- package/dist/commands/health/checks.js +30 -75
- package/dist/commands/health/config-skew.js +38 -0
- package/dist/commands/health/egress.js +54 -0
- package/dist/commands/health/html-report.js +0 -38
- package/dist/commands/health/improve-metrics.js +123 -562
- package/dist/commands/health/plugin-staleness.js +53 -3
- package/dist/commands/health/renderers.js +12 -4
- package/dist/commands/health/report-view-model.js +11 -106
- package/dist/commands/health/types-improve.js +4 -19
- package/dist/commands/health/windows.js +64 -73
- package/dist/commands/health.js +122 -143
- package/dist/commands/improve/consolidate/chunking.js +25 -100
- package/dist/commands/improve/consolidate/sanitize.js +54 -149
- package/dist/commands/improve/consolidate.js +538 -1075
- package/dist/commands/improve/content-hash.js +16 -24
- package/dist/commands/improve/distill/content-repair.js +18 -100
- package/dist/commands/improve/distill-guards.js +20 -81
- package/dist/commands/improve/distill-promotion-policy.js +23 -243
- package/dist/commands/improve/distill.js +608 -1075
- package/dist/commands/improve/eligibility.js +126 -400
- package/dist/commands/improve/execution.js +3 -5
- package/dist/commands/improve/extract.js +487 -1046
- package/dist/commands/improve/feedback-valence.js +0 -25
- package/dist/commands/improve/improve-cli.js +29 -166
- package/dist/commands/improve/improve-result-file.js +10 -66
- package/dist/commands/improve/improve-strategies.js +12 -7
- package/dist/commands/improve/improve-usage-report.js +18 -64
- package/dist/commands/improve/improve.js +443 -1063
- package/dist/commands/improve/ledger.js +114 -0
- package/dist/commands/improve/locks.js +2 -8
- package/dist/commands/improve/loop-stages.js +459 -1172
- package/dist/commands/improve/memory/derived-ref.js +12 -77
- package/dist/commands/improve/memory/memory-belief.js +14 -118
- package/dist/commands/improve/memory/memory-improve.js +4 -3
- package/dist/commands/improve/outcome-loop.js +28 -156
- package/dist/commands/improve/planner.js +5 -10
- package/dist/commands/improve/preparation.js +851 -2339
- package/dist/commands/improve/proactive-maintenance.js +34 -101
- package/dist/commands/improve/reflect-noise.js +104 -280
- package/dist/commands/improve/reflect.js +621 -1367
- package/dist/commands/improve/salience.js +46 -232
- package/dist/commands/improve/session-asset.js +19 -100
- package/dist/commands/improve/stage.js +323 -0
- package/dist/commands/proposal/drain.js +251 -644
- package/dist/commands/proposal/proposal-cli.js +3 -18
- package/dist/commands/proposal/proposal-types.js +20 -41
- package/dist/commands/proposal/proposal.js +1 -2
- package/dist/commands/proposal/propose.js +134 -160
- package/dist/commands/proposal/repository.js +502 -1487
- package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
- package/dist/commands/proposal/validators/proposal-validators.js +1 -1
- package/dist/commands/proposal/validators/proposals.js +13 -89
- package/dist/commands/read/curate.js +63 -413
- package/dist/commands/read/search-cli.js +16 -33
- package/dist/commands/read/search.js +17 -23
- package/dist/commands/read/show.js +2 -13
- package/dist/commands/sources/bundle-cli.js +25 -2
- package/dist/commands/sources/bundle-config-ops.js +7 -0
- package/dist/commands/sources/dangerous-env-audit.js +1 -2
- package/dist/commands/sources/info.js +2 -11
- package/dist/commands/sources/installed-stashes.js +197 -746
- package/dist/commands/sources/schema-repair.js +98 -129
- package/dist/commands/sources/source-add.js +62 -12
- package/dist/commands/sources/stash-cli.js +1 -1
- package/dist/commands/tasks/explain.js +10 -13
- package/dist/commands/tasks/tasks-cli.js +9 -8
- package/dist/commands/tasks/tasks.js +326 -930
- package/dist/commands/tasks/validate.js +42 -21
- package/dist/commands/workflow/plan.js +22 -29
- package/dist/commands/workflow-cli.js +4 -4
- package/dist/core/adapter/adapters/akm-adapter.js +0 -1
- package/dist/core/adapter/adapters/akm-lint.js +2 -3
- package/dist/core/adapter/adapters/akm-metadata.js +11 -12
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +17 -29
- package/dist/core/asset/resolve-ref.js +1 -1
- package/dist/core/bundle-id.js +42 -5
- package/dist/core/bundle-rename.js +291 -0
- package/dist/core/config/config-io.js +1 -2
- package/dist/core/config/config-schema.js +1 -33
- package/dist/core/config/config-walker.js +1 -1
- package/dist/core/config/config.js +163 -68
- package/dist/core/config/legacy-source-shape-shim.js +38 -9
- package/dist/core/config/schema/embedding.js +20 -5
- package/dist/core/config/schema/engines.js +5 -0
- package/dist/core/config/schema/execution.js +1 -1
- package/dist/core/config/schema/experimental.js +1 -1
- package/dist/core/config/schema/improve-processes.js +21 -95
- package/dist/core/config/schema/improve.js +4 -42
- package/dist/core/config/schema/scheduler.js +12 -12
- package/dist/core/config/schema/search.js +6 -22
- package/dist/core/env-secret-ref.js +0 -1
- package/dist/core/errors.js +8 -9
- package/dist/core/file-lock.js +76 -173
- package/dist/core/logs-db.js +2 -2
- package/dist/core/paths.js +0 -27
- package/dist/core/redaction.js +109 -2
- package/dist/core/run-lock.js +2 -5
- package/dist/core/spawn-env.js +1 -1
- package/dist/core/state/migrations.js +108 -61
- package/dist/core/state-db-scope.js +2 -4
- package/dist/core/state-db.js +126 -692
- package/dist/core/type-presentation.js +1 -9
- package/dist/core/write-source.js +293 -1012
- package/dist/execution/input-contract.js +1 -1
- package/dist/execution/resolved-request.js +135 -689
- package/dist/execution/source.js +63 -257
- package/dist/execution/target-ref.js +1 -1
- package/dist/indexer/bundle-identity-guard.js +2 -2
- package/dist/indexer/db/graph-db.js +106 -46
- package/dist/indexer/ensure-index.js +44 -85
- package/dist/indexer/graph/graph-extraction.js +340 -562
- package/dist/indexer/graph/graph-related.js +130 -0
- package/dist/indexer/index-rebuild-lock.js +3 -11
- package/dist/indexer/index-writer-lock.js +8 -17
- package/dist/indexer/index-written-assets.js +139 -151
- package/dist/indexer/indexer.js +524 -846
- package/dist/indexer/materialize-embeddings.js +60 -397
- package/dist/indexer/passes/memory-inference.js +81 -90
- package/dist/indexer/passes/metadata.js +132 -200
- package/dist/indexer/read-preflight.js +0 -7
- package/dist/indexer/scan/doc-to-entry.js +1 -3
- package/dist/indexer/scan/drain-dir.js +1 -1
- package/dist/indexer/search/db-search.js +181 -590
- package/dist/indexer/search/fts-query.js +30 -41
- package/dist/indexer/search/ranking.js +28 -154
- package/dist/indexer/search/search-attribution.js +12 -32
- package/dist/indexer/search/search-fields.js +11 -15
- package/dist/indexer/search/search-hit-enrichers.js +54 -85
- package/dist/indexer/search/search-source.js +1 -4
- package/dist/indexer/usage/usage-events.js +2 -7
- package/dist/integrations/agent/engine-fallback.js +23 -40
- package/dist/integrations/agent/engine-resolution.js +93 -183
- package/dist/integrations/agent/execution.js +507 -0
- package/dist/integrations/agent/model-map.js +28 -156
- package/dist/integrations/agent/request-lowering.js +66 -141
- package/dist/integrations/agent/runner-dispatch.js +143 -321
- package/dist/integrations/agent/runner.js +54 -14
- package/dist/integrations/lockfile.js +53 -101
- package/dist/llm/embedders/deterministic.js +2 -3
- package/dist/llm/embedders/profile.js +71 -0
- package/dist/llm/embedders/remote.js +10 -15
- package/dist/llm/graph-extract.js +3 -12
- package/dist/llm/index-passes.js +3 -5
- package/dist/llm/memory-infer.js +1 -2
- package/dist/llm/metadata-enhance.js +1 -2
- package/dist/llm/structured-call.js +5 -24
- package/dist/output/generic-render.js +23 -11
- package/dist/output/html-render.js +13 -10
- package/dist/output/render-registry.js +3 -32
- package/dist/output/shapes/helpers.js +2 -34
- package/dist/output/shapes/passthrough.js +1 -9
- package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
- package/dist/output/text/command-format.js +60 -23
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +5 -14
- package/dist/output/text/proposal-format.js +1 -2
- package/dist/output/text/workflow-format.js +0 -32
- package/dist/output/text.js +2 -0
- package/dist/registry/factory.js +4 -19
- package/dist/registry/network.js +66 -220
- package/dist/registry/providers/index.js +0 -2
- package/dist/registry/providers/skills-sh.js +3 -14
- package/dist/registry/providers/static-index.js +24 -26
- package/dist/registry/resolve.js +55 -131
- package/dist/scripts/akm-migrate-node.js +43937 -93313
- package/dist/scripts/akm-migrate.js +43697 -93071
- package/dist/setup/registry-stash-loader.js +4 -13
- package/dist/setup/semantic-assets.js +3 -44
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/tasks.js +25 -15
- package/dist/sources/provider-factory.js +17 -18
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +7 -1
- package/dist/sources/providers/git-provider.js +0 -3
- package/dist/sources/providers/git-stash.js +0 -17
- package/dist/sources/providers/npm.js +2 -4
- package/dist/sources/providers/provider-utils.js +5 -10
- package/dist/sources/providers/website.js +0 -2
- package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
- package/dist/sources/website-url.js +2 -2
- package/dist/storage/database.js +9 -35
- package/dist/storage/repositories/improve-ledger-repository.js +168 -0
- package/dist/storage/repositories/index-connection.js +34 -70
- package/dist/storage/repositories/index-entries-repository.js +69 -111
- package/dist/storage/repositories/index-entry-mapper.js +1 -2
- package/dist/storage/repositories/index-entry-schema.js +83 -269
- package/dist/storage/repositories/index-fts-repository.js +86 -256
- package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
- package/dist/storage/repositories/index-meta-repository.js +6 -4
- package/dist/storage/repositories/index-schema.js +192 -220
- package/dist/storage/repositories/index-utility-repository.js +8 -29
- package/dist/storage/repositories/index-vec-repository.js +133 -414
- package/dist/storage/repositories/outcome-repository.js +2 -1
- package/dist/storage/repositories/proposals-repository.js +35 -0
- package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
- package/dist/storage/repositories/task-history-repository.js +26 -4
- package/dist/storage/repositories/workflow-runs-repository.js +53 -244
- package/dist/storage/sqlite-migrations.js +136 -0
- package/dist/storage/sqlite-pragmas.js +11 -9
- package/dist/storage/sqlite-transaction.js +170 -0
- package/dist/storage/state-db-integrity.js +34 -27
- package/dist/tasks/activation-config.js +134 -62
- package/dist/tasks/backends/cron.js +129 -277
- package/dist/tasks/backends/exec-utils.js +2 -5
- package/dist/tasks/backends/launchd.js +125 -745
- package/dist/tasks/backends/schtasks.js +101 -620
- package/dist/tasks/prepare/prepare-support.js +5 -15
- package/dist/tasks/prepare/prepare.js +0 -2
- package/dist/tasks/resolve-akm-bin.js +20 -79
- package/dist/tasks/run/attempt-lifecycle.js +0 -1
- package/dist/tasks/scheduler-binding.js +18 -238
- package/dist/tasks/scheduler-invocation.js +52 -52
- package/dist/tasks/scheduler-lock.js +53 -0
- package/dist/tasks/scheduler-sync.js +361 -751
- package/dist/tasks/source/parse-task-source.js +160 -10
- package/dist/tasks/source/task-source-v3-frozen.js +3 -4
- package/dist/tasks/source/task-to-v4.js +2 -2
- package/dist/workflows/authoring/authoring.js +3 -12
- package/dist/workflows/compile.js +211 -0
- package/dist/workflows/concurrency-policy.js +13 -74
- package/dist/workflows/exec/child-invocation.js +3 -17
- package/dist/workflows/exec/child-workflow.js +32 -141
- package/dist/workflows/exec/dispatch-redaction.js +13 -53
- package/dist/workflows/exec/environment.js +98 -0
- package/dist/workflows/exec/exec-unit.js +33 -140
- package/dist/workflows/exec/frozen-judge.js +7 -59
- package/dist/workflows/exec/native-executor.js +82 -341
- package/dist/workflows/exec/param-secrets.js +29 -47
- package/dist/workflows/exec/run-workflow.js +154 -387
- package/dist/workflows/exec/scheduler.js +9 -36
- package/dist/workflows/exec/step-work.js +127 -430
- package/dist/workflows/exec/unit-dispatch.js +11 -63
- package/dist/workflows/exec/unit-writer.js +8 -52
- package/dist/workflows/exec/worktree.js +39 -273
- package/dist/workflows/freeze/child-output-references.js +4 -15
- package/dist/workflows/freeze/environment.js +99 -92
- package/dist/workflows/freeze/freeze.js +172 -0
- package/dist/workflows/freeze/step-values.js +19 -21
- package/dist/workflows/freeze/targets/child-workflow.js +23 -92
- package/dist/workflows/freeze/targets/command.js +10 -33
- package/dist/workflows/freeze/targets/script.js +5 -12
- package/dist/workflows/freeze/targets/shell.js +3 -6
- package/dist/workflows/freeze/targets/task.js +25 -80
- package/dist/workflows/freeze/task-bindings.js +20 -67
- package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
- package/dist/workflows/ir/params.js +6 -51
- package/dist/workflows/ir/plan-hash.js +2 -34
- package/dist/workflows/parser.js +140 -43
- package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
- package/dist/workflows/renderer.js +36 -69
- package/dist/workflows/resource-limits.js +12 -120
- package/dist/workflows/runtime/agent-identity.js +8 -40
- package/dist/workflows/runtime/run-outputs.js +3 -6
- package/dist/workflows/runtime/run-plan.js +316 -0
- package/dist/workflows/runtime/runs.js +48 -200
- package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
- package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/integration/bundling-akm.md +49 -42
- package/docs/migration/README.md +1 -0
- package/docs/migration/release-notes/0.9.17.md +41 -0
- package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
- package/docs/reference/cli.md +182 -125
- package/docs/reference/configuration.md +49 -56
- package/docs/reference/data-and-telemetry.md +19 -20
- package/docs/reference/tasks.md +86 -38
- package/docs/reference/workflow-schema.md +14 -18
- package/docs/reference/workflows.md +6 -9
- package/package.json +1 -1
- package/schemas/akm-config.json +87 -406
- package/dist/commands/health/advisories.js +0 -150
- package/dist/commands/health/metrics.js +0 -329
- package/dist/commands/health/surfaces.js +0 -102
- package/dist/commands/improve/anti-collapse.js +0 -83
- package/dist/commands/improve/collapse-detector.js +0 -432
- package/dist/commands/improve/consolidate/eligibility.js +0 -48
- package/dist/commands/improve/consolidate/merge.js +0 -146
- package/dist/commands/improve/distill/promote-memory.js +0 -329
- package/dist/commands/improve/distill/quality-gate.js +0 -500
- package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
- package/dist/commands/improve/proposal-envelope.js +0 -31
- package/dist/commands/improve/run-context.js +0 -123
- package/dist/commands/improve/shared.js +0 -21
- package/dist/commands/improve/source-identity.js +0 -28
- package/dist/commands/improve/triage.js +0 -96
- package/dist/commands/proposal/drain-policies.js +0 -151
- package/dist/commands/sources/update-transaction.js +0 -220
- package/dist/core/action-contributors.js +0 -28
- package/dist/core/config/config-version-shim.js +0 -101
- package/dist/core/config/retired-experimental-keys-shim.js +0 -62
- package/dist/core/fs-txn.js +0 -405
- package/dist/core/lexical-score.js +0 -25
- package/dist/core/maintenance-barrier.js +0 -167
- package/dist/execution/executable-identity.js +0 -105
- package/dist/execution/guarded-source.js +0 -441
- package/dist/indexer/graph/graph-boost.js +0 -427
- package/dist/indexer/graph/graph-dedup.js +0 -95
- package/dist/indexer/search/name-match.js +0 -35
- package/dist/indexer/search/ranking-contributors.js +0 -515
- package/dist/indexer/walk/project-context.js +0 -192
- package/dist/integrations/agent/execution-cascade.js +0 -566
- package/dist/integrations/agent/execution-definitions.js +0 -202
- package/dist/integrations/agent/execution-lowering.js +0 -841
- package/dist/integrations/agent/execution-preparation.js +0 -98
- package/dist/integrations/agent/inline-execution.js +0 -74
- package/dist/registry/create-provider-registry.js +0 -29
- package/dist/registry/pinned-request-helper.js +0 -247
- package/dist/registry/pinned-transport.js +0 -717
- package/dist/sources/providers/index.js +0 -14
- package/dist/storage/engines/sqlite-migrations.js +0 -271
- package/dist/storage/repositories/canaries-repository.js +0 -107
- package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
- package/dist/storage/repositories/registry-cache.js +0 -113
- package/dist/tasks/scheduler-sync-preview.js +0 -52
- package/dist/workflows/freeze/resolve-steps.js +0 -86
- package/dist/workflows/freeze/source-freeze.js +0 -64
- package/dist/workflows/ir/compile.js +0 -321
- package/dist/workflows/ir/environment-v4.js +0 -330
- package/dist/workflows/ir/freeze-v4.js +0 -153
- package/dist/workflows/ir/schema-v4.js +0 -745
- package/dist/workflows/ir/schema.js +0 -354
- package/dist/workflows/program/schema.js +0 -78
- package/dist/workflows/runtime/checkin.js +0 -57
- package/dist/workflows/runtime/plan-classifier.js +0 -196
- package/dist/workflows/runtime/unit-checkin.js +0 -45
- package/dist/workflows/runtime/unit-phases.js +0 -20
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/source-ir/compile.js +0 -200
- package/dist/workflows/source-ir/program.js +0 -50
- package/dist/workflows/source-ir/result.js +0 -26
- package/dist/workflows/source-ir/schema.js +0 -786
- package/dist/workflows/source-ir/triggers.js +0 -79
- package/dist/workflows/source-ir/uses.js +0 -40
- package/dist/workflows/validator.js +0 -60
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { getImproveProcessConfig } from "../../core/config/config.js";
|
|
5
|
+
import { ConfigError } from "../../core/errors.js";
|
|
6
|
+
import { parseEmbeddedJsonResponse } from "../../core/parse.js";
|
|
7
|
+
import { warn } from "../../core/warn.js";
|
|
8
|
+
import { LlmCallError } from "../../llm/client.js";
|
|
9
|
+
import { callStructured } from "../../llm/structured-call.js";
|
|
10
|
+
import { withLlmStage } from "../../llm/usage-telemetry.js";
|
|
11
|
+
import { isProceduralRejection } from "../proposal/proposal-types.js";
|
|
12
|
+
import { createProposal, listProposalsReadOnly, proposalContentHash, recordGateDecision, } from "../proposal/repository.js";
|
|
13
|
+
import { resolveImproveLlmExecution } from "./execution.js";
|
|
14
|
+
/** Normalize an unknown thrown value to a message. */
|
|
15
|
+
export function errMessage(e) {
|
|
16
|
+
return e instanceof Error ? e.message : String(e);
|
|
17
|
+
}
|
|
18
|
+
/** The lowering notices a stage's dispatches emitted, each once. */
|
|
19
|
+
export function noticeSet(forward) {
|
|
20
|
+
const byKey = new Map();
|
|
21
|
+
const add = (notices) => {
|
|
22
|
+
for (const notice of notices)
|
|
23
|
+
byKey.set(JSON.stringify(notice), notice);
|
|
24
|
+
forward?.(notices);
|
|
25
|
+
};
|
|
26
|
+
const list = () => Object.freeze([...byKey.values()]);
|
|
27
|
+
return { add, list, fields: () => (byKey.size > 0 ? { notices: list() } : {}) };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A stage's LLM runner: the one the improve plan froze for it (an own
|
|
31
|
+
* `llmRunner` key, `null` meaning "none"), else the process engine cascade.
|
|
32
|
+
*/
|
|
33
|
+
export function stageRunner(frozen, config, profile, processName, onNotices) {
|
|
34
|
+
if (Object.hasOwn(frozen, "llmRunner"))
|
|
35
|
+
return frozen.llmRunner ?? undefined;
|
|
36
|
+
const resolved = resolveImproveLlmExecution({
|
|
37
|
+
config,
|
|
38
|
+
profile,
|
|
39
|
+
process: getImproveProcessConfig(processName, profile),
|
|
40
|
+
processName,
|
|
41
|
+
});
|
|
42
|
+
if (resolved)
|
|
43
|
+
onNotices?.(resolved.notices);
|
|
44
|
+
return resolved?.runner;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* One model call. Provider trouble (transport error, timeout, a disabled
|
|
48
|
+
* feature) comes back as `{ ok: false }`; only a configuration failure throws.
|
|
49
|
+
*/
|
|
50
|
+
export async function callStage(call) {
|
|
51
|
+
const messages = [
|
|
52
|
+
...(call.system ? [{ role: "system", content: call.system }] : []),
|
|
53
|
+
...(call.history ?? []),
|
|
54
|
+
{ role: "user", content: call.prompt },
|
|
55
|
+
];
|
|
56
|
+
let failure;
|
|
57
|
+
try {
|
|
58
|
+
const raw = await callStructured({
|
|
59
|
+
feature: call.feature,
|
|
60
|
+
...(call.gate
|
|
61
|
+
? { akmConfig: call.gate.config, ...(call.gate.enabled !== undefined ? { enabled: call.gate.enabled } : {}) }
|
|
62
|
+
: {}),
|
|
63
|
+
runner: call.runner,
|
|
64
|
+
messages,
|
|
65
|
+
...(call.request ? { request: call.request } : {}),
|
|
66
|
+
...(call.onNotices ? { onNotices: call.onNotices } : {}),
|
|
67
|
+
parse: (r) => r ?? "",
|
|
68
|
+
onError: (_cls, err) => {
|
|
69
|
+
failure = { ok: false, reason: "error", error: errMessage(err) };
|
|
70
|
+
return undefined;
|
|
71
|
+
},
|
|
72
|
+
fallback: undefined,
|
|
73
|
+
onFallback: (event) => {
|
|
74
|
+
failure ??= { ok: false, reason: event.reason, ...(event.error ? { error: event.error.message } : {}) };
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
return raw === undefined ? (failure ?? { ok: false, reason: "error" }) : { ok: true, raw };
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
if (err instanceof ConfigError)
|
|
81
|
+
throw err;
|
|
82
|
+
const timedOut = err instanceof LlmCallError && err.code === "timeout";
|
|
83
|
+
return { ok: false, reason: timedOut ? "timeout" : "error", error: errMessage(err) };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Attribute a stage's LLM calls to its process and planned engine (the usage report). */
|
|
87
|
+
const STAGE_LABELS = {
|
|
88
|
+
reflect: "reflect",
|
|
89
|
+
distill: "distill",
|
|
90
|
+
consolidate: "consolidate",
|
|
91
|
+
extract: "session-extraction",
|
|
92
|
+
memoryInference: "memory-inference",
|
|
93
|
+
graphExtraction: "graph-extraction",
|
|
94
|
+
validation: "validation",
|
|
95
|
+
};
|
|
96
|
+
export function attributeStage(plan, process, fn) {
|
|
97
|
+
return withLlmStage(STAGE_LABELS[process], fn, { engine: plan?.processes[process].runner?.engine, process });
|
|
98
|
+
}
|
|
99
|
+
/** How many prior rejected proposals are shown to the model as "don't repeat this". */
|
|
100
|
+
export const MAX_REJECTED_PROPOSALS = 3;
|
|
101
|
+
/**
|
|
102
|
+
* Reflexion context: the newest reviewer rejections for `ref`. Procedural
|
|
103
|
+
* refusals (expiry, stale target, missing asset) are not judgements on the
|
|
104
|
+
* content and are left out. Reads never create state.db.
|
|
105
|
+
*/
|
|
106
|
+
export function rejectedProposalContext(stash, ref, ctx) {
|
|
107
|
+
if (!ref)
|
|
108
|
+
return [];
|
|
109
|
+
return listProposalsReadOnly(stash, { ref, status: "rejected", includeArchive: true }, ctx)
|
|
110
|
+
.filter((p) => !isProceduralRejection(p))
|
|
111
|
+
.sort((a, b) => new Date(b.updatedAt ?? 0).getTime() - new Date(a.updatedAt ?? 0).getTime())
|
|
112
|
+
.slice(0, MAX_REJECTED_PROPOSALS)
|
|
113
|
+
.map((p) => ({
|
|
114
|
+
ref: p.ref,
|
|
115
|
+
reason: p.review?.reason ?? "no reason given",
|
|
116
|
+
// `payload.content` is populated on every row, including legacy ones.
|
|
117
|
+
contentPreview: p.payload.content.slice(0, 500),
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
// ── Mint ─────────────────────────────────────────────────────────────────────
|
|
121
|
+
/**
|
|
122
|
+
* Create a stage's proposal. `judged` stamps a `staged` gate decision with the
|
|
123
|
+
* judged content's hash (the triage drain accepts it while the content still
|
|
124
|
+
* matches); `review` leaves it `deferred` for a human (`review_needed` in the
|
|
125
|
+
* improve ledger).
|
|
126
|
+
*/
|
|
127
|
+
export function mintProposal(stash, proposalsCtx, input, verdict = {}) {
|
|
128
|
+
const proposal = createProposal(stash, input, proposalsCtx);
|
|
129
|
+
if (verdict.review) {
|
|
130
|
+
return recordGateDecision(stash, proposal.id, { outcome: "deferred", ...verdict.review }, proposalsCtx) ?? proposal;
|
|
131
|
+
}
|
|
132
|
+
return verdict.judged ? stageJudgedProposal(stash, proposal, proposalsCtx) : proposal;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Stamp a proposal the quality judge passed. Best-effort: a failed stamp only
|
|
136
|
+
* means the triage drain judges it again.
|
|
137
|
+
*/
|
|
138
|
+
export function stageJudgedProposal(stash, proposal, proposalsCtx) {
|
|
139
|
+
try {
|
|
140
|
+
return (recordGateDecision(stash, proposal.id, {
|
|
141
|
+
outcome: "staged",
|
|
142
|
+
reason: "quality-judge",
|
|
143
|
+
gate: "quality-gate",
|
|
144
|
+
contentHash: proposalContentHash(proposal),
|
|
145
|
+
}, proposalsCtx) ?? proposal);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
warn(`[akm] failed to record the quality-judge pass for ${proposal.id}: ${errMessage(error)}`);
|
|
149
|
+
return proposal;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Lesson judge prompt; similar existing lessons let it mark near-duplicates down. */
|
|
153
|
+
export function buildJudgePrompt(lessonContent, sourceContent, similarLessons) {
|
|
154
|
+
const lines = [
|
|
155
|
+
"You are evaluating a proposed lesson asset for an akm knowledge base.",
|
|
156
|
+
"",
|
|
157
|
+
"Score this lesson on each criterion from 1 (poor) to 5 (excellent):",
|
|
158
|
+
"1. NOVELTY: Does the lesson add information not already present in the source asset?",
|
|
159
|
+
"2. NON-REDUNDANCY: Is this lesson meaningfully different from what the source already says?",
|
|
160
|
+
"",
|
|
161
|
+
"Source asset content:",
|
|
162
|
+
"```",
|
|
163
|
+
sourceContent.slice(0, 2000),
|
|
164
|
+
"```",
|
|
165
|
+
];
|
|
166
|
+
if (similarLessons && similarLessons.length > 0) {
|
|
167
|
+
lines.push("", "Existing similar lessons (top-3 by similarity). Rate lower if the proposed lesson is substantially similar to any of these:");
|
|
168
|
+
for (const sl of similarLessons)
|
|
169
|
+
lines.push(`\nExisting lesson ref: ${sl.ref}`, "```", sl.content.slice(0, 500), "```");
|
|
170
|
+
}
|
|
171
|
+
lines.push("", "Proposed lesson content:", "```", lessonContent.slice(0, 1000), "```", "", 'Return ONLY valid JSON, no prose: {"scores": {"novelty": <1-5 integer>, "nonRedundancy": <1-5 integer>}, "reason": "<one sentence>"}');
|
|
172
|
+
return lines.join("\n");
|
|
173
|
+
}
|
|
174
|
+
function boundedDocument(content, maxChars = 6000) {
|
|
175
|
+
if (content.length <= maxChars)
|
|
176
|
+
return content;
|
|
177
|
+
const half = Math.floor((maxChars - 80) / 2);
|
|
178
|
+
return `${content.slice(0, half)}\n\n[... middle omitted for bounded judge context ...]\n\n${content.slice(-half)}`;
|
|
179
|
+
}
|
|
180
|
+
function buildChangedRegion(sourceContent, candidateContent) {
|
|
181
|
+
const source = sourceContent.split("\n");
|
|
182
|
+
const candidate = candidateContent.split("\n");
|
|
183
|
+
let prefix = 0;
|
|
184
|
+
while (prefix < source.length && prefix < candidate.length && source[prefix] === candidate[prefix])
|
|
185
|
+
prefix++;
|
|
186
|
+
let suffix = 0;
|
|
187
|
+
while (suffix < source.length - prefix &&
|
|
188
|
+
suffix < candidate.length - prefix &&
|
|
189
|
+
source[source.length - 1 - suffix] === candidate[candidate.length - 1 - suffix]) {
|
|
190
|
+
suffix++;
|
|
191
|
+
}
|
|
192
|
+
const removed = source.slice(prefix, source.length - suffix).join("\n");
|
|
193
|
+
const added = candidate.slice(prefix, candidate.length - suffix).join("\n");
|
|
194
|
+
return boundedDocument(`Removed or replaced:\n${removed || "(none)"}\n\nAdded or replacement:\n${added || "(none)"}`);
|
|
195
|
+
}
|
|
196
|
+
/** Judge prompt for an in-place revision (overlap with the source is expected). */
|
|
197
|
+
export function buildReflectJudgePrompt(candidateContent, sourceContent, feedback) {
|
|
198
|
+
return [
|
|
199
|
+
"You are evaluating a proposed revision to an existing akm asset.",
|
|
200
|
+
"",
|
|
201
|
+
"Score this revision on each criterion from 1 (poor) to 5 (excellent):",
|
|
202
|
+
"1. FEEDBACK ALIGNMENT: Does the revision address the supplied feedback or improve retrieval and clarity?",
|
|
203
|
+
"2. PRESERVATION: Does it retain the source's concrete facts, code, commands, examples, and structure without truncation?",
|
|
204
|
+
"3. QUALITY: Is the revision coherent, actionable, complete, and free of unsupported claims?",
|
|
205
|
+
"",
|
|
206
|
+
"Overlap with the source is expected and must not lower the score by itself; this is an in-place revision, not a new lesson.",
|
|
207
|
+
"",
|
|
208
|
+
"Feedback:",
|
|
209
|
+
"```",
|
|
210
|
+
(feedback.length > 0 ? feedback.join("\n") : "No explicit feedback supplied.").slice(0, 1000),
|
|
211
|
+
"```",
|
|
212
|
+
"",
|
|
213
|
+
"Source asset content:",
|
|
214
|
+
"```",
|
|
215
|
+
boundedDocument(sourceContent),
|
|
216
|
+
"```",
|
|
217
|
+
"",
|
|
218
|
+
"Proposed revision:",
|
|
219
|
+
"```",
|
|
220
|
+
boundedDocument(candidateContent),
|
|
221
|
+
"```",
|
|
222
|
+
"",
|
|
223
|
+
"Changed region:",
|
|
224
|
+
"```",
|
|
225
|
+
buildChangedRegion(sourceContent, candidateContent),
|
|
226
|
+
"```",
|
|
227
|
+
"",
|
|
228
|
+
'Return ONLY valid JSON, no prose: {"scores": {"feedbackAlignment": <1-5 integer>, "preservation": <1-5 integer>, "quality": <1-5 integer>}, "reason": "<one sentence>"}',
|
|
229
|
+
].join("\n");
|
|
230
|
+
}
|
|
231
|
+
const LESSON_JUDGE_CRITERIA = ["novelty", "nonRedundancy"];
|
|
232
|
+
const REFLECT_JUDGE_CRITERIA = ["feedbackAlignment", "preservation", "quality"];
|
|
233
|
+
/**
|
|
234
|
+
* Read a judge response: the per-criterion shape (averaged here) or the older
|
|
235
|
+
* `{"score"}` shape. Only the expected criteria are read; any missing or
|
|
236
|
+
* out-of-range (1..5) value is a parse failure, extra keys are ignored.
|
|
237
|
+
*/
|
|
238
|
+
function parseJudgeResponse(raw, keys) {
|
|
239
|
+
const parsed = parseEmbeddedJsonResponse(raw);
|
|
240
|
+
if (!parsed || typeof parsed.reason !== "string")
|
|
241
|
+
return undefined;
|
|
242
|
+
const reason = parsed.reason;
|
|
243
|
+
const inRange = (value) => typeof value === "number" && Number.isFinite(value) && value >= 1 && value <= 5;
|
|
244
|
+
if (parsed.scores !== undefined) {
|
|
245
|
+
if (typeof parsed.scores !== "object" || parsed.scores === null || Array.isArray(parsed.scores))
|
|
246
|
+
return undefined;
|
|
247
|
+
const scores = parsed.scores;
|
|
248
|
+
const criteria = {};
|
|
249
|
+
for (const key of keys) {
|
|
250
|
+
const value = scores[key];
|
|
251
|
+
if (!inRange(value))
|
|
252
|
+
return undefined;
|
|
253
|
+
criteria[key] = value;
|
|
254
|
+
}
|
|
255
|
+
return { score: Object.values(criteria).reduce((a, b) => a + b, 0) / keys.length, reason, criteria };
|
|
256
|
+
}
|
|
257
|
+
return inRange(parsed.score) ? { score: parsed.score, reason } : undefined;
|
|
258
|
+
}
|
|
259
|
+
function judgeResponseSchema(keys) {
|
|
260
|
+
return {
|
|
261
|
+
type: "object",
|
|
262
|
+
required: ["scores", "reason"],
|
|
263
|
+
additionalProperties: false,
|
|
264
|
+
properties: {
|
|
265
|
+
scores: {
|
|
266
|
+
type: "object",
|
|
267
|
+
required: [...keys],
|
|
268
|
+
additionalProperties: false,
|
|
269
|
+
properties: Object.fromEntries(keys.map((key) => [key, { type: "integer", minimum: 1, maximum: 5 }])),
|
|
270
|
+
},
|
|
271
|
+
reason: { type: "string" },
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* The quality judge. Fails closed: no runner, an unparseable verdict or a
|
|
277
|
+
* provider failure never passes content. Bands: >= 3.5 pass, 2.5-3.5 review,
|
|
278
|
+
* < 2.5 reject. Temperature is pinned to 0 so verdicts do not flip.
|
|
279
|
+
*/
|
|
280
|
+
async function runQualityJudge(feature, config, prompt, keys, chat, options) {
|
|
281
|
+
const resolved = !options.runnerSelectionFrozen && !options.llmRunner
|
|
282
|
+
? resolveImproveLlmExecution({ config, processName: `${feature}-judge` })
|
|
283
|
+
: null;
|
|
284
|
+
if (resolved)
|
|
285
|
+
options.onNotices?.(resolved.notices);
|
|
286
|
+
const runner = options.llmRunner ?? resolved?.runner;
|
|
287
|
+
if (!runner)
|
|
288
|
+
return { pass: false, score: -1, reason: "no LLM configured — cannot judge, failing closed" };
|
|
289
|
+
const outcome = await callStage({
|
|
290
|
+
feature,
|
|
291
|
+
runner,
|
|
292
|
+
system: "Return only valid JSON. No prose.",
|
|
293
|
+
prompt,
|
|
294
|
+
request: {
|
|
295
|
+
enableThinking: false,
|
|
296
|
+
temperature: 0,
|
|
297
|
+
responseSchema: judgeResponseSchema(keys),
|
|
298
|
+
...(Object.hasOwn(options, "timeoutMs") ? { timeoutMs: options.timeoutMs } : {}),
|
|
299
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
300
|
+
...(chat ? { chat } : {}),
|
|
301
|
+
},
|
|
302
|
+
...(options.onNotices ? { onNotices: options.onNotices } : {}),
|
|
303
|
+
});
|
|
304
|
+
if (!outcome.ok) {
|
|
305
|
+
return { pass: false, score: -1, reason: "judge timeout/error — routed to review", reviewNeeded: true };
|
|
306
|
+
}
|
|
307
|
+
const parsed = parseJudgeResponse(outcome.raw, keys);
|
|
308
|
+
if (!parsed)
|
|
309
|
+
return { pass: false, score: -1, reason: "judge parse failed — routed to review", reviewNeeded: true };
|
|
310
|
+
const { score, reason, criteria } = parsed;
|
|
311
|
+
const verdict = score >= 3.5 ? { pass: true } : score >= 2.5 ? { pass: false, reviewNeeded: true } : { pass: false };
|
|
312
|
+
return { ...verdict, score, reason, ...(criteria ? { criteria } : {}) };
|
|
313
|
+
}
|
|
314
|
+
/** Judge a proposed lesson (or knowledge promotion) against its source. */
|
|
315
|
+
export function runLessonQualityJudge(config, lessonContent, sourceContent, chat, options = {}) {
|
|
316
|
+
const prompt = buildJudgePrompt(lessonContent, sourceContent, options.similarLessons);
|
|
317
|
+
return runQualityJudge("lesson_quality_gate", config, prompt, LESSON_JUDGE_CRITERIA, chat, options);
|
|
318
|
+
}
|
|
319
|
+
/** Judge an in-place reflect revision without new-lesson novelty criteria. */
|
|
320
|
+
export function runReflectQualityJudge(config, candidateContent, sourceContent, feedback, chat, options = {}) {
|
|
321
|
+
const prompt = buildReflectJudgePrompt(candidateContent, sourceContent, feedback);
|
|
322
|
+
return runQualityJudge("proposal_quality_gate", config, prompt, REFLECT_JUDGE_CRITERIA, chat, options);
|
|
323
|
+
}
|