@deksden-com/dd-flow-cli 0.9.0-beta.150 → 0.9.0-beta.151

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 (34) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +17 -22
  3. package/dist/build-info.json +6 -6
  4. package/dist/harness-runtime/lib/agy-error-boundary.mjs +26 -5
  5. package/dist/harness-runtime/lib/agy-terminal-envelope.mjs +67 -0
  6. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +10 -14
  7. package/dist/harness-runtime/lib/dd-agy.mjs +3 -3
  8. package/dist/harness-runtime/lib/dd-droid.mjs +2 -2
  9. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +8 -3
  10. package/dist/harness-runtime/lib/dd-opencode.mjs +2 -2
  11. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +1 -1
  12. package/dist/harness-runtime/lib/dd-zcode.mjs +37 -12
  13. package/dist/harness-runtime/lib/delegation-instructions.d.mts +1 -1
  14. package/dist/harness-runtime/lib/delegation-instructions.mjs +13 -4
  15. package/dist/harness-runtime/lib/model-observations.mjs +19 -7
  16. package/dist/harness-runtime/lib/native-children.d.mts +12 -1
  17. package/dist/harness-runtime/lib/native-children.mjs +47 -1
  18. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +9 -1
  19. package/dist/harness-runtime/lib/provider-overload-policy.mjs +97 -6
  20. package/dist/services/check-runner-evidence.js +17 -302
  21. package/dist/services/check-runner-proof.js +305 -0
  22. package/dist/services/code-checks.js +4 -1
  23. package/dist/services/controller-child-capacity.js +58 -0
  24. package/dist/services/controller-child-observer.js +9 -3
  25. package/dist/services/memory-init-native-capacity.js +1 -1
  26. package/dist/services/provider-capacity.js +15 -7
  27. package/dist/services/run-controller-adapter.js +1 -1
  28. package/dist/services/run-controller.js +87 -18
  29. package/dist/services/run-recovery-guard.js +1 -1
  30. package/dist/services/run-recovery-runtime.js +1 -1
  31. package/dist/services/stage-context.js +56 -8
  32. package/dist/services/vnext-fanout.js +1 -1
  33. package/dist/verification-components.json +299 -0
  34. package/package.json +7 -6
@@ -1,71 +1,13 @@
1
1
  import fs from "node:fs";
2
2
  import crypto from "node:crypto";
3
- import { stripVTControlCharacters } from "node:util";
4
3
  import path from "node:path";
5
4
  import { parse } from "shell-quote";
6
5
  import { AppError } from "../shared/errors.js";
7
6
  import { validateObservationDuration } from "../harness-runtime/lib/observation-clock.mjs";
8
7
  import { isDeepStrictEqual } from "node:util";
9
- import { fileURLToPath } from "node:url";
10
- function object(value) { return Boolean(value) && typeof value === "object" && !Array.isArray(value); }
11
- function boundedString(value, bytes) { return typeof value === "string" && Buffer.byteLength(value) <= bytes; }
12
- const validatedBrowserProofs = new WeakSet();
13
- const unsupportedObservationContracts = new WeakSet();
14
- const validatedNativeProofs = new WeakSet();
15
- const validatedChildren = new WeakMap();
16
- const validatedReports = new WeakMap();
17
- const hash = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
8
+ import { runnerFailureValid, validateRunnerProof, validatedRunnerChild, hasValidatedNativeProof, hasValidatedBrowserProof, hasUnsupportedObservation } from "./check-runner-proof.js";
9
+ export { candidateAbsencesValid, runnerFailureValid, runnerEvidencePass, runnerProofArtifacts } from "./check-runner-proof.js";
18
10
  const absoluteFile = (value) => typeof value === "string" && value.length > 0 && value.length <= 4096 && !value.includes("\0") && path.isAbsolute(value);
