@alan512/experienceengine 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +213 -130
- package/README.zh-CN.md +250 -119
- package/dist/adapters/claude-code/session-store.d.ts +1 -0
- package/dist/adapters/claude-code/session-store.js +24 -1
- package/dist/adapters/claude-code/session-store.js.map +1 -1
- package/dist/adapters/codex/action-registry.d.ts +84 -0
- package/dist/adapters/codex/action-registry.js +277 -0
- package/dist/adapters/codex/action-registry.js.map +1 -0
- package/dist/adapters/codex/broker-tools.d.ts +114 -0
- package/dist/adapters/codex/broker-tools.js +130 -0
- package/dist/adapters/codex/broker-tools.js.map +1 -0
- package/dist/adapters/codex/mcp-server.d.ts +21 -0
- package/dist/adapters/codex/mcp-server.js +103 -423
- package/dist/adapters/codex/mcp-server.js.map +1 -1
- package/dist/analyzer/candidate-signals.d.ts +3 -1
- package/dist/analyzer/candidate-signals.js +159 -0
- package/dist/analyzer/candidate-signals.js.map +1 -1
- package/dist/analyzer/llm-learning-gate.d.ts +12 -1
- package/dist/analyzer/llm-learning-gate.js +633 -16
- package/dist/analyzer/llm-learning-gate.js.map +1 -1
- package/dist/cli/commands/claude-hook.js +11 -4
- package/dist/cli/commands/claude-hook.js.map +1 -1
- package/dist/cli/commands/codex.d.ts +60 -0
- package/dist/cli/commands/codex.js +188 -0
- package/dist/cli/commands/codex.js.map +1 -0
- package/dist/cli/commands/doctor.js +35 -2
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/evaluate.d.ts +9 -3
- package/dist/cli/commands/evaluate.js +31 -5
- package/dist/cli/commands/evaluate.js.map +1 -1
- package/dist/cli/commands/init.js +21 -8
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/inspect.js +73 -4
- package/dist/cli/commands/inspect.js.map +1 -1
- package/dist/cli/commands/repair.js +3 -3
- package/dist/cli/commands/repair.js.map +1 -1
- package/dist/cli/commands/status.js +38 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/dispatch.js +16 -4
- package/dist/cli/dispatch.js.map +1 -1
- package/dist/config/config-schema.d.ts +177 -0
- package/dist/config/config-schema.js +142 -1
- package/dist/config/config-schema.js.map +1 -1
- package/dist/config/default-config.js +19 -1
- package/dist/config/default-config.js.map +1 -1
- package/dist/config/load-config.js +72 -1
- package/dist/config/load-config.js.map +1 -1
- package/dist/config/settings-store.d.ts +19 -0
- package/dist/config/settings-store.js +11 -0
- package/dist/config/settings-store.js.map +1 -1
- package/dist/controller/candidate-retriever.d.ts +16 -1
- package/dist/controller/candidate-retriever.js +199 -137
- package/dist/controller/candidate-retriever.js.map +1 -1
- package/dist/controller/injection-scorecard.d.ts +2 -14
- package/dist/controller/injection-scorecard.js +29 -0
- package/dist/controller/injection-scorecard.js.map +1 -1
- package/dist/controller/intervention-controller.d.ts +3 -15
- package/dist/controller/intervention-controller.js +219 -57
- package/dist/controller/intervention-controller.js.map +1 -1
- package/dist/controller/policy-enricher.d.ts +10 -0
- package/dist/controller/policy-enricher.js +186 -0
- package/dist/controller/policy-enricher.js.map +1 -0
- package/dist/controller/retrieval-context.d.ts +3 -0
- package/dist/controller/retrieval-context.js +37 -0
- package/dist/controller/retrieval-context.js.map +1 -0
- package/dist/controller/second-opinion-gate.d.ts +41 -0
- package/dist/controller/second-opinion-gate.js +225 -0
- package/dist/controller/second-opinion-gate.js.map +1 -0
- package/dist/controller/trigger-evaluator.d.ts +6 -1
- package/dist/controller/trigger-evaluator.js +31 -1
- package/dist/controller/trigger-evaluator.js.map +1 -1
- package/dist/distillation/prompt-contract.d.ts +1 -1
- package/dist/distillation/prompt-contract.js +3 -1
- package/dist/distillation/prompt-contract.js.map +1 -1
- package/dist/distillation/providers/gemini.js +5 -1
- package/dist/distillation/providers/gemini.js.map +1 -1
- package/dist/distillation/queue-worker.js +22 -3
- package/dist/distillation/queue-worker.js.map +1 -1
- package/dist/evaluation/codex-lifecycle-validation.d.ts +60 -0
- package/dist/evaluation/codex-lifecycle-validation.js +233 -0
- package/dist/evaluation/codex-lifecycle-validation.js.map +1 -0
- package/dist/evaluation/hybrid-phase1-rollout-summary.d.ts +63 -0
- package/dist/evaluation/hybrid-phase1-rollout-summary.js +108 -0
- package/dist/evaluation/hybrid-phase1-rollout-summary.js.map +1 -0
- package/dist/evaluation/hybrid-phase3-gate-metrics.d.ts +26 -0
- package/dist/evaluation/hybrid-phase3-gate-metrics.js +23 -0
- package/dist/evaluation/hybrid-phase3-gate-metrics.js.map +1 -0
- package/dist/evaluation/openclaw-baseline.d.ts +8 -0
- package/dist/evaluation/openclaw-baseline.js +27 -0
- package/dist/evaluation/openclaw-baseline.js.map +1 -1
- package/dist/experience-management/governance-observability.d.ts +13 -0
- package/dist/experience-management/governance-observability.js +37 -0
- package/dist/experience-management/governance-observability.js.map +1 -0
- package/dist/experience-management/node-lifecycle-governance.d.ts +8 -0
- package/dist/experience-management/node-lifecycle-governance.js +80 -0
- package/dist/experience-management/node-lifecycle-governance.js.map +1 -0
- package/dist/experience-management/task-management-signals.d.ts +29 -0
- package/dist/experience-management/task-management-signals.js +148 -0
- package/dist/experience-management/task-management-signals.js.map +1 -0
- package/dist/feedback/feedback-manager.d.ts +4 -1
- package/dist/feedback/feedback-manager.js +11 -22
- package/dist/feedback/feedback-manager.js.map +1 -1
- package/dist/feedback/state-transition.d.ts +6 -1
- package/dist/feedback/state-transition.js +6 -3
- package/dist/feedback/state-transition.js.map +1 -1
- package/dist/hybrid/capsule-builder.d.ts +23 -0
- package/dist/hybrid/capsule-builder.js +114 -0
- package/dist/hybrid/capsule-builder.js.map +1 -0
- package/dist/hybrid/explain-provider-client.d.ts +19 -0
- package/dist/hybrid/explain-provider-client.js +34 -0
- package/dist/hybrid/explain-provider-client.js.map +1 -0
- package/dist/hybrid/postmortem-provider-client.d.ts +19 -0
- package/dist/hybrid/postmortem-provider-client.js +34 -0
- package/dist/hybrid/postmortem-provider-client.js.map +1 -0
- package/dist/hybrid/rollout.d.ts +9 -0
- package/dist/hybrid/rollout.js +49 -0
- package/dist/hybrid/rollout.js.map +1 -0
- package/dist/hybrid/router.d.ts +4 -0
- package/dist/hybrid/router.js +62 -0
- package/dist/hybrid/router.js.map +1 -0
- package/dist/hybrid/types.d.ts +140 -0
- package/dist/hybrid/types.js +2 -0
- package/dist/hybrid/types.js.map +1 -0
- package/dist/hybrid/validators.d.ts +5 -0
- package/dist/hybrid/validators.js +94 -0
- package/dist/hybrid/validators.js.map +1 -0
- package/dist/hybrid/worker-client.d.ts +61 -0
- package/dist/hybrid/worker-client.js +196 -0
- package/dist/hybrid/worker-client.js.map +1 -0
- package/dist/hybrid/workers/explain-decision-llm.d.ts +8 -0
- package/dist/hybrid/workers/explain-decision-llm.js +152 -0
- package/dist/hybrid/workers/explain-decision-llm.js.map +1 -0
- package/dist/hybrid/workers/explain-decision.d.ts +2 -0
- package/dist/hybrid/workers/explain-decision.js +40 -0
- package/dist/hybrid/workers/explain-decision.js.map +1 -0
- package/dist/hybrid/workers/postmortem-review-llm.d.ts +8 -0
- package/dist/hybrid/workers/postmortem-review-llm.js +398 -0
- package/dist/hybrid/workers/postmortem-review-llm.js.map +1 -0
- package/dist/hybrid/workers/postmortem-review.d.ts +2 -0
- package/dist/hybrid/workers/postmortem-review.js +66 -0
- package/dist/hybrid/workers/postmortem-review.js.map +1 -0
- package/dist/install/claude-code-doctor.d.ts +1 -0
- package/dist/install/claude-code-doctor.js +20 -4
- package/dist/install/claude-code-doctor.js.map +1 -1
- package/dist/install/claude-code-installer.js +50 -1
- package/dist/install/claude-code-installer.js.map +1 -1
- package/dist/install/codex-cli.d.ts +15 -0
- package/dist/install/codex-cli.js +55 -3
- package/dist/install/codex-cli.js.map +1 -1
- package/dist/install/codex-installer.d.ts +7 -0
- package/dist/install/codex-installer.js +22 -0
- package/dist/install/codex-installer.js.map +1 -1
- package/dist/install/openclaw-cli.d.ts +11 -0
- package/dist/install/openclaw-cli.js.map +1 -1
- package/dist/install/openclaw-installer.d.ts +12 -7
- package/dist/install/openclaw-installer.js +197 -46
- package/dist/install/openclaw-installer.js.map +1 -1
- package/dist/interaction/service.d.ts +15 -0
- package/dist/interaction/service.js +189 -31
- package/dist/interaction/service.js.map +1 -1
- package/dist/plugin/hooks/before-prompt-build.d.ts +1 -0
- package/dist/plugin/hooks/before-prompt-build.js +4 -1
- package/dist/plugin/hooks/before-prompt-build.js.map +1 -1
- package/dist/plugin/openclaw-install-state.d.ts +39 -0
- package/dist/plugin/openclaw-install-state.js +24 -0
- package/dist/plugin/openclaw-install-state.js.map +1 -0
- package/dist/plugin/openclaw-plugin.d.ts +125 -0
- package/dist/plugin/openclaw-plugin.js +18 -7
- package/dist/plugin/openclaw-plugin.js.map +1 -1
- package/dist/plugin/openclaw-routine-interaction.d.ts +2 -1
- package/dist/plugin/openclaw-routine-interaction.js +12 -7
- package/dist/plugin/openclaw-routine-interaction.js.map +1 -1
- package/dist/plugin/openclaw-runtime-defaults.d.ts +16 -0
- package/dist/plugin/openclaw-runtime-defaults.js +16 -0
- package/dist/plugin/openclaw-runtime-defaults.js.map +1 -0
- package/dist/runtime/service.d.ts +34 -5
- package/dist/runtime/service.js +474 -49
- package/dist/runtime/service.js.map +1 -1
- package/dist/store/sqlite/db.js +28 -0
- package/dist/store/sqlite/db.js.map +1 -1
- package/dist/store/sqlite/repositories/hybrid-invocation-trace-repo.d.ts +11 -0
- package/dist/store/sqlite/repositories/hybrid-invocation-trace-repo.js +76 -0
- package/dist/store/sqlite/repositories/hybrid-invocation-trace-repo.js.map +1 -0
- package/dist/store/sqlite/repositories/hybrid-review-artifact-repo.d.ts +11 -0
- package/dist/store/sqlite/repositories/hybrid-review-artifact-repo.js +73 -0
- package/dist/store/sqlite/repositories/hybrid-review-artifact-repo.js.map +1 -0
- package/dist/store/sqlite/repositories/input-record-repo.d.ts +1 -0
- package/dist/store/sqlite/repositories/input-record-repo.js +13 -0
- package/dist/store/sqlite/repositories/input-record-repo.js.map +1 -1
- package/dist/store/sqlite/repositories/node-repo.d.ts +4 -0
- package/dist/store/sqlite/repositories/node-repo.js +54 -6
- package/dist/store/sqlite/repositories/node-repo.js.map +1 -1
- package/dist/store/sqlite/schema.sql +40 -0
- package/dist/store/vector/embeddings.js +26 -8
- package/dist/store/vector/embeddings.js.map +1 -1
- package/dist/types/domain.d.ts +151 -2
- package/dist/types/plugin.d.ts +2 -1
- package/docs/releases/v0.1.3.md +3 -2
- package/docs/releases/v0.2.0.md +85 -0
- package/docs/releases/v0.2.1.md +21 -0
- package/docs/user-guide.md +44 -13
- package/openclaw.plugin.json +81 -1
- package/package.json +11 -2
- package/plugins/claude-code-experienceengine/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code-experienceengine/scripts/install-deps.sh +1 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createHash, createHmac } from "node:crypto";
|
|
2
2
|
import { analyzeExperience } from "./experience-analyzer.js";
|
|
3
|
+
import { buildCandidateSignals } from "./candidate-signals.js";
|
|
3
4
|
import { dedupeCandidates } from "./node-deduper.js";
|
|
4
5
|
import { normalizeCandidate } from "./node-normalizer.js";
|
|
5
6
|
import { isSubstantiveToolEvent } from "../input/tool-event-significance.js";
|
|
7
|
+
import { deriveTaskManagementSignals } from "../experience-management/task-management-signals.js";
|
|
6
8
|
import { resolveDistillationResolution } from "../distillation/host-llm.js";
|
|
7
9
|
import { resolveGoogleAdcAccessToken } from "../distillation/providers/google-adc.js";
|
|
8
10
|
const DEFAULT_REQUEST_TIMEOUT_MS = 45_000;
|
|
@@ -92,6 +94,8 @@ const EXPECTATION_CORRECTION_REPAIR_PROMPT = `You are repairing a coding-experie
|
|
|
92
94
|
|
|
93
95
|
Decide whether the task should actually be stored as expectation_correction.
|
|
94
96
|
|
|
97
|
+
Use the provided correction_window as the semantic detection context. Only promote when the correction window shows a real directional correction and the evidence_gate shows objective support or user confirmation.
|
|
98
|
+
|
|
95
99
|
Return strict JSON:
|
|
96
100
|
- expectation_correction: boolean
|
|
97
101
|
- confidence_signal: confirmed_by_user | supported_by_objective_success | unconfirmed (required when true)
|
|
@@ -115,6 +119,87 @@ context_summary: "No user correction happened; this is a verification loop."
|
|
|
115
119
|
draft.compact_hint: "Run pnpm typecheck after each change."
|
|
116
120
|
output:
|
|
117
121
|
{"expectation_correction":false}`;
|
|
122
|
+
const EXPECTATION_CORRECTION_RESCUE_PROMPT = `You are rescuing a missed directional correction from a coding task.
|
|
123
|
+
|
|
124
|
+
The main learner rejected this task as not broadly reusable. You should only rescue it when the correction window and evidence gate show a real reusable expectation correction.
|
|
125
|
+
|
|
126
|
+
Return strict JSON:
|
|
127
|
+
- expectation_correction: boolean
|
|
128
|
+
- candidate: required only when expectation_correction=true
|
|
129
|
+
|
|
130
|
+
candidate must include:
|
|
131
|
+
- node_type: strategy | warning
|
|
132
|
+
- task_type
|
|
133
|
+
- trigger_pattern
|
|
134
|
+
- compact_hint
|
|
135
|
+
- success_signal
|
|
136
|
+
- evidence_summary
|
|
137
|
+
- experience_kind: expectation_correction
|
|
138
|
+
- confidence_signal: confirmed_by_user | supported_by_objective_success | unconfirmed
|
|
139
|
+
- validation_state: pending_reuse_validation
|
|
140
|
+
- correction_scope: task_local | repo_local | workflow_local | host_local | cross_repo_candidate
|
|
141
|
+
- correction_category: goal_interpretation | quality_bar | interaction_behavior | verification_order | implementation_boundary | style_constraint
|
|
142
|
+
- deviation_pattern
|
|
143
|
+
- corrected_constraint
|
|
144
|
+
|
|
145
|
+
Do not rescue:
|
|
146
|
+
- wording-only
|
|
147
|
+
- copy-only
|
|
148
|
+
- style-only
|
|
149
|
+
- presentation-only
|
|
150
|
+
- ordinary verification loops without a corrected direction`;
|
|
151
|
+
const EVIDENCE_DRIVEN_REVERSAL_REPAIR_PROMPT = `You are repairing a coding-experience draft for evidence-driven reversal.
|
|
152
|
+
|
|
153
|
+
Use the provided reversal_window as the semantic detection context. Only promote when:
|
|
154
|
+
- an earlier active hypothesis or direction existed
|
|
155
|
+
- later task evidence invalidated it
|
|
156
|
+
- the task pivoted to a replacement path
|
|
157
|
+
- later verification supported the replacement path
|
|
158
|
+
|
|
159
|
+
Return strict JSON:
|
|
160
|
+
- reversal_detected: boolean
|
|
161
|
+
- reversal_source: task_evidence (required when true)
|
|
162
|
+
- superseded_hypothesis: short sentence (required when true)
|
|
163
|
+
- replacement_constraint: short sentence (required when true)
|
|
164
|
+
- verification_evidence: short sentence (required when true)
|
|
165
|
+
- pivot_summary: short sentence (optional)
|
|
166
|
+
- correction_scope: task_local | repo_local | workflow_local | host_local | cross_repo_candidate (required when true)
|
|
167
|
+
- correction_category: goal_interpretation | quality_bar | interaction_behavior | verification_order | implementation_boundary | style_constraint (required when true)
|
|
168
|
+
- deviation_pattern: short sentence (required when true)
|
|
169
|
+
- corrected_constraint: short sentence (required when true)
|
|
170
|
+
|
|
171
|
+
Do not promote ordinary verification loops, confirmation of the same direction, or loose narrowing that did not overturn the original path.`;
|
|
172
|
+
const EVIDENCE_DRIVEN_REVERSAL_RESCUE_PROMPT = `You are rescuing a missed evidence-driven reversal from a coding task.
|
|
173
|
+
|
|
174
|
+
The main learner did not capture a reusable candidate. Rescue only when the reversal window shows:
|
|
175
|
+
- a prior active hypothesis
|
|
176
|
+
- stronger invalidating task evidence
|
|
177
|
+
- a pivot into a replacement path
|
|
178
|
+
- later validating evidence on the replacement path
|
|
179
|
+
|
|
180
|
+
Return strict JSON:
|
|
181
|
+
- reversal_detected: boolean
|
|
182
|
+
- reversal_source: task_evidence (required when true)
|
|
183
|
+
- superseded_hypothesis: short sentence (required when true)
|
|
184
|
+
- replacement_constraint: short sentence (required when true)
|
|
185
|
+
- verification_evidence: short sentence (required when true)
|
|
186
|
+
- pivot_summary: short sentence (optional)
|
|
187
|
+
- candidate: required only when reversal_detected=true
|
|
188
|
+
|
|
189
|
+
candidate must include:
|
|
190
|
+
- node_type: strategy | warning
|
|
191
|
+
- task_type
|
|
192
|
+
- trigger_pattern
|
|
193
|
+
- compact_hint
|
|
194
|
+
- success_signal
|
|
195
|
+
- evidence_summary
|
|
196
|
+
- experience_kind: expectation_correction
|
|
197
|
+
- confidence_signal: confirmed_by_user | supported_by_objective_success | unconfirmed
|
|
198
|
+
- validation_state: pending_reuse_validation
|
|
199
|
+
- correction_scope: task_local | repo_local | workflow_local | host_local | cross_repo_candidate
|
|
200
|
+
- correction_category: goal_interpretation | quality_bar | interaction_behavior | verification_order | implementation_boundary | style_constraint
|
|
201
|
+
- deviation_pattern
|
|
202
|
+
- corrected_constraint`;
|
|
118
203
|
const sha256Hex = (value) => createHash("sha256").update(value, "utf8").digest("hex");
|
|
119
204
|
const hmac = (key, value) => createHmac("sha256", key).update(value, "utf8").digest();
|
|
120
205
|
const toAmzDate = (date) => date.toISOString().replace(/[:-]|\.\d{3}/g, "");
|
|
@@ -257,6 +342,28 @@ const normalizeDraft = (candidate, input) => {
|
|
|
257
342
|
source_kind: "system_derived"
|
|
258
343
|
});
|
|
259
344
|
};
|
|
345
|
+
const applyTaskManagementPromotionPolicy = (input, draft) => {
|
|
346
|
+
const signals = deriveTaskManagementSignals(input);
|
|
347
|
+
const preserveHighValue = signals.realDevLikely &&
|
|
348
|
+
(signals.bugFixLike ||
|
|
349
|
+
draft.experience_kind === "expectation_correction" ||
|
|
350
|
+
input.task_type === "bug_fix" ||
|
|
351
|
+
input.task_type === "config_debug" ||
|
|
352
|
+
input.task_type === "integration_fix");
|
|
353
|
+
if (draft.promotion_signal !== "high_value" || preserveHighValue) {
|
|
354
|
+
return draft;
|
|
355
|
+
}
|
|
356
|
+
const downgradeReason = signals.metaLike
|
|
357
|
+
? "downgraded from high_value because the task looked meta-like and still needs real-dev reuse evidence"
|
|
358
|
+
: signals.validationLike
|
|
359
|
+
? "downgraded from high_value because the task looked validation-heavy and still needs real-dev reuse evidence"
|
|
360
|
+
: draft.promotion_reason;
|
|
361
|
+
return {
|
|
362
|
+
...draft,
|
|
363
|
+
promotion_signal: "normal",
|
|
364
|
+
promotion_reason: downgradeReason
|
|
365
|
+
};
|
|
366
|
+
};
|
|
260
367
|
export class LlmLearningGate {
|
|
261
368
|
config;
|
|
262
369
|
options;
|
|
@@ -351,7 +458,7 @@ export class LlmLearningGate {
|
|
|
351
458
|
temperature: 0.1
|
|
352
459
|
};
|
|
353
460
|
}
|
|
354
|
-
buildExpectationCorrectionRepairBody(endpoint, input, draft, reason) {
|
|
461
|
+
buildExpectationCorrectionRepairBody(endpoint, input, draft, reason, directionalCorrection) {
|
|
355
462
|
const payload = JSON.stringify({
|
|
356
463
|
task_summary: input.task_summary,
|
|
357
464
|
task_type: input.task_type,
|
|
@@ -372,6 +479,15 @@ export class LlmLearningGate {
|
|
|
372
479
|
success_signal: draft.success_signal,
|
|
373
480
|
evidence_summary: draft.evidence_summary
|
|
374
481
|
},
|
|
482
|
+
correction_window: {
|
|
483
|
+
selected: directionalCorrection.detected,
|
|
484
|
+
snippets: directionalCorrection.snippets,
|
|
485
|
+
sources: directionalCorrection.sources
|
|
486
|
+
},
|
|
487
|
+
evidence_gate: {
|
|
488
|
+
objective_support: directionalCorrection.objective_support,
|
|
489
|
+
user_confirmation: directionalCorrection.user_confirmation
|
|
490
|
+
},
|
|
375
491
|
original_reason: reason
|
|
376
492
|
}, null, 2);
|
|
377
493
|
if (endpoint.kind === "anthropic") {
|
|
@@ -425,6 +541,245 @@ export class LlmLearningGate {
|
|
|
425
541
|
temperature: 0
|
|
426
542
|
};
|
|
427
543
|
}
|
|
544
|
+
buildExpectationCorrectionRescueBody(endpoint, input, reason, directionalCorrection) {
|
|
545
|
+
const payload = JSON.stringify({
|
|
546
|
+
task_summary: input.task_summary,
|
|
547
|
+
task_type: input.task_type,
|
|
548
|
+
context_summary: input.context_summary,
|
|
549
|
+
outcome_signal: input.outcome_signal,
|
|
550
|
+
tool_events: input.tool_events.map((event) => ({
|
|
551
|
+
tool_name: event.tool_name,
|
|
552
|
+
status: event.status,
|
|
553
|
+
error_signature: event.error_signature,
|
|
554
|
+
output_summary: event.output_summary
|
|
555
|
+
})),
|
|
556
|
+
correction_window: {
|
|
557
|
+
selected: directionalCorrection.detected,
|
|
558
|
+
snippets: directionalCorrection.snippets,
|
|
559
|
+
sources: directionalCorrection.sources
|
|
560
|
+
},
|
|
561
|
+
evidence_gate: {
|
|
562
|
+
objective_support: directionalCorrection.objective_support,
|
|
563
|
+
user_confirmation: directionalCorrection.user_confirmation
|
|
564
|
+
},
|
|
565
|
+
original_reason: reason
|
|
566
|
+
}, null, 2);
|
|
567
|
+
if (endpoint.kind === "anthropic") {
|
|
568
|
+
return {
|
|
569
|
+
model: endpoint.model,
|
|
570
|
+
max_tokens: 768,
|
|
571
|
+
system: EXPECTATION_CORRECTION_RESCUE_PROMPT,
|
|
572
|
+
messages: [{ role: "user", content: payload }],
|
|
573
|
+
temperature: 0
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
if (endpoint.kind === "gemini") {
|
|
577
|
+
return {
|
|
578
|
+
system_instruction: {
|
|
579
|
+
parts: [{ text: EXPECTATION_CORRECTION_RESCUE_PROMPT }]
|
|
580
|
+
},
|
|
581
|
+
contents: [
|
|
582
|
+
{
|
|
583
|
+
role: "user",
|
|
584
|
+
parts: [{ text: payload }]
|
|
585
|
+
}
|
|
586
|
+
],
|
|
587
|
+
generationConfig: {
|
|
588
|
+
temperature: 0,
|
|
589
|
+
responseMimeType: "application/json"
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
if (endpoint.kind === "bedrock") {
|
|
594
|
+
return {
|
|
595
|
+
system: [{ text: EXPECTATION_CORRECTION_RESCUE_PROMPT }],
|
|
596
|
+
messages: [
|
|
597
|
+
{
|
|
598
|
+
role: "user",
|
|
599
|
+
content: [{ text: payload }]
|
|
600
|
+
}
|
|
601
|
+
],
|
|
602
|
+
inferenceConfig: {
|
|
603
|
+
maxTokens: 768,
|
|
604
|
+
temperature: 0
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
return {
|
|
609
|
+
model: endpoint.model,
|
|
610
|
+
response_format: { type: "json_object" },
|
|
611
|
+
messages: [
|
|
612
|
+
{ role: "system", content: EXPECTATION_CORRECTION_RESCUE_PROMPT },
|
|
613
|
+
{ role: "user", content: payload }
|
|
614
|
+
],
|
|
615
|
+
temperature: 0
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
buildEvidenceDrivenReversalRepairBody(endpoint, input, draft, reason, reversal) {
|
|
619
|
+
const payload = JSON.stringify({
|
|
620
|
+
task_summary: input.task_summary,
|
|
621
|
+
task_type: input.task_type,
|
|
622
|
+
context_summary: input.context_summary,
|
|
623
|
+
outcome_signal: input.outcome_signal,
|
|
624
|
+
tool_events: input.tool_events.map((event) => ({
|
|
625
|
+
tool_name: event.tool_name,
|
|
626
|
+
status: event.status,
|
|
627
|
+
error_signature: event.error_signature,
|
|
628
|
+
output_summary: event.output_summary
|
|
629
|
+
})),
|
|
630
|
+
draft: {
|
|
631
|
+
task_type: draft.task_type,
|
|
632
|
+
node_type: draft.node_type,
|
|
633
|
+
experience_kind: draft.experience_kind,
|
|
634
|
+
trigger_pattern: draft.trigger_pattern,
|
|
635
|
+
compact_hint: draft.compact_hint,
|
|
636
|
+
success_signal: draft.success_signal,
|
|
637
|
+
evidence_summary: draft.evidence_summary
|
|
638
|
+
},
|
|
639
|
+
reversal_window: {
|
|
640
|
+
selected: reversal.detected,
|
|
641
|
+
hypothesis_snippets: reversal.hypothesis_snippets,
|
|
642
|
+
invalidating_snippets: reversal.invalidating_snippets,
|
|
643
|
+
pivot_snippets: reversal.pivot_snippets,
|
|
644
|
+
replacement_snippets: reversal.replacement_snippets,
|
|
645
|
+
validating_snippets: reversal.validating_snippets
|
|
646
|
+
},
|
|
647
|
+
evidence_gate: {
|
|
648
|
+
prior_hypothesis: reversal.prior_hypothesis,
|
|
649
|
+
invalidating_evidence: reversal.invalidating_evidence,
|
|
650
|
+
validating_evidence: reversal.validating_evidence
|
|
651
|
+
},
|
|
652
|
+
original_reason: reason
|
|
653
|
+
}, null, 2);
|
|
654
|
+
if (endpoint.kind === "anthropic") {
|
|
655
|
+
return {
|
|
656
|
+
model: endpoint.model,
|
|
657
|
+
max_tokens: 640,
|
|
658
|
+
system: EVIDENCE_DRIVEN_REVERSAL_REPAIR_PROMPT,
|
|
659
|
+
messages: [{ role: "user", content: payload }],
|
|
660
|
+
temperature: 0
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
if (endpoint.kind === "gemini") {
|
|
664
|
+
return {
|
|
665
|
+
system_instruction: {
|
|
666
|
+
parts: [{ text: EVIDENCE_DRIVEN_REVERSAL_REPAIR_PROMPT }]
|
|
667
|
+
},
|
|
668
|
+
contents: [
|
|
669
|
+
{
|
|
670
|
+
role: "user",
|
|
671
|
+
parts: [{ text: payload }]
|
|
672
|
+
}
|
|
673
|
+
],
|
|
674
|
+
generationConfig: {
|
|
675
|
+
temperature: 0,
|
|
676
|
+
responseMimeType: "application/json"
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
if (endpoint.kind === "bedrock") {
|
|
681
|
+
return {
|
|
682
|
+
system: [{ text: EVIDENCE_DRIVEN_REVERSAL_REPAIR_PROMPT }],
|
|
683
|
+
messages: [
|
|
684
|
+
{
|
|
685
|
+
role: "user",
|
|
686
|
+
content: [{ text: payload }]
|
|
687
|
+
}
|
|
688
|
+
],
|
|
689
|
+
inferenceConfig: {
|
|
690
|
+
maxTokens: 640,
|
|
691
|
+
temperature: 0
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
return {
|
|
696
|
+
model: endpoint.model,
|
|
697
|
+
response_format: { type: "json_object" },
|
|
698
|
+
messages: [
|
|
699
|
+
{ role: "system", content: EVIDENCE_DRIVEN_REVERSAL_REPAIR_PROMPT },
|
|
700
|
+
{ role: "user", content: payload }
|
|
701
|
+
],
|
|
702
|
+
temperature: 0
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
buildEvidenceDrivenReversalRescueBody(endpoint, input, reason, reversal) {
|
|
706
|
+
const payload = JSON.stringify({
|
|
707
|
+
task_summary: input.task_summary,
|
|
708
|
+
task_type: input.task_type,
|
|
709
|
+
context_summary: input.context_summary,
|
|
710
|
+
outcome_signal: input.outcome_signal,
|
|
711
|
+
tool_events: input.tool_events.map((event) => ({
|
|
712
|
+
tool_name: event.tool_name,
|
|
713
|
+
status: event.status,
|
|
714
|
+
error_signature: event.error_signature,
|
|
715
|
+
output_summary: event.output_summary
|
|
716
|
+
})),
|
|
717
|
+
reversal_window: {
|
|
718
|
+
selected: reversal.detected,
|
|
719
|
+
hypothesis_snippets: reversal.hypothesis_snippets,
|
|
720
|
+
invalidating_snippets: reversal.invalidating_snippets,
|
|
721
|
+
pivot_snippets: reversal.pivot_snippets,
|
|
722
|
+
replacement_snippets: reversal.replacement_snippets,
|
|
723
|
+
validating_snippets: reversal.validating_snippets
|
|
724
|
+
},
|
|
725
|
+
evidence_gate: {
|
|
726
|
+
prior_hypothesis: reversal.prior_hypothesis,
|
|
727
|
+
invalidating_evidence: reversal.invalidating_evidence,
|
|
728
|
+
validating_evidence: reversal.validating_evidence
|
|
729
|
+
},
|
|
730
|
+
original_reason: reason
|
|
731
|
+
}, null, 2);
|
|
732
|
+
if (endpoint.kind === "anthropic") {
|
|
733
|
+
return {
|
|
734
|
+
model: endpoint.model,
|
|
735
|
+
max_tokens: 768,
|
|
736
|
+
system: EVIDENCE_DRIVEN_REVERSAL_RESCUE_PROMPT,
|
|
737
|
+
messages: [{ role: "user", content: payload }],
|
|
738
|
+
temperature: 0
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
if (endpoint.kind === "gemini") {
|
|
742
|
+
return {
|
|
743
|
+
system_instruction: {
|
|
744
|
+
parts: [{ text: EVIDENCE_DRIVEN_REVERSAL_RESCUE_PROMPT }]
|
|
745
|
+
},
|
|
746
|
+
contents: [
|
|
747
|
+
{
|
|
748
|
+
role: "user",
|
|
749
|
+
parts: [{ text: payload }]
|
|
750
|
+
}
|
|
751
|
+
],
|
|
752
|
+
generationConfig: {
|
|
753
|
+
temperature: 0,
|
|
754
|
+
responseMimeType: "application/json"
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
if (endpoint.kind === "bedrock") {
|
|
759
|
+
return {
|
|
760
|
+
system: [{ text: EVIDENCE_DRIVEN_REVERSAL_RESCUE_PROMPT }],
|
|
761
|
+
messages: [
|
|
762
|
+
{
|
|
763
|
+
role: "user",
|
|
764
|
+
content: [{ text: payload }]
|
|
765
|
+
}
|
|
766
|
+
],
|
|
767
|
+
inferenceConfig: {
|
|
768
|
+
maxTokens: 768,
|
|
769
|
+
temperature: 0
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
return {
|
|
774
|
+
model: endpoint.model,
|
|
775
|
+
response_format: { type: "json_object" },
|
|
776
|
+
messages: [
|
|
777
|
+
{ role: "system", content: EVIDENCE_DRIVEN_REVERSAL_RESCUE_PROMPT },
|
|
778
|
+
{ role: "user", content: payload }
|
|
779
|
+
],
|
|
780
|
+
temperature: 0
|
|
781
|
+
};
|
|
782
|
+
}
|
|
428
783
|
parseExpectationCorrectionRepair(content) {
|
|
429
784
|
const parsed = JSON.parse(content);
|
|
430
785
|
if (parsed.expectation_correction !== true) {
|
|
@@ -454,7 +809,112 @@ export class LlmLearningGate {
|
|
|
454
809
|
corrected_constraint: correctedConstraint
|
|
455
810
|
};
|
|
456
811
|
}
|
|
457
|
-
|
|
812
|
+
parseExpectationCorrectionRescue(content, input, directionalCorrection) {
|
|
813
|
+
const parsed = JSON.parse(content);
|
|
814
|
+
if (parsed.expectation_correction !== true) {
|
|
815
|
+
return undefined;
|
|
816
|
+
}
|
|
817
|
+
const rawCandidate = parsed.candidate && typeof parsed.candidate === "object"
|
|
818
|
+
? parsed.candidate
|
|
819
|
+
: undefined;
|
|
820
|
+
if (!rawCandidate) {
|
|
821
|
+
return undefined;
|
|
822
|
+
}
|
|
823
|
+
const draft = normalizeDraft(rawCandidate, input);
|
|
824
|
+
if (draft.experience_kind !== "expectation_correction" ||
|
|
825
|
+
!draft.correction_category ||
|
|
826
|
+
!draft.deviation_pattern ||
|
|
827
|
+
!draft.corrected_constraint) {
|
|
828
|
+
return undefined;
|
|
829
|
+
}
|
|
830
|
+
return {
|
|
831
|
+
draft,
|
|
832
|
+
directionalCorrectionSignal: {
|
|
833
|
+
...directionalCorrection,
|
|
834
|
+
semantic_detected: true,
|
|
835
|
+
correction_category: draft.correction_category,
|
|
836
|
+
deviation_pattern: draft.deviation_pattern,
|
|
837
|
+
corrected_constraint: draft.corrected_constraint
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
parseEvidenceDrivenReversalRepair(content) {
|
|
842
|
+
const parsed = JSON.parse(content);
|
|
843
|
+
if (parsed.reversal_detected !== true) {
|
|
844
|
+
return undefined;
|
|
845
|
+
}
|
|
846
|
+
const reversalSource = parsed.reversal_source === "task_evidence" ? "task_evidence" : undefined;
|
|
847
|
+
const supersededHypothesis = pickString(parsed.superseded_hypothesis);
|
|
848
|
+
const replacementConstraint = pickString(parsed.replacement_constraint);
|
|
849
|
+
const verificationEvidence = pickString(parsed.verification_evidence);
|
|
850
|
+
const pivotSummary = pickString(parsed.pivot_summary);
|
|
851
|
+
const correctionScope = isCorrectionScope(parsed.correction_scope) ? parsed.correction_scope : undefined;
|
|
852
|
+
const correctionCategory = isCorrectionCategory(parsed.correction_category) ? parsed.correction_category : undefined;
|
|
853
|
+
const deviationPattern = pickString(parsed.deviation_pattern);
|
|
854
|
+
const correctedConstraint = pickString(parsed.corrected_constraint);
|
|
855
|
+
if (!reversalSource ||
|
|
856
|
+
!supersededHypothesis ||
|
|
857
|
+
!replacementConstraint ||
|
|
858
|
+
!verificationEvidence ||
|
|
859
|
+
!correctionScope ||
|
|
860
|
+
!correctionCategory ||
|
|
861
|
+
!deviationPattern ||
|
|
862
|
+
!correctedConstraint) {
|
|
863
|
+
return undefined;
|
|
864
|
+
}
|
|
865
|
+
return {
|
|
866
|
+
reversal_detected: true,
|
|
867
|
+
reversal_source: reversalSource,
|
|
868
|
+
superseded_hypothesis: supersededHypothesis,
|
|
869
|
+
replacement_constraint: replacementConstraint,
|
|
870
|
+
verification_evidence: verificationEvidence,
|
|
871
|
+
pivot_summary: pivotSummary,
|
|
872
|
+
correction_scope: correctionScope,
|
|
873
|
+
correction_category: correctionCategory,
|
|
874
|
+
deviation_pattern: deviationPattern,
|
|
875
|
+
corrected_constraint: correctedConstraint
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
parseEvidenceDrivenReversalRescue(content, input, reversal) {
|
|
879
|
+
const parsed = JSON.parse(content);
|
|
880
|
+
if (parsed.reversal_detected !== true) {
|
|
881
|
+
return undefined;
|
|
882
|
+
}
|
|
883
|
+
const reversalSource = parsed.reversal_source === "task_evidence" ? "task_evidence" : undefined;
|
|
884
|
+
const supersededHypothesis = pickString(parsed.superseded_hypothesis);
|
|
885
|
+
const replacementConstraint = pickString(parsed.replacement_constraint);
|
|
886
|
+
const verificationEvidence = pickString(parsed.verification_evidence);
|
|
887
|
+
const pivotSummary = pickString(parsed.pivot_summary);
|
|
888
|
+
const rawCandidate = parsed.candidate && typeof parsed.candidate === "object"
|
|
889
|
+
? parsed.candidate
|
|
890
|
+
: undefined;
|
|
891
|
+
if (!rawCandidate || !reversalSource || !supersededHypothesis || !replacementConstraint || !verificationEvidence) {
|
|
892
|
+
return undefined;
|
|
893
|
+
}
|
|
894
|
+
const draft = normalizeDraft(rawCandidate, input);
|
|
895
|
+
if (draft.experience_kind !== "expectation_correction" ||
|
|
896
|
+
!draft.correction_category ||
|
|
897
|
+
!draft.deviation_pattern ||
|
|
898
|
+
!draft.corrected_constraint) {
|
|
899
|
+
return undefined;
|
|
900
|
+
}
|
|
901
|
+
return {
|
|
902
|
+
draft,
|
|
903
|
+
evidenceDrivenReversalSignal: {
|
|
904
|
+
...reversal,
|
|
905
|
+
semantic_detected: true,
|
|
906
|
+
reversal_source: reversalSource,
|
|
907
|
+
superseded_hypothesis: supersededHypothesis,
|
|
908
|
+
replacement_constraint: replacementConstraint,
|
|
909
|
+
verification_evidence: verificationEvidence,
|
|
910
|
+
pivot_summary: pivotSummary,
|
|
911
|
+
correction_category: draft.correction_category,
|
|
912
|
+
deviation_pattern: draft.deviation_pattern,
|
|
913
|
+
corrected_constraint: draft.corrected_constraint
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
async maybeRepairExpectationCorrection(endpoint, input, reason, draft, directionalCorrection) {
|
|
458
918
|
const hasCompleteExpectationCorrectionShape = draft.experience_kind === "expectation_correction" &&
|
|
459
919
|
Boolean(draft.confidence_signal &&
|
|
460
920
|
draft.validation_state &&
|
|
@@ -463,25 +923,156 @@ export class LlmLearningGate {
|
|
|
463
923
|
draft.deviation_pattern &&
|
|
464
924
|
draft.corrected_constraint);
|
|
465
925
|
if (input.outcome_signal !== "success" || hasCompleteExpectationCorrectionShape) {
|
|
466
|
-
return
|
|
926
|
+
return {
|
|
927
|
+
draft,
|
|
928
|
+
directionalCorrectionSignal: directionalCorrection?.detected ? directionalCorrection : undefined
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
if (!directionalCorrection?.detected ||
|
|
932
|
+
(!directionalCorrection.objective_support && !directionalCorrection.user_confirmation)) {
|
|
933
|
+
return {
|
|
934
|
+
draft,
|
|
935
|
+
directionalCorrectionSignal: directionalCorrection?.detected ? directionalCorrection : undefined
|
|
936
|
+
};
|
|
467
937
|
}
|
|
468
938
|
try {
|
|
469
|
-
const response = await this.postJsonWithRetry(this.buildRequestUrl(endpoint), endpoint, this.buildExpectationCorrectionRepairBody(endpoint, input, draft, reason));
|
|
939
|
+
const response = await this.postJsonWithRetry(this.buildRequestUrl(endpoint), endpoint, this.buildExpectationCorrectionRepairBody(endpoint, input, draft, reason, directionalCorrection));
|
|
470
940
|
if (!response.ok) {
|
|
471
|
-
return
|
|
941
|
+
return {
|
|
942
|
+
draft,
|
|
943
|
+
directionalCorrectionSignal: directionalCorrection
|
|
944
|
+
};
|
|
472
945
|
}
|
|
473
946
|
const content = await this.parseResponseContent(endpoint, response);
|
|
474
947
|
const repair = this.parseExpectationCorrectionRepair(content);
|
|
475
948
|
if (!repair) {
|
|
476
|
-
return
|
|
949
|
+
return {
|
|
950
|
+
draft,
|
|
951
|
+
directionalCorrectionSignal: directionalCorrection
|
|
952
|
+
};
|
|
477
953
|
}
|
|
478
|
-
return
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
954
|
+
return {
|
|
955
|
+
draft: normalizeCandidate({
|
|
956
|
+
...draft,
|
|
957
|
+
...repair
|
|
958
|
+
}),
|
|
959
|
+
directionalCorrectionSignal: {
|
|
960
|
+
...directionalCorrection,
|
|
961
|
+
semantic_detected: true,
|
|
962
|
+
correction_category: repair.correction_category,
|
|
963
|
+
deviation_pattern: repair.deviation_pattern,
|
|
964
|
+
corrected_constraint: repair.corrected_constraint
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
catch {
|
|
969
|
+
return {
|
|
970
|
+
draft,
|
|
971
|
+
directionalCorrectionSignal: directionalCorrection
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
async maybeRepairEvidenceDrivenReversal(endpoint, input, reason, draft, directionalCorrection, reversal) {
|
|
976
|
+
if (input.outcome_signal !== "success" ||
|
|
977
|
+
(directionalCorrection?.correction_source &&
|
|
978
|
+
directionalCorrection.correction_source !== "task_evidence" &&
|
|
979
|
+
directionalCorrection.detected) ||
|
|
980
|
+
!reversal?.detected ||
|
|
981
|
+
!reversal.prior_hypothesis ||
|
|
982
|
+
!reversal.invalidating_evidence ||
|
|
983
|
+
!reversal.validating_evidence) {
|
|
984
|
+
return {
|
|
985
|
+
draft,
|
|
986
|
+
evidenceDrivenReversalSignal: reversal?.detected ? reversal : undefined
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
try {
|
|
990
|
+
const response = await this.postJsonWithRetry(this.buildRequestUrl(endpoint), endpoint, this.buildEvidenceDrivenReversalRepairBody(endpoint, input, draft, reason, reversal));
|
|
991
|
+
if (!response.ok) {
|
|
992
|
+
return {
|
|
993
|
+
draft,
|
|
994
|
+
evidenceDrivenReversalSignal: reversal
|
|
995
|
+
};
|
|
996
|
+
}
|
|
997
|
+
const content = await this.parseResponseContent(endpoint, response);
|
|
998
|
+
const repair = this.parseEvidenceDrivenReversalRepair(content);
|
|
999
|
+
if (!repair) {
|
|
1000
|
+
return {
|
|
1001
|
+
draft,
|
|
1002
|
+
evidenceDrivenReversalSignal: reversal
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
return {
|
|
1006
|
+
draft: normalizeCandidate({
|
|
1007
|
+
...draft,
|
|
1008
|
+
experience_kind: "expectation_correction",
|
|
1009
|
+
confidence_signal: draft.confidence_signal ?? "supported_by_objective_success",
|
|
1010
|
+
validation_state: draft.validation_state ?? "pending_reuse_validation",
|
|
1011
|
+
correction_scope: repair.correction_scope,
|
|
1012
|
+
correction_category: repair.correction_category,
|
|
1013
|
+
deviation_pattern: repair.deviation_pattern,
|
|
1014
|
+
corrected_constraint: repair.corrected_constraint
|
|
1015
|
+
}),
|
|
1016
|
+
evidenceDrivenReversalSignal: {
|
|
1017
|
+
...reversal,
|
|
1018
|
+
semantic_detected: true,
|
|
1019
|
+
reversal_source: repair.reversal_source,
|
|
1020
|
+
superseded_hypothesis: repair.superseded_hypothesis,
|
|
1021
|
+
replacement_constraint: repair.replacement_constraint,
|
|
1022
|
+
verification_evidence: repair.verification_evidence,
|
|
1023
|
+
pivot_summary: repair.pivot_summary,
|
|
1024
|
+
correction_category: repair.correction_category,
|
|
1025
|
+
deviation_pattern: repair.deviation_pattern,
|
|
1026
|
+
corrected_constraint: repair.corrected_constraint
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
482
1029
|
}
|
|
483
1030
|
catch {
|
|
484
|
-
return
|
|
1031
|
+
return {
|
|
1032
|
+
draft,
|
|
1033
|
+
evidenceDrivenReversalSignal: reversal
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
async maybeRescueExpectationCorrection(endpoint, input, reason, directionalCorrection) {
|
|
1038
|
+
if (input.outcome_signal !== "success" ||
|
|
1039
|
+
!directionalCorrection?.detected ||
|
|
1040
|
+
(!directionalCorrection.objective_support && !directionalCorrection.user_confirmation)) {
|
|
1041
|
+
return undefined;
|
|
1042
|
+
}
|
|
1043
|
+
try {
|
|
1044
|
+
const response = await this.postJsonWithRetry(this.buildRequestUrl(endpoint), endpoint, this.buildExpectationCorrectionRescueBody(endpoint, input, reason, directionalCorrection));
|
|
1045
|
+
if (!response.ok) {
|
|
1046
|
+
return undefined;
|
|
1047
|
+
}
|
|
1048
|
+
const content = await this.parseResponseContent(endpoint, response);
|
|
1049
|
+
return this.parseExpectationCorrectionRescue(content, input, directionalCorrection);
|
|
1050
|
+
}
|
|
1051
|
+
catch {
|
|
1052
|
+
return undefined;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
async maybeRescueEvidenceDrivenReversal(endpoint, input, reason, directionalCorrection, reversal) {
|
|
1056
|
+
if (input.outcome_signal !== "success" ||
|
|
1057
|
+
(directionalCorrection?.correction_source &&
|
|
1058
|
+
directionalCorrection.correction_source !== "task_evidence" &&
|
|
1059
|
+
directionalCorrection.detected) ||
|
|
1060
|
+
!reversal?.detected ||
|
|
1061
|
+
!reversal.prior_hypothesis ||
|
|
1062
|
+
!reversal.invalidating_evidence ||
|
|
1063
|
+
!reversal.validating_evidence) {
|
|
1064
|
+
return undefined;
|
|
1065
|
+
}
|
|
1066
|
+
try {
|
|
1067
|
+
const response = await this.postJsonWithRetry(this.buildRequestUrl(endpoint), endpoint, this.buildEvidenceDrivenReversalRescueBody(endpoint, input, reason, reversal));
|
|
1068
|
+
if (!response.ok) {
|
|
1069
|
+
return undefined;
|
|
1070
|
+
}
|
|
1071
|
+
const content = await this.parseResponseContent(endpoint, response);
|
|
1072
|
+
return this.parseEvidenceDrivenReversalRescue(content, input, reversal);
|
|
1073
|
+
}
|
|
1074
|
+
catch {
|
|
1075
|
+
return undefined;
|
|
485
1076
|
}
|
|
486
1077
|
}
|
|
487
1078
|
async parseResponseContent(endpoint, response) {
|
|
@@ -624,7 +1215,7 @@ export class LlmLearningGate {
|
|
|
624
1215
|
return {
|
|
625
1216
|
worthCapturing: fallback.accepted.length > 0,
|
|
626
1217
|
reason: fallback.accepted.length > 0 ? "captured by rule fallback" : "rule fallback rejected candidate",
|
|
627
|
-
drafts: fallback.accepted,
|
|
1218
|
+
drafts: fallback.accepted.map((draft) => applyTaskManagementPromotionPolicy(input, draft)),
|
|
628
1219
|
source: "rule"
|
|
629
1220
|
};
|
|
630
1221
|
}
|
|
@@ -637,7 +1228,30 @@ export class LlmLearningGate {
|
|
|
637
1228
|
const parsed = JSON.parse(content);
|
|
638
1229
|
const worthCapturing = parsed.worth_capturing === true;
|
|
639
1230
|
const reason = pickString(parsed.reason) ?? "no reason provided";
|
|
1231
|
+
const candidateSignals = buildCandidateSignals(input);
|
|
1232
|
+
const directionalCorrection = candidateSignals.directional_correction;
|
|
1233
|
+
const evidenceDrivenReversal = candidateSignals.evidence_driven_reversal;
|
|
640
1234
|
if (!worthCapturing) {
|
|
1235
|
+
const rescued = await this.maybeRescueExpectationCorrection(resolution.endpoint, input, reason, directionalCorrection);
|
|
1236
|
+
if (rescued) {
|
|
1237
|
+
return {
|
|
1238
|
+
worthCapturing: true,
|
|
1239
|
+
reason: `rescued directional correction: ${reason}`,
|
|
1240
|
+
drafts: dedupeCandidates([applyTaskManagementPromotionPolicy(input, rescued.draft)]),
|
|
1241
|
+
source: "llm",
|
|
1242
|
+
directionalCorrectionSignal: rescued.directionalCorrectionSignal
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
const rescuedReversal = await this.maybeRescueEvidenceDrivenReversal(resolution.endpoint, input, reason, directionalCorrection, evidenceDrivenReversal);
|
|
1246
|
+
if (rescuedReversal) {
|
|
1247
|
+
return {
|
|
1248
|
+
worthCapturing: true,
|
|
1249
|
+
reason: `rescued evidence-driven reversal: ${reason}`,
|
|
1250
|
+
drafts: dedupeCandidates([applyTaskManagementPromotionPolicy(input, rescuedReversal.draft)]),
|
|
1251
|
+
source: "llm",
|
|
1252
|
+
evidenceDrivenReversalSignal: rescuedReversal.evidenceDrivenReversalSignal
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
641
1255
|
return {
|
|
642
1256
|
worthCapturing: false,
|
|
643
1257
|
reason,
|
|
@@ -651,12 +1265,15 @@ export class LlmLearningGate {
|
|
|
651
1265
|
if (!rawCandidate) {
|
|
652
1266
|
throw new Error("Learning gate marked worth_capturing=true without a candidate payload");
|
|
653
1267
|
}
|
|
654
|
-
const
|
|
1268
|
+
const repaired = await this.maybeRepairExpectationCorrection(resolution.endpoint, input, reason, normalizeDraft(rawCandidate, input), directionalCorrection);
|
|
1269
|
+
const reversalRepaired = await this.maybeRepairEvidenceDrivenReversal(resolution.endpoint, input, reason, repaired.draft, directionalCorrection, evidenceDrivenReversal);
|
|
655
1270
|
return {
|
|
656
1271
|
worthCapturing: true,
|
|
657
1272
|
reason,
|
|
658
|
-
drafts: dedupeCandidates([draft]),
|
|
659
|
-
source: "llm"
|
|
1273
|
+
drafts: dedupeCandidates([applyTaskManagementPromotionPolicy(input, reversalRepaired.draft)]),
|
|
1274
|
+
source: "llm",
|
|
1275
|
+
directionalCorrectionSignal: repaired.directionalCorrectionSignal,
|
|
1276
|
+
evidenceDrivenReversalSignal: reversalRepaired.evidenceDrivenReversalSignal
|
|
660
1277
|
};
|
|
661
1278
|
}
|
|
662
1279
|
catch (error) {
|
|
@@ -664,7 +1281,7 @@ export class LlmLearningGate {
|
|
|
664
1281
|
return {
|
|
665
1282
|
worthCapturing: fallback.accepted.length > 0,
|
|
666
1283
|
reason: `llm gate failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
667
|
-
drafts: fallback.accepted,
|
|
1284
|
+
drafts: fallback.accepted.map((draft) => applyTaskManagementPromotionPolicy(input, draft)),
|
|
668
1285
|
source: "rule"
|
|
669
1286
|
};
|
|
670
1287
|
}
|