@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.
Files changed (83) hide show
  1. package/dist/runtime-v2/__tests__/pain-ingress-persistence.test.d.ts +2 -0
  2. package/dist/runtime-v2/__tests__/pain-ingress-persistence.test.d.ts.map +1 -0
  3. package/dist/runtime-v2/__tests__/pain-ingress-persistence.test.js +276 -0
  4. package/dist/runtime-v2/__tests__/pain-ingress-persistence.test.js.map +1 -0
  5. package/dist/runtime-v2/__tests__/pain-ingress-shared-semantics.test.d.ts +2 -0
  6. package/dist/runtime-v2/__tests__/pain-ingress-shared-semantics.test.d.ts.map +1 -0
  7. package/dist/runtime-v2/__tests__/pain-ingress-shared-semantics.test.js +131 -0
  8. package/dist/runtime-v2/__tests__/pain-ingress-shared-semantics.test.js.map +1 -0
  9. package/dist/runtime-v2/__tests__/pain-outcome-convergence.test.d.ts +2 -0
  10. package/dist/runtime-v2/__tests__/pain-outcome-convergence.test.d.ts.map +1 -0
  11. package/dist/runtime-v2/__tests__/pain-outcome-convergence.test.js +126 -0
  12. package/dist/runtime-v2/__tests__/pain-outcome-convergence.test.js.map +1 -0
  13. package/dist/runtime-v2/__tests__/pain-signal-bridge-execute-pending.test.js +95 -0
  14. package/dist/runtime-v2/__tests__/pain-signal-bridge-execute-pending.test.js.map +1 -1
  15. package/dist/runtime-v2/activation/__tests__/production-gate-deps.test.js +69 -0
  16. package/dist/runtime-v2/activation/__tests__/production-gate-deps.test.js.map +1 -1
  17. package/dist/runtime-v2/activation/production-gate-deps.d.ts.map +1 -1
  18. package/dist/runtime-v2/activation/production-gate-deps.js +13 -46
  19. package/dist/runtime-v2/activation/production-gate-deps.js.map +1 -1
  20. package/dist/runtime-v2/index.d.ts +9 -1
  21. package/dist/runtime-v2/index.d.ts.map +1 -1
  22. package/dist/runtime-v2/index.js +6 -0
  23. package/dist/runtime-v2/index.js.map +1 -1
  24. package/dist/runtime-v2/internalization/__tests__/adversarial-feedback.test.js +9 -0
  25. package/dist/runtime-v2/internalization/__tests__/adversarial-feedback.test.js.map +1 -1
  26. package/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js +15 -5
  27. package/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js.map +1 -1
  28. package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.d.ts +2 -0
  29. package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.d.ts.map +1 -0
  30. package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.js +413 -0
  31. package/dist/runtime-v2/internalization/__tests__/evaluator-artificer-repair-replay.test.js.map +1 -0
  32. package/dist/runtime-v2/internalization/__tests__/evaluator-gate-authority.test.js +136 -0
  33. package/dist/runtime-v2/internalization/__tests__/evaluator-gate-authority.test.js.map +1 -1
  34. package/dist/runtime-v2/internalization/__tests__/repair-replay-resolver.test.d.ts +2 -0
  35. package/dist/runtime-v2/internalization/__tests__/repair-replay-resolver.test.d.ts.map +1 -0
  36. package/dist/runtime-v2/internalization/__tests__/repair-replay-resolver.test.js +340 -0
  37. package/dist/runtime-v2/internalization/__tests__/repair-replay-resolver.test.js.map +1 -0
  38. package/dist/runtime-v2/internalization/adversarial-feedback.d.ts.map +1 -1
  39. package/dist/runtime-v2/internalization/adversarial-feedback.js +7 -1
  40. package/dist/runtime-v2/internalization/adversarial-feedback.js.map +1 -1
  41. package/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +9 -2
  42. package/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
  43. package/dist/runtime-v2/internalization/artificer-prompt-builder.js +19 -1
  44. package/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
  45. package/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
  46. package/dist/runtime-v2/internalization/artificer-runner.js +84 -7
  47. package/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
  48. package/dist/runtime-v2/internalization/evaluator-output.d.ts +18 -1
  49. package/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
  50. package/dist/runtime-v2/internalization/evaluator-output.js +12 -2
  51. package/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
  52. package/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
  53. package/dist/runtime-v2/internalization/evaluator-runner.js +99 -5
  54. package/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
  55. package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.d.ts +18 -1
  56. package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.d.ts.map +1 -1
  57. package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.js +20 -0
  58. package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.js.map +1 -1
  59. package/dist/runtime-v2/internalization/repair-replay-resolver.d.ts +112 -0
  60. package/dist/runtime-v2/internalization/repair-replay-resolver.d.ts.map +1 -0
  61. package/dist/runtime-v2/internalization/repair-replay-resolver.js +332 -0
  62. package/dist/runtime-v2/internalization/repair-replay-resolver.js.map +1 -0
  63. package/dist/runtime-v2/pain-ingress-payload.d.ts +207 -0
  64. package/dist/runtime-v2/pain-ingress-payload.d.ts.map +1 -0
  65. package/dist/runtime-v2/pain-ingress-payload.js +340 -0
  66. package/dist/runtime-v2/pain-ingress-payload.js.map +1 -0
  67. package/dist/runtime-v2/pain-ingress.d.ts +61 -0
  68. package/dist/runtime-v2/pain-ingress.d.ts.map +1 -0
  69. package/dist/runtime-v2/pain-ingress.js +163 -0
  70. package/dist/runtime-v2/pain-ingress.js.map +1 -0
  71. package/dist/runtime-v2/pain-signal-bridge.d.ts +39 -1
  72. package/dist/runtime-v2/pain-signal-bridge.d.ts.map +1 -1
  73. package/dist/runtime-v2/pain-signal-bridge.js +163 -8
  74. package/dist/runtime-v2/pain-signal-bridge.js.map +1 -1
  75. package/dist/runtime-v2/pain-to-principle-service.d.ts +8 -1
  76. package/dist/runtime-v2/pain-to-principle-service.d.ts.map +1 -1
  77. package/dist/runtime-v2/pain-to-principle-service.js +3 -0
  78. package/dist/runtime-v2/pain-to-principle-service.js.map +1 -1
  79. package/dist/telemetry-event.d.ts +2 -2
  80. package/dist/telemetry-event.d.ts.map +1 -1
  81. package/dist/telemetry-event.js +14 -0
  82. package/dist/telemetry-event.js.map +1 -1
  83. package/package.json +1 -1
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Repair Replay Resolver — PRI-634 PR-A (SPEC Slice B, §23–§30).
3
+ *
4
+ * Resolves the deterministic replay evidence a repair round needs, BY
5
+ * REFERENCE, from the one durable authority: the source Evaluator artifact's
6
+ * runtime-owned `adversarialResult`. The resolved RepairReplayContext exists
7
+ * only in prompt context — it is never persisted, never a second fact store,
8
+ * and RepairPayload stays a bounded control payload.
9
+ *
10
+ * Pipeline:
11
+ * RepairPayload.sourceEvaluatorTaskId
12
+ * → evaluator task's durable completionIntent.sourceRunId (deterministic
13
+ * artifact identity: pi-art-<taskId>-<runId>)
14
+ * → PiArtifactStore.getArtifactById (fallback: listBySourceTaskId when
15
+ * the intent is absent — exactly-one rule, otherwise fail loud)
16
+ * → runtime-validate contentJson.adversarialResult (rc-1/rc-4)
17
+ * → normalize legacy actualDecision=<errorType> representation (SPEC §21)
18
+ * → partition trace failures / system failures / global violations
19
+ * → bounded deterministic stratified selection (SPEC §30)
20
+ *
21
+ * Trust boundary: artifact contentJson is durable-but-untrusted at read time.
22
+ * Every field access uses Object.hasOwn (rc-5) and typeof/Array.isArray
23
+ * guards (rc-4) — no `as` casts. Missing or ambiguous evidence fails loud
24
+ * with a structured reason (rc-3/rc-9) so the caller can refuse a blind
25
+ * repair retry (SPEC §27).
26
+ */
27
+ import type { TaskRecord } from '../task-status.js';
28
+ import type { PIArtifactStore } from './pi-artifact.js';
29
+ /**
30
+ * Repair-prompt budget cap for replay evidence (SPEC §29): at most this many
31
+ * failure entries enter the Artificer repair prompt. 16 entries × ~30 tokens
32
+ * stays comfortably inside the existing prompt budget.
33
+ */
34
+ export declare const MAX_REPLAY_FAILURES_IN_REPAIR = 16;
35
+ export interface ReplayFailureEvidence {
36
+ readonly caseId: string;
37
+ readonly attackType?: string;
38
+ readonly expectedDecision?: string;
39
+ /** Real decision the rule returned; absent for timeout/throw failures. */
40
+ readonly actualDecision?: string;
41
+ readonly errorType: string;
42
+ readonly message?: string;
43
+ }
44
+ export interface RepairReplayContext {
45
+ readonly sourceEvaluatorTaskId: string;
46
+ readonly sourceEvaluatorArtifactId: string;
47
+ /** True — the presence of a runtime-owned adversarialResult means replay ran. */
48
+ readonly ran: boolean;
49
+ readonly passed: boolean;
50
+ /** Total durable failures (pre-selection). */
51
+ readonly failedCaseCount: number;
52
+ /** Selected trace-case failures (bounded, mismatch-first stratified). */
53
+ readonly traceFailures: readonly ReplayFailureEvidence[];
54
+ /** Selected system-sentinel failures (bounded; excludes forbidden patterns). */
55
+ readonly systemFailures: readonly ReplayFailureEvidence[];
56
+ /** Selected forbidden-pattern violations (bounded, shared budget). */
57
+ readonly globalViolations: readonly string[];
58
+ /** Total durable forbidden-pattern violations (pre-selection). */
59
+ readonly globalViolationCount: number;
60
+ /** True when bounded selection omitted any durable failure or violation. */
61
+ readonly truncated: boolean;
62
+ }
63
+ export type RepairReplayResolutionFailureReason = 'task_missing' | 'artifact_missing' | 'artifact_ambiguous' | 'adversarial_result_missing' | 'adversarial_result_invalid';
64
+ export type RepairReplayResolution = {
65
+ readonly ok: true;
66
+ readonly context: RepairReplayContext;
67
+ } | {
68
+ readonly ok: false;
69
+ readonly reason: RepairReplayResolutionFailureReason;
70
+ readonly detail: string;
71
+ };
72
+ export interface RepairReplayResolverDeps {
73
+ readonly artifactStore: Pick<PIArtifactStore, 'getArtifactById' | 'listBySourceTaskId'>;
74
+ readonly getTask: (taskId: string) => Promise<TaskRecord | null>;
75
+ }
76
+ /**
77
+ * Bounded deterministic stratified selection (SPEC §30 as tightened by review
78
+ * 2026-09-02). Trace failures, system failures, and global violations share
79
+ * ONE capacity budget — no evidence class can bypass the prompt bound:
80
+ *
81
+ * 1. system failure representatives (stable order);
82
+ * 2. one global-violation representative for the whole violation group;
83
+ * 3. true decision mismatches FIRST by expected axis — at least one
84
+ * expected=allow, one expected=block, one expected=propose_correction
85
+ * representative each (when present) — so low-value runtime failures can
86
+ * never evict every behavioral mismatch from the prompt;
87
+ * 4. remaining errorType × expectedDecision group representatives
88
+ * (stable first-occurrence order, mismatch-preferring);
89
+ * 5. stable-order fill over trace → system → remaining violations;
90
+ * 6. truncated=true when anything was omitted.
91
+ */
92
+ export declare function selectBoundedReplayFailures(params: {
93
+ traceFailures: readonly ReplayFailureEvidence[];
94
+ systemFailures: readonly ReplayFailureEvidence[];
95
+ globalViolations: readonly string[];
96
+ capacity: number;
97
+ }): {
98
+ readonly selectedTrace: readonly ReplayFailureEvidence[];
99
+ readonly selectedSystem: readonly ReplayFailureEvidence[];
100
+ readonly selectedGlobalViolations: readonly string[];
101
+ readonly truncated: boolean;
102
+ };
103
+ /**
104
+ * Resolve the bounded, normalized replay-evidence context for a repair round.
105
+ * Pure read + transform: no writes, no telemetry side effects — callers own
106
+ * observability.
107
+ */
108
+ export declare function resolveRepairReplayContext(params: {
109
+ readonly sourceEvaluatorTaskId: string;
110
+ readonly deps: RepairReplayResolverDeps;
111
+ }): Promise<RepairReplayResolution>;
112
+ //# sourceMappingURL=repair-replay-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair-replay-resolver.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/repair-replay-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,332 @@
1
+ import { hydratePITaskRecord } from './pitask-metadata.js';
2
+ /** Sandbox error enums that legacy artifacts stored inside actualDecision. */
3
+ const LEGACY_SANDBOX_ERROR_TYPES = new Set([
4
+ 'forbidden_pattern',
5
+ 'syntax_error',
6
+ 'runtime_error',
7
+ 'timeout',
8
+ 'validation_failed',
9
+ 'unknown',
10
+ ]);
11
+ /** Real decisions a rule can return — never valid errorType values. */
12
+ const RULEHOST_DECISIONS = new Set([
13
+ 'allow',
14
+ 'block',
15
+ 'requireApproval',
16
+ 'auto_correct',
17
+ ]);
18
+ /** System sentinel prefix/suffix convention (SPEC §17): `__name__`. */
19
+ function isSystemSentinelCaseId(caseId) {
20
+ return caseId.startsWith('__') && caseId.endsWith('__') && caseId.length > 4;
21
+ }
22
+ /**
23
+ * Repair-prompt budget cap for replay evidence (SPEC §29): at most this many
24
+ * failure entries enter the Artificer repair prompt. 16 entries × ~30 tokens
25
+ * stays comfortably inside the existing prompt budget.
26
+ */
27
+ export const MAX_REPLAY_FAILURES_IN_REPAIR = 16;
28
+ function isRecord(value) {
29
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
30
+ }
31
+ function optionalNonEmptyString(value) {
32
+ return typeof value === 'string' && value.trim() !== '' ? value : undefined;
33
+ }
34
+ /**
35
+ * Normalize one durable failed-case entry (rc-4: element-level validation).
36
+ *
37
+ * Legacy representation (pre PR-A): `actualDecision` carries a sandbox error
38
+ * enum and no `errorType` exists → errorType moves over, actualDecision is
39
+ * dropped (SPEC §21 — readers normalize, no migration).
40
+ *
41
+ * Current representation: `errorType` is authoritative; `actualDecision`
42
+ * appears only when a real decision mismatched and must not be an error enum.
43
+ * Entries that fail structural validation are invalid — the caller fails
44
+ * loud rather than silently dropping evidence (rc-3).
45
+ */
46
+ /** Repair-prompt budget cap for a single failure message (SPEC §23). */
47
+ const MAX_EVIDENCE_MESSAGE_LENGTH = 300;
48
+ function boundMessage(message) {
49
+ return message.length > MAX_EVIDENCE_MESSAGE_LENGTH
50
+ ? `${message.slice(0, MAX_EVIDENCE_MESSAGE_LENGTH)}…`
51
+ : message;
52
+ }
53
+ function normalizeFailedCaseEntry(entry) {
54
+ if (!isRecord(entry))
55
+ return null;
56
+ const caseId = optionalNonEmptyString(entry.caseId);
57
+ if (caseId === undefined)
58
+ return null;
59
+ const rawErrorType = optionalNonEmptyString(entry.errorType);
60
+ const rawActual = optionalNonEmptyString(entry.actualDecision);
61
+ let errorType = rawErrorType;
62
+ let actualDecision = rawActual;
63
+ if (errorType === undefined && rawActual !== undefined) {
64
+ if (LEGACY_SANDBOX_ERROR_TYPES.has(rawActual)) {
65
+ // Legacy drift: actualDecision held the error classification.
66
+ errorType = rawActual;
67
+ actualDecision = undefined;
68
+ }
69
+ else if (RULEHOST_DECISIONS.has(rawActual)) {
70
+ // Legacy decision-mismatch entry: the mismatch was a validation failure.
71
+ errorType = 'validation_failed';
72
+ }
73
+ else {
74
+ errorType = 'unknown';
75
+ }
76
+ }
77
+ if (errorType === undefined)
78
+ errorType = 'unknown';
79
+ // Defense-in-depth on current-shape entries: an errorType value inside
80
+ // actualDecision is always reclassification drift, never a real decision.
81
+ if (actualDecision !== undefined && LEGACY_SANDBOX_ERROR_TYPES.has(actualDecision)) {
82
+ actualDecision = undefined;
83
+ }
84
+ const rationale = optionalNonEmptyString(entry.rationale);
85
+ const message = optionalNonEmptyString(entry.message) ?? rationale;
86
+ return {
87
+ caseId,
88
+ attackType: optionalNonEmptyString(entry.attackType),
89
+ expectedDecision: optionalNonEmptyString(entry.expectedDecision),
90
+ ...(actualDecision !== undefined ? { actualDecision } : {}),
91
+ errorType,
92
+ ...(message !== undefined ? { message: boundMessage(message) } : {}),
93
+ };
94
+ }
95
+ /**
96
+ * Bounded deterministic stratified selection (SPEC §30 as tightened by review
97
+ * 2026-09-02). Trace failures, system failures, and global violations share
98
+ * ONE capacity budget — no evidence class can bypass the prompt bound:
99
+ *
100
+ * 1. system failure representatives (stable order);
101
+ * 2. one global-violation representative for the whole violation group;
102
+ * 3. true decision mismatches FIRST by expected axis — at least one
103
+ * expected=allow, one expected=block, one expected=propose_correction
104
+ * representative each (when present) — so low-value runtime failures can
105
+ * never evict every behavioral mismatch from the prompt;
106
+ * 4. remaining errorType × expectedDecision group representatives
107
+ * (stable first-occurrence order, mismatch-preferring);
108
+ * 5. stable-order fill over trace → system → remaining violations;
109
+ * 6. truncated=true when anything was omitted.
110
+ */
111
+ export function selectBoundedReplayFailures(params) {
112
+ const capacity = Math.max(0, params.capacity);
113
+ let remaining = capacity;
114
+ const chosenFailures = new Set();
115
+ const chosenViolations = new Set();
116
+ // Selected failures are recorded in SELECTION PRIORITY order so the repair
117
+ // prompt renders behavioral mismatches before raw structural errors.
118
+ const traceIdentity = new Set(params.traceFailures);
119
+ const orderedSelected = [];
120
+ const takeFailure = (failure) => {
121
+ if (remaining <= 0 || chosenFailures.has(failure))
122
+ return;
123
+ chosenFailures.add(failure);
124
+ orderedSelected.push(failure);
125
+ remaining -= 1;
126
+ };
127
+ const takeViolation = (violation) => {
128
+ if (remaining <= 0 || chosenViolations.has(violation))
129
+ return;
130
+ chosenViolations.add(violation);
131
+ remaining -= 1;
132
+ };
133
+ // 1. system representatives first.
134
+ for (const systemFailure of params.systemFailures) {
135
+ if (remaining <= 0)
136
+ break;
137
+ takeFailure(systemFailure);
138
+ }
139
+ // 2. one global-violation representative.
140
+ const [firstViolation] = params.globalViolations;
141
+ if (firstViolation !== undefined)
142
+ takeViolation(firstViolation);
143
+ // 3. decision mismatches by expected axis (canonical decision order).
144
+ const mismatchByExpected = new Map();
145
+ for (const failure of params.traceFailures) {
146
+ if (failure.actualDecision === undefined)
147
+ continue;
148
+ const key = failure.expectedDecision ?? 'unknown';
149
+ if (!mismatchByExpected.has(key))
150
+ mismatchByExpected.set(key, failure);
151
+ }
152
+ for (const expectedKey of ['allow', 'block', 'propose_correction']) {
153
+ if (remaining <= 0)
154
+ break;
155
+ const representative = mismatchByExpected.get(expectedKey);
156
+ if (representative !== undefined)
157
+ takeFailure(representative);
158
+ }
159
+ // 4. remaining group representatives (mismatch-preferring, stable order).
160
+ const groups = new Map();
161
+ for (const failure of params.traceFailures) {
162
+ const key = `${failure.errorType}×${failure.expectedDecision ?? 'unknown'}`;
163
+ const existing = groups.get(key);
164
+ if (existing === undefined || (existing.actualDecision === undefined && failure.actualDecision !== undefined)) {
165
+ groups.set(key, failure);
166
+ }
167
+ }
168
+ for (const representative of groups.values()) {
169
+ if (remaining <= 0)
170
+ break;
171
+ takeFailure(representative);
172
+ }
173
+ // 5. stable-order fill: trace → system → remaining violations.
174
+ for (const failure of [...params.traceFailures, ...params.systemFailures]) {
175
+ if (remaining <= 0)
176
+ break;
177
+ takeFailure(failure);
178
+ }
179
+ for (const violation of params.globalViolations) {
180
+ if (remaining <= 0)
181
+ break;
182
+ takeViolation(violation);
183
+ }
184
+ const total = params.traceFailures.length + params.systemFailures.length + params.globalViolations.length;
185
+ const selectedCount = chosenFailures.size + chosenViolations.size;
186
+ return {
187
+ selectedTrace: orderedSelected.filter((f) => traceIdentity.has(f)),
188
+ selectedSystem: orderedSelected.filter((f) => !traceIdentity.has(f)),
189
+ selectedGlobalViolations: params.globalViolations.filter((v) => chosenViolations.has(v)),
190
+ truncated: selectedCount < total,
191
+ };
192
+ }
193
+ /**
194
+ * Resolve the authoritative Evaluator artifact for a repair round.
195
+ *
196
+ * Selection authority (SPEC §26, tightened by review 2026-09-02): the
197
+ * evaluator task's durable completionIntent records the exact run that
198
+ * produced the verdict, and the artifact ID is deterministically
199
+ * `pi-art-<taskId>-<runId>`. When the intent exists, that artifact IS the
200
+ * authority — if it is missing we FAIL LOUD; another run's artifact may never
201
+ * become a fallback authority. Only when no intent exists (legacy tasks) does
202
+ * the exactly-one list rule apply: zero or many → fail loud, never a
203
+ * positional pick.
204
+ */
205
+ async function resolveAuthoritativeEvaluatorArtifact(sourceEvaluatorTaskId, deps) {
206
+ const task = await deps.getTask(sourceEvaluatorTaskId);
207
+ if (!task) {
208
+ return { ok: false, reason: 'task_missing', detail: `evaluator task ${sourceEvaluatorTaskId} not found` };
209
+ }
210
+ const piTask = hydratePITaskRecord(task);
211
+ const intentRunId = piTask?.completionIntent?.sourceRunId;
212
+ if (typeof intentRunId === 'string' && intentRunId.trim() !== '') {
213
+ const artifactId = `pi-art-${sourceEvaluatorTaskId}-${intentRunId}`;
214
+ const artifact = await deps.artifactStore.getArtifactById(artifactId);
215
+ if (artifact) {
216
+ return { ok: true, artifactId: artifact.artifactId, contentJson: artifact.contentJson };
217
+ }
218
+ // The durable authority is KNOWN — a different run's artifact must never
219
+ // be silently promoted into its place (P1 review 2026-09-02).
220
+ return {
221
+ ok: false,
222
+ reason: 'artifact_missing',
223
+ detail: `completionIntent names run ${intentRunId} as authoritative but artifact ${artifactId} does not exist — refusing cross-run fallback`,
224
+ };
225
+ }
226
+ const artifacts = (await deps.artifactStore.listBySourceTaskId(sourceEvaluatorTaskId))
227
+ .filter((a) => a.artifactKind === 'principle');
228
+ if (artifacts.length === 0) {
229
+ return {
230
+ ok: false,
231
+ reason: 'artifact_missing',
232
+ detail: `no principle artifact for evaluator task ${sourceEvaluatorTaskId}`,
233
+ };
234
+ }
235
+ if (artifacts.length > 1) {
236
+ return {
237
+ ok: false,
238
+ reason: 'artifact_ambiguous',
239
+ detail: `evaluator task ${sourceEvaluatorTaskId} has ${artifacts.length} principle artifacts and no resolvable completion intent — authority is ambiguous: ${artifacts.map((a) => a.artifactId).sort().join(', ')}`,
240
+ };
241
+ }
242
+ const [only] = artifacts;
243
+ if (!only) {
244
+ return { ok: false, reason: 'artifact_missing', detail: `no principle artifact for evaluator task ${sourceEvaluatorTaskId}` };
245
+ }
246
+ return { ok: true, artifactId: only.artifactId, contentJson: only.contentJson };
247
+ }
248
+ /**
249
+ * Resolve the bounded, normalized replay-evidence context for a repair round.
250
+ * Pure read + transform: no writes, no telemetry side effects — callers own
251
+ * observability.
252
+ */
253
+ export async function resolveRepairReplayContext(params) {
254
+ const { sourceEvaluatorTaskId, deps } = params;
255
+ const artifactResolution = await resolveAuthoritativeEvaluatorArtifact(sourceEvaluatorTaskId, deps);
256
+ if (!artifactResolution.ok) {
257
+ return artifactResolution;
258
+ }
259
+ const { artifactId, contentJson } = artifactResolution;
260
+ let parsed;
261
+ try {
262
+ parsed = JSON.parse(contentJson);
263
+ }
264
+ catch {
265
+ return { ok: false, reason: 'adversarial_result_invalid', detail: `evaluator artifact ${artifactId} contentJson is unparseable` };
266
+ }
267
+ if (!isRecord(parsed) || !Object.hasOwn(parsed, 'adversarialResult')) {
268
+ return { ok: false, reason: 'adversarial_result_missing', detail: `evaluator artifact ${artifactId} carries no adversarialResult` };
269
+ }
270
+ const { adversarialResult } = parsed;
271
+ if (!isRecord(adversarialResult) || typeof adversarialResult.passed !== 'boolean') {
272
+ return { ok: false, reason: 'adversarial_result_invalid', detail: `evaluator artifact ${artifactId} adversarialResult is malformed (passed must be a boolean)` };
273
+ }
274
+ if (!Object.hasOwn(adversarialResult, 'failedCases') || !Array.isArray(adversarialResult.failedCases)) {
275
+ return { ok: false, reason: 'adversarial_result_invalid', detail: `evaluator artifact ${artifactId} adversarialResult.failedCases is missing or not an array` };
276
+ }
277
+ // rc-4: validate every element; any structurally invalid entry fails loud —
278
+ // dropping evidence silently would re-create the blind-retry hole.
279
+ const normalized = [];
280
+ for (const [index, entry] of adversarialResult.failedCases.entries()) {
281
+ const normalizedEntry = normalizeFailedCaseEntry(entry);
282
+ if (normalizedEntry === null) {
283
+ return {
284
+ ok: false,
285
+ reason: 'adversarial_result_invalid',
286
+ detail: `evaluator artifact ${artifactId} adversarialResult.failedCases[${index}] is structurally invalid`,
287
+ };
288
+ }
289
+ normalized.push(normalizedEntry);
290
+ }
291
+ // Partition by identity (SPEC §17/§18): real trace IDs vs system sentinels
292
+ // vs code-level global violations. Forbidden-pattern entries are counted
293
+ // ONLY as global violations — never also as system failures (review P2
294
+ // 2026-09-02: no double-count in the prompt) — and share the bounded
295
+ // selection budget with everything else.
296
+ const traceFailures = [];
297
+ const systemFailures = [];
298
+ const globalViolations = [];
299
+ for (const failure of normalized) {
300
+ if (failure.caseId === '__forbidden_pattern__') {
301
+ globalViolations.push(failure.message ?? `forbidden pattern (${failure.errorType})`);
302
+ continue;
303
+ }
304
+ if (isSystemSentinelCaseId(failure.caseId)) {
305
+ systemFailures.push(failure);
306
+ continue;
307
+ }
308
+ traceFailures.push(failure);
309
+ }
310
+ const selection = selectBoundedReplayFailures({
311
+ traceFailures,
312
+ systemFailures,
313
+ globalViolations,
314
+ capacity: MAX_REPLAY_FAILURES_IN_REPAIR,
315
+ });
316
+ return {
317
+ ok: true,
318
+ context: {
319
+ sourceEvaluatorTaskId,
320
+ sourceEvaluatorArtifactId: artifactId,
321
+ ran: true,
322
+ passed: adversarialResult.passed,
323
+ failedCaseCount: normalized.length,
324
+ traceFailures: selection.selectedTrace,
325
+ systemFailures: selection.selectedSystem,
326
+ globalViolations: selection.selectedGlobalViolations,
327
+ globalViolationCount: globalViolations.length,
328
+ truncated: selection.truncated,
329
+ },
330
+ };
331
+ }
332
+ //# sourceMappingURL=repair-replay-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair-replay-resolver.js","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/repair-replay-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Pain Ingress shared invariants + persisted payload contract — PRI-642.
3
+ *
4
+ * This module is THE single source for:
5
+ * - the report field parsers (origin / correlation / evidence / score)
6
+ * shared by write-time evaluation and persisted-payload re-entry;
7
+ * - the origin/correlation invariant (`validateOriginCorrelationInvariant`)
8
+ * — the valid-combination rules of SPEC §8.2 that must never diverge
9
+ * between write time and re-entry;
10
+ * - the sentinel session constant (frozen decision #4);
11
+ * - the versioned `painIngress.v1` persisted namespace (SPEC §9) written
12
+ * by PainSignalBridge.buildDiagnosticJson beside the legacy top-level
13
+ * fields, and re-validated by executePendingDiagnosis / retry paths.
14
+ *
15
+ * INVARIANT EQUIVALENCE (review blocker 2): re-entry validation is NOT
16
+ * weaker than write-time validation. parsePainIngressV1Payload shares the
17
+ * field parsers and the invariant with evaluatePainIngress
18
+ * (pain-ingress.ts), so every state illegal at write time — sentinel
19
+ * session ids, empty "available" evidence, impossible origin/correlation
20
+ * combinations — is also rejected on re-entry.
21
+ *
22
+ * Legacy compatibility (SPEC §9): payloads WITHOUT a painIngress.v1 block
23
+ * keep the tolerant legacy normalization branch in pain-signal-bridge.ts;
24
+ * this strictness applies only to payloads CLAIMING the v1 namespace.
25
+ *
26
+ * Pure module — no I/O. @principles/host-runtime and other adapters depend
27
+ * on core; core depends on no adapter.
28
+ */
29
+ import type { PainProvenance } from './admission-gate.js';
30
+ export declare const PAIN_INGRESS_PAYLOAD_VERSION = "v1";
31
+ export type PainIngressOriginV1 = {
32
+ kind: 'owner_manual';
33
+ channel: 'openclaw_command' | 'cli_explicit_session' | 'external_cli_unbound';
34
+ } | {
35
+ kind: 'automatic_hook';
36
+ source: string;
37
+ };
38
+ export type PainIngressCorrelationV1 = {
39
+ status: 'bound';
40
+ hostKind: 'openclaw';
41
+ sessionId: string;
42
+ traceId?: string;
43
+ } | {
44
+ status: 'bound';
45
+ hostKind: 'codex';
46
+ rootSessionId: string;
47
+ rolloutIdentity: string;
48
+ logicalObservationKey: string;
49
+ hostTurnId: string;
50
+ traceId?: string;
51
+ } | {
52
+ status: 'unbound';
53
+ reason: 'external_cli' | 'missing_host_session';
54
+ };
55
+ export type PainIngressEvidenceClassV1 = {
56
+ status: 'available';
57
+ entryCount: number;
58
+ } | {
59
+ status: 'unavailable';
60
+ reason: 'trajectory_unavailable' | 'session_not_found' | 'empty_trajectory' | 'evidence_read_failed' | 'evidence_invalid'
61
+ /** Unbound Owner reports never consult a trajectory — no evidence is sought. */
62
+ | 'not_applicable_unbound';
63
+ };
64
+ export type PainEvidenceUnavailableReason = 'trajectory_unavailable' | 'session_not_found' | 'empty_trajectory' | 'evidence_read_failed' | 'evidence_invalid'
65
+ /** Unbound Owner reports never consult a trajectory — no evidence is sought. */
66
+ | 'not_applicable_unbound';
67
+ export interface IngressEvidenceEntry {
68
+ kind: 'behavior_trace' | 'system_event';
69
+ sourceRef: string;
70
+ note: string;
71
+ }
72
+ export type PainEvidenceBundle = {
73
+ status: 'available';
74
+ entries: readonly [IngressEvidenceEntry, ...IngressEvidenceEntry[]];
75
+ } | {
76
+ status: 'unavailable';
77
+ reason: PainEvidenceUnavailableReason;
78
+ };
79
+ export type PainOrigin = PainIngressOriginV1;
80
+ export type PainCorrelation = PainIngressCorrelationV1;
81
+ export interface PainIngressReport {
82
+ identity: {
83
+ kind: 'manual_pain_id';
84
+ painId: string;
85
+ } | {
86
+ kind: 'host_observation';
87
+ observationId: string;
88
+ };
89
+ painType: 'tool_failure' | 'subagent_error' | 'user_frustration';
90
+ source: string;
91
+ reason: string;
92
+ score?: number;
93
+ origin: PainOrigin;
94
+ correlation: PainCorrelation;
95
+ evidence: PainEvidenceBundle;
96
+ }
97
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
98
+ /**
99
+ * Sentinel session ids are never real correlations (frozen decision #4).
100
+ * Import this constant instead of re-declaring the set in another module.
101
+ */
102
+ export declare const SENTINEL_SESSION_IDS: ReadonlySet<string>;
103
+ export declare function isSentinelSessionId(value: string): boolean;
104
+ export declare function parseOrigin(value: unknown): PainOrigin | null;
105
+ /**
106
+ * THE correlation parser — used by report validation (write time) and the
107
+ * persisted-payload validator (re-entry) so sentinel rejection and lineage
108
+ * completeness cannot drift between the two.
109
+ */
110
+ export declare function parseCorrelation(value: unknown): {
111
+ value: PainCorrelation;
112
+ error?: undefined;
113
+ } | {
114
+ value?: undefined;
115
+ error: string;
116
+ };
117
+ export declare function parseEvidence(value: unknown): {
118
+ value: PainEvidenceBundle;
119
+ error?: undefined;
120
+ } | {
121
+ value?: undefined;
122
+ error: string;
123
+ };
124
+ /** rc-3/rc-9: a present-but-invalid score is rejected, not silently dropped. */
125
+ export declare function parseScore(value: unknown): {
126
+ score: number | undefined;
127
+ scoreInvalid?: undefined;
128
+ } | {
129
+ score: undefined;
130
+ scoreInvalid: true;
131
+ };
132
+ export type PainIngressParseResult = {
133
+ ok: true;
134
+ report: PainIngressReport;
135
+ } | {
136
+ ok: false;
137
+ reasonCode: string;
138
+ message: string;
139
+ };
140
+ /**
141
+ * Validate an untrusted report (parsed JSON / host payload) into a typed
142
+ * PainIngressReport. Fails loud with a structured reasonCode (rc-3); uses
143
+ * the SAME field parsers and invariant as the persisted-payload validator
144
+ * (rc-1/rc-2/rc-3/rc-4).
145
+ */
146
+ export declare function parsePainIngressReport(input: unknown): PainIngressParseResult;
147
+ /**
148
+ * Origin/correlation combinations the matrix (SPEC §8.2) declares invalid.
149
+ * Shared by evaluatePainIngress (write time) and parsePainIngressV1Payload
150
+ * (re-entry) so an illegal state can never become legal across a
151
+ * persistence round trip. Returns a reasonCode string when invalid, null
152
+ * when the combination is valid.
153
+ */
154
+ export declare function validateOriginCorrelationInvariant(origin: PainOrigin, correlation: PainCorrelation): string | null;
155
+ /**
156
+ * The persisted v1 block. Evidence ENTRIES are intentionally not duplicated
157
+ * here — they remain in the legacy top-level `evidence` field; this block
158
+ * records their validated classification only (SPEC §9: one versioned
159
+ * namespace for the rev-2 facts, legacy fields stay authoritative for
160
+ * their own consumers).
161
+ */
162
+ export interface PainIngressV1Payload {
163
+ version: typeof PAIN_INGRESS_PAYLOAD_VERSION;
164
+ origin: PainIngressOriginV1;
165
+ correlation: PainIngressCorrelationV1;
166
+ evidenceClass: PainIngressEvidenceClassV1;
167
+ }
168
+ export type PainIngressV1ParseResult = {
169
+ ok: true;
170
+ payload: PainIngressV1Payload;
171
+ } | {
172
+ ok: false;
173
+ reasonCode: string;
174
+ };
175
+ /**
176
+ * Runtime validation of an untrusted persisted painIngress block
177
+ * (rc-1/rc-2/rc-3). Shares parseOrigin/parseCorrelation and the
178
+ * origin/correlation invariant with the write-time evaluator, so sentinel
179
+ * sessions, incomplete Codex lineage and impossible combinations are
180
+ * rejected identically at write time and on re-entry.
181
+ */
182
+ export declare function parsePainIngressV1Payload(value: unknown): PainIngressV1ParseResult;
183
+ /**
184
+ * Derive the legacy provenance from validated rev-2 facts (SPEC §8.3).
185
+ * Adapters do not supply provenance independently; this is the one
186
+ * derivation shared by writers and re-entry validation.
187
+ */
188
+ export declare function deriveProvenanceFromIngressFacts(origin: PainIngressOriginV1, correlation: PainIngressCorrelationV1): PainProvenance;
189
+ /**
190
+ * Re-entry consistency check between the nested v1 block and the legacy
191
+ * top-level fields produced by the same builder (SPEC §9, §12.2.4).
192
+ * Returns null when consistent; a reasonCode string otherwise.
193
+ *
194
+ * Coverage (review blocker 2 closure): every dimension of the
195
+ * nested/top-level contract is asserted — provenance, host session id,
196
+ * evidence count, evidence availability class, and host binding
197
+ * state. A v1 block with unavailable evidence cannot coexist with
198
+ * legacy top-level entries; an unbound v1 block cannot coexist with
199
+ * a legacy sessionIdHint.
200
+ */
201
+ export declare function checkIngressTopLevelConsistency(input: {
202
+ payload: PainIngressV1Payload;
203
+ topLevelProvenance: unknown;
204
+ topLevelSessionIdHint: unknown;
205
+ topLevelEvidenceCount: number;
206
+ }): string | null;
207
+ //# sourceMappingURL=pain-ingress-payload.d.ts.map