clearotron 0.4.1-beta.0 → 0.4.1-beta.2
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/THIRD-PARTY-NOTICES.md +1 -1
- package/bin/README.md +1 -1
- package/bin/clearotron.mjs +2 -0
- package/bin/mcp.mjs +80 -0
- package/bin/start.mjs +14 -1
- package/build-info.json +2 -2
- package/demo/README.md +1 -1
- package/docs/architecture/04-configuration-reference.md +0 -1
- package/docs/architecture/06-operations-runbook.md +4 -3
- package/docs/architecture/08-development-guide.md +3 -1
- package/driver/CHANGELOG.md +17 -0
- package/driver/citation-census.json +3 -3
- package/driver/compare.mjs +1 -1
- package/driver/contract-audit.mjs +6 -6
- package/driver/contract-dictation-registry.mjs +1 -1
- package/driver/contract-e3-backlog.mjs +17 -16
- package/driver/contract-vocabulary.mjs +138 -125
- package/driver/declination-call.mjs +5 -1
- package/driver/dev-portal.mjs +2 -1
- package/driver/engine/mcp/codex-config.mjs +7 -2
- package/driver/engine/mcp/gather-config.mjs +4 -0
- package/driver/engine/mcp/recording-server.mjs +1 -1
- package/driver/engine/mcp/supplemental.mjs +26 -1
- package/driver/engine/openai-agent.mjs +13 -3
- package/driver/findings-model.mjs +80 -13
- package/driver/flag-snapshot.mjs +2 -1
- package/driver/foreign-record-links.mjs +50 -0
- package/driver/frame-diff-model.mjs +1 -1
- package/driver/gateway.mjs +4 -4
- package/driver/jx.mjs +1 -1
- package/driver/knockout-review-record.mjs +55 -1
- package/driver/named-band.mjs +2 -0
- package/driver/owner-screen.mjs +7 -4
- package/driver/package.json +1 -1
- package/driver/pipeline-knockout.mjs +14 -12
- package/driver/pipeline.mjs +118 -20
- package/driver/portal-service.mjs +5 -4
- package/driver/products.mjs +1 -1
- package/driver/profiles.mjs +4 -3
- package/driver/publish/publish-inputs.mjs +2 -2
- package/driver/publish/xlsx.mjs +1 -1
- package/driver/register-count.mjs +2 -2
- package/driver/register-coverage.mjs +1 -1
- package/driver/register-plan.mjs +13 -2
- package/driver/result-noun-fields.mjs +3 -3
- package/driver/scope-rules.mjs +2 -2
- package/driver/stage-context.mjs +9 -0
- package/driver/stages-knockout.mjs +6 -5
- package/driver/stages.mjs +23 -23
- package/driver/suite-census.json +97 -31
- package/driver/synthesis-record.mjs +14 -5
- package/driver/verify.mjs +1 -1
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/CONNECT.md +9 -3
- package/mcp-server/demo-mode.mjs +10 -0
- package/mcp-server/lib/runs.mjs +7 -1
- package/mcp-server/lib/scrub.mjs +1 -1
- package/mcp-server/package.json +1 -1
- package/mcp-server/packs/README.md +1 -1
- package/mcp-server/server.mjs +16 -2
- package/package.json +3 -2
- package/portal-ui/package.json +3 -3
- package/providers/_shared/count.mjs +5 -1
- package/providers/_shared/enumerate.mjs +66 -21
- package/providers/_shared/execute-plan.mjs +13 -4
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/signa/src/capabilities.js +15 -0
- package/providers/signa/src/core.js +55 -26
- package/scripts/e2e-first-time.mjs +3 -3
- package/scripts/env-audit.mjs +3 -2
- package/scripts/freeze-example-run.mjs +8 -8
- package/scripts/mcp-registry-listing.mjs +199 -0
- package/scripts/mint-plugin-folder.mjs +65 -0
- package/scripts/release-version.mjs +44 -0
- package/scripts/score.mjs +1 -1
- package/shared/register-floor.mjs +19 -0
- package/shared/trigger-lane.mjs +1 -1
- package/skills/clearotron-ops/SKILL.md +81 -24
package/driver/pipeline.mjs
CHANGED
|
@@ -45,7 +45,7 @@ import { parseCoverageLedgerJson, parseCoverageLedgerFull, deriveCoverageStatus,
|
|
|
45
45
|
import { receiptSettled, readEnvelopeDecision, settleReceipt, settledDeferralsSection, readStickyGaps } from "./envelope-settle.mjs";
|
|
46
46
|
import { readRegisterTaint, readActiveTaintAxes } from "./register-taint.mjs";
|
|
47
47
|
import { parseNamedBand, mergeNamedBands, findCollapsedBands, quarantineUnknownStates, taintQuarantineCleanBlocks, bandRecords } from "./named-band.mjs";
|
|
48
|
-
import { recordOriginsFor } from "./record-origins.mjs";
|
|
48
|
+
import { recordOriginsFor, activeRecordOrigins } from "./record-origins.mjs"; import { recordBlanking, FOREIGN_HOST_TOKEN } from "./foreign-record-links.mjs";
|
|
49
49
|
import { REGISTER_PROVIDER } from "./driver.config.mjs";
|
|
50
50
|
import { noteRegisterServed, registersServedFrom, providerUsageCaveat } from "./register-served.mjs"; // which registers actually served this run — noted eagerly from the dispatch's own resolver, and reconciled at publish against the ledger rows, which carry the vendor per call
|
|
51
51
|
import { FACTS_FILE as DIGEST_FACTS_FILE, ACCOUNTING_STAMP as DIGEST_ACCOUNTING_STAMP, recordedFindingUris,
|
|
@@ -72,7 +72,7 @@ import { classifyGroundsNote } from "./grounds-grammar.mjs"; // — a charged
|
|
|
72
72
|
// — the register coverage form: the driver writes it before the digest dispatches, renders the
|
|
73
73
|
// `## Coverage ledger` table and the machine ledger FROM it after the pass, and unions it across passes.
|
|
74
74
|
import { documentCoverage, renderDocumentCoverageSection, spliceDocumentCoverage } from "./document-coverage.mjs"; //
|
|
75
|
-
import { buildCoverageAbsenceForm, coverageAbsenceGaps, coverageFormAbsence, coverageFormBrief, renderCoverageAbsenceSection, renderCoverageLedgerSection, spliceCoverageLedger, renderCoverageLedgerJsonFromForm } from "./coverage-form.mjs";
|
|
75
|
+
import { buildCoverageAbsenceForm, coverageAbsenceGaps, coverageFormAbsence, coverageFormBrief, renderCoverageAbsenceSection, renderCoverageLedgerSection, spliceCoverageLedger, renderCoverageLedgerJsonFromForm, unitLabel } from "./coverage-form.mjs";
|
|
76
76
|
import { unionCoverageForm } from "./coverage-union.mjs";
|
|
77
77
|
import { armCoverageForm, coverageFormInput, coverageFormPaths, coverageFormStamp, readCoverageForm, readCoverageFormInput, waitingFamilyStates, writeCoverageForm } from "./coverage-form-io.mjs";
|
|
78
78
|
import { releasedFamilyQids, readWithheldFamilies } from "./withheld-families.mjs"; // the waiting families the reading turn released join as dictated entries
|
|
@@ -163,7 +163,7 @@ import { parsePlacementsJson } from "./placement-model.mjs"; // B2 — the str
|
|
|
163
163
|
import { readAnchors } from "./anchor-reader.mjs";
|
|
164
164
|
import { findEngagementReceipts } from "./engagement-receipt.mjs";
|
|
165
165
|
import { plainRegisterFlags } from "./plain-register.mjs";
|
|
166
|
-
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";
|
|
166
|
+
import { parseFindingsJson, parseFindingsJsonLenient, consolidateFindings, deriveDisplayVerdict, bindRecommendation, compareBlockingPower, inDispositionMode, DISPOSITION_GROUP, deriveActionConditions, cardedParties, actionPartyReferences, quarantinedConditionRows, salvageRepairTargets, riskStatement, verdictStance, remapActionOrdinals, joinAskToAnswer, stripAskLabel, bandBorderlineDeclarations, reasonedNegativeGroups, blankForeignRecordLinks } from "./findings-model.mjs";
|
|
167
167
|
import { foldCaption, foldCardRead } from "./card-budget.mjs";
|
|
168
168
|
// S2 — the report card's mechanical frame, composed from the record instead of dictated (see below).
|
|
169
169
|
import { carriesOwnFrame, composeCard } from "./card-frame.mjs";
|
|
@@ -3934,7 +3934,7 @@ export function findFloorBreaches(ledger, floorAxes) { // @internal
|
|
|
3934
3934
|
* `[]`: no manifest, unreadable, unparseable. That is the honest default here and not an absence read as
|
|
3935
3935
|
* a pass, because the whole mechanism is opt-in — a run with no designation owes no floor, and a run whose
|
|
3936
3936
|
* manifest cannot be read has no designation to honour. The refusal for an absent or unparseable manifest
|
|
3937
|
-
* belongs to the stage that writes it and already exists there — verify.mjs
|
|
3937
|
+
* belongs to the stage that writes it and already exists there — validators.variantManifest in verify.mjs runs the same parser
|
|
3938
3938
|
* through `checkSiblingJson` and fails clearance-variants with `variantmodel_missing`. Checked, because
|
|
3939
3939
|
* "something else refuses it" is exactly the assumption that turns a swallowed error into a silent pass.
|
|
3940
3940
|
*/
|
|
@@ -4803,7 +4803,7 @@ async function stage(name, ctx, opts = {}) {
|
|
|
4803
4803
|
let wedgeCycles = 0;
|
|
4804
4804
|
for (;;) {
|
|
4805
4805
|
const r = await stageWithChain(name, ctx, opts);
|
|
4806
|
-
if (r.ok || r.fail !== "lane_wedge" || wedgeCycles >= LANE_WEDGE_CHAIN_RETRIES) { sweepStrayArtifacts(ctx, name); return r; }
|
|
4806
|
+
if (r.ok || r.fail !== "lane_wedge" || wedgeCycles >= LANE_WEDGE_CHAIN_RETRIES) { sweepStrayArtifacts(ctx, name); await afterLateSynthesisSave(name, ctx, r); return r; }
|
|
4807
4807
|
wedgeCycles++;
|
|
4808
4808
|
note(`[${name}] command-lane wedge — the stage timed out with zero progress (saturated lane). Waiting ${Math.round(LANE_WEDGE_BACKOFF_MS / 1000)}s for it to clear, then re-dispatching (${wedgeCycles}/${LANE_WEDGE_CHAIN_RETRIES}); full per-attempt timeouts preserved.`);
|
|
4809
4809
|
try { runLog(ctx.paths.runDir, { event: "lane-wedge-retry", stage: name + (ctx.axis ? `:${ctx.axis}` : ""), cycle: wedgeCycles, max: LANE_WEDGE_CHAIN_RETRIES }); } catch { /* telemetry best-effort */ }
|
|
@@ -5035,7 +5035,7 @@ export function buildFailurePacket({ runId, agent, job = {}, failedStage, shortR
|
|
|
5035
5035
|
// a top-level defect, or nothing salvageable — fails the run exactly as before. One bad object never silently
|
|
5036
5036
|
// suppresses a real conflict, and never silently kills a ~$40 run.
|
|
5037
5037
|
async function quarantineSynth(r, ctx, name) {
|
|
5038
|
-
if (r.ok) return r;
|
|
5038
|
+
if (r.ok) return r; if (foreignRecordLinksBlanked(r, ctx, name)) return { ...r, ok: true, fail: undefined, repaired: "foreign-record-links-blanked" };
|
|
5039
5039
|
// A6: a max_tokens-named content fault wraps the underlying validator token — strip the wrapper so a
|
|
5040
5040
|
// per-finding shape defect on a ceiling-cut turn still reaches the lenient-salvage lane.
|
|
5041
5041
|
const fail = String(r.fail || "").replace(/^max_tokens_no_output:/, "");
|
|
@@ -7028,7 +7028,7 @@ export function coverageRowAreaLabel(axis, unit) { // @internal
|
|
|
7028
7028
|
return coverageRowAreaFrom(axis, unit, labelled, "(all of it)");
|
|
7029
7029
|
}
|
|
7030
7030
|
|
|
7031
|
-
export function coverageJudgmentRows(ledgerRows, planExecution) { // @internal
|
|
7031
|
+
export function coverageJudgmentRows(ledgerRows, planExecution, plan = null) { // @internal
|
|
7032
7032
|
const open = [];
|
|
7033
7033
|
for (const r of ledgerRows ?? []) {
|
|
7034
7034
|
// `withheld-by-judgment` joins `confirmed-clean` in NOT reaching the reader, and for the opposite
|
|
@@ -7054,13 +7054,13 @@ export function coverageJudgmentRows(ledgerRows, planExecution) { // @internal
|
|
|
7054
7054
|
const host = axisOf.has(q) ? open.find((o) => o.axis === axisOf.get(q)) : null;
|
|
7055
7055
|
if (host) { host.qids.push(q); claimed.add(q); }
|
|
7056
7056
|
}
|
|
7057
|
-
//
|
|
7058
|
-
//
|
|
7057
|
+
// A claimed qid is printed nowhere: the plan-execution receipt keeps it for every gate to join on, and a
|
|
7058
|
+
// row a lawyer reads names its slice, never an engine identifier (ruled 2026-10-01). One row per slice.
|
|
7059
7059
|
const rows = open.map((o) => ({ area: o.area, ...(o.areaLabel ? { areaLabel: o.areaLabel } : {}),
|
|
7060
|
-
note: o.
|
|
7060
|
+
note: o.note }));
|
|
7061
7061
|
for (const qid of Array.isArray(planExecution?.missing) ? planExecution.missing : []) {
|
|
7062
7062
|
const q = String(qid ?? "").trim();
|
|
7063
|
-
if (q && !claimed.has(q)) rows.push({ area: q, note: "planned and not executed this run
|
|
7063
|
+
if (q && !claimed.has(q)) rows.push({ area: q, ...orphanAreaLabel(q, axisOf.get(q), plan), note: "planned and not executed this run" });
|
|
7064
7064
|
}
|
|
7065
7065
|
return rows.filter((r) => r.area && r.note);
|
|
7066
7066
|
}
|
|
@@ -7074,7 +7074,7 @@ export function stampCoverageJudgmentRows(P, runDir, note, ctx) { // @internal
|
|
|
7074
7074
|
runLog(runDir, { event: "coverage-judgment-rows", judgment: false, reason: "synthesis emitted no coverage_judgment — none is invented here" });
|
|
7075
7075
|
return;
|
|
7076
7076
|
}
|
|
7077
|
-
const rows = coverageJudgmentRows(loadCoverageLedger(runDir).rows, readPlanExecution(ctx));
|
|
7077
|
+
const rows = coverageJudgmentRows(loadCoverageLedger(runDir).rows, readPlanExecution(ctx), ctx?.registerPlan ?? null);
|
|
7078
7078
|
const discarded = Array.isArray(cj.rows) ? cj.rows.length : 0;
|
|
7079
7079
|
const next = { ...doc, coverage_judgment: { ...cj } };
|
|
7080
7080
|
if (rows.length) next.coverage_judgment.rows = rows;
|
|
@@ -7150,7 +7150,7 @@ function injectDeferralCoverage(P, runDir, note) {
|
|
|
7150
7150
|
// the two constants below BYTE-FOR-BYTE, which is why they stay exported and are asserted against the
|
|
7151
7151
|
// derivation in the tests.
|
|
7152
7152
|
//
|
|
7153
|
-
// SERP_LANES is deliberately untouched: zh-only there is the shipped design (jx-lanes.mjs
|
|
7153
|
+
// SERP_LANES is deliberately untouched: zh-only there is the shipped design (SERP_LANES declared in jx-lanes.mjs), not
|
|
7154
7154
|
// drift, and generalising the platform grid is a different piece of work.
|
|
7155
7155
|
//
|
|
7156
7156
|
// ── THE REMEDY CLAUSE NAMES A PRODUCT, AND FOR A WHILE IT NAMED A DELETED ONE ───────────────────────
|
|
@@ -7245,7 +7245,7 @@ export function scriptLaneRanOnRun(runDir, lane, { searchPolicy = null, env = pr
|
|
|
7245
7245
|
// zh — shipped the full Phase-4 deepening: the SERP platform grid and the native read. Either
|
|
7246
7246
|
// unit running IS the lane running (they gate independently; one on and one off still
|
|
7247
7247
|
// searched in Chinese), so the legs stay exactly as they were.
|
|
7248
|
-
// ja/ko — shipped as slice-1 CANDIDATE lanes only (jx-lanes.mjs
|
|
7248
|
+
// ja/ko — shipped as slice-1 CANDIDATE lanes only (LANGUAGE_LANES declared in jx-lanes.mjs): no SERP_LANES entry, so
|
|
7249
7249
|
// runJxSerpGrid hard-refuses them and neither unit flag can ever describe them. The only
|
|
7250
7250
|
// work these lanes do is the candidate fold, so "ran" is the fold having ACCEPTED
|
|
7251
7251
|
// candidates — a frozen lane decision with an empty fold searched nothing and owes the row.
|
|
@@ -8498,9 +8498,15 @@ function postponeRun(e, run, meta = {}) {
|
|
|
8498
8498
|
* PURE: a job in, a plain object out, no IO.
|
|
8499
8499
|
*/
|
|
8500
8500
|
export function instructedScopeOf(job) {
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8501
|
+
// THE MARKS ARE ALWAYS A LIST. A job that names its mark only as `markName` — a queue file written by
|
|
8502
|
+
// hand or by a forwarding agent, a resume rebuilt from status.json — recorded the bare string, and the
|
|
8503
|
+
// declination tool's identical-mark refusal reads a list, so on those runs it saw no mark and never
|
|
8504
|
+
// fired. An array that names no mark falls back the same way the intake gate does; null when nothing
|
|
8505
|
+
// names one.
|
|
8506
|
+
const named = Array.isArray(job?.marks)
|
|
8507
|
+
? job.marks.map((m) => (typeof m === "string" ? m : m?.name)).filter(Boolean) : [];
|
|
8508
|
+
const single = job?.markName ?? job?.name ?? null;
|
|
8509
|
+
const markNames = named.length ? named : (single ? [single] : null);
|
|
8504
8510
|
return {
|
|
8505
8511
|
marks: markNames,
|
|
8506
8512
|
classes: job?.classes ?? null,
|
|
@@ -8941,7 +8947,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
8941
8947
|
// frame validator compares against THIS file, never against the frame's own paraphrase) —
|
|
8942
8948
|
// paraphrase drift between the request and the frame is a defect, not a style choice.
|
|
8943
8949
|
try {
|
|
8944
|
-
writeFileSync(P.instructedScope, JSON.stringify(
|
|
8950
|
+
const scope = instructedScopeToWrite(job, { jobRebuiltFromStatus: opts.jobRebuiltFromStatus, scopeOnDisk: existsSync(P.instructedScope) }); if (scope) writeFileSync(P.instructedScope, JSON.stringify(scope, null, 2) + "\n");
|
|
8945
8951
|
} catch (e) { note(`instructed-scope write failed (non-fatal): ${e.message}`); }
|
|
8946
8952
|
// THE STORED DEFAULTS THE ENGINE CANNOT SEARCH — recorded by the run, not only by the plan preview.
|
|
8947
8953
|
//
|
|
@@ -9430,7 +9436,7 @@ async function pipelineInner(job, opts = {}) {
|
|
|
9430
9436
|
//
|
|
9431
9437
|
// The prior channel is the TRUSTED one and already carries everything needed. Half forms are
|
|
9432
9438
|
// driver-written, `seatFields(p, row)` carries their rulings by the same `pOk` path, and
|
|
9433
|
-
// gateway.mjs
|
|
9439
|
+
// syncDispositionForm() in gateway.mjs already unions this exact shape — prior-only, `{ rows: null }` submitted — on
|
|
9434
9440
|
// every attempt. So this is that mode, not a new one.
|
|
9435
9441
|
//
|
|
9436
9442
|
// ONE METRIC MOVES, deliberately: with no submission, `carried` counts every ruled row, because
|
|
@@ -13479,6 +13485,9 @@ async function pipelineInner(job, opts = {}) {
|
|
|
13479
13485
|
// structured-only). Each stage is file-gated/resumable; per-card sessions feed the lint repair below.
|
|
13480
13486
|
// C2 — fold same-owner+same-mark duplicate filings into one finding BEFORE the overview + cards read
|
|
13481
13487
|
// findings.json, so the whole delivery phase (and the published copy) sees the single consolidated set.
|
|
13488
|
+
// THE SEAM'S WRITES ARE ONE CLOSURE, so they can run again: a synthesis save after this point rewrites
|
|
13489
|
+
// findings.json from the seat's own call, and every write below went with it (`stage()` re-runs them).
|
|
13490
|
+
const seamWrites = async () => {
|
|
13482
13491
|
injectDeferralCoverage(P, run.runDir, note); injectMeaningGapCoverage(P, run.runDir, note); // A3: unclosed reopen directives, and meaning searches that did not complete, become reader-visible coverage rows first
|
|
13483
13492
|
// qw/cn-scope-honesty — the sibling injection: a CN-family-scope run whose zh lane did not run
|
|
13484
13493
|
// discloses what the native-language investigation would have searched, and where it is offered
|
|
@@ -13534,6 +13543,15 @@ async function pipelineInner(job, opts = {}) {
|
|
|
13534
13543
|
try { writeVerdictSidecar(); }
|
|
13535
13544
|
catch (e2) { throw new StageFailure("verdict", `verdict sidecar refresh failed after consolidation: ${String(e2.message).slice(0, 120)}`); }
|
|
13536
13545
|
}
|
|
13546
|
+
};
|
|
13547
|
+
await seamWrites();
|
|
13548
|
+
// Every write above is idempotent: each injection skips a row the record already carries, the stamp
|
|
13549
|
+
// replaces its rows, and the fold leaves a folded record as it is.
|
|
13550
|
+
ctx.afterSynthesisSave = async () => {
|
|
13551
|
+
note(`[seam] a synthesis save after the seam rewrote findings.json — re-applying the seam's writes`);
|
|
13552
|
+
runLog(run.runDir, { event: "seam-reapplied", after: "synthesis-save" });
|
|
13553
|
+
await seamWrites();
|
|
13554
|
+
};
|
|
13537
13555
|
// wp50/wi2 — the overview PROSE must speak the derived tier (VENZY: caption said "High risk" while
|
|
13538
13556
|
// every code surface said VERY HIGH). Thread the just-refreshed sidecar into the stage prompt; the
|
|
13539
13557
|
// deterministic backstop is predelivery-lint's overallTierChecks.
|
|
@@ -16015,6 +16033,20 @@ export function reconstructCtx(job, opts) { // @internal
|
|
|
16015
16033
|
return ctx;
|
|
16016
16034
|
}
|
|
16017
16035
|
|
|
16036
|
+
/**
|
|
16037
|
+
* The aim count the cold pass sets before synthesis (`ctx.jxAim`), set on a reconstructed context from the
|
|
16038
|
+
* same function and behind the same gate. It lives here rather than in reconstructCtx because the lane
|
|
16039
|
+
* module is only ever imported lazily and reconstructCtx is synchronous. Without it a synthesis arm on a run
|
|
16040
|
+
* whose pass carried the Chinese-evidence block dispatched without it. Returns the count it set, or null.
|
|
16041
|
+
*/
|
|
16042
|
+
export async function attachJxAim(ctx) { // @internal
|
|
16043
|
+
if (!ctx?.searchPolicy?.components?.jxLanes) return null;
|
|
16044
|
+
const { jxAimForSynthesis } = await import("./jx-units.mjs");
|
|
16045
|
+
const aim = jxAimForSynthesis(ctx.paths.runDir);
|
|
16046
|
+
if (aim) ctx.jxAim = aim.count;
|
|
16047
|
+
return aim ? aim.count : null;
|
|
16048
|
+
}
|
|
16049
|
+
|
|
16018
16050
|
// Copy a stage's about-to-be-overwritten output (+ its per-stage telemetry) into _history/<ts>-<reason>/ so a
|
|
16019
16051
|
// prior result is NEVER lost and stays comparable. Returns the snapshot dir (or null if there was no output).
|
|
16020
16052
|
//
|
|
@@ -16068,6 +16100,7 @@ export async function repairStale(job, opts = {}) { // @internal
|
|
|
16068
16100
|
const labels = Array.isArray(rec?.labels) ? rec.labels : [];
|
|
16069
16101
|
if (!labels.length) return null;
|
|
16070
16102
|
attachFramework(ctx, { write: true });
|
|
16103
|
+
await attachJxAim(ctx); // the aim count the cold pass sets, as --experiment sets it on its rebuilt context
|
|
16071
16104
|
// RE-DERIVE THE ORDER rather than trusting the file's. The recorded order was right when it was
|
|
16072
16105
|
// written, and a code change since could have moved an edge — the file names WHAT, the live graph says
|
|
16073
16106
|
// WHEN. (the file names WHAT, the live graph says WHEN)
|
|
@@ -16211,6 +16244,7 @@ async function runExperimentInner(job, opts) {
|
|
|
16211
16244
|
if (opts.dispatchTrigger != null && !DISPATCH_TRIGGERS.includes(opts.dispatchTrigger))
|
|
16212
16245
|
throw new Error(`--dispatch-trigger: unknown value "${opts.dispatchTrigger}" — it decides which production pass the arm reproduces, so a typo would compose a quietly different prompt. One of: ${DISPATCH_TRIGGERS.join(", ")}`);
|
|
16213
16246
|
const ctx = reconstructCtx(job, opts);
|
|
16247
|
+
await attachJxAim(ctx); // read off the canonical run, as the cold pass reads it; the file itself is a sandbox edge
|
|
16214
16248
|
const model = opts.model ?? (axis ? axisTier(axis).model : STAGES[name].model);
|
|
16215
16249
|
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
16216
16250
|
const tag = [name, axis, opts.label ? kebab(opts.label) : null].filter(Boolean).join("-");
|
|
@@ -16742,7 +16776,7 @@ if (isEntrypoint(import.meta.url)) void (async () => {
|
|
|
16742
16776
|
// rate-limit catch already finds the run to postpone; the same hook lets a THROWN exit name the run.
|
|
16743
16777
|
const opts = a.experiment
|
|
16744
16778
|
? { ...base, codename: a.codename, experiment: a.experiment, model: a.model, instructions: a.instructions, axis: a.axis, label: a.label, dispatchTrigger: a.dispatchTrigger }
|
|
16745
|
-
: { ...base, codename: a.codename, fromStage: a.fromStage };
|
|
16779
|
+
: { ...base, codename: a.codename, fromStage: a.fromStage, ...(a.job ? {} : { jobRebuiltFromStatus: true }) };
|
|
16746
16780
|
const script = resolve(fileURLToPath(import.meta.url));
|
|
16747
16781
|
// `jobPath` is null on a rebuilt resume, so the advice composes a command that does not name a file
|
|
16748
16782
|
// the box does not have — which is the whole defect this path exists to close, and printing it again
|
|
@@ -16922,3 +16956,67 @@ export function injectMeaningGapCoverage(P, runDir, note) { // @internal — e
|
|
|
16922
16956
|
note(`[common-law] meaning-gap coverage skipped: ${String(e?.message || e).replace(/\s+/g, " ").slice(0, 100)}`);
|
|
16923
16957
|
}
|
|
16924
16958
|
}
|
|
16959
|
+
|
|
16960
|
+
/**
|
|
16961
|
+
* A SYNTHESIS SAVE AFTER THE SEAM (the pre-delivery narrative redo, the in-pass stale repair) rewrites
|
|
16962
|
+
* findings.json from the seat's own call, and the seam's writes go with it: the coverage-judgment rows, the
|
|
16963
|
+
* injected coverage rows, the fold. The seam leaves them on the run's context, and they run again here,
|
|
16964
|
+
* before anything downstream reads the record. Before the seam there is nothing on the context, so nothing
|
|
16965
|
+
* runs. It sits at the end of this file so that adding it moved no line another file cites.
|
|
16966
|
+
*/
|
|
16967
|
+
async function afterLateSynthesisSave(name, ctx, r) {
|
|
16968
|
+
if (r?.ok && !r.skipped && name === "synthesis" && typeof ctx?.afterSynthesisSave === "function") await ctx.afterSynthesisSave();
|
|
16969
|
+
}
|
|
16970
|
+
|
|
16971
|
+
/**
|
|
16972
|
+
* The reader's name for a planned search that never ran and that no open ledger row on its axis claims —
|
|
16973
|
+
* the orphan row of `coverageJudgmentRows`. Its area is the plan's qid, which a lawyer cannot read; the
|
|
16974
|
+
* label is composed the way the workbook's released-family rows compose theirs (publish/index.mjs
|
|
16975
|
+
* releasedFamilyRows): the plan entry's unit in the coverage form's grammar, its axis head in the reader's
|
|
16976
|
+
* words. `{}` when the frozen plan does not carry the entry, so the row keeps the identifier and nothing is
|
|
16977
|
+
* invented in its place. PURE.
|
|
16978
|
+
*/
|
|
16979
|
+
function orphanAreaLabel(qid, axis, plan) {
|
|
16980
|
+
const entry = (Array.isArray(plan?.entries) ? plan.entries : []).find((e) => e?.qid === qid);
|
|
16981
|
+
if (!entry) return {};
|
|
16982
|
+
const label = coverageUnitLabel(unitLabel(axis || entry.axis, entry));
|
|
16983
|
+
return label && label !== qid ? { areaLabel: label } : {};
|
|
16984
|
+
}
|
|
16985
|
+
|
|
16986
|
+
/**
|
|
16987
|
+
* The instructed scope this run writes, or null to keep the one already on disk. A resume that rebuilt its
|
|
16988
|
+
* job from status.json holds only the job's identity (id, reference, mark, classes, forwarder), so writing
|
|
16989
|
+
* the scope from it would replace the order's goods, customer and territories with nothing, and every
|
|
16990
|
+
* later reader of the scope would see a narrower matter than was ordered. Such a resume keeps the scope the
|
|
16991
|
+
* run started with. A job read from a file, or a run with no scope yet, writes as before. PURE.
|
|
16992
|
+
*/
|
|
16993
|
+
export function instructedScopeToWrite(job, { jobRebuiltFromStatus = false, scopeOnDisk = false } = {}) { // @internal
|
|
16994
|
+
return jobRebuiltFromStatus && scopeOnDisk ? null : instructedScopeOf(job);
|
|
16995
|
+
}
|
|
16996
|
+
|
|
16997
|
+
// ── THE SALVAGE FOR A FOREIGN RECORD LINK: BLANK IT, RE-CHECK, DELIVER ──────────────────────────────────
|
|
16998
|
+
//
|
|
16999
|
+
// A seat that writes an office's page, or another register's, into a record link is refused by the
|
|
17000
|
+
// findings gate (`finding_record_url_foreign_host`). The salvage lane below takes that token, because it is
|
|
17001
|
+
// a `finding_…` token, but its lenient re-parse does not judge hosts, so it found nothing to repair and
|
|
17002
|
+
// failed the run: R2 on 0.4.1-beta.1 delivered no report over eleven copied office links. Here the driver
|
|
17003
|
+
// blanks every foreign link itself (blankForeignRecordLinks says how), keeps what it changed beside the run,
|
|
17004
|
+
// and re-checks the file with the stage's own validator. A pass delivers; anything still refused falls
|
|
17005
|
+
// through to the lanes below exactly as before, with fewer defects in the file.
|
|
17006
|
+
export function foreignRecordLinksBlanked(r, ctx, name) { // exported for its test
|
|
17007
|
+
const fail = String(r?.fail || "").replace(/^max_tokens_no_output:/, "");
|
|
17008
|
+
if (!fail.includes(FOREIGN_HOST_TOKEN) || !existsSync(ctx.paths.findings)) return false;
|
|
17009
|
+
let doc;
|
|
17010
|
+
try { doc = JSON.parse(readFileSync(ctx.paths.findings, "utf8")); } catch { return false; }
|
|
17011
|
+
const { doc: repaired, blanked, kept } = blankForeignRecordLinks(doc, activeRecordOrigins());
|
|
17012
|
+
if (!blanked.length) return false;
|
|
17013
|
+
atomicWrite(ctx.paths.findings, JSON.stringify(repaired, null, 2) + "\n");
|
|
17014
|
+
recordBlanking(ctx.paths.runDir, { stage: name, layer: "salvage", blanked, kept, fail });
|
|
17015
|
+
note(`[${name}] ${blanked.length} record link(s) on a host this register does not publish were blanked by the driver; the originals are in _driver/foreign-record-links.json`);
|
|
17016
|
+
const def = STAGES[name];
|
|
17017
|
+
const out = def?.out ? def.out(ctx.paths, ctx.axis) : null;
|
|
17018
|
+
const v = out && existsSync(out) && def.validate ? def.validate(out, readFileSync(out, "utf8")) : null;
|
|
17019
|
+
if (v?.ok) return true;
|
|
17020
|
+
runLog(ctx.paths.runDir, { event: "foreign-record-links-recheck", stage: name, ok: false, fail: String(v?.reason ?? "no validator").slice(0, 200) });
|
|
17021
|
+
return false;
|
|
17022
|
+
}
|
|
@@ -131,7 +131,7 @@ const INSTALL_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
|
131
131
|
const READ_OFF_NOTE = "Reading a brief is not available on this instance — set the search up below.";
|
|
132
132
|
import { basename, dirname, join, resolve as pathResolve } from "node:path"; import { studioDirFor } from "../shared/pre-rename-spellings.mjs";
|
|
133
133
|
import { driverDir } from "../shared/driver-dir.mjs"; //
|
|
134
|
-
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
134
|
+
import { createHmac, timingSafeEqual, randomBytes } from "node:crypto";
|
|
135
135
|
import { makePrincipal, assertPrincipal, genericOrgOf, mayReadRun, reachCovers, principalView, seesEverything, mayRun,
|
|
136
136
|
PortalDeny } from "./portal-access.mjs";
|
|
137
137
|
// — the THIRD identity source (after the CF Access edge and, until, the deleted bypass). It
|
|
@@ -220,7 +220,7 @@ export function jobHashOf(job) {
|
|
|
220
220
|
})).digest("base64url");
|
|
221
221
|
}
|
|
222
222
|
export function mintConfirmation({ secret, account, email, jobHash, now = Date.now(), ttlMs = 10 * 60 * 1000 }) {
|
|
223
|
-
const jti = createHmac("sha256", secret).update(`${account}|${jobHash}|${now}|${
|
|
223
|
+
const jti = createHmac("sha256", secret).update(`${account}|${jobHash}|${now}|${randomBytes(16).toString("hex")}`).digest("base64url").slice(0, 24);
|
|
224
224
|
const payload = { account, email, jobHash, jti, exp: now + ttlMs };
|
|
225
225
|
const body = Buffer.from(canonical(payload)).toString("base64url");
|
|
226
226
|
const sig = createHmac("sha256", secret).update(body).digest("base64url");
|
|
@@ -1395,7 +1395,7 @@ export function makePortalService({
|
|
|
1395
1395
|
//
|
|
1396
1396
|
// DISPLAY NAMES, computed server-side, because five vocabularies sit between a name on the form
|
|
1397
1397
|
// and an office code (display → normalizeTerritory → canonicalJurisdictionCode → offices.translate
|
|
1398
|
-
// → covered.has) and register-plan.mjs
|
|
1398
|
+
// → covered.has) and resolveRegions() in register-plan.mjs records what re-implementing that chain cost.
|
|
1399
1399
|
//
|
|
1400
1400
|
// THE FIELD IS OMITTED, not nulled, when the snapshot does not say. `null` is a real answer here
|
|
1401
1401
|
// ("no declared restriction") and the browser must be able to tell it from "this deployment has
|
|
@@ -4620,7 +4620,8 @@ const PORT = PORT_CHOICE.port;
|
|
|
4620
4620
|
// stays fail-closed — an empty array would be truthy and open it.
|
|
4621
4621
|
const AUD = accessAudience(envFrom(process.env, "CLEAROTRON_OIDC_AUDIENCE"));
|
|
4622
4622
|
// item 1 — THE SAME FOUR VALUES THE STAFF MCP FACE ALREADY READS, under portal-side names
|
|
4623
|
-
// (
|
|
4623
|
+
// (OIDC_ISSUER declared in http-server.mjs, and the three read beside it). `makeAccessVerifier` has
|
|
4624
|
+
// always accepted them; the portal simply
|
|
4624
4625
|
// never passed them, which is how one product shipped a provider-agnostic API face and a
|
|
4625
4626
|
// Cloudflare-only web portal. Unset ⇒ the CF Access shapes derived from CF_ACCESS_TEAM, exactly as
|
|
4626
4627
|
// before.
|
package/driver/products.mjs
CHANGED
|
@@ -344,7 +344,7 @@ export const CASE_LAW_NOT_A_REQUEST = Object.freeze({
|
|
|
344
344
|
/**
|
|
345
345
|
* `searchLevel` — THE SELECTOR ITSELF, AND THE ONE FIELD DELETED WITHOUT REFUSING.
|
|
346
346
|
*
|
|
347
|
-
* `search-policy.mjs
|
|
347
|
+
* `search-policy.mjs` says the wire field is "DELETED — not deprecated, not hidden behind the product
|
|
348
348
|
* name." The code made it deprecated: nothing on any door read it, nothing refused it, and there is no
|
|
349
349
|
* generic unknown-field rejection — so a request naming a depth was accepted, the field dropped, and the
|
|
350
350
|
* run went out at whatever product the SCOPE happened to imply.
|
package/driver/profiles.mjs
CHANGED
|
@@ -1107,9 +1107,10 @@ export function resolveEffectiveProfile(job, { profiles = loadProfiles(), projec
|
|
|
1107
1107
|
//
|
|
1108
1108
|
// `resolveEffectiveScope` decides whether to tell an approver "this project" or "the account's default
|
|
1109
1109
|
// classes" by reading `profile.origins`. It was returned HERE as a sibling and no caller bridged the
|
|
1110
|
-
// two — checked on origin/main: run-quote.mjs
|
|
1111
|
-
// all pass the profile alone. So both
|
|
1112
|
-
// FROM.project branch was dead code: a
|
|
1110
|
+
// two — checked on origin/main: quoteForJob() in run-quote.mjs, resolveRequest() in resolve-request.mjs
|
|
1111
|
+
// (twice) and checkClearanceScopeRules() in scope-rules.mjs all pass the profile alone. So both
|
|
1112
|
+
// `=== "project"` tests were permanently false and the whole FROM.project branch was dead code: a
|
|
1113
|
+
// project that REPLACES its customer's classes ran on the
|
|
1113
1114
|
// project's list and told the approver those were the account's defaults. The number was right; the
|
|
1114
1115
|
// reason given for it was wrong, and it pointed at the wrong place to go and change it.
|
|
1115
1116
|
//
|
|
@@ -121,8 +121,8 @@ export const NOT_READ_BY_NAME = {
|
|
|
121
121
|
// absent one is the caller's error and already throws. Declared so the source scan can tell "argument"
|
|
122
122
|
// from "undeclared store" instead of demanding a gating for something that has none.
|
|
123
123
|
export const CALLER_SUPPLIED = {
|
|
124
|
-
"report.md": "the reportMd ARGUMENT — read unconditionally
|
|
125
|
-
"audit.md": "the auditMd ARGUMENT — existence-gated
|
|
124
|
+
"report.md": "the reportMd ARGUMENT — read unconditionally by publishReport() in index.mjs; an unreadable one throws, which is correct (there is no report to publish)",
|
|
125
|
+
"audit.md": "the auditMd ARGUMENT — existence-gated in publishReport() in index.mjs; a run with no audit markdown legitimately publishes without a workbook",
|
|
126
126
|
};
|
|
127
127
|
|
|
128
128
|
/**
|
package/driver/publish/xlsx.mjs
CHANGED
|
@@ -574,7 +574,7 @@ function coverageJudgmentSummaryRows(cj) {
|
|
|
574
574
|
const rows = Array.isArray(cj?.rows) ? cj.rows : [];
|
|
575
575
|
if (!rows.length) return [];
|
|
576
576
|
return [{ Field: '', Value: '' }, { Field: 'Coverage judgment — slices considered', Value: '', _head: true },
|
|
577
|
-
...rows.map((r) => ({ Field: ` ${plainNote(r.area)}`, Value: plainNote(r.note) }))];
|
|
577
|
+
...rows.map((r) => ({ Field: ` ${plainNote(r.areaLabel || r.area)}`, Value: plainNote(r.note) }))];
|
|
578
578
|
}
|
|
579
579
|
function correctionsSummaryRows(c) {
|
|
580
580
|
const entries = Array.isArray(c?.entries) ? c.entries : [];
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
import { existsSync, readFileSync, appendFileSync } from "node:fs";
|
|
91
91
|
import { join } from "node:path";
|
|
92
92
|
|
|
93
|
-
import { kebab } from "./search-policy.mjs";
|
|
93
|
+
import { kebab } from "./search-policy.mjs"; import { moreThan } from "../shared/register-floor.mjs";
|
|
94
94
|
import { resolveRegions } from "./register-plan.mjs";
|
|
95
95
|
import { reachableRegions } from "./register-availability.mjs"; // — pure; the env binding is injected
|
|
96
96
|
import { variantForms, VARIANT_RULES, VARIANT_CAP } from "./register-variants.mjs";
|
|
@@ -592,7 +592,7 @@ export function disclosedFloor(c) {
|
|
|
592
592
|
}
|
|
593
593
|
|
|
594
594
|
/** A floor as every page prints it: the register's own figure, and no sentence around it. */
|
|
595
|
-
export
|
|
595
|
+
export { moreThan } from "../shared/register-floor.mjs";
|
|
596
596
|
|
|
597
597
|
/**
|
|
598
598
|
* THE READER'S LINE FOR A COUNT THAT DID NOT LAND. A count's `unavailable` text is the counts record's: it
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
// ── AND WHY IT DELEGATES TO resolveRegions RATHER THAN RE-IMPLEMENTING IT ───────────────────────────
|
|
33
33
|
//
|
|
34
34
|
// Five vocabularies sit between a display name and a covered office: display → `normalizeTerritory` →
|
|
35
|
-
// `canonicalJurisdictionCode` → `offices.translate` → `covered.has`.
|
|
35
|
+
// `canonicalJurisdictionCode` → `offices.translate` → `covered.has`. resolveRegions() in register-plan.mjs records
|
|
36
36
|
// the copper-bastion incident from re-implementing that chain — the composer submitted display names,
|
|
37
37
|
// corsearch's ISO-passthrough translate sent them to the wire verbatim, the vendor answered 500 rather
|
|
38
38
|
// than 400, and recovery burned its park budget re-sending a query that could never succeed.
|
package/driver/register-plan.mjs
CHANGED
|
@@ -375,6 +375,11 @@ export const planExactOrWidth = (capabilities) =>
|
|
|
375
375
|
Number.isFinite(capabilities?.exactOrWidth) && capabilities.exactOrWidth >= 1
|
|
376
376
|
? Math.floor(capabilities.exactOrWidth) : planMaxOrWidth(capabilities);
|
|
377
377
|
|
|
378
|
+
/** The OR-stack width for a SOUND-ALIKE band, by the same rule: `phoneticOrWidth` where a provider declares one. */
|
|
379
|
+
export const planPhoneticOrWidth = (capabilities) =>
|
|
380
|
+
Number.isFinite(capabilities?.phoneticOrWidth) && capabilities.phoneticOrWidth >= 1
|
|
381
|
+
? Math.floor(capabilities.phoneticOrWidth) : planMaxOrWidth(capabilities);
|
|
382
|
+
|
|
378
383
|
// The plan emits ONE `wildcard` predicate; the provider contract splits it into three sub-capabilities.
|
|
379
384
|
// Mirrors the executor's planPredicateParams anchoring exactly (trailing * → prefix/starts-with,
|
|
380
385
|
// leading * → suffix/ends-with, both/neither → infix over the raw pattern).
|
|
@@ -2190,7 +2195,9 @@ export function validatePlanFeasibility(plan, { capabilities = null, maxOrWidth
|
|
|
2190
2195
|
if (!PLAN_PREDICATES.includes(e?.predicate)) add("unexecutable", `unknown predicate "${e?.predicate}"`);
|
|
2191
2196
|
const names = Array.isArray(e?.terms) ? e.terms : e?.term != null ? [e.term] : [];
|
|
2192
2197
|
if (!names.length || names.some((t) => !String(t ?? "").trim())) add("unexecutable", "empty term(s)");
|
|
2193
|
-
const width =
|
|
2198
|
+
const width = !capabilities ? maxOrWidth
|
|
2199
|
+
: e?.predicate === "exact" ? Math.max(maxOrWidth, planExactOrWidth(capabilities))
|
|
2200
|
+
: e?.predicate === "phonetic" ? Math.max(maxOrWidth, planPhoneticOrWidth(capabilities)) : maxOrWidth;
|
|
2194
2201
|
if (Array.isArray(e?.terms) && e.terms.length > width) add("repairable", `OR-stack of ${e.terms.length} names exceeds the executor bound (${width}) — the executor runs it chunked`);
|
|
2195
2202
|
for (const t of names) if (String(t).length > maxNameLength) add("repairable", `name exceeds ${maxNameLength} chars ("${String(t).slice(0, 40)}…") — provider-side truncation risk only`);
|
|
2196
2203
|
if ((e?.nice_classes ?? []).some((c) => !Number.isFinite(Number(c)))) add("unexecutable", "non-numeric nice_class");
|
|
@@ -2433,6 +2440,8 @@ export function joinPlanToBands(plan, bandBlocksByAxis, { released = new Set() }
|
|
|
2433
2440
|
// WHAT THE TOTAL COUNTS, when the register said: `records`, one per country a mark covers. Every
|
|
2434
2441
|
// reader of this row reads the count as the register's own number (ruled 2026-10-02).
|
|
2435
2442
|
...(typeof b.total_counts === "string" ? { total_counts: b.total_counts } : {}),
|
|
2443
|
+
// The register's floor when it answered "at least N" instead of a count: total_hits stays null beside it.
|
|
2444
|
+
...(Number.isFinite(b.total_floor) ? { total_floor: b.total_floor } : {}),
|
|
2436
2445
|
});
|
|
2437
2446
|
}
|
|
2438
2447
|
const planQids = new Set(plan.entries.map((e) => e.qid));
|
|
@@ -2831,8 +2840,10 @@ export function openBlocksByAxis(skeleton, bandBlocksByAxis, plan) {
|
|
|
2831
2840
|
// under the deleted prose join (the qid, or this number standalone). Both are now written INTO the
|
|
2832
2841
|
// form's row by the driver, so the equivalence the join had to test for is structural — see
|
|
2833
2842
|
// coverage-form.mjs. The field stays because the row, the render and the failure token all carry it.
|
|
2843
|
+
// A null total stays off the row: `Number(null)` is 0, which printed "(0 counted)" for a register's floor
|
|
2844
|
+
// ("at least 10,000") and for a count the register refused to give.
|
|
2834
2845
|
unverified.push({ qid: e.qid,
|
|
2835
|
-
...(Number.isInteger(Number(b.total_hits)) ? { total_hits: Number(b.total_hits) } : {}),
|
|
2846
|
+
...(b.total_hits != null && Number.isInteger(Number(b.total_hits)) ? { total_hits: Number(b.total_hits) } : {}),
|
|
2836
2847
|
...(unaccounted.length ? { unaccounted: unaccounted.slice(0, 8) } : {}),
|
|
2837
2848
|
...(unaccountedClasses.length ? { unaccounted_classes: unaccountedClasses.slice(0, 8) } : {}) });
|
|
2838
2849
|
}
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
// `verdict` is one of:
|
|
45
45
|
// "result" — the value states what happened. The name is honest.
|
|
46
46
|
// "invocation" — the value states that something was CALLED. Fix by renaming, or by adding a sibling
|
|
47
|
-
// that carries the result (the remedy
|
|
47
|
+
// that carries the result (the remedy createRepairLedger() in repairs.mjs already uses, keeping
|
|
48
48
|
// `outcome` for existing readers beside `dispatch` and `verdict`).
|
|
49
49
|
// "out-of-scope" — never reaches `_driver/*.json` or `run.jsonl`; `atWriteSite` is 0.
|
|
50
50
|
|
|
@@ -62,8 +62,8 @@ export const RESULT_NOUN_FIELDS = Object.freeze([
|
|
|
62
62
|
{ file: "driver/pipeline-knockout.mjs", noun: "recovered", sites: 1, atWriteSite: 1, verdict: "result",
|
|
63
63
|
why: "written after the chunk files were actually removed" },
|
|
64
64
|
{ file: "driver/pipeline-knockout.mjs", noun: "outcome", sites: 3, atWriteSite: 3, verdict: "result",
|
|
65
|
-
why: "the reviewing pass's own verdict on itself, read at each writing site: `nothing-flagged`
|
|
66
|
-
+ "the
|
|
65
|
+
why: "the reviewing pass's own verdict on itself, read at each writing site: `nothing-flagged` when "
|
|
66
|
+
+ "the record had no line a reader meets first, `applied` after the rewrite passed the merged gate and was "
|
|
67
67
|
+ "written, and the `keep()` forms after the artifact or the gate refused it. Every one is a fact "
|
|
68
68
|
+ "about what already happened to the record, never the return of the call being logged" },
|
|
69
69
|
{ file: "driver/pipeline.mjs", noun: "closed", sites: 6, atWriteSite: 4, verdict: "result",
|
package/driver/scope-rules.mjs
CHANGED
|
@@ -99,7 +99,7 @@ export function checkClearanceScopeRules({ job = null, profile = null, resolved
|
|
|
99
99
|
//
|
|
100
100
|
// Everything a CLIENT reads quotes `named`. This module was the one caller that discarded the
|
|
101
101
|
// originals, so the wall refused a two-country Full country search naming "GB", "FR" while the door
|
|
102
|
-
// refused the identical request naming "United Kingdom", "France" — products.mjs
|
|
102
|
+
// refused the identical request naming "United Kingdom", "France" — tally() in products.mjs states exactly
|
|
103
103
|
// that failure ("a refusal that quotes \"EU\" at someone who typed \"European Union\" sends them
|
|
104
104
|
// hunting for a value they never used") and territory-tiers.mjs restates it for partitionTerritories.
|
|
105
105
|
// The COUNT is the same either way: canonicalize dedups on code and products.mjs `tally` dedups on
|
|
@@ -131,7 +131,7 @@ export function checkClearanceScopeRules({ job = null, profile = null, resolved
|
|
|
131
131
|
// `nativeLanguage: true` over a knockout base) and through any account whose defaultProduct does not
|
|
132
132
|
// carry it.
|
|
133
133
|
//
|
|
134
|
-
// That is the shape products.mjs
|
|
134
|
+
// That is the shape CASE_LAW_NOT_A_REQUEST declared in products.mjs refuses `caseLaw` for in as many words — "a flag accepted and
|
|
135
135
|
// dropped is the worst available shape: whoever sent it believes they bought the deep reading, and
|
|
136
136
|
// nothing anywhere disagrees" — and it was this build's own doctrine broken by this build's own code.
|
|
137
137
|
//
|
package/driver/stage-context.mjs
CHANGED
|
@@ -233,6 +233,15 @@ const UNDECLARED = {
|
|
|
233
233
|
synthesis: (P) => [
|
|
234
234
|
{ path: P.enforcerSignals, kind: "conditional",
|
|
235
235
|
why: "named in the prompt only when ctx.enforcerSignals > 0; aim-attention telemetry, deliberately outside the freshness map" },
|
|
236
|
+
// The job's own scope. The prompt never names it, so nothing declared it, and the sandbox rebuilt the
|
|
237
|
+
// declination spec without it: no marks and no classes, so both of the tool's refusals were off in every
|
|
238
|
+
// synthesis arm while the canonical pass had them on.
|
|
239
|
+
{ path: P.instructedScope, kind: "driver-side",
|
|
240
|
+
why: "prepareDeclinationSpec writes the declination spec's scope from it; without it the tool's refusals rest on nothing and accept what the canonical pass refused" },
|
|
241
|
+
// The Chinese-evidence flags, named in the prompt only when ctx.jxAim is set (stages.mjs synthesis
|
|
242
|
+
// message). Undeclared, an arm on a run that had them dispatched without the block.
|
|
243
|
+
{ path: driverDir(P.runDir, "jx", "aim-attention.json"), kind: "conditional",
|
|
244
|
+
why: "named in the prompt only when ctx.jxAim > 0 — the zh lane's aim-attention flags; aim-attention only, deliberately outside the freshness map" },
|
|
236
245
|
],
|
|
237
246
|
};
|
|
238
247
|
|
|
@@ -560,9 +560,10 @@ export const KO_STAGES = {
|
|
|
560
560
|
// be composed by anything except the production call site, which is how a dispatch goes unexamined
|
|
561
561
|
// — and the promise has to branch. A stage message that says "the lines are below" and then lists
|
|
562
562
|
// none has handed the seat an absence dressed as a pass, which is the reading this whole rule
|
|
563
|
-
// exists to stop.
|
|
564
|
-
//
|
|
565
|
-
|
|
563
|
+
// exists to stop. A record the driver's read flags nowhere is handed its first-read lines instead,
|
|
564
|
+
// by the owner's ruling of 2026-10-10, so both branches have rows under them; a record with no such
|
|
565
|
+
// line is not dispatched at all.
|
|
566
|
+
message: ({ K, evidenceLines = [], firstReadLines = [], exclusionNote = "" }) => lines(
|
|
566
567
|
// THE CLIENT'S QUESTION LEADS, in the owner's words (ruling 2026-09-24), ahead of the rewrite job.
|
|
567
568
|
`Does the report answer the client's question: who could object, how strong they are, what the client should do? Are the marks a lawyer would list present, and is each position written from the record that matters? Answer that before any check on wording.`,
|
|
568
569
|
reads(["skills/clearance-search/report-prose.md"]),
|
|
@@ -571,8 +572,8 @@ export const KO_STAGES = {
|
|
|
571
572
|
`The rated record: ${K.findings}. Read it — the lines named below are quoted from it and you are rewriting them in place.`,
|
|
572
573
|
evidenceLines.length
|
|
573
574
|
? `THE DRIVER MEASURED THESE LINES. Each row is the line, the ADDRESS that names it, and what a deterministic read found. 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}`
|
|
574
|
-
: `THE DRIVER'S READ FLAGGED NO LINE ON THIS RECORD, so
|
|
575
|
-
...evidenceLines,
|
|
575
|
+
: `THE DRIVER'S READ FLAGGED NO LINE ON THIS RECORD, so nothing below is evidence of a fault. These are the lines a reader meets first, each with the ADDRESS that names it. Rewrite one only where it would answer the client's question more plainly; if every line already does, send one \`declined\` row at one of these addresses saying so, rather than inventing a rewrite to fill the call.`,
|
|
576
|
+
...(evidenceLines.length ? evidenceLines : firstReadLines),
|
|
576
577
|
// ── THE DICTATION NAMES THE FIELD, NOT AN EFFECT ────────────────────────────────
|
|
577
578
|
//
|
|
578
579
|
// "Make the report plainer" is read and not applied, and nothing refuses — it simply does not
|