@riddledc/riddle-proof 0.7.111 → 0.7.113

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.
@@ -654,6 +654,48 @@ function normalizeNetworkMocks(value) {
654
654
  if (!Array.isArray(value)) throw new Error("target.network_mocks must be an array.");
655
655
  return value.map(normalizeNetworkMock);
656
656
  }
657
+ function profileStringList(value) {
658
+ return Array.isArray(value) ? value.map((item) => String(item)).filter(Boolean) : [];
659
+ }
660
+ function responseHasRequestBodyContract(response) {
661
+ if (!response) return false;
662
+ return profileStringList(response.request_body_contains).length > 0 || profileStringList(response.request_body_patterns).length > 0 || profileStringList(response.request_body_not_contains).length > 0 || profileStringList(response.request_body_not_patterns).length > 0;
663
+ }
664
+ function responseHasOnlyPositiveTextSelector(response) {
665
+ if (!response) return false;
666
+ return profileStringList(response.request_body_contains).length > 0 && profileStringList(response.request_body_patterns).length === 0 && profileStringList(response.request_body_not_contains).length === 0 && profileStringList(response.request_body_not_patterns).length === 0;
667
+ }
668
+ function responseMayShadowLaterRequestBodyMatch(earlier, later) {
669
+ if (!responseHasOnlyPositiveTextSelector(earlier) || !responseHasRequestBodyContract(later)) return false;
670
+ const earlierContains = profileStringList(earlier.request_body_contains);
671
+ const laterContains = profileStringList(later.request_body_contains);
672
+ if (!laterContains.length) return false;
673
+ return earlierContains.every((fragment) => laterContains.includes(fragment));
674
+ }
675
+ function responseLabel(response, index) {
676
+ return response.label ? `"${response.label}"` : `responses[${index}]`;
677
+ }
678
+ function collectRiddleProofProfileWarnings(profile) {
679
+ const warnings = [];
680
+ for (const [mockIndex, mock] of (profile.target.network_mocks || []).entries()) {
681
+ const responses = Array.isArray(mock.responses) ? mock.responses : [];
682
+ if (responses.length < 2) continue;
683
+ for (let laterIndex = 1; laterIndex < responses.length; laterIndex += 1) {
684
+ const later = responses[laterIndex];
685
+ if (!responseHasRequestBodyContract(later)) continue;
686
+ for (let earlierIndex = 0; earlierIndex < laterIndex; earlierIndex += 1) {
687
+ const earlier = responses[earlierIndex];
688
+ if (!responseMayShadowLaterRequestBodyMatch(earlier, later)) continue;
689
+ const mockLabel = mock.label ? ` (${mock.label})` : "";
690
+ warnings.push(
691
+ `target.network_mocks[${mockIndex}]${mockLabel} ${responseLabel(earlier, earlierIndex)} can shadow ${responseLabel(later, laterIndex)} because the earlier request_body_contains fragments are a subset of the later response and have no negative or pattern disambiguator. First matching request-body response wins.`
692
+ );
693
+ break;
694
+ }
695
+ }
696
+ }
697
+ return warnings;
698
+ }
657
699
  function normalizeRouteInventoryPath(value, label) {
658
700
  const path = stringValue(value);
659
701
  if (!path) throw new Error(`${label} requires path.`);
@@ -1012,6 +1054,13 @@ function normalizeLinkStatusContentType(value) {
1012
1054
  const normalized = value?.split(";")[0]?.trim().toLowerCase();
1013
1055
  return normalized || void 0;
1014
1056
  }
1057
+ function linkStatusContentTypesMatch(actual, expected) {
1058
+ if (!actual || !expected) return false;
1059
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
1060
+ if (actual === expected) return true;
1061
+ const yamlTypes = /* @__PURE__ */ new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
1062
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
1063
+ }
1015
1064
  function linkStatusContentTypeOk(result, check) {
1016
1065
  const expected = check.allowed_content_types;
1017
1066
  if (!expected?.length) return true;
@@ -1020,8 +1069,7 @@ function linkStatusContentTypeOk(result, check) {
1020
1069
  return expected.some((contentType) => {
1021
1070
  const normalized = normalizeLinkStatusContentType(contentType);
1022
1071
  if (!normalized) return false;
1023
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
1024
- return actual === normalized;
1072
+ return linkStatusContentTypesMatch(actual, normalized);
1025
1073
  });
1026
1074
  }
1027
1075
  function httpStatusBodyContainsFailures(result, check) {
@@ -2042,11 +2090,11 @@ function networkMockResponseHitsByLabel(events) {
2042
2090
  for (const event of events) {
2043
2091
  if (!event || event.ok === false) continue;
2044
2092
  const label = typeof event.label === "string" ? event.label : "";
2045
- const responseLabel = typeof event.response_label === "string" ? event.response_label : "";
2046
- const hasSequenceResponse = typeof event.response_index === "number" || event.sequence_cycle === true || Boolean(responseLabel && responseLabel !== label);
2047
- if (!label || !responseLabel || !hasSequenceResponse) continue;
2093
+ const responseLabel2 = typeof event.response_label === "string" ? event.response_label : "";
2094
+ const hasSequenceResponse = typeof event.response_index === "number" || event.sequence_cycle === true || Boolean(responseLabel2 && responseLabel2 !== label);
2095
+ if (!label || !responseLabel2 || !hasSequenceResponse) continue;
2048
2096
  responseHits[label] || (responseHits[label] = {});
2049
- responseHits[label][responseLabel] = (responseHits[label][responseLabel] || 0) + 1;
2097
+ responseHits[label][responseLabel2] = (responseHits[label][responseLabel2] || 0) + 1;
2050
2098
  }
2051
2099
  return responseHits;
2052
2100
  }
@@ -2069,6 +2117,7 @@ function profileStatusFromEvidence(profile, evidence, checks) {
2069
2117
  }
2070
2118
  function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
2071
2119
  const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
2120
+ const warnings = collectRiddleProofProfileWarnings(profile);
2072
2121
  const checks = evidence ? [
2073
2122
  assessNetworkMocksFromEvidence(profile, evidence),
2074
2123
  assessSetupActionsFromEvidence(profile, evidence),
@@ -2094,6 +2143,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
2094
2143
  checks,
2095
2144
  summary: summarizeRiddleProofProfileResult({ profile_name: profile.name, status, checks, viewports: evidence?.viewports || [] }),
2096
2145
  captured_at: capturedAt,
2146
+ warnings: warnings.length ? warnings : void 0,
2097
2147
  evidence,
2098
2148
  riddle: options.riddle
2099
2149
  };
@@ -2142,6 +2192,7 @@ function createRiddleProofProfileConfigurationError(name, error, runner = "riddl
2142
2192
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
2143
2193
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
2144
2194
  const environmentBlocker = extractRiddleRunnerBlocker(message);
2195
+ const warnings = collectRiddleProofProfileWarnings(input.profile);
2145
2196
  return {
2146
2197
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
2147
2198
  profile_name: input.profile.name,
@@ -2153,6 +2204,7 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
2153
2204
  checks: [],
2154
2205
  summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
2155
2206
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
2207
+ warnings: warnings.length ? warnings : void 0,
2156
2208
  riddle: input.riddle,
2157
2209
  environment_blocker: environmentBlocker,
2158
2210
  error: message
@@ -2211,6 +2263,7 @@ function summarizeEnvironmentBlockedRunner(profileName, blocker) {
2211
2263
  }
2212
2264
  function createRiddleProofProfileInsufficientResult(input) {
2213
2265
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
2266
+ const warnings = collectRiddleProofProfileWarnings(input.profile);
2214
2267
  return {
2215
2268
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
2216
2269
  profile_name: input.profile.name,
@@ -2222,6 +2275,7 @@ function createRiddleProofProfileInsufficientResult(input) {
2222
2275
  checks: [],
2223
2276
  summary: `${input.profile.name} did not produce enough evidence for a profile judgment.`,
2224
2277
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
2278
+ warnings: warnings.length ? warnings : void 0,
2225
2279
  riddle: input.riddle,
2226
2280
  error: message
2227
2281
  };
@@ -2426,6 +2480,13 @@ function normalizeLinkStatusContentType(value) {
2426
2480
  const normalized = (value.split(";")[0] || "").trim().toLowerCase();
2427
2481
  return normalized || undefined;
2428
2482
  }
2483
+ function linkStatusContentTypesMatch(actual, expected) {
2484
+ if (!actual || !expected) return false;
2485
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
2486
+ if (actual === expected) return true;
2487
+ const yamlTypes = new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
2488
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
2489
+ }
2429
2490
  function linkStatusContentTypeOk(result, check) {
2430
2491
  if (!Array.isArray(check.allowed_content_types) || !check.allowed_content_types.length) return true;
2431
2492
  const actual = normalizeLinkStatusContentType(result.content_type);
@@ -2433,8 +2494,7 @@ function linkStatusContentTypeOk(result, check) {
2433
2494
  return check.allowed_content_types.some((contentType) => {
2434
2495
  const normalized = normalizeLinkStatusContentType(contentType);
2435
2496
  if (!normalized) return false;
2436
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
2437
- return actual === normalized;
2497
+ return linkStatusContentTypesMatch(actual, normalized);
2438
2498
  });
2439
2499
  }
2440
2500
  function httpStatusBodyContainsFailures(result, check) {
@@ -3528,6 +3588,7 @@ function assessProfile(profile, evidence) {
3528
3588
  checks,
3529
3589
  summary,
3530
3590
  captured_at: evidence.captured_at,
3591
+ warnings: profileWarnings.length ? profileWarnings : undefined,
3531
3592
  evidence,
3532
3593
  };
3533
3594
  }
@@ -3536,11 +3597,14 @@ function assessProfile(profile, evidence) {
3536
3597
  function buildRiddleProofProfileScript(profile) {
3537
3598
  const targetUrl = resolveRiddleProofProfileTargetUrl(profile);
3538
3599
  const slug = slugifyRiddleProofProfileName(profile.name);
3600
+ const profileWarnings = collectRiddleProofProfileWarnings(profile);
3539
3601
  const serializableProfile = JSON.stringify(profile);
3602
+ const serializableProfileWarnings = JSON.stringify(profileWarnings);
3540
3603
  const serializableTargetUrl = JSON.stringify(targetUrl);
3541
3604
  const serializableSlug = JSON.stringify(slug);
3542
3605
  return String.raw`
3543
3606
  const profile = ${serializableProfile};
3607
+ const profileWarnings = ${serializableProfileWarnings};
3544
3608
  const targetUrl = ${serializableTargetUrl};
3545
3609
  const profileSlug = ${serializableSlug};
3546
3610
  const capturedAt = new Date().toISOString();
@@ -4566,6 +4630,13 @@ function normalizeLinkProbeContentType(value) {
4566
4630
  const normalized = (value.split(";")[0] || "").trim().toLowerCase();
4567
4631
  return normalized || undefined;
4568
4632
  }
4633
+ function linkProbeContentTypesMatch(actual, expected) {
4634
+ if (!actual || !expected) return false;
4635
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
4636
+ if (actual === expected) return true;
4637
+ const yamlTypes = new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
4638
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
4639
+ }
4569
4640
  function linkProbeContentTypeAllowed(result, check) {
4570
4641
  if (!Array.isArray(check.allowed_content_types) || !check.allowed_content_types.length) return true;
4571
4642
  const actual = normalizeLinkProbeContentType(result.content_type);
@@ -4573,8 +4644,7 @@ function linkProbeContentTypeAllowed(result, check) {
4573
4644
  return check.allowed_content_types.some((contentType) => {
4574
4645
  const normalized = normalizeLinkProbeContentType(contentType);
4575
4646
  if (!normalized) return false;
4576
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
4577
- return actual === normalized;
4647
+ return linkProbeContentTypesMatch(actual, normalized);
4578
4648
  });
4579
4649
  }
4580
4650
  function linkProbeResponseFields(response, method) {
@@ -5668,6 +5738,7 @@ export {
5668
5738
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
5669
5739
  RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
5670
5740
  slugifyRiddleProofProfileName,
5741
+ collectRiddleProofProfileWarnings,
5671
5742
  normalizeRiddleProofProfile,
5672
5743
  resolveRiddleProofProfileTargetUrl,
5673
5744
  resolveRiddleProofProfileTimeoutSec,
package/dist/cli.cjs CHANGED
@@ -7547,6 +7547,48 @@ function normalizeNetworkMocks(value) {
7547
7547
  if (!Array.isArray(value)) throw new Error("target.network_mocks must be an array.");
7548
7548
  return value.map(normalizeNetworkMock);
7549
7549
  }
7550
+ function profileStringList(value) {
7551
+ return Array.isArray(value) ? value.map((item) => String(item)).filter(Boolean) : [];
7552
+ }
7553
+ function responseHasRequestBodyContract(response) {
7554
+ if (!response) return false;
7555
+ return profileStringList(response.request_body_contains).length > 0 || profileStringList(response.request_body_patterns).length > 0 || profileStringList(response.request_body_not_contains).length > 0 || profileStringList(response.request_body_not_patterns).length > 0;
7556
+ }
7557
+ function responseHasOnlyPositiveTextSelector(response) {
7558
+ if (!response) return false;
7559
+ return profileStringList(response.request_body_contains).length > 0 && profileStringList(response.request_body_patterns).length === 0 && profileStringList(response.request_body_not_contains).length === 0 && profileStringList(response.request_body_not_patterns).length === 0;
7560
+ }
7561
+ function responseMayShadowLaterRequestBodyMatch(earlier, later) {
7562
+ if (!responseHasOnlyPositiveTextSelector(earlier) || !responseHasRequestBodyContract(later)) return false;
7563
+ const earlierContains = profileStringList(earlier.request_body_contains);
7564
+ const laterContains = profileStringList(later.request_body_contains);
7565
+ if (!laterContains.length) return false;
7566
+ return earlierContains.every((fragment) => laterContains.includes(fragment));
7567
+ }
7568
+ function responseLabel(response, index) {
7569
+ return response.label ? `"${response.label}"` : `responses[${index}]`;
7570
+ }
7571
+ function collectRiddleProofProfileWarnings(profile) {
7572
+ const warnings = [];
7573
+ for (const [mockIndex, mock] of (profile.target.network_mocks || []).entries()) {
7574
+ const responses = Array.isArray(mock.responses) ? mock.responses : [];
7575
+ if (responses.length < 2) continue;
7576
+ for (let laterIndex = 1; laterIndex < responses.length; laterIndex += 1) {
7577
+ const later = responses[laterIndex];
7578
+ if (!responseHasRequestBodyContract(later)) continue;
7579
+ for (let earlierIndex = 0; earlierIndex < laterIndex; earlierIndex += 1) {
7580
+ const earlier = responses[earlierIndex];
7581
+ if (!responseMayShadowLaterRequestBodyMatch(earlier, later)) continue;
7582
+ const mockLabel = mock.label ? ` (${mock.label})` : "";
7583
+ warnings.push(
7584
+ `target.network_mocks[${mockIndex}]${mockLabel} ${responseLabel(earlier, earlierIndex)} can shadow ${responseLabel(later, laterIndex)} because the earlier request_body_contains fragments are a subset of the later response and have no negative or pattern disambiguator. First matching request-body response wins.`
7585
+ );
7586
+ break;
7587
+ }
7588
+ }
7589
+ }
7590
+ return warnings;
7591
+ }
7550
7592
  function normalizeRouteInventoryPath(value, label) {
7551
7593
  const path7 = stringValue2(value);
7552
7594
  if (!path7) throw new Error(`${label} requires path.`);
@@ -7905,6 +7947,13 @@ function normalizeLinkStatusContentType(value) {
7905
7947
  const normalized = value?.split(";")[0]?.trim().toLowerCase();
7906
7948
  return normalized || void 0;
7907
7949
  }
7950
+ function linkStatusContentTypesMatch(actual, expected) {
7951
+ if (!actual || !expected) return false;
7952
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
7953
+ if (actual === expected) return true;
7954
+ const yamlTypes = /* @__PURE__ */ new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
7955
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
7956
+ }
7908
7957
  function linkStatusContentTypeOk(result, check) {
7909
7958
  const expected = check.allowed_content_types;
7910
7959
  if (!expected?.length) return true;
@@ -7913,8 +7962,7 @@ function linkStatusContentTypeOk(result, check) {
7913
7962
  return expected.some((contentType) => {
7914
7963
  const normalized = normalizeLinkStatusContentType(contentType);
7915
7964
  if (!normalized) return false;
7916
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
7917
- return actual === normalized;
7965
+ return linkStatusContentTypesMatch(actual, normalized);
7918
7966
  });
7919
7967
  }
7920
7968
  function httpStatusBodyContainsFailures(result, check) {
@@ -8935,11 +8983,11 @@ function networkMockResponseHitsByLabel(events) {
8935
8983
  for (const event of events) {
8936
8984
  if (!event || event.ok === false) continue;
8937
8985
  const label = typeof event.label === "string" ? event.label : "";
8938
- const responseLabel = typeof event.response_label === "string" ? event.response_label : "";
8939
- const hasSequenceResponse = typeof event.response_index === "number" || event.sequence_cycle === true || Boolean(responseLabel && responseLabel !== label);
8940
- if (!label || !responseLabel || !hasSequenceResponse) continue;
8986
+ const responseLabel2 = typeof event.response_label === "string" ? event.response_label : "";
8987
+ const hasSequenceResponse = typeof event.response_index === "number" || event.sequence_cycle === true || Boolean(responseLabel2 && responseLabel2 !== label);
8988
+ if (!label || !responseLabel2 || !hasSequenceResponse) continue;
8941
8989
  responseHits[label] || (responseHits[label] = {});
8942
- responseHits[label][responseLabel] = (responseHits[label][responseLabel] || 0) + 1;
8990
+ responseHits[label][responseLabel2] = (responseHits[label][responseLabel2] || 0) + 1;
8943
8991
  }
8944
8992
  return responseHits;
8945
8993
  }
@@ -8962,6 +9010,7 @@ function profileStatusFromEvidence(profile, evidence, checks) {
8962
9010
  }
8963
9011
  function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
8964
9012
  const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
9013
+ const warnings = collectRiddleProofProfileWarnings(profile);
8965
9014
  const checks = evidence ? [
8966
9015
  assessNetworkMocksFromEvidence(profile, evidence),
8967
9016
  assessSetupActionsFromEvidence(profile, evidence),
@@ -8987,6 +9036,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
8987
9036
  checks,
8988
9037
  summary: summarizeRiddleProofProfileResult({ profile_name: profile.name, status, checks, viewports: evidence?.viewports || [] }),
8989
9038
  captured_at: capturedAt,
9039
+ warnings: warnings.length ? warnings : void 0,
8990
9040
  evidence,
8991
9041
  riddle: options.riddle
8992
9042
  };
@@ -9019,6 +9069,7 @@ function profileStatusExitCode(profile, status) {
9019
9069
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
9020
9070
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
9021
9071
  const environmentBlocker = extractRiddleRunnerBlocker(message);
9072
+ const warnings = collectRiddleProofProfileWarnings(input.profile);
9022
9073
  return {
9023
9074
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
9024
9075
  profile_name: input.profile.name,
@@ -9030,6 +9081,7 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
9030
9081
  checks: [],
9031
9082
  summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
9032
9083
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
9084
+ warnings: warnings.length ? warnings : void 0,
9033
9085
  riddle: input.riddle,
9034
9086
  environment_blocker: environmentBlocker,
9035
9087
  error: message
@@ -9088,6 +9140,7 @@ function summarizeEnvironmentBlockedRunner(profileName, blocker) {
9088
9140
  }
9089
9141
  function createRiddleProofProfileInsufficientResult(input) {
9090
9142
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
9143
+ const warnings = collectRiddleProofProfileWarnings(input.profile);
9091
9144
  return {
9092
9145
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
9093
9146
  profile_name: input.profile.name,
@@ -9099,6 +9152,7 @@ function createRiddleProofProfileInsufficientResult(input) {
9099
9152
  checks: [],
9100
9153
  summary: `${input.profile.name} did not produce enough evidence for a profile judgment.`,
9101
9154
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
9155
+ warnings: warnings.length ? warnings : void 0,
9102
9156
  riddle: input.riddle,
9103
9157
  error: message
9104
9158
  };
@@ -9303,6 +9357,13 @@ function normalizeLinkStatusContentType(value) {
9303
9357
  const normalized = (value.split(";")[0] || "").trim().toLowerCase();
9304
9358
  return normalized || undefined;
9305
9359
  }
9360
+ function linkStatusContentTypesMatch(actual, expected) {
9361
+ if (!actual || !expected) return false;
9362
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
9363
+ if (actual === expected) return true;
9364
+ const yamlTypes = new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
9365
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
9366
+ }
9306
9367
  function linkStatusContentTypeOk(result, check) {
9307
9368
  if (!Array.isArray(check.allowed_content_types) || !check.allowed_content_types.length) return true;
9308
9369
  const actual = normalizeLinkStatusContentType(result.content_type);
@@ -9310,8 +9371,7 @@ function linkStatusContentTypeOk(result, check) {
9310
9371
  return check.allowed_content_types.some((contentType) => {
9311
9372
  const normalized = normalizeLinkStatusContentType(contentType);
9312
9373
  if (!normalized) return false;
9313
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
9314
- return actual === normalized;
9374
+ return linkStatusContentTypesMatch(actual, normalized);
9315
9375
  });
9316
9376
  }
9317
9377
  function httpStatusBodyContainsFailures(result, check) {
@@ -10405,6 +10465,7 @@ function assessProfile(profile, evidence) {
10405
10465
  checks,
10406
10466
  summary,
10407
10467
  captured_at: evidence.captured_at,
10468
+ warnings: profileWarnings.length ? profileWarnings : undefined,
10408
10469
  evidence,
10409
10470
  };
10410
10471
  }
@@ -10413,11 +10474,14 @@ function assessProfile(profile, evidence) {
10413
10474
  function buildRiddleProofProfileScript(profile) {
10414
10475
  const targetUrl = resolveRiddleProofProfileTargetUrl(profile);
10415
10476
  const slug = slugifyRiddleProofProfileName(profile.name);
10477
+ const profileWarnings = collectRiddleProofProfileWarnings(profile);
10416
10478
  const serializableProfile = JSON.stringify(profile);
10479
+ const serializableProfileWarnings = JSON.stringify(profileWarnings);
10417
10480
  const serializableTargetUrl = JSON.stringify(targetUrl);
10418
10481
  const serializableSlug = JSON.stringify(slug);
10419
10482
  return String.raw`
10420
10483
  const profile = ${serializableProfile};
10484
+ const profileWarnings = ${serializableProfileWarnings};
10421
10485
  const targetUrl = ${serializableTargetUrl};
10422
10486
  const profileSlug = ${serializableSlug};
10423
10487
  const capturedAt = new Date().toISOString();
@@ -11443,6 +11507,13 @@ function normalizeLinkProbeContentType(value) {
11443
11507
  const normalized = (value.split(";")[0] || "").trim().toLowerCase();
11444
11508
  return normalized || undefined;
11445
11509
  }
11510
+ function linkProbeContentTypesMatch(actual, expected) {
11511
+ if (!actual || !expected) return false;
11512
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
11513
+ if (actual === expected) return true;
11514
+ const yamlTypes = new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
11515
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
11516
+ }
11446
11517
  function linkProbeContentTypeAllowed(result, check) {
11447
11518
  if (!Array.isArray(check.allowed_content_types) || !check.allowed_content_types.length) return true;
11448
11519
  const actual = normalizeLinkProbeContentType(result.content_type);
@@ -11450,8 +11521,7 @@ function linkProbeContentTypeAllowed(result, check) {
11450
11521
  return check.allowed_content_types.some((contentType) => {
11451
11522
  const normalized = normalizeLinkProbeContentType(contentType);
11452
11523
  if (!normalized) return false;
11453
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
11454
- return actual === normalized;
11524
+ return linkProbeContentTypesMatch(actual, normalized);
11455
11525
  });
11456
11526
  }
11457
11527
  function linkProbeResponseFields(response, method) {
@@ -12824,10 +12894,17 @@ function profileResultMarkdown(result) {
12824
12894
  `Captured: ${result.captured_at}`,
12825
12895
  "",
12826
12896
  result.summary,
12827
- "",
12828
- "## Checks",
12829
12897
  ""
12830
12898
  ];
12899
+ if (Array.isArray(result.warnings) && result.warnings.length) {
12900
+ lines.push("## Profile Warnings", "");
12901
+ for (const warning of result.warnings.slice(0, 12)) {
12902
+ lines.push(`- ${warning}`);
12903
+ }
12904
+ if (result.warnings.length > 12) lines.push(`- ${result.warnings.length - 12} additional warning(s) omitted.`);
12905
+ lines.push("");
12906
+ }
12907
+ lines.push("## Checks", "");
12831
12908
  for (const check of result.checks) {
12832
12909
  lines.push(`- ${check.status}: ${profileCheckMarkdownLabel(check)}`);
12833
12910
  if (check.message) lines.push(` ${check.message}`);
@@ -13102,7 +13179,7 @@ function profileNetworkMockSummaryMarkdown(result) {
13102
13179
  const responseHits = cliRecord(responseHitsByLabel[label]);
13103
13180
  const responseLabels = responseHits ? Object.keys(responseHits).sort() : [];
13104
13181
  if (responseHits && responseLabels.length) {
13105
- const responseParts = responseLabels.slice(0, 8).map((responseLabel) => `${responseLabel} ${cliRecordNumber(responseHits, responseLabel) ?? 0}`);
13182
+ const responseParts = responseLabels.slice(0, 8).map((responseLabel2) => `${responseLabel2} ${cliRecordNumber(responseHits, responseLabel2) ?? 0}`);
13106
13183
  const omitted = responseLabels.length > 8 ? `; ${responseLabels.length - 8} additional response label(s) omitted` : "";
13107
13184
  lines.push(`- ${label} responses: ${responseParts.join("; ")}${omitted}`);
13108
13185
  }
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  profileStatusExitCode,
11
11
  resolveRiddleProofProfileTargetUrl,
12
12
  resolveRiddleProofProfileTimeoutSec
13
- } from "./chunk-KKH76HIA.js";
13
+ } from "./chunk-3CND75DM.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport
@@ -322,10 +322,17 @@ function profileResultMarkdown(result) {
322
322
  `Captured: ${result.captured_at}`,
323
323
  "",
324
324
  result.summary,
325
- "",
326
- "## Checks",
327
325
  ""
328
326
  ];
327
+ if (Array.isArray(result.warnings) && result.warnings.length) {
328
+ lines.push("## Profile Warnings", "");
329
+ for (const warning of result.warnings.slice(0, 12)) {
330
+ lines.push(`- ${warning}`);
331
+ }
332
+ if (result.warnings.length > 12) lines.push(`- ${result.warnings.length - 12} additional warning(s) omitted.`);
333
+ lines.push("");
334
+ }
335
+ lines.push("## Checks", "");
329
336
  for (const check of result.checks) {
330
337
  lines.push(`- ${check.status}: ${profileCheckMarkdownLabel(check)}`);
331
338
  if (check.message) lines.push(` ${check.message}`);
package/dist/index.cjs CHANGED
@@ -2948,6 +2948,7 @@ __export(index_exports, {
2948
2948
  checkpointResponseIdentity: () => checkpointResponseIdentity,
2949
2949
  checkpointSummaryFromState: () => checkpointSummaryFromState,
2950
2950
  collectRiddleProfileArtifactRefs: () => collectRiddleProfileArtifactRefs,
2951
+ collectRiddleProofProfileWarnings: () => collectRiddleProofProfileWarnings,
2951
2952
  compactBasicGameplayText: () => compactBasicGameplayText,
2952
2953
  compactRecord: () => compactRecord,
2953
2954
  compareVisualProofSessionFingerprint: () => compareVisualProofSessionFingerprint,
@@ -9383,6 +9384,48 @@ function normalizeNetworkMocks(value) {
9383
9384
  if (!Array.isArray(value)) throw new Error("target.network_mocks must be an array.");
9384
9385
  return value.map(normalizeNetworkMock);
9385
9386
  }
9387
+ function profileStringList(value) {
9388
+ return Array.isArray(value) ? value.map((item) => String(item)).filter(Boolean) : [];
9389
+ }
9390
+ function responseHasRequestBodyContract(response) {
9391
+ if (!response) return false;
9392
+ return profileStringList(response.request_body_contains).length > 0 || profileStringList(response.request_body_patterns).length > 0 || profileStringList(response.request_body_not_contains).length > 0 || profileStringList(response.request_body_not_patterns).length > 0;
9393
+ }
9394
+ function responseHasOnlyPositiveTextSelector(response) {
9395
+ if (!response) return false;
9396
+ return profileStringList(response.request_body_contains).length > 0 && profileStringList(response.request_body_patterns).length === 0 && profileStringList(response.request_body_not_contains).length === 0 && profileStringList(response.request_body_not_patterns).length === 0;
9397
+ }
9398
+ function responseMayShadowLaterRequestBodyMatch(earlier, later) {
9399
+ if (!responseHasOnlyPositiveTextSelector(earlier) || !responseHasRequestBodyContract(later)) return false;
9400
+ const earlierContains = profileStringList(earlier.request_body_contains);
9401
+ const laterContains = profileStringList(later.request_body_contains);
9402
+ if (!laterContains.length) return false;
9403
+ return earlierContains.every((fragment) => laterContains.includes(fragment));
9404
+ }
9405
+ function responseLabel(response, index) {
9406
+ return response.label ? `"${response.label}"` : `responses[${index}]`;
9407
+ }
9408
+ function collectRiddleProofProfileWarnings(profile) {
9409
+ const warnings = [];
9410
+ for (const [mockIndex, mock] of (profile.target.network_mocks || []).entries()) {
9411
+ const responses = Array.isArray(mock.responses) ? mock.responses : [];
9412
+ if (responses.length < 2) continue;
9413
+ for (let laterIndex = 1; laterIndex < responses.length; laterIndex += 1) {
9414
+ const later = responses[laterIndex];
9415
+ if (!responseHasRequestBodyContract(later)) continue;
9416
+ for (let earlierIndex = 0; earlierIndex < laterIndex; earlierIndex += 1) {
9417
+ const earlier = responses[earlierIndex];
9418
+ if (!responseMayShadowLaterRequestBodyMatch(earlier, later)) continue;
9419
+ const mockLabel = mock.label ? ` (${mock.label})` : "";
9420
+ warnings.push(
9421
+ `target.network_mocks[${mockIndex}]${mockLabel} ${responseLabel(earlier, earlierIndex)} can shadow ${responseLabel(later, laterIndex)} because the earlier request_body_contains fragments are a subset of the later response and have no negative or pattern disambiguator. First matching request-body response wins.`
9422
+ );
9423
+ break;
9424
+ }
9425
+ }
9426
+ }
9427
+ return warnings;
9428
+ }
9386
9429
  function normalizeRouteInventoryPath(value, label) {
9387
9430
  const path6 = stringValue5(value);
9388
9431
  if (!path6) throw new Error(`${label} requires path.`);
@@ -9741,6 +9784,13 @@ function normalizeLinkStatusContentType(value) {
9741
9784
  const normalized = value?.split(";")[0]?.trim().toLowerCase();
9742
9785
  return normalized || void 0;
9743
9786
  }
9787
+ function linkStatusContentTypesMatch(actual, expected) {
9788
+ if (!actual || !expected) return false;
9789
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
9790
+ if (actual === expected) return true;
9791
+ const yamlTypes = /* @__PURE__ */ new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
9792
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
9793
+ }
9744
9794
  function linkStatusContentTypeOk(result, check) {
9745
9795
  const expected = check.allowed_content_types;
9746
9796
  if (!expected?.length) return true;
@@ -9749,8 +9799,7 @@ function linkStatusContentTypeOk(result, check) {
9749
9799
  return expected.some((contentType) => {
9750
9800
  const normalized = normalizeLinkStatusContentType(contentType);
9751
9801
  if (!normalized) return false;
9752
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
9753
- return actual === normalized;
9802
+ return linkStatusContentTypesMatch(actual, normalized);
9754
9803
  });
9755
9804
  }
9756
9805
  function httpStatusBodyContainsFailures(result, check) {
@@ -10771,11 +10820,11 @@ function networkMockResponseHitsByLabel(events) {
10771
10820
  for (const event of events) {
10772
10821
  if (!event || event.ok === false) continue;
10773
10822
  const label = typeof event.label === "string" ? event.label : "";
10774
- const responseLabel = typeof event.response_label === "string" ? event.response_label : "";
10775
- const hasSequenceResponse = typeof event.response_index === "number" || event.sequence_cycle === true || Boolean(responseLabel && responseLabel !== label);
10776
- if (!label || !responseLabel || !hasSequenceResponse) continue;
10823
+ const responseLabel2 = typeof event.response_label === "string" ? event.response_label : "";
10824
+ const hasSequenceResponse = typeof event.response_index === "number" || event.sequence_cycle === true || Boolean(responseLabel2 && responseLabel2 !== label);
10825
+ if (!label || !responseLabel2 || !hasSequenceResponse) continue;
10777
10826
  responseHits[label] || (responseHits[label] = {});
10778
- responseHits[label][responseLabel] = (responseHits[label][responseLabel] || 0) + 1;
10827
+ responseHits[label][responseLabel2] = (responseHits[label][responseLabel2] || 0) + 1;
10779
10828
  }
10780
10829
  return responseHits;
10781
10830
  }
@@ -10798,6 +10847,7 @@ function profileStatusFromEvidence(profile, evidence, checks) {
10798
10847
  }
10799
10848
  function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
10800
10849
  const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
10850
+ const warnings = collectRiddleProofProfileWarnings(profile);
10801
10851
  const checks = evidence ? [
10802
10852
  assessNetworkMocksFromEvidence(profile, evidence),
10803
10853
  assessSetupActionsFromEvidence(profile, evidence),
@@ -10823,6 +10873,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
10823
10873
  checks,
10824
10874
  summary: summarizeRiddleProofProfileResult({ profile_name: profile.name, status, checks, viewports: evidence?.viewports || [] }),
10825
10875
  captured_at: capturedAt,
10876
+ warnings: warnings.length ? warnings : void 0,
10826
10877
  evidence,
10827
10878
  riddle: options.riddle
10828
10879
  };
@@ -10871,6 +10922,7 @@ function createRiddleProofProfileConfigurationError(name, error, runner = "riddl
10871
10922
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
10872
10923
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
10873
10924
  const environmentBlocker = extractRiddleRunnerBlocker(message);
10925
+ const warnings = collectRiddleProofProfileWarnings(input.profile);
10874
10926
  return {
10875
10927
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
10876
10928
  profile_name: input.profile.name,
@@ -10882,6 +10934,7 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
10882
10934
  checks: [],
10883
10935
  summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
10884
10936
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
10937
+ warnings: warnings.length ? warnings : void 0,
10885
10938
  riddle: input.riddle,
10886
10939
  environment_blocker: environmentBlocker,
10887
10940
  error: message
@@ -10940,6 +10993,7 @@ function summarizeEnvironmentBlockedRunner(profileName, blocker) {
10940
10993
  }
10941
10994
  function createRiddleProofProfileInsufficientResult(input) {
10942
10995
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
10996
+ const warnings = collectRiddleProofProfileWarnings(input.profile);
10943
10997
  return {
10944
10998
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
10945
10999
  profile_name: input.profile.name,
@@ -10951,6 +11005,7 @@ function createRiddleProofProfileInsufficientResult(input) {
10951
11005
  checks: [],
10952
11006
  summary: `${input.profile.name} did not produce enough evidence for a profile judgment.`,
10953
11007
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
11008
+ warnings: warnings.length ? warnings : void 0,
10954
11009
  riddle: input.riddle,
10955
11010
  error: message
10956
11011
  };
@@ -11155,6 +11210,13 @@ function normalizeLinkStatusContentType(value) {
11155
11210
  const normalized = (value.split(";")[0] || "").trim().toLowerCase();
11156
11211
  return normalized || undefined;
11157
11212
  }
11213
+ function linkStatusContentTypesMatch(actual, expected) {
11214
+ if (!actual || !expected) return false;
11215
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
11216
+ if (actual === expected) return true;
11217
+ const yamlTypes = new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
11218
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
11219
+ }
11158
11220
  function linkStatusContentTypeOk(result, check) {
11159
11221
  if (!Array.isArray(check.allowed_content_types) || !check.allowed_content_types.length) return true;
11160
11222
  const actual = normalizeLinkStatusContentType(result.content_type);
@@ -11162,8 +11224,7 @@ function linkStatusContentTypeOk(result, check) {
11162
11224
  return check.allowed_content_types.some((contentType) => {
11163
11225
  const normalized = normalizeLinkStatusContentType(contentType);
11164
11226
  if (!normalized) return false;
11165
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
11166
- return actual === normalized;
11227
+ return linkStatusContentTypesMatch(actual, normalized);
11167
11228
  });
11168
11229
  }
11169
11230
  function httpStatusBodyContainsFailures(result, check) {
@@ -12257,6 +12318,7 @@ function assessProfile(profile, evidence) {
12257
12318
  checks,
12258
12319
  summary,
12259
12320
  captured_at: evidence.captured_at,
12321
+ warnings: profileWarnings.length ? profileWarnings : undefined,
12260
12322
  evidence,
12261
12323
  };
12262
12324
  }
@@ -12265,11 +12327,14 @@ function assessProfile(profile, evidence) {
12265
12327
  function buildRiddleProofProfileScript(profile) {
12266
12328
  const targetUrl = resolveRiddleProofProfileTargetUrl(profile);
12267
12329
  const slug2 = slugifyRiddleProofProfileName(profile.name);
12330
+ const profileWarnings = collectRiddleProofProfileWarnings(profile);
12268
12331
  const serializableProfile = JSON.stringify(profile);
12332
+ const serializableProfileWarnings = JSON.stringify(profileWarnings);
12269
12333
  const serializableTargetUrl = JSON.stringify(targetUrl);
12270
12334
  const serializableSlug = JSON.stringify(slug2);
12271
12335
  return String.raw`
12272
12336
  const profile = ${serializableProfile};
12337
+ const profileWarnings = ${serializableProfileWarnings};
12273
12338
  const targetUrl = ${serializableTargetUrl};
12274
12339
  const profileSlug = ${serializableSlug};
12275
12340
  const capturedAt = new Date().toISOString();
@@ -13295,6 +13360,13 @@ function normalizeLinkProbeContentType(value) {
13295
13360
  const normalized = (value.split(";")[0] || "").trim().toLowerCase();
13296
13361
  return normalized || undefined;
13297
13362
  }
13363
+ function linkProbeContentTypesMatch(actual, expected) {
13364
+ if (!actual || !expected) return false;
13365
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
13366
+ if (actual === expected) return true;
13367
+ const yamlTypes = new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
13368
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
13369
+ }
13298
13370
  function linkProbeContentTypeAllowed(result, check) {
13299
13371
  if (!Array.isArray(check.allowed_content_types) || !check.allowed_content_types.length) return true;
13300
13372
  const actual = normalizeLinkProbeContentType(result.content_type);
@@ -13302,8 +13374,7 @@ function linkProbeContentTypeAllowed(result, check) {
13302
13374
  return check.allowed_content_types.some((contentType) => {
13303
13375
  const normalized = normalizeLinkProbeContentType(contentType);
13304
13376
  if (!normalized) return false;
13305
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
13306
- return actual === normalized;
13377
+ return linkProbeContentTypesMatch(actual, normalized);
13307
13378
  });
13308
13379
  }
13309
13380
  function linkProbeResponseFields(response, method) {
@@ -14772,6 +14843,7 @@ function createRiddleApiClient(config = {}) {
14772
14843
  checkpointResponseIdentity,
14773
14844
  checkpointSummaryFromState,
14774
14845
  collectRiddleProfileArtifactRefs,
14846
+ collectRiddleProofProfileWarnings,
14775
14847
  compactBasicGameplayText,
14776
14848
  compactRecord,
14777
14849
  compareVisualProofSessionFingerprint,
package/dist/index.d.cts CHANGED
@@ -10,5 +10,5 @@ export { CreateCaptureDiagnosticInput, DEFAULT_DIAGNOSTIC_ARRAY_LIMIT, DEFAULT_D
10
10
  export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION, RIDDLE_PROOF_VISUAL_SESSION_VERSION, VisualProofSessionMismatch, buildVisualProofSession, compareVisualProofSessionFingerprint, parseVisualProofSession, visualSessionFingerprint, visualSessionFingerprintBasis } from './proof-session.cjs';
11
11
  export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.cjs';
12
12
  export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayBoundsOffender, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayResponsiveViewportEvidence, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.cjs';
13
- export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
13
+ export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, collectRiddleProofProfileWarnings, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
14
14
  export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
package/dist/index.d.ts CHANGED
@@ -10,5 +10,5 @@ export { CreateCaptureDiagnosticInput, DEFAULT_DIAGNOSTIC_ARRAY_LIMIT, DEFAULT_D
10
10
  export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION, RIDDLE_PROOF_VISUAL_SESSION_VERSION, VisualProofSessionMismatch, buildVisualProofSession, compareVisualProofSessionFingerprint, parseVisualProofSession, visualSessionFingerprint, visualSessionFingerprintBasis } from './proof-session.js';
11
11
  export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.js';
12
12
  export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayBoundsOffender, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayResponsiveViewportEvidence, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.js';
13
- export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
13
+ export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, collectRiddleProofProfileWarnings, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
14
14
  export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
package/dist/index.js CHANGED
@@ -47,6 +47,7 @@ import {
47
47
  assessRiddleProofProfileEvidence,
48
48
  buildRiddleProofProfileScript,
49
49
  collectRiddleProfileArtifactRefs,
50
+ collectRiddleProofProfileWarnings,
50
51
  createRiddleProofProfileConfigurationError,
51
52
  createRiddleProofProfileEnvironmentBlockedResult,
52
53
  createRiddleProofProfileInsufficientResult,
@@ -58,7 +59,7 @@ import {
58
59
  resolveRiddleProofProfileTimeoutSec,
59
60
  slugifyRiddleProofProfileName,
60
61
  summarizeRiddleProofProfileResult
61
- } from "./chunk-KKH76HIA.js";
62
+ } from "./chunk-3CND75DM.js";
62
63
  import {
63
64
  DEFAULT_RIDDLE_API_BASE_URL,
64
65
  DEFAULT_RIDDLE_API_KEY_FILE,
@@ -188,6 +189,7 @@ export {
188
189
  checkpointResponseIdentity,
189
190
  checkpointSummaryFromState,
190
191
  collectRiddleProfileArtifactRefs,
192
+ collectRiddleProofProfileWarnings,
191
193
  compactBasicGameplayText,
192
194
  compactRecord,
193
195
  compareVisualProofSessionFingerprint,
package/dist/profile.cjs CHANGED
@@ -29,6 +29,7 @@ __export(profile_exports, {
29
29
  assessRiddleProofProfileEvidence: () => assessRiddleProofProfileEvidence,
30
30
  buildRiddleProofProfileScript: () => buildRiddleProofProfileScript,
31
31
  collectRiddleProfileArtifactRefs: () => collectRiddleProfileArtifactRefs,
32
+ collectRiddleProofProfileWarnings: () => collectRiddleProofProfileWarnings,
32
33
  createRiddleProofProfileConfigurationError: () => createRiddleProofProfileConfigurationError,
33
34
  createRiddleProofProfileEnvironmentBlockedResult: () => createRiddleProofProfileEnvironmentBlockedResult,
34
35
  createRiddleProofProfileInsufficientResult: () => createRiddleProofProfileInsufficientResult,
@@ -697,6 +698,48 @@ function normalizeNetworkMocks(value) {
697
698
  if (!Array.isArray(value)) throw new Error("target.network_mocks must be an array.");
698
699
  return value.map(normalizeNetworkMock);
699
700
  }
701
+ function profileStringList(value) {
702
+ return Array.isArray(value) ? value.map((item) => String(item)).filter(Boolean) : [];
703
+ }
704
+ function responseHasRequestBodyContract(response) {
705
+ if (!response) return false;
706
+ return profileStringList(response.request_body_contains).length > 0 || profileStringList(response.request_body_patterns).length > 0 || profileStringList(response.request_body_not_contains).length > 0 || profileStringList(response.request_body_not_patterns).length > 0;
707
+ }
708
+ function responseHasOnlyPositiveTextSelector(response) {
709
+ if (!response) return false;
710
+ return profileStringList(response.request_body_contains).length > 0 && profileStringList(response.request_body_patterns).length === 0 && profileStringList(response.request_body_not_contains).length === 0 && profileStringList(response.request_body_not_patterns).length === 0;
711
+ }
712
+ function responseMayShadowLaterRequestBodyMatch(earlier, later) {
713
+ if (!responseHasOnlyPositiveTextSelector(earlier) || !responseHasRequestBodyContract(later)) return false;
714
+ const earlierContains = profileStringList(earlier.request_body_contains);
715
+ const laterContains = profileStringList(later.request_body_contains);
716
+ if (!laterContains.length) return false;
717
+ return earlierContains.every((fragment) => laterContains.includes(fragment));
718
+ }
719
+ function responseLabel(response, index) {
720
+ return response.label ? `"${response.label}"` : `responses[${index}]`;
721
+ }
722
+ function collectRiddleProofProfileWarnings(profile) {
723
+ const warnings = [];
724
+ for (const [mockIndex, mock] of (profile.target.network_mocks || []).entries()) {
725
+ const responses = Array.isArray(mock.responses) ? mock.responses : [];
726
+ if (responses.length < 2) continue;
727
+ for (let laterIndex = 1; laterIndex < responses.length; laterIndex += 1) {
728
+ const later = responses[laterIndex];
729
+ if (!responseHasRequestBodyContract(later)) continue;
730
+ for (let earlierIndex = 0; earlierIndex < laterIndex; earlierIndex += 1) {
731
+ const earlier = responses[earlierIndex];
732
+ if (!responseMayShadowLaterRequestBodyMatch(earlier, later)) continue;
733
+ const mockLabel = mock.label ? ` (${mock.label})` : "";
734
+ warnings.push(
735
+ `target.network_mocks[${mockIndex}]${mockLabel} ${responseLabel(earlier, earlierIndex)} can shadow ${responseLabel(later, laterIndex)} because the earlier request_body_contains fragments are a subset of the later response and have no negative or pattern disambiguator. First matching request-body response wins.`
736
+ );
737
+ break;
738
+ }
739
+ }
740
+ }
741
+ return warnings;
742
+ }
700
743
  function normalizeRouteInventoryPath(value, label) {
701
744
  const path = stringValue(value);
702
745
  if (!path) throw new Error(`${label} requires path.`);
@@ -1055,6 +1098,13 @@ function normalizeLinkStatusContentType(value) {
1055
1098
  const normalized = value?.split(";")[0]?.trim().toLowerCase();
1056
1099
  return normalized || void 0;
1057
1100
  }
1101
+ function linkStatusContentTypesMatch(actual, expected) {
1102
+ if (!actual || !expected) return false;
1103
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
1104
+ if (actual === expected) return true;
1105
+ const yamlTypes = /* @__PURE__ */ new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
1106
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
1107
+ }
1058
1108
  function linkStatusContentTypeOk(result, check) {
1059
1109
  const expected = check.allowed_content_types;
1060
1110
  if (!expected?.length) return true;
@@ -1063,8 +1113,7 @@ function linkStatusContentTypeOk(result, check) {
1063
1113
  return expected.some((contentType) => {
1064
1114
  const normalized = normalizeLinkStatusContentType(contentType);
1065
1115
  if (!normalized) return false;
1066
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
1067
- return actual === normalized;
1116
+ return linkStatusContentTypesMatch(actual, normalized);
1068
1117
  });
1069
1118
  }
1070
1119
  function httpStatusBodyContainsFailures(result, check) {
@@ -2085,11 +2134,11 @@ function networkMockResponseHitsByLabel(events) {
2085
2134
  for (const event of events) {
2086
2135
  if (!event || event.ok === false) continue;
2087
2136
  const label = typeof event.label === "string" ? event.label : "";
2088
- const responseLabel = typeof event.response_label === "string" ? event.response_label : "";
2089
- const hasSequenceResponse = typeof event.response_index === "number" || event.sequence_cycle === true || Boolean(responseLabel && responseLabel !== label);
2090
- if (!label || !responseLabel || !hasSequenceResponse) continue;
2137
+ const responseLabel2 = typeof event.response_label === "string" ? event.response_label : "";
2138
+ const hasSequenceResponse = typeof event.response_index === "number" || event.sequence_cycle === true || Boolean(responseLabel2 && responseLabel2 !== label);
2139
+ if (!label || !responseLabel2 || !hasSequenceResponse) continue;
2091
2140
  responseHits[label] || (responseHits[label] = {});
2092
- responseHits[label][responseLabel] = (responseHits[label][responseLabel] || 0) + 1;
2141
+ responseHits[label][responseLabel2] = (responseHits[label][responseLabel2] || 0) + 1;
2093
2142
  }
2094
2143
  return responseHits;
2095
2144
  }
@@ -2112,6 +2161,7 @@ function profileStatusFromEvidence(profile, evidence, checks) {
2112
2161
  }
2113
2162
  function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
2114
2163
  const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
2164
+ const warnings = collectRiddleProofProfileWarnings(profile);
2115
2165
  const checks = evidence ? [
2116
2166
  assessNetworkMocksFromEvidence(profile, evidence),
2117
2167
  assessSetupActionsFromEvidence(profile, evidence),
@@ -2137,6 +2187,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
2137
2187
  checks,
2138
2188
  summary: summarizeRiddleProofProfileResult({ profile_name: profile.name, status, checks, viewports: evidence?.viewports || [] }),
2139
2189
  captured_at: capturedAt,
2190
+ warnings: warnings.length ? warnings : void 0,
2140
2191
  evidence,
2141
2192
  riddle: options.riddle
2142
2193
  };
@@ -2185,6 +2236,7 @@ function createRiddleProofProfileConfigurationError(name, error, runner = "riddl
2185
2236
  function createRiddleProofProfileEnvironmentBlockedResult(input) {
2186
2237
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "Riddle runner did not complete successfully.";
2187
2238
  const environmentBlocker = extractRiddleRunnerBlocker(message);
2239
+ const warnings = collectRiddleProofProfileWarnings(input.profile);
2188
2240
  return {
2189
2241
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
2190
2242
  profile_name: input.profile.name,
@@ -2196,6 +2248,7 @@ function createRiddleProofProfileEnvironmentBlockedResult(input) {
2196
2248
  checks: [],
2197
2249
  summary: summarizeEnvironmentBlockedRunner(input.profile.name, environmentBlocker),
2198
2250
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
2251
+ warnings: warnings.length ? warnings : void 0,
2199
2252
  riddle: input.riddle,
2200
2253
  environment_blocker: environmentBlocker,
2201
2254
  error: message
@@ -2254,6 +2307,7 @@ function summarizeEnvironmentBlockedRunner(profileName, blocker) {
2254
2307
  }
2255
2308
  function createRiddleProofProfileInsufficientResult(input) {
2256
2309
  const message = input.error instanceof Error ? input.error.message : input.error ? String(input.error) : "No proof.json profile result artifact was found.";
2310
+ const warnings = collectRiddleProofProfileWarnings(input.profile);
2257
2311
  return {
2258
2312
  version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
2259
2313
  profile_name: input.profile.name,
@@ -2265,6 +2319,7 @@ function createRiddleProofProfileInsufficientResult(input) {
2265
2319
  checks: [],
2266
2320
  summary: `${input.profile.name} did not produce enough evidence for a profile judgment.`,
2267
2321
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
2322
+ warnings: warnings.length ? warnings : void 0,
2268
2323
  riddle: input.riddle,
2269
2324
  error: message
2270
2325
  };
@@ -2469,6 +2524,13 @@ function normalizeLinkStatusContentType(value) {
2469
2524
  const normalized = (value.split(";")[0] || "").trim().toLowerCase();
2470
2525
  return normalized || undefined;
2471
2526
  }
2527
+ function linkStatusContentTypesMatch(actual, expected) {
2528
+ if (!actual || !expected) return false;
2529
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
2530
+ if (actual === expected) return true;
2531
+ const yamlTypes = new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
2532
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
2533
+ }
2472
2534
  function linkStatusContentTypeOk(result, check) {
2473
2535
  if (!Array.isArray(check.allowed_content_types) || !check.allowed_content_types.length) return true;
2474
2536
  const actual = normalizeLinkStatusContentType(result.content_type);
@@ -2476,8 +2538,7 @@ function linkStatusContentTypeOk(result, check) {
2476
2538
  return check.allowed_content_types.some((contentType) => {
2477
2539
  const normalized = normalizeLinkStatusContentType(contentType);
2478
2540
  if (!normalized) return false;
2479
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
2480
- return actual === normalized;
2541
+ return linkStatusContentTypesMatch(actual, normalized);
2481
2542
  });
2482
2543
  }
2483
2544
  function httpStatusBodyContainsFailures(result, check) {
@@ -3571,6 +3632,7 @@ function assessProfile(profile, evidence) {
3571
3632
  checks,
3572
3633
  summary,
3573
3634
  captured_at: evidence.captured_at,
3635
+ warnings: profileWarnings.length ? profileWarnings : undefined,
3574
3636
  evidence,
3575
3637
  };
3576
3638
  }
@@ -3579,11 +3641,14 @@ function assessProfile(profile, evidence) {
3579
3641
  function buildRiddleProofProfileScript(profile) {
3580
3642
  const targetUrl = resolveRiddleProofProfileTargetUrl(profile);
3581
3643
  const slug = slugifyRiddleProofProfileName(profile.name);
3644
+ const profileWarnings = collectRiddleProofProfileWarnings(profile);
3582
3645
  const serializableProfile = JSON.stringify(profile);
3646
+ const serializableProfileWarnings = JSON.stringify(profileWarnings);
3583
3647
  const serializableTargetUrl = JSON.stringify(targetUrl);
3584
3648
  const serializableSlug = JSON.stringify(slug);
3585
3649
  return String.raw`
3586
3650
  const profile = ${serializableProfile};
3651
+ const profileWarnings = ${serializableProfileWarnings};
3587
3652
  const targetUrl = ${serializableTargetUrl};
3588
3653
  const profileSlug = ${serializableSlug};
3589
3654
  const capturedAt = new Date().toISOString();
@@ -4609,6 +4674,13 @@ function normalizeLinkProbeContentType(value) {
4609
4674
  const normalized = (value.split(";")[0] || "").trim().toLowerCase();
4610
4675
  return normalized || undefined;
4611
4676
  }
4677
+ function linkProbeContentTypesMatch(actual, expected) {
4678
+ if (!actual || !expected) return false;
4679
+ if (expected.endsWith("/*")) return actual.startsWith(expected.slice(0, -1));
4680
+ if (actual === expected) return true;
4681
+ const yamlTypes = new Set(["application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"]);
4682
+ return yamlTypes.has(actual) && yamlTypes.has(expected);
4683
+ }
4612
4684
  function linkProbeContentTypeAllowed(result, check) {
4613
4685
  if (!Array.isArray(check.allowed_content_types) || !check.allowed_content_types.length) return true;
4614
4686
  const actual = normalizeLinkProbeContentType(result.content_type);
@@ -4616,8 +4688,7 @@ function linkProbeContentTypeAllowed(result, check) {
4616
4688
  return check.allowed_content_types.some((contentType) => {
4617
4689
  const normalized = normalizeLinkProbeContentType(contentType);
4618
4690
  if (!normalized) return false;
4619
- if (normalized.endsWith("/*")) return actual.startsWith(normalized.slice(0, -1));
4620
- return actual === normalized;
4691
+ return linkProbeContentTypesMatch(actual, normalized);
4621
4692
  });
4622
4693
  }
4623
4694
  function linkProbeResponseFields(response, method) {
@@ -5713,6 +5784,7 @@ function extractRiddleProofProfileResult(input) {
5713
5784
  assessRiddleProofProfileEvidence,
5714
5785
  buildRiddleProofProfileScript,
5715
5786
  collectRiddleProfileArtifactRefs,
5787
+ collectRiddleProofProfileWarnings,
5716
5788
  createRiddleProofProfileConfigurationError,
5717
5789
  createRiddleProofProfileEnvironmentBlockedResult,
5718
5790
  createRiddleProofProfileInsufficientResult,
@@ -266,6 +266,7 @@ interface RiddleProofProfileResult {
266
266
  checks: RiddleProofProfileCheckResult[];
267
267
  summary: string;
268
268
  captured_at: string;
269
+ warnings?: string[];
269
270
  evidence?: RiddleProofProfileEvidence;
270
271
  riddle?: {
271
272
  job_id?: string;
@@ -289,6 +290,7 @@ interface NormalizeRiddleProofProfileOptions {
289
290
  viewports?: RiddleProofProfileViewport[];
290
291
  }
291
292
  declare function slugifyRiddleProofProfileName(value: string): string;
293
+ declare function collectRiddleProofProfileWarnings(profile: RiddleProofProfile): string[];
292
294
  declare function normalizeRiddleProofProfile(input: unknown, options?: NormalizeRiddleProofProfileOptions): RiddleProofProfile;
293
295
  declare function resolveRiddleProofProfileTargetUrl(profile: RiddleProofProfile): string;
294
296
  declare function resolveRiddleProofProfileTimeoutSec(profile: RiddleProofProfile, requestedTimeoutSec?: number): number | undefined;
@@ -324,4 +326,4 @@ declare function buildRiddleProofProfileScript(profile: RiddleProofProfile): str
324
326
  declare function collectRiddleProfileArtifactRefs(input: unknown): RiddleProofProfileArtifactRef[];
325
327
  declare function extractRiddleProofProfileResult(input: unknown): RiddleProofProfileResult | undefined;
326
328
 
327
- export { type NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, type RiddleProofProfile, type RiddleProofProfileArtifactRef, type RiddleProofProfileBaselinePolicy, type RiddleProofProfileBoundsOffender, type RiddleProofProfileCheck, type RiddleProofProfileCheckResult, type RiddleProofProfileCheckType, type RiddleProofProfileEvidence, type RiddleProofProfileFailureAction, type RiddleProofProfileNetworkMock, type RiddleProofProfileNetworkMockResponse, type RiddleProofProfileResult, type RiddleProofProfileRouteEvidence, type RiddleProofProfileRouteInventoryRoute, type RiddleProofProfileRunner, type RiddleProofProfileSetupAction, type RiddleProofProfileSetupActionType, type RiddleProofProfileStatus, type RiddleProofProfileTarget, type RiddleProofProfileViewport, type RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult };
329
+ export { type NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, type RiddleProofProfile, type RiddleProofProfileArtifactRef, type RiddleProofProfileBaselinePolicy, type RiddleProofProfileBoundsOffender, type RiddleProofProfileCheck, type RiddleProofProfileCheckResult, type RiddleProofProfileCheckType, type RiddleProofProfileEvidence, type RiddleProofProfileFailureAction, type RiddleProofProfileNetworkMock, type RiddleProofProfileNetworkMockResponse, type RiddleProofProfileResult, type RiddleProofProfileRouteEvidence, type RiddleProofProfileRouteInventoryRoute, type RiddleProofProfileRunner, type RiddleProofProfileSetupAction, type RiddleProofProfileSetupActionType, type RiddleProofProfileStatus, type RiddleProofProfileTarget, type RiddleProofProfileViewport, type RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, collectRiddleProofProfileWarnings, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult };
package/dist/profile.d.ts CHANGED
@@ -266,6 +266,7 @@ interface RiddleProofProfileResult {
266
266
  checks: RiddleProofProfileCheckResult[];
267
267
  summary: string;
268
268
  captured_at: string;
269
+ warnings?: string[];
269
270
  evidence?: RiddleProofProfileEvidence;
270
271
  riddle?: {
271
272
  job_id?: string;
@@ -289,6 +290,7 @@ interface NormalizeRiddleProofProfileOptions {
289
290
  viewports?: RiddleProofProfileViewport[];
290
291
  }
291
292
  declare function slugifyRiddleProofProfileName(value: string): string;
293
+ declare function collectRiddleProofProfileWarnings(profile: RiddleProofProfile): string[];
292
294
  declare function normalizeRiddleProofProfile(input: unknown, options?: NormalizeRiddleProofProfileOptions): RiddleProofProfile;
293
295
  declare function resolveRiddleProofProfileTargetUrl(profile: RiddleProofProfile): string;
294
296
  declare function resolveRiddleProofProfileTimeoutSec(profile: RiddleProofProfile, requestedTimeoutSec?: number): number | undefined;
@@ -324,4 +326,4 @@ declare function buildRiddleProofProfileScript(profile: RiddleProofProfile): str
324
326
  declare function collectRiddleProfileArtifactRefs(input: unknown): RiddleProofProfileArtifactRef[];
325
327
  declare function extractRiddleProofProfileResult(input: unknown): RiddleProofProfileResult | undefined;
326
328
 
327
- export { type NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, type RiddleProofProfile, type RiddleProofProfileArtifactRef, type RiddleProofProfileBaselinePolicy, type RiddleProofProfileBoundsOffender, type RiddleProofProfileCheck, type RiddleProofProfileCheckResult, type RiddleProofProfileCheckType, type RiddleProofProfileEvidence, type RiddleProofProfileFailureAction, type RiddleProofProfileNetworkMock, type RiddleProofProfileNetworkMockResponse, type RiddleProofProfileResult, type RiddleProofProfileRouteEvidence, type RiddleProofProfileRouteInventoryRoute, type RiddleProofProfileRunner, type RiddleProofProfileSetupAction, type RiddleProofProfileSetupActionType, type RiddleProofProfileStatus, type RiddleProofProfileTarget, type RiddleProofProfileViewport, type RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult };
329
+ export { type NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, type RiddleProofProfile, type RiddleProofProfileArtifactRef, type RiddleProofProfileBaselinePolicy, type RiddleProofProfileBoundsOffender, type RiddleProofProfileCheck, type RiddleProofProfileCheckResult, type RiddleProofProfileCheckType, type RiddleProofProfileEvidence, type RiddleProofProfileFailureAction, type RiddleProofProfileNetworkMock, type RiddleProofProfileNetworkMockResponse, type RiddleProofProfileResult, type RiddleProofProfileRouteEvidence, type RiddleProofProfileRouteInventoryRoute, type RiddleProofProfileRunner, type RiddleProofProfileSetupAction, type RiddleProofProfileSetupActionType, type RiddleProofProfileStatus, type RiddleProofProfileTarget, type RiddleProofProfileViewport, type RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, collectRiddleProofProfileWarnings, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult };
package/dist/profile.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  assessRiddleProofProfileEvidence,
9
9
  buildRiddleProofProfileScript,
10
10
  collectRiddleProfileArtifactRefs,
11
+ collectRiddleProofProfileWarnings,
11
12
  createRiddleProofProfileConfigurationError,
12
13
  createRiddleProofProfileEnvironmentBlockedResult,
13
14
  createRiddleProofProfileInsufficientResult,
@@ -19,7 +20,7 @@ import {
19
20
  resolveRiddleProofProfileTimeoutSec,
20
21
  slugifyRiddleProofProfileName,
21
22
  summarizeRiddleProofProfileResult
22
- } from "./chunk-KKH76HIA.js";
23
+ } from "./chunk-3CND75DM.js";
23
24
  export {
24
25
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
25
26
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
@@ -30,6 +31,7 @@ export {
30
31
  assessRiddleProofProfileEvidence,
31
32
  buildRiddleProofProfileScript,
32
33
  collectRiddleProfileArtifactRefs,
34
+ collectRiddleProofProfileWarnings,
33
35
  createRiddleProofProfileConfigurationError,
34
36
  createRiddleProofProfileEnvironmentBlockedResult,
35
37
  createRiddleProofProfileInsufficientResult,
@@ -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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
295
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
385
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
662
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
295
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
385
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
662
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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.111",
3
+ "version": "0.7.113",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",