@riddledc/riddle-proof 0.7.108 → 0.7.110

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -276,6 +276,14 @@ request-body fields may also be placed on individual `responses[]` entries when
276
276
  each step has a different request contract, such as a fail-then-success retry
277
277
  where the second request must carry newer state.
278
278
 
279
+ When `responses[]` entries include request-body predicates, the runner selects
280
+ the first response whose request-body contract matches the actual request before
281
+ falling back to sequence order. This keeps repeated multi-viewport profiles from
282
+ misrouting interleaved requests while preserving sequence behavior for response
283
+ lists that do not declare body-specific contracts. The proof evidence records
284
+ `response_selection: "request_body"` and the original `sequence_response_index`
285
+ when body matching overrides sequence order.
286
+
279
287
  `target.setup_actions` is optional. Use it when the meaningful proof surface
280
288
  appears only after a picker, tab, login stub, storage seed, form fill,
281
289
  transport control, or other bounded interaction. Supported setup actions are
@@ -526,8 +534,13 @@ artifact links should fail the profile:
526
534
  ```
527
535
 
528
536
  The check defaults to `a[href]`, deduplicates URLs, probes up to 100 selected
529
- URLs, and treats HTTP `2xx` / `3xx` responses as healthy. Use
530
- `allowed_statuses` or `expected_status` when a narrower status contract is
537
+ URLs, and treats HTTP `2xx` / `3xx` responses as healthy. `expected_count` and
538
+ `min_count` apply to the probed URL set after same-origin filtering, URL
539
+ deduplication, and the `max_links` limit. The run summary also reports
540
+ `discovered_count` when it differs, which helps explain cases where a page has
541
+ two DOM nodes pointing at the same artifact URL. Use `dedupe: false` when the
542
+ contract should count duplicate DOM candidates instead of unique artifact URLs.
543
+ Use `allowed_statuses` or `expected_status` when a narrower status contract is
531
544
  intentional, `min_count` for lower-bound audits, `min_bytes` when a one-byte
532
545
  range response is too weak, `allowed_content_types` for MIME checks, and
533
546
  `max_links` when the selected set is intentionally larger than 100.
@@ -3816,6 +3816,14 @@ function networkMockShouldCaptureRequestBody(...sources) {
3816
3816
  || networkMockStringList(source.request_body_not_patterns).length > 0
3817
3817
  ));
3818
3818
  }
3819
+ function networkMockHasRequestBodyContract(source) {
3820
+ return Boolean(source) && (
3821
+ networkMockStringList(source.request_body_contains).length > 0
3822
+ || networkMockStringList(source.request_body_patterns).length > 0
3823
+ || networkMockStringList(source.request_body_not_contains).length > 0
3824
+ || networkMockStringList(source.request_body_not_patterns).length > 0
3825
+ );
3826
+ }
3819
3827
  function networkMockRequestBodyFailuresForSource(body, source) {
3820
3828
  const failures = [];
3821
3829
  if (!source) return failures;
@@ -3876,6 +3884,15 @@ function networkMockRequestBodyFailuresForSource(body, source) {
3876
3884
  function networkMockRequestBodyFailures(body, ...sources) {
3877
3885
  return sources.flatMap((source) => networkMockRequestBodyFailuresForSource(body, source));
3878
3886
  }
3887
+ function selectNetworkMockResponseByRequestBody(mock, responses, requestBody) {
3888
+ if (!Array.isArray(responses) || !responses.length) return null;
3889
+ const candidates = responses
3890
+ .map((response, index) => ({ response, index }))
3891
+ .filter((candidate) => networkMockHasRequestBodyContract(candidate.response));
3892
+ if (!candidates.length) return null;
3893
+ const matched = candidates.find((candidate) => networkMockRequestBodyFailures(requestBody, mock, candidate.response).length === 0);
3894
+ return matched ? matched.index : null;
3895
+ }
3879
3896
  async function setupLocatorVisible(locator, index) {
3880
3897
  return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
3881
3898
  }
@@ -3897,9 +3914,20 @@ async function registerNetworkMocks(mocks) {
3897
3914
  const responses = Array.isArray(mock.responses) ? mock.responses : [];
3898
3915
  const hitIndex = hitCount;
3899
3916
  hitCount += 1;
3900
- const responseIndex = responses.length
3917
+ const sequenceResponseIndex = responses.length
3901
3918
  ? (mock.repeat_responses ? hitIndex % responses.length : Math.min(hitIndex, responses.length - 1))
3902
3919
  : null;
3920
+ let responseIndex = sequenceResponseIndex;
3921
+ let responseSelection = responseIndex === null ? "mock" : "sequence";
3922
+ const shouldCaptureRequestBodyForAnyResponse = networkMockShouldCaptureRequestBody(mock, ...responses);
3923
+ const requestBody = shouldCaptureRequestBodyForAnyResponse && request.postData ? request.postData() || "" : "";
3924
+ const requestBodyResponseIndex = shouldCaptureRequestBodyForAnyResponse
3925
+ ? selectNetworkMockResponseByRequestBody(mock, responses, requestBody)
3926
+ : null;
3927
+ if (requestBodyResponseIndex !== null) {
3928
+ responseIndex = requestBodyResponseIndex;
3929
+ responseSelection = "request_body";
3930
+ }
3903
3931
  const response = responseIndex === null ? mock : responses[responseIndex];
3904
3932
  const headers = { ...(response.headers || mock.headers || {}) };
3905
3933
  let body = response.body || "";
@@ -3909,8 +3937,7 @@ async function registerNetworkMocks(mocks) {
3909
3937
  contentType = response.content_type || headers["content-type"] || headers["Content-Type"] || "application/json";
3910
3938
  }
3911
3939
  const responseBodyContract = responseIndex === null ? null : response;
3912
- const shouldCaptureRequestBody = networkMockShouldCaptureRequestBody(mock, responseBodyContract);
3913
- const requestBody = shouldCaptureRequestBody && request.postData ? request.postData() || "" : "";
3940
+ const shouldCaptureRequestBody = shouldCaptureRequestBodyForAnyResponse || networkMockShouldCaptureRequestBody(mock, responseBodyContract);
3914
3941
  const requestBodyFailures = shouldCaptureRequestBody ? networkMockRequestBodyFailures(requestBody, mock, responseBodyContract) : [];
3915
3942
  const status = response.status || mock.status || 200;
3916
3943
  const delayMs = numberValue(response.delay_ms) || 0;
@@ -3920,8 +3947,10 @@ async function registerNetworkMocks(mocks) {
3920
3947
  response_label: response.label || null,
3921
3948
  hit_index: hitIndex,
3922
3949
  response_index: responseIndex,
3923
- sequence_reused: responseIndex !== null && !mock.repeat_responses && hitIndex >= responses.length,
3924
- sequence_cycle: responseIndex !== null && mock.repeat_responses === true && hitIndex >= responses.length,
3950
+ sequence_response_index: responseSelection === "request_body" ? sequenceResponseIndex : undefined,
3951
+ response_selection: responseIndex === null ? null : responseSelection,
3952
+ sequence_reused: responseSelection === "sequence" && responseIndex !== null && !mock.repeat_responses && hitIndex >= responses.length,
3953
+ sequence_cycle: responseSelection === "sequence" && responseIndex !== null && mock.repeat_responses === true && hitIndex >= responses.length,
3925
3954
  url: request.url(),
3926
3955
  method,
3927
3956
  status,
package/dist/cli.cjs CHANGED
@@ -10693,6 +10693,14 @@ function networkMockShouldCaptureRequestBody(...sources) {
10693
10693
  || networkMockStringList(source.request_body_not_patterns).length > 0
10694
10694
  ));
10695
10695
  }
10696
+ function networkMockHasRequestBodyContract(source) {
10697
+ return Boolean(source) && (
10698
+ networkMockStringList(source.request_body_contains).length > 0
10699
+ || networkMockStringList(source.request_body_patterns).length > 0
10700
+ || networkMockStringList(source.request_body_not_contains).length > 0
10701
+ || networkMockStringList(source.request_body_not_patterns).length > 0
10702
+ );
10703
+ }
10696
10704
  function networkMockRequestBodyFailuresForSource(body, source) {
10697
10705
  const failures = [];
10698
10706
  if (!source) return failures;
@@ -10753,6 +10761,15 @@ function networkMockRequestBodyFailuresForSource(body, source) {
10753
10761
  function networkMockRequestBodyFailures(body, ...sources) {
10754
10762
  return sources.flatMap((source) => networkMockRequestBodyFailuresForSource(body, source));
10755
10763
  }
10764
+ function selectNetworkMockResponseByRequestBody(mock, responses, requestBody) {
10765
+ if (!Array.isArray(responses) || !responses.length) return null;
10766
+ const candidates = responses
10767
+ .map((response, index) => ({ response, index }))
10768
+ .filter((candidate) => networkMockHasRequestBodyContract(candidate.response));
10769
+ if (!candidates.length) return null;
10770
+ const matched = candidates.find((candidate) => networkMockRequestBodyFailures(requestBody, mock, candidate.response).length === 0);
10771
+ return matched ? matched.index : null;
10772
+ }
10756
10773
  async function setupLocatorVisible(locator, index) {
10757
10774
  return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
10758
10775
  }
@@ -10774,9 +10791,20 @@ async function registerNetworkMocks(mocks) {
10774
10791
  const responses = Array.isArray(mock.responses) ? mock.responses : [];
10775
10792
  const hitIndex = hitCount;
10776
10793
  hitCount += 1;
10777
- const responseIndex = responses.length
10794
+ const sequenceResponseIndex = responses.length
10778
10795
  ? (mock.repeat_responses ? hitIndex % responses.length : Math.min(hitIndex, responses.length - 1))
10779
10796
  : null;
10797
+ let responseIndex = sequenceResponseIndex;
10798
+ let responseSelection = responseIndex === null ? "mock" : "sequence";
10799
+ const shouldCaptureRequestBodyForAnyResponse = networkMockShouldCaptureRequestBody(mock, ...responses);
10800
+ const requestBody = shouldCaptureRequestBodyForAnyResponse && request.postData ? request.postData() || "" : "";
10801
+ const requestBodyResponseIndex = shouldCaptureRequestBodyForAnyResponse
10802
+ ? selectNetworkMockResponseByRequestBody(mock, responses, requestBody)
10803
+ : null;
10804
+ if (requestBodyResponseIndex !== null) {
10805
+ responseIndex = requestBodyResponseIndex;
10806
+ responseSelection = "request_body";
10807
+ }
10780
10808
  const response = responseIndex === null ? mock : responses[responseIndex];
10781
10809
  const headers = { ...(response.headers || mock.headers || {}) };
10782
10810
  let body = response.body || "";
@@ -10786,8 +10814,7 @@ async function registerNetworkMocks(mocks) {
10786
10814
  contentType = response.content_type || headers["content-type"] || headers["Content-Type"] || "application/json";
10787
10815
  }
10788
10816
  const responseBodyContract = responseIndex === null ? null : response;
10789
- const shouldCaptureRequestBody = networkMockShouldCaptureRequestBody(mock, responseBodyContract);
10790
- const requestBody = shouldCaptureRequestBody && request.postData ? request.postData() || "" : "";
10817
+ const shouldCaptureRequestBody = shouldCaptureRequestBodyForAnyResponse || networkMockShouldCaptureRequestBody(mock, responseBodyContract);
10791
10818
  const requestBodyFailures = shouldCaptureRequestBody ? networkMockRequestBodyFailures(requestBody, mock, responseBodyContract) : [];
10792
10819
  const status = response.status || mock.status || 200;
10793
10820
  const delayMs = numberValue(response.delay_ms) || 0;
@@ -10797,8 +10824,10 @@ async function registerNetworkMocks(mocks) {
10797
10824
  response_label: response.label || null,
10798
10825
  hit_index: hitIndex,
10799
10826
  response_index: responseIndex,
10800
- sequence_reused: responseIndex !== null && !mock.repeat_responses && hitIndex >= responses.length,
10801
- sequence_cycle: responseIndex !== null && mock.repeat_responses === true && hitIndex >= responses.length,
10827
+ sequence_response_index: responseSelection === "request_body" ? sequenceResponseIndex : undefined,
10828
+ response_selection: responseIndex === null ? null : responseSelection,
10829
+ sequence_reused: responseSelection === "sequence" && responseIndex !== null && !mock.repeat_responses && hitIndex >= responses.length,
10830
+ sequence_cycle: responseSelection === "sequence" && responseIndex !== null && mock.repeat_responses === true && hitIndex >= responses.length,
10802
10831
  url: request.url(),
10803
10832
  method,
10804
10833
  status,
@@ -12911,8 +12940,8 @@ function profileCheckMarkdownTarget(check) {
12911
12940
  const minCount = cliFiniteNumber(evidence.min_count);
12912
12941
  const minBytes = cliFiniteNumber(evidence.min_bytes);
12913
12942
  const parts = [];
12914
- if (expectedCount !== void 0) parts.push(`links = ${expectedCount}`);
12915
- else if (minCount !== void 0) parts.push(`links >= ${minCount}`);
12943
+ if (expectedCount !== void 0) parts.push(`probed links = ${expectedCount}`);
12944
+ else if (minCount !== void 0) parts.push(`probed links >= ${minCount}`);
12916
12945
  if (minBytes !== void 0) parts.push(`bytes >= ${minBytes}`);
12917
12946
  if (selector && parts.length) return `${markdownInlineCode(selector)} ${parts.join(", ")}`;
12918
12947
  return selector ? markdownInlineCode(selector) : parts.join(", ") || void 0;
@@ -13124,6 +13153,7 @@ function profileLinkStatusSummaryMarkdown(result) {
13124
13153
  const selector = cliString(evidence.selector);
13125
13154
  const viewports = Array.isArray(evidence.viewports) ? evidence.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
13126
13155
  const totals = viewports.map((viewport) => cliFiniteNumber(viewport.total_count)).filter((count) => count !== void 0);
13156
+ const discoveredTotals = viewports.map((viewport) => cliFiniteNumber(viewport.discovered_count)).filter((count) => count !== void 0);
13127
13157
  const okTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.ok_count) || 0), 0);
13128
13158
  const failedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.failed_count) || 0), 0);
13129
13159
  const truncatedTotal = viewports.filter((viewport) => viewport.truncated === true).length;
@@ -13131,8 +13161,9 @@ function profileLinkStatusSummaryMarkdown(result) {
13131
13161
  const minBytes = cliFiniteNumber(evidence.min_bytes);
13132
13162
  const allowedContentTypes = Array.isArray(evidence.allowed_content_types) ? evidence.allowed_content_types.map(cliString).filter((value) => Boolean(value)) : [];
13133
13163
  const countText = totals.length ? totals.join("/") : "unknown";
13164
+ const discoveredText = discoveredTotals.length && discoveredTotals.some((count, index) => count !== totals[index]) ? `, discovered ${discoveredTotals.join("/")}` : "";
13134
13165
  lines.push(
13135
- `- ${label}${selector ? ` ${markdownInlineCode(selector)}` : ""}: links ${countText}, ok ${okTotal}, failures ${failedTotal}${omittedTotal ? `, compacted ${omittedTotal} result row(s)` : ""}${truncatedTotal ? `, truncated viewports ${truncatedTotal}` : ""}${minBytes !== void 0 ? `, min bytes ${minBytes}` : ""}${allowedContentTypes.length ? `, content types ${allowedContentTypes.map((value) => markdownInlineCode(value)).join(", ")}` : ""}`
13166
+ `- ${label}${selector ? ` ${markdownInlineCode(selector)}` : ""}: probed links ${countText}${discoveredText}, ok ${okTotal}, failures ${failedTotal}${omittedTotal ? `, compacted ${omittedTotal} result row(s)` : ""}${truncatedTotal ? `, truncated viewports ${truncatedTotal}` : ""}${minBytes !== void 0 ? `, min bytes ${minBytes}` : ""}${allowedContentTypes.length ? `, content types ${allowedContentTypes.map((value) => markdownInlineCode(value)).join(", ")}` : ""}`
13136
13167
  );
13137
13168
  }
13138
13169
  return lines;
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  profileStatusExitCode,
11
11
  resolveRiddleProofProfileTargetUrl,
12
12
  resolveRiddleProofProfileTimeoutSec
13
- } from "./chunk-NPNALRHV.js";
13
+ } from "./chunk-KKH76HIA.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport
@@ -438,8 +438,8 @@ function profileCheckMarkdownTarget(check) {
438
438
  const minCount = cliFiniteNumber(evidence.min_count);
439
439
  const minBytes = cliFiniteNumber(evidence.min_bytes);
440
440
  const parts = [];
441
- if (expectedCount !== void 0) parts.push(`links = ${expectedCount}`);
442
- else if (minCount !== void 0) parts.push(`links >= ${minCount}`);
441
+ if (expectedCount !== void 0) parts.push(`probed links = ${expectedCount}`);
442
+ else if (minCount !== void 0) parts.push(`probed links >= ${minCount}`);
443
443
  if (minBytes !== void 0) parts.push(`bytes >= ${minBytes}`);
444
444
  if (selector && parts.length) return `${markdownInlineCode(selector)} ${parts.join(", ")}`;
445
445
  return selector ? markdownInlineCode(selector) : parts.join(", ") || void 0;
@@ -651,6 +651,7 @@ function profileLinkStatusSummaryMarkdown(result) {
651
651
  const selector = cliString(evidence.selector);
652
652
  const viewports = Array.isArray(evidence.viewports) ? evidence.viewports.map(cliRecord).filter((viewport) => Boolean(viewport)) : [];
653
653
  const totals = viewports.map((viewport) => cliFiniteNumber(viewport.total_count)).filter((count) => count !== void 0);
654
+ const discoveredTotals = viewports.map((viewport) => cliFiniteNumber(viewport.discovered_count)).filter((count) => count !== void 0);
654
655
  const okTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.ok_count) || 0), 0);
655
656
  const failedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.failed_count) || 0), 0);
656
657
  const truncatedTotal = viewports.filter((viewport) => viewport.truncated === true).length;
@@ -658,8 +659,9 @@ function profileLinkStatusSummaryMarkdown(result) {
658
659
  const minBytes = cliFiniteNumber(evidence.min_bytes);
659
660
  const allowedContentTypes = Array.isArray(evidence.allowed_content_types) ? evidence.allowed_content_types.map(cliString).filter((value) => Boolean(value)) : [];
660
661
  const countText = totals.length ? totals.join("/") : "unknown";
662
+ const discoveredText = discoveredTotals.length && discoveredTotals.some((count, index) => count !== totals[index]) ? `, discovered ${discoveredTotals.join("/")}` : "";
661
663
  lines.push(
662
- `- ${label}${selector ? ` ${markdownInlineCode(selector)}` : ""}: links ${countText}, ok ${okTotal}, failures ${failedTotal}${omittedTotal ? `, compacted ${omittedTotal} result row(s)` : ""}${truncatedTotal ? `, truncated viewports ${truncatedTotal}` : ""}${minBytes !== void 0 ? `, min bytes ${minBytes}` : ""}${allowedContentTypes.length ? `, content types ${allowedContentTypes.map((value) => markdownInlineCode(value)).join(", ")}` : ""}`
664
+ `- ${label}${selector ? ` ${markdownInlineCode(selector)}` : ""}: probed links ${countText}${discoveredText}, ok ${okTotal}, failures ${failedTotal}${omittedTotal ? `, compacted ${omittedTotal} result row(s)` : ""}${truncatedTotal ? `, truncated viewports ${truncatedTotal}` : ""}${minBytes !== void 0 ? `, min bytes ${minBytes}` : ""}${allowedContentTypes.length ? `, content types ${allowedContentTypes.map((value) => markdownInlineCode(value)).join(", ")}` : ""}`
663
665
  );
664
666
  }
665
667
  return lines;
package/dist/index.cjs CHANGED
@@ -12545,6 +12545,14 @@ function networkMockShouldCaptureRequestBody(...sources) {
12545
12545
  || networkMockStringList(source.request_body_not_patterns).length > 0
12546
12546
  ));
12547
12547
  }
12548
+ function networkMockHasRequestBodyContract(source) {
12549
+ return Boolean(source) && (
12550
+ networkMockStringList(source.request_body_contains).length > 0
12551
+ || networkMockStringList(source.request_body_patterns).length > 0
12552
+ || networkMockStringList(source.request_body_not_contains).length > 0
12553
+ || networkMockStringList(source.request_body_not_patterns).length > 0
12554
+ );
12555
+ }
12548
12556
  function networkMockRequestBodyFailuresForSource(body, source) {
12549
12557
  const failures = [];
12550
12558
  if (!source) return failures;
@@ -12605,6 +12613,15 @@ function networkMockRequestBodyFailuresForSource(body, source) {
12605
12613
  function networkMockRequestBodyFailures(body, ...sources) {
12606
12614
  return sources.flatMap((source) => networkMockRequestBodyFailuresForSource(body, source));
12607
12615
  }
12616
+ function selectNetworkMockResponseByRequestBody(mock, responses, requestBody) {
12617
+ if (!Array.isArray(responses) || !responses.length) return null;
12618
+ const candidates = responses
12619
+ .map((response, index) => ({ response, index }))
12620
+ .filter((candidate) => networkMockHasRequestBodyContract(candidate.response));
12621
+ if (!candidates.length) return null;
12622
+ const matched = candidates.find((candidate) => networkMockRequestBodyFailures(requestBody, mock, candidate.response).length === 0);
12623
+ return matched ? matched.index : null;
12624
+ }
12608
12625
  async function setupLocatorVisible(locator, index) {
12609
12626
  return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
12610
12627
  }
@@ -12626,9 +12643,20 @@ async function registerNetworkMocks(mocks) {
12626
12643
  const responses = Array.isArray(mock.responses) ? mock.responses : [];
12627
12644
  const hitIndex = hitCount;
12628
12645
  hitCount += 1;
12629
- const responseIndex = responses.length
12646
+ const sequenceResponseIndex = responses.length
12630
12647
  ? (mock.repeat_responses ? hitIndex % responses.length : Math.min(hitIndex, responses.length - 1))
12631
12648
  : null;
12649
+ let responseIndex = sequenceResponseIndex;
12650
+ let responseSelection = responseIndex === null ? "mock" : "sequence";
12651
+ const shouldCaptureRequestBodyForAnyResponse = networkMockShouldCaptureRequestBody(mock, ...responses);
12652
+ const requestBody = shouldCaptureRequestBodyForAnyResponse && request.postData ? request.postData() || "" : "";
12653
+ const requestBodyResponseIndex = shouldCaptureRequestBodyForAnyResponse
12654
+ ? selectNetworkMockResponseByRequestBody(mock, responses, requestBody)
12655
+ : null;
12656
+ if (requestBodyResponseIndex !== null) {
12657
+ responseIndex = requestBodyResponseIndex;
12658
+ responseSelection = "request_body";
12659
+ }
12632
12660
  const response = responseIndex === null ? mock : responses[responseIndex];
12633
12661
  const headers = { ...(response.headers || mock.headers || {}) };
12634
12662
  let body = response.body || "";
@@ -12638,8 +12666,7 @@ async function registerNetworkMocks(mocks) {
12638
12666
  contentType = response.content_type || headers["content-type"] || headers["Content-Type"] || "application/json";
12639
12667
  }
12640
12668
  const responseBodyContract = responseIndex === null ? null : response;
12641
- const shouldCaptureRequestBody = networkMockShouldCaptureRequestBody(mock, responseBodyContract);
12642
- const requestBody = shouldCaptureRequestBody && request.postData ? request.postData() || "" : "";
12669
+ const shouldCaptureRequestBody = shouldCaptureRequestBodyForAnyResponse || networkMockShouldCaptureRequestBody(mock, responseBodyContract);
12643
12670
  const requestBodyFailures = shouldCaptureRequestBody ? networkMockRequestBodyFailures(requestBody, mock, responseBodyContract) : [];
12644
12671
  const status = response.status || mock.status || 200;
12645
12672
  const delayMs = numberValue(response.delay_ms) || 0;
@@ -12649,8 +12676,10 @@ async function registerNetworkMocks(mocks) {
12649
12676
  response_label: response.label || null,
12650
12677
  hit_index: hitIndex,
12651
12678
  response_index: responseIndex,
12652
- sequence_reused: responseIndex !== null && !mock.repeat_responses && hitIndex >= responses.length,
12653
- sequence_cycle: responseIndex !== null && mock.repeat_responses === true && hitIndex >= responses.length,
12679
+ sequence_response_index: responseSelection === "request_body" ? sequenceResponseIndex : undefined,
12680
+ response_selection: responseIndex === null ? null : responseSelection,
12681
+ sequence_reused: responseSelection === "sequence" && responseIndex !== null && !mock.repeat_responses && hitIndex >= responses.length,
12682
+ sequence_cycle: responseSelection === "sequence" && responseIndex !== null && mock.repeat_responses === true && hitIndex >= responses.length,
12654
12683
  url: request.url(),
12655
12684
  method,
12656
12685
  status,
package/dist/index.js CHANGED
@@ -58,7 +58,7 @@ import {
58
58
  resolveRiddleProofProfileTimeoutSec,
59
59
  slugifyRiddleProofProfileName,
60
60
  summarizeRiddleProofProfileResult
61
- } from "./chunk-NPNALRHV.js";
61
+ } from "./chunk-KKH76HIA.js";
62
62
  import {
63
63
  DEFAULT_RIDDLE_API_BASE_URL,
64
64
  DEFAULT_RIDDLE_API_KEY_FILE,
package/dist/profile.cjs CHANGED
@@ -3859,6 +3859,14 @@ function networkMockShouldCaptureRequestBody(...sources) {
3859
3859
  || networkMockStringList(source.request_body_not_patterns).length > 0
3860
3860
  ));
3861
3861
  }
3862
+ function networkMockHasRequestBodyContract(source) {
3863
+ return Boolean(source) && (
3864
+ networkMockStringList(source.request_body_contains).length > 0
3865
+ || networkMockStringList(source.request_body_patterns).length > 0
3866
+ || networkMockStringList(source.request_body_not_contains).length > 0
3867
+ || networkMockStringList(source.request_body_not_patterns).length > 0
3868
+ );
3869
+ }
3862
3870
  function networkMockRequestBodyFailuresForSource(body, source) {
3863
3871
  const failures = [];
3864
3872
  if (!source) return failures;
@@ -3919,6 +3927,15 @@ function networkMockRequestBodyFailuresForSource(body, source) {
3919
3927
  function networkMockRequestBodyFailures(body, ...sources) {
3920
3928
  return sources.flatMap((source) => networkMockRequestBodyFailuresForSource(body, source));
3921
3929
  }
3930
+ function selectNetworkMockResponseByRequestBody(mock, responses, requestBody) {
3931
+ if (!Array.isArray(responses) || !responses.length) return null;
3932
+ const candidates = responses
3933
+ .map((response, index) => ({ response, index }))
3934
+ .filter((candidate) => networkMockHasRequestBodyContract(candidate.response));
3935
+ if (!candidates.length) return null;
3936
+ const matched = candidates.find((candidate) => networkMockRequestBodyFailures(requestBody, mock, candidate.response).length === 0);
3937
+ return matched ? matched.index : null;
3938
+ }
3922
3939
  async function setupLocatorVisible(locator, index) {
3923
3940
  return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
3924
3941
  }
@@ -3940,9 +3957,20 @@ async function registerNetworkMocks(mocks) {
3940
3957
  const responses = Array.isArray(mock.responses) ? mock.responses : [];
3941
3958
  const hitIndex = hitCount;
3942
3959
  hitCount += 1;
3943
- const responseIndex = responses.length
3960
+ const sequenceResponseIndex = responses.length
3944
3961
  ? (mock.repeat_responses ? hitIndex % responses.length : Math.min(hitIndex, responses.length - 1))
3945
3962
  : null;
3963
+ let responseIndex = sequenceResponseIndex;
3964
+ let responseSelection = responseIndex === null ? "mock" : "sequence";
3965
+ const shouldCaptureRequestBodyForAnyResponse = networkMockShouldCaptureRequestBody(mock, ...responses);
3966
+ const requestBody = shouldCaptureRequestBodyForAnyResponse && request.postData ? request.postData() || "" : "";
3967
+ const requestBodyResponseIndex = shouldCaptureRequestBodyForAnyResponse
3968
+ ? selectNetworkMockResponseByRequestBody(mock, responses, requestBody)
3969
+ : null;
3970
+ if (requestBodyResponseIndex !== null) {
3971
+ responseIndex = requestBodyResponseIndex;
3972
+ responseSelection = "request_body";
3973
+ }
3946
3974
  const response = responseIndex === null ? mock : responses[responseIndex];
3947
3975
  const headers = { ...(response.headers || mock.headers || {}) };
3948
3976
  let body = response.body || "";
@@ -3952,8 +3980,7 @@ async function registerNetworkMocks(mocks) {
3952
3980
  contentType = response.content_type || headers["content-type"] || headers["Content-Type"] || "application/json";
3953
3981
  }
3954
3982
  const responseBodyContract = responseIndex === null ? null : response;
3955
- const shouldCaptureRequestBody = networkMockShouldCaptureRequestBody(mock, responseBodyContract);
3956
- const requestBody = shouldCaptureRequestBody && request.postData ? request.postData() || "" : "";
3983
+ const shouldCaptureRequestBody = shouldCaptureRequestBodyForAnyResponse || networkMockShouldCaptureRequestBody(mock, responseBodyContract);
3957
3984
  const requestBodyFailures = shouldCaptureRequestBody ? networkMockRequestBodyFailures(requestBody, mock, responseBodyContract) : [];
3958
3985
  const status = response.status || mock.status || 200;
3959
3986
  const delayMs = numberValue(response.delay_ms) || 0;
@@ -3963,8 +3990,10 @@ async function registerNetworkMocks(mocks) {
3963
3990
  response_label: response.label || null,
3964
3991
  hit_index: hitIndex,
3965
3992
  response_index: responseIndex,
3966
- sequence_reused: responseIndex !== null && !mock.repeat_responses && hitIndex >= responses.length,
3967
- sequence_cycle: responseIndex !== null && mock.repeat_responses === true && hitIndex >= responses.length,
3993
+ sequence_response_index: responseSelection === "request_body" ? sequenceResponseIndex : undefined,
3994
+ response_selection: responseIndex === null ? null : responseSelection,
3995
+ sequence_reused: responseSelection === "sequence" && responseIndex !== null && !mock.repeat_responses && hitIndex >= responses.length,
3996
+ sequence_cycle: responseSelection === "sequence" && responseIndex !== null && mock.repeat_responses === true && hitIndex >= responses.length,
3968
3997
  url: request.url(),
3969
3998
  method,
3970
3999
  status,
package/dist/profile.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  resolveRiddleProofProfileTimeoutSec,
20
20
  slugifyRiddleProofProfileName,
21
21
  summarizeRiddleProofProfileResult
22
- } from "./chunk-NPNALRHV.js";
22
+ } from "./chunk-KKH76HIA.js";
23
23
  export {
24
24
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
25
25
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
@@ -292,7 +292,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
292
292
  blocking?: boolean;
293
293
  details?: Record<string, unknown>;
294
294
  ok: boolean;
295
- action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
295
+ action: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
296
296
  state_path: string;
297
297
  stage: any;
298
298
  summary: string;
@@ -382,7 +382,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
382
382
  continueWithStage?: WorkflowStage | null;
383
383
  blocking?: boolean;
384
384
  details?: Record<string, unknown>;
385
- action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
385
+ action: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
386
386
  state_path: string;
387
387
  stage: any;
388
388
  checkpoint: string;
@@ -659,7 +659,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
659
659
  error?: undefined;
660
660
  } | {
661
661
  ok: boolean;
662
- action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
662
+ action: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
663
663
  state_path: string;
664
664
  stage: any;
665
665
  summary: string;
@@ -292,7 +292,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
292
292
  blocking?: boolean;
293
293
  details?: Record<string, unknown>;
294
294
  ok: boolean;
295
- action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
295
+ action: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
296
296
  state_path: string;
297
297
  stage: any;
298
298
  summary: string;
@@ -382,7 +382,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
382
382
  continueWithStage?: WorkflowStage | null;
383
383
  blocking?: boolean;
384
384
  details?: Record<string, unknown>;
385
- action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
385
+ action: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
386
386
  state_path: string;
387
387
  stage: any;
388
388
  checkpoint: string;
@@ -659,7 +659,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
659
659
  error?: undefined;
660
660
  } | {
661
661
  ok: boolean;
662
- action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
662
+ action: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
663
663
  state_path: string;
664
664
  stage: any;
665
665
  summary: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.108",
3
+ "version": "0.7.110",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",