@riddledc/riddle-proof 0.8.25 → 0.8.27

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 (54) hide show
  1. package/dist/adapters/codex-exec-agent.cjs +21 -3
  2. package/dist/adapters/codex-exec-agent.js +1 -1
  3. package/dist/adapters/codex.cjs +21 -3
  4. package/dist/adapters/codex.js +1 -1
  5. package/dist/adapters/local-agent.cjs +21 -3
  6. package/dist/adapters/local-agent.js +1 -1
  7. package/dist/adapters/openclaw.js +4 -4
  8. package/dist/advanced/engine-harness.cjs +103 -2
  9. package/dist/advanced/engine-harness.js +5 -5
  10. package/dist/advanced/index.cjs +103 -2
  11. package/dist/advanced/index.js +7 -7
  12. package/dist/advanced/proof-run-core.cjs +98 -1
  13. package/dist/advanced/proof-run-core.js +1 -1
  14. package/dist/advanced/proof-run-engine.cjs +98 -1
  15. package/dist/advanced/proof-run-engine.js +2 -2
  16. package/dist/advanced/runner.js +5 -5
  17. package/dist/checkpoint.cjs +20 -1
  18. package/dist/checkpoint.js +1 -1
  19. package/dist/{chunk-27AB2TEQ.js → chunk-27BG64ZG.js} +3 -3
  20. package/dist/{chunk-P2RN2NYR.js → chunk-3OTO7IDH.js} +2 -2
  21. package/dist/{chunk-EEIYUZXE.js → chunk-4PPJKW3Z.js} +21 -3
  22. package/dist/{chunk-2DW2LBUD.js → chunk-AM3K5FPW.js} +4 -4
  23. package/dist/{chunk-RBWSCU6V.js → chunk-AYMHHRJZ.js} +1 -1
  24. package/dist/{chunk-FU73I4V3.js → chunk-K6HZUSHH.js} +98 -1
  25. package/dist/{chunk-4FOHZ7JG.js → chunk-OILKSY5J.js} +20 -1
  26. package/dist/{chunk-FMOYUYH2.js → chunk-RDPG554T.js} +1 -1
  27. package/dist/{chunk-KS3N5APP.js → chunk-YC77HZVF.js} +1 -1
  28. package/dist/{chunk-YZUVEJ5B.js → chunk-ZQWVXQKJ.js} +1 -1
  29. package/dist/cli/index.js +7 -7
  30. package/dist/cli.cjs +139 -5
  31. package/dist/cli.js +7 -7
  32. package/dist/codex-exec-agent.cjs +21 -3
  33. package/dist/codex-exec-agent.js +1 -1
  34. package/dist/engine-harness.cjs +103 -2
  35. package/dist/engine-harness.js +5 -5
  36. package/dist/index.cjs +139 -5
  37. package/dist/index.js +7 -7
  38. package/dist/local-agent.cjs +21 -3
  39. package/dist/local-agent.js +1 -1
  40. package/dist/openclaw.js +4 -4
  41. package/dist/proof-run-core.cjs +98 -1
  42. package/dist/proof-run-core.js +1 -1
  43. package/dist/proof-run-engine.cjs +98 -1
  44. package/dist/proof-run-engine.js +2 -2
  45. package/dist/run-card.js +2 -2
  46. package/dist/runner.js +5 -5
  47. package/dist/spec/checkpoint.cjs +20 -1
  48. package/dist/spec/checkpoint.js +1 -1
  49. package/dist/spec/index.cjs +20 -1
  50. package/dist/spec/index.js +3 -3
  51. package/dist/spec/run-card.js +2 -2
  52. package/dist/spec/state.js +3 -3
  53. package/dist/state.js +3 -3
  54. package/package.json +1 -1
@@ -208,6 +208,30 @@ function normalizeRoutePath(value) {
208
208
  return `${pathname}${query}${hash}`;
209
209
  }
210
210
  }
211
+ function trimRouteCandidate(value) {
212
+ return value.trim().replace(/[),.;\]}]+$/g, "");
213
+ }
214
+ function expectedTerminalRouteFromText(value) {
215
+ const text = typeof value === "string" ? value.trim() : "";
216
+ if (!text) return "";
217
+ const routePattern = "(https?:\\/\\/[^\\s\"'<>`]+|\\/[^\\s\"'<>`]+)";
218
+ const patterns = [
219
+ new RegExp(`\\bexpected\\s+(?:terminal\\s+|final\\s+|after\\s+)?(?:url|route|path)\\s*(?:is|=|:)\\s*${routePattern}`, "i"),
220
+ new RegExp(`\\b(?:terminal|final|after)\\s+(?:url|route|path)\\s*(?:is|=|:)\\s*${routePattern}`, "i"),
221
+ new RegExp(`\\b(?:ends|end|ending|lands|land|landing)\\s+(?:at|on)\\s*${routePattern}`, "i")
222
+ ];
223
+ for (const pattern of patterns) {
224
+ const match = text.match(pattern);
225
+ if (!match) continue;
226
+ const candidate = trimRouteCandidate(match[1] || "");
227
+ const normalized = normalizeRoutePath(candidate);
228
+ if (normalized) return normalized;
229
+ }
230
+ return "";
231
+ }
232
+ function requestedExpectedTerminalRouteForState(state) {
233
+ return expectedTerminalRouteFromText(state.success_criteria) || expectedTerminalRouteFromText(state.change_request) || expectedTerminalRouteFromText(state.context) || expectedTerminalRouteFromText(state.assertions_json);
234
+ }
211
235
  function isInteractionVerificationMode(value) {
212
236
  return INTERACTION_VERIFICATION_MODES.has(typeof value === "string" ? value.trim().toLowerCase() : "");
213
237
  }
