clearotron 0.2.3 → 0.2.4

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.
Files changed (76) hide show
  1. package/.env.example +36 -37
  2. package/CONTRIBUTING.md +8 -4
  3. package/INSTALL.md +24 -4
  4. package/README.md +7 -6
  5. package/bin/example.mjs +6 -5
  6. package/bin/onboard.mjs +175 -9
  7. package/bin/start.mjs +66 -4
  8. package/build-info.json +2 -2
  9. package/demo/README.md +1 -1
  10. package/docs/GLOSSARY.md +85 -0
  11. package/docs/README.md +1 -0
  12. package/docs/architecture/01-product-overview.md +21 -9
  13. package/docs/architecture/05-config-governance.md +5 -0
  14. package/docs/decisions/0006-what-the-public-repository-carries.md +30 -5
  15. package/driver/CHANGELOG.md +34 -0
  16. package/driver/README.md +25 -6
  17. package/driver/connotation-search.mjs +1 -1
  18. package/driver/contract-audit.mjs +5 -1
  19. package/driver/contract-e3-baseline.json +11 -11
  20. package/driver/doubt-selection.mjs +1 -1
  21. package/driver/drainer-identity.mjs +1 -1
  22. package/driver/effort-model.mjs +2 -2
  23. package/driver/engine/probe.mjs +45 -5
  24. package/driver/gateway.mjs +2 -2
  25. package/driver/outbox-backoff.mjs +1 -1
  26. package/driver/package.json +1 -1
  27. package/driver/pipeline.mjs +206 -101
  28. package/driver/plain-register.mjs +16 -2
  29. package/driver/portal-config-view.mjs +30 -1
  30. package/driver/portal-local-auth.mjs +5 -1
  31. package/driver/portal-service.mjs +53 -2
  32. package/driver/predelivery-lint.mjs +54 -25
  33. package/driver/publish/render.mjs +109 -14
  34. package/driver/search-policy.mjs +1 -1
  35. package/driver/stage-context.mjs +13 -0
  36. package/driver/stages.mjs +51 -4
  37. package/driver/suite-census.json +97 -31
  38. package/driver/systemd/clearotron-worker.service +3 -3
  39. package/driver/tokens.mjs +1 -1
  40. package/driver/unit-inventory.mjs +34 -4
  41. package/mcp-server/CHANGELOG.md +2 -0
  42. package/mcp-server/package.json +1 -1
  43. package/package.json +4 -10
  44. package/portal-ui/dist/assets/{index-CEYvXdqH.js → index-KFAHMgdT.js} +73 -34
  45. package/portal-ui/dist/index.html +1 -1
  46. package/portal-ui/package.json +1 -1
  47. package/providers/oauth-mcp-bridge/CHANGELOG.md +2 -0
  48. package/providers/oauth-mcp-bridge/package.json +1 -1
  49. package/scripts/added-reference-check.mjs +45 -89
  50. package/scripts/e2e.mjs +2 -2
  51. package/scripts/generated-files-are-current.mjs +125 -0
  52. package/scripts/mint-names-in-force.mjs +4 -2
  53. package/scripts/mint-public-residue.mjs +74 -0
  54. package/scripts/mint-reference-strip-backlog.mjs +12 -1
  55. package/scripts/mint-suite-census.mjs +5 -2
  56. package/scripts/render-check.mjs +13 -2
  57. package/scripts/report-frame-check.mjs +8 -1
  58. package/scripts/report-screenshot.mjs +6 -3
  59. package/scripts/revisit-render-check.mjs +6 -3
  60. package/scripts/score.mjs +1 -1
  61. package/scripts/strip-tracker-citations.mjs +9 -1
  62. package/scripts/test-full.mjs +226 -0
  63. package/shared/README.md +2 -1
  64. package/shared/browser-temp-root.mjs +142 -0
  65. package/shared/checkout-move.mjs +1 -1
  66. package/shared/client-door.mjs +4 -3
  67. package/shared/identifier-scan.mjs +1 -1
  68. package/shared/install-auth.mjs +35 -0
  69. package/shared/invocation.mjs +5 -1
  70. package/shared/listen.mjs +55 -3
  71. package/shared/names-in-force.mjs +4 -1
  72. package/shared/os-advice.mjs +91 -0
  73. package/shared/reap-on-exit.mjs +42 -0
  74. package/shared/reference-guard-classes.mjs +351 -0
  75. package/shared/suite-census.mjs +31 -3
  76. package/shared/withheld-paths-access.mjs +36 -18
@@ -31,7 +31,7 @@ import { buildRunContext, deriveSlug, kebab } from "./phase0.mjs";
31
31
  import { paths, STAGES, axisTier, decideAxes, assertTierSanity, assertEffectiveTier, lines, AGENT_WHATSAPP, whatsappRouting,
32
32
  chainEntries, stageOrdinal, stageInputs, stageOutputs, dependencyOrder, REGISTER_AXES, REGISTER_ENUMERATE_TOOL,
33
33
  buildEscalationFollowup, buildEnvelopeCloseFollowup, buildFrameReopenFollowup,
34
- buildFrameReopenRetryMessage, thinkingFor, composeFollowup, stampDispatchBlocks, PROVIDER_META, proseRungDirective, inquiryRungDirective } from "./stages.mjs";
34
+ buildFrameReopenRetryMessage, thinkingFor, composeFollowup, stampDispatchBlocks, recordEmptyReturn, nothingFound, nothingToRead, PROVIDER_META, proseRungDirective, inquiryRungDirective } from "./stages.mjs";
35
35
  import { IDENTITY_FILE as REPORT_IDENTITY_FILE } from "./report-overview-record.mjs";
36
36
  import { dispatchRows, clearedSignatures } from "./seat-attempts.mjs";
37
37
  import { CONTEXT_DERIVATIONS, DISPATCH_EXTRAS, INLINE_CONTEXT, sandboxManifest, sandboxGaps, derivationsFor } from "./stage-context.mjs"; // — what a stage is actually handed
@@ -150,6 +150,7 @@ import { runLint, flagLines, properNameCandidates } from "./predelivery-lint.mjs
150
150
  import { parsePlacementsJson } from "./placement-model.mjs"; // B2 — the structured tier mirror; the lint reads it only to flag an EMPTY one
151
151
  import { readAnchors } from "./anchor-reader.mjs";
152
152
  import { findEngagementReceipts } from "./engagement-receipt.mjs";
153
+ import { plainRegisterFlags } from "./plain-register.mjs";
153
154
  import { parseFindingsJson, parseFindingsJsonLenient, consolidateFindings, deriveDisplayVerdict, bindRecommendation, compareBlockingPower, inDispositionMode, DISPOSITION_GROUP, deriveActionConditions, cardedParties, actionPartyReferences, quarantinedConditionRows, salvageRepairTargets, riskStatement, verdictStance, remapActionOrdinals, joinAskToAnswer, stripAskLabel, bandBorderlineDeclarations, reasonedNegativeGroups } from "./findings-model.mjs";
154
155
  import { foldCaption, foldCardRead } from "./card-budget.mjs";
155
156
  // S2 — the report card's mechanical frame, composed from the record instead of dictated (see below).
@@ -225,7 +226,7 @@ const CITED_URI_RE = /\/mark\/[a-z]{2,6}\/[a-z0-9][a-z0-9_-]*/gi;
225
226
  * opening the channel. Exported because a guard that can only be asserted by reading source is a guard
226
227
  * whose behaviour was never tested. PURE; never throws.
227
228
  */
