@riddledc/riddle-proof 0.8.72 → 0.8.73

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
@@ -545,6 +545,10 @@ stable enough for Playwright's default click actionability checks. Use `press`
545
545
  with a Playwright key name, such as `Enter`, `Space`, or `ArrowLeft`,
546
546
  when a route's intended browser control is keyboard-driven; omit `selector` for
547
547
  a page-level key press, or provide `selector` to press against a focused element.
548
+ Target-level `wait_for_selector` runs immediately after navigation and before
549
+ `setup_actions`. If setup creates the ready state, for example by seeding
550
+ localStorage and reloading an authenticated fixture, put the readiness wait in
551
+ `setup_actions` after the state change instead.
548
552
  For canvas games that read key state rather than keypress events, add `hold_ms`
549
553
  or `holdMs` to keep the key down before releasing it. When the profile needs
550
554
  to observe or wait on runtime evidence while a key remains held, use paired
@@ -1259,15 +1259,83 @@ function profileHttpStatusPreflightSummary(result) {
1259
1259
  return `${lines.join("\n")}
1260
1260
  `;
1261
1261
  }
1262
+ function profilePlainStatusLabel(status) {
1263
+ if (status === "passed") return "passed";
1264
+ if (status === "product_regression") return "product issue";
1265
+ if (status === "proof_insufficient") return "missing evidence";
1266
+ if (status === "environment_blocked") return "environment blocked";
1267
+ if (status === "configuration_error") return "configuration issue";
1268
+ return "needs review";
1269
+ }
1270
+ function profilePlainCheckSummary(result) {
1271
+ const total = result.checks.length;
1272
+ const passed = result.checks.filter((check) => check.status === "passed").length;
1273
+ const failed = result.checks.filter((check) => check.status === "failed").length;
1274
+ const review = result.checks.filter((check) => check.status === "needs_human_review").length;
1275
+ const skipped = result.checks.filter((check) => check.status === "skipped").length;
1276
+ const evidenceViewportNames = (result.evidence?.viewports || []).map((viewport) => cliString(viewport.name)).filter((name) => Boolean(name));
1277
+ const setupViewportNames = evidenceViewportNames.length ? [] : profileSetupSummaryViewports(result).map((viewport) => cliString(viewport.name)).filter((name) => Boolean(name));
1278
+ const viewportNames = evidenceViewportNames.length ? evidenceViewportNames : setupViewportNames;
1279
+ const route = result.route?.requested || result.route?.observed;
1280
+ const countText = total === 1 ? "1 check" : `${total} checks`;
1281
+ const viewportText = viewportNames.length ? ` across ${viewportNames.length} viewport${viewportNames.length === 1 ? "" : "s"} (${viewportNames.join(", ")})` : "";
1282
+ const routeText = route ? ` on ${markdownInlineCode(route, 120)}` : "";
1283
+ const outcomes = [
1284
+ passed ? `${passed} passed` : "",
1285
+ failed ? `${failed} failed` : "",
1286
+ review ? `${review} needs review` : "",
1287
+ skipped ? `${skipped} skipped` : ""
1288
+ ].filter(Boolean).join(", ");
1289
+ if (!total) return route ? `No browser checks were recorded for ${markdownInlineCode(route, 120)}.` : "No browser checks were recorded.";
1290
+ return `${countText}${viewportText}${routeText}; ${outcomes || "no completed checks"}.`;
1291
+ }
1292
+ function profileArtifactRefIsScreenshot(artifact) {
1293
+ const kind = cliString(artifact.kind)?.toLowerCase() || "";
1294
+ const contentType = cliString(artifact.content_type)?.toLowerCase() || "";
1295
+ const text = [artifact.name, artifact.url, artifact.path].map((value) => cliString(value)).filter(Boolean).join(" ");
1296
+ return kind === "screenshot" || contentType.startsWith("image/") || /\.(png|jpe?g|webp)(?:$|[?#])/i.test(text);
1297
+ }
1298
+ function profileArtifactDisplay(artifact) {
1299
+ const name = artifact.name || artifact.kind || "artifact";
1300
+ const location = artifact.url || artifact.path;
1301
+ return location ? `${name}: ${location}` : name;
1302
+ }
1303
+ function profilePlainArtifactSummary(result) {
1304
+ const hostedArtifacts = result.artifacts.riddle_artifacts || [];
1305
+ const hostedScreenshot = hostedArtifacts.find(profileArtifactRefIsScreenshot);
1306
+ if (hostedScreenshot) return `Hosted screenshot ${profileArtifactDisplay(hostedScreenshot)}`;
1307
+ const hostedProof = hostedArtifacts.find((artifact) => {
1308
+ const name = (artifact.name || artifact.url || artifact.path || "").toLowerCase();
1309
+ return name.includes("proof.json");
1310
+ });
1311
+ if (hostedProof) return `Hosted proof JSON ${profileArtifactDisplay(hostedProof)}`;
1312
+ if (result.artifacts.screenshots?.length) return `Screenshot ${markdownInlineCode(result.artifacts.screenshots[0])}`;
1313
+ if (result.artifacts.proof_json) return `Proof JSON ${markdownInlineCode(result.artifacts.proof_json)}`;
1314
+ return "profile-result.json and summary.md";
1315
+ }
1316
+ function profilePlainNextStep(result) {
1317
+ if (result.status === "passed") return "Use this packet as scoped browser evidence, then review the linked artifacts before merge.";
1318
+ if (result.status === "product_regression") return "Fix the failed product check(s), then rerun this profile.";
1319
+ if (result.status === "proof_insufficient") return "Adjust the profile or runner so the required evidence artifacts are produced, then rerun.";
1320
+ if (result.status === "environment_blocked") return "Fix the runner or environment blocker, then rerun.";
1321
+ if (result.status === "configuration_error") return result.error ? `Fix the profile setup: ${result.error}` : "Fix the profile setup, then rerun.";
1322
+ return "Review the artifacts manually, then refine the profile if the verdict should be automated.";
1323
+ }
1262
1324
  function profileResultMarkdown(result) {
1263
1325
  const lines = [
1264
1326
  `# Riddle Proof Profile: ${result.profile_name}`,
1265
1327
  "",
1266
- `Status: ${result.status}`,
1267
- `Runner: ${result.runner}`,
1268
- `Captured: ${result.captured_at}`,
1328
+ `Result: ${profilePlainStatusLabel(result.status)}`,
1329
+ `What was checked: ${profilePlainCheckSummary(result)}`,
1330
+ `Artifact that proves it: ${profilePlainArtifactSummary(result)}`,
1331
+ `What to do next: ${profilePlainNextStep(result)}`,
1269
1332
  "",
1270
- result.summary,
1333
+ "## Details",
1334
+ "",
1335
+ `- Status: ${result.status}`,
1336
+ `- Runner: ${result.runner}`,
1337
+ `- Captured: ${result.captured_at}`,
1338
+ `- Summary: ${result.summary}`,
1271
1339
  ""
1272
1340
  ];
1273
1341
  if (Array.isArray(result.warnings) && result.warnings.length) {
package/dist/cli/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import "../chunk-XIJI62DC.js";
1
+ import "../chunk-ICIJTEHD.js";
2
2
  import "../chunk-B2DP2LET.js";
3
3
  import "../chunk-CWRIXP5H.js";
4
4
  import "../chunk-UE4I7RTI.js";
package/dist/cli.cjs CHANGED
@@ -19821,15 +19821,83 @@ function profileHttpStatusPreflightSummary(result) {
19821
19821
  return `${lines.join("\n")}
19822
19822
  `;
19823
19823
  }
19824
+ function profilePlainStatusLabel(status) {
19825
+ if (status === "passed") return "passed";
19826
+ if (status === "product_regression") return "product issue";
19827
+ if (status === "proof_insufficient") return "missing evidence";
19828
+ if (status === "environment_blocked") return "environment blocked";
19829
+ if (status === "configuration_error") return "configuration issue";
19830
+ return "needs review";
19831
+ }
19832
+ function profilePlainCheckSummary(result) {
19833
+ const total = result.checks.length;
19834
+ const passed = result.checks.filter((check) => check.status === "passed").length;
19835
+ const failed = result.checks.filter((check) => check.status === "failed").length;
19836
+ const review = result.checks.filter((check) => check.status === "needs_human_review").length;
19837
+ const skipped = result.checks.filter((check) => check.status === "skipped").length;
19838
+ const evidenceViewportNames = (result.evidence?.viewports || []).map((viewport) => cliString(viewport.name)).filter((name) => Boolean(name));
19839
+ const setupViewportNames = evidenceViewportNames.length ? [] : profileSetupSummaryViewports(result).map((viewport) => cliString(viewport.name)).filter((name) => Boolean(name));
19840
+ const viewportNames = evidenceViewportNames.length ? evidenceViewportNames : setupViewportNames;
19841
+ const route = result.route?.requested || result.route?.observed;
19842
+ const countText = total === 1 ? "1 check" : `${total} checks`;
19843
+ const viewportText = viewportNames.length ? ` across ${viewportNames.length} viewport${viewportNames.length === 1 ? "" : "s"} (${viewportNames.join(", ")})` : "";
19844
+ const routeText = route ? ` on ${markdownInlineCode(route, 120)}` : "";
19845
+ const outcomes = [
19846
+ passed ? `${passed} passed` : "",
19847
+ failed ? `${failed} failed` : "",
19848
+ review ? `${review} needs review` : "",
19849
+ skipped ? `${skipped} skipped` : ""
19850
+ ].filter(Boolean).join(", ");
19851
+ if (!total) return route ? `No browser checks were recorded for ${markdownInlineCode(route, 120)}.` : "No browser checks were recorded.";
19852
+ return `${countText}${viewportText}${routeText}; ${outcomes || "no completed checks"}.`;
19853
+ }
19854
+ function profileArtifactRefIsScreenshot2(artifact) {
19855
+ const kind = cliString(artifact.kind)?.toLowerCase() || "";
19856
+ const contentType = cliString(artifact.content_type)?.toLowerCase() || "";
19857
+ const text = [artifact.name, artifact.url, artifact.path].map((value) => cliString(value)).filter(Boolean).join(" ");
19858
+ return kind === "screenshot" || contentType.startsWith("image/") || /\.(png|jpe?g|webp)(?:$|[?#])/i.test(text);
19859
+ }
19860
+ function profileArtifactDisplay(artifact) {
19861
+ const name = artifact.name || artifact.kind || "artifact";
19862
+ const location = artifact.url || artifact.path;
19863
+ return location ? `${name}: ${location}` : name;
19864
+ }
19865
+ function profilePlainArtifactSummary(result) {
19866
+ const hostedArtifacts = result.artifacts.riddle_artifacts || [];
19867
+ const hostedScreenshot = hostedArtifacts.find(profileArtifactRefIsScreenshot2);
19868
+ if (hostedScreenshot) return `Hosted screenshot ${profileArtifactDisplay(hostedScreenshot)}`;
19869
+ const hostedProof = hostedArtifacts.find((artifact) => {
19870
+ const name = (artifact.name || artifact.url || artifact.path || "").toLowerCase();
19871
+ return name.includes("proof.json");
19872
+ });
19873
+ if (hostedProof) return `Hosted proof JSON ${profileArtifactDisplay(hostedProof)}`;
19874
+ if (result.artifacts.screenshots?.length) return `Screenshot ${markdownInlineCode(result.artifacts.screenshots[0])}`;
19875
+ if (result.artifacts.proof_json) return `Proof JSON ${markdownInlineCode(result.artifacts.proof_json)}`;
19876
+ return "profile-result.json and summary.md";
19877
+ }
19878
+ function profilePlainNextStep(result) {
19879
+ if (result.status === "passed") return "Use this packet as scoped browser evidence, then review the linked artifacts before merge.";
19880
+ if (result.status === "product_regression") return "Fix the failed product check(s), then rerun this profile.";
19881
+ if (result.status === "proof_insufficient") return "Adjust the profile or runner so the required evidence artifacts are produced, then rerun.";
19882
+ if (result.status === "environment_blocked") return "Fix the runner or environment blocker, then rerun.";
19883
+ if (result.status === "configuration_error") return result.error ? `Fix the profile setup: ${result.error}` : "Fix the profile setup, then rerun.";
19884
+ return "Review the artifacts manually, then refine the profile if the verdict should be automated.";
19885
+ }
19824
19886
  function profileResultMarkdown(result) {
19825
19887
  const lines = [
19826
19888
  `# Riddle Proof Profile: ${result.profile_name}`,
19827
19889
  "",
19828
- `Status: ${result.status}`,
19829
- `Runner: ${result.runner}`,
19830
- `Captured: ${result.captured_at}`,
19890
+ `Result: ${profilePlainStatusLabel(result.status)}`,
19891
+ `What was checked: ${profilePlainCheckSummary(result)}`,
19892
+ `Artifact that proves it: ${profilePlainArtifactSummary(result)}`,
19893
+ `What to do next: ${profilePlainNextStep(result)}`,
19831
19894
  "",
19832
- result.summary,
19895
+ "## Details",
19896
+ "",
19897
+ `- Status: ${result.status}`,
19898
+ `- Runner: ${result.runner}`,
19899
+ `- Captured: ${result.captured_at}`,
19900
+ `- Summary: ${result.summary}`,
19833
19901
  ""
19834
19902
  ];
19835
19903
  if (Array.isArray(result.warnings) && result.warnings.length) {
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-XIJI62DC.js";
2
+ import "./chunk-ICIJTEHD.js";
3
3
  import "./chunk-B2DP2LET.js";
4
4
  import "./chunk-CWRIXP5H.js";
5
5
  import "./chunk-UE4I7RTI.js";
@@ -17,3 +17,11 @@ packages/riddle-proof-runner-playwright/bin/riddle-proof-playwright run-profile
17
17
  The sibling `neutral-fixture-product-regression.json` profile intentionally
18
18
  looks for a missing selector. A correct Riddle Proof run reports
19
19
  `product_regression`, not `passed`.
20
+
21
+ `neutral-fixture-auth-session.json` exercises a stored browser-state handoff by
22
+ writing a deterministic localStorage token, reloading `auth.html`, and proving
23
+ that the authenticated fixture state is visible.
24
+
25
+ The auth profile keeps its readiness wait inside `setup_actions`, after the
26
+ localStorage write and reload. A target-level `wait_for_selector` would run
27
+ before setup and would block the token handoff.
@@ -0,0 +1,45 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Riddle Proof Auth Fixture</title>
7
+ <link rel="stylesheet" href="./styles.css" />
8
+ </head>
9
+ <body>
10
+ <main class="fixture-shell" data-rp-fixture="auth">
11
+ <p class="eyebrow">Neutral fixture</p>
12
+ <h1>Stored Auth Smoke</h1>
13
+ <p class="lead">
14
+ This page only exposes the success state when the runner supplies the
15
+ expected stored browser token.
16
+ </p>
17
+ <section class="evidence-panel auth-state" id="auth-state" data-rp-fixture="auth-pending" aria-live="polite">
18
+ Checking stored browser state.
19
+ </section>
20
+ </main>
21
+ <script>
22
+ (() => {
23
+ const expectedToken = "riddle-proof-fixture-token";
24
+ const observedToken = window.localStorage.getItem("rp_fixture_auth_token") || "";
25
+ const panel = document.getElementById("auth-state");
26
+ if (!panel) return;
27
+ if (observedToken === expectedToken) {
28
+ document.documentElement.dataset.authState = "passed";
29
+ panel.dataset.rpFixture = "auth-passed";
30
+ panel.innerHTML = [
31
+ "<strong>Authenticated fixture passed</strong>",
32
+ "<span>Stored browser state reached the page before checks ran.</span>",
33
+ ].join("");
34
+ return;
35
+ }
36
+ document.documentElement.dataset.authState = "blocked";
37
+ panel.dataset.rpFixture = "auth-blocked";
38
+ panel.innerHTML = [
39
+ "<strong>Sign in required</strong>",
40
+ "<span>The expected stored browser token was not present.</span>",
41
+ ].join("");
42
+ })();
43
+ </script>
44
+ </body>
45
+ </html>
@@ -17,6 +17,7 @@
17
17
  </p>
18
18
  <nav aria-label="Fixture pages">
19
19
  <a href="./pass.html">Passing fixture page</a>
20
+ <a href="./auth.html">Stored auth fixture page</a>
20
21
  </nav>
21
22
  </main>
22
23
  </body>
@@ -22,6 +22,13 @@ a {
22
22
  font-weight: 700;
23
23
  }
24
24
 
25
+ nav {
26
+ display: flex;
27
+ flex-wrap: wrap;
28
+ gap: 14px 18px;
29
+ margin-top: 28px;
30
+ }
31
+
25
32
  .fixture-shell {
26
33
  width: min(100% - 32px, 760px);
27
34
  margin: 0 auto;
@@ -90,6 +97,31 @@ dd {
90
97
  font-weight: 700;
91
98
  }
92
99
 
100
+ .auth-state {
101
+ display: grid;
102
+ gap: 6px;
103
+ padding: 18px;
104
+ }
105
+
106
+ .auth-state strong,
107
+ .auth-state span {
108
+ display: block;
109
+ }
110
+
111
+ .auth-state strong {
112
+ font-size: 1.05rem;
113
+ }
114
+
115
+ .auth-state[data-rp-fixture="auth-passed"] {
116
+ border-color: #7bb69c;
117
+ background: #f1fbf6;
118
+ }
119
+
120
+ .auth-state[data-rp-fixture="auth-blocked"] {
121
+ border-color: #c58b8b;
122
+ background: #fff6f4;
123
+ }
124
+
93
125
  @media (max-width: 640px) {
94
126
  h1 {
95
127
  font-size: 2.25rem;
@@ -0,0 +1,44 @@
1
+ {
2
+ "version": "riddle-proof.profile.v1",
3
+ "name": "neutral-fixture-auth-session",
4
+ "target": {
5
+ "route": "/auth.html",
6
+ "viewports": [
7
+ { "name": "phone", "width": 390, "height": 844 },
8
+ { "name": "desktop", "width": 1440, "height": 1000 }
9
+ ],
10
+ "auth": "stored-browser-state-fixture",
11
+ "setup_actions": [
12
+ {
13
+ "type": "local_storage",
14
+ "key": "rp_fixture_auth_token",
15
+ "value": "riddle-proof-fixture-token",
16
+ "reload": true
17
+ },
18
+ {
19
+ "type": "wait_for_selector",
20
+ "selector": "[data-rp-fixture=\"auth-passed\"]",
21
+ "timeout_ms": 10000
22
+ },
23
+ { "type": "wait", "ms": 100 }
24
+ ]
25
+ },
26
+ "checks": [
27
+ { "type": "route_loaded", "expected_path": "/auth.html" },
28
+ { "type": "selector_visible", "selector": "[data-rp-fixture=\"auth-passed\"]" },
29
+ { "type": "selector_text_visible", "selector": "[data-rp-fixture=\"auth-passed\"]", "text": "Authenticated fixture passed" },
30
+ { "type": "selector_text_absent", "selector": "body", "text": "Sign in required" },
31
+ { "type": "no_mobile_horizontal_overflow" },
32
+ { "type": "no_fatal_console_errors" }
33
+ ],
34
+ "artifacts": ["screenshot", "console", "dom_summary", "proof_json"],
35
+ "metadata": {
36
+ "fixture_kind": "stored_auth_session",
37
+ "covers": "localStorage auth/session handoff before browser checks"
38
+ },
39
+ "failure_policy": {
40
+ "environment_blocked": "neutral",
41
+ "proof_insufficient": "fail",
42
+ "product_regression": "fail"
43
+ }
44
+ }
@@ -334,6 +334,25 @@
334
334
  "existing_coverage": ["docs/riddle-proof-story-matrix-runs/2026-06-22-neutral-fixture-batch.md"],
335
335
  "status": "recurring"
336
336
  },
337
+ {
338
+ "id": "rp-story-neutral-fixture-auth-session-smoke",
339
+ "batch": "neutral-fixture",
340
+ "surface": "neutral fixture auth/session profile",
341
+ "user_story": "As a Riddle Proof user, I can run a browser profile that supplies stored auth/session state before page checks execute.",
342
+ "expected_behavior": "The profile writes a deterministic localStorage token, reloads the page, reaches the authenticated fixture state, and produces normal proof artifacts locally and hosted.",
343
+ "primary_runner": "hosted-riddle",
344
+ "command": "riddle-proof-loop run-profile --profile packages/riddle-proof/examples/profiles/neutral-fixture-auth-session.json --url <preview-url> --runner riddle --output artifacts/riddle-proof/neutral-fixture-auth-session-hosted --result-format compact-json",
345
+ "expected_verdict": "passed",
346
+ "evidence_required": [
347
+ "profile-result.json status is passed",
348
+ "setup_actions_succeeded records local_storage with reload",
349
+ "hosted or local screenshots show the authenticated fixture state"
350
+ ],
351
+ "receipt_types": ["profile-result.json", "proof.json", "summary.md", "screenshot"],
352
+ "failure_classes": ["product_regression", "proof_insufficient", "environment_blocked"],
353
+ "existing_coverage": ["examples/profiles/neutral-fixture-auth-session.json", "examples/neutral-fixture-site/auth.html"],
354
+ "status": "recurring"
355
+ },
337
356
  {
338
357
  "id": "rp-story-neutral-fixture-public-state-blockers",
339
358
  "batch": "neutral-fixture",
@@ -21,8 +21,9 @@ area,user_story_id,user_story,expected_behavior,surface,runner,evidence_required
21
21
  "Agent summary","rp-ux-agent-summary-contract-human-review","As an agent consuming Riddle Proof output, I see needs_human_review as a held proof state, not a pass.","Agent summary helper maps needs_human_review to proof_blocked and requires human-review disclosure.","agent summary contract","formal-conformance","needs_human_review packet; disclosure; prohibited proof_passed claim","passed","2026-06-21","packages/riddle-proof/formal-conformance.test.js","Human-review verdicts now stay blocked in public consumer surfaces.","Keep this for evidence packets with subjective or unsupported checks.","P2","contract_gap"
22
22
  "Agent summary","rp-ux-agent-summary-product-wiring-uses-contract","As an agent consuming real Riddle Proof output, the emitted summary uses the shared contract rather than raw fields.","Agent-facing summaries import/use the public-state consumer helper for status, handoff, and prohibited claims.","agent-facing summary","manual-review","summary text; contract import or documented gap; negative-control packet","needs_product_hook","","","Package helper is now contract-tested; product wiring still needs an executable consumer check outside PR comments.","Find the actual agent summary renderer/emitter and wire or verify summarizeRiddleProofAgentSummarySurface usage.","P1","contract_gap"
23
23
  "Neutral fixture","rp-ux-neutral-fixture-public-state-blockers","As a consumer of Riddle Proof summaries, I can validate status semantics on neutral packets rather than Riddle docs packets.","Neutral public-state fixtures cover passed handoff, product_regression, proof_insufficient, environment_blocked, and checkpoint audit claims.","neutral public-state fixtures","runtime-test","fixture JSON; hosted proof view helper; agent summary helper","passed","2026-06-22","packages/riddle-proof/story-matrix.test.js","Neutral packet fixtures keep public-state semantics separate from Riddle docs dogfood.","Keep this as the fast semantic canary before local, hosted, docs, and real-app sweeps.","P1","contract_gap"
24
- "Neutral fixture","rp-ux-neutral-fixture-local-pass","As a maintainer, I can run a non-Riddle static fixture page locally and get a normal evidence packet.","Local Playwright pass profile returns passed with proof JSON, console, DOM summary, artifact manifest, and screenshots.","neutral fixture browser profile","local-playwright","profile-result.json; artifact-manifest.json; screenshot; proof.json","passed","2026-06-22","docs/riddle-proof-story-matrix-runs/2026-06-22-neutral-fixture-batch.md","Neutral static fixture produced a passed local evidence packet across phone and desktop.","Keep as the clean non-docs local canary before real-app sweeps.","P1","configuration_error"
25
- "Neutral fixture","rp-ux-neutral-fixture-negative-control","As a maintainer, I can run a non-Riddle negative-control profile and get product_regression instead of a false pass.","Local Playwright negative-control profile fails only the deliberate missing selector and preserves review artifacts.","neutral fixture browser profile","local-playwright","profile-result.json; failed check; screenshot; proof.json","product_regression_expected","2026-06-22","docs/riddle-proof-story-matrix-runs/2026-06-22-neutral-fixture-batch.md","Neutral negative control stayed red on [data-rp-fixture=""missing-required-control""] while preserving artifacts.","Keep paired with the pass fixture before broader UX sweeps.","P1","contract_gap"
26
- "Neutral fixture","rp-ux-neutral-fixture-hosted-pass","As a maintainer, I can run a non-Riddle static fixture preview on hosted Riddle and get a normal evidence packet.","Hosted pass profile returns passed with hosted job id, proof JSON, console, DOM summary, and screenshots.","neutral fixture hosted profile","hosted-riddle","profile-result.json; riddle.job_id; screenshot URLs; proof.json","passed","2026-06-22","docs/riddle-proof-story-matrix-runs/2026-06-22-neutral-fixture-batch.md","Hosted neutral pass produced job_2ab0f3f3 after fixture artifact requirements were calibrated.","Keep as the clean hosted canary before docs dogfood and real-app sweeps.","P1","environment_blocked"
27
- "Neutral fixture","rp-ux-neutral-fixture-hosted-negative-control","As a maintainer, I can run a non-Riddle hosted negative-control profile and get product_regression instead of a false pass.","Hosted negative-control profile reaches the static preview and fails only the deliberate missing selector.","neutral fixture hosted profile","hosted-riddle","profile-result.json; failed check; screenshot URLs; proof.json","product_regression_expected","2026-06-22","docs/riddle-proof-story-matrix-runs/2026-06-22-neutral-fixture-batch.md","Hosted neutral negative control produced job_b308bc57 with product_regression and preserved artifact URLs.","Keep paired with the hosted pass fixture before broader hosted UX sweeps.","P1","contract_gap"
24
+ "Neutral fixture","rp-ux-neutral-fixture-local-pass","As a maintainer, I can run a non-Riddle static fixture page locally and get a normal evidence packet.","Local Playwright pass profile returns passed with proof JSON, console, DOM summary, artifact manifest, and screenshots.","neutral fixture browser profile","local-playwright","profile-result.json; artifact-manifest.json; screenshot; proof.json","passed","2026-06-22","docs/riddle-proof-story-matrix-runs/2026-06-22-auth-session-smoke.md","Neutral static fixture still produced a passed local evidence packet across phone and desktop after auth fixture changes.","Keep as the clean non-docs local canary before real-app sweeps.","P1","configuration_error"
25
+ "Neutral fixture","rp-ux-neutral-fixture-negative-control","As a maintainer, I can run a non-Riddle negative-control profile and get product_regression instead of a false pass.","Local Playwright negative-control profile fails only the deliberate missing selector and preserves review artifacts.","neutral fixture browser profile","local-playwright","profile-result.json; failed check; screenshot; proof.json","product_regression_expected","2026-06-22","docs/riddle-proof-story-matrix-runs/2026-06-22-auth-session-smoke.md","Neutral negative control still stayed red on [data-rp-fixture=""missing-required-control""] while preserving artifacts.","Keep paired with the pass fixture before broader UX sweeps.","P1","contract_gap"
26
+ "Neutral fixture","rp-ux-neutral-fixture-hosted-pass","As a maintainer, I can run a non-Riddle static fixture preview on hosted Riddle and get a normal evidence packet.","Hosted pass profile returns passed with hosted job id, proof JSON, console, DOM summary, and screenshots.","neutral fixture hosted profile","hosted-riddle","profile-result.json; riddle.job_id; screenshot URLs; proof.json","passed","2026-06-22","job_3867a928; docs/riddle-proof-story-matrix-runs/2026-06-22-auth-session-smoke.md","Hosted neutral pass produced job_3867a928 after auth fixture changes.","Keep as the clean hosted canary before docs dogfood and real-app sweeps.","P1","environment_blocked"
27
+ "Neutral fixture","rp-ux-neutral-fixture-hosted-negative-control","As a maintainer, I can run a non-Riddle hosted negative-control profile and get product_regression instead of a false pass.","Hosted negative-control profile reaches the static preview and fails only the deliberate missing selector.","neutral fixture hosted profile","hosted-riddle","profile-result.json; failed check; screenshot URLs; proof.json","product_regression_expected","2026-06-22","job_552de3af; docs/riddle-proof-story-matrix-runs/2026-06-22-auth-session-smoke.md","Hosted neutral negative control produced job_552de3af with product_regression and preserved artifact URLs.","Keep paired with the hosted pass fixture before broader hosted UX sweeps.","P1","contract_gap"
28
+ "Neutral fixture","rp-story-neutral-fixture-auth-session-smoke","As a maintainer, I can run a non-Riddle profile that supplies stored auth/session state before checks execute.","Auth/session profile writes localStorage, reloads the page, reaches the authenticated fixture state, and preserves artifacts.","neutral fixture auth/session profile","hosted-riddle","profile-result.json; setup_actions_succeeded local_storage receipt; screenshot; proof.json","passed","2026-06-22","job_1daf11b4; docs/riddle-proof-story-matrix-runs/2026-06-22-auth-session-smoke.md","Local and hosted auth/session smoke passed; profile-authoring note added for setup-action readiness ordering.","Keep this next to neutral pass and negative controls before real authenticated product sweeps.","P1","environment_blocked"
28
29
  "Release and publish","rp-ux-release-publish-flow","As a package maintainer, I can merge a fix, get a version PR, and publish the package without manual status fakery.","Changeset release PR validates, merges, and trusted npm publish updates latest.","changesets release","github-actions","release PR; Release workflow; npm view latest","passed","2026-06-21","@riddledc/riddle-proof@0.8.68","Release path worked for the reporting fix and published with provenance.","Keep GitHub Action noise low and use this as release smoke.","P2","environment_blocked"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.8.72",
3
+ "version": "0.8.73",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",