create-principles-disciple 1.79.0 → 1.81.0
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/console/package.json +1 -0
- package/core/dist/runtime-v2/__tests__/admission-gate.test.js +6 -6
- package/core/dist/runtime-v2/__tests__/admission-gate.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +39 -0
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js +52 -0
- package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice.test.js +245 -1
- package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js +131 -1
- package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/fixtures/llm-e2e-config.d.ts.map +1 -1
- package/core/dist/runtime-v2/__tests__/fixtures/llm-e2e-config.js +4 -2
- package/core/dist/runtime-v2/__tests__/fixtures/llm-e2e-config.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/scribe-runner-vslice.test.js +425 -2
- package/core/dist/runtime-v2/__tests__/scribe-runner-vslice.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/telemetry-event.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/telemetry-event.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/telemetry-event.test.js +69 -0
- package/core/dist/runtime-v2/__tests__/telemetry-event.test.js.map +1 -0
- package/core/dist/runtime-v2/admission-gate.d.ts.map +1 -1
- package/core/dist/runtime-v2/admission-gate.js +0 -8
- package/core/dist/runtime-v2/admission-gate.js.map +1 -1
- package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.d.ts +15 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.js +685 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.js.map +1 -0
- package/core/dist/runtime-v2/config/index.d.ts +14 -0
- package/core/dist/runtime-v2/config/index.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/index.js +16 -0
- package/core/dist/runtime-v2/config/index.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.d.ts +14 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.js +74 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-effective.d.ts +14 -0
- package/core/dist/runtime-v2/config/pd-config-effective.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-effective.js +118 -0
- package/core/dist/runtime-v2/config/pd-config-effective.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.d.ts +35 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.js +99 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.d.ts +22 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.js +179 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-types.d.ts +124 -0
- package/core/dist/runtime-v2/config/pd-config-types.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-types.js +35 -0
- package/core/dist/runtime-v2/config/pd-config-types.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-validate.d.ts +16 -0
- package/core/dist/runtime-v2/config/pd-config-validate.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-validate.js +443 -0
- package/core/dist/runtime-v2/config/pd-config-validate.js.map +1 -0
- package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js +10 -10
- package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js.map +1 -1
- package/core/dist/runtime-v2/feedback/index.d.ts +1 -1
- package/core/dist/runtime-v2/feedback/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/feedback/index.js +1 -1
- package/core/dist/runtime-v2/feedback/index.js.map +1 -1
- package/core/dist/runtime-v2/feedback/redact-sensitive.d.ts +2 -0
- package/core/dist/runtime-v2/feedback/redact-sensitive.d.ts.map +1 -1
- package/core/dist/runtime-v2/feedback/redact-sensitive.js +32 -3
- package/core/dist/runtime-v2/feedback/redact-sensitive.js.map +1 -1
- package/core/dist/runtime-v2/index.d.ts +5 -1
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +9 -1
- package/core/dist/runtime-v2/index.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/peer-runner-lineage-injection.test.d.ts +2 -0
- package/core/dist/runtime-v2/internalization/__tests__/peer-runner-lineage-injection.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/peer-runner-lineage-injection.test.js +95 -0
- package/core/dist/runtime-v2/internalization/__tests__/peer-runner-lineage-injection.test.js.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.d.ts +2 -0
- package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.js +398 -0
- package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.js.map +1 -0
- package/core/dist/runtime-v2/internalization/artificer-output.d.ts +3 -2
- package/core/dist/runtime-v2/internalization/artificer-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-output.js +40 -31
- package/core/dist/runtime-v2/internalization/artificer-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.d.ts +59 -38
- package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.js +122 -394
- package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/dreamer-output.d.ts +4 -3
- package/core/dist/runtime-v2/internalization/dreamer-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/dreamer-output.js +11 -9
- package/core/dist/runtime-v2/internalization/dreamer-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/dreamer-runner.d.ts +31 -92
- package/core/dist/runtime-v2/internalization/dreamer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/dreamer-runner.js +80 -492
- package/core/dist/runtime-v2/internalization/dreamer-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-output.d.ts +2 -2
- package/core/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-output.js +29 -23
- package/core/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts +74 -48
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.js +165 -443
- package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/peer-runner-contracts.d.ts +14 -0
- package/core/dist/runtime-v2/internalization/peer-runner-contracts.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/peer-runner-contracts.js +21 -0
- package/core/dist/runtime-v2/internalization/peer-runner-contracts.js.map +1 -1
- package/core/dist/runtime-v2/internalization/philosopher-output.d.ts +8 -2
- package/core/dist/runtime-v2/internalization/philosopher-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/philosopher-output.js +16 -11
- package/core/dist/runtime-v2/internalization/philosopher-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/philosopher-runner.d.ts +36 -55
- package/core/dist/runtime-v2/internalization/philosopher-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/philosopher-runner.js +118 -400
- package/core/dist/runtime-v2/internalization/philosopher-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/rollout-reviewer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/rollout-reviewer-runner.js +3 -1
- package/core/dist/runtime-v2/internalization/rollout-reviewer-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-output.d.ts +8 -2
- package/core/dist/runtime-v2/internalization/scribe-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-output.js +33 -17
- package/core/dist/runtime-v2/internalization/scribe-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-runner.d.ts +56 -49
- package/core/dist/runtime-v2/internalization/scribe-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-runner.js +117 -397
- package/core/dist/runtime-v2/internalization/scribe-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/trainer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/trainer-runner.js +3 -1
- package/core/dist/runtime-v2/internalization/trainer-runner.js.map +1 -1
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.d.ts +2 -0
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.js +379 -0
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.js.map +1 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.d.ts +122 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.d.ts.map +1 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.js +528 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.js.map +1 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.d.ts +107 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.d.ts.map +1 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.js +13 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.js.map +1 -0
- package/core/dist/telemetry-event.d.ts +2 -2
- package/core/dist/telemetry-event.d.ts.map +1 -1
- package/core/dist/telemetry-event.js +89 -0
- package/core/dist/telemetry-event.js.map +1 -1
- package/dist/installer.d.ts +1 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +39 -10
- package/dist/installer.js.map +1 -1
- package/dist/mvp-config.d.ts +33 -0
- package/dist/mvp-config.d.ts.map +1 -1
- package/dist/mvp-config.js +174 -0
- package/dist/mvp-config.js.map +1 -1
- package/package.json +3 -3
- package/pd-cli/dist/commands/config-doctor.d.ts +17 -0
- package/pd-cli/dist/commands/config-doctor.d.ts.map +1 -0
- package/pd-cli/dist/commands/config-doctor.js +143 -0
- package/pd-cli/dist/commands/config-doctor.js.map +1 -0
- package/pd-cli/dist/commands/console.d.ts +18 -0
- package/pd-cli/dist/commands/console.d.ts.map +1 -1
- package/pd-cli/dist/commands/console.js +439 -0
- package/pd-cli/dist/commands/console.js.map +1 -1
- package/pd-cli/dist/commands/runtime-features.d.ts +23 -8
- package/pd-cli/dist/commands/runtime-features.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-features.js +72 -31
- package/pd-cli/dist/commands/runtime-features.js.map +1 -1
- package/pd-cli/dist/index.d.ts +1 -1
- package/pd-cli/dist/index.js +83 -31
- package/pd-cli/dist/index.js.map +1 -1
- package/pd-cli/dist/services/config-doctor.d.ts +102 -0
- package/pd-cli/dist/services/config-doctor.d.ts.map +1 -0
- package/pd-cli/dist/services/config-doctor.js +426 -0
- package/pd-cli/dist/services/config-doctor.js.map +1 -0
- package/pd-cli/dist/services/console-launcher.d.ts +110 -0
- package/pd-cli/dist/services/console-launcher.d.ts.map +1 -0
- package/pd-cli/dist/services/console-launcher.js +282 -0
- package/pd-cli/dist/services/console-launcher.js.map +1 -0
- package/pd-cli/dist/services/pd-config-loader.d.ts +64 -0
- package/pd-cli/dist/services/pd-config-loader.d.ts.map +1 -0
- package/pd-cli/dist/services/pd-config-loader.js +156 -0
- package/pd-cli/dist/services/pd-config-loader.js.map +1 -0
- package/pd-cli/package.json +3 -1
- package/plugin/dist/core/event-log.d.ts +10 -0
- package/plugin/dist/core/event-log.js +85 -1
- package/plugin/dist/core/pd-config-loader.d.ts +96 -0
- package/plugin/dist/core/pd-config-loader.js +307 -0
- package/plugin/dist/core/runtime-v2-prompt-activation-reader.d.ts +4 -0
- package/plugin/dist/core/runtime-v2-prompt-activation-reader.js +12 -56
- package/plugin/dist/core/surface-guard.d.ts +12 -8
- package/plugin/dist/core/surface-guard.js +51 -2
- package/plugin/dist/hooks/gate.js +3 -0
- package/plugin/dist/hooks/prompt.js +4 -5
- package/plugin/dist/index.d.ts +4 -0
- package/plugin/dist/index.js +70 -94
- package/plugin/dist/service/correction-observer-service.d.ts +8 -0
- package/plugin/dist/service/correction-observer-service.js +48 -29
- package/plugin/dist/utils/workspace-resolver.d.ts +33 -1
- package/plugin/dist/utils/workspace-resolver.js +182 -3
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { PDRuntimeError } from '../error-categories.js';
|
|
1
|
+
import { PDRuntimeError, isPDErrorCategory } from '../error-categories.js';
|
|
2
2
|
import { hydratePITaskRecord } from './pitask-metadata.js';
|
|
3
|
-
import { RunnerPhase } from '../runner/runner-phase.js';
|
|
4
3
|
import { EvaluatorPromptBuilder } from './evaluator-prompt-builder.js';
|
|
5
|
-
|
|
4
|
+
import { injectRunnerLineageIfAbsent } from './peer-runner-contracts.js';
|
|
5
|
+
import { BasePeerRunner } from '../runner/base-peer-runner.js';
|
|
6
|
+
export const DEFAULT_EVALUATOR_RUNNER_OPTIONS = {
|
|
6
7
|
pollIntervalMs: 5_000,
|
|
7
8
|
timeoutMs: 300_000,
|
|
8
9
|
defaultMaxAttempts: 3,
|
|
@@ -18,118 +19,22 @@ export function resolveEvaluatorRunnerOptions(options) {
|
|
|
18
19
|
agentId: options.agentId ?? DEFAULT_EVALUATOR_RUNNER_OPTIONS.agentId,
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
]);
|
|
24
|
-
export class EvaluatorRunner {
|
|
25
|
-
phase = RunnerPhase.Idle;
|
|
26
|
-
resolvedOptions;
|
|
27
|
-
stateManager;
|
|
28
|
-
runtimeAdapter;
|
|
29
|
-
eventEmitter;
|
|
22
|
+
// ── EvaluatorRunner ───────────────────────────────────────────────────────────
|
|
23
|
+
export class EvaluatorRunner extends BasePeerRunner {
|
|
30
24
|
validator;
|
|
31
|
-
artifactStore;
|
|
32
25
|
constructor(deps, options) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
this.resolvedOptions = resolveEvaluatorRunnerOptions(options);
|
|
39
|
-
}
|
|
40
|
-
get currentPhase() {
|
|
41
|
-
return this.phase;
|
|
42
|
-
}
|
|
43
|
-
emitEvaluatorEvent(eventType, taskId, payload) {
|
|
44
|
-
this.eventEmitter.emitTelemetry({
|
|
45
|
-
eventType: eventType,
|
|
46
|
-
traceId: taskId,
|
|
47
|
-
timestamp: new Date().toISOString(),
|
|
48
|
-
sessionId: this.resolvedOptions.owner,
|
|
49
|
-
agentId: this.resolvedOptions.agentId,
|
|
50
|
-
payload,
|
|
26
|
+
super(deps, options, {
|
|
27
|
+
runnerName: 'evaluator',
|
|
28
|
+
expectedTaskKind: 'evaluator',
|
|
29
|
+
defaultAgentId: 'evaluator',
|
|
30
|
+
resultRefPrefix: 'evaluator',
|
|
51
31
|
});
|
|
32
|
+
this.validator = deps.validator;
|
|
52
33
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
leasedTask = await this.stateManager.acquireLease({
|
|
59
|
-
taskId,
|
|
60
|
-
owner: this.resolvedOptions.owner,
|
|
61
|
-
runtimeKind: this.resolvedOptions.runtimeKind,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
return await this.handleLeaseOrPhaseError(taskId, error);
|
|
66
|
-
}
|
|
67
|
-
if (leasedTask.taskKind !== 'evaluator') {
|
|
68
|
-
this.emitEvaluatorEvent('evaluator_wrong_task_kind', taskId, {
|
|
69
|
-
expectedKind: 'evaluator',
|
|
70
|
-
actualKind: leasedTask.taskKind,
|
|
71
|
-
});
|
|
72
|
-
return this.retryOrFail({
|
|
73
|
-
taskId,
|
|
74
|
-
task: leasedTask,
|
|
75
|
-
errorCategory: 'input_invalid',
|
|
76
|
-
failureReason: `Task kind must be 'evaluator', got '${leasedTask.taskKind}'`,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
this.emitEvaluatorEvent('evaluator_task_leased', taskId, {
|
|
80
|
-
taskKind: 'evaluator',
|
|
81
|
-
attemptCount: leasedTask.attemptCount,
|
|
82
|
-
});
|
|
83
|
-
try {
|
|
84
|
-
const storeRunId = await this.resolveStoreRunId(taskId);
|
|
85
|
-
this.phase = RunnerPhase.BuildingContext;
|
|
86
|
-
const { contextHash, artificerArtifact, sourceArtificerArtifactId } = await this.buildContext(taskId);
|
|
87
|
-
if (!artificerArtifact || !sourceArtificerArtifactId) {
|
|
88
|
-
return this.retryOrFail({
|
|
89
|
-
taskId,
|
|
90
|
-
task: leasedTask,
|
|
91
|
-
errorCategory: 'input_invalid',
|
|
92
|
-
failureReason: sourceArtificerArtifactId ? 'Artificer dependency artifact not found' : 'Artificer dependency artifact ID not resolved',
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
this.emitEvaluatorEvent('evaluator_context_built', taskId, { contextHash });
|
|
96
|
-
this.phase = RunnerPhase.Invoking;
|
|
97
|
-
const runHandle = await this.invokeRuntime({ taskId, contextHash, artificerArtifact, sourceArtificerArtifactId });
|
|
98
|
-
this.emitEvaluatorEvent('evaluator_run_started', taskId, {
|
|
99
|
-
runtimeKind: this.resolvedOptions.runtimeKind,
|
|
100
|
-
});
|
|
101
|
-
this.phase = RunnerPhase.Polling;
|
|
102
|
-
const finalStatus = await this.pollUntilTerminal(runHandle);
|
|
103
|
-
if (finalStatus.status !== 'succeeded') {
|
|
104
|
-
return await this.handleRuntimeFailure(taskId, leasedTask, finalStatus);
|
|
105
|
-
}
|
|
106
|
-
this.phase = RunnerPhase.FetchingOutput;
|
|
107
|
-
const output = await this.fetchAndParseOutput(runHandle.runId);
|
|
108
|
-
this.phase = RunnerPhase.Validating;
|
|
109
|
-
const validationResult = await this.validator.validate(output, taskId, sourceArtificerArtifactId ?? undefined);
|
|
110
|
-
if (!validationResult.valid) {
|
|
111
|
-
return await this.handleValidationError({
|
|
112
|
-
taskId,
|
|
113
|
-
task: leasedTask,
|
|
114
|
-
errors: validationResult.errors,
|
|
115
|
-
errorCategory: validationResult.errorCategory,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
this.emitEvaluatorEvent('evaluator_output_validated', taskId, {
|
|
119
|
-
evaluationDecision: output.evaluation.decision,
|
|
120
|
-
evaluationScore: output.evaluation.score,
|
|
121
|
-
});
|
|
122
|
-
return await this.succeedTask({
|
|
123
|
-
taskId,
|
|
124
|
-
runId: storeRunId,
|
|
125
|
-
output,
|
|
126
|
-
task: leasedTask,
|
|
127
|
-
contextHash,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
catch (error) {
|
|
131
|
-
return await this.handlePostLeaseError(taskId, leasedTask, error);
|
|
132
|
-
}
|
|
34
|
+
// ── Abstract implementations ────────────────────────────────────────────────
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
36
|
+
get permanentErrorCategories() {
|
|
37
|
+
return new Set(['storage_unavailable', 'workspace_invalid', 'capability_missing', 'cancelled', 'input_invalid', 'output_invalid']);
|
|
133
38
|
}
|
|
134
39
|
async buildContext(taskId) {
|
|
135
40
|
const task = await this.stateManager.getTask(taskId);
|
|
@@ -139,8 +44,8 @@ export class EvaluatorRunner {
|
|
|
139
44
|
const piTask = hydratePITaskRecord(task);
|
|
140
45
|
const deps = piTask?.dependencyTaskIds ?? [];
|
|
141
46
|
if (deps.length === 0) {
|
|
142
|
-
this.
|
|
143
|
-
|
|
47
|
+
this.emitEvent('no_dependencies', taskId, {});
|
|
48
|
+
throw new PDRuntimeError('input_invalid', 'Artificer dependency artifact ID not resolved');
|
|
144
49
|
}
|
|
145
50
|
for (const depId of deps) {
|
|
146
51
|
const depTask = await this.stateManager.getTask(depId);
|
|
@@ -149,7 +54,7 @@ export class EvaluatorRunner {
|
|
|
149
54
|
if (depTask.taskKind !== 'artificer')
|
|
150
55
|
continue;
|
|
151
56
|
if (depTask.status !== 'succeeded') {
|
|
152
|
-
this.
|
|
57
|
+
this.emitEvent('dependency_not_succeeded', taskId, {
|
|
153
58
|
depTaskId: depId,
|
|
154
59
|
depStatus: depTask.status,
|
|
155
60
|
});
|
|
@@ -161,170 +66,149 @@ export class EvaluatorRunner {
|
|
|
161
66
|
if (!firstArtifact)
|
|
162
67
|
continue;
|
|
163
68
|
const artifactRef = firstArtifact.artifactId;
|
|
164
|
-
this.
|
|
69
|
+
this.emitEvent('artificer_dep_selected', taskId, {
|
|
165
70
|
depTaskId: depId,
|
|
166
71
|
artifactId: firstArtifact.artifactId,
|
|
167
72
|
});
|
|
168
73
|
return {
|
|
169
|
-
contextHash:
|
|
74
|
+
contextHash: BasePeerRunner.hashContextRefs([artifactRef]),
|
|
170
75
|
artificerArtifact: firstArtifact.contentJson,
|
|
171
76
|
sourceArtificerArtifactId: firstArtifact.artifactId,
|
|
172
77
|
};
|
|
173
78
|
}
|
|
174
79
|
}
|
|
175
|
-
this.
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
static hashContextRefs(refs) {
|
|
179
|
-
if (refs.length === 0)
|
|
180
|
-
return 'empty';
|
|
181
|
-
const str = refs.join('|');
|
|
182
|
-
let hash = 0;
|
|
183
|
-
for (let i = 0; i < str.length; i++) {
|
|
184
|
-
hash = (Math.imul(31, hash) + str.charCodeAt(i)) | 0;
|
|
185
|
-
}
|
|
186
|
-
return `ctx-${Math.abs(hash).toString(16)}`;
|
|
187
|
-
}
|
|
188
|
-
async resolveStoreRunId(taskId) {
|
|
189
|
-
const runs = await this.stateManager.getRunsByTask(taskId);
|
|
190
|
-
const latestRun = runs[runs.length - 1];
|
|
191
|
-
if (!latestRun) {
|
|
192
|
-
throw new PDRuntimeError('execution_failed', `No run records found for task ${taskId} after lease acquisition`);
|
|
193
|
-
}
|
|
194
|
-
return latestRun.runId;
|
|
80
|
+
this.emitEvent('no_artificer_artifact', taskId, {});
|
|
81
|
+
throw new PDRuntimeError('input_invalid', 'Artificer dependency artifact not found');
|
|
195
82
|
}
|
|
196
|
-
async invokeRuntime(
|
|
83
|
+
async invokeRuntime(taskId, context) {
|
|
197
84
|
let parsedArtificerArtifact = null;
|
|
198
|
-
if (
|
|
85
|
+
if (context.artificerArtifact) {
|
|
199
86
|
try {
|
|
200
|
-
parsedArtificerArtifact = JSON.parse(
|
|
87
|
+
parsedArtificerArtifact = JSON.parse(context.artificerArtifact);
|
|
201
88
|
}
|
|
202
89
|
catch {
|
|
203
|
-
parsedArtificerArtifact =
|
|
90
|
+
parsedArtificerArtifact = context.artificerArtifact;
|
|
204
91
|
}
|
|
205
92
|
}
|
|
206
93
|
const builder = new EvaluatorPromptBuilder();
|
|
207
94
|
const { message } = builder.buildPrompt({
|
|
208
|
-
taskId
|
|
209
|
-
contextHash:
|
|
95
|
+
taskId,
|
|
96
|
+
contextHash: context.contextHash,
|
|
210
97
|
artificerArtifact: parsedArtificerArtifact,
|
|
211
|
-
sourceArtificerArtifactId:
|
|
98
|
+
sourceArtificerArtifactId: context.sourceArtificerArtifactId ?? '',
|
|
212
99
|
});
|
|
213
|
-
|
|
100
|
+
return this.runtimeAdapter.startRun({
|
|
214
101
|
agentSpec: { agentId: this.resolvedOptions.agentId, schemaVersion: 'v1' },
|
|
215
|
-
taskRef: { taskId
|
|
102
|
+
taskRef: { taskId },
|
|
216
103
|
inputPayload: message,
|
|
217
104
|
contextItems: [],
|
|
218
105
|
outputSchemaRef: 'evaluator-output-v1',
|
|
219
106
|
timeoutMs: this.resolvedOptions.timeoutMs,
|
|
220
|
-
};
|
|
221
|
-
return this.runtimeAdapter.startRun(startInput);
|
|
107
|
+
});
|
|
222
108
|
}
|
|
223
|
-
async
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
await this.runtimeAdapter.cancelRun(runHandle.runId);
|
|
243
|
-
}
|
|
244
|
-
catch (cancelErr) {
|
|
245
|
-
cancelFailed = true;
|
|
246
|
-
this.emitEvaluatorEvent('evaluator_cancel_run_failed', runHandle.runId, {
|
|
247
|
-
runId: runHandle.runId,
|
|
248
|
-
errorMessage: cancelErr instanceof Error ? cancelErr.message : String(cancelErr),
|
|
249
|
-
});
|
|
109
|
+
async validateOutput(output, taskId, context) {
|
|
110
|
+
const result = await this.validator.validate(output, taskId, context.sourceArtificerArtifactId ?? undefined);
|
|
111
|
+
// Trust-boundary: validator is an injected dependency returning `string | undefined`
|
|
112
|
+
// for errorCategory. We must not `as`-cast; validate at runtime (ERR-001, ERR-005).
|
|
113
|
+
const rawCategory = result.errorCategory;
|
|
114
|
+
let errorCategory;
|
|
115
|
+
if (rawCategory == null) {
|
|
116
|
+
errorCategory = undefined;
|
|
117
|
+
}
|
|
118
|
+
else if (isPDErrorCategory(rawCategory)) {
|
|
119
|
+
errorCategory = rawCategory;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Invalid errorCategory from validator — fail loud, do not pass through
|
|
123
|
+
return {
|
|
124
|
+
valid: false,
|
|
125
|
+
errors: [...result.errors, `invalid errorCategory: ${rawCategory}`],
|
|
126
|
+
errorCategory: 'output_invalid',
|
|
127
|
+
};
|
|
250
128
|
}
|
|
251
|
-
|
|
252
|
-
|
|
129
|
+
return {
|
|
130
|
+
valid: result.valid,
|
|
131
|
+
errors: result.errors,
|
|
132
|
+
errorCategory,
|
|
133
|
+
};
|
|
253
134
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
135
|
+
// eslint-disable-next-line @typescript-eslint/max-params
|
|
136
|
+
async succeedTask(taskId, runId, output, task, contextHash, context) {
|
|
137
|
+
// Lineage consistency: sourceArtificerArtifactId must match buildContext result (ERR-004).
|
|
138
|
+
if (context.sourceArtificerArtifactId && output.sourceArtificerArtifactId !== context.sourceArtificerArtifactId) {
|
|
139
|
+
throw new PDRuntimeError('output_invalid', `sourceArtificerArtifactId mismatch: expected ${context.sourceArtificerArtifactId}, got ${output.sourceArtificerArtifactId}`);
|
|
258
140
|
}
|
|
259
|
-
|
|
260
|
-
if (typeof payload !== 'object' || payload === null) {
|
|
261
|
-
throw new PDRuntimeError('output_invalid', `Output payload is not an object for run ${runId}`);
|
|
262
|
-
}
|
|
263
|
-
if (typeof payload.evaluation !== 'object' || payload.evaluation === null) {
|
|
264
|
-
throw new PDRuntimeError('output_invalid', `Output payload missing evaluation object for run ${runId}`);
|
|
265
|
-
}
|
|
266
|
-
return result.payload;
|
|
267
|
-
}
|
|
268
|
-
async succeedTask(ctx) {
|
|
141
|
+
// Store output before marking succeeded
|
|
269
142
|
try {
|
|
270
|
-
await this.stateManager.updateRunOutput(
|
|
143
|
+
await this.stateManager.updateRunOutput(runId, JSON.stringify(output));
|
|
271
144
|
}
|
|
272
145
|
catch (updateErr) {
|
|
273
|
-
this.
|
|
274
|
-
runId
|
|
146
|
+
this.emitEvent('update_output_failed', taskId, {
|
|
147
|
+
runId,
|
|
275
148
|
errorMessage: updateErr instanceof Error ? updateErr.message : String(updateErr),
|
|
276
149
|
});
|
|
277
150
|
throw updateErr;
|
|
278
151
|
}
|
|
279
|
-
|
|
280
|
-
const now = new Date().toISOString();
|
|
152
|
+
// Resolve lineage artifact IDs
|
|
281
153
|
let lineageArtifactIds = [];
|
|
154
|
+
let lineageHasRejected = false;
|
|
282
155
|
try {
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
156
|
+
const lineageResult = await this.resolveLineageArtifactIds(taskId);
|
|
157
|
+
lineageArtifactIds = lineageResult.ids;
|
|
158
|
+
lineageHasRejected = lineageResult.hasRejected;
|
|
159
|
+
}
|
|
160
|
+
catch (lineageErr) {
|
|
161
|
+
this.emitEvent('lineage_resolve_failed', taskId, {
|
|
162
|
+
runId,
|
|
163
|
+
errorMessage: lineageErr instanceof Error ? lineageErr.message : String(lineageErr),
|
|
164
|
+
});
|
|
293
165
|
}
|
|
294
|
-
|
|
166
|
+
if (lineageHasRejected) {
|
|
167
|
+
this.emitEvent('lineage_partial', taskId, {
|
|
168
|
+
runId,
|
|
169
|
+
resolvedCount: lineageArtifactIds.length,
|
|
170
|
+
warning: 'Some dependency artifact queries were rejected; lineage may be incomplete',
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
// Write PIArtifact via artifactStore (idempotent upsert)
|
|
174
|
+
const artifactId = `pi-art-${taskId}-${runId}`;
|
|
175
|
+
const now = new Date().toISOString();
|
|
295
176
|
try {
|
|
296
177
|
await this.artifactStore.upsertArtifact({
|
|
297
178
|
artifactId,
|
|
298
179
|
artifactKind: 'principle',
|
|
299
|
-
sourceTaskId:
|
|
180
|
+
sourceTaskId: taskId,
|
|
300
181
|
lineageArtifactIds,
|
|
301
182
|
validationStatus: 'pending',
|
|
302
|
-
contentJson: JSON.stringify(
|
|
183
|
+
contentJson: JSON.stringify(output),
|
|
303
184
|
createdAt: now,
|
|
304
185
|
updatedAt: now,
|
|
305
186
|
});
|
|
306
187
|
}
|
|
307
188
|
catch (artifactErr) {
|
|
308
|
-
this.
|
|
309
|
-
runId
|
|
189
|
+
this.emitEvent('artifact_write_failed', taskId, {
|
|
190
|
+
runId,
|
|
310
191
|
errorMessage: artifactErr instanceof Error ? artifactErr.message : String(artifactErr),
|
|
311
192
|
});
|
|
312
193
|
return this.retryOrFail({
|
|
313
|
-
taskId
|
|
314
|
-
task
|
|
194
|
+
taskId,
|
|
195
|
+
task,
|
|
315
196
|
errorCategory: 'artifact_commit_failed',
|
|
316
197
|
failureReason: `PIArtifact write failed: ${artifactErr instanceof Error ? artifactErr.message : String(artifactErr)}`,
|
|
317
198
|
});
|
|
318
199
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
200
|
+
// ── Evaluator-specific: validate principle-bearing Scribe artifact ──
|
|
201
|
+
// This is the critical business logic: approved evaluator must validate
|
|
202
|
+
// the Scribe principle artifact, NOT the Artificer plan artifact.
|
|
203
|
+
if (output.evaluation.decision === 'approved') {
|
|
204
|
+
const principleArtifactId = await this.resolvePrincipleBearerArtifact(output, taskId);
|
|
322
205
|
if (principleArtifactId) {
|
|
323
206
|
try {
|
|
324
207
|
const updated = await this.artifactStore.updateValidationStatus(principleArtifactId, 'validated');
|
|
325
208
|
if (!updated) {
|
|
326
|
-
|
|
327
|
-
|
|
209
|
+
// updateValidationStatus returned false — fail loud with structured telemetry (ERR-018)
|
|
210
|
+
this.emitEvent('source_validation_update_not_found', taskId, {
|
|
211
|
+
runId,
|
|
328
212
|
sourceArtifactId: principleArtifactId,
|
|
329
213
|
reason: 'principle_artifact_not_found_in_store',
|
|
330
214
|
nextAction: 'verify_artifact_lineage_and_store_consistency',
|
|
@@ -332,228 +216,88 @@ export class EvaluatorRunner {
|
|
|
332
216
|
}
|
|
333
217
|
}
|
|
334
218
|
catch (updateErr) {
|
|
335
|
-
this.
|
|
336
|
-
runId
|
|
219
|
+
this.emitEvent('source_validation_update_failed', taskId, {
|
|
220
|
+
runId,
|
|
337
221
|
sourceArtifactId: principleArtifactId,
|
|
338
222
|
errorMessage: updateErr instanceof Error ? updateErr.message : String(updateErr),
|
|
339
223
|
});
|
|
340
224
|
}
|
|
341
225
|
}
|
|
342
226
|
}
|
|
227
|
+
// Mark task succeeded
|
|
228
|
+
const resultRef = `${this.config.resultRefPrefix}://${runId}`;
|
|
343
229
|
try {
|
|
344
|
-
await this.stateManager.markTaskSucceeded(
|
|
230
|
+
await this.stateManager.markTaskSucceeded(taskId, resultRef);
|
|
345
231
|
}
|
|
346
232
|
catch (stateErr) {
|
|
347
|
-
this.
|
|
348
|
-
taskId
|
|
349
|
-
runId
|
|
233
|
+
this.emitEvent('mark_succeeded_failed', taskId, {
|
|
234
|
+
taskId,
|
|
235
|
+
runId,
|
|
350
236
|
errorMessage: stateErr instanceof Error ? stateErr.message : String(stateErr),
|
|
351
237
|
});
|
|
352
238
|
throw stateErr;
|
|
353
239
|
}
|
|
354
|
-
this.
|
|
355
|
-
attemptCount:
|
|
240
|
+
this.emitEvent('task_succeeded', taskId, {
|
|
241
|
+
attemptCount: task.attemptCount,
|
|
356
242
|
resultRef,
|
|
357
|
-
evaluationDecision:
|
|
358
|
-
evaluationScore:
|
|
243
|
+
evaluationDecision: output.evaluation.decision,
|
|
244
|
+
evaluationScore: output.evaluation.score,
|
|
359
245
|
});
|
|
360
|
-
this.phase = RunnerPhase.Completed;
|
|
361
246
|
return {
|
|
362
247
|
status: 'succeeded',
|
|
363
|
-
taskId
|
|
364
|
-
runId
|
|
248
|
+
taskId,
|
|
249
|
+
runId,
|
|
365
250
|
artifactId,
|
|
366
251
|
resultRef,
|
|
367
|
-
contextHash
|
|
368
|
-
output
|
|
369
|
-
attemptCount:
|
|
252
|
+
contextHash,
|
|
253
|
+
output,
|
|
254
|
+
attemptCount: task.attemptCount,
|
|
370
255
|
};
|
|
371
256
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
errorCategory,
|
|
382
|
-
failureReason: `Runtime execution ended with status: ${runStatus.status}`,
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
async handleValidationError(ctx) {
|
|
386
|
-
const category = (ctx.errorCategory ?? 'output_invalid');
|
|
387
|
-
this.emitEvaluatorEvent('evaluator_output_invalid', ctx.taskId, {
|
|
388
|
-
errorCount: ctx.errors.length,
|
|
389
|
-
errorCategory: category,
|
|
390
|
-
});
|
|
391
|
-
return this.retryOrFail({
|
|
392
|
-
taskId: ctx.taskId,
|
|
393
|
-
task: ctx.task,
|
|
394
|
-
errorCategory: category,
|
|
395
|
-
failureReason: `Validation failed: ${ctx.errors.join('; ')}`,
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
async handleLeaseOrPhaseError(taskId, error) {
|
|
399
|
-
const classified = this.classifyError(error);
|
|
400
|
-
if (classified.category === 'lease_conflict') {
|
|
401
|
-
this.emitEvaluatorEvent('evaluator_run_failed', taskId, {
|
|
402
|
-
errorCategory: 'lease_conflict',
|
|
403
|
-
errorMessage: classified.message,
|
|
404
|
-
});
|
|
405
|
-
return {
|
|
406
|
-
status: 'failed',
|
|
407
|
-
taskId,
|
|
408
|
-
errorCategory: 'lease_conflict',
|
|
409
|
-
failureReason: classified.message,
|
|
410
|
-
attemptCount: 1,
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
this.emitEvaluatorEvent('evaluator_run_failed', taskId, {
|
|
414
|
-
errorCategory: classified.category,
|
|
415
|
-
errorMessage: classified.message,
|
|
416
|
-
});
|
|
417
|
-
const task = {
|
|
418
|
-
taskId,
|
|
419
|
-
taskKind: 'evaluator',
|
|
420
|
-
status: 'leased',
|
|
421
|
-
createdAt: new Date().toISOString(),
|
|
422
|
-
updatedAt: new Date().toISOString(),
|
|
423
|
-
attemptCount: 1,
|
|
424
|
-
maxAttempts: this.resolvedOptions.defaultMaxAttempts,
|
|
425
|
-
};
|
|
426
|
-
return this.retryOrFail({ taskId, task, errorCategory: classified.category, failureReason: classified.message });
|
|
257
|
+
// ── Optional hooks ──────────────────────────────────────────────────────────
|
|
258
|
+
/**
|
|
259
|
+
* Re-inject taskId if stripped by stripLineageFields (PRI-272 / ERR-008).
|
|
260
|
+
* Only fill when absent via Object.hasOwn — present-but-falsy values
|
|
261
|
+
* must reach validation and fail loud (Runtime Contract Rule 3).
|
|
262
|
+
*/
|
|
263
|
+
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
264
|
+
postFetchTransform(taskId, untrustedOutput) {
|
|
265
|
+
injectRunnerLineageIfAbsent(untrustedOutput, 'taskId', taskId);
|
|
427
266
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
errorMessage: classified.message,
|
|
267
|
+
emitSuccessTelemetry(taskId, output) {
|
|
268
|
+
this.emitEvent('decision_recorded', taskId, {
|
|
269
|
+
evaluationDecision: output.evaluation.decision,
|
|
270
|
+
evaluationScore: output.evaluation.score,
|
|
433
271
|
});
|
|
434
|
-
return this.retryOrFail({ taskId, task, errorCategory: classified.category, failureReason: classified.message });
|
|
435
272
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
return {
|
|
448
|
-
status: 'failed',
|
|
449
|
-
taskId: ctx.taskId,
|
|
450
|
-
errorCategory: 'storage_unavailable',
|
|
451
|
-
failureReason: `State manager error: ${ctx.failureReason}`,
|
|
452
|
-
attemptCount: ctx.task.attemptCount,
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
this.emitEvaluatorEvent('evaluator_task_failed', ctx.taskId, {
|
|
456
|
-
errorCategory: ctx.errorCategory,
|
|
457
|
-
attemptCount: ctx.task.attemptCount,
|
|
458
|
-
failureReason: ctx.failureReason,
|
|
459
|
-
});
|
|
460
|
-
this.phase = RunnerPhase.Failed;
|
|
461
|
-
return {
|
|
462
|
-
status: 'failed',
|
|
463
|
-
taskId: ctx.taskId,
|
|
464
|
-
errorCategory: ctx.errorCategory,
|
|
465
|
-
failureReason: ctx.failureReason,
|
|
466
|
-
attemptCount: ctx.task.attemptCount,
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
const shouldRetry = this.stateManager.getRetryPolicy().shouldRetry(ctx.task);
|
|
470
|
-
if (shouldRetry) {
|
|
471
|
-
try {
|
|
472
|
-
await this.stateManager.markTaskRetryWait(ctx.taskId, ctx.errorCategory);
|
|
473
|
-
}
|
|
474
|
-
catch (stateErr) {
|
|
475
|
-
this.emitEvaluatorEvent('evaluator_mark_retry_error', ctx.taskId, {
|
|
476
|
-
errorCategory: 'storage_unavailable',
|
|
477
|
-
attemptCount: ctx.task.attemptCount,
|
|
478
|
-
errorMessage: stateErr instanceof Error ? stateErr.message : String(stateErr),
|
|
479
|
-
});
|
|
480
|
-
return {
|
|
481
|
-
status: 'failed',
|
|
482
|
-
taskId: ctx.taskId,
|
|
483
|
-
errorCategory: 'storage_unavailable',
|
|
484
|
-
failureReason: `State manager error: ${ctx.failureReason}`,
|
|
485
|
-
attemptCount: ctx.task.attemptCount,
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
this.emitEvaluatorEvent('evaluator_task_retried', ctx.taskId, {
|
|
489
|
-
errorCategory: ctx.errorCategory,
|
|
490
|
-
attemptCount: ctx.task.attemptCount,
|
|
273
|
+
/**
|
|
274
|
+
* Check lineage strip contract after validation passes.
|
|
275
|
+
* Validates sourceTrace.scribeArtifactId consistency (ERR-004, ERR-008).
|
|
276
|
+
*/
|
|
277
|
+
checkLineageIntegrity(taskId, output) {
|
|
278
|
+
// sourceTrace.artificerArtifactId must match sourceArtificerArtifactId
|
|
279
|
+
if (output.sourceTrace.artificerArtifactId !== output.sourceArtificerArtifactId) {
|
|
280
|
+
this.emitEvent('lineage_integrity_violation', taskId, {
|
|
281
|
+
sourceArtificerArtifactId: output.sourceArtificerArtifactId,
|
|
282
|
+
traceArtificerArtifactId: output.sourceTrace.artificerArtifactId,
|
|
283
|
+
reason: 'sourceArtificerArtifactId_and_sourceTrace_artificerArtifactId_mismatch',
|
|
491
284
|
});
|
|
492
|
-
this.phase = RunnerPhase.RetryWaiting;
|
|
493
|
-
return {
|
|
494
|
-
status: 'retried',
|
|
495
|
-
taskId: ctx.taskId,
|
|
496
|
-
errorCategory: ctx.errorCategory,
|
|
497
|
-
failureReason: ctx.failureReason,
|
|
498
|
-
attemptCount: ctx.task.attemptCount,
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
try {
|
|
502
|
-
await this.stateManager.markTaskFailed(ctx.taskId, 'max_attempts_exceeded');
|
|
503
|
-
}
|
|
504
|
-
catch (stateErr) {
|
|
505
|
-
this.emitEvaluatorEvent('evaluator_mark_failed_error', ctx.taskId, {
|
|
506
|
-
errorCategory: 'storage_unavailable',
|
|
507
|
-
attemptCount: ctx.task.attemptCount,
|
|
508
|
-
errorMessage: stateErr instanceof Error ? stateErr.message : String(stateErr),
|
|
509
|
-
});
|
|
510
|
-
return {
|
|
511
|
-
status: 'failed',
|
|
512
|
-
taskId: ctx.taskId,
|
|
513
|
-
errorCategory: 'storage_unavailable',
|
|
514
|
-
failureReason: `State manager error: ${ctx.failureReason}`,
|
|
515
|
-
attemptCount: ctx.task.attemptCount,
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
this.emitEvaluatorEvent('evaluator_task_failed', ctx.taskId, {
|
|
519
|
-
errorCategory: 'max_attempts_exceeded',
|
|
520
|
-
attemptCount: ctx.task.attemptCount,
|
|
521
|
-
failureReason: `Max attempts exceeded: ${ctx.failureReason}`,
|
|
522
|
-
});
|
|
523
|
-
this.phase = RunnerPhase.Failed;
|
|
524
|
-
return {
|
|
525
|
-
status: 'failed',
|
|
526
|
-
taskId: ctx.taskId,
|
|
527
|
-
errorCategory: 'max_attempts_exceeded',
|
|
528
|
-
failureReason: `Max attempts exceeded: ${ctx.failureReason}`,
|
|
529
|
-
attemptCount: ctx.task.attemptCount,
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
533
|
-
isPermanentError(category) {
|
|
534
|
-
return EVALUATOR_PERMANENT_ERROR_CATEGORIES.has(category);
|
|
535
|
-
}
|
|
536
|
-
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
537
|
-
classifyError(error) {
|
|
538
|
-
if (error instanceof PDRuntimeError) {
|
|
539
|
-
return { category: error.category, message: error.message };
|
|
540
|
-
}
|
|
541
|
-
if (error instanceof Error) {
|
|
542
|
-
return { category: 'execution_failed', message: error.message };
|
|
543
|
-
}
|
|
544
|
-
return { category: 'execution_failed', message: String(error) };
|
|
545
|
-
}
|
|
546
|
-
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
547
|
-
mapRunStatusToErrorCategory(status) {
|
|
548
|
-
switch (status) {
|
|
549
|
-
case 'failed': return 'execution_failed';
|
|
550
|
-
case 'timed_out': return 'timeout';
|
|
551
|
-
case 'cancelled': return 'cancelled';
|
|
552
|
-
default: return 'execution_failed';
|
|
553
285
|
}
|
|
554
286
|
}
|
|
287
|
+
// ── Evaluator-specific: principle bearer resolution ─────────────────────────
|
|
288
|
+
/**
|
|
289
|
+
* Resolve the principle-bearing artifact that the evaluator should validate.
|
|
290
|
+
*
|
|
291
|
+
* Strategy 1: Use scribeArtifactId from sourceTrace (the Scribe artifact
|
|
292
|
+
* carries principleDraft).
|
|
293
|
+
* Strategy 2: Search lineage for principle-kind artifacts with principleDraft.
|
|
294
|
+
* Strategy 3: No principle-bearing artifact found → telemetry, return null.
|
|
295
|
+
*
|
|
296
|
+
* Ambiguous candidates (more than 1) → fail loud with telemetry, return null.
|
|
297
|
+
* Never silently pick the first candidate (ERR-018, ERR-019).
|
|
298
|
+
*/
|
|
555
299
|
async resolvePrincipleBearerArtifact(output, taskId) {
|
|
556
|
-
// Strategy 1: Use scribeArtifactId from sourceTrace
|
|
300
|
+
// Strategy 1: Use scribeArtifactId from sourceTrace
|
|
557
301
|
const scribeArtifactId = output.sourceTrace?.scribeArtifactId;
|
|
558
302
|
if (typeof scribeArtifactId === 'string' && scribeArtifactId.trim() !== '') {
|
|
559
303
|
const scribeArtifact = await this.artifactStore.getArtifactById(scribeArtifactId);
|
|
@@ -561,13 +305,13 @@ export class EvaluatorRunner {
|
|
|
561
305
|
return scribeArtifactId;
|
|
562
306
|
}
|
|
563
307
|
// Scribe artifact not found or wrong kind — fall through to lineage search
|
|
564
|
-
this.
|
|
308
|
+
this.emitEvent('scribe_artifact_not_principle', taskId, {
|
|
565
309
|
scribeArtifactId,
|
|
566
310
|
actualKind: scribeArtifact?.artifactKind ?? 'not_found',
|
|
567
311
|
});
|
|
568
312
|
}
|
|
569
313
|
// Strategy 2: Search lineage for all principle-kind artifacts with principleDraft content
|
|
570
|
-
const lineageArtifactIds = await this.resolveLineageArtifactIds(taskId);
|
|
314
|
+
const { ids: lineageArtifactIds } = await this.resolveLineageArtifactIds(taskId);
|
|
571
315
|
const candidates = [];
|
|
572
316
|
for (const lineageId of lineageArtifactIds) {
|
|
573
317
|
const artifact = await this.artifactStore.getArtifactById(lineageId);
|
|
@@ -584,15 +328,16 @@ export class EvaluatorRunner {
|
|
|
584
328
|
return only ?? null;
|
|
585
329
|
}
|
|
586
330
|
if (candidates.length > 1) {
|
|
587
|
-
|
|
331
|
+
// Ambiguous — fail loud, do NOT silently pick first (ERR-018)
|
|
332
|
+
this.emitEvent('principle_bearer_ambiguous', taskId, {
|
|
588
333
|
candidateArtifactIds: candidates,
|
|
589
334
|
reason: 'multiple_principle_bearing_artifacts_in_lineage',
|
|
590
335
|
nextAction: 'disambiguate_principle_source_or_fix_lineage',
|
|
591
336
|
});
|
|
592
337
|
return null;
|
|
593
338
|
}
|
|
594
|
-
// Strategy 3:
|
|
595
|
-
this.
|
|
339
|
+
// Strategy 3: No principle-bearing artifact found
|
|
340
|
+
this.emitEvent('no_principle_bearer_found', taskId, {
|
|
596
341
|
runId: output.taskId,
|
|
597
342
|
scribeArtifactId: scribeArtifactId ?? 'not_provided',
|
|
598
343
|
lineageCount: lineageArtifactIds.length,
|
|
@@ -601,28 +346,10 @@ export class EvaluatorRunner {
|
|
|
601
346
|
});
|
|
602
347
|
return null;
|
|
603
348
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
return [];
|
|
609
|
-
const piTask = hydratePITaskRecord(task);
|
|
610
|
-
const deps = piTask?.dependencyTaskIds ?? [];
|
|
611
|
-
const results = await Promise.allSettled(deps.map((depId) => this.artifactStore.listBySourceTaskId(depId)));
|
|
612
|
-
const ids = [];
|
|
613
|
-
for (const result of results) {
|
|
614
|
-
if (result.status === 'fulfilled') {
|
|
615
|
-
for (const artifact of result.value) {
|
|
616
|
-
ids.push(artifact.artifactId);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
return ids;
|
|
621
|
-
}
|
|
622
|
-
catch {
|
|
623
|
-
return [];
|
|
624
|
-
}
|
|
625
|
-
}
|
|
349
|
+
/**
|
|
350
|
+
* Check if an artifact's contentJson contains principle-bearing content.
|
|
351
|
+
* Uses Object.hasOwn (ERR-013) and runtime type checks (ERR-001, ERR-005).
|
|
352
|
+
*/
|
|
626
353
|
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
627
354
|
hasPrincipleDraftContent(contentJson) {
|
|
628
355
|
try {
|
|
@@ -652,10 +379,5 @@ export class EvaluatorRunner {
|
|
|
652
379
|
static isRecord(value) {
|
|
653
380
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
654
381
|
}
|
|
655
|
-
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
656
|
-
sleep(ms) {
|
|
657
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
658
|
-
}
|
|
659
382
|
}
|
|
660
|
-
export { DEFAULT_EVALUATOR_RUNNER_OPTIONS };
|
|
661
383
|
//# sourceMappingURL=evaluator-runner.js.map
|