clearotron 0.3.3-beta.0 → 0.3.3
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/bin/onboard.mjs +80 -6
- package/build-info.json +2 -2
- package/docs/architecture/04-configuration-reference.md +28 -10
- package/docs/releases/0.3.3.md +52 -0
- package/driver/CHANGELOG.md +56 -0
- package/driver/citation-census.json +3 -3
- package/driver/config-inventory.mjs +1 -1
- package/driver/dev-portal.mjs +3 -3
- package/driver/driver.config.mjs +80 -9
- package/driver/engine/CONTRACT.md +3 -2
- package/driver/engine/anthropic-agent.mjs +34 -7
- package/driver/engine/mcp/probe-server.mjs +12 -3
- package/driver/package.json +1 -1
- package/driver/pipeline-knockout.mjs +3 -3
- package/driver/pipeline.mjs +14 -14
- package/driver/plan-run-agreement-verdict.mjs +49 -0
- package/driver/portal-service.mjs +8 -4
- package/driver/progress.mjs +14 -3
- package/driver/publish/index.mjs +1 -1
- package/driver/publish/report-data.mjs +4 -3
- package/driver/reference-score.mjs +10 -2
- package/driver/settle-stamp.mjs +10 -3
- package/driver/status-snapshot.mjs +2 -2
- package/driver/suite-census.json +61 -19
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/lib/brief.mjs +11 -5
- package/mcp-server/package.json +1 -1
- package/package.json +2 -2
- package/portal-ui/package.json +1 -1
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/scripts/e2e.mjs +1 -1
- package/scripts/live-surface-check.mjs +6 -14
- package/scripts/repo-writes.mjs +1 -1
- package/scripts/report-sections-render-check.mjs +7 -3
- package/scripts/score.mjs +7 -1
- package/shared/scroll-settle.mjs +67 -0
|
@@ -639,7 +639,7 @@ export async function knockoutInner(ctx, job, opts = {}) {
|
|
|
639
639
|
// for reconcile-runs' exact liveness test. The stepper and the identity are separate calls now.
|
|
640
640
|
...identitySeed(),
|
|
641
641
|
stepIndex: 0, stepLabel: STEPS[0], stepN: 1, stepTotal: STEPS.length,
|
|
642
|
-
|
|
642
|
+
review: null, url: null, failedStage: null, reason: null, deliveredAt: null,
|
|
643
643
|
// A5/A3: a re-run of a previously-terminal knockout may reopen the state ONLY because the resume
|
|
644
644
|
// guard cleared the sentinel (ctx.stateReset threads that authority); startedAt is no longer
|
|
645
645
|
// seeded anywhere — writeRunStatus backfills it first-write-wins.
|
|
@@ -1092,11 +1092,11 @@ export async function knockoutInner(ctx, job, opts = {}) {
|
|
|
1092
1092
|
const deliveredAt = new Date().toISOString();
|
|
1093
1093
|
// `tier` beside `verdict` — the same band word under the name the clearance lane records it by, so a
|
|
1094
1094
|
// reader of either lane's status finds the rating in one place. `verdict` stays as it was.
|
|
1095
|
-
writeRunStatus(ctx, { state: "delivered",
|
|
1095
|
+
writeRunStatus(ctx, { state: "delivered", tier: overall, statement: published.statement, url: published.url, reports: published.reports.map((r) => ({ mark: r.mark, url: r.url })), deliveredAt, sendPending: true, stepIndex: STEPS.length - 1, stepLabel: STEPS[STEPS.length - 1], stepN: STEPS.length, stepTotal: STEPS.length });
|
|
1096
1096
|
// — the knockout lane's pool copy learns its terminal state the same way,
|
|
1097
1097
|
// for the same reason: publish returns the pool dir, and `state: "delivered"` is decided after it
|
|
1098
1098
|
// returns. Same seam, same best-effort contract, no lane-specific exception to write down.
|
|
1099
|
-
const stamp = writeSettleStamp(published.poolRunDir, { state: "delivered",
|
|
1099
|
+
const stamp = writeSettleStamp(published.poolRunDir, { state: "delivered", tier: overall, deliveredAt, runId: published.runId ?? run.runId, lane: "knockout" });
|
|
1100
1100
|
if (!stamp.written) note(`delivery: settle stamp not written (${stamp.reason})`);
|
|
1101
1101
|
const archived = archive(run);
|
|
1102
1102
|
rollupStatus(run.studioRoot);
|
package/driver/pipeline.mjs
CHANGED
|
@@ -91,7 +91,7 @@ import { deriveScopeFacts } from "./scope-facts.mjs";
|
|
|
91
91
|
import { documentGrowth } from "./gate-metrics.mjs";
|
|
92
92
|
import { editRepairTail, abbrev } from "./repair-contract.mjs";
|
|
93
93
|
import { repairFollowup } from "./repair-composers.mjs";
|
|
94
|
-
import { seedRunStatus, recordTransition, writeRunStatus, rollupStatus, atomicWrite, finalStepFields, terminalRunState } from "./progress.mjs";
|
|
94
|
+
import { seedRunStatus, recordTransition, writeRunStatus, rollupStatus, atomicWrite, finalStepFields, terminalRunState, signoffPatch, readSignoff } from "./progress.mjs";
|
|
95
95
|
import { batchMarkName } from "./mark-name.mjs";
|
|
96
96
|
import { writeOutboxPacket } from "./outbox.mjs";
|
|
97
97
|
import { publishReport, composeEmailHtml, deliverySubject } from "./publish/index.mjs";
|
|
@@ -12603,7 +12603,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
12603
12603
|
: "failed after retries + fallback (the ladder recorded no condition)");
|
|
12604
12604
|
let verdict = firstRef.verdict;
|
|
12605
12605
|
runLog(run.runDir, { event: "verdict", verdict });
|
|
12606
|
-
writeRunStatus(ctx,
|
|
12606
|
+
writeRunStatus(ctx, signoffPatch(verdict));
|
|
12607
12607
|
note(`refutation verdict: ${verdict}`);
|
|
12608
12608
|
// qw/typed-correction-kinds — TELEMETRY ONLY (data first; the corrective-skip decision is a
|
|
12609
12609
|
// separate owner-gated build): partition the review's flagged-correction lines by their
|
|
@@ -12847,7 +12847,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
12847
12847
|
verdict = rc.ok ? (parseVerdict(readFileSync(P.seniorEyeReview, "utf8")) ?? entryVerdict) : entryVerdict;
|
|
12848
12848
|
correctiveRecheckOk = rc.ok === true;
|
|
12849
12849
|
runLog(run.runDir, { event: "verdict-2", verdict });
|
|
12850
|
-
writeRunStatus(ctx,
|
|
12850
|
+
writeRunStatus(ctx, signoffPatch(verdict));
|
|
12851
12851
|
}
|
|
12852
12852
|
// AD-2 A1 — the completion receipt, written ONLY when the cycle finished with a verified recheck:
|
|
12853
12853
|
// a fallen-back recheck kept the entry verdict WITHOUT re-verifying, and cementing that would stop
|
|
@@ -13089,7 +13089,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
13089
13089
|
if (d.clamped) {
|
|
13090
13090
|
runLog(run.runDir, { event: "terminal-guard-clamp", defect: d.record.defect, from: verdict, to: d.verdict });
|
|
13091
13091
|
verdict = d.verdict;
|
|
13092
|
-
writeRunStatus(ctx,
|
|
13092
|
+
writeRunStatus(ctx, signoffPatch(verdict));
|
|
13093
13093
|
}
|
|
13094
13094
|
};
|
|
13095
13095
|
|
|
@@ -13223,7 +13223,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
13223
13223
|
runLog(run.runDir, { event: "coverage-floor-clamp", cause: "forward-actions", from: "CLEAR", to: "CONDITIONAL", legalActions: conditions.length });
|
|
13224
13224
|
note(`deliver-conditional floor: the opinion names ${conditions.length} forward legal action(s) a human must take (${conditions[0].slice(0, 140)}${conditions.length > 1 ? `; +${conditions.length - 1} more` : ""}) — clamping CLEAR→CONDITIONAL (spec 64: the disposition is derived from the findings' named actions).`);
|
|
13225
13225
|
verdict = "CONDITIONAL";
|
|
13226
|
-
writeRunStatus(ctx,
|
|
13226
|
+
writeRunStatus(ctx, signoffPatch(verdict));
|
|
13227
13227
|
} else if (fresh.length) {
|
|
13228
13228
|
runLog(run.runDir, { event: "verdict-conditions-recorded", legalActions: fresh.length });
|
|
13229
13229
|
}
|
|
@@ -13261,7 +13261,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
13261
13261
|
if (droppedConditions.length && verdict === "CLEAR") {
|
|
13262
13262
|
runLog(run.runDir, { event: "coverage-floor-clamp", cause: "dropped-actions", from: "CLEAR", to: "CONDITIONAL", actionsDropped: droppedConditions.length });
|
|
13263
13263
|
verdict = "CONDITIONAL";
|
|
13264
|
-
writeRunStatus(ctx,
|
|
13264
|
+
writeRunStatus(ctx, signoffPatch(verdict));
|
|
13265
13265
|
}
|
|
13266
13266
|
}
|
|
13267
13267
|
} catch (e) { note(`legal-actions floor skipped (${String(e.message).slice(0, 80)}) — never-kill; the predelivery coherence lint is the second net`); }
|
|
@@ -13309,7 +13309,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
13309
13309
|
// re-ask can flip a clamped verdict back to CLEAR, and it must meet this floor again with the
|
|
13310
13310
|
// reason ALREADY recorded. Folding these two into one guard would let the second pass skip on
|
|
13311
13311
|
// the dedup and deliver CLEAR — the precise defect this issue is about.
|
|
13312
|
-
if (clReason && verdict === "CLEAR") { verdict = "CONDITIONAL"; writeRunStatus(ctx,
|
|
13312
|
+
if (clReason && verdict === "CLEAR") { verdict = "CONDITIONAL"; writeRunStatus(ctx, signoffPatch(verdict)); }
|
|
13313
13313
|
}
|
|
13314
13314
|
} catch (e) { note(`common-law downgrade floor skipped (${String(e.message).slice(0, 80)}) — never-kill`); }
|
|
13315
13315
|
if (entryVerdict === "CLEAR") {
|
|
@@ -13403,7 +13403,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
13403
13403
|
// The reason KINDS distinguish coverage/frame/screen-gate/senior-right/register residue for the
|
|
13404
13404
|
// report bound line and the client conditions row (merged — legalActions survives).
|
|
13405
13405
|
clampKinds = { ...clampKinds, coverage: coverageInsufficient || undefined, frame: frameResidual || undefined, screenGate: screenGateGap || undefined, seniorRight: seniorGap || undefined, registerGap: registerGap || undefined, deadlineCarry: deadlineGap || undefined };
|
|
13406
|
-
writeRunStatus(ctx,
|
|
13406
|
+
writeRunStatus(ctx, signoffPatch(verdict));
|
|
13407
13407
|
}
|
|
13408
13408
|
}
|
|
13409
13409
|
};
|
|
@@ -13591,7 +13591,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
13591
13591
|
if (rr.ok) {
|
|
13592
13592
|
verdict = parseVerdict(readReview()) ?? "BLOCKING";
|
|
13593
13593
|
runLog(run.runDir, { event: "verdict-3", verdict, trigger: "degenerate-reask" });
|
|
13594
|
-
writeRunStatus(ctx,
|
|
13594
|
+
writeRunStatus(ctx, signoffPatch(verdict));
|
|
13595
13595
|
applyCoverageFloor(); // a re-asked CLEAR passes the same deliver-conditional floor
|
|
13596
13596
|
try { writeVerdictSidecar(); }
|
|
13597
13597
|
catch (e) { throw new StageFailure("verdict", `verdict sidecar write failed (the single label authority): ${String(e.message).slice(0, 120)}`); }
|
|
@@ -14616,7 +14616,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
14616
14616
|
applyCoverageFloor();
|
|
14617
14617
|
try { writeVerdictSidecar(); }
|
|
14618
14618
|
catch (e) { throw new StageFailure("verdict", `verdict sidecar re-derive failed (spec-64 coherence repair): ${String(e.message).slice(0, 120)}`); }
|
|
14619
|
-
if (verdict !== beforeVerdict) writeRunStatus(ctx,
|
|
14619
|
+
if (verdict !== beforeVerdict) writeRunStatus(ctx, signoffPatch(verdict));
|
|
14620
14620
|
runLog(run.runDir, { event: "verdict-rederive-repair", from: beforeVerdict, to: verdict });
|
|
14621
14621
|
lint = lintNow();
|
|
14622
14622
|
}
|
|
@@ -14902,7 +14902,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
14902
14902
|
runLog(run.runDir, { event: "verdict-hardened-by-repair", was: verdict, now: hardened, stage: s2.label, adopted: true });
|
|
14903
14903
|
note(`stale-repair: the reviewer returned ${hardened} — adopting it as the run's verdict (the one settled earlier was decided against a review this repair has since rewritten) and rebuilding the label from it`);
|
|
14904
14904
|
verdict = hardened;
|
|
14905
|
-
writeRunStatus(ctx,
|
|
14905
|
+
writeRunStatus(ctx, signoffPatch(verdict));
|
|
14906
14906
|
try { writeVerdictSidecar(); }
|
|
14907
14907
|
catch (e) { throw new StageFailure("verdict", `verdict sidecar write failed (the single label authority): ${String(e.message).slice(0, 120)}`); }
|
|
14908
14908
|
reassemble = true;
|
|
@@ -15468,13 +15468,13 @@ async function pipelineInner(job, opts = {}) {
|
|
|
15468
15468
|
// .published + .delivered on disk must never read "7/9" on any status surface (nothing runs after
|
|
15469
15469
|
// the packet, so no stage transition would ever finish the display sequence). finalStepFields ⇒ 9/9.
|
|
15470
15470
|
const deliveredAt = new Date().toISOString();
|
|
15471
|
-
writeRunStatus(ctx, { state: "delivered", verdict, statement: emailVerdictOpts.statement ?? undefined, caption: published.caption ?? undefined, url: published.url, deliveredAt, sendPending: true, ...finalStepFields() });
|
|
15471
|
+
writeRunStatus(ctx, { state: "delivered", ...signoffPatch(verdict), statement: emailVerdictOpts.statement ?? undefined, caption: published.caption ?? undefined, url: published.url, deliveredAt, sendPending: true, ...finalStepFields() });
|
|
15472
15472
|
// — THE POOL COPY LEARNS ITS OWN TERMINAL STATE, HERE AND NOWHERE ELSE.
|
|
15473
15473
|
// `meta.json` cannot carry this: it is composed inside publish, before this line runs, so the state
|
|
15474
15474
|
// did not exist yet when it was written. This is the one moment where the terminal state and the
|
|
15475
15475
|
// pool directory are both in hand. Best-effort by construction — the report is already published
|
|
15476
15476
|
// and the run is already settled, so a failure to stamp is logged and the delivery proceeds.
|
|
15477
|
-
const stamp = writeSettleStamp(published.poolRunDir, { state: "delivered", verdict, deliveredAt, runId: published.runId ?? run.runId, lane: "clearance" });
|
|
15477
|
+
const stamp = writeSettleStamp(published.poolRunDir, { state: "delivered", signoff: verdict, deliveredAt, runId: published.runId ?? run.runId, lane: "clearance" });
|
|
15478
15478
|
if (!stamp.written) note(`delivery: settle stamp not written (${stamp.reason})`);
|
|
15479
15479
|
const archived = archive(run);
|
|
15480
15480
|
rollupStatus(run.studioRoot);
|
|
@@ -16043,7 +16043,7 @@ export function reconstructCtx(job, opts) { // @internal
|
|
|
16043
16043
|
} catch { /* no/corrupt frozen plan — prose axes stand, as they always did */ }
|
|
16044
16044
|
const readJson = (f) => { try { return JSON.parse(readFileSync(join(run.runDir, f), "utf8")); } catch { return null; } };
|
|
16045
16045
|
const status = readJson("status.json");
|
|
16046
|
-
if (status
|
|
16046
|
+
if (readSignoff(status)) ctx.verdict = readSignoff(status); // `review.signoff`, or `verdict` on a record written before the move
|
|
16047
16047
|
const pub = readJson(".published");
|
|
16048
16048
|
if (pub?.url) ctx.publishedUrl = pub.url;
|
|
16049
16049
|
// ── THE CTX FIELDS THIS USED TO DROP (item) ───────────────────────────────────────────────────
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright 2026 Cordillera Sarl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
|
|
3
|
+
//
|
|
4
|
+
// DO describe_options AND plan_run AGREE ON WHICH PRODUCTS ARE AVAILABLE — the deployment check's arm,
|
|
5
|
+
// extracted so it can be driven without a door to call (the reason surface-exit-verdict.mjs gives).
|
|
6
|
+
//
|
|
7
|
+
// A plan_run that THROWS compared nothing. A 429 from the door's rate limit, a timeout, a refused
|
|
8
|
+
// connection: each means the question was never answered, and the check used to file it beside the real
|
|
9
|
+
// disagreements and exit 1, "drifted". Three runs of the check in two minutes exhausted the ops door's
|
|
10
|
+
// rate limit and the third reported a drift that a redeploy could not have fixed. So an unanswered ask is
|
|
11
|
+
// a marked skip, which exits 3, and only an answer that contradicts describe_options is a drift.
|
|
12
|
+
|
|
13
|
+
// The blocker wording plan_run uses for a product it will not run.
|
|
14
|
+
const UNAVAILABLE = /not part of the current release|not switched on|unavailable/i;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Ask plan_run about each product describe_options listed, and say whether the two agree.
|
|
18
|
+
*
|
|
19
|
+
* @param {{ keys: string[], doorSays: Map<string, boolean>, probeProfileKey: string|null,
|
|
20
|
+
* ask: (key: string) => Promise<{blockers?: unknown[]}> }} input
|
|
21
|
+
* `ask` is the plan_run call for one product; a throw is a question that was not answered.
|
|
22
|
+
* @returns {Promise<{state: "pass"|"fail"|"skip", message: string, blocked?: true}>}
|
|
23
|
+
*/
|
|
24
|
+
export async function planRunAgreementVerdict({ keys = [], doorSays = new Map(), probeProfileKey = null, ask }) {
|
|
25
|
+
if (!probeProfileKey) {
|
|
26
|
+
return { state: "skip", message: "no customer resolved to plan against — see the roster check" };
|
|
27
|
+
}
|
|
28
|
+
const disagreements = [];
|
|
29
|
+
const unanswered = [];
|
|
30
|
+
for (const key of keys) {
|
|
31
|
+
let plan;
|
|
32
|
+
try { plan = await ask(key); } catch (e) { unanswered.push(`${key}: ${String(e?.message ?? e).slice(0, 120)}`); continue; }
|
|
33
|
+
const unavailable = (plan?.blockers ?? []).some((b) => UNAVAILABLE.test(String(b)));
|
|
34
|
+
if (unavailable !== !doorSays.get(key)) {
|
|
35
|
+
disagreements.push(`${key}: describe_options=${doorSays.get(key) ? "available" : "unavailable"} plan_run=${unavailable ? "unavailable" : "available"}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// A drift outranks an unanswered ask, as in exitFor: the drift is actionable now. The unanswered
|
|
39
|
+
// products stay on the line so the report does not read as though they were compared.
|
|
40
|
+
if (disagreements.length) {
|
|
41
|
+
return { state: "fail", message: disagreements.join(" · ")
|
|
42
|
+
+ (unanswered.length ? ` · and plan_run gave no answer for ${unanswered.length}: ${unanswered.join(" · ")}` : "") };
|
|
43
|
+
}
|
|
44
|
+
if (unanswered.length) {
|
|
45
|
+
return { state: "skip", blocked: true, message: `could not ask plan_run about ${unanswered.length} of ${keys.length} product(s), `
|
|
46
|
+
+ `so those were not compared — ${unanswered.join(" · ")}` };
|
|
47
|
+
}
|
|
48
|
+
return { state: "pass", message: `${keys.length} products checked through both code paths` };
|
|
49
|
+
}
|
|
@@ -350,7 +350,7 @@ export function scanAccountRuns({ poolRoot, workspaceRoot, account = null, gener
|
|
|
350
350
|
const docs = reportsOf(meta).filter((r) => existsSync(join(poolRoot, name, r.file)));
|
|
351
351
|
const hasReport = docs.length > 0;
|
|
352
352
|
const { bands, toneFor } = ladderOf(meta);
|
|
353
|
-
const band = meta.overall ?? meta
|
|
353
|
+
const band = meta.overall ?? null; // the rating; a meta's retired `verdict` held the reviewer's sign-off on the full-search lane
|
|
354
354
|
out.push({ runId: meta.runId ?? name, account: owner, ...(owner === "generic" ? { organisation: meta.organisation ?? null } : {}),
|
|
355
355
|
title: meta.title ?? meta.matter ?? name, kind: meta.kind ?? "clearance",
|
|
356
356
|
// THE MARK, separate from the report's headline.
|
|
@@ -540,7 +540,7 @@ export function scanAccountRuns({ poolRoot, workspaceRoot, account = null, gener
|
|
|
540
540
|
// hide this. Staff only: the client redaction below replaces `reason` and must drop this too,
|
|
541
541
|
// or the redaction would be defeated by the field that carries the raw words.
|
|
542
542
|
reasonDetail: s.reasonDetail ?? null,
|
|
543
|
-
date: (s.updatedAt ?? "").slice(0, 10), overall: s.
|
|
543
|
+
date: (s.updatedAt ?? "").slice(0, 10), overall: s.tier ?? null, // the rating, never the reviewer's sign-off word
|
|
544
544
|
// A live run has not been issued, so its last progress write is the honest ordering key — the
|
|
545
545
|
// same role issuedAt plays for a delivered one, never presented as a finish time.
|
|
546
546
|
issuedAt: typeof s.updatedAt === "string" ? s.updatedAt : null,
|
|
@@ -4006,7 +4006,7 @@ ${signedIn
|
|
|
4006
4006
|
<div><a href="/portal">Go to the portal</a></div>
|
|
4007
4007
|
<form method="post" action="/portal/logout"><button type="submit">Sign out</button></form>`
|
|
4008
4008
|
: `<p>This ${escHtml(BRAND.name)} has one user: <b class="who">${escHtml(email)}</b>. Enter its passphrase.</p>
|
|
4009
|
-
${discarded ? `<p class="hint">
|
|
4009
|
+
${discarded ? `<p class="hint">Your earlier sign-in has expired. Sign in again.</p>` : ""}
|
|
4010
4010
|
${error ? `<p class="err">${escHtml(error)}</p>` : ""}
|
|
4011
4011
|
<form method="post" action="/portal/login">
|
|
4012
4012
|
<label for="passphrase">Passphrase</label>
|
|
@@ -4130,6 +4130,10 @@ async function readFormBody(req, limitBytes = 8192) {
|
|
|
4130
4130
|
});
|
|
4131
4131
|
}
|
|
4132
4132
|
|
|
4133
|
+
// The brief reader's model when PORTAL_READ_MODEL is unset: a TIER, like every stage's. An exact id goes to
|
|
4134
|
+
// the program as that model — past a cloud's ANTHROPIC_DEFAULT_SONNET_MODEL — and codex maps tiers only.
|
|
4135
|
+
export const PORTAL_READ_MODEL_DEFAULT = "sonnet";
|
|
4136
|
+
|
|
4133
4137
|
export function makeHttpHandler({ verify, limiter, service, log = () => {}, devIdentity = null, localAuth = null, static: staticHandler = null,
|
|
4134
4138
|
// item 1 — PASSED IN, because this handler is its own function and the bootstrap that reads
|
|
4135
4139
|
// the environment is another. The default is the Cloudflare Access header, so a caller that does
|
|
@@ -5211,7 +5215,7 @@ const PORT = PORT_CHOICE.port;
|
|
|
5211
5215
|
// two are parameters on the shared runner for exactly this reason: `compose-read.mjs` records that
|
|
5212
5216
|
// Haiku 4.5 refuses a thinking block outright (400), so inheriting the jx constants here would
|
|
5213
5217
|
// have been a failure on every press.
|
|
5214
|
-
const model = process.env.PORTAL_READ_MODEL ||
|
|
5218
|
+
const model = process.env.PORTAL_READ_MODEL || PORTAL_READ_MODEL_DEFAULT;
|
|
5215
5219
|
const runner = await makeJxTurnRunner({ model, thinking: "off", lane: "the brief reader" });
|
|
5216
5220
|
if (runner?.error) {
|
|
5217
5221
|
// NAMES THE CONDITION, on the operator's surface. The client-facing note stays client-facing;
|
package/driver/progress.mjs
CHANGED
|
@@ -194,6 +194,16 @@ const TERMINAL_STATES = new Set(["delivered", "failed", "cancelled"]);
|
|
|
194
194
|
* preflight before an unattended run remains the operational guard for that case; this closes the
|
|
195
195
|
* invisibility for every failure short of it, which is the honest claim.
|
|
196
196
|
*/
|
|
197
|
+
// ── THE REVIEWER'S SIGN-OFF IS NOT THE CLEARANCE'S ANSWER (ruled 2026-09-22) ─────────────────────────
|
|
198
|
+
//
|
|
199
|
+
// The narrative-refutation stage signs the draft off CLEAR, CONDITIONAL or BLOCKING. At the top of the run
|
|
200
|
+
// record as `verdict` it read as the clearance's answer, competed with the rating, and a BLOCKING one was
|
|
201
|
+
// printed to clients as "on hold" although nothing holds delivery on it. It now lives under the stage
|
|
202
|
+
// that produced it, named for what it is: `review.signoff`. The rating (`tier`) is the run's headline.
|
|
203
|
+
// A record written before the move carries the old field; `readSignoff` reads either.
|
|
204
|
+
export const signoffPatch = (signoff) => ({ review: { signoff: signoff ?? null } });
|
|
205
|
+
export const readSignoff = (s) => s?.review?.signoff ?? s?.verdict ?? null;
|
|
206
|
+
|
|
197
207
|
export function writeRunStatus(ctx, patch = {}, runDirOverride = null, { critical = false } = {}) {
|
|
198
208
|
const runDir = runDirOverride ?? ctx?.run?.runDir;
|
|
199
209
|
// — A STATE WRITE THAT CANNOT FIND ITS RUN DIRECTORY SAYS SO. It used to `return` here, in
|
|
@@ -222,6 +232,7 @@ export function writeRunStatus(ctx, patch = {}, runDirOverride = null, { critica
|
|
|
222
232
|
const { __stateReset, ...rest } = patch;
|
|
223
233
|
const old = readRunStatus(runDir);
|
|
224
234
|
const merged = { ...old, ...rest, updatedAt: nowISO() };
|
|
235
|
+
delete merged.verdict; // the retired top-level field: a record rewritten here carries `review.signoff` alone
|
|
225
236
|
if (typeof rest.stepIndex === "number" && typeof old.stepIndex === "number" && old.stepIndex > rest.stepIndex) {
|
|
226
237
|
// keep the furthest step ever reached (label/n/total move together with the index)
|
|
227
238
|
merged.stepIndex = old.stepIndex;
|
|
@@ -378,7 +389,7 @@ export function identitySeed() {
|
|
|
378
389
|
// first-write-wins makes it the honest wall-clock start across any number of resumes. A resume instead
|
|
379
390
|
// records itself: resumedAt (this resume's clock) + attempts (fresh run = 1, each resume +1), and
|
|
380
391
|
// threads __stateReset because the resume guard has deliberately cleared a terminal sentinel. The
|
|
381
|
-
//
|
|
392
|
+
// review/failedStage/reason resets stay (a resumed run owes a fresh outcome);
|
|
382
393
|
// recoveryAttempts/recoveryHistory stay OUT of the seed (they are the park budget's memory).
|
|
383
394
|
export function seedRunStatus(ctx, { resume = false } = {}) {
|
|
384
395
|
const { job, run, agent } = ctx;
|
|
@@ -412,7 +423,7 @@ export function seedRunStatus(ctx, { resume = false } = {}) {
|
|
|
412
423
|
stepIndex: first.index, stepLabel: first.label, stepN: first.n, stepTotal: first.total,
|
|
413
424
|
currentStep: currentStepOf(first),
|
|
414
425
|
lastStage: null,
|
|
415
|
-
|
|
426
|
+
review: null,
|
|
416
427
|
url: null,
|
|
417
428
|
failedStage: null,
|
|
418
429
|
reason: null,
|
|
@@ -489,7 +500,7 @@ export function lineFor(s) {
|
|
|
489
500
|
// The rollup now carries the send state loudly; clearotron-deliver flips sendPending:false on send.
|
|
490
501
|
const pending = s.sendPending === true ? " — 📮 SEND PENDING (email/WhatsApp NOT yet out — run clearotron-deliver)" : "";
|
|
491
502
|
if (s.state === "delivered") {
|
|
492
|
-
const v = s.
|
|
503
|
+
const v = s.tier ? ` (${s.tier})` : ""; // the rating, not the reviewer's sign-off word
|
|
493
504
|
return `- ${head} — delivered${v}${s.url ? ` — ${s.url}` : ""}${pending}`;
|
|
494
505
|
}
|
|
495
506
|
if (s.state === "failed") {
|
package/driver/publish/index.mjs
CHANGED
|
@@ -1352,7 +1352,7 @@ export async function publishReport({ runId, codename, reportMd, auditMd, findin
|
|
|
1352
1352
|
// null-guard and old rows render byte-identically.
|
|
1353
1353
|
statement: verdictInfo?.statement ?? undefined,
|
|
1354
1354
|
caption: fm.overall_caption || undefined, // the report's own conclusion, which the run list quotes
|
|
1355
|
-
|
|
1355
|
+
review: verdictInfo?.verdict ? { signoff: verdictInfo.verdict } : undefined, // the reviewer's sign-off, not the clearance's answer (ruled 2026-09-22)
|
|
1356
1356
|
// doc 50 — which framework rated this run (custom vs Generic default) + its ladder, for the archive
|
|
1357
1357
|
// card, the email table sort/colour and the per-customer index; absent on archived runs forever.
|
|
1358
1358
|
framework: framework ? { key: framework.framework_key, title: framework.title,
|
|
@@ -98,9 +98,10 @@ export function clearanceReportData({
|
|
|
98
98
|
auditFile: auditFile || null,
|
|
99
99
|
level: { searchLevel: searchLevel ?? null, stageLabel: stageLabel ?? null },
|
|
100
100
|
framework: framework ? { key: framework.framework_key, title: framework.title, bands: framework.bands.map((b) => ({ label: b.label, tone: b.tone })) } : null,
|
|
101
|
-
// The one risk statement
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
// The rating + the one risk statement — the exact record every other surface joins (spec 64). Named
|
|
102
|
+
// `rating` (ruled 2026-09-22): as `verdict` it read as the clearance's answer and carried the reviewer's
|
|
103
|
+
// sign-off word beside the band. The sign-off stays in the review stage's own record, not the client's.
|
|
104
|
+
rating: verdictInfo ? {
|
|
104
105
|
tier: verdictInfo.tier ?? null,
|
|
105
106
|
badge: verdictInfo.badge ?? null,
|
|
106
107
|
band: verdictInfo.band ?? null,
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
import { normalizeElement, consonantSkeleton } from "./form-neighbourhood.mjs";
|
|
47
47
|
import { canonicalJurisdictionCode } from "./jurisdiction-codes.mjs";
|
|
48
|
+
import { territoryTier } from "./territory-tiers.mjs";
|
|
48
49
|
|
|
49
50
|
export const REFERENCE_SCHEMA_VERSION = 1;
|
|
50
51
|
|
|
@@ -378,6 +379,12 @@ export function inScope(entry, scopeClasses = [], scopeTerritories = []) {
|
|
|
378
379
|
// that scenario it is five of fifteen entries, which is the difference between a bad round and a fine
|
|
379
380
|
// one. Same shape as the class rule: an entry naming no territory is in scope, and a run that recorded
|
|
380
381
|
// no scope cannot exclude anything.
|
|
382
|
+
// A WORLDWIDE SCOPE EXCLUDES NOTHING ON TERRITORY, for the reason a missing scope excludes nothing: it
|
|
383
|
+
// names no territory an entry could fall outside. Without this a worldwide run compared every entry
|
|
384
|
+
// with the word itself (`GLOBAL`), no entry names that, and the whole reference landed in `excluded`,
|
|
385
|
+
// an empty score that read as a clean one. Which words mean worldwide is the intake's own list
|
|
386
|
+
// (`territoryTier`), not a pattern restated here; `canonTerritory` still guesses nothing about `intl`.
|
|
387
|
+
if (scopeTerritories.some((t) => territoryTier(t) === "worldwide")) return true;
|
|
381
388
|
const terr = (entry?.jurisdictions ?? []).map(canonTerritory).filter(Boolean);
|
|
382
389
|
const scopeTerr = scopeTerritories.map(canonTerritory).filter(Boolean);
|
|
383
390
|
if (scopeTerr.length && terr.length && !terr.some((t) => scopeTerr.includes(t))) return false;
|
|
@@ -911,7 +918,8 @@ export function readVerdict({ verdictDoc = null, knockoutFindings = null, status
|
|
|
911
918
|
const rows = marks
|
|
912
919
|
.map((m) => [m.name, [m.rating, m.ratingQualifier ? `(${m.ratingQualifier})` : null].filter(Boolean).join(" ")].filter(Boolean).join(": "))
|
|
913
920
|
.filter((s) => s.includes(":"));
|
|
914
|
-
const
|
|
921
|
+
const worst = status?.tier ?? status?.verdict ?? null; // `verdict` on a quick-search record written before the move
|
|
922
|
+
const text = [worst ? `worst band ${worst}` : null, ...rows].filter(Boolean).join(" · ");
|
|
915
923
|
if (text) return { clean: clean(text), text, source: "knockout-findings.json + status.json — this lane writes no _driver/verdict.json", why: null };
|
|
916
924
|
}
|
|
917
925
|
return { clean: null, text: null, source: null,
|
|
@@ -2194,7 +2202,7 @@ export function deliveryLine(run) {
|
|
|
2194
2202
|
}
|
|
2195
2203
|
if (run.poolMeta) {
|
|
2196
2204
|
const issued = run.poolMeta.issuedAt ? ` published ${run.poolMeta.issuedAt}` : " publication time not recorded";
|
|
2197
|
-
const verdict = run.poolMeta.verdict ?? run.poolMeta.overall;
|
|
2205
|
+
const verdict = run.poolMeta.review?.signoff ?? run.poolMeta.verdict ?? run.poolMeta.overall;
|
|
2198
2206
|
// NOT PRESERVED stays the honest answer for a pool copy with no stamp — a run archived before the
|
|
2199
2207
|
// stamp existed, or one whose best-effort write failed. An absent stamp is unknown, not a refusal.
|
|
2200
2208
|
return `delivered: NOT PRESERVED — this is a pool copy carrying no settle stamp, so the terminal`
|
package/driver/settle-stamp.mjs
CHANGED
|
@@ -55,12 +55,15 @@ export const SETTLE_SCHEMA_VERSION = 1;
|
|
|
55
55
|
* reads a delivery date (turnaround, an SLA, a client-facing "delivered on") would have inherited it.
|
|
56
56
|
* A backfiller must not compose this value at all: call `backfillSettleStamp`, which reads it.
|
|
57
57
|
*/
|
|
58
|
-
|
|
58
|
+
// The outcome words are named for what they are: the full-search lane's reviewer `signoff` (CLEAR /
|
|
59
|
+
// CONDITIONAL / BLOCKING) and the quick-search lane's rating `tier`. Both once shared one `verdict` field,
|
|
60
|
+
// which read as the clearance's answer and held a different vocabulary on each lane.
|
|
61
|
+
export function writeSettleStamp(poolRunDir, { state, signoff = null, tier = null, deliveredAt = null, runId = null, lane = null } = {}) {
|
|
59
62
|
if (!poolRunDir) return { written: false, reason: "no pool run directory — the run published nowhere" };
|
|
60
63
|
if (!state) return { written: false, reason: "no terminal state given — a stamp with no state is the absence it would be mistaken for" };
|
|
61
64
|
const path = join(poolRunDir, SETTLE_FILE);
|
|
62
65
|
try {
|
|
63
|
-
writeFileSync(path, `${JSON.stringify({ schema_version: SETTLE_SCHEMA_VERSION, state,
|
|
66
|
+
writeFileSync(path, `${JSON.stringify({ schema_version: SETTLE_SCHEMA_VERSION, state, ...(signoff ? { signoff } : {}), ...(tier ? { tier } : {}), deliveredAt, runId, lane, stampedAt: new Date().toISOString() }, null, 2)}\n`);
|
|
64
67
|
// Group-read like every other pool file. Best-effort on its own: a stamp nobody can chmod is still
|
|
65
68
|
// a stamp, and the set-GID pool already grants the group.
|
|
66
69
|
try { chmodSync(path, 0o640); } catch { /* best-effort, exactly as publish's writeRO does */ }
|
|
@@ -116,7 +119,11 @@ export function backfillSettleStamp(poolRunDir, runDir, { readStatus = defaultRe
|
|
|
116
119
|
return { written: false, reason: "status.json says delivered but carries no deliveredAt — the delivery time this backfill exists to preserve is not recorded" };
|
|
117
120
|
return writeSettleStamp(poolRunDir, {
|
|
118
121
|
state: status.state,
|
|
119
|
-
|
|
122
|
+
// A status.json written before the sign-off moved carries it as `verdict`, and on the quick-search
|
|
123
|
+
// lane that field held the rating; each is read back into the field it always meant.
|
|
124
|
+
...((status.lane ?? (status.marks ? "knockout" : "clearance")) === "knockout"
|
|
125
|
+
? { tier: status.tier ?? status.verdict ?? null }
|
|
126
|
+
: { signoff: status.review?.signoff ?? status.verdict ?? null }),
|
|
120
127
|
deliveredAt: status.deliveredAt ?? null,
|
|
121
128
|
runId: status.runId ?? null,
|
|
122
129
|
lane: status.lane ?? (status.marks ? "knockout" : "clearance"),
|
|
@@ -80,7 +80,7 @@ const slimRun = (r) => ({
|
|
|
80
80
|
markName: r.markName, ref: r.ref, classes: r.classes,
|
|
81
81
|
state: r.state, stepN: r.stepN, stepTotal: r.stepTotal, stepLabel: r.stepLabel,
|
|
82
82
|
lastStage: r.lastStage, // spec 64 C — the RAW stage key ("register-unit:primary-sweep"): what the run is actually doing
|
|
83
|
-
|
|
83
|
+
tier: r.tier, statement: r.statement, caption: r.caption, // the rating, never the reviewer's sign-off; spec 64 — THE one risk statement (absent on legacy runs); caption — the report's own conclusion
|
|
84
84
|
url: r.url, failedStage: r.failedStage, reason: r.reason,
|
|
85
85
|
resetsAt: r.resetsAt, // rate-limit POSTPONE ONLY: when the cap window clears + the run auto-resumes (ISO)
|
|
86
86
|
recoveryResumesAt: r.recoveryResumesAt ?? null, // recovery park's backoff clock (A4 split — never conflated with a provider cap)
|
|
@@ -100,7 +100,7 @@ export function buildRecentActivity({ reports = [], limit = 12 } = {}) {
|
|
|
100
100
|
// spec 64 — a delivered run's outcome is THE one risk statement when the run carries it (band +
|
|
101
101
|
// stance in one sentence), never a bare disposition word beside a severity word on another page.
|
|
102
102
|
out.push({ kind: "report", ok, when: r.deliveredAt || r.updatedAt || r.startedAt || "", label: r.markName || r.slug || r.runId,
|
|
103
|
-
outcome: ok ? (r.statement || r.
|
|
103
|
+
outcome: ok ? (r.caption || r.statement || r.tier || "delivered") : `failed${r.failedStage ? " · " + r.failedStage : ""}`,
|
|
104
104
|
url: r.url || (ok && r.runId ? `${r.runId}/report.html` : "") });
|
|
105
105
|
}
|
|
106
106
|
// ONE explicit time key per row: a report's `when` can come from any of three stamps, and they all sort on
|
package/driver/suite-census.json
CHANGED
|
@@ -621,6 +621,12 @@
|
|
|
621
621
|
"skips": 0,
|
|
622
622
|
"todos": 0
|
|
623
623
|
},
|
|
624
|
+
"a-model-of-the-current-generation-is-named-in-every-spelling.test.mjs": {
|
|
625
|
+
"tests": 4,
|
|
626
|
+
"asserts": 13,
|
|
627
|
+
"skips": 0,
|
|
628
|
+
"todos": 0
|
|
629
|
+
},
|
|
624
630
|
"a-name-documented-in-any-example-file-is-documented.test.mjs": {
|
|
625
631
|
"tests": 7,
|
|
626
632
|
"asserts": 16,
|
|
@@ -711,6 +717,12 @@
|
|
|
711
717
|
"skips": 0,
|
|
712
718
|
"todos": 0
|
|
713
719
|
},
|
|
720
|
+
"a-plan-run-that-was-not-answered-is-not-a-drift.test.mjs": {
|
|
721
|
+
"tests": 5,
|
|
722
|
+
"asserts": 16,
|
|
723
|
+
"skips": 0,
|
|
724
|
+
"todos": 0
|
|
725
|
+
},
|
|
714
726
|
"a-pool-copy-is-not-a-refusal.test.mjs": {
|
|
715
727
|
"tests": 8,
|
|
716
728
|
"asserts": 28,
|
|
@@ -723,12 +735,24 @@
|
|
|
723
735
|
"skips": 0,
|
|
724
736
|
"todos": 0
|
|
725
737
|
},
|
|
738
|
+
"a-press-that-starts-late-is-not-a-page-that-did-not-move.test.mjs": {
|
|
739
|
+
"tests": 5,
|
|
740
|
+
"asserts": 13,
|
|
741
|
+
"skips": 0,
|
|
742
|
+
"todos": 0
|
|
743
|
+
},
|
|
726
744
|
"a-printed-command-runs-from-where-the-reader-stands.test.mjs": {
|
|
727
745
|
"tests": 15,
|
|
728
746
|
"asserts": 62,
|
|
729
747
|
"skips": 0,
|
|
730
748
|
"todos": 0
|
|
731
749
|
},
|
|
750
|
+
"a-program-already-here-is-checked-against-the-floor.test.mjs": {
|
|
751
|
+
"tests": 9,
|
|
752
|
+
"asserts": 38,
|
|
753
|
+
"skips": 1,
|
|
754
|
+
"todos": 0
|
|
755
|
+
},
|
|
732
756
|
"a-project-cannot-break-the-tree-it-joins.test.mjs": {
|
|
733
757
|
"tests": 13,
|
|
734
758
|
"asserts": 37,
|
|
@@ -933,6 +957,12 @@
|
|
|
933
957
|
"skips": 0,
|
|
934
958
|
"todos": 0
|
|
935
959
|
},
|
|
960
|
+
"a-run-records-the-tier-it-asked-for.test.mjs": {
|
|
961
|
+
"tests": 5,
|
|
962
|
+
"asserts": 18,
|
|
963
|
+
"skips": 0,
|
|
964
|
+
"todos": 0
|
|
965
|
+
},
|
|
936
966
|
"a-run-records-the-tool-that-served-it.test.mjs": {
|
|
937
967
|
"tests": 13,
|
|
938
968
|
"asserts": 33,
|
|
@@ -1253,7 +1283,7 @@
|
|
|
1253
1283
|
},
|
|
1254
1284
|
"an-absent-portal-bundle-is-not-a-stale-one.test.mjs": {
|
|
1255
1285
|
"tests": 4,
|
|
1256
|
-
"asserts":
|
|
1286
|
+
"asserts": 13,
|
|
1257
1287
|
"skips": 0,
|
|
1258
1288
|
"todos": 0
|
|
1259
1289
|
},
|
|
@@ -1271,7 +1301,7 @@
|
|
|
1271
1301
|
},
|
|
1272
1302
|
"an-archived-run-says-whether-it-was-delivered.test.mjs": {
|
|
1273
1303
|
"tests": 8,
|
|
1274
|
-
"asserts":
|
|
1304
|
+
"asserts": 44,
|
|
1275
1305
|
"skips": 0,
|
|
1276
1306
|
"todos": 0
|
|
1277
1307
|
},
|
|
@@ -2452,8 +2482,8 @@
|
|
|
2452
2482
|
"todos": 0
|
|
2453
2483
|
},
|
|
2454
2484
|
"engine-probe.test.mjs": {
|
|
2455
|
-
"tests":
|
|
2456
|
-
"asserts":
|
|
2485
|
+
"tests": 35,
|
|
2486
|
+
"asserts": 172,
|
|
2457
2487
|
"skips": 0,
|
|
2458
2488
|
"todos": 0
|
|
2459
2489
|
},
|
|
@@ -2465,7 +2495,7 @@
|
|
|
2465
2495
|
},
|
|
2466
2496
|
"engine.anthropic.test.mjs": {
|
|
2467
2497
|
"tests": 65,
|
|
2468
|
-
"asserts":
|
|
2498
|
+
"asserts": 245,
|
|
2469
2499
|
"skips": 0,
|
|
2470
2500
|
"todos": 0
|
|
2471
2501
|
},
|
|
@@ -3412,8 +3442,8 @@
|
|
|
3412
3442
|
"todos": 0
|
|
3413
3443
|
},
|
|
3414
3444
|
"pipeline.mock.test.mjs": {
|
|
3415
|
-
"tests":
|
|
3416
|
-
"asserts":
|
|
3445
|
+
"tests": 99,
|
|
3446
|
+
"asserts": 827,
|
|
3417
3447
|
"skips": 0,
|
|
3418
3448
|
"todos": 0
|
|
3419
3449
|
},
|
|
@@ -3665,7 +3695,7 @@
|
|
|
3665
3695
|
},
|
|
3666
3696
|
"progress.test.mjs": {
|
|
3667
3697
|
"tests": 26,
|
|
3668
|
-
"asserts":
|
|
3698
|
+
"asserts": 97,
|
|
3669
3699
|
"skips": 0,
|
|
3670
3700
|
"todos": 0
|
|
3671
3701
|
},
|
|
@@ -3880,8 +3910,8 @@
|
|
|
3880
3910
|
"todos": 0
|
|
3881
3911
|
},
|
|
3882
3912
|
"reference-score.test.mjs": {
|
|
3883
|
-
"tests":
|
|
3884
|
-
"asserts":
|
|
3913
|
+
"tests": 65,
|
|
3914
|
+
"asserts": 221,
|
|
3885
3915
|
"skips": 0,
|
|
3886
3916
|
"todos": 0
|
|
3887
3917
|
},
|
|
@@ -4048,8 +4078,8 @@
|
|
|
4048
4078
|
"todos": 0
|
|
4049
4079
|
},
|
|
4050
4080
|
"release-pipeline.test.mjs": {
|
|
4051
|
-
"tests":
|
|
4052
|
-
"asserts":
|
|
4081
|
+
"tests": 121,
|
|
4082
|
+
"asserts": 456,
|
|
4053
4083
|
"skips": 0,
|
|
4054
4084
|
"todos": 0
|
|
4055
4085
|
},
|
|
@@ -4133,7 +4163,7 @@
|
|
|
4133
4163
|
},
|
|
4134
4164
|
"report-data.test.mjs": {
|
|
4135
4165
|
"tests": 5,
|
|
4136
|
-
"asserts":
|
|
4166
|
+
"asserts": 56,
|
|
4137
4167
|
"skips": 0,
|
|
4138
4168
|
"todos": 0
|
|
4139
4169
|
},
|
|
@@ -4715,7 +4745,7 @@
|
|
|
4715
4745
|
},
|
|
4716
4746
|
"status-snapshot.test.mjs": {
|
|
4717
4747
|
"tests": 6,
|
|
4718
|
-
"asserts":
|
|
4748
|
+
"asserts": 40,
|
|
4719
4749
|
"skips": 0,
|
|
4720
4750
|
"todos": 0
|
|
4721
4751
|
},
|
|
@@ -5121,6 +5151,12 @@
|
|
|
5121
5151
|
"skips": 0,
|
|
5122
5152
|
"todos": 0
|
|
5123
5153
|
},
|
|
5154
|
+
"the-engine-floor-can-run-the-current-top-tier.test.mjs": {
|
|
5155
|
+
"tests": 2,
|
|
5156
|
+
"asserts": 5,
|
|
5157
|
+
"skips": 0,
|
|
5158
|
+
"todos": 0
|
|
5159
|
+
},
|
|
5124
5160
|
"the-engine-step-cannot-loop-on-a-menu-nothing-changed.test.mjs": {
|
|
5125
5161
|
"tests": 17,
|
|
5126
5162
|
"asserts": 45,
|
|
@@ -5225,7 +5261,7 @@
|
|
|
5225
5261
|
},
|
|
5226
5262
|
"the-install-pages-describe-the-install-this-build-performs.test.mjs": {
|
|
5227
5263
|
"tests": 11,
|
|
5228
|
-
"asserts":
|
|
5264
|
+
"asserts": 90,
|
|
5229
5265
|
"skips": 0,
|
|
5230
5266
|
"todos": 0
|
|
5231
5267
|
},
|
|
@@ -5374,8 +5410,8 @@
|
|
|
5374
5410
|
"todos": 0
|
|
5375
5411
|
},
|
|
5376
5412
|
"the-portal-shows-only-approved-strings.test.mjs": {
|
|
5377
|
-
"tests":
|
|
5378
|
-
"asserts":
|
|
5413
|
+
"tests": 20,
|
|
5414
|
+
"asserts": 46,
|
|
5379
5415
|
"skips": 0,
|
|
5380
5416
|
"todos": 0
|
|
5381
5417
|
},
|
|
@@ -5517,6 +5553,12 @@
|
|
|
5517
5553
|
"skips": 0,
|
|
5518
5554
|
"todos": 0
|
|
5519
5555
|
},
|
|
5556
|
+
"the-reviewers-sign-off-is-not-the-clearances-answer.test.mjs": {
|
|
5557
|
+
"tests": 3,
|
|
5558
|
+
"asserts": 19,
|
|
5559
|
+
"skips": 0,
|
|
5560
|
+
"todos": 0
|
|
5561
|
+
},
|
|
5520
5562
|
"the-reviewing-pass-reads-the-lines-a-client-sees-first.test.mjs": {
|
|
5521
5563
|
"tests": 10,
|
|
5522
5564
|
"asserts": 27,
|
|
@@ -5591,7 +5633,7 @@
|
|
|
5591
5633
|
},
|
|
5592
5634
|
"the-short-surfaces-quote-the-report.test.mjs": {
|
|
5593
5635
|
"tests": 3,
|
|
5594
|
-
"asserts":
|
|
5636
|
+
"asserts": 9,
|
|
5595
5637
|
"skips": 0,
|
|
5596
5638
|
"todos": 0
|
|
5597
5639
|
},
|
|
@@ -5717,7 +5759,7 @@
|
|
|
5717
5759
|
},
|
|
5718
5760
|
"tokens.test.mjs": {
|
|
5719
5761
|
"tests": 10,
|
|
5720
|
-
"asserts":
|
|
5762
|
+
"asserts": 54,
|
|
5721
5763
|
"skips": 0,
|
|
5722
5764
|
"todos": 0
|
|
5723
5765
|
},
|