@alan512/experienceengine 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.mcp.json +11 -11
  2. package/dist/adapters/codex/mcp-server.js +1 -1
  3. package/dist/analyzer/llm-learning-gate.d.ts +7 -0
  4. package/dist/analyzer/llm-learning-gate.js +76 -11
  5. package/dist/analyzer/llm-learning-gate.js.map +1 -1
  6. package/dist/cli/commands/doctor.d.ts +2 -1
  7. package/dist/cli/commands/doctor.js +23 -0
  8. package/dist/cli/commands/doctor.js.map +1 -1
  9. package/dist/cli/commands/inspect.js +9 -0
  10. package/dist/cli/commands/inspect.js.map +1 -1
  11. package/dist/cli/commands/status.js +16 -0
  12. package/dist/cli/commands/status.js.map +1 -1
  13. package/dist/cli/index.js +0 -0
  14. package/dist/controller/injection-renderer.d.ts +7 -2
  15. package/dist/controller/injection-renderer.js +50 -19
  16. package/dist/controller/injection-renderer.js.map +1 -1
  17. package/dist/controller/injection-scorecard.js +3 -0
  18. package/dist/controller/injection-scorecard.js.map +1 -1
  19. package/dist/controller/intervention-controller.js +8 -2
  20. package/dist/controller/intervention-controller.js.map +1 -1
  21. package/dist/controller/skip-reason.d.ts +12 -0
  22. package/dist/controller/skip-reason.js +82 -0
  23. package/dist/controller/skip-reason.js.map +1 -0
  24. package/dist/controller/skip-scorecard.d.ts +2 -0
  25. package/dist/controller/skip-scorecard.js +39 -0
  26. package/dist/controller/skip-scorecard.js.map +1 -0
  27. package/dist/install/claude-code-doctor.js +6 -4
  28. package/dist/install/claude-code-doctor.js.map +1 -1
  29. package/dist/install/claude-code-installer.js +2 -5
  30. package/dist/install/claude-code-installer.js.map +1 -1
  31. package/dist/install/claude-runtime-target.js +7 -1
  32. package/dist/install/claude-runtime-target.js.map +1 -1
  33. package/dist/install/openclaw-installer.js +5 -9
  34. package/dist/install/openclaw-installer.js.map +1 -1
  35. package/dist/interaction/service.d.ts +23 -0
  36. package/dist/interaction/service.js +85 -0
  37. package/dist/interaction/service.js.map +1 -1
  38. package/dist/plugin/openclaw-plugin.d.ts +1 -1
  39. package/dist/runtime/learning-candidate-factory.d.ts +3 -0
  40. package/dist/runtime/learning-candidate-factory.js +126 -0
  41. package/dist/runtime/learning-candidate-factory.js.map +1 -0
  42. package/dist/runtime/learning-pipeline-service.d.ts +24 -0
  43. package/dist/runtime/learning-pipeline-service.js +78 -0
  44. package/dist/runtime/learning-pipeline-service.js.map +1 -0
  45. package/dist/runtime/prompt-service.d.ts +3 -3
  46. package/dist/runtime/prompt-service.js +39 -34
  47. package/dist/runtime/prompt-service.js.map +1 -1
  48. package/dist/runtime/service.d.ts +5 -5
  49. package/dist/runtime/service.js +70 -306
  50. package/dist/runtime/service.js.map +1 -1
  51. package/dist/runtime/task-finalization-service.d.ts +36 -0
  52. package/dist/runtime/task-finalization-service.js +97 -0
  53. package/dist/runtime/task-finalization-service.js.map +1 -0
  54. package/dist/store/sqlite/repositories/task-run-repo.d.ts +1 -0
  55. package/dist/store/sqlite/repositories/task-run-repo.js +6 -0
  56. package/dist/store/sqlite/repositories/task-run-repo.js.map +1 -1
  57. package/dist/types/domain.d.ts +7 -0
  58. package/docs/releases/v0.3.3.md +18 -0
  59. package/docs/releases/v0.3.4.md +22 -0
  60. package/openclaw.plugin.json +1 -1
  61. package/package.json +13 -12
@@ -2,6 +2,7 @@ import { buildInjectionScorecard } from "../controller/injection-scorecard.js";
2
2
  import { buildRetrievalContext } from "../controller/retrieval-context.js";
3
3
  import { decideIntervention } from "../controller/intervention-controller.js";
4
4
  import { renderInlineNotice } from "../controller/inline-notice.js";
5
+ import { buildSkipScorecard } from "../controller/skip-scorecard.js";
5
6
  import { buildExperienceInput } from "../input/input-adapter.js";
