@principles/core 1.274.4 → 1.275.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/dist/runtime-v2/__tests__/pain-ingress-persistence.test.d.ts +2 -0
- package/dist/runtime-v2/__tests__/pain-ingress-persistence.test.d.ts.map +1 -0
- package/dist/runtime-v2/__tests__/pain-ingress-persistence.test.js +276 -0
- package/dist/runtime-v2/__tests__/pain-ingress-persistence.test.js.map +1 -0
- package/dist/runtime-v2/__tests__/pain-ingress-shared-semantics.test.d.ts +2 -0
- package/dist/runtime-v2/__tests__/pain-ingress-shared-semantics.test.d.ts.map +1 -0
- package/dist/runtime-v2/__tests__/pain-ingress-shared-semantics.test.js +131 -0
- package/dist/runtime-v2/__tests__/pain-ingress-shared-semantics.test.js.map +1 -0
- package/dist/runtime-v2/__tests__/pain-outcome-convergence.test.d.ts +2 -0
- package/dist/runtime-v2/__tests__/pain-outcome-convergence.test.d.ts.map +1 -0
- package/dist/runtime-v2/__tests__/pain-outcome-convergence.test.js +126 -0
- package/dist/runtime-v2/__tests__/pain-outcome-convergence.test.js.map +1 -0
- package/dist/runtime-v2/__tests__/pain-signal-bridge-execute-pending.test.js +95 -0
- package/dist/runtime-v2/__tests__/pain-signal-bridge-execute-pending.test.js.map +1 -1
- package/dist/runtime-v2/activation/__tests__/production-gate-deps.test.js +69 -0
- package/dist/runtime-v2/activation/__tests__/production-gate-deps.test.js.map +1 -1
- package/dist/runtime-v2/activation/production-gate-deps.d.ts.map +1 -1
- package/dist/runtime-v2/activation/production-gate-deps.js +13 -46
- package/dist/runtime-v2/activation/production-gate-deps.js.map +1 -1
- package/dist/runtime-v2/index.d.ts +9 -1
- package/dist/runtime-v2/index.d.ts.map +1 -1
- package/dist/runtime-v2/index.js +6 -0
- package/dist/runtime-v2/index.js.map +1 -1
- package/dist/runtime-v2/internalization/__tests__/adversarial-feedback.test.js +9 -0
- package/dist/runtime-v2/internalization/__tests__/adversarial-feedback.test.js.map +1 -1
- package/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js +15 -5
- package/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js.map +1 -1
- package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.d.ts +2 -0
- package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.js +413 -0
- package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.js.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/evaluator-gate-authority.test.js +136 -0
- package/dist/runtime-v2/internalization/__tests__/evaluator-gate-authority.test.js.map +1 -1
- package/dist/runtime-v2/internalization/__tests__/repair-replay-resolver.test.d.ts +2 -0
- package/dist/runtime-v2/internalization/__tests__/repair-replay-resolver.test.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/repair-replay-resolver.test.js +340 -0
- package/dist/runtime-v2/internalization/__tests__/repair-replay-resolver.test.js.map +1 -0
- package/dist/runtime-v2/internalization/adversarial-feedback.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/adversarial-feedback.js +7 -1
- package/dist/runtime-v2/internalization/adversarial-feedback.js.map +1 -1
- package/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +9 -2
- package/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/artificer-prompt-builder.js +19 -1
- package/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
- package/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/artificer-runner.js +84 -7
- package/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-output.d.ts +18 -1
- package/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-output.js +12 -2
- package/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-runner.js +99 -5
- package/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.d.ts +18 -1
- package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.js +20 -0
- package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.js.map +1 -1
- package/dist/runtime-v2/internalization/repair-replay-resolver.d.ts +112 -0
- package/dist/runtime-v2/internalization/repair-replay-resolver.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/repair-replay-resolver.js +332 -0
- package/dist/runtime-v2/internalization/repair-replay-resolver.js.map +1 -0
- package/dist/runtime-v2/pain-ingress-payload.d.ts +207 -0
- package/dist/runtime-v2/pain-ingress-payload.d.ts.map +1 -0
- package/dist/runtime-v2/pain-ingress-payload.js +340 -0
- package/dist/runtime-v2/pain-ingress-payload.js.map +1 -0
- package/dist/runtime-v2/pain-ingress.d.ts +61 -0
- package/dist/runtime-v2/pain-ingress.d.ts.map +1 -0
- package/dist/runtime-v2/pain-ingress.js +163 -0
- package/dist/runtime-v2/pain-ingress.js.map +1 -0
- package/dist/runtime-v2/pain-signal-bridge.d.ts +39 -1
- package/dist/runtime-v2/pain-signal-bridge.d.ts.map +1 -1
- package/dist/runtime-v2/pain-signal-bridge.js +163 -8
- package/dist/runtime-v2/pain-signal-bridge.js.map +1 -1
- package/dist/runtime-v2/pain-to-principle-service.d.ts +8 -1
- package/dist/runtime-v2/pain-to-principle-service.d.ts.map +1 -1
- package/dist/runtime-v2/pain-to-principle-service.js +3 -0
- package/dist/runtime-v2/pain-to-principle-service.js.map +1 -1
- package/dist/telemetry-event.d.ts +2 -2
- package/dist/telemetry-event.d.ts.map +1 -1
- package/dist/telemetry-event.js +14 -0
- package/dist/telemetry-event.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-634 PR-A — Runner-level deterministic regression (SPEC §31/§35/§38).
|
|
3
|
+
*
|
|
4
|
+
* The full self-healing closure, through REAL production components:
|
|
5
|
+
*
|
|
6
|
+
* Round 1: Artificer emits RuleCode calling input.action.paramsSummary.includes(...)
|
|
7
|
+
* → REAL deterministic replay (createProductionGateDeps, node:vm)
|
|
8
|
+
* → every case fails runtime_error ("…includes is not a function")
|
|
9
|
+
* → Evaluator artifact durably carries concrete failed-case evidence
|
|
10
|
+
* (caseId / expectedDecision / errorType / message; no fabricated
|
|
11
|
+
* actualDecision)
|
|
12
|
+
* → repair task seeded with diagnosticReplay {ran:true, passed:false}
|
|
13
|
+
*
|
|
14
|
+
* Repair: ArtificerRunner.buildContext resolves the evidence BY REFERENCE
|
|
15
|
+
* from the source Evaluator artifact (intent-runId artifact
|
|
16
|
+
* identity) — with all three Progressive Disclosure flags OFF —
|
|
17
|
+
* and the repair prompt contains the concrete case details.
|
|
18
|
+
*
|
|
19
|
+
* Round 2: Artificer emits correct RuleCode → evaluator approved → REAL
|
|
20
|
+
* replay PASSES all cases (incl. the 5 canonical v2 adversarial
|
|
21
|
+
* cases) → formal pi-rule-* artifact assembled + validated.
|
|
22
|
+
*
|
|
23
|
+
* No mock gate, no hand-written artifacts, no DB writes outside the runners.
|
|
24
|
+
* The only scripted component is the LLM (allowed: deterministic failure
|
|
25
|
+
* injection per SPEC §37).
|
|
26
|
+
*/
|
|
27
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
28
|
+
import * as fs from 'node:fs';
|
|
29
|
+
import * as path from 'node:path';
|
|
30
|
+
import * as os from 'node:os';
|
|
31
|
+
import { RuntimeStateManager } from '../../store/runtime-state-manager.js';
|
|
32
|
+
import { EvaluatorRunner } from '../evaluator-runner.js';
|
|
33
|
+
import { ArtificerRunner } from '../artificer-runner.js';
|
|
34
|
+
import { DefaultEvaluatorValidator } from '../evaluator-output.js';
|
|
35
|
+
import { DefaultArtificerValidator } from '../artificer-output.js';
|
|
36
|
+
import { StoreEventEmitter } from '../../store/event-emitter.js';
|
|
37
|
+
import { SqliteConnection } from '../../store/sqlite-connection.js';
|
|
38
|
+
import { SqlitePIArtifactStore } from '../../store/artifact/sqlite-pi-artifact-store.js';
|
|
39
|
+
import { createPITaskDiagnosticJson } from '../pitask-metadata.js';
|
|
40
|
+
import { createProductionGateDeps } from '../../activation/production-gate-deps.js';
|
|
41
|
+
import { computeFeatureFlagsFromConfig, isFeatureEnabled } from '../../config/pd-config-feature-flags.js';
|
|
42
|
+
let workspaceDir;
|
|
43
|
+
let stateManager;
|
|
44
|
+
let emitter;
|
|
45
|
+
let emitted;
|
|
46
|
+
let store;
|
|
47
|
+
const SCRIBE_ID = 'scribe-rr';
|
|
48
|
+
const ART1_ID = 'artificer-rr1';
|
|
49
|
+
const EVAL1_ID = 'evaluator-rr1';
|
|
50
|
+
const REPAIR_ID = 'artificer-repair-rr1';
|
|
51
|
+
const EVAL2_ID = 'evaluator-rr2';
|
|
52
|
+
const SCRIBE_ART = 'pi-art-scribe-rr';
|
|
53
|
+
/** Round-1 RuleCode: the classic whole-object string-method bug. */
|
|
54
|
+
const BAD_RULE_CODE = `function evaluate(input, helpers) {
|
|
55
|
+
if (input.action.paramsSummary.includes('/etc/passwd')) {
|
|
56
|
+
return { decision: 'block', matched: true, reason: 'risk path' };
|
|
57
|
+
}
|
|
58
|
+
return { decision: 'allow', matched: false, reason: 'safe path' };
|
|
59
|
+
}`;
|
|
60
|
+
/** Round-2 RuleCode: risk-path dominance + read-before-write via context facts.
|
|
61
|
+
* Reads params via guarded key access — the exact pattern the repaired
|
|
62
|
+
* prompt contract teaches (contrast with the BAD code's string-method call). */
|
|
63
|
+
const GOOD_RULE_CODE = `function evaluate(input, helpers) {
|
|
64
|
+
var rawPath = input.action.paramsSummary.path;
|
|
65
|
+
var p = (typeof rawPath === 'string') ? rawPath : (input.action.normalizedPath || '');
|
|
66
|
+
if (p.indexOf('/etc/') === 0 || p === '/etc/passwd') {
|
|
67
|
+
return { decision: 'block', matched: true, reason: 'risk path dominates prior context' };
|
|
68
|
+
}
|
|
69
|
+
var ctx = input.context;
|
|
70
|
+
if (ctx && ctx.facts && ctx.facts.priorReadOfTarget === 'no') {
|
|
71
|
+
return { decision: 'block', matched: true, reason: 'write target was not read first' };
|
|
72
|
+
}
|
|
73
|
+
return { decision: 'allow', matched: false, reason: 'no risk signal' };
|
|
74
|
+
}`;
|
|
75
|
+
const GOLDEN_TRACE_CASES = [
|
|
76
|
+
{ caseId: 'neg-1', kind: 'negative', toolName: 'write_file', params: { path: '/etc/passwd' }, expectedDecision: 'block' },
|
|
77
|
+
{ caseId: 'pos-1', kind: 'positive', toolName: 'write_file', params: { path: '/workspace/src/a.ts' }, expectedDecision: 'allow' },
|
|
78
|
+
];
|
|
79
|
+
function flagsOffConfig() {
|
|
80
|
+
return {
|
|
81
|
+
config: {
|
|
82
|
+
version: 1,
|
|
83
|
+
features: {
|
|
84
|
+
artifact_summary_redundancy: { category: 'quiet', enabled: false },
|
|
85
|
+
context_manifest_budget: { category: 'quiet', enabled: false },
|
|
86
|
+
progressive_evaluator: { category: 'quiet', enabled: false },
|
|
87
|
+
},
|
|
88
|
+
runtimeProfiles: {},
|
|
89
|
+
internalAgents: {},
|
|
90
|
+
ui: { diagnostics: { mode: 'simple' } },
|
|
91
|
+
},
|
|
92
|
+
source: 'user_config',
|
|
93
|
+
warnings: [],
|
|
94
|
+
resolvedContextInjection: {
|
|
95
|
+
thinkingOs: false,
|
|
96
|
+
projectFocus: 'off',
|
|
97
|
+
evolutionContext: { enabled: true, maxMessages: 4, maxCharsPerMessage: 200 },
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function artificerOutput(implementationCode, scribeArtifactId, taskId) {
|
|
102
|
+
return {
|
|
103
|
+
taskId,
|
|
104
|
+
sourceScribeArtifactId: scribeArtifactId,
|
|
105
|
+
implementationSummary: 'read-before-write guard',
|
|
106
|
+
sourceTrace: { scribeArtifactId: scribeArtifactId },
|
|
107
|
+
risks: [],
|
|
108
|
+
implementationCode,
|
|
109
|
+
goldenTraceCases: GOLDEN_TRACE_CASES,
|
|
110
|
+
affectedTools: ['write_file'],
|
|
111
|
+
generatedAt: new Date().toISOString(),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function evaluatorOutput(taskId, artificerArtifactId, decision) {
|
|
115
|
+
return {
|
|
116
|
+
taskId,
|
|
117
|
+
sourceArtificerArtifactId: artificerArtifactId,
|
|
118
|
+
evaluation: {
|
|
119
|
+
decision,
|
|
120
|
+
summary: 'repair-replay regression',
|
|
121
|
+
score: decision === 'approved' ? 0.9 : 0.6,
|
|
122
|
+
strengths: [],
|
|
123
|
+
concerns: decision === 'needs_revision' ? ['paramsSummary misuse'] : [],
|
|
124
|
+
requiredChanges: decision === 'needs_revision' ? ['Fix the paramsSummary string-method crash'] : [],
|
|
125
|
+
// PRI-630 convergence: the round-2 evaluator adjudicates the round-1
|
|
126
|
+
// requirement (req-1 = the round-1 requiredChange, sequential id).
|
|
127
|
+
...(taskId === EVAL2_ID
|
|
128
|
+
? {
|
|
129
|
+
priorRequirementStatuses: [{ id: 'req-1', status: 'resolved' }],
|
|
130
|
+
requirementLedger: [{ id: 'req-1', statement: 'Fix the paramsSummary string-method crash', status: 'resolved' }],
|
|
131
|
+
}
|
|
132
|
+
: {}),
|
|
133
|
+
},
|
|
134
|
+
sourceTrace: { artificerArtifactId, scribeArtifactId: SCRIBE_ART },
|
|
135
|
+
risks: [],
|
|
136
|
+
generatedAt: new Date().toISOString(),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/** Scripted LLM adapter that records every prompt it receives. */
|
|
140
|
+
function scriptedAdapter(payload, prompts, runId) {
|
|
141
|
+
return {
|
|
142
|
+
startRun: async (req) => {
|
|
143
|
+
prompts.push(String(req.inputPayload));
|
|
144
|
+
return { runId, runtimeKind: 'test-double', startedAt: new Date().toISOString() };
|
|
145
|
+
},
|
|
146
|
+
pollRun: async () => ({ status: 'succeeded', runId }),
|
|
147
|
+
fetchOutput: async () => ({ runId, payload }),
|
|
148
|
+
cancelRun: async () => undefined,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function meta(o = {}) {
|
|
152
|
+
return createPITaskDiagnosticJson({
|
|
153
|
+
dependencyTaskIds: [], channel: 'prompt', timeoutMs: 300_000,
|
|
154
|
+
inputArtifactRefs: [], outputArtifactRefs: [], ...o,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
async function mkTask(spec) {
|
|
158
|
+
await stateManager.createTask({
|
|
159
|
+
taskId: spec.id, taskKind: spec.kind, status: 'pending', attemptCount: 0, maxAttempts: 3,
|
|
160
|
+
diagnosticJson: spec.diagnosticJson ?? meta({ dependencyTaskIds: spec.deps }),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
async function succeed(id) {
|
|
164
|
+
await stateManager.acquireLease({ taskId: id, owner: 'rr-test', runtimeKind: 'test-double' });
|
|
165
|
+
await stateManager.markTaskSucceeded(id);
|
|
166
|
+
}
|
|
167
|
+
beforeEach(async () => {
|
|
168
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-repair-replay-'));
|
|
169
|
+
stateManager = new RuntimeStateManager({ workspaceDir });
|
|
170
|
+
await stateManager.initialize();
|
|
171
|
+
emitter = new StoreEventEmitter();
|
|
172
|
+
emitted = [];
|
|
173
|
+
emitter.onTelemetry((event) => {
|
|
174
|
+
emitted.push({ eventType: event.eventType, payload: event.payload });
|
|
175
|
+
});
|
|
176
|
+
store = new SqlitePIArtifactStore(new SqliteConnection(workspaceDir));
|
|
177
|
+
});
|
|
178
|
+
afterEach(async () => {
|
|
179
|
+
await stateManager.close();
|
|
180
|
+
try {
|
|
181
|
+
fs.rmSync(workspaceDir, { recursive: true, force: true });
|
|
182
|
+
}
|
|
183
|
+
catch { /* temp */ }
|
|
184
|
+
});
|
|
185
|
+
describe('PRI-634 PR-A: FAIL → durable evidence → repair retrieval → PASS → pi-rule (flags OFF)', () => {
|
|
186
|
+
it('closes the full self-healing loop through the REAL deterministic replay gate', async () => {
|
|
187
|
+
// SPEC §38 acceptance: prove the fix works with all Progressive
|
|
188
|
+
// Disclosure quiet features explicitly OFF (they default off; pin them).
|
|
189
|
+
const flags = computeFeatureFlagsFromConfig(flagsOffConfig());
|
|
190
|
+
expect(isFeatureEnabled(flags, 'artifact_summary_redundancy')).toBe(false);
|
|
191
|
+
expect(isFeatureEnabled(flags, 'context_manifest_budget')).toBe(false);
|
|
192
|
+
expect(isFeatureEnabled(flags, 'progressive_evaluator')).toBe(false);
|
|
193
|
+
// ── lineage: scribe task + artifact ──
|
|
194
|
+
await mkTask({ id: SCRIBE_ID, kind: 'scribe', deps: [] });
|
|
195
|
+
await succeed(SCRIBE_ID);
|
|
196
|
+
await store.upsertArtifact({
|
|
197
|
+
artifactId: SCRIBE_ART, artifactKind: 'principle', sourceTaskId: SCRIBE_ID,
|
|
198
|
+
lineageArtifactIds: [], validationStatus: 'validated',
|
|
199
|
+
contentJson: JSON.stringify({ principleId: 'pri-rr-read-before-write', principleDraft: { statement: 'Read a file before writing it.' }, sourceTrace: {} }),
|
|
200
|
+
createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(),
|
|
201
|
+
});
|
|
202
|
+
// ── Round 1: Artificer emits the paramsSummary string-method bug ──
|
|
203
|
+
await mkTask({ id: ART1_ID, kind: 'artificer', deps: [SCRIBE_ID] });
|
|
204
|
+
const artPrompts = [];
|
|
205
|
+
const artificer1 = new ArtificerRunner({
|
|
206
|
+
stateManager,
|
|
207
|
+
runtimeAdapter: scriptedAdapter(artificerOutput(BAD_RULE_CODE, SCRIBE_ART, ART1_ID), artPrompts, 'run-art-1'),
|
|
208
|
+
eventEmitter: emitter,
|
|
209
|
+
artifactStore: store,
|
|
210
|
+
validator: new DefaultArtificerValidator(),
|
|
211
|
+
}, { owner: 'rr-test', runtimeKind: 'test-double', pollIntervalMs: 5, timeoutMs: 5_000, effectiveConfig: flagsOffConfig() });
|
|
212
|
+
const art1Result = await artificer1.run(ART1_ID);
|
|
213
|
+
expect(art1Result.status).toBe('succeeded');
|
|
214
|
+
const art1Artifacts = await store.listBySourceTaskId(ART1_ID);
|
|
215
|
+
const art1Artifact = art1Artifacts.find((a) => a.artifactKind === 'principle');
|
|
216
|
+
expect(art1Artifact).toBeDefined();
|
|
217
|
+
if (!art1Artifact)
|
|
218
|
+
return;
|
|
219
|
+
// ── Round 1: Evaluator needs_revision + REAL diagnostic replay ──
|
|
220
|
+
await mkTask({ id: EVAL1_ID, kind: 'evaluator', deps: [ART1_ID] });
|
|
221
|
+
const evalPrompts = [];
|
|
222
|
+
const seededRepair = {};
|
|
223
|
+
const evaluator1 = new EvaluatorRunner({
|
|
224
|
+
stateManager,
|
|
225
|
+
runtimeAdapter: scriptedAdapter(evaluatorOutput(EVAL1_ID, art1Artifact.artifactId, 'needs_revision'), evalPrompts, 'run-eval-1'),
|
|
226
|
+
eventEmitter: emitter,
|
|
227
|
+
artifactStore: store,
|
|
228
|
+
validator: new DefaultEvaluatorValidator(),
|
|
229
|
+
isRepairLoopEnabled: () => true,
|
|
230
|
+
seedArtificerRepairTask: async (params) => {
|
|
231
|
+
seededRepair.payload = params.repairPayload;
|
|
232
|
+
// Plugin-style seeder: real task row carrying the repairPayload.
|
|
233
|
+
await mkTask({ id: REPAIR_ID, kind: 'artificer', deps: params.inheritedDependencyTaskIds, diagnosticJson: meta({
|
|
234
|
+
dependencyTaskIds: params.inheritedDependencyTaskIds,
|
|
235
|
+
repairPayload: params.repairPayload,
|
|
236
|
+
}) });
|
|
237
|
+
return REPAIR_ID;
|
|
238
|
+
},
|
|
239
|
+
}, {
|
|
240
|
+
owner: 'rr-test', runtimeKind: 'test-double', pollIntervalMs: 5, timeoutMs: 5_000,
|
|
241
|
+
gateDeps: createProductionGateDeps(), // REAL deterministic replay — no stubs
|
|
242
|
+
// EvaluatorRunner takes no effectiveConfig — base-runner flag helpers
|
|
243
|
+
// default to legacy (all three quiet flags OFF) without it.
|
|
244
|
+
});
|
|
245
|
+
const eval1Result = await evaluator1.run(EVAL1_ID);
|
|
246
|
+
expect(eval1Result.status).toBe('succeeded');
|
|
247
|
+
// (1) The durable Evaluator artifact carries CONCRETE replay evidence.
|
|
248
|
+
const eval1Artifacts = await store.listBySourceTaskId(EVAL1_ID);
|
|
249
|
+
const eval1Artifact = eval1Artifacts.find((a) => a.artifactKind === 'principle');
|
|
250
|
+
expect(eval1Artifact).toBeDefined();
|
|
251
|
+
if (!eval1Artifact)
|
|
252
|
+
return;
|
|
253
|
+
const eval1Content = JSON.parse(eval1Artifact.contentJson);
|
|
254
|
+
expect(eval1Content.evaluation?.decision).toBe('needs_revision'); // verdict not overridden
|
|
255
|
+
expect(eval1Content.adversarialResult?.passed).toBe(false);
|
|
256
|
+
const failedCases = eval1Content.adversarialResult?.failedCases ?? [];
|
|
257
|
+
expect(failedCases.length).toBeGreaterThanOrEqual(5); // 5 v2 cases at minimum all crashed
|
|
258
|
+
for (const failure of failedCases) {
|
|
259
|
+
expect(typeof failure.errorType).toBe('string'); // SPEC §14: errorType is its own field
|
|
260
|
+
expect(failure.errorType).toBe('runtime_error');
|
|
261
|
+
expect(failure.actualDecision).toBeUndefined(); // no fabricated decision on throws
|
|
262
|
+
expect(typeof failure.message).toBe('string');
|
|
263
|
+
}
|
|
264
|
+
const v2Unavailable = failedCases.find((f) => f.caseId === 'v2-unavailable');
|
|
265
|
+
expect(v2Unavailable).toBeDefined();
|
|
266
|
+
if (!v2Unavailable)
|
|
267
|
+
return;
|
|
268
|
+
expect(v2Unavailable.expectedDecision).toBe('allow');
|
|
269
|
+
expect(String(v2Unavailable.message)).toContain('includes is not a function');
|
|
270
|
+
// (2) The repair round was seeded with the bounded control summary only.
|
|
271
|
+
expect(seededRepair.payload).toBeDefined();
|
|
272
|
+
const seededRepairPayload = seededRepair.payload;
|
|
273
|
+
if (seededRepairPayload === undefined)
|
|
274
|
+
return;
|
|
275
|
+
expect(seededRepairPayload.diagnosticReplay).toEqual({ ran: true, passed: false, failedCaseCount: failedCases.length });
|
|
276
|
+
expect(seededRepairPayload.sourceEvaluatorTaskId).toBe(EVAL1_ID);
|
|
277
|
+
// RepairPayload must NOT carry full failedCases (SPEC §21/§24).
|
|
278
|
+
expect(Object.hasOwn(seededRepairPayload, 'failedCases')).toBe(false);
|
|
279
|
+
// (3) Repair round: ArtificerRunner resolves the evidence BY REFERENCE and
|
|
280
|
+
// the prompt contains the concrete case details — flags OFF.
|
|
281
|
+
const repairPrompts = [];
|
|
282
|
+
const artificerRepair = new ArtificerRunner({
|
|
283
|
+
stateManager,
|
|
284
|
+
runtimeAdapter: scriptedAdapter(artificerOutput(GOOD_RULE_CODE, SCRIBE_ART, REPAIR_ID), repairPrompts, 'run-repair-1'),
|
|
285
|
+
eventEmitter: emitter,
|
|
286
|
+
artifactStore: store,
|
|
287
|
+
validator: new DefaultArtificerValidator(),
|
|
288
|
+
}, { owner: 'rr-test', runtimeKind: 'test-double', pollIntervalMs: 5, timeoutMs: 5_000, effectiveConfig: flagsOffConfig() });
|
|
289
|
+
const repairResult = await artificerRepair.run(REPAIR_ID);
|
|
290
|
+
expect(repairResult.status).toBe('succeeded');
|
|
291
|
+
expect(repairPrompts).toHaveLength(1);
|
|
292
|
+
const [repairPrompt] = repairPrompts;
|
|
293
|
+
if (repairPrompt === undefined)
|
|
294
|
+
return;
|
|
295
|
+
expect(repairPrompt).toContain('Deterministic Replay Evidence (resolved by reference from evaluator artifact');
|
|
296
|
+
expect(repairPrompt).toContain(`Case: v2-unavailable`);
|
|
297
|
+
expect(repairPrompt).toContain('Expected: allow');
|
|
298
|
+
expect(repairPrompt).toContain('Error: runtime_error');
|
|
299
|
+
expect(repairPrompt).toContain('includes is not a function');
|
|
300
|
+
expect(repairPrompt).toContain(EVAL1_ID); // stable source reference in the evidence header
|
|
301
|
+
expect(emitted.some((e) => e.eventType === 'artificer_repair_replay_evidence_resolved')).toBe(true);
|
|
302
|
+
const repairArtifacts = await store.listBySourceTaskId(REPAIR_ID);
|
|
303
|
+
const repairArtifact = repairArtifacts.find((a) => a.artifactKind === 'principle');
|
|
304
|
+
expect(repairArtifact).toBeDefined();
|
|
305
|
+
if (!repairArtifact)
|
|
306
|
+
return;
|
|
307
|
+
// ── Round 2: Evaluator approves the repaired code → REAL replay PASSES → pi-rule ──
|
|
308
|
+
await mkTask({ id: EVAL2_ID, kind: 'evaluator', deps: [REPAIR_ID] });
|
|
309
|
+
const evaluator2 = new EvaluatorRunner({
|
|
310
|
+
stateManager,
|
|
311
|
+
runtimeAdapter: scriptedAdapter(evaluatorOutput(EVAL2_ID, repairArtifact.artifactId, 'approved'), [], 'run-eval-2'),
|
|
312
|
+
eventEmitter: emitter,
|
|
313
|
+
artifactStore: store,
|
|
314
|
+
validator: new DefaultEvaluatorValidator(),
|
|
315
|
+
}, {
|
|
316
|
+
owner: 'rr-test', runtimeKind: 'test-double', pollIntervalMs: 5, timeoutMs: 5_000,
|
|
317
|
+
gateDeps: createProductionGateDeps(), // REAL gate again
|
|
318
|
+
});
|
|
319
|
+
const eval2Result = await evaluator2.run(EVAL2_ID);
|
|
320
|
+
expect(eval2Result.status).toBe('succeeded');
|
|
321
|
+
const eval2Artifacts = await store.listBySourceTaskId(EVAL2_ID);
|
|
322
|
+
const ruleArtifact = eval2Artifacts.find((a) => a.artifactKind === 'rule');
|
|
323
|
+
expect(ruleArtifact).toBeDefined();
|
|
324
|
+
if (!ruleArtifact)
|
|
325
|
+
return;
|
|
326
|
+
expect(ruleArtifact.artifactId).toContain('pi-rule-');
|
|
327
|
+
expect(ruleArtifact.validationStatus).toBe('validated');
|
|
328
|
+
// The repaired code replayed clean: adversarialResult.passed=true durable.
|
|
329
|
+
const eval2Principle = eval2Artifacts.find((a) => a.artifactKind === 'principle');
|
|
330
|
+
const eval2Content = JSON.parse((eval2Principle ?? { contentJson: '{}' }).contentJson);
|
|
331
|
+
expect(eval2Content.adversarialResult?.passed).toBe(true);
|
|
332
|
+
expect(eval2Content.adversarialResult?.failedCases).toHaveLength(0);
|
|
333
|
+
});
|
|
334
|
+
it('missing replay evidence fails loud — no blind LLM repair round (SPEC §27)', async () => {
|
|
335
|
+
// Build a repair task whose diagnosticReplay says FAILED but whose source
|
|
336
|
+
// evaluator artifact does not exist.
|
|
337
|
+
await mkTask({ id: SCRIBE_ID, kind: 'scribe', deps: [] });
|
|
338
|
+
await succeed(SCRIBE_ID);
|
|
339
|
+
await store.upsertArtifact({
|
|
340
|
+
artifactId: SCRIBE_ART, artifactKind: 'principle', sourceTaskId: SCRIBE_ID,
|
|
341
|
+
lineageArtifactIds: [], validationStatus: 'validated',
|
|
342
|
+
contentJson: JSON.stringify({ principleDraft: { statement: 'x' } }),
|
|
343
|
+
createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(),
|
|
344
|
+
});
|
|
345
|
+
await mkTask({ id: 'evaluator-ghost', kind: 'evaluator', deps: [] }); // no artifacts for this task
|
|
346
|
+
await stateManager.deleteTask?.('evaluator-ghost').catch(() => undefined);
|
|
347
|
+
await mkTask({ id: REPAIR_ID, kind: 'artificer', deps: [SCRIBE_ID], diagnosticJson: meta({
|
|
348
|
+
dependencyTaskIds: [SCRIBE_ID],
|
|
349
|
+
repairPayload: {
|
|
350
|
+
requiredChanges: ['fix it'],
|
|
351
|
+
concerns: [],
|
|
352
|
+
previousScore: 0.5,
|
|
353
|
+
repairIteration: 1,
|
|
354
|
+
sourceArtificerArtifactId: 'pi-art-ghost',
|
|
355
|
+
sourceEvaluatorTaskId: 'evaluator-ghost',
|
|
356
|
+
diagnosticReplay: { ran: true, passed: false, failedCaseCount: 3 },
|
|
357
|
+
},
|
|
358
|
+
}) });
|
|
359
|
+
const repairPrompts = [];
|
|
360
|
+
const artificerRepair = new ArtificerRunner({
|
|
361
|
+
stateManager,
|
|
362
|
+
runtimeAdapter: scriptedAdapter(artificerOutput(GOOD_RULE_CODE, SCRIBE_ART, REPAIR_ID), repairPrompts, 'run-repair-x'),
|
|
363
|
+
eventEmitter: emitter,
|
|
364
|
+
artifactStore: store,
|
|
365
|
+
validator: new DefaultArtificerValidator(),
|
|
366
|
+
}, { owner: 'rr-test', runtimeKind: 'test-double', pollIntervalMs: 5, timeoutMs: 5_000, effectiveConfig: flagsOffConfig() });
|
|
367
|
+
const result = await artificerRepair.run(REPAIR_ID);
|
|
368
|
+
// Fail loud BEFORE any LLM call: no prompt consumed, structured evidence.
|
|
369
|
+
expect(result.status).toBe('failed');
|
|
370
|
+
expect(repairPrompts).toHaveLength(0);
|
|
371
|
+
expect(result.failureReason).toContain('repair_replay_evidence_unavailable');
|
|
372
|
+
expect(emitted.some((e) => e.eventType === 'artificer_repair_replay_evidence_unavailable')).toBe(true);
|
|
373
|
+
});
|
|
374
|
+
it('diagnosticReplay absent (replay never ran) keeps legacy repair behavior — no resolver, no fail', async () => {
|
|
375
|
+
await mkTask({ id: SCRIBE_ID, kind: 'scribe', deps: [] });
|
|
376
|
+
await succeed(SCRIBE_ID);
|
|
377
|
+
await store.upsertArtifact({
|
|
378
|
+
artifactId: SCRIBE_ART, artifactKind: 'principle', sourceTaskId: SCRIBE_ID,
|
|
379
|
+
lineageArtifactIds: [], validationStatus: 'validated',
|
|
380
|
+
contentJson: JSON.stringify({ principleDraft: { statement: 'x' } }),
|
|
381
|
+
createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(),
|
|
382
|
+
});
|
|
383
|
+
await mkTask({ id: REPAIR_ID, kind: 'artificer', deps: [SCRIBE_ID], diagnosticJson: meta({
|
|
384
|
+
dependencyTaskIds: [SCRIBE_ID],
|
|
385
|
+
repairPayload: {
|
|
386
|
+
requiredChanges: ['improve matcher'],
|
|
387
|
+
concerns: ['scope too broad'],
|
|
388
|
+
previousScore: 0.4,
|
|
389
|
+
repairIteration: 1,
|
|
390
|
+
sourceArtificerArtifactId: 'pi-art-old',
|
|
391
|
+
sourceEvaluatorTaskId: 'evaluator-old-no-replay',
|
|
392
|
+
// no diagnosticReplay — the rejecting round never ran a deterministic replay
|
|
393
|
+
},
|
|
394
|
+
}) });
|
|
395
|
+
const repairPrompts = [];
|
|
396
|
+
const artificerRepair = new ArtificerRunner({
|
|
397
|
+
stateManager,
|
|
398
|
+
runtimeAdapter: scriptedAdapter(artificerOutput(GOOD_RULE_CODE, SCRIBE_ART, REPAIR_ID), repairPrompts, 'run-repair-y'),
|
|
399
|
+
eventEmitter: emitter,
|
|
400
|
+
artifactStore: store,
|
|
401
|
+
validator: new DefaultArtificerValidator(),
|
|
402
|
+
}, { owner: 'rr-test', runtimeKind: 'test-double', pollIntervalMs: 5, timeoutMs: 5_000, effectiveConfig: flagsOffConfig() });
|
|
403
|
+
const result = await artificerRepair.run(REPAIR_ID);
|
|
404
|
+
expect(result.status).toBe('succeeded');
|
|
405
|
+
expect(repairPrompts).toHaveLength(1);
|
|
406
|
+
// No dynamic evidence block (assert on the resolved-evidence header, not
|
|
407
|
+
// the instruction paragraph which always names the block), but evaluator
|
|
408
|
+
// semantic feedback still present.
|
|
409
|
+
expect(repairPrompts[0]).not.toContain('Deterministic Replay Evidence (resolved by reference from evaluator artifact');
|
|
410
|
+
expect(repairPrompts[0]).toContain('Required changes');
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
//# sourceMappingURL=evaluator-artificer-repair-replay.test.js.map
|
package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator-artificer-repair-replay.test.js","sourceRoot":"","sources":["../../../../src/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -474,5 +474,141 @@ describe('PRI-634 R4: code-bearing + needs_revision → diagnostic replay 执行
|
|
|
474
474
|
const rp = seeded.payload;
|
|
475
475
|
expect(rp.diagnosticReplay).toEqual({ ran: true, passed: true, failedCaseCount: 0 });
|
|
476
476
|
});
|
|
477
|
+
// ── PRI-634 PR-A (SPEC §16/§17): merged real case ID uniqueness guard ──
|
|
478
|
+
// An LLM-supplied adversarial case whose caseId collides with a
|
|
479
|
+
// runtime-generated v2 case must never reach the sandbox — the evidence Map
|
|
480
|
+
// would silently overwrite and mis-attribute failures. Approved binding
|
|
481
|
+
// path fails loud (R3 terminal-state guard); needs_revision keeps its
|
|
482
|
+
// verdict, records the conflict observably, and stays evidence fail-closed.
|
|
483
|
+
it('PR-A: duplicate real caseId (LLM case collides with v2-unavailable) → conflict telemetry, no sandbox run', async () => {
|
|
484
|
+
const store = await seedLineage(codeBearingArtificerContent());
|
|
485
|
+
const calls = { count: 0 };
|
|
486
|
+
const llmCollidedCases = [{
|
|
487
|
+
caseId: 'v2-unavailable', // collides with the runtime-generated v2 case
|
|
488
|
+
attackType: 'boundary',
|
|
489
|
+
toolName: 'edit_file',
|
|
490
|
+
params: { path: '/project/src/safe.ts' },
|
|
491
|
+
expectedDecision: 'block',
|
|
492
|
+
rationale: 'adversarially crafted collision',
|
|
493
|
+
}];
|
|
494
|
+
const collisionPayload = {
|
|
495
|
+
...v1EvaluatorOutput('needs_revision'),
|
|
496
|
+
adversarialCases: llmCollidedCases,
|
|
497
|
+
};
|
|
498
|
+
const runner = makeRunner(store, {
|
|
499
|
+
gateDeps: makeGateDepsStub(calls),
|
|
500
|
+
payload: collisionPayload,
|
|
501
|
+
}, {
|
|
502
|
+
isRepairLoopEnabled: () => true,
|
|
503
|
+
seedArtificerRepairTask: async (_params) => 'repair-task-collision',
|
|
504
|
+
});
|
|
505
|
+
const result = await runner.run(EVAL_ID);
|
|
506
|
+
// sandbox never ran — the conflict is detected pre-sandbox
|
|
507
|
+
expect(calls.count).toBe(0);
|
|
508
|
+
expect(emitted.some((e) => e.eventType === 'evaluator_adversarial_replay_case_id_conflict' && e.payload.caseId === 'v2-unavailable')).toBe(true);
|
|
509
|
+
// needs_revision diagnostic path: verdict stands, task completes
|
|
510
|
+
expect(result.status).toBe('succeeded');
|
|
511
|
+
// fail-closed provenance: no diagnosticReplay evidence was produced
|
|
512
|
+
const artifacts = await store.listBySourceTaskId(EVAL_ID);
|
|
513
|
+
const principle = artifacts.find((a) => a.artifactKind === 'principle');
|
|
514
|
+
expect(principle).toBeDefined();
|
|
515
|
+
if (!principle)
|
|
516
|
+
return;
|
|
517
|
+
const parsed = JSON.parse(principle.contentJson);
|
|
518
|
+
expect(Object.hasOwn(parsed, 'adversarialResult')).toBe(false);
|
|
519
|
+
});
|
|
520
|
+
// ── PRI-634 PR-A (review P1 2026-09-02): reserved __*__ namespace guard ──
|
|
521
|
+
// A real (Artificer/LLM-supplied) trace case must not name itself
|
|
522
|
+
// `__compile__` etc. — the schema allows it, but every downstream reader
|
|
523
|
+
// partitions `__*__` IDs as system failures. Enforced pre-sandbox.
|
|
524
|
+
it('PR-A: real caseId using the reserved __compile__ sentinel → conflict telemetry, no sandbox run', async () => {
|
|
525
|
+
const store = await seedLineage(codeBearingArtificerContent());
|
|
526
|
+
const calls = { count: 0 };
|
|
527
|
+
const reservedIdCases = [{
|
|
528
|
+
caseId: '__compile__', // real LLM case squatting on the system namespace
|
|
529
|
+
attackType: 'boundary',
|
|
530
|
+
toolName: 'edit_file',
|
|
531
|
+
params: { path: '/project/src/safe.ts' },
|
|
532
|
+
expectedDecision: 'block',
|
|
533
|
+
rationale: 'adversarially crafted reserved-namespace collision',
|
|
534
|
+
}];
|
|
535
|
+
const reservedPayload = {
|
|
536
|
+
...v1EvaluatorOutput('needs_revision'),
|
|
537
|
+
adversarialCases: reservedIdCases,
|
|
538
|
+
};
|
|
539
|
+
const runner = makeRunner(store, {
|
|
540
|
+
gateDeps: makeGateDepsStub(calls),
|
|
541
|
+
payload: reservedPayload,
|
|
542
|
+
}, {
|
|
543
|
+
isRepairLoopEnabled: () => true,
|
|
544
|
+
seedArtificerRepairTask: async (_params) => 'repair-task-reserved',
|
|
545
|
+
});
|
|
546
|
+
const result = await runner.run(EVAL_ID);
|
|
547
|
+
// sandbox never ran — the reserved namespace is rejected pre-sandbox
|
|
548
|
+
expect(calls.count).toBe(0);
|
|
549
|
+
expect(emitted.some((e) => e.eventType === 'evaluator_adversarial_replay_case_id_conflict'
|
|
550
|
+
&& e.payload.caseId === '__compile__'
|
|
551
|
+
&& e.payload.violationKind === 'reserved_system_namespace')).toBe(true);
|
|
552
|
+
// needs_revision diagnostic path: verdict stands, task completes
|
|
553
|
+
expect(result.status).toBe('succeeded');
|
|
554
|
+
const artifacts = await store.listBySourceTaskId(EVAL_ID);
|
|
555
|
+
const principle = artifacts.find((a) => a.artifactKind === 'principle');
|
|
556
|
+
expect(principle).toBeDefined();
|
|
557
|
+
if (!principle)
|
|
558
|
+
return;
|
|
559
|
+
const parsed = JSON.parse(principle.contentJson);
|
|
560
|
+
expect(Object.hasOwn(parsed, 'adversarialResult')).toBe(false);
|
|
561
|
+
});
|
|
562
|
+
// ── PRI-634 PR-A (review P2 2026-09-02): bounded durable evidence ──
|
|
563
|
+
// message AND rationale must both be built from the bounded form — the
|
|
564
|
+
// unbounded raw sandbox message may not leak into the durable artifact
|
|
565
|
+
// through a second field.
|
|
566
|
+
it('PR-A: oversized failure message is bounded in BOTH message and rationale on the durable artifact', async () => {
|
|
567
|
+
const store = await seedLineage(codeBearingArtificerContent());
|
|
568
|
+
const longMessage = `x`.repeat(500) + ' tail-evidence-probe';
|
|
569
|
+
const gateDeps = {
|
|
570
|
+
evaluateInSandbox: (_code, _trace) => ({
|
|
571
|
+
success: false,
|
|
572
|
+
failedCases: [{
|
|
573
|
+
caseId: 'v2-unavailable',
|
|
574
|
+
errorType: 'runtime_error',
|
|
575
|
+
message: longMessage,
|
|
576
|
+
}],
|
|
577
|
+
executionTimeMs: 1,
|
|
578
|
+
forbiddenPatternViolations: [],
|
|
579
|
+
}),
|
|
580
|
+
};
|
|
581
|
+
const runner = makeRunner(store, {
|
|
582
|
+
gateDeps,
|
|
583
|
+
payload: v1EvaluatorOutput('needs_revision'),
|
|
584
|
+
}, {
|
|
585
|
+
isRepairLoopEnabled: () => true,
|
|
586
|
+
seedArtificerRepairTask: async (_params) => 'repair-task-bounded',
|
|
587
|
+
});
|
|
588
|
+
const result = await runner.run(EVAL_ID);
|
|
589
|
+
expect(result.status).toBe('succeeded');
|
|
590
|
+
const artifacts = await store.listBySourceTaskId(EVAL_ID);
|
|
591
|
+
const principle = artifacts.find((a) => a.artifactKind === 'principle');
|
|
592
|
+
expect(principle).toBeDefined();
|
|
593
|
+
if (!principle)
|
|
594
|
+
return;
|
|
595
|
+
const parsed = JSON.parse(principle.contentJson);
|
|
596
|
+
const failedCase = parsed.adversarialResult?.failedCases?.[0];
|
|
597
|
+
expect(failedCase).toBeDefined();
|
|
598
|
+
if (!failedCase)
|
|
599
|
+
return;
|
|
600
|
+
const boundedMessage = failedCase.message;
|
|
601
|
+
const boundedRationale = failedCase.rationale;
|
|
602
|
+
expect(failedCase.caseId).toBe('v2-unavailable');
|
|
603
|
+
if (boundedMessage === undefined || boundedRationale === undefined) {
|
|
604
|
+
throw new Error('durable failedCase must carry bounded message and rationale');
|
|
605
|
+
}
|
|
606
|
+
expect(boundedMessage.length).toBeLessThanOrEqual(301); // 300 + ellipsis
|
|
607
|
+
expect(boundedMessage).not.toContain('tail-evidence-probe');
|
|
608
|
+
expect(boundedRationale.length).toBeLessThanOrEqual(320); // errorType prefix + bounded message
|
|
609
|
+
expect(boundedRationale).not.toContain('tail-evidence-probe');
|
|
610
|
+
// no fabricated decision on a throw-style failure
|
|
611
|
+
expect(failedCase.actualDecision).toBeUndefined();
|
|
612
|
+
});
|
|
477
613
|
});
|
|
478
614
|
//# sourceMappingURL=evaluator-gate-authority.test.js.map
|