akm-cli 0.9.1 → 0.9.2-alpha.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 +103 -28
- package/README.md +3 -1
- package/SECURITY.md +1 -1
- package/STABILITY.md +1 -1
- package/dist/akm +2 -2
- package/dist/akm-migrate +2 -2
- package/dist/assets/hints/cli-hints-full.md +14 -9
- package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/models.json +35 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
- package/dist/assets/tasks/core/extract.yml +6 -5
- package/dist/assets/tasks/core/improve.yml +6 -5
- package/dist/assets/tasks/core/index-refresh.yml +6 -5
- package/dist/assets/tasks/core/sync.yml +6 -5
- package/dist/assets/tasks/core/version-check.yml +6 -5
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
- package/dist/cli/confirm.js +2 -2
- package/dist/cli/parse-args.js +3 -24
- package/dist/cli/retired-commands.js +1 -1
- package/dist/cli/shared.js +2 -2
- package/dist/cli.js +11 -9
- package/dist/commands/agent/agent-dispatch.js +55 -89
- package/dist/commands/agent/contribute-cli.js +12 -45
- package/dist/commands/command/builtin-action.js +32 -0
- package/dist/commands/command/command-cli.js +99 -0
- package/dist/commands/command/command-execution.js +308 -0
- package/dist/commands/command/execution-source-loader.js +176 -0
- package/dist/commands/command/portable-template.js +60 -0
- package/dist/commands/config-cli.js +10 -4
- package/dist/commands/env/env.js +4 -2
- package/dist/commands/feedback-cli.js +1 -1
- package/dist/commands/health/checks.js +241 -29
- package/dist/commands/health/html-report.js +0 -14
- package/dist/commands/health/report-view-model.js +0 -1
- package/dist/commands/health/surfaces.js +6 -7
- package/dist/commands/health/types.js +0 -2
- package/dist/commands/health.js +63 -18
- package/dist/commands/improve/collapse-detector.js +5 -6
- package/dist/commands/improve/consolidate.js +251 -214
- package/dist/commands/improve/distill/promote-memory.js +71 -34
- package/dist/commands/improve/distill/quality-gate.js +17 -5
- package/dist/commands/improve/distill.js +232 -155
- package/dist/commands/improve/eligibility.js +112 -79
- package/dist/commands/improve/execution.js +57 -0
- package/dist/commands/improve/extract-cli.js +5 -5
- package/dist/commands/improve/extract-prompt.js +64 -22
- package/dist/commands/improve/extract.js +608 -360
- package/dist/commands/improve/improve-strategies.js +43 -14
- package/dist/commands/improve/improve.js +249 -29
- package/dist/commands/improve/loop-stages.js +11 -17
- package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
- package/dist/commands/improve/outcome-loop.js +22 -38
- package/dist/commands/improve/planner.js +134 -0
- package/dist/commands/improve/preparation.js +730 -409
- package/dist/commands/improve/reflect.js +386 -223
- package/dist/commands/improve/run-context.js +3 -4
- package/dist/commands/improve/salience.js +6 -58
- package/dist/commands/improve/session-asset.js +12 -12
- package/dist/commands/lint/index.js +101 -29
- package/dist/commands/migrate-cli.js +11 -69
- package/dist/commands/migration-tool.js +6 -9
- package/dist/commands/models-cli.js +27 -0
- package/dist/commands/proposal/drain.js +258 -186
- package/dist/commands/proposal/proposal-cli.js +32 -10
- package/dist/commands/proposal/proposal.js +2 -5
- package/dist/commands/proposal/propose.js +192 -172
- package/dist/commands/proposal/repository.js +54 -91
- package/dist/commands/proposal/validators/proposal-validators.js +9 -7
- package/dist/commands/read/curate.js +53 -22
- package/dist/commands/read/registry-search.js +25 -9
- package/dist/commands/read/remember-cli.js +14 -2
- package/dist/commands/read/search.js +10 -4
- package/dist/commands/read/show.js +139 -153
- package/dist/commands/registry-cli.js +16 -7
- package/dist/commands/remember.js +33 -18
- package/dist/commands/sources/add-cli.js +19 -178
- package/dist/commands/sources/bundle-cli.js +15 -3
- package/dist/commands/sources/dangerous-env-audit.js +135 -0
- package/dist/commands/sources/info.js +2 -1
- package/dist/commands/sources/installed-stashes.js +901 -177
- package/dist/commands/sources/schema-repair.js +174 -95
- package/dist/commands/sources/self-update.js +30 -74
- package/dist/commands/sources/source-add.js +3 -5
- package/dist/commands/sources/sources-cli.js +2 -15
- package/dist/commands/sources/update-transaction.js +220 -0
- package/dist/commands/tasks/tasks-cli.js +3 -3
- package/dist/commands/tasks/tasks.js +736 -317
- package/dist/commands/workflow-cli.js +2 -2
- package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
- package/dist/core/adapter/adapters/akm-adapter.js +85 -35
- package/dist/core/adapter/adapters/akm-lint.js +54 -39
- package/dist/core/adapter/adapters/akm-metadata.js +45 -45
- package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
- package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
- package/dist/core/adapter/adapters/index.js +0 -9
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
- package/dist/core/adapter/adapters/okf-adapter.js +4 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
- package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
- package/dist/core/adapter/execution-source.js +308 -0
- package/dist/core/adapter/recognize-match.js +36 -13
- package/dist/core/adapter/registry.js +0 -9
- package/dist/core/asset/stash-meta.js +94 -4
- package/dist/core/common.js +6 -11
- package/dist/core/config/config-io.js +3 -3
- package/dist/core/config/config-schema.js +18 -40
- package/dist/core/config/config-sources.js +11 -21
- package/dist/core/config/config-walker.js +31 -13
- package/dist/core/config/config.js +23 -26
- package/dist/core/config/schema/engines.js +8 -7
- package/dist/core/config/schema/improve-processes.js +29 -5
- package/dist/core/config/schema/index-config.js +0 -27
- package/dist/core/config/schema/primitives.js +1 -23
- package/dist/core/config/schema/sources-bundles.js +13 -16
- package/dist/core/errors.js +2 -0
- package/dist/core/events.js +68 -32
- package/dist/core/extra-params.js +1 -0
- package/dist/core/improve-result.js +315 -0
- package/dist/core/lesson-lint.js +0 -6
- package/dist/core/maintenance-barrier.js +4 -4
- package/dist/core/network-policy.js +152 -0
- package/dist/core/paths.js +1 -1
- package/dist/core/recognition-util.js +4 -4
- package/dist/core/registry-url.js +456 -0
- package/dist/core/state/migrations.js +161 -47
- package/dist/core/state-db.js +453 -80
- package/dist/core/system-error.js +32 -0
- package/dist/core/time.js +2 -12
- package/dist/core/write-source.js +0 -18
- package/dist/execution/directory-identity.js +52 -0
- package/dist/execution/executable-identity.js +107 -0
- package/dist/execution/guarded-source.js +398 -0
- package/dist/execution/json.js +95 -0
- package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
- package/dist/execution/record.js +55 -0
- package/dist/execution/resolved-request.js +730 -0
- package/dist/execution/source.js +320 -0
- package/dist/indexer/bundle-identity-guard.js +5 -4
- package/dist/indexer/db/graph-db.js +33 -0
- package/dist/indexer/graph/graph-boost.js +3 -4
- package/dist/indexer/graph/graph-extraction.js +562 -373
- package/dist/indexer/index-written-assets.js +78 -39
- package/dist/indexer/indexer.js +471 -432
- package/dist/indexer/installations.js +6 -0
- package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
- package/dist/indexer/materialize-embeddings.js +155 -0
- package/dist/indexer/passes/memory-inference.js +227 -174
- package/dist/indexer/passes/metadata.js +263 -118
- package/dist/indexer/scan/doc-to-entry.js +7 -10
- package/dist/indexer/scan/drain-dir.js +51 -23
- package/dist/indexer/search/db-search.js +156 -50
- package/dist/indexer/search/fts-query.js +40 -40
- package/dist/indexer/search/ranking.js +36 -1
- package/dist/indexer/search/search-attribution.js +3 -1
- package/dist/indexer/search/search-fields.js +23 -14
- package/dist/indexer/search/search-hit-enrichers.js +1 -1
- package/dist/indexer/search/search-source.js +7 -16
- package/dist/indexer/search/semantic-status.js +10 -1
- package/dist/indexer/usage/show-usage.js +105 -0
- package/dist/indexer/usage/usage-events.js +7 -2
- package/dist/indexer/walk/matchers.js +40 -10
- package/dist/indexer/walk/path-resolver.js +5 -2
- package/dist/indexer/walk/walker.js +20 -2
- package/dist/integrations/agent/builder-shared.js +3 -6
- package/dist/integrations/agent/conversation-fallback.js +16 -0
- package/dist/integrations/agent/engine-resolution.js +87 -87
- package/dist/integrations/agent/execution-cascade.js +566 -0
- package/dist/integrations/agent/execution-definitions.js +211 -0
- package/dist/integrations/agent/execution-lowering.js +811 -0
- package/dist/integrations/agent/execution-preparation.js +67 -0
- package/dist/integrations/agent/index.js +0 -2
- package/dist/integrations/agent/inline-execution.js +74 -0
- package/dist/integrations/agent/model-map.js +515 -0
- package/dist/integrations/agent/persona-fallback.js +30 -0
- package/dist/integrations/agent/request-lowering.js +186 -0
- package/dist/integrations/agent/runner-dispatch.js +230 -37
- package/dist/integrations/agent/runner.js +12 -83
- package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
- package/dist/integrations/harnesses/aider/index.js +0 -1
- package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
- package/dist/integrations/harnesses/amazonq/index.js +0 -1
- package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
- package/dist/integrations/harnesses/claude/index.js +1 -5
- package/dist/integrations/harnesses/claude/session-log.js +3 -33
- package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
- package/dist/integrations/harnesses/codex/index.js +0 -1
- package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
- package/dist/integrations/harnesses/copilot/index.js +0 -1
- package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
- package/dist/integrations/harnesses/gemini/index.js +0 -1
- package/dist/integrations/harnesses/index.js +4 -44
- package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
- package/dist/integrations/harnesses/opencode/index.js +0 -2
- package/dist/integrations/harnesses/opencode/session-log.js +14 -204
- package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
- package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
- package/dist/integrations/harnesses/openhands/index.js +0 -1
- package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
- package/dist/integrations/harnesses/pi/index.js +0 -1
- package/dist/integrations/harnesses/shared.js +0 -1
- package/dist/integrations/harnesses/types.js +1 -3
- package/dist/integrations/lockfile.js +82 -79
- package/dist/integrations/session-logs/index.js +6 -17
- package/dist/integrations/session-logs/provider-base.js +1 -29
- package/dist/llm/client.js +10 -5
- package/dist/llm/embedder.js +6 -7
- package/dist/llm/embedders/local.js +37 -88
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +75 -50
- package/dist/llm/index-passes.js +43 -5
- package/dist/llm/memory-infer.js +8 -6
- package/dist/llm/metadata-enhance.js +5 -3
- package/dist/llm/structured-call.js +122 -25
- package/dist/output/format-exempt.js +1 -1
- package/dist/output/render-registry.js +0 -16
- package/dist/output/renderers.js +12 -7
- package/dist/output/shapes/curate.js +1 -0
- package/dist/output/shapes/helpers.js +10 -2
- package/dist/output/shapes/passthrough.js +2 -0
- package/dist/output/text/command-format.js +31 -33
- package/dist/output/text/health-format.js +1 -29
- package/dist/output/text/migrate.js +6 -56
- package/dist/output/text/proposal-format.js +16 -1
- package/dist/output/text/workflow-format.js +16 -0
- package/dist/registry/network.js +279 -0
- package/dist/registry/pinned-request-helper.js +247 -0
- package/dist/registry/pinned-transport.js +717 -0
- package/dist/registry/providers/skills-sh.js +18 -6
- package/dist/registry/providers/static-index.js +20 -7
- package/dist/registry/resolve.js +53 -28
- package/dist/scripts/akm-migrate-node.js +19334 -52269
- package/dist/scripts/akm-migrate.js +19270 -51612
- package/dist/setup/registry-stash-loader.js +64 -20
- package/dist/setup/semantic-assets.js +9 -34
- package/dist/setup/setup.js +12 -30
- package/dist/setup/source-identity.js +17 -0
- package/dist/setup/steps/sources.js +36 -15
- package/dist/setup/steps/tasks.js +39 -11
- package/dist/sources/providers/git-provider.js +3 -3
- package/dist/sources/providers/npm.js +2 -2
- package/dist/sources/providers/provider-utils.js +4 -3
- package/dist/sources/providers/website.js +11 -7
- package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
- package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
- package/dist/sources/website-url.js +73 -0
- package/dist/storage/engines/sqlite-migrations.js +81 -26
- package/dist/storage/managed-db.js +27 -24
- package/dist/storage/repositories/events-repository.js +3 -0
- package/dist/storage/repositories/index-connection.js +42 -10
- package/dist/storage/repositories/index-entries-repository.js +203 -229
- package/dist/storage/repositories/index-entry-mapper.js +8 -12
- package/dist/storage/repositories/index-entry-schema.js +255 -0
- package/dist/storage/repositories/index-fts-repository.js +64 -71
- package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
- package/dist/storage/repositories/index-meta-repository.js +0 -11
- package/dist/storage/repositories/index-schema.js +74 -350
- package/dist/storage/repositories/index-utility-repository.js +12 -17
- package/dist/storage/repositories/index-vec-repository.js +56 -7
- package/dist/storage/repositories/proposals-repository.js +4 -127
- package/dist/storage/repositories/registry-cache.js +2 -1
- package/dist/storage/repositories/task-history-repository.js +20 -40
- package/dist/storage/repositories/workflow-runs-repository.js +228 -129
- package/dist/storage/sqlite-read-snapshot.js +148 -0
- package/dist/tasks/backends/cron.js +170 -42
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +787 -202
- package/dist/tasks/backends/schtasks.js +282 -83
- package/dist/tasks/embedded.js +7 -7
- package/dist/tasks/frozen-script.js +50 -0
- package/dist/tasks/resolve-akm-bin.js +5 -1
- package/dist/tasks/runner.js +239 -251
- package/dist/tasks/runtime-v3.js +281 -0
- package/dist/tasks/scheduler-binding.js +272 -0
- package/dist/tasks/scheduler-invocation.js +57 -43
- package/dist/tasks/scheduler-sync.js +654 -0
- package/dist/tasks/source-v3.js +752 -0
- package/dist/tasks/standalone-script-entry.js +5 -0
- package/dist/tasks/task-id.js +29 -0
- package/dist/workflows/authoring/authoring.js +15 -32
- package/dist/workflows/exec/dispatch-redaction.js +14 -8
- package/dist/workflows/exec/exec-unit.js +7 -28
- package/dist/workflows/exec/frozen-judge.js +57 -89
- package/dist/workflows/exec/lowering-notices.js +23 -0
- package/dist/workflows/exec/native-executor.js +301 -458
- package/dist/workflows/exec/param-secrets.js +4 -3
- package/dist/workflows/exec/run-workflow.js +26 -32
- package/dist/workflows/exec/step-work.js +105 -109
- package/dist/workflows/exec/unit-dispatch.js +103 -27
- package/dist/workflows/exec/unit-writer.js +3 -3
- package/dist/workflows/exec/worktree.js +2 -2
- package/dist/workflows/ir/compile.js +86 -72
- package/dist/workflows/ir/environment-v4.js +328 -0
- package/dist/workflows/ir/freeze-v4.js +122 -0
- package/dist/workflows/ir/plan-hash.js +13 -7
- package/dist/workflows/ir/schema-v4.js +525 -0
- package/dist/workflows/ir/schema.js +25 -284
- package/dist/workflows/ir/source-freeze-v4.js +506 -0
- package/dist/workflows/parser.js +27 -24
- package/dist/workflows/program/schema.js +1 -2
- package/dist/workflows/renderer.js +42 -29
- package/dist/workflows/resource-limits.js +4 -5
- package/dist/workflows/runtime/agent-identity.js +11 -13
- package/dist/workflows/runtime/plan-classifier.js +8 -8
- package/dist/workflows/runtime/runs.js +27 -43
- package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
- package/dist/workflows/source-files.js +373 -0
- package/dist/workflows/source-ir/compile.js +196 -0
- package/dist/workflows/source-ir/github-yaml.js +577 -0
- package/dist/workflows/source-ir/ordering.js +38 -0
- package/dist/workflows/source-ir/program.js +50 -0
- package/dist/workflows/source-ir/result.js +26 -0
- package/dist/workflows/source-ir/schema.js +772 -0
- package/dist/workflows/source-ir/semantics.js +242 -0
- package/dist/workflows/source-ir/uses.js +14 -0
- package/docs/README.md +2 -0
- package/docs/migration/README.md +3 -1
- package/docs/migration/release-notes/0.9.2.md +55 -0
- package/docs/migration/release-notes/README.md +5 -0
- package/docs/migration/v0.8-to-v0.9.md +76 -1077
- package/docs/migration/v0.9.0-troubleshooting.md +104 -516
- package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
- package/docs/reference/README.md +1 -0
- package/docs/reference/cli.md +230 -98
- package/docs/reference/configuration.md +159 -36
- package/docs/reference/data-and-telemetry.md +19 -1
- package/docs/reference/supported-formats.md +23 -3
- package/docs/reference/tasks.md +182 -0
- package/docs/reference/workflow-schema.md +91 -40
- package/docs/reference/workflows.md +33 -6
- package/package.json +10 -6
- package/schemas/akm-config.json +372 -224
- package/schemas/akm-task.json +324 -80
- package/schemas/akm-workflow.json +6 -9
- package/dist/core/migration-operation.js +0 -75
- package/dist/integrations/agent/model-aliases.js +0 -74
- package/dist/tasks/parser.js +0 -380
- package/dist/tasks/schema.js +0 -123
- package/dist/tasks/validator.js +0 -80
- package/dist/workflows/ir/freeze.js +0 -320
- package/dist/workflows/runtime/document-cache.js +0 -13
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* content. Pull recent feedback (`feedback` events for that ref) and
|
|
12
12
|
* lesson-lint findings to surface as schema hints.
|
|
13
13
|
* 3. Build the prompt via {@link buildReflectPrompt}.
|
|
14
|
-
* 4.
|
|
14
|
+
* 4. Prepare, authorize, lower, and dispatch the frozen engine selection.
|
|
15
15
|
* 5. Parse the agent's stdout into a {@link AgentProposalPayload}.
|
|
16
16
|
* 6. Insert into the proposal queue via {@link createProposal} with
|
|
17
17
|
* `source: "reflect"`.
|
|
@@ -39,23 +39,32 @@ import { warn } from "../../core/warn.js";
|
|
|
39
39
|
import { lookup } from "../../indexer/indexer.js";
|
|
40
40
|
import { DEFAULT_LLM_TIMEOUT_MS } from "../../integrations/agent/config.js";
|
|
41
41
|
import { fallbackAnnouncement, NO_ENGINE_MESSAGE_SUFFIX, NO_ENGINE_REMEDY, withEngineFallback, } from "../../integrations/agent/engine-fallback.js";
|
|
42
|
-
import {
|
|
42
|
+
import { acquireLoweredExecutionDispatchLease, dispatchLoweredExecutionRequest, disposeLoweredExecutionDispatchLease, lowerResolvedExecutionRequest, lowerResolvedExecutionRequestWithRunner, } from "../../integrations/agent/execution-lowering.js";
|
|
43
|
+
import { prepareInlineExecution, prepareInlineExecutionWithRunner } from "../../integrations/agent/inline-execution.js";
|
|
43
44
|
import { buildReflectOutputRepairPrompt, buildReflectPrompt, extractDraftConfidence, parseAgentProposalPayload, } from "../../integrations/agent/prompts.js";
|
|
44
|
-
import {
|
|
45
|
-
import { collectDispatchSensitiveValues
|
|
45
|
+
import { runnerIsLlm, runnerSupportsFileWrite } from "../../integrations/agent/runner.js";
|
|
46
|
+
import { collectDispatchSensitiveValues } from "../../integrations/agent/runner-dispatch.js";
|
|
46
47
|
import { LlmCallError } from "../../llm/client.js";
|
|
47
48
|
import { callStructured } from "../../llm/structured-call.js";
|
|
48
49
|
import { baseFailureFields, enoentHintMessage, isEnoentFailure } from "../agent/agent-support.js";
|
|
49
|
-
import { isProposalSkipped,
|
|
50
|
+
import { isProposalSkipped, listProposalsReadOnly, proposalContent, } from "../proposal/repository.js";
|
|
50
51
|
import { checkReflectSize, isValidDescription } from "../proposal/validators/proposal-quality-validators.js";
|
|
51
52
|
import { deriveLessonRef } from "./distill.js";
|
|
52
53
|
import { runReflectQualityJudge } from "./distill/quality-gate.js";
|
|
53
54
|
import { findAssetFilePath } from "./eligibility.js";
|
|
55
|
+
import { resolveImproveLlmExecution } from "./execution.js";
|
|
54
56
|
import { emitProposal } from "./proposal-envelope.js";
|
|
55
57
|
import { classifyReflectChange } from "./reflect-noise.js";
|
|
56
58
|
import { createRunContext, resolveRunStashDir } from "./run-context.js";
|
|
57
59
|
import { MAX_REJECTED_PROPOSALS } from "./shared.js";
|
|
58
60
|
import { durableImproveRef, improveStateReadRefs } from "./source-identity.js";
|
|
61
|
+
function collectLoweringNotices(target, notices) {
|
|
62
|
+
for (const notice of notices)
|
|
63
|
+
target.set(JSON.stringify(notice), notice);
|
|
64
|
+
}
|
|
65
|
+
function reflectNoticeFields(notices) {
|
|
66
|
+
return notices.size > 0 ? { notices: Object.freeze([...notices.values()]) } : {};
|
|
67
|
+
}
|
|
59
68
|
const MAX_FEEDBACK_LINES = 10;
|
|
60
69
|
const MAX_GLOBAL_FEEDBACK_LINES = 20;
|
|
61
70
|
/**
|
|
@@ -64,9 +73,12 @@ const MAX_GLOBAL_FEEDBACK_LINES = 20;
|
|
|
64
73
|
* all assets so `akm reflect` can operate in a general "review recent
|
|
65
74
|
* signals" mode. Best-effort — a missing or empty events stream returns `[]`.
|
|
66
75
|
*/
|
|
67
|
-
function
|
|
76
|
+
function readOnlyEventsContext(ctx) {
|
|
77
|
+
return ctx?.db ? ctx : { ...(ctx ?? {}), readOnly: true };
|
|
78
|
+
}
|
|
79
|
+
function readRecentFeedback(ref, eventsCtx) {
|
|
68
80
|
try {
|
|
69
|
-
const events = readEvents({ type: "feedback", ...(ref ? { ref } : {}) }).events;
|
|
81
|
+
const events = readEvents({ type: "feedback", ...(ref ? { ref } : {}) }, readOnlyEventsContext(eventsCtx)).events;
|
|
70
82
|
const lines = [];
|
|
71
83
|
const limit = ref ? MAX_FEEDBACK_LINES : MAX_GLOBAL_FEEDBACK_LINES;
|
|
72
84
|
for (const event of events.slice(-limit)) {
|
|
@@ -126,11 +138,11 @@ const PROTECTED_FRONTMATTER_FIELDS = new Set(["name", "ref", "id", "slug", "type
|
|
|
126
138
|
* into the reflect prompt so the agent avoids re-proposing already-refused
|
|
127
139
|
* content (arXiv:2303.11366).
|
|
128
140
|
*/
|
|
129
|
-
function readRejectedProposals(stash, ref) {
|
|
141
|
+
function readRejectedProposals(stash, ref, proposalsCtx) {
|
|
130
142
|
if (!ref)
|
|
131
143
|
return [];
|
|
132
144
|
try {
|
|
133
|
-
return
|
|
145
|
+
return listProposalsReadOnly(stash, { ref, status: "rejected", includeArchive: true }, proposalsCtx)
|
|
134
146
|
.sort((a, b) => new Date(b.updatedAt ?? 0).getTime() - new Date(a.updatedAt ?? 0).getTime())
|
|
135
147
|
.slice(0, MAX_REJECTED_PROPOSALS)
|
|
136
148
|
.map((p) => ({
|
|
@@ -211,7 +223,7 @@ async function readRelatedLessons(ctx, stash, ref, parsedRef, itemRef) {
|
|
|
211
223
|
try {
|
|
212
224
|
// Match events using the candidate's single durable state key.
|
|
213
225
|
const distillInvokedKeys = new Set(improveStateReadRefs(ref, itemRef));
|
|
214
|
-
const feedbackEvents = readEvents({ type: "distill_invoked" }).events.filter((event) => event.ref !== undefined && distillInvokedKeys.has(event.ref));
|
|
226
|
+
const feedbackEvents = readEvents({ type: "distill_invoked" }, readOnlyEventsContext(ctx.eventsCtx)).events.filter((event) => event.ref !== undefined && distillInvokedKeys.has(event.ref));
|
|
215
227
|
for (const event of feedbackEvents) {
|
|
216
228
|
const proposalRef = typeof event.metadata?.proposalRef === "string" ? event.metadata.proposalRef : undefined;
|
|
217
229
|
if (proposalRef && lenientRefType(proposalRef) === "lesson")
|
|
@@ -266,7 +278,7 @@ async function readRelatedLessons(ctx, stash, ref, parsedRef, itemRef) {
|
|
|
266
278
|
// ref itself, indicating a human or external system rated the skill.
|
|
267
279
|
let hasIndependentFeedback = false;
|
|
268
280
|
try {
|
|
269
|
-
const feedbackEventsForSkill = readEvents({ type: "feedback", ref }).events;
|
|
281
|
+
const feedbackEventsForSkill = readEvents({ type: "feedback", ref }, readOnlyEventsContext(ctx.eventsCtx)).events;
|
|
270
282
|
hasIndependentFeedback = feedbackEventsForSkill.length > 0;
|
|
271
283
|
}
|
|
272
284
|
catch {
|
|
@@ -616,6 +628,29 @@ const REFLECT_UNSCOPED_JSON_SCHEMA = {
|
|
|
616
628
|
};
|
|
617
629
|
/** Critique prompt injected between prior draft and refinement request (Self-Refine loop). */
|
|
618
630
|
const REFLECT_CRITIQUE_PROMPT = "Your previous proposal is shown above. Review it critically and provide an improved version that is more specific, actionable, and avoids any issues with the previous attempt. Return only the improved response using the output contract from the original prompt.";
|
|
631
|
+
/**
|
|
632
|
+
* OpenAI-compatible thinking models charge hidden reasoning against
|
|
633
|
+
* `max_tokens` before they emit the visible response. Reflect asks for a
|
|
634
|
+
* machine-readable payload and requests `enableThinking: false`, but local
|
|
635
|
+
* servers do not uniformly honour that flag. Keep visible-content sizing
|
|
636
|
+
* separate from the allowance that lets an uncooperative thinking model reach
|
|
637
|
+
* its JSON/frame envelope.
|
|
638
|
+
*
|
|
639
|
+
* The 2,048-token allowance exceeds the observed 1,798-token peak that
|
|
640
|
+
* previously cut direct reflect responses off mid-envelope. It applies to all
|
|
641
|
+
* bounded direct-LLM calls because a server's thinking behavior is not a
|
|
642
|
+
* reliable capability signal; the post-processor still enforces the original
|
|
643
|
+
* content-size policy.
|
|
644
|
+
*/
|
|
645
|
+
const REFLECT_REASONING_TOKEN_HEADROOM = 2_048;
|
|
646
|
+
const REFLECT_RESPONSE_ENVELOPE_CHARS = 500;
|
|
647
|
+
function reflectMaxTokensForOutput(maxOutputChars) {
|
|
648
|
+
if (maxOutputChars === undefined)
|
|
649
|
+
return undefined;
|
|
650
|
+
// Divide by 3 chars/token (conservative — most models are 3.5–4), retain
|
|
651
|
+
// space for the JSON/frame wrapper, then reserve independent reasoning room.
|
|
652
|
+
return Math.ceil((maxOutputChars + REFLECT_RESPONSE_ENVELOPE_CHARS) / 3) + REFLECT_REASONING_TOKEN_HEADROOM;
|
|
653
|
+
}
|
|
619
654
|
function reflectLlmTelemetry(result) {
|
|
620
655
|
if (!result.parsed || typeof result.parsed !== "object" || Array.isArray(result.parsed))
|
|
621
656
|
return undefined;
|
|
@@ -743,11 +778,12 @@ function parseDirectReflectOutput(raw, mode, targetRef) {
|
|
|
743
778
|
export async function runReflectViaLlm(opts) {
|
|
744
779
|
const start = Date.now();
|
|
745
780
|
let repairAttempts = 0;
|
|
781
|
+
const connection = opts.runner.connection;
|
|
746
782
|
const messages = [{ role: "user", content: opts.prompt ?? "" }];
|
|
747
783
|
const configuredTimeout = Object.hasOwn(opts, "timeoutMs")
|
|
748
784
|
? (opts.timeoutMs ?? null)
|
|
749
|
-
: Object.hasOwn(opts.
|
|
750
|
-
? (opts.
|
|
785
|
+
: Object.hasOwn(opts.runner, "timeoutMs")
|
|
786
|
+
? (opts.runner.timeoutMs ?? null)
|
|
751
787
|
: DEFAULT_LLM_TIMEOUT_MS;
|
|
752
788
|
const deadline = typeof configuredTimeout === "number" ? start + configuredTimeout : undefined;
|
|
753
789
|
if (opts.priorDraft !== undefined && opts.iteration > 0) {
|
|
@@ -756,7 +792,8 @@ export async function runReflectViaLlm(opts) {
|
|
|
756
792
|
}
|
|
757
793
|
const call = async (callMessages, repairTimeoutMs) => callStructured({
|
|
758
794
|
feature: "reflect_proposal",
|
|
759
|
-
|
|
795
|
+
runner: opts.runner,
|
|
796
|
+
...(opts.lease ? { lease: opts.lease } : {}),
|
|
760
797
|
messages: callMessages,
|
|
761
798
|
request: {
|
|
762
799
|
...(repairTimeoutMs !== undefined
|
|
@@ -772,6 +809,7 @@ export async function runReflectViaLlm(opts) {
|
|
|
772
809
|
enableThinking: false,
|
|
773
810
|
...(opts.chat ? { chat: opts.chat } : {}),
|
|
774
811
|
},
|
|
812
|
+
...(opts.onNotices ? { onNotices: opts.onNotices } : {}),
|
|
775
813
|
parse: (raw) => raw ?? "",
|
|
776
814
|
// Unreachable on the ungated path (errors propagate to the catch below).
|
|
777
815
|
onError: () => "",
|
|
@@ -836,6 +874,8 @@ export async function runReflectViaLlm(opts) {
|
|
|
836
874
|
};
|
|
837
875
|
}
|
|
838
876
|
catch (err) {
|
|
877
|
+
if (err instanceof ConfigError)
|
|
878
|
+
throw err;
|
|
839
879
|
const reason = opts.signal?.aborted
|
|
840
880
|
? "aborted"
|
|
841
881
|
: err instanceof LlmCallError && err.code === "timeout"
|
|
@@ -861,7 +901,7 @@ function failureEnvelope(result, ref, engine, fallbackReason = "non_zero_exit")
|
|
|
861
901
|
* byte-identical.
|
|
862
902
|
*/
|
|
863
903
|
async function finalizeReflectProposal(args) {
|
|
864
|
-
const { assetContent, result, options, engineName, config,
|
|
904
|
+
const { assetContent, result, options, engineName, config, qualityGateEnabled, qualityJudgeRunner, qualityJudgeLease, feedback, stash, emitReflectFailed, onNotices, } = args;
|
|
865
905
|
let payload = args.payload;
|
|
866
906
|
const outputTelemetry = reflectLlmTelemetry(result);
|
|
867
907
|
// 7. Reflect content-preservation rails:
|
|
@@ -941,13 +981,14 @@ async function finalizeReflectProposal(args) {
|
|
|
941
981
|
}
|
|
942
982
|
// 7c. Judge the exact sanitized content that can be persisted. Fail closed
|
|
943
983
|
// on cancellation, transport failure, malformed output, or an invalid score.
|
|
944
|
-
const qualityGateEnabled = (activeStrategy?.processes?.reflect?.qualityGate?.enabled ?? false) ||
|
|
945
|
-
(activeStrategy?.processes?.distill?.qualityGate?.enabled ?? true);
|
|
946
984
|
if (qualityGateEnabled) {
|
|
947
985
|
const judgeResult = await runReflectQualityJudge(config, payload.content, assetContent ?? "", feedback, options.chat, {
|
|
948
|
-
|
|
986
|
+
runnerSelectionFrozen: true,
|
|
987
|
+
...(qualityJudgeRunner ? { llmRunner: qualityJudgeRunner } : {}),
|
|
988
|
+
...(qualityJudgeLease ? { lease: qualityJudgeLease } : {}),
|
|
949
989
|
...(Object.hasOwn(options, "timeoutMs") ? { timeoutMs: options.timeoutMs } : {}),
|
|
950
990
|
...(options.signal ? { signal: options.signal } : {}),
|
|
991
|
+
onNotices,
|
|
951
992
|
});
|
|
952
993
|
if (!judgeResult.pass) {
|
|
953
994
|
appendEvent({
|
|
@@ -1160,6 +1201,32 @@ function resolveReflectPayload(args) {
|
|
|
1160
1201
|
};
|
|
1161
1202
|
}
|
|
1162
1203
|
}
|
|
1204
|
+
function isReflectQualityGateEnabled(activeStrategy) {
|
|
1205
|
+
return ((activeStrategy?.processes?.reflect?.qualityGate?.enabled ?? false) ||
|
|
1206
|
+
(activeStrategy?.processes?.distill?.qualityGate?.enabled ?? true));
|
|
1207
|
+
}
|
|
1208
|
+
/** Resolve the exact judge transport before generation so its credential can join the operation snapshot. */
|
|
1209
|
+
function resolveReflectQualityJudgeRunner(config, runnerSpec, enabled, onNotices) {
|
|
1210
|
+
if (!enabled)
|
|
1211
|
+
return Object.freeze({ enabled: false, runner: undefined });
|
|
1212
|
+
if (runnerIsLlm(runnerSpec))
|
|
1213
|
+
return Object.freeze({ enabled: true, runner: runnerSpec });
|
|
1214
|
+
const resolved = resolveImproveLlmExecution({ config, processName: "reflect_proposal_quality-judge" });
|
|
1215
|
+
if (resolved)
|
|
1216
|
+
onNotices(resolved.notices);
|
|
1217
|
+
return Object.freeze({ enabled: true, runner: resolved?.runner });
|
|
1218
|
+
}
|
|
1219
|
+
/** Acquire through genuine preparation/lowering for all runner kinds, including SDK fallback credentials. */
|
|
1220
|
+
function acquireReflectDispatchLease(runnerSpec, onNotices) {
|
|
1221
|
+
const prepared = prepareInlineExecutionWithRunner({
|
|
1222
|
+
content: "Validate reflect operation transport before dispatch.",
|
|
1223
|
+
runner: runnerSpec,
|
|
1224
|
+
invocationKind: "direct",
|
|
1225
|
+
});
|
|
1226
|
+
const lowered = lowerResolvedExecutionRequestWithRunner(prepared.request, prepared.runner);
|
|
1227
|
+
onNotices(lowered.notices);
|
|
1228
|
+
return acquireLoweredExecutionDispatchLease(lowered);
|
|
1229
|
+
}
|
|
1163
1230
|
/**
|
|
1164
1231
|
* Resolve the single named engine for a reflect invocation (standalone --engine
|
|
1165
1232
|
* / defaults.engine, or the improve strategy's LLM-only process overlay),
|
|
@@ -1170,21 +1237,30 @@ function resolveReflectRunner(options) {
|
|
|
1170
1237
|
const config = options.config ?? loadConfig();
|
|
1171
1238
|
const activeStrategy = options.improveProfile ?? config.improve?.strategies?.[config.defaults?.improveStrategy ?? "default"];
|
|
1172
1239
|
let runnerSpec;
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1240
|
+
let notices = [];
|
|
1241
|
+
if (options.engine) {
|
|
1242
|
+
const prepared = prepareInlineExecution({
|
|
1243
|
+
content: "reflect engine selection",
|
|
1244
|
+
config,
|
|
1245
|
+
invocationKind: "direct",
|
|
1246
|
+
current: { engine: options.engine },
|
|
1247
|
+
});
|
|
1248
|
+
const lowered = lowerResolvedExecutionRequest(prepared.request, prepared.config);
|
|
1249
|
+
runnerSpec = lowered.runner;
|
|
1250
|
+
notices = lowered.notices;
|
|
1181
1251
|
}
|
|
1182
1252
|
else if (options.improveProfile) {
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1253
|
+
const resolved = resolveImproveLlmExecution({
|
|
1254
|
+
config,
|
|
1255
|
+
profile: activeStrategy,
|
|
1256
|
+
process: activeStrategy?.processes?.reflect,
|
|
1257
|
+
processName: "reflect",
|
|
1258
|
+
});
|
|
1259
|
+
if (!resolved) {
|
|
1185
1260
|
throw new ConfigError("Reflect requires an LLM engine for the active improve strategy.", "LLM_NOT_CONFIGURED", "Set defaults.llmEngine or improve.strategies.<name>.processes.reflect.engine.");
|
|
1186
1261
|
}
|
|
1187
|
-
runnerSpec =
|
|
1262
|
+
runnerSpec = resolved.runner;
|
|
1263
|
+
notices = resolved.notices;
|
|
1188
1264
|
}
|
|
1189
1265
|
else {
|
|
1190
1266
|
const { config: engineConfig, fallbackEngineName } = withEngineFallback(config);
|
|
@@ -1197,7 +1273,14 @@ function resolveReflectRunner(options) {
|
|
|
1197
1273
|
if (!defaultEngine) {
|
|
1198
1274
|
throw new ConfigError(`reflect ${NO_ENGINE_MESSAGE_SUFFIX} ${NO_ENGINE_REMEDY}`, "INVALID_CONFIG_FILE");
|
|
1199
1275
|
}
|
|
1200
|
-
|
|
1276
|
+
const prepared = prepareInlineExecution({
|
|
1277
|
+
content: "reflect engine selection",
|
|
1278
|
+
config,
|
|
1279
|
+
invocationKind: "direct",
|
|
1280
|
+
});
|
|
1281
|
+
const lowered = lowerResolvedExecutionRequest(prepared.request, prepared.config);
|
|
1282
|
+
runnerSpec = lowered.runner;
|
|
1283
|
+
notices = lowered.notices;
|
|
1201
1284
|
}
|
|
1202
1285
|
if (options.eventSource === "improve" && !runnerIsLlm(runnerSpec)) {
|
|
1203
1286
|
throw new ConfigError(`Unattended improve requires an LLM engine for reflect; engine "${runnerSpec.engine ?? options.engine ?? "unknown"}" is tool-capable.`, "INVALID_CONFIG_FILE", "Set defaults.llmEngine or improve.strategies.<name>.processes.reflect.engine to an LLM engine.");
|
|
@@ -1206,7 +1289,7 @@ function resolveReflectRunner(options) {
|
|
|
1206
1289
|
if (!engineName) {
|
|
1207
1290
|
throw new ConfigError("Reflect requires a named engine.", "INVALID_CONFIG_FILE");
|
|
1208
1291
|
}
|
|
1209
|
-
return { config, activeStrategy, runnerSpec, engineName };
|
|
1292
|
+
return { config, activeStrategy, runnerSpec, engineName, notices };
|
|
1210
1293
|
}
|
|
1211
1294
|
/**
|
|
1212
1295
|
* Resolve the reflect target's parsed ref + current on-disk content: enforce the
|
|
@@ -1277,7 +1360,7 @@ async function resolveReflectSource(options, stash, emitReflectFailed) {
|
|
|
1277
1360
|
* result + last draft path. Extracted verbatim from `akmReflect`.
|
|
1278
1361
|
*/
|
|
1279
1362
|
async function runReflectRefineIterations(args) {
|
|
1280
|
-
const { options, parsedRef, assetContent, feedback, schemaHints, relatedLessons, rejectedProposals, standardsContext, runnerSpec, agentEnv, draftPathsToCleanup, } = args;
|
|
1363
|
+
const { options, parsedRef, assetContent, feedback, schemaHints, relatedLessons, rejectedProposals, standardsContext, runnerSpec, lease, agentEnv, draftPathsToCleanup, onNotices, } = args;
|
|
1281
1364
|
const MAX_REFINE_ITERS = 3;
|
|
1282
1365
|
const maxRefineIters = Math.min(Math.max(1, options.maxRefineIters ?? 1), MAX_REFINE_ITERS);
|
|
1283
1366
|
// Determine whether this dispatch can honour the file-write contract.
|
|
@@ -1324,40 +1407,63 @@ async function runReflectRefineIterations(args) {
|
|
|
1324
1407
|
...(iterDraftPath ? { draftFilePath: iterDraftPath } : {}),
|
|
1325
1408
|
...(outputMode ? { outputMode } : {}),
|
|
1326
1409
|
});
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
stdio: "captured",
|
|
1335
|
-
parseOutput: "text",
|
|
1336
|
-
...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
|
|
1337
|
-
...(Object.keys(agentEnv).length > 0 ? { env: agentEnv } : {}),
|
|
1338
|
-
...(options.runAgentOptions ?? {}),
|
|
1339
|
-
};
|
|
1340
|
-
const iterResult = await executeRunner(runnerSpec, prompt ?? "", runOptions, {
|
|
1341
|
-
llm: async (spec, _prompt, opts) =>
|
|
1342
|
-
// LLM HTTP runners cannot honor the file-write contract, so they
|
|
1343
|
-
// return structured JSON through stdout.
|
|
1344
|
-
runReflectViaLlm({
|
|
1410
|
+
const maxTokensForLlm = reflectMaxTokensForOutput(maxOutputChars);
|
|
1411
|
+
let iterResult;
|
|
1412
|
+
if (runnerIsLlm(runnerSpec)) {
|
|
1413
|
+
// LLM HTTP runners cannot honor the file-write contract, so they return
|
|
1414
|
+
// structured output through stdout. callStructured owns preparation,
|
|
1415
|
+
// lowering, credential materialization, and direct transport dispatch.
|
|
1416
|
+
iterResult = await runReflectViaLlm({
|
|
1345
1417
|
prompt,
|
|
1346
|
-
|
|
1347
|
-
|
|
1418
|
+
runner: runnerSpec,
|
|
1419
|
+
lease,
|
|
1420
|
+
...(Object.hasOwn(options, "timeoutMs") ? { timeoutMs: options.timeoutMs } : {}),
|
|
1348
1421
|
...(options.signal ? { signal: options.signal } : {}),
|
|
1349
1422
|
priorDraft,
|
|
1350
1423
|
iteration: iter,
|
|
1351
|
-
...(
|
|
1424
|
+
...(runnerSpec.connection.supportsJsonSchema
|
|
1352
1425
|
? { responseSchema: options.ref ? REFLECT_JSON_SCHEMA : REFLECT_UNSCOPED_JSON_SCHEMA }
|
|
1353
1426
|
: {}),
|
|
1354
|
-
outputMode:
|
|
1427
|
+
outputMode: runnerSpec.connection.supportsJsonSchema ? "json_schema" : "framed_markdown",
|
|
1355
1428
|
...(options.ref ? { targetRef: options.ref } : {}),
|
|
1356
1429
|
allowRepair: repairAttempts === 0,
|
|
1357
|
-
chat: options.chat,
|
|
1430
|
+
...(options.chat ? { chat: options.chat } : {}),
|
|
1358
1431
|
...(maxTokensForLlm !== undefined ? { maxTokens: maxTokensForLlm } : {}),
|
|
1359
|
-
|
|
1360
|
-
|
|
1432
|
+
onNotices,
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
else {
|
|
1436
|
+
const conversationPriorDraft = priorDraft;
|
|
1437
|
+
const hasConversation = conversationPriorDraft !== undefined && iter > 0;
|
|
1438
|
+
const current = {
|
|
1439
|
+
...(Object.hasOwn(options, "timeoutMs") ? { timeout: options.timeoutMs } : {}),
|
|
1440
|
+
...(Object.keys(agentEnv).length > 0 ? { environment: agentEnv } : {}),
|
|
1441
|
+
};
|
|
1442
|
+
const prepared = prepareInlineExecutionWithRunner({
|
|
1443
|
+
content: hasConversation ? REFLECT_CRITIQUE_PROMPT : (prompt ?? ""),
|
|
1444
|
+
...(hasConversation
|
|
1445
|
+
? {
|
|
1446
|
+
conversation: [
|
|
1447
|
+
{ role: "user", content: prompt ?? "" },
|
|
1448
|
+
{ role: "assistant", content: conversationPriorDraft },
|
|
1449
|
+
],
|
|
1450
|
+
}
|
|
1451
|
+
: {}),
|
|
1452
|
+
runner: runnerSpec,
|
|
1453
|
+
invocationKind: "direct",
|
|
1454
|
+
...(Object.keys(current).length > 0 ? { current } : {}),
|
|
1455
|
+
});
|
|
1456
|
+
const lowered = lowerResolvedExecutionRequestWithRunner(prepared.request, prepared.runner);
|
|
1457
|
+
onNotices(lowered.notices);
|
|
1458
|
+
iterResult = await dispatchLoweredExecutionRequest(lowered, {
|
|
1459
|
+
lease,
|
|
1460
|
+
...(options.runSdk ? { runSdk: options.runSdk } : {}),
|
|
1461
|
+
runOptions: {
|
|
1462
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
1463
|
+
...(options.runAgentOptions ?? {}),
|
|
1464
|
+
},
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1361
1467
|
const iterTelemetry = reflectLlmTelemetry(iterResult);
|
|
1362
1468
|
if (iterTelemetry)
|
|
1363
1469
|
repairAttempts += iterTelemetry.repairAttempts;
|
|
@@ -1407,17 +1513,16 @@ function buildReflectRunContext(args) {
|
|
|
1407
1513
|
// buildImproveRunContext's proposalsCtx comment in improve.ts).
|
|
1408
1514
|
proposalsCtx: options.ctx ?? {},
|
|
1409
1515
|
chat: options.chat,
|
|
1410
|
-
|
|
1516
|
+
getLlmRunner: () => (runnerIsLlm(runnerSpec) ? runnerSpec : null),
|
|
1411
1517
|
sourceRun: `reflect-${Date.now()}`,
|
|
1412
1518
|
dryRun: false,
|
|
1413
1519
|
signal: options.signal,
|
|
1414
1520
|
});
|
|
1415
1521
|
}
|
|
1416
1522
|
/**
|
|
1417
|
-
*
|
|
1418
|
-
*
|
|
1419
|
-
*
|
|
1420
|
-
* the original inline comments preserved below for the "why".
|
|
1523
|
+
* Build idempotent `reflect_invoked` / `reflect_completed` emitters. Invocation
|
|
1524
|
+
* is delayed until canonical dispatch validates symbolic credentials, while
|
|
1525
|
+
* deterministic pre-dispatch failures still close an invoke/complete pair.
|
|
1421
1526
|
*
|
|
1422
1527
|
* Fix #3 (observability 0.8.0): every failure path below MUST emit
|
|
1423
1528
|
* `reflect_completed` so observers can close the invoke/complete loop. The
|
|
@@ -1429,22 +1534,27 @@ function buildReflectRunContext(args) {
|
|
|
1429
1534
|
* "ref_mismatch" / "enoent" / "draft_missing" subtypes for cases the agent
|
|
1430
1535
|
* surface conflates as "parse_error". Sub-reasons land in `subreason`.
|
|
1431
1536
|
*/
|
|
1432
|
-
function
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
...(options.
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1537
|
+
function buildReflectEventEmitters(options) {
|
|
1538
|
+
let invoked = false;
|
|
1539
|
+
const emitInvoked = () => {
|
|
1540
|
+
if (invoked)
|
|
1541
|
+
return;
|
|
1542
|
+
appendEvent({
|
|
1543
|
+
eventType: "reflect_invoked",
|
|
1544
|
+
// Key on item_ref when planning supplied one, otherwise the conceptId.
|
|
1545
|
+
...(options.ref ? { ref: options.itemRef ?? durableImproveRef(options.ref) } : {}),
|
|
1546
|
+
metadata: {
|
|
1547
|
+
...(options.task ? { task: options.task } : {}),
|
|
1548
|
+
...(options.engine ? { engine: options.engine } : {}),
|
|
1549
|
+
// Attribution tagging: stamp the eligibility lane so reflect_invoked can be
|
|
1550
|
+
// sliced by lane downstream. See EligibilitySource.
|
|
1551
|
+
...(options.eligibilitySource ? { eligibilitySource: options.eligibilitySource } : {}),
|
|
1552
|
+
},
|
|
1553
|
+
}, options.eventsCtx);
|
|
1554
|
+
invoked = true;
|
|
1555
|
+
};
|
|
1556
|
+
const emitFailed = (reason, subreason, ref, extra) => {
|
|
1557
|
+
emitInvoked();
|
|
1448
1558
|
appendEvent({
|
|
1449
1559
|
eventType: "reflect_completed",
|
|
1450
1560
|
...(ref ? { ref } : {}),
|
|
@@ -1457,12 +1567,58 @@ function emitReflectInvokedAndBuildFailureEmitter(options) {
|
|
|
1457
1567
|
},
|
|
1458
1568
|
}, options.eventsCtx);
|
|
1459
1569
|
};
|
|
1570
|
+
return { emitInvoked, emitFailed };
|
|
1571
|
+
}
|
|
1572
|
+
function cleanupReflectDrafts(paths) {
|
|
1573
|
+
for (const draftPath of paths) {
|
|
1574
|
+
try {
|
|
1575
|
+
if (fs.existsSync(draftPath))
|
|
1576
|
+
fs.unlinkSync(draftPath);
|
|
1577
|
+
}
|
|
1578
|
+
catch {
|
|
1579
|
+
// Draft cleanup is best-effort; the proposal result remains authoritative.
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
function validateReflectPayloadRef(args) {
|
|
1584
|
+
const { payload, result, options, engineName, emitReflectFailed, executionNotices } = args;
|
|
1585
|
+
if (!options.ref)
|
|
1586
|
+
return undefined;
|
|
1587
|
+
try {
|
|
1588
|
+
const expectedParsed = parseRefInput(options.ref);
|
|
1589
|
+
const actualParsed = parseRefInput(payload.ref);
|
|
1590
|
+
if (expectedParsed.type === actualParsed.type && expectedParsed.name === actualParsed.name)
|
|
1591
|
+
return undefined;
|
|
1592
|
+
emitReflectFailed("parse_error", "ref_mismatch", options.ref, {
|
|
1593
|
+
expectedRef: options.ref,
|
|
1594
|
+
actualRef: payload.ref,
|
|
1595
|
+
...(result.exitCode !== null ? { exitCode: result.exitCode } : {}),
|
|
1596
|
+
...(reflectLlmTelemetry(result) ?? {}),
|
|
1597
|
+
});
|
|
1598
|
+
return {
|
|
1599
|
+
schemaVersion: 2,
|
|
1600
|
+
ok: false,
|
|
1601
|
+
reason: "parse_error",
|
|
1602
|
+
error: `Agent retargeted proposal: expected ref "${options.ref}" but got "${payload.ref}". Proposal rejected to prevent silent ref hallucination.`,
|
|
1603
|
+
ref: options.ref,
|
|
1604
|
+
engine: engineName,
|
|
1605
|
+
exitCode: result.exitCode,
|
|
1606
|
+
stdout: result.stdout,
|
|
1607
|
+
...(result.stderr ? { stderr: result.stderr } : {}),
|
|
1608
|
+
...reflectNoticeFields(executionNotices),
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
catch {
|
|
1612
|
+
// Malformed refs are rejected downstream by proposal validation.
|
|
1613
|
+
return undefined;
|
|
1614
|
+
}
|
|
1460
1615
|
}
|
|
1461
1616
|
export async function akmReflect(options = {}) {
|
|
1462
1617
|
const stash = resolveRunStashDir(options.stashDir);
|
|
1463
|
-
//
|
|
1464
|
-
//
|
|
1465
|
-
|
|
1618
|
+
// Build lazy event emitters. The invocation row is committed only after the
|
|
1619
|
+
// canonical dispatch has validated symbolic credentials; deterministic
|
|
1620
|
+
// pre-dispatch skips still emit it through emitReflectFailed.
|
|
1621
|
+
const { emitInvoked: emitReflectInvoked, emitFailed: emitReflectFailed } = buildReflectEventEmitters(options);
|
|
1466
1622
|
// 2. Resolve target asset content (if a ref is supplied).
|
|
1467
1623
|
const sourceResolved = await resolveReflectSource(options, stash, emitReflectFailed);
|
|
1468
1624
|
if ("failure" in sourceResolved)
|
|
@@ -1471,161 +1627,168 @@ export async function akmReflect(options = {}) {
|
|
|
1471
1627
|
// 3. Resolve exactly one named engine. Standalone reflect uses --engine or
|
|
1472
1628
|
// defaults.engine; improve resolves its LLM-only strategy/process overlay.
|
|
1473
1629
|
// An incompatible explicit engine is an error and never falls through.
|
|
1474
|
-
const { config, activeStrategy, runnerSpec, engineName } = resolveReflectRunner(options);
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
// 5. Spawn the agent — with the optional Self-Refine loop (R-1 / #372),
|
|
1495
|
-
// extracted to {@link runReflectRefineIterations}.
|
|
1496
|
-
const agentEnv = options.eventSource === "improve" ? { AKM_EVENT_SOURCE: "improve" } : {};
|
|
1497
|
-
const sensitiveValues = collectDispatchSensitiveValues(runnerSpec, {
|
|
1498
|
-
...(Object.keys(agentEnv).length > 0 ? { env: agentEnv } : {}),
|
|
1499
|
-
...(options.runAgentOptions ?? {}),
|
|
1500
|
-
});
|
|
1501
|
-
// Track every draft file path we synthesize so cleanup can remove them on
|
|
1502
|
-
// every return path (success and failure). Mirrors propose's unlink pattern
|
|
1503
|
-
// in `src/commands/proposal/propose.ts` but generalised to N refinement
|
|
1504
|
-
// iterations. Always called via {@link cleanupDrafts} below.
|
|
1505
|
-
const draftPathsToCleanup = [];
|
|
1506
|
-
// Best-effort unlink: tolerate already-deleted files (we may have unlinked
|
|
1507
|
-
// an intermediate iteration's draft) and unwritable paths. Never throws —
|
|
1508
|
-
// the proposal result is the source of truth for the caller.
|
|
1509
|
-
const cleanupDrafts = () => {
|
|
1510
|
-
for (const p of draftPathsToCleanup) {
|
|
1511
|
-
try {
|
|
1512
|
-
if (fs.existsSync(p))
|
|
1513
|
-
fs.unlinkSync(p);
|
|
1514
|
-
}
|
|
1515
|
-
catch {
|
|
1516
|
-
// Swallow — cleanup is best-effort.
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
};
|
|
1520
|
-
// `result` / `lastDraftPath` / `payload` are populated inside the try. Hoisted
|
|
1521
|
-
// here so the post-try sections (R-3 ref guard, sanitizer, quality gate,
|
|
1522
|
-
// createProposal) can use them after the drafts have been cleaned up.
|
|
1523
|
-
let result = {};
|
|
1524
|
-
let lastDraftPath;
|
|
1525
|
-
let payload;
|
|
1630
|
+
const { config, activeStrategy, runnerSpec, engineName, notices: resolutionNotices } = resolveReflectRunner(options);
|
|
1631
|
+
const executionNotices = new Map();
|
|
1632
|
+
collectLoweringNotices(executionNotices, resolutionNotices);
|
|
1633
|
+
const collectExecutionNotices = (notices) => collectLoweringNotices(executionNotices, notices);
|
|
1634
|
+
const qualityJudgeSelection = resolveReflectQualityJudgeRunner(config, runnerSpec, isReflectQualityGateEnabled(activeStrategy), collectExecutionNotices);
|
|
1635
|
+
if (qualityJudgeSelection.enabled && !qualityJudgeSelection.runner) {
|
|
1636
|
+
return {
|
|
1637
|
+
schemaVersion: 2,
|
|
1638
|
+
ok: false,
|
|
1639
|
+
reason: "parse_error",
|
|
1640
|
+
error: 'Reflect proposal quality gate rejected: score=-1, reason="no LLM configured — cannot judge, failing closed"',
|
|
1641
|
+
...(options.ref ? { ref: options.ref } : {}),
|
|
1642
|
+
engine: engineName,
|
|
1643
|
+
exitCode: null,
|
|
1644
|
+
...reflectNoticeFields(executionNotices),
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
const qualityJudgeRunner = qualityJudgeSelection.runner;
|
|
1648
|
+
let generationLease;
|
|
1649
|
+
let qualityJudgeLease;
|
|
1526
1650
|
try {
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1651
|
+
generationLease = acquireReflectDispatchLease(runnerSpec, collectExecutionNotices);
|
|
1652
|
+
qualityJudgeLease =
|
|
1653
|
+
qualityJudgeRunner === runnerSpec
|
|
1654
|
+
? generationLease
|
|
1655
|
+
: qualityJudgeRunner
|
|
1656
|
+
? acquireReflectDispatchLease(qualityJudgeRunner, collectExecutionNotices)
|
|
1657
|
+
: undefined;
|
|
1658
|
+
// WI-9.10: RunContext, built only once config/runnerSpec exist so engine
|
|
1659
|
+
// resolution's existing error-priority ordering is undisturbed (see
|
|
1660
|
+
// buildReflectRunContext's docblock). D6: assetCtx is a fresh,
|
|
1661
|
+
// per-invocation memo — readRelatedLessons below is its genuine
|
|
1662
|
+
// content-read consumer.
|
|
1663
|
+
const ctx = buildReflectRunContext({ options, stash, config, runnerSpec });
|
|
1664
|
+
const assetCtx = ctx.withFreshAssetMemo();
|
|
1665
|
+
// 4. Build the shared prompt inputs — feedback, hints, lessons, rejected
|
|
1666
|
+
// proposals. These are stable across refinement iterations; only the
|
|
1667
|
+
// `priorDraft` field changes per-iteration (R-1 / #372).
|
|
1668
|
+
const feedback = readRecentFeedback(options.ref ? (options.itemRef ?? durableImproveRef(options.ref)) : undefined, options.eventsCtx);
|
|
1669
|
+
const schemaHints = buildSchemaHints(parsedRef?.type ?? "", assetContent);
|
|
1670
|
+
const relatedLessons = options.ref && parsedRef
|
|
1671
|
+
? await readRelatedLessons(assetCtx, stash, options.ref, parsedRef, options.itemRef)
|
|
1672
|
+
: [];
|
|
1673
|
+
// Reflexion-style verbal-RL: inject rejected proposals so the agent avoids
|
|
1674
|
+
// reproducing proposals that have already been reviewed and refused.
|
|
1675
|
+
const rejectedProposals = readRejectedProposals(stash, options.ref, options.ctx);
|
|
1676
|
+
// Standards "rulebook" for this target — stash convention/meta facts; empty
|
|
1677
|
+
// when none fire.
|
|
1678
|
+
const standardsContext = resolveStandardsContext(options.ref, stash);
|
|
1679
|
+
// 5. Spawn the agent — with the optional Self-Refine loop (R-1 / #372),
|
|
1680
|
+
// extracted to {@link runReflectRefineIterations}.
|
|
1681
|
+
const agentEnv = options.eventSource === "improve" ? { AKM_EVENT_SOURCE: "improve" } : {};
|
|
1682
|
+
const sensitiveValues = collectDispatchSensitiveValues(runnerSpec, {
|
|
1683
|
+
...(Object.keys(agentEnv).length > 0 ? { env: agentEnv } : {}),
|
|
1684
|
+
...(options.runAgentOptions ?? {}),
|
|
1539
1685
|
});
|
|
1540
|
-
|
|
1541
|
-
lastDraftPath
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1686
|
+
const draftPathsToCleanup = [];
|
|
1687
|
+
// `result` / `lastDraftPath` / `payload` are populated inside the try. Hoisted
|
|
1688
|
+
// here so the post-try sections (R-3 ref guard, sanitizer, quality gate,
|
|
1689
|
+
// createProposal) can use them after the drafts have been cleaned up.
|
|
1690
|
+
let result = {};
|
|
1691
|
+
let lastDraftPath;
|
|
1692
|
+
let payload;
|
|
1693
|
+
try {
|
|
1694
|
+
const iterated = await runReflectRefineIterations({
|
|
1695
|
+
options,
|
|
1696
|
+
parsedRef,
|
|
1697
|
+
assetContent,
|
|
1698
|
+
feedback,
|
|
1699
|
+
schemaHints,
|
|
1700
|
+
relatedLessons,
|
|
1701
|
+
rejectedProposals,
|
|
1702
|
+
standardsContext,
|
|
1703
|
+
runnerSpec,
|
|
1704
|
+
lease: generationLease,
|
|
1705
|
+
agentEnv,
|
|
1706
|
+
draftPathsToCleanup,
|
|
1707
|
+
onNotices: collectExecutionNotices,
|
|
1708
|
+
});
|
|
1709
|
+
emitReflectInvoked();
|
|
1710
|
+
result = iterated.result;
|
|
1711
|
+
lastDraftPath = iterated.lastDraftPath;
|
|
1712
|
+
const finalResult = result;
|
|
1713
|
+
if (!finalResult.ok) {
|
|
1714
|
+
// B3: ENOENT / not-found gives an actionable hint.
|
|
1715
|
+
if (isEnoentFailure(finalResult)) {
|
|
1716
|
+
emitReflectFailed("spawn_failed", "enoent", options.ref, {
|
|
1717
|
+
...(finalResult.exitCode !== undefined ? { exitCode: finalResult.exitCode } : {}),
|
|
1718
|
+
});
|
|
1719
|
+
return {
|
|
1720
|
+
...failureEnvelope(finalResult, options.ref, engineName),
|
|
1721
|
+
error: enoentHintMessage(runnerIsLlm(runnerSpec) ? engineName : runnerSpec.profile.bin),
|
|
1722
|
+
...reflectNoticeFields(executionNotices),
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
const envelope = failureEnvelope(finalResult, options.ref, engineName);
|
|
1726
|
+
emitReflectFailed(envelope.reason, envelope.reason === "parse_error" ? "parse_error" : "agent_crash", options.ref, {
|
|
1727
|
+
...(envelope.exitCode !== null ? { exitCode: envelope.exitCode } : {}),
|
|
1728
|
+
...(reflectLlmTelemetry(finalResult) ?? {}),
|
|
1548
1729
|
});
|
|
1549
|
-
return {
|
|
1550
|
-
...failureEnvelope(finalResult, options.ref, engineName),
|
|
1551
|
-
error: enoentHintMessage(runnerIsLlm(runnerSpec) ? engineName : runnerSpec.profile.bin),
|
|
1552
|
-
};
|
|
1730
|
+
return { ...envelope, ...reflectNoticeFields(executionNotices) };
|
|
1553
1731
|
}
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1732
|
+
// Re-alias to `result` for the downstream code that references it.
|
|
1733
|
+
result = finalResult;
|
|
1734
|
+
const resolved = resolveReflectPayload({
|
|
1735
|
+
result,
|
|
1736
|
+
lastDraftPath,
|
|
1737
|
+
sensitiveValues,
|
|
1738
|
+
options,
|
|
1739
|
+
engineName,
|
|
1740
|
+
emitReflectFailed,
|
|
1558
1741
|
});
|
|
1559
|
-
|
|
1742
|
+
if ("failure" in resolved) {
|
|
1743
|
+
return { ...resolved.failure, ...reflectNoticeFields(executionNotices) };
|
|
1744
|
+
}
|
|
1745
|
+
payload = resolved.payload;
|
|
1746
|
+
}
|
|
1747
|
+
catch (error) {
|
|
1748
|
+
if (!(error instanceof ConfigError))
|
|
1749
|
+
emitReflectInvoked();
|
|
1750
|
+
throw error;
|
|
1560
1751
|
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1752
|
+
finally {
|
|
1753
|
+
// Always remove tmp draft files — success, failure, or exception. Returns
|
|
1754
|
+
// inside the try above trigger this block before the function exits. Code
|
|
1755
|
+
// after this point uses the already-loaded `payload` and never touches the
|
|
1756
|
+
// draft paths.
|
|
1757
|
+
cleanupReflectDrafts(draftPathsToCleanup);
|
|
1758
|
+
}
|
|
1759
|
+
payload = { ...payload, content: redactSensitiveText(payload.content, sensitiveValues) };
|
|
1760
|
+
const refFailure = validateReflectPayloadRef({
|
|
1761
|
+
payload,
|
|
1762
|
+
result,
|
|
1763
|
+
options,
|
|
1764
|
+
engineName,
|
|
1765
|
+
emitReflectFailed,
|
|
1766
|
+
executionNotices,
|
|
1767
|
+
});
|
|
1768
|
+
if (refFailure)
|
|
1769
|
+
return refFailure;
|
|
1770
|
+
const finalized = await finalizeReflectProposal({
|
|
1771
|
+
payload,
|
|
1772
|
+
assetContent,
|
|
1564
1773
|
result,
|
|
1565
|
-
lastDraftPath,
|
|
1566
|
-
sensitiveValues,
|
|
1567
1774
|
options,
|
|
1568
1775
|
engineName,
|
|
1776
|
+
config,
|
|
1777
|
+
qualityGateEnabled: qualityJudgeSelection.enabled,
|
|
1778
|
+
qualityJudgeRunner,
|
|
1779
|
+
qualityJudgeLease,
|
|
1780
|
+
feedback,
|
|
1781
|
+
stash,
|
|
1569
1782
|
emitReflectFailed,
|
|
1783
|
+
onNotices: collectExecutionNotices,
|
|
1570
1784
|
});
|
|
1571
|
-
|
|
1572
|
-
return resolved.failure;
|
|
1573
|
-
payload = resolved.payload;
|
|
1785
|
+
return { ...finalized, ...reflectNoticeFields(executionNotices) };
|
|
1574
1786
|
}
|
|
1575
1787
|
finally {
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
// after this point uses the already-loaded `payload` and never touches the
|
|
1579
|
-
// draft paths.
|
|
1580
|
-
cleanupDrafts();
|
|
1581
|
-
}
|
|
1582
|
-
payload = { ...payload, content: redactSensitiveText(payload.content, sensitiveValues) };
|
|
1583
|
-
// 6b. Validate payload.ref === options.ref (R-3 / #366).
|
|
1584
|
-
// A hallucinating agent can silently retarget proposals to a different ref.
|
|
1585
|
-
// Parse both current refs so an optional bundle prefix does not cause a false
|
|
1586
|
-
// positive, then reject genuine concept mismatches.
|
|
1587
|
-
// References: CRITIC (arXiv:2305.11738), CoVe (arXiv:2309.11495).
|
|
1588
|
-
if (options.ref) {
|
|
1589
|
-
try {
|
|
1590
|
-
const expectedParsed = parseRefInput(options.ref);
|
|
1591
|
-
const actualParsed = parseRefInput(payload.ref);
|
|
1592
|
-
// Compare type + name (drop origin — agent may omit origin prefix).
|
|
1593
|
-
if (expectedParsed.type !== actualParsed.type || expectedParsed.name !== actualParsed.name) {
|
|
1594
|
-
emitReflectFailed("parse_error", "ref_mismatch", options.ref, {
|
|
1595
|
-
expectedRef: options.ref,
|
|
1596
|
-
actualRef: payload.ref,
|
|
1597
|
-
...(result.exitCode !== null ? { exitCode: result.exitCode } : {}),
|
|
1598
|
-
...(reflectLlmTelemetry(result) ?? {}),
|
|
1599
|
-
});
|
|
1600
|
-
return {
|
|
1601
|
-
schemaVersion: 2,
|
|
1602
|
-
ok: false,
|
|
1603
|
-
reason: "parse_error",
|
|
1604
|
-
error: `Agent retargeted proposal: expected ref "${options.ref}" but got "${payload.ref}". Proposal rejected to prevent silent ref hallucination.`,
|
|
1605
|
-
ref: options.ref,
|
|
1606
|
-
engine: engineName,
|
|
1607
|
-
exitCode: result.exitCode,
|
|
1608
|
-
stdout: result.stdout,
|
|
1609
|
-
...(result.stderr ? { stderr: result.stderr } : {}),
|
|
1610
|
-
};
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1613
|
-
catch {
|
|
1614
|
-
// parseRefInput failure means the agent returned a malformed ref — already
|
|
1615
|
-
// caught downstream by createProposal; allow it to surface naturally.
|
|
1788
|
+
if (qualityJudgeLease && qualityJudgeLease !== generationLease) {
|
|
1789
|
+
disposeLoweredExecutionDispatchLease(qualityJudgeLease);
|
|
1616
1790
|
}
|
|
1791
|
+
if (generationLease)
|
|
1792
|
+
disposeLoweredExecutionDispatchLease(generationLease);
|
|
1617
1793
|
}
|
|
1618
|
-
return finalizeReflectProposal({
|
|
1619
|
-
payload,
|
|
1620
|
-
assetContent,
|
|
1621
|
-
result,
|
|
1622
|
-
options,
|
|
1623
|
-
engineName,
|
|
1624
|
-
config,
|
|
1625
|
-
activeStrategy,
|
|
1626
|
-
runnerSpec,
|
|
1627
|
-
feedback,
|
|
1628
|
-
stash,
|
|
1629
|
-
emitReflectFailed,
|
|
1630
|
-
});
|
|
1631
1794
|
}
|