6
7
  import { resolveScope } from "../input/scope-resolver.js";
7
8
  import { evaluateRepoPolicy } from "../experience-management/repo-policy.js";
@@ -59,31 +60,6 @@ const resolveEpisodeId = (session, sessionId, input) => {
59
60
  session.episodeId ??= stableId("episode", `${sessionId}:${input.scope_id}:${input.task_summary}`);
60
61
  return session.episodeId;
61
62
  };
62
- const buildRecordOnlyDiagnosticScorecard = (input, sessionId, diagnostics) => ({
63
- sessionId,
64
- scopeId: input.scope_id,
65
- taskType: input.task_type === "unknown" ? "general" : input.task_type,
66
- taskSummary: input.task_summary,
67
- mode: "skip",
68
- interventionStrength: "diagnostic_hint",
69
- riskLevel: "high",
70
- recommendation: "Record-only diagnostic candidate matched; keep it out of prompt text until the live gate clears.",
71
- reasons: ["A same-scope shadow candidate matched this task but was not delivered."],
72
- topCandidates: diagnostics.topCandidates,
73
- topCandidateScore: diagnostics.topCandidateScore,
74
- scoreMargin: diagnostics.scoreMargin,
75
- fastPathApplied: diagnostics.fastPathApplied,
76
- queryRewriteApplied: diagnostics.queryRewriteApplied,
77
- gateReason: diagnostics.gateReason,
78
- decisionReason: diagnostics.decisionReason,
79
- confidence: diagnostics.confidence,
80
- budgetClass: diagnostics.budgetClass,
81
- selectedCandidateIds: [],
82
- recordOnlyDiagnosticCandidateIds: diagnostics.recordOnlyDiagnosticCandidateIds,
83
- rejectedCandidates: diagnostics.rejectedCandidates,
84
- nodes: [],
85
- createdAt: nowIso()
86
- });
87
63
  export class ExperiencePromptRuntimeService {
88
64
  config;
89
65
  db;
@@ -127,21 +103,42 @@ export class ExperiencePromptRuntimeService {
127
103
  const existingScope = this.scopeRepo.getById(resolvedScope.scope_id);
128
104
  if (existingScope?.is_disabled) {
129
105
  session.injectedNodeIds = [];
130
- session.lastInjectionEvent = undefined;
131
106
  session.context = {
132
107
  ...session.context,
133
108
  injectedNodeIds: []
134
109
  };
110
+ const disabledInput = {
111
+ ...input,
112
+ scope_id: existingScope.scope_id,
113
+ injected_node_ids: []
114
+ };
115
+ const scorecard = buildSkipScorecard(disabledInput, sessionId, undefined, true);
116
+ const injectionEvent = {
117
+ injection_id: createId("decision"),
118
+ episode_id: resolveEpisodeId(session, sessionId, disabledInput),
119
+ session_id: sessionId,
120
+ scope_id: disabledInput.scope_id,
121
+ task_type: disabledInput.task_type === "unknown" ? "general" : disabledInput.task_type,
122
+ task_summary: disabledInput.task_summary,
123
+ mode: "skip",
124
+ delivery_mode: "live",
125
+ delivered: false,
126
+ injected_node_ids: [],
127
+ injection_count: 0,
128
+ scorecard,
129
+ was_successful: null,
130
+ harm_observed: null,
131
+ created_at: nowIso()
132
+ };
133
+ this.injectionRepo.upsert(injectionEvent);
134
+ session.lastInjectionEvent = injectionEvent;
135
135
  return {
136
136
  mode: "skip",
137
137
  text: undefined,
138
138
  notice: undefined,
139
+ scorecard,
139
140
  retrievalContext,
140
- input: {
141
- ...input,
142
- scope_id: existingScope.scope_id,
143
- injected_node_ids: []
144
- }
141
+ input: disabledInput
145
142
  };
146
143
  }
147
144
  const stats = input.task_type !== "unknown" ? this.statsRepo.get(input.scope_id, input.task_type) : undefined;
@@ -168,9 +165,17 @@ export class ExperiencePromptRuntimeService {
168
165
  };
169
166
  const scorecard = decision.mode !== "skip"
170
167
  ? buildInjectionScorecard(input, decision.mode, decision.selected, sessionId, decision.diagnostics)
171
- : decision.diagnostics?.recordOnlyDiagnosticCandidateIds?.length
172
- ? buildRecordOnlyDiagnosticScorecard(input, sessionId, decision.diagnostics)
173
- : undefined;
168
+ : buildSkipScorecard(input, sessionId, decision.diagnostics);
169
+ if (scorecard && decision.mode !== "skip" && !delivery.delivered) {
170
+ if (delivery.deliveryMode === "holdout") {
171
+ scorecard.skipReasonCode = "holdout_suppressed";
172
+ scorecard.skipReasonExplanation = "ExperienceEngine found a usable match but withheld it for holdout evaluation.";
173
+ }
174
+ else {
175
+ scorecard.skipReasonCode = "shadow_suppressed";
176
+ scorecard.skipReasonExplanation = "ExperienceEngine found a usable match but shadow mode suppressed prompt delivery.";
177
+ }
178
+ }
174
179
  const injectionEvent = {
175
180
  injection_id: createId(decision.mode === "skip" ? "decision" : "inject"),
176
181
  episode_id: episodeId,
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-service.js","sourceRoot":"","sources":["../../src/runtime/prompt-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prompt-service.js","sourceRoot":"","sources":["../../src/runtime/prompt-service.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { type HybridRouteDecision, type HybridRouteSignals } from "../hybrid/router.js";
2
- import type { EvaluationMode, ExperienceInput, InjectionScorecard, ToolEvent } from "../types/domain.js";
2
+ import type { EvaluationMode, ExperienceInput, ToolEvent } from "../types/domain.js";
3
3
  import type { ExperiencePlugin, HostPromptContext, HostToolResult, OpenClawLogger } from "../types/plugin.js";
4
4
  import type { ExperienceEngineConfig } from "../config/config-schema.js";
5
5
  import { RuntimeCaptureWriter } from "../plugin/runtime-capture.js";
@@ -35,6 +35,8 @@ export declare class ExperienceRuntimeService implements ExperiencePlugin {
35
35
  private readonly repoPolicyRepo;
36
36
  private readonly hybridReviewArtifactRepo;
37
37
  private readonly hybridTraceRepo;
38
+ private readonly learningPipeline;
39
+ private readonly taskFinalization;
38
40
  private readonly runtimeOptions;
39
41
  private readonly backgroundLearningEnabled;
40
42
  private readonly hybridPosttaskEnabled;
@@ -50,8 +52,6 @@ export declare class ExperienceRuntimeService implements ExperiencePlugin {
50
52
  private resolveConservativeCrossScopeCandidates;
51
53
  private resolveDiagnosticCandidates;
52
54
  recoverToolEvents(sessionId: string, payload: unknown): void;
53
- private buildFinalizedInput;
54
- private persistFinalizedInput;
55
55
  private trackLearningTask;
56
56
  waitForBackgroundLearning(): Promise<void>;
57
57
  private getLearningGate;
@@ -69,6 +69,7 @@ export declare class ExperienceRuntimeService implements ExperiencePlugin {
69
69
  mode: "skip";
70
70
  text: undefined;
71
71
  notice: undefined;
72
+ scorecard: import("../types/domain.js").InjectionScorecard;
72
73
  retrievalContext: import("../types/domain.js").RetrievalContext;
73
74
  input: {
74
75
  scope_id: string;
@@ -79,14 +80,13 @@ export declare class ExperienceRuntimeService implements ExperiencePlugin {
79
80
  outcome_signal: import("../types/domain.js").OutcomeSignal;
80
81
  context_summary?: string;
81
82
  };
82
- scorecard?: undefined;
83
83
  deliveryMode?: undefined;
84
84
  delivered?: undefined;
85
85
  } | {
86
86
  mode: import("../types/domain.js").InjectionMode;
87
87
  text: string | undefined;
88
88
  notice: string | undefined;
89
- scorecard: InjectionScorecard | undefined;
89
+ scorecard: import("../types/domain.js").InjectionScorecard | undefined;
90
90
  deliveryMode: EvaluationMode | undefined;
91
91
  delivered: boolean | undefined;
92
92
  retrievalContext: import("../types/domain.js").RetrievalContext;
@@ -3,12 +3,12 @@ import { buildInjectionScorecard } from "../controller/injection-scorecard.js";
3
3
  import { classifyFailureAttributionReason } from "../feedback/automatic-attribution.js";
4
4
  import { applyFeedback } from "../feedback/feedback-manager.js";
5
5
  import { detectHarm } from "../feedback/harm-detector.js";
6
- import { createEmptyStats, updateStats } from "../feedback/stats-updater.js";
7
6
  import { buildExperienceInput } from "../input/input-adapter.js";
8
7
  import { buildRetrievalContext } from "../controller/retrieval-context.js";
9
8
  import { resolveScope } from "../input/scope-resolver.js";
10
9
  import { decideIntervention } from "../controller/intervention-controller.js";
11
10
  import { renderInlineNotice } from "../controller/inline-notice.js";
11
+ import { buildSkipScorecard } from "../controller/skip-scorecard.js";
12
12
  import { applyGovernedNodeFeedback, deriveNodeOriginProfileForNode } from "../experience-management/node-lifecycle-governance.js";
13
13
  import { evaluateRepoPolicy } from "../experience-management/repo-policy.js";
14
14
  import { resolveHybridRolloutState } from "../hybrid/rollout.js";
@@ -33,191 +33,17 @@ import { RuntimeCaptureWriter } from "../plugin/runtime-capture.js";
33
33
  import { normalizeToolResult } from "../plugin/hooks/tool-result-persist.js";
34
34
  import { extractToolResultsFromPayload } from "../plugin/runtime-helpers.js";
35
35
  import { HybridReviewArtifactRepository } from "../store/sqlite/repositories/hybrid-review-artifact-repo.js";
36
+ import { LearningPipelineService } from "./learning-pipeline-service.js";
37
+ import { mergeContext, TaskFinalizationService } from "./task-finalization-service.js";
36
38
  const loadLlmLearningGate = async () => import("../analyzer/llm-learning-gate.js");
37
39
  const loadDistillationQueueWorker = async () => import("../distillation/queue-worker.js");
38
40
  const loadHybridWorkerClientModule = async () => import("../hybrid/worker-client.js");
39
41
  const loadHybridCapsuleBuilder = async () => import("../hybrid/capsule-builder.js");
40
42
  const loadHybridPostmortemProviderClient = async () => import("../hybrid/postmortem-provider-client.js");
41
- const toEvidence = (input) => input.tool_events.map((event) => [event.tool_name, event.status, event.error_signature ?? event.output_summary]
42
- .filter(Boolean)
43
- .join(": "));
44
- const toInputRecord = (input, sessionId, episodeId) => ({
45
- record_id: createId("input"),
46
- episode_id: episodeId,
47
- scope_id: input.scope_id,
48
- session_id: sessionId,
49
- task_type: input.task_type,
50
- task_summary: input.task_summary,
51
- outcome_signal: input.outcome_signal,
52
- context_summary: input.context_summary,
53
- evidence: toEvidence(input),
54
- injected_node_ids: input.injected_node_ids,
55
- created_at: nowIso()
56
- });
57
- const toTaskRun = (input, sessionId, context, episodeId) => {
58
- const timestamp = nowIso();
59
- const signals = buildCandidateSignals(input);
60
- return {
61
- id: stableId("taskrun", `${sessionId}:${input.task_summary}:${timestamp}`),
62
- episode_id: episodeId,
63
- host: context.host ?? "openclaw",
64
- scope_id: input.scope_id,
65
- session_id: sessionId,
66
- task_type: input.task_type,
67
- task_summary: input.task_summary,
68
- prompt_excerpt: context.userMessage,
69
- context_summary: input.context_summary,
70
- started_at: timestamp,
71
- ended_at: timestamp,
72
- final_status: input.outcome_signal === "success" ? "success" : input.outcome_signal === "failure" ? "failure" : "unknown",
73
- failure_signature: signals.failure_signature,
74
- learning_status: undefined,
75
- learning_reason: undefined,
76
- created_at: timestamp,
77
- updated_at: timestamp
78
- };
79
- };
80
- const toOutcomeRecord = (taskRun, input, episodeId) => ({
81
- id: createId("outcome"),
82
- episode_id: episodeId,
83
- task_run_id: taskRun.id,
84
- outcome_signal: input.outcome_signal,
85
- failure_signature: taskRun.failure_signature,
86
- summary: input.task_summary,
87
- created_at: nowIso()
88
- });
89
- const buildCandidateSourceSignal = (input) => {
90
- const signals = buildCandidateSignals(input);
91
- return {
92
- task_summary: input.task_summary,
93
- context_summary: input.context_summary,
94
- outcome_signal: input.outcome_signal,
95
- tool_events: input.tool_events,
96
- evidence: toEvidence(input),
97
- failure_signature: signals.failure_signature,
98
- retry_count: signals.retry_count,
99
- correction_signals: signals.correction_signals,
100
- directional_correction: signals.directional_correction,
101
- evidence_driven_reversal: signals.evidence_driven_reversal,
102
- tool_event_summary: signals.tool_event_summary
103
- };
104
- };
105
43
  const resolveEpisodeId = (session, sessionId, input) => {
106
44
  session.episodeId ??= stableId("episode", `${sessionId}:${input.scope_id}:${input.task_summary}`);
107
45
  return session.episodeId;
108
46
  };
109
- const mergeDirectionalCorrectionIntoSourceSignal = (sourceSignal, draft) => {
110
- const directionalCorrection = sourceSignal.directional_correction;
111
- if (!directionalCorrection) {
112
- return sourceSignal;
113
- }
114
- const semanticDetected = Boolean(draft.experience_kind === "expectation_correction" &&
115
- draft.correction_category &&
116
- draft.deviation_pattern &&
117
- draft.corrected_constraint);
118
- if (!semanticDetected) {
119
- return sourceSignal;
120
- }
121
- return {
122
- ...sourceSignal,
123
- directional_correction: {
124
- ...directionalCorrection,
125
- semantic_detected: true,
126
- correction_category: draft.correction_category,
127
- deviation_pattern: draft.deviation_pattern,
128
- corrected_constraint: draft.corrected_constraint
129
- }
130
- };
131
- };
132
- const mergeEvidenceDrivenReversalIntoSourceSignal = (sourceSignal, draft) => {
133
- const reversal = sourceSignal.evidence_driven_reversal;
134
- if (!reversal) {
135
- return sourceSignal;
136
- }
137
- const semanticDetected = Boolean(draft.experience_kind === "expectation_correction" &&
138
- draft.correction_category &&
139
- draft.deviation_pattern &&
140
- draft.corrected_constraint);
141
- if (!semanticDetected) {
142
- return sourceSignal;
143
- }
144
- return {
145
- ...sourceSignal,
146
- evidence_driven_reversal: {
147
- ...reversal,
148
- semantic_detected: true,
149
- correction_category: draft.correction_category,
150
- deviation_pattern: draft.deviation_pattern,
151
- corrected_constraint: draft.corrected_constraint
152
- }
153
- };
154
- };
155
- const summarizeRawCandidate = (sourceSignal) => {
156
- const fragments = [...sourceSignal.tool_event_summary];
157
- if (sourceSignal.failure_signature) {
158
- fragments.unshift(`failure signature: ${sourceSignal.failure_signature}`);
159
- }
160
- return fragments.slice(0, 3).join(" | ");
161
- };
162
- const resolveCandidateKind = (input, sourceSignal) => {
163
- if (input.outcome_signal === "success") {
164
- return "successful_fix";
165
- }
166
- if (sourceSignal.retry_count > 1) {
167
- return "retry_pattern";
168
- }
169
- if (sourceSignal.correction_signals.length > 0) {
170
- return "correction";
171
- }
172
- return "failure";
173
- };
174
- const draftToCandidate = (draft, input, originRecordId, taskRunId, directionalCorrectionSignal, evidenceDrivenReversalSignal) => {
175
- const timestamp = nowIso();
176
- const baseSourceSignal = buildCandidateSourceSignal(input);
177
- const sourceSignal = mergeEvidenceDrivenReversalIntoSourceSignal(mergeDirectionalCorrectionIntoSourceSignal({
178
- ...baseSourceSignal,
179
- directional_correction: directionalCorrectionSignal ?? baseSourceSignal.directional_correction,
180
- evidence_driven_reversal: evidenceDrivenReversalSignal ?? baseSourceSignal.evidence_driven_reversal
181
- }, draft), draft);
182
- const candidateId = stableId("candidate", [draft.scope_id, draft.task_type, draft.node_type, draft.compact_hint, originRecordId].join(":"));
183
- return {
184
- id: candidateId,
185
- task_run_id: taskRunId ?? originRecordId,
186
- candidate_kind: resolveCandidateKind(input, sourceSignal),
187
- ...draft,
188
- source_record_id: originRecordId,
189
- source_context_summary: input.context_summary,
190
- source_outcome_signal: input.outcome_signal,
191
- raw_summary: summarizeRawCandidate(sourceSignal),
192
- failure_signature: sourceSignal.failure_signature,
193
- source_signal: sourceSignal,
194
- lifecycle_state: "pending",
195
- retry_count: 0,
196
- created_at: timestamp,
197
- updated_at: timestamp
198
- };
199
- };
200
- const candidateToInitialJob = (candidate, extractorProfile) => {
201
- const timestamp = nowIso();
202
- return {
203
- id: stableId("distill", candidate.id),
204
- candidate_id: candidate.id,
205
- status: "pending",
206
- extractor_profile: extractorProfile,
207
- retry_count: candidate.retry_count,
208
- created_at: timestamp,
209
- updated_at: timestamp
210
- };
211
- };
212
- const mergeContext = (existing, incoming) => ({
213
- host: incoming.host ?? existing?.host,
214
- sessionId: incoming.sessionId ?? existing?.sessionId,
215
- cwd: incoming.cwd ?? existing?.cwd,
216
- userMessage: incoming.userMessage || existing?.userMessage || "",
217
- taskSummary: incoming.taskSummary ?? existing?.taskSummary,
218
- contextSummary: incoming.contextSummary ?? existing?.contextSummary,
219
- injectedNodeIds: incoming.injectedNodeIds ?? existing?.injectedNodeIds
220
- });
221
47
  const buildToolEventKey = (toolEvent, toolCallId) => toolCallId ??
222
48
  [
223
49
  toolEvent.tool_name,
@@ -259,31 +85,6 @@ const resolveDeliveryMode = (evaluationMode, holdoutRate, sessionId, taskSummary
259
85
  delivered: true
260
86
  };
261
87
  };
262
- const buildRecordOnlyDiagnosticScorecard = (input, sessionId, diagnostics) => ({
263
- sessionId,
264
- scopeId: input.scope_id,
265
- taskType: input.task_type === "unknown" ? "general" : input.task_type,
266
- taskSummary: input.task_summary,
267
- mode: "skip",
268
- interventionStrength: "diagnostic_hint",
269
- riskLevel: "high",
270
- recommendation: "Record-only diagnostic candidate matched; keep it out of prompt text until the live gate clears.",
271
- reasons: ["A same-scope shadow candidate matched this task but was not delivered."],
272
- topCandidates: diagnostics.topCandidates,
273
- topCandidateScore: diagnostics.topCandidateScore,
274
- scoreMargin: diagnostics.scoreMargin,
275
- fastPathApplied: diagnostics.fastPathApplied,
276
- queryRewriteApplied: diagnostics.queryRewriteApplied,
277
- gateReason: diagnostics.gateReason,
278
- decisionReason: diagnostics.decisionReason,
279
- confidence: diagnostics.confidence,
280
- budgetClass: diagnostics.budgetClass,
281
- selectedCandidateIds: [],
282
- recordOnlyDiagnosticCandidateIds: diagnostics.recordOnlyDiagnosticCandidateIds,
283
- rejectedCandidates: diagnostics.rejectedCandidates,
284
- nodes: [],
285
- createdAt: nowIso()
286
- });
287
88
  const HYBRID_LIGHTWEIGHT_PATTERN = /\b(wording-only|wording only|copy-only|copy only|copy pass|inline notice wording|expression-layer refinement)\b/i;
288
89
  const isLightweightHybridExcludedTask = (input) => HYBRID_LIGHTWEIGHT_PATTERN.test(`${input.task_summary} ${input.context_summary ?? ""}`);
289
90
  export const decidePosttaskHybridRoute = (config, input, signals, rolloutKey = input.task_summary) => {
@@ -321,6 +122,8 @@ export class ExperienceRuntimeService {
321
122
  repoPolicyRepo;
322
123
  hybridReviewArtifactRepo;
323
124
  hybridTraceRepo;
125
+ learningPipeline;
126
+ taskFinalization;
324
127
  runtimeOptions;
325
128
  backgroundLearningEnabled;
326
129
  hybridPosttaskEnabled;
@@ -351,6 +154,23 @@ export class ExperienceRuntimeService {
351
154
  this.repoPolicyRepo = new RepoPolicyRepository(this.db);
352
155
  this.hybridReviewArtifactRepo = new HybridReviewArtifactRepository(this.db);
353
156
  this.hybridTraceRepo = new HybridInvocationTraceRepository(this.db);
157
+ this.learningPipeline = new LearningPipelineService({
158
+ config: this.config,
159
+ db: this.db,
160
+ candidateRepo: this.candidateRepo,
161
+ jobRepo: this.jobRepo,
162
+ taskRunRepo: this.taskRunRepo,
163
+ logger: this.logger,
164
+ getLearningGate: () => this.getLearningGate(),
165
+ getDistillationWorker: () => this.getDistillationWorker()
166
+ });
167
+ this.taskFinalization = new TaskFinalizationService({
168
+ scopeRepo: this.scopeRepo,
169
+ inputRepo: this.inputRepo,
170
+ taskRunRepo: this.taskRunRepo,
171
+ outcomeRepo: this.outcomeRepo,
172
+ statsRepo: this.statsRepo
173
+ });
354
174
  this.captureWriter = new RuntimeCaptureWriter(config, this.logger);
355
175
  }
356
176
  getSession(sessionId) {
@@ -397,30 +217,6 @@ export class ExperienceRuntimeService {
397
217
  }
398
218
  }
399
219
  }
400
- buildFinalizedInput(context, session) {
401
- const mergedContext = mergeContext(session.context, context);
402
- const injectedNodeIds = session.injectedNodeIds.length > 0 ? session.injectedNodeIds : mergedContext.injectedNodeIds ?? [];
403
- const input = buildExperienceInput({
404
- ...mergedContext,
405
- injectedNodeIds
406
- }, session.toolEvents);
407
- return input;
408
- }
409
- persistFinalizedInput(input, sessionId, session, episodeId, cwd) {
410
- const resolvedScope = resolveScope(cwd ?? session.context?.cwd);
411
- const existingScope = this.scopeRepo.getById(resolvedScope.scope_id);
412
- this.scopeRepo.upsert({
413
- ...resolvedScope,
414
- is_disabled: existingScope?.is_disabled ?? resolvedScope.is_disabled
415
- });
416
- const record = toInputRecord(input, sessionId, episodeId);
417
- this.inputRepo.upsert(record);
418
- if (input.task_type !== "unknown") {
419
- const currentStats = this.statsRepo.get(input.scope_id, input.task_type) ?? createEmptyStats(input.scope_id, input.task_type);
420
- this.statsRepo.upsert(updateStats(currentStats, input.outcome_signal, input.injected_node_ids.length > 0));
421
- }
422
- return record;
423
- }
424
220
  trackLearningTask(task) {
425
221
  const tracked = task
426
222
  .catch((error) => {
@@ -661,72 +457,7 @@ export class ExperienceRuntimeService {
661
457
  }
662
458
  }
663
459
  async persistCandidatesAsync(input, originRecordId, taskRunId, sessionId) {
664
- const learningGate = await this.getLearningGate();
665
- if (!learningGate) {
666
- if (taskRunId) {
667
- const taskRun = this.taskRunRepo.getById(taskRunId);
668
- if (taskRun) {
669
- this.taskRunRepo.upsert({
670
- ...taskRun,
671
- learning_status: "not_applicable",
672
- learning_reason: "background learning disabled",
673
- updated_at: nowIso()
674
- });
675
- }
676
- }
677
- return;
678
- }
679
- const result = await learningGate.generateCandidateDrafts(input);
680
- if (taskRunId) {
681
- const taskRun = this.taskRunRepo.getById(taskRunId);
682
- if (taskRun) {
683
- this.taskRunRepo.upsert({
684
- ...taskRun,
685
- learning_status: result.drafts.length
686
- ? "captured"
687
- : result.source === "disabled" && result.reason === "distillation disabled"
688
- ? "not_applicable"
689
- : "rejected",
690
- learning_reason: result.reason,
691
- updated_at: nowIso()
692
- });
693
- }
694
- }
695
- if (!result.drafts.length) {
696
- this.logger.debug?.("experienceengine.learning_skipped", {
697
- sessionId,
698
- taskType: input.task_type,
699
- reason: result.reason,
700
- source: result.source
701
- });
702
- return;
703
- }
704
- const persistedCandidates = result.drafts.map((draft) => draftToCandidate(draft, input, originRecordId, taskRunId, result.directionalCorrectionSignal, result.evidenceDrivenReversalSignal));
705
- withTransaction(this.db, () => {
706
- for (const candidate of persistedCandidates) {
707
- this.candidateRepo.upsert(candidate);
708
- this.jobRepo.upsert(candidateToInitialJob(candidate, this.config.distillerProfile));
709
- }
710
- });
711
- this.logger.info?.("experienceengine.learning_captured", {
712
- sessionId,
713
- taskType: input.task_type,
714
- candidateCount: persistedCandidates.length,
715
- source: result.source,
716
- reason: result.reason
717
- });
718
- if (this.config.distillationAutoDrain) {
719
- const distillationWorker = await this.getDistillationWorker();
720
- if (!distillationWorker) {
721
- return;
722
- }
723
- await distillationWorker.drain().catch((error) => {
724
- this.logger.error?.("experienceengine.distillation_drain_failed", {
725
- sessionId,
726
- error: error instanceof Error ? error.message : String(error)
727
- });
728
- });
729
- }
460
+ await this.learningPipeline.persistCandidatesAsync(input, originRecordId, taskRunId, sessionId);
730
461
  }
731
462
  updateInjectedNodes(input, attributionRecordId, taskRunId, injectionEvent, episodeId) {
732
463
  if (!input.injected_node_ids.length) {
@@ -894,11 +625,35 @@ export class ExperienceRuntimeService {
894
625
  const existingScope = this.scopeRepo.getById(resolvedScope.scope_id);
895
626
  if (existingScope?.is_disabled) {
896
627
  session.injectedNodeIds = [];
897
- session.lastInjectionEvent = undefined;
898
628
  session.context = {
899
629
  ...session.context,
900
630
  injectedNodeIds: []
901
631
  };
632
+ const disabledInput = {
633
+ ...input,
634
+ scope_id: existingScope.scope_id,
635
+ injected_node_ids: []
636
+ };
637
+ const scorecard = buildSkipScorecard(disabledInput, sessionId, undefined, true);
638
+ const injectionEvent = {
639
+ injection_id: createId("decision"),
640
+ episode_id: resolveEpisodeId(session, sessionId, disabledInput),
641
+ session_id: sessionId,
642
+ scope_id: disabledInput.scope_id,
643
+ task_type: disabledInput.task_type === "unknown" ? "general" : disabledInput.task_type,
644
+ task_summary: disabledInput.task_summary,
645
+ mode: "skip",
646
+ delivery_mode: "live",
647
+ delivered: false,
648
+ injected_node_ids: [],
649
+ injection_count: 0,
650
+ scorecard,
651
+ was_successful: null,
652
+ harm_observed: null,
653
+ created_at: nowIso()
654
+ };
655
+ this.injectionRepo.upsert(injectionEvent);
656
+ session.lastInjectionEvent = injectionEvent;
902
657
  this.logger.info?.("experienceengine.scope_disabled", {
903
658
  sessionId,
904
659
  scopeId: existingScope.scope_id
@@ -907,12 +662,9 @@ export class ExperienceRuntimeService {
907
662
  mode: "skip",
908
663
  text: undefined,
909
664
  notice: undefined,
665
+ scorecard,
910
666
  retrievalContext,
911
- input: {
912
- ...input,
913
- scope_id: existingScope.scope_id,
914
- injected_node_ids: []
915
- }
667
+ input: disabledInput
916
668
  };
917
669
  }
918
670
  const stats = input.task_type !== "unknown" ? this.statsRepo.get(input.scope_id, input.task_type) : undefined;
@@ -945,9 +697,17 @@ export class ExperienceRuntimeService {
945
697
  };
946
698
  const scorecard = decision.mode !== "skip"
947
699
  ? buildInjectionScorecard(input, decision.mode, decision.selected, sessionId, decision.diagnostics)
948
- : decision.diagnostics?.recordOnlyDiagnosticCandidateIds?.length
949
- ? buildRecordOnlyDiagnosticScorecard(input, sessionId, decision.diagnostics)
950
- : undefined;
700
+ : buildSkipScorecard(input, sessionId, decision.diagnostics);
701
+ if (scorecard && decision.mode !== "skip" && !delivery.delivered) {
702
+ if (delivery.deliveryMode === "holdout") {
703
+ scorecard.skipReasonCode = "holdout_suppressed";
704
+ scorecard.skipReasonExplanation = "ExperienceEngine found a usable match but withheld it for holdout evaluation.";
705
+ }
706
+ else {
707
+ scorecard.skipReasonCode = "shadow_suppressed";
708
+ scorecard.skipReasonExplanation = "ExperienceEngine found a usable match but shadow mode suppressed prompt delivery.";
709
+ }
710
+ }
951
711
  const injectionEvent = {
952
712
  injection_id: createId(decision.mode === "skip" ? "decision" : "inject"),
953
713
  episode_id: episodeId,
@@ -1009,14 +769,18 @@ export class ExperienceRuntimeService {
1009
769
  async finalizeTask(context) {
1010
770
  const sessionId = context.sessionId ?? "global";
1011
771
  const session = this.getSession(sessionId);
1012
- const input = this.buildFinalizedInput(context, session);
772
+ const input = this.taskFinalization.buildFinalizedInput(context, session);
1013
773
  let learningTaskContext;
1014
774
  withTransaction(this.db, () => {
1015
775
  const episodeId = resolveEpisodeId(session, sessionId, input);
1016
- const record = this.persistFinalizedInput(input, sessionId, session, episodeId, context.cwd);
1017
- const taskRun = toTaskRun(input, sessionId, context, episodeId);
1018
- this.taskRunRepo.upsert(taskRun);
1019
- this.outcomeRepo.upsert(toOutcomeRecord(taskRun, input, episodeId));
776
+ const { record, taskRun } = this.taskFinalization.persistFinalizedRun({
777
+ experienceInput: input,
778
+ sessionId,
779
+ session,
780
+ episodeId,
781
+ context,
782
+ cwd: context.cwd
783
+ });
1020
784
  const injectionEvent = session.lastInjectionEvent ?? this.injectionRepo.getLatestBySessionId(sessionId);
1021
785
  this.updateInjectedNodes(input, record.record_id, taskRun.id, injectionEvent, episodeId);
1022
786
  if (injectionEvent) {