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.
- package/.env.example +36 -37
- package/CONTRIBUTING.md +8 -4
- package/INSTALL.md +24 -4
- package/README.md +7 -6
- package/bin/example.mjs +6 -5
- package/bin/onboard.mjs +175 -9
- package/bin/start.mjs +66 -4
- package/build-info.json +2 -2
- package/demo/README.md +1 -1
- package/docs/GLOSSARY.md +85 -0
- package/docs/README.md +1 -0
- package/docs/architecture/01-product-overview.md +21 -9
- package/docs/architecture/05-config-governance.md +5 -0
- package/docs/decisions/0006-what-the-public-repository-carries.md +30 -5
- package/driver/CHANGELOG.md +34 -0
- package/driver/README.md +25 -6
- package/driver/connotation-search.mjs +1 -1
- package/driver/contract-audit.mjs +5 -1
- package/driver/contract-e3-baseline.json +11 -11
- package/driver/doubt-selection.mjs +1 -1
- package/driver/drainer-identity.mjs +1 -1
- package/driver/effort-model.mjs +2 -2
- package/driver/engine/probe.mjs +45 -5
- package/driver/gateway.mjs +2 -2
- package/driver/outbox-backoff.mjs +1 -1
- package/driver/package.json +1 -1
- package/driver/pipeline.mjs +206 -101
- package/driver/plain-register.mjs +16 -2
- package/driver/portal-config-view.mjs +30 -1
- package/driver/portal-local-auth.mjs +5 -1
- package/driver/portal-service.mjs +53 -2
- package/driver/predelivery-lint.mjs +54 -25
- package/driver/publish/render.mjs +109 -14
- package/driver/search-policy.mjs +1 -1
- package/driver/stage-context.mjs +13 -0
- package/driver/stages.mjs +51 -4
- package/driver/suite-census.json +97 -31
- package/driver/systemd/clearotron-worker.service +3 -3
- package/driver/tokens.mjs +1 -1
- package/driver/unit-inventory.mjs +34 -4
- package/mcp-server/CHANGELOG.md +2 -0
- package/mcp-server/package.json +1 -1
- package/package.json +4 -10
- package/portal-ui/dist/assets/{index-CEYvXdqH.js → index-KFAHMgdT.js} +73 -34
- package/portal-ui/dist/index.html +1 -1
- package/portal-ui/package.json +1 -1
- package/providers/oauth-mcp-bridge/CHANGELOG.md +2 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/scripts/added-reference-check.mjs +45 -89
- package/scripts/e2e.mjs +2 -2
- package/scripts/generated-files-are-current.mjs +125 -0
- package/scripts/mint-names-in-force.mjs +4 -2
- package/scripts/mint-public-residue.mjs +74 -0
- package/scripts/mint-reference-strip-backlog.mjs +12 -1
- package/scripts/mint-suite-census.mjs +5 -2
- package/scripts/render-check.mjs +13 -2
- package/scripts/report-frame-check.mjs +8 -1
- package/scripts/report-screenshot.mjs +6 -3
- package/scripts/revisit-render-check.mjs +6 -3
- package/scripts/score.mjs +1 -1
- package/scripts/strip-tracker-citations.mjs +9 -1
- package/scripts/test-full.mjs +226 -0
- package/shared/README.md +2 -1
- package/shared/browser-temp-root.mjs +142 -0
- package/shared/checkout-move.mjs +1 -1
- package/shared/client-door.mjs +4 -3
- package/shared/identifier-scan.mjs +1 -1
- package/shared/install-auth.mjs +35 -0
- package/shared/invocation.mjs +5 -1
- package/shared/listen.mjs +55 -3
- package/shared/names-in-force.mjs +4 -1
- package/shared/os-advice.mjs +91 -0
- package/shared/reap-on-exit.mjs +42 -0
- package/shared/reference-guard-classes.mjs +351 -0
- package/shared/suite-census.mjs +31 -3
- package/shared/withheld-paths-access.mjs +36 -18
package/driver/pipeline.mjs
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
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
|
-
//
|
|
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 [];
|