19
- export function candidateAbsencesValid(value) { return Array.isArray(value) && value.length <= 64 && value.every(item => object(item) && absoluteFile(item.file) && item.path_state === "missing" && object(item.declaration) && absoluteFile(item.declaration.file) && hash(item.declaration.sha256)); }
20
- function relativeProofPath(value) { return typeof value === "string" && value.length > 0 && Buffer.byteLength(value) <= 4096 && !path.isAbsolute(value) && !value.includes("\\") && value.split("/").every(part => part !== "" && part !== "." && part !== ".."); }
21
- function proofArtifact(value) { return object(value) && relativeProofPath(value.relative_path) && typeof value.sha256 === "string" && /^[a-f0-9]{64}$/.test(value.sha256); }
22
- function browserProofShape(proof) {
23
- const attempt = proof.attempt, step = proof.step;
24
- return (proof.observation_contract === undefined || proof.observation_contract === "dd-tasks/browser-observation@2" && object(proof.target) && [proof.target.page_id, proof.target.context_id].every(value => boundedString(value, 256) && Boolean(value)) && Number.isSafeInteger(proof.window_epoch) && Number(proof.window_epoch) > 0)
25
- && proof.native_code === "PLAYWRIGHT_ACTION_INACTIVITY" && object(attempt) && boundedString(attempt.invocation_id, 4096) && boundedString(attempt.test_id, 4096) && Boolean(attempt.test_id)
26
- && [attempt.retry, attempt.repeat_each_index, attempt.worker_index].every(value => Number.isSafeInteger(value) && value >= 0)
27
- && object(step) && boundedString(step.id, 4096) && Boolean(step.id) && ["pw:api", "expect"].includes(String(step.category)) && step.file === proof.file && Number.isSafeInteger(step.line) && step.line > 0
28
- && proofArtifact(proof.worker_snapshot) && proofArtifact(proof.native_result);
29
- }
30
- export function runnerFailureValid(value) {
31
- if (!object(value) || typeof value.category !== "string" || !["assertion", "tooling", "unclassified"].includes(value.category))
32
- return false;
33
- if (value.diagnostic_artifact !== undefined && !proofArtifact(value.diagnostic_artifact))
34
- return false;
35
- for (const key of ["code", "message", "file", "test_id", "native_code", "classification_reason"])
36
- if (value[key] !== undefined && !boundedString(value[key], 4096))
37
- return false;
38
- if (value.stack !== undefined && !boundedString(value.stack, 16384) || value.origin !== undefined && (typeof value.origin !== "string" || !["candidate", "tooling", "unknown"].includes(value.origin)) || value.phase !== undefined && (typeof value.phase !== "string" || !["test", "setup", "teardown", "collection", "runner"].includes(value.phase)))
39
- return false;
40
- if (value.repair_evidence !== undefined) {
41
- const proof = value.repair_evidence;
42
- if (object(proof) && proof.rule === "candidate_test_runtime_error")
43
- return ["TypeError", "ReferenceError", "Error"].includes(String(proof.exception_type)) && (proof.exception_type !== "Error" || proof.phase === "test")
44
- && absoluteFile(proof.file) && hash(proof.file_sha256) && ["test", "setup", "collection"].includes(String(proof.phase))
45
- && [proof.line, proof.column].every(value => Number.isSafeInteger(value) && Number(value) > 0) && proofArtifact(proof.native_artifact);
46
- if (object(proof) && proof.rule === "candidate_migration_sql")
47
- return proof.native_code === "42601" && absoluteFile(proof.file) && hash(proof.file_sha256)
48
- && boundedString(proof.operation_id, 4096) && Boolean(proof.operation_id) && proofArtifact(proof.native_artifact) && object(proof.world)
49
- && boundedString(proof.world.invocation_id, 4096) && typeof proof.world.world_id === "string" && /^[a-f0-9]{32}$/.test(proof.world.world_id)
50
- && boundedString(proof.world.role, 128) && Boolean(proof.world.role) && hash(proof.world.migrations_sha256) && proof.world.phase === "migrating" && proof.world.setup_completed === false;
51
- if (object(proof) && proof.rule === "candidate_tool_diagnostic")
52
- return absoluteFile(proof.file) && proofArtifact(proof.native_artifact)
53
- && object(proof.tool) && { biome: "2.5.6", typescript: "5.9.3", docs: "1", "value-absence": "1" }[String(proof.tool.name)] === proof.tool.version
54
- && object(proof.step) && boundedString(proof.step.id, 256) && Boolean(proof.step.id) && Number.isSafeInteger(proof.step.ordinal) && proof.step.ordinal >= 0 && hash(proof.step.command_sha256)
55
- && boundedString(proof.diagnostic_code, 256) && (proof.tool.name === "biome" ? ["format", "assist/source/organizeImports"].includes(String(proof.diagnostic_code)) || /^lint\/[\w/-]+$/.test(String(proof.diagnostic_code)) : proof.tool.name === "typescript" ? /^TS\d+$/.test(String(proof.diagnostic_code)) : proof.tool.name === "docs" ? ["required_path_missing", "docs_contract"].includes(String(proof.diagnostic_code)) : proof.diagnostic_code === "value_absence")
56
- && (proof.path_state === "present" && hash(proof.file_sha256) || proof.path_state === "missing" && proof.tool.name === "docs" && proof.diagnostic_code === "required_path_missing" && proof.file_sha256 === null && object(proof.declaration) && absoluteFile(proof.declaration.file) && hash(proof.declaration.sha256));
57
- if (!object(proof) || !boundedString(proof.rule, 128) || !boundedString(proof.native_code, 128) || !boundedString(proof.file, 4096) || !object(proof.world))
58
- return false;
59
- const world = proof.world;
60
- if (world.schema_id !== "dd-tasks/test-world-ready@1" || !boundedString(world.invocation_id, 4096) || typeof world.world_id !== "string" || !/^[a-f0-9]{32}$/.test(world.world_id) || typeof world.migrations_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(world.migrations_sha256) || world.ready !== true || world.setup_completed !== true || !boundedString(world.role, 128) || !world.role)
61
- return false;
62
- if (proof.rule === "candidate_browser_action_inactivity" && !browserProofShape(proof))
63
- return false;
64
- if (!["candidate_sql_integrity", "candidate_browser_action_inactivity"].includes(String(proof.rule)))
65
- return false;
66
- }
67
- return true;
68
- }
69
11
  function candidateFile(root, file) {
70
12
  if (!root || !path.isAbsolute(file))
71
13
  return false;
@@ -90,7 +32,7 @@ function candidateFile(root, file) {
90
32
  }
91
33
  export function candidateFailureFiles(evidence, root) {
92
34
  return [...new Set((evidence?.failures ?? []).flatMap(failure => {
93
- const child = validatedChildren.get(failure);
35
+ const child = validatedRunnerChild(failure);
94
36
  if (child)
95
37
  return candidateFailureFiles({ ...child.evidence, failures: [child.failure] }, root);
96
38
  const proof = failure.repair_evidence;
@@ -147,12 +89,12 @@ function absentCandidate(root, file) {
147
89
  }
148
90
  export function candidateFailureAbsences(evidence, root) {
149
91
  return (evidence?.failures ?? []).flatMap(failure => {
150
- const child = validatedChildren.get(failure);
92
+ const child = validatedRunnerChild(failure);
151
93
  if (child)
152
94
  return candidateFailureAbsences({ ...child.evidence, failures: [child.failure] }, root);
153
95
  try {
154
96
  const proof = failure.repair_evidence;
155
- if (proof?.rule !== "candidate_tool_diagnostic" || proof.path_state !== "missing" || !proof.declaration || !validatedNativeProofs.has(proof)
97
+ if (proof?.rule !== "candidate_tool_diagnostic" || proof.path_state !== "missing" || !proof.declaration || !hasValidatedNativeProof(proof)
156
98
  || !absentCandidate(root, proof.file) || !candidateFile(root, proof.declaration.file) || crypto.createHash("sha256").update(fs.readFileSync(proof.declaration.file)).digest("hex") !== proof.declaration.sha256)
157
99
  return [];
158
100
  return [{ file: proof.file, declaration: proof.declaration, path_state: "missing" }];
@@ -163,7 +105,7 @@ export function candidateFailureAbsences(evidence, root) {
163
105
  });
164
106
  }
165
107
  function candidateFailure(failure, evidence, root, capturedFiles, capturedAbsences) {
166
- const child = validatedChildren.get(failure);
108
+ const child = validatedRunnerChild(failure);
167
109
  if (child)
168
110
  return candidateFailure(child.failure, child.evidence, root, capturedFiles, capturedAbsences);
169
111
  const owned = (file) => {
@@ -185,10 +127,10 @@ function candidateFailure(failure, evidence, root, capturedFiles, capturedAbsenc
185
127
  return failure.origin === undefined || failure.origin === "candidate" && failure.file !== undefined && owned(failure.file);
186
128
  const proof = failure.repair_evidence;
187
129
  if (proof?.rule === "candidate_test_runtime_error")
188
- return validatedNativeProofs.has(proof) && failure.category === "unclassified" && failure.origin === "candidate"
130
+ return hasValidatedNativeProof(proof) && failure.category === "unclassified" && failure.origin === "candidate"
189
131
  && failure.phase === proof.phase && failure.native_code === proof.exception_type && failure.file === proof.file && owned(proof.file);
190
132
  if (proof?.rule === "candidate_migration_sql" || proof?.rule === "candidate_tool_diagnostic") {
191
- if (!validatedNativeProofs.has(proof) || failure.category !== "unclassified" || failure.origin !== "candidate" || failure.file !== proof.file || !["setup", "collection", "test"].includes(failure.phase ?? ""))
133
+ if (!hasValidatedNativeProof(proof) || failure.category !== "unclassified" || failure.origin !== "candidate" || failure.file !== proof.file || !["setup", "collection", "test"].includes(failure.phase ?? ""))
192
134
  return false;
193
135
  if (proof.rule === "candidate_migration_sql")
194
136
  return failure.phase === "setup" && failure.native_code === "42601" && proof.world.invocation_id === evidence.binding.invocation_id && owned(proof.file);
@@ -197,7 +139,7 @@ function candidateFailure(failure, evidence, root, capturedFiles, capturedAbsenc
197
139
  return proof.path_state === "missing" ? Boolean(proof.declaration && (capturedAbsences ?? (root ? candidateFailureAbsences(evidence, root) : [])).some(item => item.file === proof.file && isDeepStrictEqual(item.declaration, proof.declaration))) : owned(proof.file);
198
140
  }
199
141
  if (proof?.rule === "candidate_browser_action_inactivity")
200
- return validatedBrowserProofs.has(proof) && failure.category === "unclassified" && failure.phase === "test" && failure.origin === "candidate" && failure.native_code === proof.native_code && failure.file === proof.file && failure.test_id === proof.attempt.test_id && proof.attempt.invocation_id === evidence.binding.invocation_id && owned(proof.file);
142
+ return hasValidatedBrowserProof(proof) && failure.category === "unclassified" && failure.phase === "test" && failure.origin === "candidate" && failure.native_code === proof.native_code && failure.file === proof.file && failure.test_id === proof.attempt.test_id && proof.attempt.invocation_id === evidence.binding.invocation_id && owned(proof.file);
201
143
  return failure.category === "unclassified" && failure.origin === "candidate" && ["test", "setup"].includes(failure.phase ?? "") && proof?.rule === "candidate_sql_integrity" && ["23502", "23503", "23505", "23514"].includes(proof.native_code) && failure.native_code === proof.native_code && failure.file === proof.file && proof.world.invocation_id === evidence.binding.invocation_id && owned(proof.file);
202
144
  }
203
145
  export function runnerObservationDurations(environment) {
@@ -278,48 +220,6 @@ function readBoundedProofFile(file, limit) {
278
220
  fs.closeSync(fd);
279
221
  }
280
222
  }
281
- function readProofArtifact(root, ref, limit = 256 * 1024) {
282
- let current = root;
283
- if (fs.lstatSync(current).isSymbolicLink())
284
- throw new Error("Symlink evidence root");
285
- for (const part of ref.relative_path.split("/")) {
286
- current = path.join(current, part);
287
- if (fs.lstatSync(current).isSymbolicLink())
288
- throw new Error("Symlink proof artifact");
289
- }
290
- const bytes = readBoundedProofFile(current, limit);
291
- if (crypto.createHash("sha256").update(bytes).digest("hex") !== ref.sha256)
292
- throw new Error("Browser proof hash differs");
293
- const value = JSON.parse(bytes.toString("utf8"));
294
- if (!object(value))
295
- throw new Error("Invalid proof object");
296
- return value;
297
- }
298
- function matches(actual, expected) { return object(actual) && Object.entries(expected).every(([key, value]) => actual[key] === value); }
299
- function validateBrowserArtifacts(root, proof, binding) {
300
- const snapshot = readProofArtifact(root, proof.worker_snapshot), native = readProofArtifact(root, proof.native_result);
301
- if (proof.observation_contract !== undefined && (proof.observation_contract !== "dd-tasks/browser-observation@2" || snapshot.observation_contract !== proof.observation_contract || native.observation_contract !== proof.observation_contract
302
- || !isDeepStrictEqual(snapshot.target, proof.target) || !isDeepStrictEqual(native.target, proof.target) || snapshot.window_epoch !== proof.window_epoch || native.window_epoch !== proof.window_epoch))
303
- return false;
304
- if (!Array.isArray(native.errors) || native.errors.length < 1 || native.errors.length > 64 || native.errors.some(error => !boundedString(error, 4096) || !/^(?:Error: )?(?:[A-Za-z][\w.]*: )?Test timeout of [1-9]\d*ms exceeded\.(?:\nCall log:[\s\S]*)?$/.test(stripVTControlCharacters(String(error)))))
305
- return false;
306
- if (!matches(snapshot.binding, binding) || !matches(native.binding, binding) || !matches(snapshot.attempt, proof.attempt) || !matches(native.attempt, proof.attempt)
307
- || !matches(snapshot.step, proof.step) || !matches(native.step, proof.step) || !matches(snapshot.world, proof.world) || proof.world.invocation_id !== binding.invocation_id
308
- || native.status !== "timedOut" || native.phase !== "test" || native.file !== proof.file || snapshot.phase !== "body" || snapshot.observation_gap !== false || !matches(snapshot.browser, { connected: true, page_closed: false, crashed: false })
309
- || !matches(snapshot.world_health, { api: true, web: true, db: true }))
310
- return false;
311
- const quiet = snapshot.quiet_ms, last = Date.parse(String(snapshot.last_progress_at)), deadline = Date.parse(String(snapshot.deadline_at)), observed = Date.parse(String(snapshot.observed_at)), health = Date.parse(String(snapshot.health_observed_at)), ended = Date.parse(String(native.ended_at));
312
- return Number.isSafeInteger(quiet) && quiet > 0 && [last, deadline, observed, health, ended].every(Number.isFinite) && Math.abs(deadline - last - quiet) <= 2 && observed >= last && observed <= deadline && health <= observed && health >= last && deadline - health <= Math.min(1000, quiet / 4) && ended >= deadline && ended <= Date.now() && ended - deadline <= 5000;
313
- }
314
- export function runnerProofArtifacts(evidence) {
315
- return [...new Set([...(evidence?.failures ?? []).flatMap(failure => {
316
- const child = validatedChildren.get(failure);
317
- if (child && failure.child_evidence)
318
- return [failure.child_evidence.report.relative_path, ...runnerProofArtifacts(child.evidence).map(file => path.posix.join(path.posix.dirname(failure.child_evidence.report.relative_path), file))];
319
- const proof = failure.repair_evidence;
320
- return [...(failure.diagnostic_artifact ? [failure.diagnostic_artifact.relative_path] : []), ...(proof?.rule === "candidate_browser_action_inactivity" ? [proof.worker_snapshot.relative_path, proof.native_result.relative_path] : proof && "native_artifact" in proof ? [proof.native_artifact.relative_path] : [])];
321
- }), ...(evidence ? validatedReports.get(evidence) ?? [] : []).flatMap(child => [child.report.relative_path, ...runnerProofArtifacts(child.evidence).map(file => path.posix.join(path.posix.dirname(child.report.relative_path), file))])])];
322
- }
323
223
  export function runnerContractsValid(value) {
324
224
  if (value === undefined)
325
225
  return true;
@@ -332,211 +232,26 @@ export function runnerContractsValid(value) {
332
232
  return alias.startsWith("@check/") && ["dd-flow/check-runner-evidence@1", "dd-flow/check-runner-evidence@2"].includes(String(contract.schema_id)) && typeof contract.path === "string" && contract.path.length > 0 && contract.path.split("/")[0] !== "engine-outcome.json" && !contract.path.includes("\\") && !path.isAbsolute(contract.path) && !contract.path.split("/").some(part => part === ".." || part === "" || part === ".");
333
233
  });
334
234
  }
335
- function diagnostic(context, value) {
336
- // Diagnostics are locators, never another copy of untrusted report content.
337
- if (context.diagnostics.length >= 64 || context.bytes + Buffer.byteLength(JSON.stringify(value)) > 32 * 1024 - 64) {
338
- context.truncated = true;
339
- return;
340
- }
341
- context.diagnostics.push(value);
342
- context.bytes += Buffer.byteLength(JSON.stringify(value));
343
- }
344
235
  export function readRunnerEvidenceDetailed(root, contract, binding) {
345
- const context = { diagnostics: [], bytes: 0, truncated: false };
346
- const evidence = readRunnerEvidenceInternal(root, contract, binding, 0, { reports: 0 }, context, "");
347
- return { evidence, diagnostics: context.diagnostics, ...(context.truncated ? { diagnostics_truncated: true } : {}) };
348
- }
349
- export function readRunnerEvidence(root, contract, binding, depth = 0, budget = { reports: 0 }) {
350
- return readRunnerEvidenceInternal(root, contract, binding, depth, budget, { diagnostics: [], bytes: 0, truncated: false }, "");
351
- }
352
- function readRunnerEvidenceInternal(root, contract, binding, depth, budget, context, prefix) {
353
- const report = relativeProofPath(contract.path) ? path.posix.join(prefix, contract.path) : "<invalid-report-path>";
354
- const count = context.diagnostics.length;
355
- let accepted = false;
356
- let failureReason = "invalid_shape";
357
- const invalid = () => { if (context.diagnostics.length === count)
358
- diagnostic(context, { reason: failureReason, report }); return null; };
359
- try {
360
- if (!relativeProofPath(contract.path))
361
- return invalid();
362
- if (depth > 4 || ++budget.reports > 64)
363
- return null;
236
+ return validateRunnerProof(contract, binding, relative => {
364
237
  let current = root;
365
238
  if (!fs.lstatSync(current).isDirectory() || fs.lstatSync(current).isSymbolicLink())
366
- return null;
367
- for (const part of contract.path.split(/[\\/]/)) {
239
+ throw new Error("Unsafe proof root");
240
+ for (const part of relative.split("/")) {
368
241
  current = path.join(current, part);
369
242
  if (fs.lstatSync(current).isSymbolicLink())
370
- return null;
371
- }
372
- const bytes = readBoundedProofFile(current, 1024 * 1024);
373
- failureReason = "invalid_json";
374
- const evidence = JSON.parse(bytes.toString("utf8"));
375
- failureReason = "invalid_shape";
376
- if (!object(evidence))
377
- return invalid();
378
- if (!["dd-flow/check-runner-evidence@1", "dd-flow/check-runner-evidence@2"].includes(contract.schema_id))
379
- return null;
380
- const partial = evidence.failure_projection;
381
- if (partial !== undefined && (evidence.schema_id !== "dd-flow/check-runner-evidence@2" || !object(partial) || partial.state !== "partial" || !["count_bound", "byte_bound", "interrupt"].includes(partial.reason)
382
- || ![partial.represented, partial.omitted].every(value => Number.isSafeInteger(value) && value >= 0)))
383
- return null;
384
- if (evidence.schema_id !== contract.schema_id) {
385
- diagnostic(context, { reason: "invalid_shape", report, expected: contract.schema_id, observed: ["dd-flow/check-runner-evidence@1", "dd-flow/check-runner-evidence@2"].includes(evidence.schema_id) ? evidence.schema_id : "unsupported" });
386
- return null;
387
- }
388
- if (!evidence.binding || Object.entries(binding).some(([key, value]) => evidence.binding[key] !== value)) {
389
- diagnostic(context, { reason: "binding_mismatch", report });
390
- return null;
391
- }
392
- if (typeof evidence.runner?.name !== "string" || !evidence.runner.name || typeof evidence.runner.version !== "string" || !evidence.runner.version || typeof evidence.completed !== "boolean" || !evidence.counts
393
- || ![evidence.counts.passed, evidence.counts.failed, evidence.counts.skipped].every(n => Number.isSafeInteger(n) && n >= 0)
394
- || !Array.isArray(evidence.failures) || evidence.failures.length > 64 || evidence.failures.some(f => !runnerFailureValid(f))
395
- || !partial && evidence.counts.failed > evidence.failures.length || evidence.observation_unknown !== undefined && typeof evidence.observation_unknown !== "boolean")
396
- return null;
397
- const children = new Map();
398
- const consumed = new Map();
399
- if (evidence.steps !== undefined) {
400
- if (!Array.isArray(evidence.steps) || evidence.steps.length > 64)
401
- return null;
402
- const ids = new Set(), invocations = new Set();
403
- let stopped = false;
404
- for (const [ordinal, step] of evidence.steps.entries()) {
405
- if (!step || !boundedString(step.id, 256) || !step.id || ids.has(step.id) || step.ordinal !== ordinal || !hash(step.command_sha256) || !["passed", "failed", "unreached"].includes(step.state))
406
- return null;
407
- ids.add(step.id);
408
- if (step.state === "unreached") {
409
- if (!stopped || step.binding !== undefined || step.report !== undefined || step.exit_code !== undefined)
410
- return null;
411
- continue;
412
- }
413
- if (stopped)
414
- return null;
415
- if (step.state === "failed")
416
- stopped = true;
417
- if (!step.binding || !proofArtifact(step.report) || !Number.isSafeInteger(step.exit_code) || step.state === "passed" && step.exit_code !== 0 || step.state === "failed" && step.exit_code === 0 || invocations.has(step.binding.invocation_id) || step.binding.invocation_id === binding.invocation_id)
418
- return null;
419
- if (step.binding.invocation_id !== `${binding.invocation_id}:step:${step.id}` || step.binding.check_id !== `${binding.check_id}/${step.id}` || step.binding.verification_epoch !== binding.verification_epoch || step.binding.input_hash !== crypto.createHash("sha256").update(JSON.stringify([binding.input_hash, step.command_sha256])).digest("hex"))
420
- return null;
421
- if (crypto.createHash("sha256").update(step.binding.command).digest("hex") !== step.command_sha256)
422
- return null;
423
- invocations.add(step.binding.invocation_id);
424
- failureReason = "artifact_mismatch";
425
- readProofArtifact(root, step.report, 1024 * 1024);
426
- failureReason = "invalid_shape";
427
- const child = readRunnerEvidenceInternal(path.join(root, path.dirname(step.report.relative_path)), { schema_id: contract.schema_id, path: path.basename(step.report.relative_path) }, step.binding, depth + 1, budget, context, path.posix.join(prefix, path.posix.dirname(step.report.relative_path)));
428
- if (!child || step.state === "passed" && (child.counts.failed !== 0 || child.failures.length !== 0) || step.state === "failed" && !child.failures.length && child.completed && !child.observation_unknown)
429
- return null;
430
- if (!child.completed || child.observation_unknown)
431
- stopped = true;
432
- children.set(step.id, child);
433
- }
434
- for (const key of ["passed", "failed", "skipped"])
435
- if (evidence.counts[key] !== [...children.values()].reduce((total, child) => total + child.counts[key], 0))
436
- return null;
243
+ throw new Error("Symlink proof artifact");
437
244
  }
438
- for (const failure of evidence.failures) {
439
- failureReason = "artifact_mismatch";
440
- if (failure.child_evidence) {
441
- const ref = failure.child_evidence, step = evidence.steps?.find(item => item.id === ref.step_id), child = children.get(ref.step_id);
442
- if (!step || !child || !isDeepStrictEqual(ref.binding, step.binding) || !isDeepStrictEqual(ref.report, step.report))
443
- return null;
444
- const original = { ...failure };
445
- delete original.child_evidence;
446
- const used = consumed.get(child) ?? new Set();
447
- consumed.set(child, used);
448
- const index = child.failures.findIndex((item, index) => { const native = { ...item }; delete native.child_evidence; return !used.has(index) && isDeepStrictEqual(native, original); });
449
- if (index < 0)
450
- return null;
451
- used.add(index);
452
- const matched = child.failures[index];
453
- if (!matched.child_evidence && matched.repair_evidence?.rule === "candidate_tool_diagnostic" && !isDeepStrictEqual(matched.repair_evidence.step, { id: step.id, ordinal: step.ordinal, command_sha256: step.command_sha256 }))
454
- return null;
455
- validatedChildren.set(failure, { failure: matched, evidence: child });
456
- continue;
457
- }
458
- if (failure.diagnostic_artifact && !matches(readProofArtifact(root, failure.diagnostic_artifact, 2 * 1024 * 1024).binding, binding))
459
- return null;
460
- const proof = failure.repair_evidence;
461
- if (proof?.rule === "candidate_migration_sql" || proof?.rule === "candidate_tool_diagnostic" || proof?.rule === "candidate_test_runtime_error") {
462
- const native = readProofArtifact(root, proof.native_artifact, 2 * 1024 * 1024), facts = Object.fromEntries(Object.entries(proof).filter(([key]) => key !== "native_artifact"));
463
- if (!isDeepStrictEqual(native.binding, binding) || Object.entries(facts).some(([key, value]) => !isDeepStrictEqual(native[key], value)))
464
- return null;
465
- if (proof.rule === "candidate_test_runtime_error") {
466
- failureReason = "attribution_unproven";
467
- if (evidence.schema_id !== "dd-flow/check-runner-evidence@2" || native.executing_file !== proof.file || native.exception_name !== proof.exception_type
468
- || !isDeepStrictEqual(native.top_frame, { file: proof.file, line: proof.line, column: proof.column }) || !boundedString(native.stack, 16384) || !String(native.stack).startsWith(`${proof.exception_type}:`))
469
- return null;
470
- const firstFrame = String(native.stack).split("\n").find(line => /^\s*at\s/.test(line));
471
- const frame = firstFrame?.match(/^\s*at\s+(?:.*?\()?((?:file:\/\/)?\/[^\n]+):(\d+):(\d+)\)?$/);
472
- if (!frame || (frame[1].startsWith("file://") ? fileURLToPath(frame[1]) : frame[1]) !== proof.file || Number(frame[2]) !== proof.line || Number(frame[3]) !== proof.column)
473
- return null;
474
- }
475
- validatedNativeProofs.add(proof);
476
- }
477
- if (proof?.rule === "candidate_browser_action_inactivity") {
478
- if (proof.observation_contract === undefined && evidence.schema_id === "dd-flow/check-runner-evidence@1") {
479
- // Legacy diagnostics remain readable; they do not prove the new window/target guarantee.
480
- if (!validateBrowserArtifacts(root, proof, binding))
481
- return null;
482
- evidence.completed = false;
483
- unsupportedObservationContracts.add(evidence);
484
- continue;
485
- }
486
- if (proof.observation_contract !== "dd-tasks/browser-observation@2" || !validateBrowserArtifacts(root, proof, binding))
487
- return null;
488
- validatedBrowserProofs.add(proof);
489
- }
490
- }
491
- failureReason = "invalid_shape";
492
- const represented = [...consumed.values()].reduce((total, used) => total + used.size, 0), childFailures = [...children.values()].reduce((total, child) => total + child.failures.length, 0);
493
- if (partial) {
494
- if (children.size ? partial.represented !== represented || partial.omitted !== childFailures - represented : partial.represented !== evidence.failures.filter(failure => failure.code !== "report_truncated").length)
495
- return null;
496
- evidence.completed = false;
497
- }
498
- else if (represented !== childFailures)
499
- return null;
500
- // Valid but incomplete native observation is diagnostic evidence, not a
501
- // malformed schema. Preserve the primary failure and references through
502
- // every composite, including a parent that incorrectly claims completion.
503
- if ([...children.values()].some(child => !child.completed || child.observation_unknown)) {
504
- evidence.completed = false;
505
- if ([...children.values()].some(child => unsupportedObservationContracts.has(child)))
506
- unsupportedObservationContracts.add(evidence);
507
- if (evidence.schema_id === "dd-flow/check-runner-evidence@1" && [...children.values()].some(child => !child.completed && !unsupportedObservationContracts.has(child)) || [...children.values()].some(child => child.observation_unknown))
508
- evidence.observation_unknown = true;
509
- }
510
- validatedReports.set(evidence, (evidence.steps ?? []).flatMap(step => step.report && children.has(step.id) ? [{ report: step.report, evidence: children.get(step.id) }] : []));
511
- if (unsupportedObservationContracts.has(evidence))
512
- diagnostic(context, { reason: "unsupported_observation_contract", report, expected: "dd-tasks/browser-observation@2", observed: "legacy" });
513
- else if (!evidence.completed || evidence.observation_unknown)
514
- diagnostic(context, { reason: "observation_incomplete", report });
515
- for (const failure of evidence.failures)
516
- if (failure.origin === "unknown" || failure.category === "unclassified" && !failure.repair_evidence) {
517
- diagnostic(context, { reason: "attribution_unproven", report });
518
- break;
519
- }
520
- accepted = true;
521
- return evidence;
522
- }
523
- catch (error) {
524
- if (error.code === "ENOENT")
525
- failureReason = "missing";
526
- return invalid();
527
- }
528
- finally {
529
- if (!accepted && context.diagnostics.length === count)
530
- diagnostic(context, { reason: failureReason, report });
531
- }
245
+ return readBoundedProofFile(current, 2 * 1024 * 1024);
246
+ });
532
247
  }
533
- export function runnerEvidencePass(evidence) { return Boolean(evidence?.completed && !evidence.failure_projection && !evidence.observation_unknown && evidence.counts.failed === 0 && evidence.failures.length === 0); }
248
+ export function readRunnerEvidence(root, contract, binding) { return readRunnerEvidenceDetailed(root, contract, binding).evidence; }
534
249
  export function checkRepairDisposition(receipt) {
535
250
  if (receipt.fingerprint_scope != null && receipt.fingerprint_scope !== "check_inputs")
536
251
  return "tooling_blocker";
537
252
  if (receipt.status === "running" || receipt.status === "aborted" || receipt.runner_evidence?.observation_unknown)
538
253
  return "settlement_required";
539
- if (receipt.runner_evidence && unsupportedObservationContracts.has(receipt.runner_evidence) || receipt.runner_evidence?.failure_projection || receipt.runner_evidence?.schema_id === "dd-flow/check-runner-evidence@2" && !receipt.runner_evidence.completed)
254
+ if (receipt.runner_evidence && hasUnsupportedObservation(receipt.runner_evidence) || receipt.runner_evidence?.failure_projection || receipt.runner_evidence?.schema_id === "dd-flow/check-runner-evidence@2" && !receipt.runner_evidence.completed)
540
255
  return "tooling_blocker";
541
256
  if (receipt.status === "passed")
542
257
  return "passed";