@@ -220,6 +244,25 @@ function appendStateWarning(state, key, warning) {
220
244
  const existing = Array.isArray(state[key]) ? state[key].filter((item) => typeof item === "string") : [];
221
245
  if (!existing.includes(warning)) state[key] = [...existing, warning];
222
246
  }
247
+ function applyRequestedInteractionRouteContract(state) {
248
+ if (!isInteractionVerificationMode(state.verification_mode)) return;
249
+ const requestedTerminal = requestedExpectedTerminalRouteForState(state);
250
+ if (!requestedTerminal) return;
251
+ state.requested_expected_terminal_path = requestedTerminal;
252
+ if (!stringRecordValue(state, "expected_terminal_path")) {
253
+ state.expected_terminal_path = requestedTerminal;
254
+ }
255
+ const startPath = normalizeRoutePath(state.server_path) || normalizeRoutePath(state.expected_start_path) || "/";
256
+ if (!stringRecordValue(state, "expected_start_path")) {
257
+ state.expected_start_path = startPath;
258
+ }
259
+ const existingContract = state.interaction_contract && typeof state.interaction_contract === "object" ? state.interaction_contract : {};
260
+ state.interaction_contract = {
261
+ ...existingContract,
262
+ start_path: stringRecordValue(existingContract, "start_path") || startPath,
263
+ expected_terminal_path: stringRecordValue(existingContract, "expected_terminal_path") || requestedTerminal
264
+ };
265
+ }
223
266
  function interactionStartPathForAuthorPacket(state, parsed, refined) {
224
267
  return normalizeRoutePath(
225
268
  stringRecordValue(state, "expected_start_path") || stringRecordValue(refined, "expected_start_path") || stringRecordValue(parsed.interaction_contract, "start_path") || stringRecordValue(parsed.proof_contract, "start_path") || stringRecordValue(state, "server_path") || "/"
@@ -262,6 +305,36 @@ function normalizeCaptureScript(value) {
262
305
  const script = normalizeOptionalString(value) || "";
263
306
  return script ? guardProofEvidenceGlobalAssignments(script) : "";
264
307
  }
308
+ function compactCaptureScriptForHeuristics(script) {
309
+ return script.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:])\/\/.*$/gm, "$1 ").replace(/\s+/g, " ").trim().toLowerCase();
310
+ }
311
+ function interactionCaptureScriptLooksPassive(script) {
312
+ const text = compactCaptureScriptForHeuristics(script);
313
+ if (!text) return true;
314
+ const actionPatterns = [
315
+ /\bpage\.(click|dblclick|tap|fill|press|type|check|uncheck|selectoption|dispatch(event)?|goto|reload)\s*\(/,
316
+ /\blocator\s*\([^)]*\)\s*\.\s*(click|dblclick|tap|fill|press|type|check|uncheck|selectoption|dispatch(event)?)\s*\(/,
317
+ /\b(getby(role|text|label|testid|placeholder|title)|getbyalttext)\s*\([^)]*\)\s*\.\s*(click|dblclick|tap|fill|press|type|check|uncheck|selectoption)\s*\(/,
318
+ /\bkeyboard\s*\.\s*(press|type|inserttext)\s*\(/,
319
+ /\bmouse\s*\.\s*(click|dblclick|down|up|move)\s*\(/,
320
+ /\btouchscreen\s*\.\s*tap\s*\(/
321
+ ];
322
+ if (actionPatterns.some((pattern) => pattern.test(text))) return false;
323
+ const evidencePatterns = [
324
+ /\breturn\s+[{[]/,
325
+ /\breturn\s+\w+/,
326
+ /__riddleproofevidence/,
327
+ /\bproof_evidence\b/,
328
+ /\brouteexpectationsource\b/,
329
+ /\bexpectedurl\b/,
330
+ /\bassertions?\b/
331
+ ];
332
+ return !evidencePatterns.some((pattern) => pattern.test(text));
333
+ }
334
+ function setStructuredInteractionCaptureFailure(state, summary) {
335
+ const existing = typeof state.structured_interaction_capture_failure_summary === "string" ? state.structured_interaction_capture_failure_summary.trim() : "";
336
+ if (!existing) state.structured_interaction_capture_failure_summary = summary;
337
+ }
265
338
  function appendProofSummaryLine(state, line) {
266
339
  const text = String(line || "").trim();
267
340
  if (!text) return;
@@ -511,6 +584,9 @@ function proofAssessmentHardBlockersForState(state = {}) {
511
584
  }
512
585
  add(state?.structured_interaction_capture_failure_summary);
513
586
  add(state?.structured_interaction_failure_summary);
587
+ if (isInteractionVerificationMode(normalizedVerificationMode(state)) && !stateHasProofEvidence(state)) {
588
+ add("interaction proof evidence is required before ready_to_ship; proof_evidence_present=false");
589
+ }
514
590
  const mergeRecommendation = String(state?.merge_recommendation || "").trim();
515
591
  if (mergeRecommendation === "do-not-merge" && blockers.length) {
516
592
  add("merge_recommendation=do-not-merge because the proof bundle contains hard blockers.");
@@ -546,7 +622,22 @@ function stateHasAfterEvidence(state = {}) {
546
622
  const observation = objectValue(after.observation);
547
623
  const supporting = objectValue(after.supporting_artifacts);
548
624
  return Boolean(
549
- observation.valid === true && (supporting.has_structured_payload === true || supporting.proof_evidence_present === true || observation.telemetry_ready === true || Object.keys(objectValue(bundle.proof_evidence)).length > 0 || Object.keys(objectValue(after.proof_evidence)).length > 0)
625
+ observation.valid === true && (supporting.has_structured_payload === true || stateHasProofEvidence(state) || observation.telemetry_ready === true)
626
+ );
627
+ }
628
+ function stateHasProofEvidence(state = {}) {
629
+ if (state?.proof_evidence_present === true) return true;
630
+ if (state?.proof_evidence !== void 0 && state?.proof_evidence !== null) {
631
+ if (typeof state.proof_evidence !== "object") return true;
632
+ if (Object.keys(objectValue(state.proof_evidence)).length > 0) return true;
633
+ }
634
+ const bundle = objectValue(state?.evidence_bundle);
635
+ const after = objectValue(bundle.after);
636
+ const supporting = objectValue(after.supporting_artifacts);
637
+ const request = objectValue(state?.proof_assessment_request);
638
+ const structuredEvidence = objectValue(request.structured_evidence);
639
+ return Boolean(
640
+ supporting.proof_evidence_present === true || structuredEvidence.proof_evidence_present === true || Object.keys(objectValue(bundle.proof_evidence)).length > 0 || Object.keys(objectValue(after.proof_evidence)).length > 0
550
641
  );
551
642
  }
552
643
  function validateShipGate(state = {}) {
@@ -888,6 +979,7 @@ function mergeStateFromParams(statePath, params) {
888
979
  if (params.use_auth !== void 0) state.use_auth = params.use_auth ? "true" : "";
889
980
  if (params.leave_draft !== void 0) state.leave_draft = params.leave_draft ? "true" : "";
890
981
  if (params.advance_stage !== void 0) state.last_requested_advance_stage = params.advance_stage;
982
+ applyRequestedInteractionRouteContract(state);
891
983
  if (params.recon_assessment_json !== void 0) {
892
984
  const raw = normalizeOptionalString(params.recon_assessment_json) || "";
893
985
  if (!raw) {
@@ -924,6 +1016,11 @@ function mergeStateFromParams(statePath, params) {
924
1016
  state.supervisor_author_packet = parsed;
925
1017
  if (typeof parsed?.proof_plan === "string") state.proof_plan = normalizeOptionalString(parsed.proof_plan) || "";
926
1018
  if (typeof parsed?.capture_script === "string") state.capture_script = normalizeCaptureScript(parsed.capture_script);
1019
+ if (isInteractionVerificationMode(state.verification_mode) && interactionCaptureScriptLooksPassive(state.capture_script || "")) {
1020
+ const warning = "Interaction proof capture script appears passive: it does not perform a browser interaction or return structured proof evidence.";
1021
+ appendStateWarning(state, "author_warnings", warning);
1022
+ setStructuredInteractionCaptureFailure(state, warning);
1023
+ }
927
1024
  if (parsed?.baseline_understanding_used && typeof parsed.baseline_understanding_used === "object") {
928
1025
  state.author_baseline_understanding_used = parsed.baseline_understanding_used;
929
1026
  }
@@ -65,7 +65,7 @@ function responseSchemaForAuthorPacket() {
65
65
  summary: { type: "string" },
66
66
  payload: {
67
67
  type: "object",
68
- description: "For decision=author_packet, provide the proof packet itself or {author_packet:{...}} with proof_plan, capture_script, and refined_inputs.expected_terminal_path when the proof changes route, query, or hash."
68
+ description: "For decision=author_packet, provide the proof packet itself or {author_packet:{...}} with proof_plan, capture_script, refined_inputs.expected_terminal_path, and interaction_contract when the proof changes route, query, or hash."
69
69
  },
70
70
  reasons: { type: "array", items: { type: "string" } },
71
71
  continue_with_stage: { type: "string", enum: ["author", "recon"] },
@@ -376,6 +376,10 @@ function buildAuthorCheckpointPacket(input) {
376
376
  reference: input.request.reference || fullState.reference,
377
377
  server_path: fullState.server_path,
378
378
  wait_for_selector: fullState.wait_for_selector,
379
+ expected_start_path: fullState.expected_start_path,
380
+ expected_terminal_path: fullState.expected_terminal_path,
381
+ requested_expected_terminal_path: fullState.requested_expected_terminal_path,
382
+ interaction_contract: jsonCloneRecord(fullState.interaction_contract),
379
383
  route_expectation: jsonCloneRecord(fullState.route_expectation),
380
384
  author_summary: fullState.author_summary,
381
385
  author_request: jsonCloneRecord(authorRequest),
@@ -583,9 +587,24 @@ function defaultContinueStage(packet, decision) {
583
587
  }
584
588
  function templatePayloadFor(packet, decision) {
585
589
  if (decision === "author_packet") {
590
+ const expectedTerminalPath = packet.state_excerpt?.expected_terminal_path || packet.state_excerpt?.requested_expected_terminal_path || null;
591
+ const expectedStartPath = packet.state_excerpt?.expected_start_path || packet.state_excerpt?.server_path || null;
586
592
  return {
587
593
  proof_plan: "TODO: describe the exact proof plan and stop condition.",
588
594
  capture_script: "TODO: provide the capture script that collects required artifacts/evidence.",
595
+ refined_inputs: {
596
+ server_path: packet.state_excerpt?.server_path || null,
597
+ wait_for_selector: packet.state_excerpt?.wait_for_selector || null,
598
+ reference: packet.state_excerpt?.reference || null,
599
+ expected_start_path: expectedStartPath,
600
+ expected_terminal_path: expectedTerminalPath
601
+ },
602
+ interaction_contract: {
603
+ start_path: expectedStartPath,
604
+ expected_terminal_path: expectedTerminalPath,
605
+ action: "TODO: describe the browser interaction, for example click the visible Proof nav link.",
606
+ assertions: []
607
+ },
589
608
  summary: "TODO: summarize why this proof packet targets the requested change."
590
609
  };
591
610
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  statePathsForRunState
3
- } from "./chunk-4FOHZ7JG.js";
3
+ } from "./chunk-OILKSY5J.js";
4
4
  import {
5
5
  compactRecord,
6
6
  isTerminalStatus,
@@ -16,7 +16,7 @@ import {
16
16
  validateShipGate,
17
17
  workflowFile,
18
18
  writeState
19
- } from "./chunk-FU73I4V3.js";
19
+ } from "./chunk-K6HZUSHH.js";
20
20
  import {
21
21
  __export
22
22
  } from "./chunk-MLKGABMK.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createRiddleProofRunCard
3
- } from "./chunk-FMOYUYH2.js";
3
+ } from "./chunk-RDPG554T.js";
4
4
  import {
5
5
  compactRecord,
6
6
  isTerminalStatus,
package/dist/cli/index.js CHANGED
@@ -1,12 +1,12 @@
1
- import "../chunk-27AB2TEQ.js";
1
+ import "../chunk-27BG64ZG.js";
2
2
  import "../chunk-PEWAIEER.js";
3
3
  import "../chunk-TWTEUS7R.js";
4
- import "../chunk-2DW2LBUD.js";
5
- import "../chunk-YZUVEJ5B.js";
6
- import "../chunk-FMOYUYH2.js";
7
- import "../chunk-FU73I4V3.js";
8
- import "../chunk-4FOHZ7JG.js";
4
+ import "../chunk-AM3K5FPW.js";
5
+ import "../chunk-ZQWVXQKJ.js";
6
+ import "../chunk-RDPG554T.js";
7
+ import "../chunk-K6HZUSHH.js";
8
+ import "../chunk-OILKSY5J.js";
9
9
  import "../chunk-JFQXAJH2.js";
10
- import "../chunk-EEIYUZXE.js";
10
+ import "../chunk-4PPJKW3Z.js";
11
11
  import "../chunk-VY4Y5U57.js";
12
12
  import "../chunk-MLKGABMK.js";
package/dist/cli.cjs CHANGED
@@ -190,6 +190,30 @@ function normalizeRoutePath(value) {
190
190
  return `${pathname}${query}${hash}`;
191
191
  }
192
192
  }
193
+ function trimRouteCandidate(value) {
194
+ return value.trim().replace(/[),.;\]}]+$/g, "");
195
+ }
196
+ function expectedTerminalRouteFromText(value) {
197
+ const text = typeof value === "string" ? value.trim() : "";
198
+ if (!text) return "";
199
+ const routePattern = "(https?:\\/\\/[^\\s\"'<>`]+|\\/[^\\s\"'<>`]+)";
200
+ const patterns = [
201
+ new RegExp(`\\bexpected\\s+(?:terminal\\s+|final\\s+|after\\s+)?(?:url|route|path)\\s*(?:is|=|:)\\s*${routePattern}`, "i"),
202
+ new RegExp(`\\b(?:terminal|final|after)\\s+(?:url|route|path)\\s*(?:is|=|:)\\s*${routePattern}`, "i"),
203
+ new RegExp(`\\b(?:ends|end|ending|lands|land|landing)\\s+(?:at|on)\\s*${routePattern}`, "i")
204
+ ];
205
+ for (const pattern of patterns) {
206
+ const match = text.match(pattern);
207
+ if (!match) continue;
208
+ const candidate = trimRouteCandidate(match[1] || "");
209
+ const normalized = normalizeRoutePath(candidate);
210
+ if (normalized) return normalized;
211
+ }
212
+ return "";
213
+ }
214
+ function requestedExpectedTerminalRouteForState(state) {
215
+ return expectedTerminalRouteFromText(state.success_criteria) || expectedTerminalRouteFromText(state.change_request) || expectedTerminalRouteFromText(state.context) || expectedTerminalRouteFromText(state.assertions_json);
216
+ }
193
217
  function isInteractionVerificationMode(value) {
194
218
  return INTERACTION_VERIFICATION_MODES.has(typeof value === "string" ? value.trim().toLowerCase() : "");
195
219
  }
@@ -202,6 +226,25 @@ function appendStateWarning(state, key, warning) {
202
226
  const existing = Array.isArray(state[key]) ? state[key].filter((item) => typeof item === "string") : [];
203
227
  if (!existing.includes(warning)) state[key] = [...existing, warning];
204
228
  }
229
+ function applyRequestedInteractionRouteContract(state) {
230
+ if (!isInteractionVerificationMode(state.verification_mode)) return;
231
+ const requestedTerminal = requestedExpectedTerminalRouteForState(state);
232
+ if (!requestedTerminal) return;
233
+ state.requested_expected_terminal_path = requestedTerminal;
234
+ if (!stringRecordValue(state, "expected_terminal_path")) {
235
+ state.expected_terminal_path = requestedTerminal;
236
+ }
237
+ const startPath = normalizeRoutePath(state.server_path) || normalizeRoutePath(state.expected_start_path) || "/";
238
+ if (!stringRecordValue(state, "expected_start_path")) {
239
+ state.expected_start_path = startPath;
240
+ }
241
+ const existingContract = state.interaction_contract && typeof state.interaction_contract === "object" ? state.interaction_contract : {};
242
+ state.interaction_contract = {
243
+ ...existingContract,
244
+ start_path: stringRecordValue(existingContract, "start_path") || startPath,
245
+ expected_terminal_path: stringRecordValue(existingContract, "expected_terminal_path") || requestedTerminal
246
+ };
247
+ }
205
248
  function interactionStartPathForAuthorPacket(state, parsed, refined) {
206
249
  return normalizeRoutePath(
207
250
  stringRecordValue(state, "expected_start_path") || stringRecordValue(refined, "expected_start_path") || stringRecordValue(parsed.interaction_contract, "start_path") || stringRecordValue(parsed.proof_contract, "start_path") || stringRecordValue(state, "server_path") || "/"
@@ -244,6 +287,36 @@ function normalizeCaptureScript(value) {
244
287
  const script = normalizeOptionalString(value) || "";
245
288
  return script ? guardProofEvidenceGlobalAssignments(script) : "";
246
289
  }
290
+ function compactCaptureScriptForHeuristics(script) {
291
+ return script.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:])\/\/.*$/gm, "$1 ").replace(/\s+/g, " ").trim().toLowerCase();
292
+ }
293
+ function interactionCaptureScriptLooksPassive(script) {
294
+ const text = compactCaptureScriptForHeuristics(script);
295
+ if (!text) return true;
296
+ const actionPatterns = [
297
+ /\bpage\.(click|dblclick|tap|fill|press|type|check|uncheck|selectoption|dispatch(event)?|goto|reload)\s*\(/,
298
+ /\blocator\s*\([^)]*\)\s*\.\s*(click|dblclick|tap|fill|press|type|check|uncheck|selectoption|dispatch(event)?)\s*\(/,
299
+ /\b(getby(role|text|label|testid|placeholder|title)|getbyalttext)\s*\([^)]*\)\s*\.\s*(click|dblclick|tap|fill|press|type|check|uncheck|selectoption)\s*\(/,
300
+ /\bkeyboard\s*\.\s*(press|type|inserttext)\s*\(/,
301
+ /\bmouse\s*\.\s*(click|dblclick|down|up|move)\s*\(/,
302
+ /\btouchscreen\s*\.\s*tap\s*\(/
303
+ ];
304
+ if (actionPatterns.some((pattern) => pattern.test(text))) return false;
305
+ const evidencePatterns = [
306
+ /\breturn\s+[{[]/,
307
+ /\breturn\s+\w+/,
308
+ /__riddleproofevidence/,
309
+ /\bproof_evidence\b/,
310
+ /\brouteexpectationsource\b/,
311
+ /\bexpectedurl\b/,
312
+ /\bassertions?\b/
313
+ ];
314
+ return !evidencePatterns.some((pattern) => pattern.test(text));
315
+ }
316
+ function setStructuredInteractionCaptureFailure(state, summary) {
317
+ const existing = typeof state.structured_interaction_capture_failure_summary === "string" ? state.structured_interaction_capture_failure_summary.trim() : "";
318
+ if (!existing) state.structured_interaction_capture_failure_summary = summary;
319
+ }
247
320
  function appendProofSummaryLine(state, line) {
248
321
  const text = String(line || "").trim();
249
322
  if (!text) return;
@@ -484,6 +557,9 @@ function proofAssessmentHardBlockersForState(state = {}) {
484
557
  }
485
558
  add(state?.structured_interaction_capture_failure_summary);
486
559
  add(state?.structured_interaction_failure_summary);
560
+ if (isInteractionVerificationMode(normalizedVerificationMode(state)) && !stateHasProofEvidence(state)) {
561
+ add("interaction proof evidence is required before ready_to_ship; proof_evidence_present=false");
562
+ }
487
563
  const mergeRecommendation = String(state?.merge_recommendation || "").trim();
488
564
  if (mergeRecommendation === "do-not-merge" && blockers.length) {
489
565
  add("merge_recommendation=do-not-merge because the proof bundle contains hard blockers.");
@@ -519,7 +595,22 @@ function stateHasAfterEvidence(state = {}) {
519
595
  const observation = objectValue(after.observation);
520
596
  const supporting = objectValue(after.supporting_artifacts);
521
597
  return Boolean(
522
- observation.valid === true && (supporting.has_structured_payload === true || supporting.proof_evidence_present === true || observation.telemetry_ready === true || Object.keys(objectValue(bundle.proof_evidence)).length > 0 || Object.keys(objectValue(after.proof_evidence)).length > 0)
598
+ observation.valid === true && (supporting.has_structured_payload === true || stateHasProofEvidence(state) || observation.telemetry_ready === true)
599
+ );
600
+ }
601
+ function stateHasProofEvidence(state = {}) {
602
+ if (state?.proof_evidence_present === true) return true;
603
+ if (state?.proof_evidence !== void 0 && state?.proof_evidence !== null) {
604
+ if (typeof state.proof_evidence !== "object") return true;
605
+ if (Object.keys(objectValue(state.proof_evidence)).length > 0) return true;
606
+ }
607
+ const bundle = objectValue(state?.evidence_bundle);
608
+ const after = objectValue(bundle.after);
609
+ const supporting = objectValue(after.supporting_artifacts);
610
+ const request = objectValue(state?.proof_assessment_request);
611
+ const structuredEvidence = objectValue(request.structured_evidence);
612
+ return Boolean(
613
+ supporting.proof_evidence_present === true || structuredEvidence.proof_evidence_present === true || Object.keys(objectValue(bundle.proof_evidence)).length > 0 || Object.keys(objectValue(after.proof_evidence)).length > 0
523
614
  );
524
615
  }
525
616
  function validateShipGate(state = {}) {
@@ -689,6 +780,7 @@ function mergeStateFromParams(statePath, params) {
689
780
  if (params.use_auth !== void 0) state.use_auth = params.use_auth ? "true" : "";
690
781
  if (params.leave_draft !== void 0) state.leave_draft = params.leave_draft ? "true" : "";
691
782
  if (params.advance_stage !== void 0) state.last_requested_advance_stage = params.advance_stage;
783
+ applyRequestedInteractionRouteContract(state);
692
784
  if (params.recon_assessment_json !== void 0) {
693
785
  const raw = normalizeOptionalString(params.recon_assessment_json) || "";
694
786
  if (!raw) {
@@ -725,6 +817,11 @@ function mergeStateFromParams(statePath, params) {
725
817
  state.supervisor_author_packet = parsed;
726
818
  if (typeof parsed?.proof_plan === "string") state.proof_plan = normalizeOptionalString(parsed.proof_plan) || "";
727
819
  if (typeof parsed?.capture_script === "string") state.capture_script = normalizeCaptureScript(parsed.capture_script);
820
+ if (isInteractionVerificationMode(state.verification_mode) && interactionCaptureScriptLooksPassive(state.capture_script || "")) {
821
+ const warning = "Interaction proof capture script appears passive: it does not perform a browser interaction or return structured proof evidence.";
822
+ appendStateWarning(state, "author_warnings", warning);
823
+ setStructuredInteractionCaptureFailure(state, warning);
824
+ }
728
825
  if (parsed?.baseline_understanding_used && typeof parsed.baseline_understanding_used === "object") {
729
826
  state.author_baseline_understanding_used = parsed.baseline_understanding_used;
730
827
  }
@@ -3443,7 +3540,7 @@ function responseSchemaForAuthorPacket() {
3443
3540
  summary: { type: "string" },
3444
3541
  payload: {
3445
3542
  type: "object",
3446
- description: "For decision=author_packet, provide the proof packet itself or {author_packet:{...}} with proof_plan, capture_script, and refined_inputs.expected_terminal_path when the proof changes route, query, or hash."
3543
+ description: "For decision=author_packet, provide the proof packet itself or {author_packet:{...}} with proof_plan, capture_script, refined_inputs.expected_terminal_path, and interaction_contract when the proof changes route, query, or hash."
3447
3544
  },
3448
3545
  reasons: { type: "array", items: { type: "string" } },
3449
3546
  continue_with_stage: { type: "string", enum: ["author", "recon"] },
@@ -3754,6 +3851,10 @@ function buildAuthorCheckpointPacket(input) {
3754
3851
  reference: input.request.reference || fullState.reference,
3755
3852
  server_path: fullState.server_path,
3756
3853
  wait_for_selector: fullState.wait_for_selector,
3854
+ expected_start_path: fullState.expected_start_path,
3855
+ expected_terminal_path: fullState.expected_terminal_path,
3856
+ requested_expected_terminal_path: fullState.requested_expected_terminal_path,
3857
+ interaction_contract: jsonCloneRecord(fullState.interaction_contract),
3757
3858
  route_expectation: jsonCloneRecord(fullState.route_expectation),
3758
3859
  author_summary: fullState.author_summary,
3759
3860
  author_request: jsonCloneRecord(authorRequest),
@@ -3961,9 +4062,24 @@ function defaultContinueStage(packet, decision) {
3961
4062
  }
3962
4063
  function templatePayloadFor(packet, decision) {
3963
4064
  if (decision === "author_packet") {
4065
+ const expectedTerminalPath = packet.state_excerpt?.expected_terminal_path || packet.state_excerpt?.requested_expected_terminal_path || null;
4066
+ const expectedStartPath = packet.state_excerpt?.expected_start_path || packet.state_excerpt?.server_path || null;
3964
4067
  return {
3965
4068
  proof_plan: "TODO: describe the exact proof plan and stop condition.",
3966
4069
  capture_script: "TODO: provide the capture script that collects required artifacts/evidence.",
4070
+ refined_inputs: {
4071
+ server_path: packet.state_excerpt?.server_path || null,
4072
+ wait_for_selector: packet.state_excerpt?.wait_for_selector || null,
4073
+ reference: packet.state_excerpt?.reference || null,
4074
+ expected_start_path: expectedStartPath,
4075
+ expected_terminal_path: expectedTerminalPath
4076
+ },
4077
+ interaction_contract: {
4078
+ start_path: expectedStartPath,
4079
+ expected_terminal_path: expectedTerminalPath,
4080
+ action: "TODO: describe the browser interaction, for example click the visible Proof nav link.",
4081
+ assertions: []
4082
+ },
3967
4083
  summary: "TODO: summarize why this proof packet targets the requested change."
3968
4084
  };
3969
4085
  }
@@ -6126,7 +6242,20 @@ var REFINED_INPUTS_SCHEMA = {
6126
6242
  properties: {
6127
6243
  server_path: { type: ["string", "null"] },
6128
6244
  wait_for_selector: { type: ["string", "null"] },
6129
- reference: { enum: ["before", "prod", "both", null] }
6245
+ reference: { enum: ["before", "prod", "both", null] },
6246
+ expected_start_path: { type: ["string", "null"] },
6247
+ expected_terminal_path: { type: ["string", "null"] }
6248
+ }
6249
+ };
6250
+ var INTERACTION_CONTRACT_SCHEMA = {
6251
+ type: "object",
6252
+ additionalProperties: true,
6253
+ properties: {
6254
+ start_path: { type: ["string", "null"] },
6255
+ expected_terminal_path: { type: ["string", "null"] },
6256
+ expected_url: { type: ["string", "null"] },
6257
+ action: { type: ["string", "null"] },
6258
+ assertions: { type: "array", items: { type: "string" } }
6130
6259
  }
6131
6260
  };
6132
6261
  var BASELINE_UNDERSTANDING_SCHEMA = {
@@ -6196,6 +6325,8 @@ var AUTHOR_SCHEMA = {
6196
6325
  capture_script: { type: "string" },
6197
6326
  baseline_understanding_used: BASELINE_UNDERSTANDING_SCHEMA,
6198
6327
  refined_inputs: REFINED_INPUTS_SCHEMA,
6328
+ expected_terminal_path: { type: ["string", "null"] },
6329
+ interaction_contract: INTERACTION_CONTRACT_SCHEMA,
6199
6330
  rationale: { type: "array", items: { type: "string" } },
6200
6331
  confidence: { type: "string", enum: ["low", "medium", "high"] },
6201
6332
  summary: { type: "string" }
@@ -6803,7 +6934,10 @@ function createCodexExecAgentAdapter(config = {}, runner = createCodexExecJsonRu
6803
6934
  "Do not leave this authoring stage pending for external investigation. Keep any repo inspection brief, do not modify files, and return the JSON proof packet from the available state.",
6804
6935
  "Choose the evidence modality from verification_mode and success_criteria: screenshots for visual/UI proof, interactions plus screenshots for interaction proof, structured metrics/logs/JSON/audio analysis for non-visual proof.",
6805
6936
  "For playable/gameplay proof, treat screenshots as supporting artifacts only: start the game, send keyboard or pointer input, measure state before/after, measure non-HUD canvas/playfield pixel deltas across time, and return playability evidence with version riddle-proof.playability.v1.",
6806
- "For interaction proof, return a structured evidence object with start route/state, terminal route/state, action, assertions, and matched UI text. Catch waitForURL or selector timeouts and record them as failed assertions instead of throwing before evidence is emitted.",
6937
+ "For interaction proof, author the browser action explicitly in capture_script; a wait-only script is invalid. Return a structured evidence object with start route/state, terminal route/state, action, assertions, and matched UI text.",
6938
+ "For route-changing interaction proof, set refined_inputs.expected_start_path and refined_inputs.expected_terminal_path, and include interaction_contract with start_path, expected_terminal_path, action, and assertions. Keep refined_inputs.server_path on the start route; do not replace it with the terminal route.",
6939
+ "If the original request or success_criteria names an expected terminal URL/path, preserve it exactly in refined_inputs.expected_terminal_path and in interaction_contract.expected_terminal_path, including query and hash.",
6940
+ "Catch waitForURL or selector timeouts and record them as failed assertions instead of throwing before evidence is emitted.",
6807
6941
  "For structured proof, collect meaningful measurements inside page.evaluate, assign them to an evidence variable, and return that object from capture_script. Screenshots are optional supporting context for data/audio/log/metric/custom modes.",
6808
6942
  "Do not assign globalThis.__riddleProofEvidence, window.__riddleProofEvidence, or self.__riddleProofEvidence in the worker context. Avoid global evidence assignment unless it is inside page.evaluate for compatibility with older packets.",
6809
6943
  "Do not call Playwright page.* APIs inside page.evaluate; page.evaluate runs in the browser page, while page.waitForFunction, page.waitForSelector, page.click, and saveScreenshot belong in the outer capture script.",
@@ -6817,7 +6951,7 @@ function createCodexExecAgentAdapter(config = {}, runner = createCodexExecJsonRu
6817
6951
  "For visual/UI proof, include saveScreenshot('after-proof') exactly once.",
6818
6952
  "Avoid generic proof language. The packet should be specific enough that verify can tell whether the requested change actually happened.",
6819
6953
  "Echo the baseline understanding you used in baseline_understanding_used so later stages can detect drift.",
6820
- "Use refined_inputs for server_path, wait_for_selector, or reference when useful; use null values when no refinement is needed."
6954
+ "Use refined_inputs for server_path, wait_for_selector, reference, expected_start_path, and expected_terminal_path when useful; use null values when no refinement is needed."
6821
6955
  ].join("\n")
6822
6956
  });
6823
6957
  return payloadOrBlocker(raw, context.checkpoint);
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-27AB2TEQ.js";
2
+ import "./chunk-27BG64ZG.js";
3
3
  import "./chunk-PEWAIEER.js";
4
4
  import "./chunk-TWTEUS7R.js";
5
- import "./chunk-2DW2LBUD.js";
6
- import "./chunk-YZUVEJ5B.js";
7
- import "./chunk-FMOYUYH2.js";
8
- import "./chunk-FU73I4V3.js";
9
- import "./chunk-4FOHZ7JG.js";
5
+ import "./chunk-AM3K5FPW.js";
6
+ import "./chunk-ZQWVXQKJ.js";
7
+ import "./chunk-RDPG554T.js";
8
+ import "./chunk-K6HZUSHH.js";
9
+ import "./chunk-OILKSY5J.js";
10
10
  import "./chunk-JFQXAJH2.js";
11
- import "./chunk-EEIYUZXE.js";
11
+ import "./chunk-4PPJKW3Z.js";
12
12
  import "./chunk-VY4Y5U57.js";
13
13
  import "./chunk-MLKGABMK.js";
@@ -55,7 +55,20 @@ var REFINED_INPUTS_SCHEMA = {
55
55
  properties: {
56
56
  server_path: { type: ["string", "null"] },
57
57
  wait_for_selector: { type: ["string", "null"] },
58
- reference: { enum: ["before", "prod", "both", null] }
58
+ reference: { enum: ["before", "prod", "both", null] },
59
+ expected_start_path: { type: ["string", "null"] },
60
+ expected_terminal_path: { type: ["string", "null"] }
61
+ }
62
+ };
63
+ var INTERACTION_CONTRACT_SCHEMA = {
64
+ type: "object",
65
+ additionalProperties: true,
66
+ properties: {
67
+ start_path: { type: ["string", "null"] },
68
+ expected_terminal_path: { type: ["string", "null"] },
69
+ expected_url: { type: ["string", "null"] },
70
+ action: { type: ["string", "null"] },
71
+ assertions: { type: "array", items: { type: "string" } }
59
72
  }
60
73
  };
61
74
  var BASELINE_UNDERSTANDING_SCHEMA = {
@@ -125,6 +138,8 @@ var AUTHOR_SCHEMA = {
125
138
  capture_script: { type: "string" },
126
139
  baseline_understanding_used: BASELINE_UNDERSTANDING_SCHEMA,
127
140
  refined_inputs: REFINED_INPUTS_SCHEMA,
141
+ expected_terminal_path: { type: ["string", "null"] },
142
+ interaction_contract: INTERACTION_CONTRACT_SCHEMA,
128
143
  rationale: { type: "array", items: { type: "string" } },
129
144
  confidence: { type: "string", enum: ["low", "medium", "high"] },
130
145
  summary: { type: "string" }
@@ -732,7 +747,10 @@ function createCodexExecAgentAdapter(config = {}, runner = createCodexExecJsonRu
732
747
  "Do not leave this authoring stage pending for external investigation. Keep any repo inspection brief, do not modify files, and return the JSON proof packet from the available state.",
733
748
  "Choose the evidence modality from verification_mode and success_criteria: screenshots for visual/UI proof, interactions plus screenshots for interaction proof, structured metrics/logs/JSON/audio analysis for non-visual proof.",
734
749
  "For playable/gameplay proof, treat screenshots as supporting artifacts only: start the game, send keyboard or pointer input, measure state before/after, measure non-HUD canvas/playfield pixel deltas across time, and return playability evidence with version riddle-proof.playability.v1.",
735
- "For interaction proof, return a structured evidence object with start route/state, terminal route/state, action, assertions, and matched UI text. Catch waitForURL or selector timeouts and record them as failed assertions instead of throwing before evidence is emitted.",
750
+ "For interaction proof, author the browser action explicitly in capture_script; a wait-only script is invalid. Return a structured evidence object with start route/state, terminal route/state, action, assertions, and matched UI text.",
751
+ "For route-changing interaction proof, set refined_inputs.expected_start_path and refined_inputs.expected_terminal_path, and include interaction_contract with start_path, expected_terminal_path, action, and assertions. Keep refined_inputs.server_path on the start route; do not replace it with the terminal route.",
752
+ "If the original request or success_criteria names an expected terminal URL/path, preserve it exactly in refined_inputs.expected_terminal_path and in interaction_contract.expected_terminal_path, including query and hash.",
753
+ "Catch waitForURL or selector timeouts and record them as failed assertions instead of throwing before evidence is emitted.",
736
754
  "For structured proof, collect meaningful measurements inside page.evaluate, assign them to an evidence variable, and return that object from capture_script. Screenshots are optional supporting context for data/audio/log/metric/custom modes.",
737
755
  "Do not assign globalThis.__riddleProofEvidence, window.__riddleProofEvidence, or self.__riddleProofEvidence in the worker context. Avoid global evidence assignment unless it is inside page.evaluate for compatibility with older packets.",
738
756
  "Do not call Playwright page.* APIs inside page.evaluate; page.evaluate runs in the browser page, while page.waitForFunction, page.waitForSelector, page.click, and saveScreenshot belong in the outer capture script.",
@@ -746,7 +764,7 @@ function createCodexExecAgentAdapter(config = {}, runner = createCodexExecJsonRu
746
764
  "For visual/UI proof, include saveScreenshot('after-proof') exactly once.",
747
765
  "Avoid generic proof language. The packet should be specific enough that verify can tell whether the requested change actually happened.",
748
766
  "Echo the baseline understanding you used in baseline_understanding_used so later stages can detect drift.",
749
- "Use refined_inputs for server_path, wait_for_selector, or reference when useful; use null values when no refinement is needed."
767
+ "Use refined_inputs for server_path, wait_for_selector, reference, expected_start_path, and expected_terminal_path when useful; use null values when no refinement is needed."
750
768
  ].join("\n")
751
769
  });
752
770
  return payloadOrBlocker(raw, context.checkpoint);
@@ -2,7 +2,7 @@ import {
2
2
  createCodexExecAgentAdapter,
3
3
  createCodexExecJsonRunner,
4
4
  runCodexExecAgentDoctor
5
- } from "./chunk-EEIYUZXE.js";
5
+ } from "./chunk-4PPJKW3Z.js";
6
6
  import "./chunk-VY4Y5U57.js";
7
7
  import "./chunk-MLKGABMK.js";
8
8
  export {