ccqa 1.57.3 → 1.58.1

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
@@ -15464,7 +15464,7 @@ const JUDGE_CALL = "judgeByLlm";
15464
15464
  * would notice.
15465
15465
  */
15466
15466
  function headerPreserveRule(header, titleSuffix) {
15467
- const parts = [header ? `the comment block at the top of the draft, verbatim` : "", titleSuffix ? `the \`${titleSuffix.trim()}\` suffix on the test's name` : ""].filter(Boolean);
15467
+ const parts = [header ? `the comment block right below the draft's imports, verbatim` : "", titleSuffix ? `the \`${titleSuffix.trim()}\` suffix on the test's name` : ""].filter(Boolean);
15468
15468
  return `**Keep ${parts.join(" and ")}.** Written from the case's own record, not decided per test; do not reword, move, or drop ${parts.length > 1 ? "either" : "it"}.`;
15469
15469
  }
15470
15470
  /**
@@ -15554,11 +15554,11 @@ function emitPlaywrightDraft(input) {
15554
15554
  ] : []
15555
15555
  ];
15556
15556
  const source = [
15557
- ...input.header ? [input.header.trimEnd(), ""] : [],
15558
15557
  `import { test, expect } from "@playwright/test";`,
15559
15558
  ...judgements.length > 0 ? [`import { ${JUDGE_CALL} } from ${j(JUDGE_MODULE)};`] : [],
15560
15559
  ...runId ? [runId.import] : [],
15561
15560
  "",
15561
+ ...input.header ? [input.header.trimEnd(), ""] : [],
15562
15562
  ...declaration,
15563
15563
  ""
15564
15564
  ].join("\n");
@@ -16208,7 +16208,7 @@ function injectedCallGaps(corpus, { markers, judgements, header, titleSuffix })
16208
16208
  warnings.push(`step ${stepId}: the generated test no longer opens that step with the \`test.step\` title the draft wrote. The evidence table, the run's screenshots and the spec review read it back to attribute assertions, so a reshaped one makes all three report the step as deciding nothing. Keep the title unchanged.`);
16209
16209
  }
16210
16210
  const firstHeaderLine = stamped.header.split("\n")[0]?.trim() ?? "";
16211
- if (firstHeaderLine && !corpus.includes(firstHeaderLine)) warnings.push("the generated test no longer opens with the configured header — a rewrite pass dropped it, so the file does not say which case it came from");
16211
+ if (firstHeaderLine && !corpus.includes(firstHeaderLine)) warnings.push("the generated test no longer carries the configured header — a rewrite pass dropped it, so the file does not say which case it came from");
16212
16212
  if (stamped.titleSuffix && !corpus.includes(stamped.titleSuffix.trim())) warnings.push(`the generated test's name no longer ends with "${stamped.titleSuffix.trim()}" — a rewrite pass dropped the tag, and whatever selects tests by it will skip this one`);
16213
16213
  for (const { step } of judgements) {
16214
16214
  if (judgeCall(step).pattern.test(corpus)) continue;
@@ -17910,8 +17910,9 @@ const AttestationSchema = z.object({
17910
17910
  const AttestationsSchema = z.object({ specs: z.record(z.string(), AttestationSchema).default({}) });
17911
17911
  /**
17912
17912
  * Why an attestation stopped covering the spec. One reason is named even when
17913
- * several hold, in the order the checks run (coverage, then the spec's own
17914
- * edits, then a later red run) — enough for a reader to see what to verify
17913
+ * several hold, in the order the checks run (a later red that is still the
17914
+ * latest run, then coverage, then the spec's own edits, then a later red since
17915
+ * replaced by a green) — enough for a reader to see what to verify
17915
17916
  * before attesting again.
17916
17917
  */
17917
17918
  const AttestationLapseSchema = z.enum([
@@ -31915,7 +31916,7 @@ function computeRerun(input) {
31915
31916
  const runMoved = specMovedSince(spec.changedAt, coords.lastRun?.deployedSha ?? null, coords.lastRun?.at ?? "", deployTimes);
31916
31917
  if (auditMoved && audit.audit !== "due") audit = { audit: "due" };
31917
31918
  if (runMoved && execution.execution === "passed") execution = { execution: "stale" };
31918
- const manualState = readAttestation(attestations.specs[spec.key], spec, coords.lastRed, range, log, deployTimes);
31919
+ const manualState = readAttestation(attestations.specs[spec.key], spec, coords, range, log, deployTimes);
31919
31920
  const lapsedOverRed = manualState?.kind === "lapsed" && manualState.because !== "newerRed";
31920
31921
  if (execution.execution === "failed" && lapsedOverRed) execution = { execution: "stale" };
31921
31922
  const held = heldBy(locks, spec.key, now);
@@ -31946,18 +31947,24 @@ function computeRerun(input) {
31946
31947
  return out;
31947
31948
  }
31948
31949
  /**
31949
- * Does the attestation still speak for what is deployed? Checked in the order
31950
- * the lapse enum documents: deploy coverage first (a sha the log cannot place
31951
- * reads as reached, ADR-0014, with the hole kept as an annotation), then the
31952
- * spec's own edits — compared against when the person looked, because they
31953
- * read the spec as it stood that moment, which `specMovedSince` covers via a
31954
- * null baseline sha — then a red run recorded after them, which is newer
31955
- * information than their word. The null-sha case is the profile that had no
31956
- * deploy log when they checked: their word covers exactly as long as that
31957
- * stays true.
31950
+ * Does the attestation still speak for what is deployed? A red run recorded
31951
+ * after the person looked and still the latest run is checked first, since it
31952
+ * alone keeps the spec parked (see the caller). Then deploy coverage (a sha the
31953
+ * log cannot place reads as reached, ADR-0014, with the hole kept as an
31954
+ * annotation), then the spec's own edits — compared against when the person
31955
+ * looked, because they read the spec as it stood that moment, which
31956
+ * `specMovedSince` covers via a null baseline sha — then a later red a green
31957
+ * run has since replaced. The null-sha case is the profile that had no deploy
31958
+ * log when they checked: their word covers exactly as long as that stays true.
31958
31959
  */
31959
- function readAttestation(attest, spec, lastRed, range, log, deployTimes) {
31960
+ function readAttestation(attest, spec, { lastRun, lastRed }, range, log, deployTimes) {
31960
31961
  if (!attest) return null;
31962
+ const newerRed = lastRed !== null && lastRed.at > attest.at;
31963
+ if (newerRed && lastRed.runId === lastRun?.runId) return {
31964
+ kind: "lapsed",
31965
+ attest,
31966
+ because: "newerRed"
31967
+ };
31961
31968
  const coverage = attest.deployedSha === null ? log.entries.length === 0 ? { kind: "current" } : {
31962
31969
  kind: "unanswerable",
31963
31970
  reason: "unknownDeployedSha"
@@ -31979,7 +31986,7 @@ function readAttestation(attest, spec, lastRed, range, log, deployTimes) {
31979
31986
  attest,
31980
31987
  because: "specEdited"
31981
31988
  };
31982
- if (lastRed !== null && lastRed.at > attest.at) return {
31989
+ if (newerRed) return {
31983
31990
  kind: "lapsed",
31984
31991
  attest,
31985
31992
  because: "newerRed"
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccqa",
3
- "version": "1.57.3",
3
+ "version": "1.58.1",
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.57.3",
3
+ "version": "1.58.1",
4
4
  "type": "module",
5
5
  "description": "Browser test recorder powered by Claude Code and agent-browser",
6
6
  "repository": {