ccqa 1.35.1 → 1.36.0

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/dist/bin/ccqa.mjs CHANGED
@@ -19419,9 +19419,11 @@ function computeRerun(input) {
19419
19419
  const runMoved = specMovedSince(spec.changedAt, coords.lastRun?.deployedSha ?? null, coords.lastRun?.at ?? "", deployTimes);
19420
19420
  if (auditMoved && audit.audit !== "due") audit = { audit: "due" };
19421
19421
  if (runMoved && execution.execution === "passed") execution = { execution: "stale" };
19422
+ const manualState = readAttestation(attestations.specs[spec.key], spec, coords.lastRed, range, log, deployTimes);
19423
+ const lapsedOverRed = manualState?.kind === "lapsed" && manualState.because !== "newerRed";
19424
+ if (execution.execution === "failed" && lapsedOverRed) execution = { execution: "stale" };
19422
19425
  const held = heldBy(locks, spec.key, now);
19423
19426
  let verdict = decide(audit.audit, execution.execution, held);
19424
- const manualState = readAttestation(attestations.specs[spec.key], spec, coords.lastRed, range, log, deployTimes);
19425
19427
  if (manualState?.kind === "covers" && !held && verdict !== "verified") verdict = "manuallyVerified";
19426
19428
  out[spec.key] = {
19427
19429
  verdict,
@@ -19530,8 +19532,10 @@ function auditState(drift, key, range) {
19530
19532
  * buckets advance from the same terminal-run trigger, so the run that wrote
19531
19533
  * `run` wrote exactly one of `green` or `red`.
19532
19534
  *
19533
- * `failed` outranks `stale`: a red result is current information whatever has
19534
- * deployed since, and re-running it teaches nothing until someone repairs it.
19535
+ * `failed` outranks `stale` here: a red result is current information whatever
19536
+ * has deployed since, and re-running it teaches nothing until someone repairs
19537
+ * it. Its caller retires a red a lapsed attestation already answered
19538
+ * (ADR-0020) — this function does not know about attestations.
19535
19539
  */
19536
19540
  function executionState(coords, since) {
19537
19541
  const { lastRun, lastRed } = coords;
@@ -24015,6 +24019,13 @@ const CLIENT_JS = `
24015
24019
  return null;
24016
24020
  }
24017
24021
 
24022
+ // Did the last run end red? Read off the ledger the same way the execution
24023
+ // axis reads it, because a red a lapsed attestation retired ships as stale
24024
+ // and the sites that need the failure itself must still find it (ADR-0020).
24025
+ function lastFailed(rr) {
24026
+ return !!(rr && rr.lastRun && rr.lastRed && rr.lastRed.runId === rr.lastRun.runId);
24027
+ }
24028
+
24018
24029
  // The execution axis as one state. "What did it say last time" and "is that
24019
24030
  // still true" are two faces of one question, so the row answers it once and
24020
24031
  // the detail panel keeps the coordinates.
@@ -24545,7 +24556,9 @@ const CLIENT_JS = `
24545
24556
  }
24546
24557
  // Only once the audit has actually cleared the spec: while it is still
24547
24558
  // due, nobody knows yet whether the environment was the only thing wrong.
24548
- if (rr.audit === "clean" && rr.execution === "failed" && rr.lastRed && rr.lastRed.label === "ENVIRONMENT") {
24559
+ // Read off the ledger, not the axis: an environment red is demoted to
24560
+ // stale so it re-runs (ADR-0020), and the offer has to survive that.
24561
+ if (rr.audit === "clean" && lastFailed(rr) && rr.lastRed.label === "ENVIRONMENT") {
24549
24562
  return buildOverrideOffer("environment", feature, spec);
24550
24563
  }
24551
24564
  return null;
@@ -24585,7 +24598,7 @@ const CLIENT_JS = `
24585
24598
  // report loads — and the whole content if it never arrives.
24586
24599
  function reasonFindingSource(rr, driftEntry) {
24587
24600
  if (auditOpen(rr) && driftEntry && driftEntry.runId && driftEntry.label) return driftEntry;
24588
- if (rr.execution === "failed" && rr.lastRed && rr.lastRed.runId && rr.lastRed.label) return rr.lastRed;
24601
+ if (lastFailed(rr) && rr.lastRed.runId && rr.lastRed.label) return rr.lastRed;
24589
24602
  return null;
24590
24603
  }
24591
24604
 
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccqa",
3
- "version": "1.35.1",
3
+ "version": "1.36.0",
4
4
  "type": "module",
5
5
  "description": "Browser test recorder powered by Claude Code and agent-browser",
6
6
  "repository": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccqa",
3
- "version": "1.35.1",
3
+ "version": "1.36.0",
4
4
  "type": "module",
5
5
  "description": "Browser test recorder powered by Claude Code and agent-browser",
6
6
  "repository": {