228
- export function connotationRemedyToken(err) {
229
+ export function connotationRemedyToken(err) { // @internal
229
230
  const re = new RegExp(`${CONNOTATION_FORM_TOKEN_SRC}[^)]*`);
230
231
  for (const text of [err?.message, err?.detail]) {
231
232
  const m = String(text ?? "").match(re);
@@ -301,7 +302,7 @@ const FALLBACK_ELIGIBLE = [
301
302
  /^timeout$/, /^lane_wedge$/, /^embedded_fallback$/, /^nonzero_exit/,
302
303
  /^status_timeout$/, /^status_overloaded$/, /^status_error$/, /^status_aborted$/, /^status_rate_limited$/,
303
304
  ];
304
- export function isFallbackEligible(fail) {
305
+ export function isFallbackEligible(fail) { // @internal
305
306
  return Boolean(fail) && FALLBACK_ELIGIBLE.some((re) => re.test(fail));
306
307
  }
307
308
 
@@ -313,7 +314,7 @@ export function isFallbackEligible(fail) {
313
314
  // HTTP 502 …"). repairs.mjs's own doctrine says those are sampling noise, not a content verdict — so
314
315
  // anything classifyFailureReason calls transient breaks the streak too. Exported so the strike tests
315
316
  // exercise THIS predicate, not a hand-rolled stand-in.
316
- export function isContentShapedFail(fail) {
317
+ export function isContentShapedFail(fail) { // @internal
317
318
  return classifyFailureReason(String(fail ?? "")) !== "transient" && !isFallbackEligible(fail);
318
319
  }
319
320
 
@@ -326,7 +327,7 @@ export { parseCoverageLedger, parseCoverageLedgerFull } from "./coverage-ledger.
326
327
  // Called FRESH at each gate — register-findings.md AND the JSON are rewritten by re-digests, so a
327
328
  // cached read could span a rewrite. An unreadable machine ledger here is near-impossible (the file
328
329
  // passed the stage validator) — fall back to prose rather than crash; the validator owns that failure.
329
- export function loadCoverageLedger(runDir) {
330
+ export function loadCoverageLedger(runDir) { // @internal
330
331
  // Keystone (#1): every consumer reads through here, so the tool-absence→deferred relabel applies ONCE,
331
332
  // at the single choke point — the escalation-skip gate, the deadline envelope, and the U1 clamp all then
332
333
  // act on the corrected status. The relabel is a pure backstop over coverageLedger.coerceToolAbsenceDeferred
@@ -354,7 +355,7 @@ export function loadCoverageLedger(runDir) {
354
355
  // `named_band_*` tokens — a parse miss is a stage fail with the token, never a hard crash. mergeNamedBands
355
356
  // de-dups enumerated records by record_id and preserves every crowd descriptor. Returns the merged band
356
357
  // object {enumerated, crowds} plus { axes:[…], invalid:[{axis,reason}] } so the caller can flag a bad axis.
357
- export function mergeRegisterBands(P, axes = []) {
358
+ export function mergeRegisterBands(P, axes = []) { // @internal
358
359
  const bands = [];
359
360
  const merged = [];
360
361
  const invalid = [];
@@ -409,7 +410,7 @@ export function mergeRegisterBands(P, axes = []) {
409
410
  // supplemental is skeleton-tracked and receipt-durable exactly like a dictated entry — the taint
410
411
  // chain, the clean-gates, and dispatchPlanQids cover them with zero extra code. Run-local only: the
411
412
  // slug store is never written (clearances run once; senior lawyer 2026-07-10).
412
- export function readRegisterBands(P, axes) {
413
+ export function readRegisterBands(P, axes) { // @internal
413
414
  const byAxis = {};
414
415
  for (const a of axes ?? []) {
415
416
  if (!existsSync(P.registerBand(a))) continue;
@@ -421,12 +422,12 @@ export function readRegisterBands(P, axes) {
421
422
  return byAxis;
422
423
  }
423
424
  /** The plan-execution receipt in hand (ctx first, then the on-disk copy). Never throws. */
424
- export function readPlanExecution(ctx) {
425
+ export function readPlanExecution(ctx) { // @internal
425
426
  if (ctx?.planExecution) return ctx.planExecution;
426
427
  const p = ctx?.paths?.planExecution;
427
428
  try { return p && existsSync(p) ? JSON.parse(readFileSync(p, "utf8")) : null; } catch { return null; }
428
429
  }
429
- export function writePlanExecutionReceipt(ctx, joinRes) {
430
+ export function writePlanExecutionReceipt(ctx, joinRes) { // @internal
430
431
  const P = ctx.paths;
431
432
  // — the ONE place the receipt is written is the one place this decision is taken. The
432
433
  // reclassification is keyed off the receipt already on disk (ladderExhaustedQids), so every writer
@@ -512,7 +513,7 @@ export function writePlanExecutionReceipt(ctx, joinRes) {
512
513
  *
513
514
  * Returns the record it wrote, or null if the findings file could not be read.
514
515
  */
515
- export function settleDerivedBases(ctx, at) {
516
+ export function settleDerivedBases(ctx, at) { // @internal
516
517
  const P = ctx.paths;
517
518
  try {
518
519
  const recordFile = (uri) => join(P.runDir, "_records", String(uri).replace(/^\/mark\//, "").replace(/[^a-z0-9]+/gi, "-") + ".json");
@@ -584,7 +585,7 @@ export function settleDerivedBases(ctx, at) {
584
585
  }
585
586
  }
586
587
 
587
- export function foldSupplementalProposals(ctx) {
588
+ export function foldSupplementalProposals(ctx) { // @internal
588
589
  if (!ctx.registerPlan) return [];
589
590
  const P = ctx.paths;
590
591
  const entries = [];
@@ -632,7 +633,7 @@ export function foldSupplementalProposals(ctx) {
632
633
  // Post-followup accounting: escalation/envelope/reopen turns may have proposed new supplementals —
633
634
  // fold them and refresh the receipt so plan-execution.json (the not-finished substrate every gate
634
635
  // reads) always includes them. NEVER-KILL: accounting must not fail a run the followup just repaired.
635
- export function refreshSupplementalExecution(ctx) {
636
+ export function refreshSupplementalExecution(ctx) { // @internal
636
637
  if (!ctx.registerPlan) return;
637
638
  try {
638
639
  const added = foldSupplementalProposals(ctx);
@@ -760,7 +761,7 @@ function deriveOwnerScreenArtifact(ctx, band) {
760
761
  }
761
762
 
762
763
  /** Read the owner-screen receipt back (the lint + the digest/skeptic data block read it). */
763
- export function readOwnerScreen(P) {
764
+ export function readOwnerScreen(P) { // @internal
764
765
  try { return existsSync(P.ownerScreen) ? JSON.parse(readFileSync(P.ownerScreen, "utf8")) : null; }
765
766
  catch { return null; }
766
767
  }
@@ -773,7 +774,7 @@ export function readOwnerScreen(P) {
773
774
  * instrumentation house rule exists to kill. The absence is therefore also RECORDED either way, with
774
775
  * the reason, so "this matter has no owner lane" and "the receipt went missing" are distinguishable.
775
776
  */
776
- export function ownerScreenForDelivery(ctx) {
777
+ export function ownerScreenForDelivery(ctx) { // @internal
777
778
  const P = ctx.paths;
778
779
  const onDisk = readOwnerScreen(P);
779
780
  if (onDisk?.owners?.length) return onDisk;
@@ -1067,7 +1068,7 @@ function deriveGridSpec(ctx) {
1067
1068
  // the reason this issue could not be answered by persisting and replaying: all three `probeOrder` seams
1068
1069
  // sit INSIDE band-shape.mjs's derivation functions, so a rig that replayed a persisted band-shape.json
1069
1070
  // would hand a seeded arm the unseeded artifact and report — byte-identically, and wrongly — no effect.
1070
- export const DERIVATION_RUNNERS = {
1071
+ export const DERIVATION_RUNNERS = { // @internal
1071
1072
  "band-shape": (ctx) => {
1072
1073
  const P = ctx.paths;
1073
1074
  if (!existsSync(P.registerNamedBand)) return false;
@@ -1117,6 +1118,7 @@ const DISPATCH_EXTRA_BUILDERS = {
1117
1118
  // corruption 2 — narrative-refutation's two, composed inline at the dispatch site until now.
1118
1119
  "plan-audit": (ctx) => planAuditExtra(ctx),
1119
1120
  "refute-registry-check": (ctx) => refuteRegistryCheckExtra(ctx),
1121
+ "refute-plain-register": (ctx) => plainRegisterExtra(ctx),
1120
1122
  // — the SAME receipt derivation, one seat earlier. A distinct id rather than a second
1121
1123
  // `plan-audit` entry so the dispatch receipt (`extras`) still says which stage carried which block;
1122
1124
  // the builder delegates, so there is one derivation and one set of graded classes.
@@ -1164,13 +1166,13 @@ const DISPATCH_EXTRA_BUILDERS = {
1164
1166
  * bug. Collapsing the two would make the bug read as an ordinary run — an absence that is not a
1165
1167
  * finding. The prompt says which of the two it is, and the note() still fires for the run log.
1166
1168
  */
1167
- export function composeDispatchExtra(name, ctx, opts = {}) {
1168
- const parts = [], ids = [], failed = [];
1169
+ export function composeDispatchExtra(name, ctx, opts = {}) { // @internal
1170
+ const parts = [], ids = [], failed = [], empty = [];
1169
1171
  for (const x of DISPATCH_EXTRAS) {
1170
1172
  if (x.stage !== name) continue;
1171
1173
  try {
1172
1174
  const built = DISPATCH_EXTRA_BUILDERS[x.id](ctx, opts);
1173
- if (built) { parts.push(built); ids.push({ id: x.id, chars: built.length }); }
1175
+ recordEmptyReturn(built, x.id, { parts, ids, empty }); // EVERY builder that ran is recorded, not only those that produced text: `if (built)` alone put an empty return in neither list, so a block that ran with nothing to flag read exactly like one that never ran — and only the second is a defect. The three-way sort lives in stages.mjs beside the sentinels it reads.
1174
1176
  } catch (e) {
1175
1177
  const detail = String(e?.message ?? e).slice(0, 100);
1176
1178
  failed.push({ id: x.id, error: detail });
@@ -1181,8 +1183,8 @@ export function composeDispatchExtra(name, ctx, opts = {}) {
1181
1183
  // composes blocks for several stages over a run and the last one must never answer for another.
1182
1184
  // `stampDispatchBlocks` is imported from stages.mjs, where the reader lives: one definition of the
1183
1185
  // stamp's shape, rather than a field name two files agree on by hand.
1184
- stampDispatchBlocks(ctx, name, { built: ids.map((x) => x.id), failed });
1185
- return { text: parts.length ? parts.join("\n\n") : "", ids, failed };
1186
+ stampDispatchBlocks(ctx, name, { built: ids.map((x) => x.id), failed, empty });
1187
+ return { text: parts.length ? parts.join("\n\n") : "", ids, failed, empty };
1186
1188
  }
1187
1189
 
1188
1190
  // A declared derivation or extra with no runner would silently produce NOTHING and the sandbox would
@@ -1242,7 +1244,7 @@ const AXIS_VOCABULARY = {
1242
1244
  // Which production pass an --experiment arm may reproduce. "fresh" is the first full dispatch (the one
1243
1245
  // a preserved run's canonical artefact came from); the rest are the re-dispatch triggers runDigest
1244
1246
  // labels, and they carry the placement rulings tail a fresh pass does not.
1245
- export const DISPATCH_TRIGGERS = ["fresh", "escalation", "envelope", "late-bind", "stale-repair", "settlement-flush", "corrective"]; // — the corrective pass is the seam the losses happen in; see driver/corrective-arm.mjs for warm vs cold
1247
+ export const DISPATCH_TRIGGERS = ["fresh", "escalation", "envelope", "late-bind", "stale-repair", "settlement-flush", "corrective"]; // @internal the corrective pass is the seam the losses happen in; see driver/corrective-arm.mjs for warm vs cold
1246
1248
 
1247
1249
  /**
1248
1250
  * The sha of a sandbox file AS IT WOULD READ on the canonical run — the sandbox's own directory
@@ -1344,7 +1346,7 @@ const isCoverageLedgerFail = (fail) => /invalid_file:[^:]*:coverage_(ledger|axis
1344
1346
  */
1345
1347
  // The five words whose presence in the draft narrative means the run's own reading turned on a precedent
1346
1348
  // or an opposition. Exported so a probe binds to it instead of retyping it (the rule).
1347
- export const CASE_LAW_TRIGGERS = /watchlist|precedent|case[- ]law|opposition|famous mark/i;
1349
+ export const CASE_LAW_TRIGGERS = /watchlist|precedent|case[- ]law|opposition|famous mark/i; // @internal
1348
1350
 
1349
1351
  // — CASE LAW HAS EXACTLY ONE HOME, AND THE PRODUCT DECIDES IT, NOT THE NARRATIVE.
1350
1352
  //
@@ -1366,7 +1368,7 @@ export const CASE_LAW_TRIGGERS = /watchlist|precedent|case[- ]law|opposition|fam
1366
1368
  // "a case-law question exists in territory X — a Full country search would examine it" recommendation,
1367
1369
  // and NO report or email sentence for it exists here: no wording enters a deliverable that the owner has
1368
1370
  // not agreed.
1369
- export const CASE_LAW_PRODUCT = "full-country-search";
1371
+ export const CASE_LAW_PRODUCT = "full-country-search"; // @internal
1370
1372
 
1371
1373
  /**
1372
1374
  * Does the case-law grounding stage run? PRODUCT-GATED, requested-or-detected within it.
@@ -1382,7 +1384,7 @@ export const CASE_LAW_PRODUCT = "full-country-search";
1382
1384
  *
1383
1385
  * PURE; never throws.
1384
1386
  */
1385
- export function decideCaseLaw({ job, narrative, policy } = {}) {
1387
+ export function decideCaseLaw({ job, narrative, policy } = {}) { // @internal
1386
1388
  const requested = job?.caseLaw === true || policy?.caseLaw === true;
1387
1389
  const m = CASE_LAW_TRIGGERS.exec(String(narrative ?? ""));
1388
1390
  const detected = Boolean(m);
@@ -1411,7 +1413,7 @@ export function decideCaseLaw({ job, narrative, policy } = {}) {
1411
1413
  // T1 (J2): default 500→150. 500 detail-fetches cannot fit the 1500s stage wall — the old default
1412
1414
  // contradicted the prompt's own "a bounded WRITTEN band beats an exhaustive one killed mid-fetch" and drove
1413
1415
  // the 48% reopen-timeout class ( F5). 150 fits the wall with margin; env-tunable for deep closure.
1414
- export function reopenFetchCeiling(envVal) {
1416
+ export function reopenFetchCeiling(envVal) { // @internal
1415
1417
  const n = Number(envVal);
1416
1418
  return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 150;
1417
1419
  }
@@ -1426,7 +1428,7 @@ export function reopenFetchCeiling(envVal) {
1426
1428
  // The exact subset of the resolved profile frozen into the run sidecar (_driver/profile.json). Exported so
1427
1429
  // the freeze contract is unit-testable (the bug this guards: a per-customer field configured in a profile
1428
1430
  // but DROPPED here is silently never applied — the stages read the frozen copy, not the raw profile).
1429
- export function freezeProfile(p, project = null) {
1431
+ export function freezeProfile(p, project = null) { // @internal
1430
1432
  const frozen = {
1431
1433
  profileKey: p.key,
1432
1434
  name: p.name,
@@ -1507,7 +1509,7 @@ function canonicalJson(v) {
1507
1509
  if (v && typeof v === "object") return `{${Object.keys(v).sort().map((k) => `${JSON.stringify(k)}:${canonicalJson(v[k])}`).join(",")}}`;
1508
1510
  return JSON.stringify(v) ?? "null";
1509
1511
  }
1510
- export function profileShaOf(frozen) {
1512
+ export function profileShaOf(frozen) { // @internal
1511
1513
  const { profileSha: _omit, ...rest } = frozen ?? {};
1512
1514
  return createHash("sha256").update(canonicalJson(rest)).digest("hex");
1513
1515
  }
@@ -1630,7 +1632,7 @@ function attachFramework(ctx, { write = true } = {}) {
1630
1632
  * list still unions in later at the gather door). Idempotent by construction, so the resume
1631
1633
  * re-fold from the frozen sidecar changes nothing; sidecars frozen before recipeScope existed
1632
1634
  * carry null and no-op. */
1633
- export function foldRecipeScope(job, searchPolicy) {
1635
+ export function foldRecipeScope(job, searchPolicy) { // @internal
1634
1636
  const s = searchPolicy?.recipeScope;
1635
1637
  if (!s || typeof s !== "object") return job;
1636
1638
  const nonEmpty = (a) => Array.isArray(a) && a.length > 0;
@@ -1659,7 +1661,7 @@ export function foldRecipeScope(job, searchPolicy) {
1659
1661
  return job;
1660
1662
  }
1661
1663
 
1662
- export function attachSearchPolicy(ctx, job, { write = true } = {}) {
1664
+ export function attachSearchPolicy(ctx, job, { write = true } = {}) { // @internal
1663
1665
  const sidecarPath = driverDir(ctx.paths.runDir, "search-policy.json");
1664
1666
  let raw = null;
1665
1667
  try { raw = readFileSync(sidecarPath, "utf8"); } catch { /* ENOENT — genuinely absent */ }
@@ -1891,7 +1893,7 @@ function renderDocumentCoverageFromRecords(ctx, trigger) {
1891
1893
  // returns empty facts; every seat-sent uri then refuses by name (`registerdigest_uri_unknown`) on the
1892
1894
  // first call. So a driver fault surfaces as a loud refusal on call 1 rather than as a document of blank
1893
1895
  // identifier cells — the same fail-closed direction the coverage form's write order takes.
1894
- export function writeRegisterDigestFacts(ctx, trigger) {
1896
+ export function writeRegisterDigestFacts(ctx, trigger) { // @internal
1895
1897
  const P = ctx.paths;
1896
1898
  try {
1897
1899
  const records = existsSync(P.registerNamedBand)
@@ -2345,7 +2347,7 @@ function attachRegisterPlan(ctx, { frozenOnly = false } = {}) {
2345
2347
  * from the searched set, and log/note them. `plan.deferred_coverage` is [{jurisdiction, reason}].
2346
2348
  * Exported for test; never throws (a plan without the key is a fully-covered plan → no-op).
2347
2349
  */
2348
- export function registerDeferredCoverage(ctx, plan) {
2350
+ export function registerDeferredCoverage(ctx, plan) { // @internal
2349
2351
  const deferred = Array.isArray(plan?.deferred_coverage) ? plan.deferred_coverage : [];
2350
2352
  // A12: recorded in the CANONICAL vocabulary (UK→GB, EM/EUTM/EUIPO→EU) so the scope backstop's
2351
2353
  // subtraction meets extractSearchedJurisdictions on the same codes — never GB-vs-UK as two territories.
@@ -2413,7 +2415,7 @@ function mechanicalFormGapDirectives(ctx) {
2413
2415
  * runDigest re-arms and re-writes the form before the next dispatch, and in the window between, a stamp
2414
2416
  * with no form is `coverage_form_missing` — the fail-closed direction.
2415
2417
  */
2416
- export function taintParkJudgmentArtifacts(P, runDir) {
2418
+ export function taintParkJudgmentArtifacts(P, runDir) { // @internal
2417
2419
  const form = coverageFormPaths(runDir, coverageFormStamp(runDir).formName);
2418
2420
  return [P.registerFindings, P.registerCoverageLedger, form.seat, form.sidecar];
2419
2421
  }
@@ -2509,7 +2511,7 @@ const RECALL_FOLLOWUP_MAX = 2;
2509
2511
  // tell a graded product from an ungraded one, and every measurement across the change is unattributable.
2510
2512
  // `source` is the load-bearing field — `default-ungraded` says a product this build has no row for fell
2511
2513
  // back to one-country values, which otherwise looks exactly like a deliberate setting.
2512
- export function depthLadderEvent(ctx) {
2514
+ export function depthLadderEvent(ctx) { // @internal
2513
2515
  const depth = ctx?.depth ?? null;
2514
2516
  return {
2515
2517
  event: "depth-ladder",
@@ -2521,7 +2523,7 @@ export function depthLadderEvent(ctx) {
2521
2523
  };
2522
2524
  }
2523
2525
 
2524
- export const recallFollowupMaxFor = (ctx) => {
2526
+ export const recallFollowupMaxFor = (ctx) => { // @internal
2525
2527
  const n = ctx?.depth?.recallFollowupMax;
2526
2528
  return Number.isInteger(n) && n > 0 ? n : RECALL_FOLLOWUP_MAX;
2527
2529
  };
@@ -2971,7 +2973,7 @@ function recordSynthesisSeam(ctx, r, trigger = null) {
2971
2973
  // `findings` is passed in rather than read here so the caller proves it has them. The previous version
2972
2974
  // read the file itself, from inside register-digest, which runs BEFORE synthesis authors it — so it
2973
2975
  // joined against `[]` and reported every record that became a finding as dropped.
2974
- export function deriveRecordCarry(ctx, trigger, { findings = null } = {}) { // exported for its CALL-SITE test ( leg b)
2976
+ export function deriveRecordCarry(ctx, trigger, { findings = null } = {}) { // @internal — exported for its CALL-SITE test ( leg b)
2975
2977
  const P = ctx.paths;
2976
2978
  const write = (artifact) => {
2977
2979
  try {
@@ -3576,7 +3578,7 @@ async function runDigest(ctx, opts = {}) {
3576
3578
  // EXTRACTION ONLY. Same blocks, same order, same guards: A8 and the owner receipt are unconditional,
3577
3579
  // the rulings tail keeps `willRun && trigger !== "fresh"`. Returns `extra` UNCHANGED — by identity, so
3578
3580
  // a caller can tell nothing was appended — when no block fires.
3579
- export function digestDispatchExtra(ctx, { trigger = "fresh", willRun = true, extra = undefined } = {}) {
3581
+ export function digestDispatchExtra(ctx, { trigger = "fresh", willRun = true, extra = undefined } = {}) { // @internal
3580
3582
  const P = ctx.paths;
3581
3583
  let out = extra;
3582
3584
  // — THE COVERAGE FORM BRIEF, replacing the deferred-slice block (was A8, 2026-07-30).
@@ -3680,7 +3682,7 @@ export function digestDispatchExtra(ctx, { trigger = "fresh", willRun = true, ex
3680
3682
  //
3681
3683
  // NO DESIGNATION ⇒ NO BREACH, and that is load-bearing rather than incidental: a floor that defaulted to
3682
3684
  // on would manufacture the hold on every run, which is worse than the widening closes.
3683
- export function findFloorBreaches(ledger, floorAxes) {
3685
+ export function findFloorBreaches(ledger, floorAxes) { // @internal
3684
3686
  const floors = new Set((floorAxes ?? []).map((a) => String(a ?? "").trim().toLowerCase()).filter(Boolean));
3685
3687
  if (!floors.size) return [];
3686
3688
  return (ledger ?? [])
@@ -3700,7 +3702,7 @@ export function findFloorBreaches(ledger, floorAxes) {
3700
3702
  * through `checkSiblingJson` and fails prelim-variants with `variantmodel_missing`. Checked, because
3701
3703
  * "something else refuses it" is exactly the assumption that turns a swallowed error into a silent pass.
3702
3704
  */
3703
- export function readFloorAxes(paths) {
3705
+ export function readFloorAxes(paths) { // @internal
3704
3706
  try { return parseVariantManifestModel(readFileSync(paths.variantManifestModel, "utf8")).search_floor ?? []; }
3705
3707
  catch { return []; }
3706
3708
  }
@@ -3711,7 +3713,7 @@ export function readFloorAxes(paths) {
3711
3713
  // It is `deferred` only because a non-search must not be dressed as a clean — it is NOT floor work left
3712
3714
  // open. Keyed on the self-digest scope (deterministic, skill-dictated), never a genuine floor's
3713
3715
  // substantive scope, so a real open floor can never be swept out.
3714
- export function isInactiveAxisRow(r) {
3716
+ export function isInactiveAxisRow(r) { // @internal
3715
3717
  return /\bnot[\s-]?applicable\b/i.test(String(r?.unit ?? r?.scope ?? ""));
3716
3718
  }
3717
3719
 
@@ -3727,7 +3729,7 @@ export function isInactiveAxisRow(r) {
3727
3729
  //
3728
3730
  // The breach line names WHY it is disclosed, because "unit X" on a disclosure a client reads is not a
3729
3731
  // finding — it is a word.
3730
- export function computeOpenFloors(ledger, floorAxes) {
3732
+ export function computeOpenFloors(ledger, floorAxes) { // @internal
3731
3733
  return (ledger ?? []).filter((r) => r.status === "deferred" && !isInactiveAxisRow(r)).map((r) => r.unit)
3732
3734
  .concat(findFloorBreaches(ledger, floorAxes)
3733
3735
  .map((b) => `${b.unit} (labelled coverage-limited — search-floor work on a designated axis, without a found/not-found result)`));
@@ -3741,7 +3743,7 @@ export function computeOpenFloors(ledger, floorAxes) {
3741
3743
  // must reach the in-flight run: before matter-frame consumes the job ⇒ fold normally; after matter-frame
3742
3744
  // but before the narrative exists ⇒ exclusion is a FILTER — re-classify at (re-)digest, never re-run
3743
3745
  // searches; after the narrative exists ⇒ too late to bind silently — the answer ships as a delivery note.
3744
- export function lateBindAction({ matterFrameRan, digestRan, narrativeExists }) {
3746
+ export function lateBindAction({ matterFrameRan, digestRan, narrativeExists }) { // @internal
3745
3747
  if (narrativeExists) return "front-matter-note";
3746
3748
  if (digestRan) return "warm-redigest";
3747
3749
  if (matterFrameRan) return "digest-message";
@@ -3757,7 +3759,7 @@ export function lateBindAction({ matterFrameRan, digestRan, narrativeExists }) {
3757
3759
  // can log them and leave them standing. They are NOT resolved, NOT relabelled and NOT quietly dropped:
3758
3760
  // a held row stays `deferred`, keeps its open-floor status, and ships disclosed with its mechanical
3759
3761
  // cause. The coverage floor's right to refuse a clean verdict over that slice is exactly the point.
3760
- export function envelopeDecision({ deferredAxes, deadline, now, estCloseSec, heldAxes = [] }) {
3762
+ export function envelopeDecision({ deferredAxes, deadline, now, estCloseSec, heldAxes = [] }) { // @internal
3761
3763
  const held = [...new Set((heldAxes ?? []).map((a) => String(a)))];
3762
3764
  const closeable = (deferredAxes ?? []).filter((a) => !held.includes(String(a)));
3763
3765
  const heldNote = held.length
@@ -3784,7 +3786,7 @@ export function envelopeDecision({ deferredAxes, deadline, now, estCloseSec, hel
3784
3786
  * deferred end to end. The AUTHORITY half of the capability-gap split; prose only ever narrows inside
3785
3787
  * an axis this set already names. PURE.
3786
3788
  */
3787
- export function capabilityGapAxes(plan, receipt) {
3789
+ export function capabilityGapAxes(plan, receipt) { // @internal
3788
3790
  const axisOf = new Map((plan?.entries ?? []).map((e) => [String(e?.qid ?? ""), String(e?.axis ?? "").toLowerCase()]));
3789
3791
  const out = new Set();
3790
3792
  for (const d of receipt?.deferred ?? []) {
@@ -3862,7 +3864,7 @@ function forceFromActive(ctx, name) {
3862
3864
  // warm-resume a session no engine ever opened. A code-side winner therefore recovers its TRUE model (the
3863
3865
  // telemetry stays honest in the skip event) with key:null — the same "resumed-past axis" contract
3864
3866
  // runSaturationProbeCodeSide already declares (null unitKey ⇒ escalation/envelope use their code/fresh lanes).
3865
- export function recoverWinningAttempt(runDir, label) {
3867
+ export function recoverWinningAttempt(runDir, label) { // @internal
3866
3868
  try {
3867
3869
  const lines = readFileSync(driverDir(runDir, `${label}.jsonl`), "utf8").trim().split("\n");
3868
3870
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -3891,7 +3893,7 @@ export function recoverWinningAttempt(runDir, label) {
3891
3893
  // Returns the stageOnce result shape. sessionKey is ALWAYS null: there is no live session to
3892
3894
  // warm-resume, so the escalation/envelope arms and the plan-join treat the axis as resumed-past and use
3893
3895
  // their code/fresh lanes (they already must — resumed-past axes have had a null unitKey since).
3894
- export async function runSaturationProbeCodeSide(ctx, planExec) {
3896
+ export async function runSaturationProbeCodeSide(ctx, planExec) { // @internal
3895
3897
  const P = ctx.paths;
3896
3898
  const a = "saturation-probe";
3897
3899
  const label = `register-unit:${a}`;
@@ -4917,7 +4919,7 @@ async function runBatched(items, limit, fn) {
4917
4919
  // Pure text→text so the extraction tests offline; "" when the heading is absent (a legacy or
4918
4920
  // register-less run costs the dispatch nothing). Capped so a crowded band's rulings cannot balloon
4919
4921
  // a followup dispatch — the cut lands on a line boundary and says so, never a silent mid-row chop.
4920
- export function extractRulingsTail(placementMd, { cap = 8000 } = {}) {
4922
+ export function extractRulingsTail(placementMd, { cap = 8000 } = {}) { // @internal
4921
4923
  const text = String(placementMd ?? "");
4922
4924
  const m = text.match(/^#{2,4}\s*Coverage rulings\b.*$/im);
4923
4925
  if (!m) return "";
@@ -4952,7 +4954,7 @@ export function extractRulingsTail(placementMd, { cap = 8000 } = {}) {
4952
4954
  * Composed from the same function the fresh dispatch uses, so the two are the same string rather than
4953
4955
  * two texts that agree today.
4954
4956
  */
4955
- export function stageCharter(stageName, depth, framework = null) {
4957
+ export function stageCharter(stageName, depth, framework = null) { // @internal
4956
4958
  // THE BAND ORDER RIDES THE CHARTER, because rule 2 names the run's own band labels and a warm dispatch
4957
4959
  // that composed them from nothing would send a DIFFERENT directive to the same seat — which is the
4958
4960
  // whole failure this helper exists to prevent, reintroduced one argument down.
@@ -4971,7 +4973,7 @@ export function stageCharter(stageName, depth, framework = null) {
4971
4973
  * A re-emission that is not told the rung is not a repair of the rung's output. It is a fresh write
4972
4974
  * under the default contract, wearing the corrective pass's name.
4973
4975
  */
4974
- export function correctionsExtra(P, depth = null, framework = null) {
4976
+ export function correctionsExtra(P, depth = null, framework = null) { // @internal
4975
4977
  const review = existsSync(P.seniorEyeReview) ? readFileSync(P.seniorEyeReview, "utf8") : "";
4976
4978
  const rulingsTail = extractRulingsTail(existsSync(P.placement) ? readFileSync(P.placement, "utf8") : "");
4977
4979
  // — THE FLAGS ARRIVE AS A TYPED WORKLIST, not only as a wall of prose. The reviewer already
@@ -5039,7 +5041,7 @@ export function correctionsExtra(P, depth = null, framework = null) {
5039
5041
  // means: a receipt exists AND the review + narrative bytes are exactly the ones the completed cycle
5040
5042
  // left behind (both non-null — an absent file is never "settled"). Either file moving re-arms the
5041
5043
  // cycle: a recomputed narrative or a fresh review is new work, never a replay.
5042
- export function correctiveCycleSettledDecision(receipt, current) {
5044
+ export function correctiveCycleSettledDecision(receipt, current) { // @internal
5043
5045
  return Boolean(receipt?.shas
5044
5046
  && receipt.shas.review != null && receipt.shas.review === current?.review
5045
5047
  && receipt.shas.narrative != null && receipt.shas.narrative === current?.narrative);
@@ -5074,7 +5076,7 @@ export function correctiveCycleSettledDecision(receipt, current) {
5074
5076
  * Logged rather than thrown: the freshness module is best-effort by contract, and killing a run over
5075
5077
  * bookkeeping would trade a cheap park for a dead one.
5076
5078
  */
5077
- export function settleOneShotStamp(runDir, label, files, why) {
5079
+ export function settleOneShotStamp(runDir, label, files, why) { // @internal
5078
5080
  const changed = [], missed = [];
5079
5081
  for (const f of files.filter(Boolean)) {
5080
5082
  const r = restampStage(runDir, label, f, { project: projectStageInput });
@@ -5126,7 +5128,7 @@ export function settleOneShotStamp(runDir, label, files, why) {
5126
5128
  // artifact is blessed past a live consumer. And it narrows what is COMPARED, never what is DECLARED —
5127
5129
  // narrowing the declaration would let a card be repaired ahead of its stale upstream, which is the one
5128
5130
  // thing item 15a exists to prevent, and dependency-repair.test.mjs pins that edge.
5129
- export function projectStageInput(label, absPath) {
5131
+ export function projectStageInput(label, absPath) { // @internal
5130
5132
  if (typeof label !== "string" || !label.startsWith("report-card:")) return null;
5131
5133
  if (basename(String(absPath ?? "")) !== "findings.json") return null;
5132
5134
  const ord = Number(label.slice("report-card:".length));
@@ -5157,7 +5159,7 @@ export function projectStageInput(label, absPath) {
5157
5159
  // document at its canonical path — the surviving copy is the preserved best draft — so that is read
5158
5160
  // too, and `source` says which, since a best draft is the model's last work and not necessarily its
5159
5161
  // final one. Best-effort throughout: an audit that cannot be written must never cost a run.
5160
- export function connotationAuditSeats(P, runDir) {
5162
+ export function connotationAuditSeats(P, runDir) { // @internal
5161
5163
  const seats = [];
5162
5164
  // B — the audit reads the ACCUMULATORS in `_driver/` (formSidecarPath), the same copies the gate
5163
5165
  // judges. The seat-facing mirrors this used to read died with the form path; reading a path nothing
@@ -5186,7 +5188,7 @@ export function connotationAuditSeats(P, runDir) {
5186
5188
  // numbers it produces were not, so the whole point — that the audit READS the verdict ledger — was
5187
5189
  // asserted only in the pure functions it calls. A wiring that never runs in a test is a wiring nobody has
5188
5190
  // seen work.
5189
- export function recordConnotationAudit(run, P) {
5191
+ export function recordConnotationAudit(run, P) { // @internal
5190
5192
  try {
5191
5193
  const seats = [];
5192
5194
  let didNotBind = 0, neverAddressed = 0, quotesUnbound = 0, recordedQueries = 0;
@@ -5620,8 +5622,8 @@ const UPSTREAM_STALE_REPAIR = {
5620
5622
  // settleOneShotStamp above, not a re-run.
5621
5623
  };
5622
5624
 
5623
- export const DELIVERY_TAIL_LABEL_RE = /^(report-overview|report-card:.+)$/;
5624
- export function partitionDeliveryStale(staleStages) {
5625
+ export const DELIVERY_TAIL_LABEL_RE = /^(report-overview|report-card:.+)$/; // @internal
5626
+ export function partitionDeliveryStale(staleStages) { // @internal
5625
5627
  const tail = [], upstream = [];
5626
5628
  for (const s of staleStages ?? []) (DELIVERY_TAIL_LABEL_RE.test(String(s?.label ?? "")) ? tail : upstream).push(s);
5627
5629
  return { tail, upstream };
@@ -5684,7 +5686,7 @@ function snapshotFindingsForCorrections(P, runDir) {
5684
5686
  *
5685
5687
  * Returns the rollback record, or null to mean "this one still throws".
5686
5688
  */
5687
- export function rollbackCorrectivePass(P, runDir, pre, fail) {
5689
+ export function rollbackCorrectivePass(P, runDir, pre, fail) { // @internal
5688
5690
  if (fail?.fail === "rate_limited" || fail?.resetsAt) return null;
5689
5691
  if (!pre?.raw) return null;
5690
5692
  let now = null;
@@ -5715,7 +5717,7 @@ export function rollbackCorrectivePass(P, runDir, pre, fail) {
5715
5717
  * replace and there is no shape that deletes. This runs underneath, for the whole-document path that
5716
5718
  * remains reachable.
5717
5719
  *
5718
- * REPAIR AND DELIVER, ruled by overwatch under authority the owner delegated in session on 2026-08-27.
5720
+ * REPAIR AND DELIVER, decided under authority the owner delegated in session on 2026-08-27.
5719
5721
  * The three alternatives were weighed and written down: rolling back gives the client every finding but
5720
5722
  * none of the reviewer's corrections — one silent loss traded for another; printing the removals as open
5721
5723
  * points tells the client about a hole instead of filling it; holding the report is against the standing
@@ -5737,7 +5739,7 @@ export function rollbackCorrectivePass(P, runDir, pre, fail) {
5737
5739
  *
5738
5740
  * @returns {null | {restoredFindings: {ordinal: *, mark: *}[], restoredKeys: string[], leftRemoved: {ordinal: *, mark: *}[]}}
5739
5741
  */
5740
- export function repairUnnamedRemovals(P, runDir, pre, namedOrdinals, namedMarks) {
5742
+ export function repairUnnamedRemovals(P, runDir, pre, namedOrdinals, namedMarks) { // @internal
5741
5743
  if (!pre?.raw) return null; // nothing held — nothing to compare against
5742
5744
  let preDoc = null, postDoc = null, postRaw = null;
5743
5745
  try { preDoc = JSON.parse(pre.raw); } catch { return null; }
@@ -5803,7 +5805,7 @@ export function repairUnnamedRemovals(P, runDir, pre, namedOrdinals, namedMarks)
5803
5805
  * "" WHEN NOTHING WAS RESTORED, which is every ordinary run: `lines()` drops an empty string, so the
5804
5806
  * dispatch is byte-identical to the one before this existed unless the repair actually fired.
5805
5807
  */
5806
- export function restoredFindingsTable(repair) {
5808
+ export function restoredFindingsTable(repair) { // @internal
5807
5809
  const rows = repair?.restoredFindings ?? [];
5808
5810
  if (!rows.length) return "";
5809
5811
  return [
@@ -5928,7 +5930,7 @@ async function enforceCorrectionsReachFindings(ctx, P, pre, resume) {
5928
5930
  // authority (stages.mjs also lists them as inputs) but the rows are already here, so nothing has to
5929
5931
  // be re-derived to answer the escalation question. Best-effort by construction: the skeptic is
5930
5932
  // non-fatal and a missing block only returns it to the prose it reads anyway.
5931
- export function skepticDeferralExtra(ctx) {
5933
+ export function skepticDeferralExtra(ctx) { // @internal
5932
5934
  const P = ctx.paths;
5933
5935
  try {
5934
5936
  const rows = loadCoverageLedger(P.runDir).rows;
@@ -6012,6 +6014,109 @@ function refuteRegistryCheckExtra(ctx) {
6012
6014
  } catch (e) { note(`refute registry pre-check (non-fatal): ${e.message}`); return ""; }
6013
6015
  }
6014
6016
 
6017
+ /**
6018
+ * Rule 1 of the two-register rule, over the clearance's default-visible lines, as a prompt block.
6019
+ *
6020
+ * ADVISORY, AND IT STAYS ADVISORY. A hit is a rewritten sentence in the reviewer's own flags — never a
6021
+ * disclosure to the client, never a run failure. It moves no band, no evidence and nothing that is
6022
+ * searched. That is the whole reason it rides THIS stage rather than the pre-delivery lint: the
6023
+ * reviewing pass already quotes a sentence and hands back the rewrite, in the voice it uses for
6024
+ * everything else, and it reaches the writer instead of the reader.
6025
+ *
6026
+ * THE DRIVER MEASURES, THE SEAT JUDGES. `plainRegisterFlags` is deterministic; this block reports what
6027
+ * it found — which line carries a word of the profession's, and how long a sentence ran. Whether the
6028
+ * sentence is actually wrong, and what replaces it, is the reviewer's call. The decision this
6029
+ * implements rejects a word list AS THE MECHANISM, so the block hands the seat evidence and never a
6030
+ * verdict: half these words are ordinary English and several are plausible marks.
6031
+ *
6032
+ * AND IT IS BLIND TO THE RUN'S OWN NOUNS. Every mark, variant and owner the run is about is blanked
6033
+ * before the text is read, because a check that flagged the mark being cleared would put its noise on
6034
+ * the one report where it matters most — the same defect one level in that turned "AXIS Bank filed in
6035
+ * class 36" into "group Bank filed in class 36" on a report clearing AXIS.
6036
+ *
6037
+ * WHY THE FIELDS ARE THE RECORD'S OWN KEYS AND NOT `DEFAULT_VISIBLE_FIELDS.clearance`. That list's
6038
+ * clearance half names five fields nothing in this tree reads — `oneLiner`, `freedomToOperate`,
6039
+ * `thirdPartyRights`, `ownRights` and `batchOpener`, in either casing. Iterating it would open nothing
6040
+ * and report a clean result over text it never read, which is the absence-as-pass this block exists to
6041
+ * avoid. The keys below are the ones the record actually carries, and they are the surfaces the
6042
+ * READER-OWNED NOUNS directive already names as reaching the client. Reconciling that list is its own
6043
+ * change because it is shared with the knockout half, which IS real.
6044
+ *
6045
+ * An absent or malformed findings.json yields no block, and the composer records the id as not built —
6046
+ * so "nothing to say" and "could not look" are told apart on the dispatch receipt rather than inferred.
6047
+ */
6048
+ function plainRegisterExtra(ctx) {
6049
+ try {
6050
+ const P = ctx.paths;
6051
+ if (!existsSync(P.findings)) return nothingToRead(`no findings record at ${P.findings}, so no visible line was read`); // NOT the same nothing as the one below: this never read a line
6052
+ // ABSENT IS NOT CORRUPT, and the composer already tells them apart — so let a parse failure THROW.
6053
+ // Swallowing it here would return "" and land the id in neither `ids` nor `failed`, which reads on
6054
+ // the dispatch receipt as "this run had nothing to say" over a record nobody could open. The file
6055
+ // being missing is the legitimately empty case and returns above; a record that exists and will not
6056
+ // parse is a real defect, and the receipt should carry it.
6057
+ const doc = parseFindingsJson(readFileSync(P.findings, "utf8"));
6058
+
6059
+ const about = {
6060
+ marks: [
6061
+ ...(Array.isArray(ctx.job?.marks) ? ctx.job.marks.map((m) => (typeof m === "string" ? m : m?.name)) : []),
6062
+ ctx.job?.markName, ctx.job?.name,
6063
+ ].filter((x) => typeof x === "string" && x),
6064
+ owners: (doc.findings ?? [])
6065
+ .flatMap((f) => [f?.owner, f?.owner_name, f?.owner?.name])
6066
+ .filter((x) => typeof x === "string" && x),
6067
+ };
6068
+
6069
+ // The surfaces a clearance reader meets before opening anything, named one by one so adding a
6070
+ // field to the page is a deliberate addition here too.
6071
+ const visible = [];
6072
+ const add = (where, v) => { const t = String(v ?? "").trim(); if (t) visible.push({ where, text: t }); };
6073
+ for (const f of doc.findings ?? []) add(`conflict ${f?.ordinal ?? "?"}'s one sentence`, f?.net);
6074
+ for (const c of doc.coverage ?? []) add(`the coverage line for "${c?.area ?? "an area"}"`, c?.note);
6075
+ for (const a of doc.actions ?? []) add(`the action "${a?.id ?? a?.kind ?? ""}"`.replace(/ ""$/, ""), a?.text);
6076
+ for (const k of ["distinctiveness", "connotation"]) {
6077
+ const v = doc.markAssessment?.[k];
6078
+ add(`the mark assessment's ${k}`, typeof v === "string" ? v : v?.read);
6079
+ }
6080
+
6081
+ const hits = [];
6082
+ for (const { where, text } of visible) {
6083
+ for (const flag of plainRegisterFlags(text, about)) hits.push(`- ${where} — ${flag.say}`);
6084
+ }
6085
+ if (!hits.length) return nothingFound(`no plain-words flag over ${visible.length} visible line(s)`); // a NEGATIVE FINDING, and the count travels with it so a clean read is not a read of nothing
6086
+
6087
+ // THE LAST SENTENCE IS DERIVED, NEVER ASSERTED, and the reason is that it is the one the seat acts
6088
+ // on. `about` is built from three optional job keys and from owners found in the record, and
6089
+ // nothing guarantees any of them is present — so on a run where the exclusion found nothing, an
6090
+ // absolute claim that every mark was removed is false in exactly the state where a hit IS the mark.
6091
+ // Found in review, 2026-09-08, driven on a job carrying no marks.
6092
+ //
6093
+ // THE EMPTY STATE SAYS SO RATHER THAN GOING QUIET. Dropping the clause would leave the seat with no
6094
+ // reading of a fact that changes what it should do; telling it the mark was not excluded is more
6095
+ // useful than telling it nothing, and far more useful than telling it the opposite.
6096
+ // TWO EXCLUSIONS, TWO FACTS, AND ONLY ONE OF THEM PROTECTS THE MARK. Keying the reassurance on
6097
+ // marks ∪ owners was the first repair and it moved the defect rather than closing it: owners come
6098
+ // from the RECORD and marks from the JOB, so a record carrying thirteen owners and a job naming no
6099
+ // mark made the set non-empty, fired the reassurance, and told the seat no flag was the mark under
6100
+ // clearance over a flag that was exactly that. That mixed state is the LIKELIER one in production —
6101
+ // records carry owners; a job missing its marks is the unusual half. Found in review, 2026-09-08,
6102
+ // driven on the first repair's own head.
6103
+ const marks = about.marks ?? [], owners = about.owners ?? [];
6104
+ const ownerNote = owners.length ? ` The ${owners.length} owner name(s) from the record were also removed.` : "";
6105
+ const exclusionNote = marks.length
6106
+ ? `The ${marks.length} mark(s) this run is about were removed before reading, so none of these is a hit inside the name being cleared.${ownerNote}`
6107
+ : `THIS RUN NAMED NO MARK TO EXCLUDE, so the mark under clearance was NOT removed before reading — a flag below may BE that mark. Check each against the matter before rewriting it.${ownerNote}`;
6108
+ return lines(
6109
+ `PLAIN WORDS ON WHAT THE READER SEES FIRST: a deterministic read of this run's default-visible lines — the ones a client meets before opening anything — flagged the lines below. Treat each as a candidate FLAGGED CORRECTION [kind: narrative] and handle it exactly as you handle the reader-owned nouns above: quote the sentence and give the rewrite that keeps every fact. THIS IS EVIDENCE, NOT A VERDICT — judge each in context and pass over any where the word is the subject rather than the profession's shorthand. ${exclusionNote}`,
6110
+ ...hits,
6111
+ );
6112
+ } catch (e) {
6113
+ // Re-thrown, not swallowed: composeDispatchExtra notes it and records the id under `failed`, so an
6114
+ // unreadable record is visible on the receipt instead of looking like a clean run. A prompt block is
6115
+ // additive context and the composer already refuses to fail a dispatch over one.
6116
+ throw new Error(`plain-register pre-check: ${String(e?.message ?? e).slice(0, 120)}`);
6117
+ }
6118
+ }
6119
+
6015
6120
  // ── THE RECEIPT, AND THE THREE CLASSES, STATED ONCE ────────────────────────────────────────────────
6016
6121
  //
6017
6122
  //. The receipt this block tabulates is the answer to "did that search run", and until now exactly
@@ -6170,7 +6275,7 @@ function sentinel(runDir, name, obj) {
6170
6275
  * Best-effort throughout: a failure to settle must never stop the archive, because a run that cannot
6171
6276
  * archive is a much larger problem than a job with no row.
6172
6277
  */
6173
- export function settlePendingWhatIfsBeforeArchive(run) {
6278
+ export function settlePendingWhatIfsBeforeArchive(run) { // @internal
6174
6279
  let pending = [];
6175
6280
  // NOT a silent catch. This function exists because a job went unanswered with no row anywhere; a
6176
6281
  // failure to enumerate that returned quietly would reproduce exactly that, one level up, and the
@@ -6340,7 +6445,7 @@ function inScopeClassList(job, profile) {
6340
6445
  // account's default territories: the register plan swept seven countries for a search sold as
6341
6446
  // everywhere, and nothing anywhere disagreed. An empty list is the worldwide answer downstream
6342
6447
  // (register-plan.mjs treats emptiness as unrestricted), so the fix is the ladder, not a special case.
6343
- export function registerJurisdictions(job, profile) {
6448
+ export function registerJurisdictions(job, profile) { // @internal
6344
6449
  const list = resolveTerritories(job, profile).jurisdictions;
6345
6450
  return [...new Set((Array.isArray(list) ? list : []).map((x) => String(x ?? "").trim()).filter(Boolean))];
6346
6451
  }
@@ -6360,7 +6465,7 @@ export function registerJurisdictions(job, profile) {
6360
6465
  // every downstream message builder. Section missing on a fresh run ⇒ ONE warm save-only followup
6361
6466
  // (the grid-ledger-followup posture), then proceed with [] + a logged note — never-kill, replay-safe
6362
6467
  // (archived runs simply have no sidecar and all consumers falsy-skip).
6363
- export function parseIntakeAsks(matterContextMd) {
6468
+ export function parseIntakeAsks(matterContextMd) { // @internal
6364
6469
  const m = String(matterContextMd ?? "").match(/^###\s*Intake asks\s*\n([\s\S]*?)(?=^#{1,3}\s|$(?![\s\S]))/im);
6365
6470
  if (!m) return null; // section absent (legacy / model miss)
6366
6471
  const asks = [];
@@ -6528,7 +6633,7 @@ const DEFERRAL_AREA_ITEM_BUDGET = 48; // characters after "Follow-up / "
6528
6633
  /** Cut `s` to at most `max` characters at a WORD boundary, marking the cut with an explicit "…".
6529
6634
  * Trailing punctuation and whitespace are trimmed before the ellipsis so no heading ends "monitoring …"
6530
6635
  * or with a dangling bracket. Returns `s` unchanged when it already fits. PURE. */
6531
- export function clipToWord(s, max) {
6636
+ export function clipToWord(s, max) { // @internal
6532
6637
  const t = String(s ?? "").trim();
6533
6638
  if (t.length <= max) return t;
6534
6639
  const cut = t.slice(0, max);
@@ -6539,7 +6644,7 @@ export function clipToWord(s, max) {
6539
6644
 
6540
6645
  /** — ONE deferral's reader-visible coverage row. Exported so the shape a client reads is testable
6541
6646
  * without a run directory: injectDeferralCoverage below is the file-I/O wrapper around this. PURE. */
6542
- export function deferralCoverageRow(directive, reason) {
6647
+ export function deferralCoverageRow(directive, reason) { // @internal
6543
6648
  const full = plainDirective(directive);
6544
6649
  return {
6545
6650
  area: `Follow-up / ${clipToWord(full, DEFERRAL_AREA_ITEM_BUDGET)}`,
@@ -6625,7 +6730,7 @@ function coverageRowAreaFrom(axis, unit, unitText, scopeless) {
6625
6730
  return u.toLowerCase() === a.toLowerCase() ? `${unitText} ${scopeless}` : unitText;
6626
6731
  }
6627
6732
 
6628
- export function coverageRowArea(axis, unit) {
6733
+ export function coverageRowArea(axis, unit) { // @internal
6629
6734
  return coverageRowAreaFrom(axis, unit, String(unit ?? "").trim(), "(entire axis)");
6630
6735
  }
6631
6736
 
@@ -6634,14 +6739,14 @@ export function coverageRowArea(axis, unit) {
6634
6739
  // nothing downstream has to recognise an axis token inside a string it was handed — which is the
6635
6740
  // mechanism that ate the mark AXIS. null when the identifier is already plain English: three
6636
6741
  // driver injectors write areas like "Follow-up / …", and a label repeating them would be noise.
6637
- export function coverageRowAreaLabel(axis, unit) {
6742
+ export function coverageRowAreaLabel(axis, unit) { // @internal
6638
6743
  const u = String(unit ?? "").trim();
6639
6744
  const labelled = coverageUnitLabel(u);
6640
6745
  if (!u || labelled === u) return null;
6641
6746
  return coverageRowAreaFrom(axis, unit, labelled, "(all of it)");
6642
6747
  }
6643
6748
 
6644
- export function coverageJudgmentRows(ledgerRows, planExecution) {
6749
+ export function coverageJudgmentRows(ledgerRows, planExecution) { // @internal
6645
6750
  const open = [];
6646
6751
  for (const r of ledgerRows ?? []) {
6647
6752
  if (!r || String(r.status ?? "").toLowerCase() === "confirmed-clean") continue;
@@ -6671,7 +6776,7 @@ export function coverageJudgmentRows(ledgerRows, planExecution) {
6671
6776
  return rows.filter((r) => r.area && r.note);
6672
6777
  }
6673
6778
 
6674
- export function stampCoverageJudgmentRows(P, runDir, note, ctx) {
6779
+ export function stampCoverageJudgmentRows(P, runDir, note, ctx) { // @internal
6675
6780
  try {
6676
6781
  if (!existsSync(P.findings)) return;
6677
6782
  const doc = JSON.parse(readFileSync(P.findings, "utf8"));
@@ -6770,8 +6875,8 @@ function injectDeferralCoverage(P, runDir, note) {
6770
6875
  // The remedy now comes from products.mjs (NATIVE_LANGUAGE_REMEDY), which is where the offering's names
6771
6876
  // live and the one place that moves when the offering does. "at this level" goes with it: there is no
6772
6877
  // ladder for a level to sit on, and the honest subject is the search the client bought.
6773
- export const ZH_SCOPE_COVERAGE_AREA = "Chinese-script register equivalents (CN / HK / TW / MO)";
6774
- export const ZH_SCOPE_COVERAGE_NOTE = `Chinese-script same-meaning/phonetic register equivalents not searched on this search — ${NATIVE_LANGUAGE_REMEDY}`;
6878
+ export const ZH_SCOPE_COVERAGE_AREA = "Chinese-script register equivalents (CN / HK / TW / MO)"; // @internal
6879
+ export const ZH_SCOPE_COVERAGE_NOTE = `Chinese-script same-meaning/phonetic register equivalents not searched on this search — ${NATIVE_LANGUAGE_REMEDY}`; // @internal
6775
6880
  const WORLDWIDE_SCOPE_RE = /^(worldwide|global|all|all[- ]jurisdictions)$/i;
6776
6881
  /** What a synthesis-authored Stage-1.5 coverage row looks like when it has ALREADY made this
6777
6882
  * disclosure — see the suppression in injectScriptScopeCoverage. Both the current vocabulary and the
@@ -6781,7 +6886,7 @@ const SCRIPT_SCOPE_RECOMMENDATION_TOKENS = Object.freeze(["native-language inves
6781
6886
  /** The disclosure vocabulary for ONE candidate lane, derived (never tabulated). Returns
6782
6887
  * `{area, note, territories, marker}` — `marker` is the lowercased script prefix the suppression
6783
6888
  * check keys on. Null for a lane with no LANGUAGE_LANES spec or no territory routed to it. PURE. */
6784
- export function scriptScopeDisclosure(lane) {
6889
+ export function scriptScopeDisclosure(lane) { // @internal
6785
6890
  const spec = LANGUAGE_LANES[lane];
6786
6891
  if (!spec) return null;
6787
6892
  const prefix = String(spec.label ?? "").replace(/\s*deepening\s*$/i, "").trim(); // "Chinese-script"
@@ -6801,7 +6906,7 @@ export function scriptScopeDisclosure(lane) {
6801
6906
  * `laneDepthOff`: customer config always wins (the golden rule) — a customer who configured
6802
6907
  * jxPolicy.laneDepth.zh "off" has already declined the lane; re-advertising it on every report
6803
6908
  * would nag against their own config. */
6804
- export function decideScriptScopeHonesty({ lane = "zh", scope = [], laneRan = false, laneDepthOff = false } = {}) {
6909
+ export function decideScriptScopeHonesty({ lane = "zh", scope = [], laneRan = false, laneDepthOff = false } = {}) { // @internal
6805
6910
  if (laneRan || laneDepthOff) return null;
6806
6911
  const d = scriptScopeDisclosure(lane);
6807
6912
  if (!d) return null;
@@ -6817,7 +6922,7 @@ export function decideScriptScopeHonesty({ lane = "zh", scope = [], laneRan = fa
6817
6922
 
6818
6923
  /** The zh-bound form, kept because it is the name the existing callers and tests use. Delegates —
6819
6924
  * there is one decision, not two. PURE. */
6820
- export function decideZhScopeHonesty(opts = {}) {
6925
+ export function decideZhScopeHonesty(opts = {}) { // @internal
6821
6926
  return decideScriptScopeHonesty({ ...opts, lane: "zh" });
6822
6927
  }
6823
6928
 
@@ -6838,7 +6943,7 @@ export function decideZhScopeHonesty(opts = {}) {
6838
6943
  * run whose units never executed; keeping a leg on a variable nothing sets any more would read false
6839
6944
  * forever and tell every client the lane did not run, including the runs where it did. So the legs
6840
6945
  * track the switches that SURVIVE, which is what "mirrors the jx-units gating legs" has to mean. */
6841
- export function scriptLaneRanOnRun(runDir, lane, { searchPolicy = null, env = process.env } = {}) {
6946
+ export function scriptLaneRanOnRun(runDir, lane, { searchPolicy = null, env = process.env } = {}) { // @internal
6842
6947
  if (!searchPolicy?.components?.jxLanes) return false;
6843
6948
  if (!laneArmed(lane, env)) return false; // — the shared fail-open reader
6844
6949
  let sidecar = null;
@@ -6872,7 +6977,7 @@ export function scriptLaneRanOnRun(runDir, lane, { searchPolicy = null, env = pr
6872
6977
  }
6873
6978
 
6874
6979
  /** The zh-bound form, kept for the existing callers and tests. PURE apart from the sidecar read. */
6875
- export function zhLaneRanOnRun(runDir, opts = {}) {
6980
+ export function zhLaneRanOnRun(runDir, opts = {}) { // @internal
6876
6981
  return scriptLaneRanOnRun(runDir, "zh", opts);
6877
6982
  }
6878
6983
 
@@ -6880,7 +6985,7 @@ export function zhLaneRanOnRun(runDir, opts = {}) {
6880
6985
  * discipline, same "the reader always gets the row" purpose. Idempotent on resume: the row is keyed
6881
6986
  * by its area, and a coverage row that already discloses the Stage-1.5 recommendation (a synthesis
6882
6987
  * that weighed it in on a re-run) suppresses the injection rather than duplicating it. */
6883
- export function injectScriptScopeCoverage(P, runDir, note, { searchPolicy = null, job = null, profile = null, env = process.env, lanes = Object.keys(LANGUAGE_LANES) } = {}) {
6988
+ export function injectScriptScopeCoverage(P, runDir, note, { searchPolicy = null, job = null, profile = null, env = process.env, lanes = Object.keys(LANGUAGE_LANES) } = {}) { // @internal
6884
6989
  try {
6885
6990
  if (!existsSync(P.findings)) return;
6886
6991
  const scope = jxScopeJurisdictions(job ?? {}, profile ?? {});
@@ -6929,7 +7034,7 @@ export function injectScriptScopeCoverage(P, runDir, note, { searchPolicy = null
6929
7034
  }
6930
7035
 
6931
7036
  /** The zh-only form, kept because it is the name the existing tests use. One writer, one lane. */
6932
- export function injectZhScopeCoverage(P, runDir, note, opts = {}) {
7037
+ export function injectZhScopeCoverage(P, runDir, note, opts = {}) { // @internal
6933
7038
  return injectScriptScopeCoverage(P, runDir, note, { ...opts, lanes: ["zh"] });
6934
7039
  }
6935
7040
 
@@ -6951,7 +7056,7 @@ export function injectZhScopeCoverage(P, runDir, note, opts = {}) {
6951
7056
  * must not manufacture a disclosure either).
6952
7057
  *
6953
7058
  * Same posture as its two siblings: never-kill, re-validate, atomic write, idempotent by area. */
6954
- export function injectLaneDepthCoverage(P, runDir, note) {
7059
+ export function injectLaneDepthCoverage(P, runDir, note) { // @internal
6955
7060
  try {
6956
7061
  if (!existsSync(P.findings)) return;
6957
7062
  let sidecar = null;
@@ -6996,7 +7101,7 @@ export function injectLaneDepthCoverage(P, runDir, note) {
6996
7101
  // crash between the gate and delivery. This reader prefers the in-process ctx rows (this session
6997
7102
  // produced them); the sidecar is the resume shape — a pass that reaches the coverage floor without
6998
7103
  // having re-entered the gate still owes the clamp. Exported for the unit tests.
6999
- export function loadScreenGateUnresolved(runDir, ctx = {}) {
7104
+ export function loadScreenGateUnresolved(runDir, ctx = {}) { // @internal
7000
7105
  if (Array.isArray(ctx.screenGateUnresolved) && ctx.screenGateUnresolved.length) return ctx.screenGateUnresolved;
7001
7106
  try {
7002
7107
  const rows = JSON.parse(readFileSync(driverDir(runDir, "screen-gate-unresolved.json"), "utf8"))?.unresolved;
@@ -7011,7 +7116,7 @@ export function loadScreenGateUnresolved(runDir, ctx = {}) {
7011
7116
  * screenGateGap arm reading the same ctx/sidecar set. This function only makes that disclosure
7012
7117
  * legible on the report. Idempotent by mark+uri (the area string carries both), so a resume or a
7013
7118
  * second injection pass never duplicates a row. Exported for the unit tests. */
7014
- export function injectScreenGateCoverage(P, runDir, note, ctx = {}) {
7119
+ export function injectScreenGateCoverage(P, runDir, note, ctx = {}) { // @internal
7015
7120
  try {
7016
7121
  if (!existsSync(P.findings)) return;
7017
7122
  const unresolved = loadScreenGateUnresolved(runDir, ctx);
@@ -7157,14 +7262,14 @@ const softNorm = (s) => String(s ?? "").normalize("NFD").replace(/[̀-ͯ]/g, "")
7157
7262
  * So the guard that catches the next one walks THIS list against what actually reaches a seat, and a
7158
7263
  * section joins the list by the same act that makes it code-built: its builder returning one of these.
7159
7264
  */
7160
- export const CODE_BUILT_SECTIONS = Object.freeze({
7265
+ export const CODE_BUILT_SECTIONS = Object.freeze({ // @internal
7161
7266
  onlyYou: "### Only you can close these",
7162
7267
  reviewerOpenPoints: "### Reviewer's open questions",
7163
7268
  askAnswers: "### Answers to your instructions",
7164
7269
  reasonedNegatives: "# Reasoned negatives",
7165
7270
  });
7166
7271
 
7167
- export function buildOnlyYouSection(actions, findings, { nowMs = Date.now(), withinDays = 60, graceDays = 14 } = {}) {
7272
+ export function buildOnlyYouSection(actions, findings, { nowMs = Date.now(), withinDays = 60, graceDays = 14 } = {}) { // @internal
7168
7273
  const { conditionActions, advisoryActions } = deriveActionConditions(actions, findings);
7169
7274
  // ── PR-3 (report voice), CORRECTED BY — WHAT THE SUBJECT JOIN DOES AND DOES NOT GUARANTEE ───
7170
7275
  //
@@ -7340,7 +7445,7 @@ export function buildOnlyYouSection(actions, findings, { nowMs = Date.now(), wit
7340
7445
  // pass, be worked, and leave the report unchanged — and the client then reads a delivered report with
7341
7446
  // no sign that the reviewer objected to something nobody fixed.
7342
7447
  //
7343
- // Put to Krzys as the client outcome, with options. His answer, verbatim: PRINT THEM, ANY VERDICT.
7448
+ // Decided as the client outcome, with options put first: print them, on any verdict.
7344
7449
  // So the set is no longer chosen by the verdict. It is:
7345
7450
  //
7346
7451
  // BLOCKING every ground the reviewer cites — unchanged, the reviewer refused to sign
@@ -7366,7 +7471,7 @@ export function buildOnlyYouSection(actions, findings, { nowMs = Date.now(), wit
7366
7471
  // impossible, and rendering nothing would ship a report whose body reads as reviewed while the reviewer
7367
7472
  // refused. Silence is the one thing the section exists to prevent. The wording is the sidecar's own,
7368
7473
  // already carried at the degenerate branch above — one sentence for one fact, in both places.
7369
- export function buildReviewerOpenPointsSection(reviewMd, appliedRows = null) {
7474
+ export function buildReviewerOpenPointsSection(reviewMd, appliedRows = null) { // @internal
7370
7475
  const blocking = parseVerdict(reviewMd) === "BLOCKING";
7371
7476
  const cited = blocking ? parseCorrections(reviewMd) : [];
7372
7477
  const unfixed = unresolvedFlags(appliedRows);
@@ -7447,7 +7552,7 @@ export function buildReviewerOpenPointsSection(reviewMd, appliedRows = null) {
7447
7552
  // the lint judges), so the answer the client reads and the answer the lint verifies are one record.
7448
7553
  // Frozen-intake order leads (the requester's own sequence); answers that join no frozen ask follow in
7449
7554
  // register order (an answer synthesis chose to give is never dropped). Returns "" when no answers.
7450
- export function buildAskAnswersSection(askAnswers, intakeAsks) {
7555
+ export function buildAskAnswersSection(askAnswers, intakeAsks) { // @internal
7451
7556
  const entries = (Array.isArray(askAnswers) ? askAnswers : [])
7452
7557
  .filter((a) => a && typeof a.ask === "string" && a.ask.trim() && typeof a.answer === "string" && a.answer.trim());
7453
7558
  if (!entries.length) return "";
@@ -7539,7 +7644,7 @@ export function buildAskAnswersSection(askAnswers, intakeAsks) {
7539
7644
  * This section itself is untouched by the ladder: the grouping is not extended and not re-keyed. 's
7540
7645
  * graded entries render in a SIBLING section (buildGradedEntriesSection) using the same line grammar.
7541
7646
  */
7542
- export function buildReasonedNegativesSection(findings) {
7647
+ export function buildReasonedNegativesSection(findings) { // @internal
7543
7648
  const { total, groups } = reasonedNegativeGroups(findings ?? []);
7544
7649
  // ZERO IS NOT ABSENCE — the same rule the HTML section states. A run that grouped and found none says
7545
7650
  // so, so a reader never has to guess whether there were no negatives or the grouping never ran.
@@ -7560,7 +7665,7 @@ export function buildReasonedNegativesSection(findings) {
7560
7665
  return `${CODE_BUILT_SECTIONS.reasonedNegatives}\n\n${lines.join("\n\n")}`;
7561
7666
  }
7562
7667
 
7563
- export function assembleReportMd(P, findings, cardOrdinals, { grouped = [], byRight = false } = {}) {
7668
+ export function assembleReportMd(P, findings, cardOrdinals, { grouped = [], byRight = false } = {}) { // @internal
7564
7669
  const overviewRaw = existsSync(P.reportOverview) ? readFileSync(P.reportOverview, "utf8") : "---\n---\n";
7565
7670
  let overview = overviewRaw.split(/^#\s+Marks\b/m)[0].replace(/\s*$/, ""); // defensive: overview owns down to # Marks
7566
7671
  // PR-9 (Levels) — the caption budget, enforced at assembly: overall_caption clipped at 3 sentences,
@@ -7778,7 +7883,7 @@ export function assembleReportMd(P, findings, cardOrdinals, { grouped = [], byRi
7778
7883
  // Mechanics live in slot-lock.mjs (shared with the WS-C turn cap): pid:nonce tokens, ATOMIC stale
7779
7884
  // reclaim, ownership-verified release — the old read-then-rm reclaim had a TOCTOU two concurrent
7780
7885
  // acquirers (legal under cap 3) could use to end up sharing a slot. Returns a handle {slot, token}.
7781
- export async function acquireRunSlot(agent = null) {
7886
+ export async function acquireRunSlot(agent = null) { // @internal
7782
7887
  // — one read, through the config getter. This line used to read `process.env`
7783
7888
  // first and fall through `config.maxConcurrentRuns || 1`, which READ as a third default and could
7784
7889
  // never produce one: the getter it fell through returns either a number >= 1 or NaN, and NaN is
@@ -7830,7 +7935,7 @@ function reconcilePassStamps(runRef, ctx) {
7830
7935
  // — the live slot, exposed so the CLI's unsettled-run net can release it. `pipeline`'s own
7831
7936
  // `finally` is the normal path and is unchanged; this is only reachable when that finally never runs,
7832
7937
  // which is exactly the case a deadlock produces.
7833
- export let liveRunSlot = null;
7938
+ export let liveRunSlot = null; // @internal
7834
7939
 
7835
7940
  /**
7836
7941
  * — WHY THIS RESUME MUST NOT HAPPEN, OR null.
@@ -7849,7 +7954,7 @@ export let liveRunSlot = null;
7849
7954
  * delivery markers it found, and it refuses for a different reason (a duplicate report, not a
7850
7955
  * countermanded decision). Two refusals, two messages a reader can act on.
7851
7956
  */
7852
- export function resumeStopRefusal(runDir) {
7957
+ export function resumeStopRefusal(runDir) { // @internal
7853
7958
  if (!runDir) return null;
7854
7959
  if (isCancelled(runDir)) return "an operator asked it to stop (.cancel present)";
7855
7960
  // ── CANCELLED ONLY, AND THE FIRST CUT OF THIS WAS WRONG ────────────────────────────────────────
@@ -7961,7 +8066,7 @@ export function stageWallFields(tDispatch, tSettled = Date.now()) {
7961
8066
  };
7962
8067
  }
7963
8068
 
7964
- export function journalStageInputs(paths = [], { reads = null, readsTruncated = null, warm = false } = {}) {
8069
+ export function journalStageInputs(paths = [], { reads = null, readsTruncated = null, warm = false } = {}) { // @internal
7965
8070
  const readSet = Array.isArray(reads) ? new Set(reads) : null;
7966
8071
  // A-1 — `followup` was an arm of this predicate and is not any more. It encoded the same false premise
7967
8072
  // the composer above fixes: that a followup is a resumed session whose files were not re-offered. It is
@@ -7999,7 +8104,7 @@ export function journalStageInputs(paths = [], { reads = null, readsTruncated =
7999
8104
  // run) — they are append-only and the LAST row is the run's outcome; the earlier ones are the honest record
8000
8105
  // of how long each leg took. HOURS ONLY: the tokens-only directive holds and no currency appears here.
8001
8106
  // Best-effort telemetry — this must never affect a delivery, a failure notice or a park.
8002
- export function logTurnaroundReconciliation(runDir, quote, state) {
8107
+ export function logTurnaroundReconciliation(runDir, quote, state) { // @internal
8003
8108
  if (!runDir) return null;
8004
8109
  try {
8005
8110
  let startedAt = null;
@@ -15192,7 +15297,7 @@ function resolveRun(job, opts) {
15192
15297
 
15193
15298
  // Rebuild the ctx a single stage needs WITHOUT re-running upstream: axes from the persisted manifest, verdict
15194
15299
  // from status.json, publishedUrl from .published. (Mirrors what pipeline() accumulates mid-run.)
15195
- export function reconstructCtx(job, opts) {
15300
+ export function reconstructCtx(job, opts) { // @internal
15196
15301
  const run = resolveRun(job, opts);
15197
15302
  const P = paths(run.runDir);
15198
15303
  // A KNOCKOUT run has none of the clearance stages this tooling drives — and letting it through would
@@ -15343,7 +15448,7 @@ function snapshotOutputs(ctx, name, reason) {
15343
15448
  //
15344
15449
  // Returns null when there is nothing recorded to repair — the caller then resumes as it always has, so
15345
15450
  // this is an accelerator that can never become a requirement.
15346
- export async function repairStale(job, opts = {}) {
15451
+ export async function repairStale(job, opts = {}) { // @internal
15347
15452
  const ctx = reconstructCtx(job, opts);
15348
15453
  const P = ctx.paths;
15349
15454
  let rec = null;
@@ -15396,9 +15501,9 @@ export async function repairStale(job, opts = {}) {
15396
15501
  * built and an arm that legitimately holds no tools are opposite facts, and `{groups: []}` for both
15397
15502
  * would be the same absence-read-as-pass the rest of this file spends its comments on.
15398
15503
  */
15399
- export const dispatchLabel = (name, axis) => name + (axis ? `:${axis}` : "");
15504
+ export const dispatchLabel = (name, axis) => name + (axis ? `:${axis}` : ""); // @internal
15400
15505
 
15401
- export function experimentWiring(name, axis, { sessionKey, agent, runDir } = {}) {
15506
+ export function experimentWiring(name, axis, { sessionKey, agent, runDir } = {}) { // @internal
15402
15507
  const label = dispatchLabel(name, axis);
15403
15508
  let groups;
15404
15509
  try { groups = experimentToolGroups(label); }
@@ -15450,7 +15555,7 @@ function experimentEngineName() {
15450
15555
  * The cap is deliberately far above any real number of concurrent draws, because this lock exists to be
15451
15556
  * SEEN and never to ration. A draw that blocked here would be a new failure mode in place of an old one.
15452
15557
  */
15453
- export async function runExperiment(job, opts) {
15558
+ export async function runExperiment(job, opts) { // @internal
15454
15559
  const lock = await acquireSlot({ dir: config.runLockDir, cap: 1024, prefix: "draw" });
15455
15560
  try {
15456
15561
  return await runExperimentInner(job, opts);
@@ -15765,7 +15870,7 @@ const RETIRED_FLAGS = {
15765
15870
  };
15766
15871
 
15767
15872
  // The refusal for the first retired flag in argv, or null. Pure: the CLI block prints it and exits 2.
15768
- export function retiredFlagRefusal(argv) {
15873
+ export function retiredFlagRefusal(argv) { // @internal
15769
15874
  for (const arg of argv) if (Object.hasOwn(RETIRED_FLAGS, arg)) return `error: ${arg} was deleted — ${RETIRED_FLAGS[arg]}`;
15770
15875
  return null;
15771
15876
  }
@@ -15832,7 +15937,7 @@ export function retiredEnvWarnings(env = process.env) {
15832
15937
  //
15833
15938
  // ABSOLUTE PATHS on purpose: this line is read hours later, possibly from a different directory, and a
15834
15939
  // relative path that silently resolves somewhere else would be a worse answer than no line at all.
15835
- export function resumeCommand({ script, jobPath, codename, agent = null }) {
15940
+ export function resumeCommand({ script, jobPath, codename, agent = null }) { // @internal
15836
15941
  if (!script || !jobPath || !codename) return null;
15837
15942
  return `node ${script} --job ${jobPath}${agent ? ` --agent ${agent}` : ""} --resume ${codename}`;
15838
15943
  }
@@ -15851,7 +15956,7 @@ export function resumeCommand({ script, jobPath, codename, agent = null }) {
15851
15956
  // And where NO identity exists yet (the door preflights: tier sanity, engine binary, register credential,
15852
15957
  // an unresolvable resume codename), the honest line says there is nothing to resume rather than printing a
15853
15958
  // command with a hole in it.
15854
- export function resumeAdvice({ result = null, error = null, signal = null, script = null, jobPath = null, agent = null, codename = null, experiment = false, noResume = false } = {}) {
15959
+ export function resumeAdvice({ result = null, error = null, signal = null, script = null, jobPath = null, agent = null, codename = null, experiment = false, noResume = false } = {}) { // @internal
15855
15960
  if (result?.ok) return [];
15856
15961
  if (experiment) return [];
15857
15962
  if (noResume || error?.noResume) return [];