clearotron 0.3.2-beta.6 → 0.3.2-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/.env.example +24 -23
  2. package/INSTALL.md +142 -75
  3. package/README.md +3 -3
  4. package/bin/onboard.mjs +637 -216
  5. package/bin/start.mjs +133 -23
  6. package/bin/update.mjs +82 -11
  7. package/build-info.json +2 -2
  8. package/docs/architecture/04-configuration-reference.md +26 -11
  9. package/docs/architecture/05-config-governance.md +17 -7
  10. package/driver/CHANGELOG.md +83 -0
  11. package/driver/band-size.mjs +59 -0
  12. package/driver/config-inventory.mjs +112 -9
  13. package/driver/connotation-search.mjs +45 -0
  14. package/driver/contract-arm2-baseline.json +1 -3
  15. package/driver/contract-e3-backlog.mjs +29 -29
  16. package/driver/contract-vocabulary.mjs +59 -25
  17. package/driver/door-gates.mjs +41 -7
  18. package/driver/driver.config.mjs +272 -59
  19. package/driver/engine/CONTRACT.md +10 -3
  20. package/driver/engine/README.md +2 -2
  21. package/driver/engine/anthropic-agent.mjs +77 -21
  22. package/driver/engine/auth.mjs +129 -10
  23. package/driver/engine/jx-turn.mjs +7 -6
  24. package/driver/engine/mcp/recording-server.mjs +13 -0
  25. package/driver/engine/openai-agent.mjs +4 -2
  26. package/driver/engine/probe.mjs +110 -23
  27. package/driver/findings-model.mjs +1 -1
  28. package/driver/flag-snapshot.mjs +28 -5
  29. package/driver/gateway.mjs +30 -21
  30. package/driver/jx-lanes.mjs +21 -2
  31. package/driver/jx-units.mjs +6 -3
  32. package/driver/jx.mjs +4 -2
  33. package/driver/matter-frame-record.mjs +90 -1
  34. package/driver/named-band.mjs +34 -2
  35. package/driver/package.json +1 -1
  36. package/driver/pipeline.mjs +391 -26
  37. package/driver/portal-config-view.mjs +30 -1
  38. package/driver/portal-report.mjs +15 -1
  39. package/driver/portal-service.mjs +46 -6
  40. package/driver/predelivery-lint.mjs +12 -2
  41. package/driver/publish/index.mjs +46 -5
  42. package/driver/publish/knockout.mjs +10 -1
  43. package/driver/publish/render-knockout.mjs +69 -7
  44. package/driver/publish/render.mjs +170 -59
  45. package/driver/publish/report-data.mjs +4 -1
  46. package/driver/publish/report-topbar.mjs +58 -0
  47. package/driver/publish/templates/report.css +28 -2
  48. package/driver/publish/xlsx.mjs +13 -1
  49. package/driver/register-availability.mjs +2 -2
  50. package/driver/register-coverage.mjs +94 -1
  51. package/driver/register-digest-record.mjs +236 -11
  52. package/driver/register-plan.mjs +170 -0
  53. package/driver/result-noun-fields.mjs +7 -4
  54. package/driver/run-economics.mjs +41 -10
  55. package/driver/run-requirements.mjs +173 -9
  56. package/driver/runner.mjs +3 -3
  57. package/driver/stages.mjs +12 -8
  58. package/driver/suite-census.json +162 -72
  59. package/driver/systemd/README.md +7 -4
  60. package/driver/terminal-clamp.mjs +107 -1
  61. package/driver/tokens.mjs +169 -3
  62. package/driver/unit-environment.mjs +42 -15
  63. package/driver/unit-inventory.mjs +19 -2
  64. package/driver/verify.mjs +50 -5
  65. package/mcp-server/CHANGELOG.md +8 -0
  66. package/mcp-server/http-server.mjs +4 -0
  67. package/mcp-server/lib/audit.mjs +11 -1
  68. package/mcp-server/lib/http-handler.mjs +6 -2
  69. package/mcp-server/package.json +1 -1
  70. package/mcp-server/server.mjs +16 -2
  71. package/package.json +1 -1
  72. package/portal-ui/dist/assets/{index-5UyqAyNM.js → index-6jzO9HiX.js} +155 -79
  73. package/portal-ui/dist/index.html +1 -1
  74. package/portal-ui/package.json +1 -1
  75. package/providers/clarivate/src/capabilities.js +5 -5
  76. package/providers/clarivate/src/core.js +1 -1
  77. package/providers/corsearch/src/core.js +2 -2
  78. package/providers/jx/README.md +2 -1
  79. package/providers/jx/src/turn-envelope.mjs +8 -3
  80. package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
  81. package/providers/oauth-mcp-bridge/package.json +1 -1
  82. package/providers/perplexity/src/core.js +3 -3
  83. package/providers/signa/src/capabilities.js +5 -6
  84. package/providers/signa/src/core.js +1 -1
  85. package/providers/uspto-local/README.md +1 -1
  86. package/scripts/authority-boundary-probe.mjs +4 -2
  87. package/scripts/env-audit.mjs +12 -6
  88. package/scripts/freeze-example-run.mjs +49 -16
  89. package/scripts/generated-files-are-current.mjs +69 -4
  90. package/scripts/release-duplicate-notes.mjs +246 -0
  91. package/scripts/release-publish-guard.mjs +64 -6
  92. package/scripts/report-print-check.mjs +194 -0
  93. package/scripts/settings-render-check.mjs +75 -2
  94. package/scripts/test-full.mjs +96 -3
  95. package/scripts/test-run.mjs +10 -0
  96. package/shared/deployment-box.mjs +7 -2
  97. package/shared/driver-dir.mjs +1 -1
  98. package/shared/names-in-force.mjs +1 -1
@@ -185,7 +185,7 @@ export const E3_BACKLOG = [
185
185
  // it one: authored once in renderConnotationObligations, and reaching the seat through the perplexity
186
186
  // MCP server (driver/engine/mcp/perplexity-server.mjs:111) rather than a stage message. Three rows
187
187
  // pointing at one block would fabricate two authored sites the surface does not have.
188
- where: "driver/connotation-search.mjs:1435-1448 (renderConnotationObligations; delivered to the seat via driver/engine/mcp/perplexity-server.mjs:111 — a TOOL RESPONSE, no longer a stage message)",
188
+ where: "driver/connotation-search.mjs:1480-1493 (renderConnotationObligations; delivered to the seat via driver/engine/mcp/perplexity-server.mjs:111 — a TOOL RESPONSE, no longer a stage message)",
189
189
  surface: "tool-response",
190
190
  // ── (a) THE ORIGINAL SUBJECT WAS DELETED BY DESIGN — DISCHARGED, NOT FAILED ────────────────────
191
191
  // The old rows dictated `receipt_id` (an 8-char token the seat copied) and `quote`. Both are gone:
@@ -283,7 +283,7 @@ export const E3_BACKLOG = [
283
283
  {
284
284
  stage: "register-unit",
285
285
  kind: "exactly-these-keys",
286
- where: "driver/stages.mjs:4191 (the frame-reopen / scoped-retry message builder). A second number stood here and had been stale for some time: it pointed at a contract-element description rather than a builder, at its old line and at every mechanical shift of it. Two candidate builders sit beside 4157 and picking one would be a guess, so the wrong pointer is removed rather than moved a third time — one accurate citation beats one accurate and one invented.",
286
+ where: "driver/stages.mjs:4195 (the frame-reopen / scoped-retry message builder). A second number stood here and had been stale for some time: it pointed at a contract-element description rather than a builder, at its old line and at every mechanical shift of it. Two candidate builders sit beside 4157 and picking one would be a guess, so the wrong pointer is removed rather than moved a third time — one accurate citation beats one accurate and one invented.",
287
287
  surface: "stage-message",
288
288
  evidence: "Every block you append MUST carry \"state\":\"enumerated\" (ONLY if paged to has_more:false) or \"state\":\"incomplete\" — EXACTLY those two strings … (re-dispatch builders, which REPLACE def.message)",
289
289
  reparsedBy: "driver/named-band.mjs parseNamedBand. Scope warning: these builders replace def.message on every escalation / envelope-close / frame-reopen dispatch, so an E3 lint that walks STAGES[*].message only never sees them",
@@ -346,7 +346,7 @@ export const E3_BACKLOG = [
346
346
  // (coverage-form.mjs coverageFormBrief) and the tool schema, with every row receiver-validated at
347
347
  // call time. Same dictated vocabulary, same authored site, new route — this row's evidence follows
348
348
  // the dictation so the row keeps describing something that exists.
349
- where: "driver/stages.mjs:2618 (the digest message) + driver/coverage-form.mjs (coverageFormBrief — the dispatch block carrying the enum and the row shape)",
349
+ where: "driver/stages.mjs:2622 (the digest message) + driver/coverage-form.mjs (coverageFormBrief — the dispatch block carrying the enum and the row shape)",
350
350
  surface: "stage-message",
351
351
  evidence: "Record a \"status\" and a \"reason\" on EVERY row ONLY by calling the … tool — the driver validates each row as it arrives, holds the record itself, and renders both the ## Coverage ledger table and the coverage JSON from it",
352
352
  reparsedBy: "driver/coverage-call.mjs validateCoverageCall (receiver-validated at call time, the same predicates the gate judges with) + driver/coverage-form.mjs rowIsSettled via validators.registerFindings over the _driver/ accumulator",
@@ -429,7 +429,7 @@ export const E3_BACKLOG = [
429
429
  {
430
430
  stage: "frame-diff",
431
431
  kind: "exactly-these-keys",
432
- where: "driver/stages.mjs:2798",
432
+ where: "driver/stages.mjs:2802",
433
433
  surface: "stage-message",
434
434
  evidence: "For each blind-model variant / field / source the run did NOT scope or search, emit one directive {layer, item, observation, severity} … severity = dominant-element (the omission is ON the spine) | material (a real omission worth a targeted sweep) | minor (already covered, or presentation only).",
435
435
  reparsedBy: "driver/verify.mjs validators.frameDiff + driver/pipeline.mjs runSupplementalSweeps (the parser REFUSES a firing variant directive that dictates nothing dispatchable)",
@@ -453,7 +453,7 @@ export const E3_BACKLOG = [
453
453
  {
454
454
  stage: "synthesis",
455
455
  kind: "literal-json-skeleton",
456
- where: "driver/stages.mjs:3178",
456
+ where: "driver/stages.mjs:3182",
457
457
  surface: "stage-message",
458
458
  evidence: "MACHINE FINDINGS (MANDATORY): … a JSON OBJECT {\"schema_version\":<FINDINGS_SCHEMA_VERSION>,\"rated_under_framework\":\"…\",\"findings\":[...],\"coverage\":[...],\"context_notes\":[...],\"actions\":[...],\"ask_answers\":[...]} … Each finding object has EXACTLY these keys: {\"ordinal\",\"mark\",\"owner\",\"band\",\"net\",\"bor",
459
459
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson via validators.narrative",
@@ -467,7 +467,7 @@ export const E3_BACKLOG = [
467
467
  {
468
468
  stage: "synthesis",
469
469
  kind: "exactly-these-keys",
470
- where: "driver/stages.mjs:3214",
470
+ where: "driver/stages.mjs:3218",
471
471
  surface: "stage-message",
472
472
  evidence: "- off_field_ground (MANDATORY on every off-field finding, FORBIDDEN on every other disposition): EXACTLY one bare token of: ${OFF_FIELD_GROUNDS.join(\" / \")}",
473
473
  reparsedBy: "driver/findings-model.mjs validateOffFieldGround — the enum is imported from findings-model.mjs and interpolated back into the prompt, so code already holds the list it asks the model to type",
@@ -476,7 +476,7 @@ export const E3_BACKLOG = [
476
476
  {
477
477
  stage: "synthesis",
478
478
  kind: "literal-json-skeleton",
479
- where: "driver/stages.mjs:3215",
479
+ where: "driver/stages.mjs:3219",
480
480
  surface: "stage-message",
481
481
  evidence: "- manageable …: {\"category\":\"<EXACTLY one of large-competitor / commercial-partner / troll / well-known-enforcer>\",\"reason\":\"<one-two lines…>\"}",
482
482
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson",
@@ -485,16 +485,16 @@ export const E3_BACKLOG = [
485
485
  {
486
486
  stage: "synthesis",
487
487
  kind: "literal-json-skeleton",
488
- where: "driver/stages.mjs:3231",
488
+ where: "driver/stages.mjs:3235",
489
489
  surface: "stage-message",
490
490
  evidence: "- meters: {\"mark_similarity\":{...},\"goods_proximity\":{...},\"use\":{...},\"enforcer\":{...}} — all four present, each {\"token\",\"basis\",\"source\"}. … mark_similarity = high | medium | low. goods_proximity = high | medium | low. enforcer = high | medium | low | unknown. use = confirmed | not-confirmed | un",
491
- reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson; driver/verify.mjs:1153 checkFindingsSibling gates meters.*.source; finding_basis_source_missing",
491
+ reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson; driver/verify.mjs:1171 checkFindingsSibling gates meters.*.source; finding_basis_source_missing",
492
492
  removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
493
493
  },
494
494
  {
495
495
  stage: "synthesis",
496
496
  kind: "literal-json-skeleton",
497
- where: "driver/stages.mjs:3232",
497
+ where: "driver/stages.mjs:3236",
498
498
  surface: "stage-message",
499
499
  evidence: "- quadrant: {\"x\",\"y\"} numbers in [0,1]. x = goods/services proximity (0 = distant, 1 = identical). y = mark similarity (0 = distinct, 1 = identical).",
500
500
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson",
@@ -503,7 +503,7 @@ export const E3_BACKLOG = [
503
503
  {
504
504
  stage: "synthesis",
505
505
  kind: "literal-json-skeleton",
506
- where: "driver/stages.mjs:3233",
506
+ where: "driver/stages.mjs:3237",
507
507
  surface: "stage-message",
508
508
  evidence: "- source: {\"source_type\",\"resolved_link\"}. source_type EXACTLY one of: register-vendor / register-euipo / common-law-marketplace / common-law-web / case-law",
509
509
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson",
@@ -512,7 +512,7 @@ export const E3_BACKLOG = [
512
512
  {
513
513
  stage: "synthesis",
514
514
  kind: "exactly-these-keys",
515
- where: "driver/stages.mjs:3234",
515
+ where: "driver/stages.mjs:3238",
516
516
  surface: "stage-message",
517
517
  evidence: "coverage[]: ONE object per coverage AREA, EXACTLY {\"area\",\"state\",\"note\"}. … state EXACTLY one of: confirmed-clean / coverage-limited / open / not-searched / note.",
518
518
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson; the render owns the coverage panel from these typed states",
@@ -521,7 +521,7 @@ export const E3_BACKLOG = [
521
521
  {
522
522
  stage: "synthesis",
523
523
  kind: "literal-json-skeleton",
524
- where: "driver/stages.mjs:3243",
524
+ where: "driver/stages.mjs:3247",
525
525
  surface: "stage-message",
526
526
  evidence: "use_check = {\"source\",\"quality\"}: … quality: OPTIONAL, EXACTLY one of owner-site / independent / register-mirror … own_rights = {\"source\"}",
527
527
  reparsedBy: "driver/verify.mjs:988 checkFindingsSibling (finding_use_check_missing); driver/own-rights.mjs:19-22",
@@ -530,7 +530,7 @@ export const E3_BACKLOG = [
530
530
  {
531
531
  stage: "synthesis",
532
532
  kind: "literal-json-skeleton",
533
- where: "driver/stages.mjs:3300",
533
+ where: "driver/stages.mjs:3304",
534
534
  surface: "stage-message",
535
535
  evidence: "MARK ASSESSMENT … STRUCTURED FORM …: either field may instead be an OBJECT {\"read\":\"…\",\"spectrum\":\"…\",\"per_class\":[{\"class\":\"5\",\"note\":\"…\"}],\"per_market\":[{\"market\":\"CN\",\"note\":\"…\"}],\"counter_registrations\":[{\"mark\":\"…\",\"uri\":\"/mark/…\",\"note\":\"…\"}],\"acquired\":\"<optional>\",\"note\":\"<optional residual>",
536
536
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson; the report collapses the rows behind toggles and the audit workbook renders them",
@@ -539,7 +539,7 @@ export const E3_BACKLOG = [
539
539
  {
540
540
  stage: "synthesis",
541
541
  kind: "literal-json-skeleton",
542
- where: "driver/stages.mjs:3306",
542
+ where: "driver/stages.mjs:3310",
543
543
  surface: "stage-message",
544
544
  evidence: "FOUR ANSWERS …: \"four_answers\": {\"third_party_rights\":{...},\"objection_likelihood\":{...},\"registrability\":{...},\"client_enforceability\":{...}} … Each answer … is {\"read\":\"…\",\"token\":\"…\",\"basis\":\"…\",\"ordinals\":[…]}. Tokens (closed enums …): third_party_rights = strong|moderate|weak; objection_likelih",
545
545
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson",
@@ -548,7 +548,7 @@ export const E3_BACKLOG = [
548
548
  {
549
549
  stage: "synthesis",
550
550
  kind: "literal-json-skeleton",
551
- where: "driver/stages.mjs:3217",
551
+ where: "driver/stages.mjs:3221",
552
552
  surface: "stage-message",
553
553
  evidence: "ACTIONS REGISTER …: emit \"actions\": [...] — ONE object per forward step …, each EXACTLY {\"id\",\"kind\",\"text\",\"ordinals\"} plus an OPTIONAL \"deadline\" and an OPTIONAL \"condition\". … kind: EXACTLY one of — consent / coexistence-agreement / territorial-delimitation / goods-amendment / mark-modification /",
554
554
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson; pipeline applyCoverageFloor legalActions arm derives the delivered disposition from the closed kind enum",
@@ -557,7 +557,7 @@ export const E3_BACKLOG = [
557
557
  {
558
558
  stage: "synthesis",
559
559
  kind: "exactly-these-keys",
560
- where: "driver/stages.mjs:3313",
560
+ where: "driver/stages.mjs:3317",
561
561
  surface: "stage-message",
562
562
  evidence: "COVERAGE JUDGMENT …: emit \"coverage_judgment\": {\"sufficient\":<bool>, \"reason\":\"<one line…>\"} — EXACTLY those two keys. Do NOT emit \"rows\": the driver writes that register itself … anything you type there is replaced wholesale.",
563
563
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson. The \"Do NOT emit rows\" clause is the purest E3 case in the tree — the prompt names a field, dictates its shape and states in the same breath that code overwrites it",
@@ -566,7 +566,7 @@ export const E3_BACKLOG = [
566
566
  {
567
567
  stage: "synthesis",
568
568
  kind: "literal-json-skeleton",
569
- where: "driver/stages.mjs:3156",
569
+ where: "driver/stages.mjs:3160",
570
570
  surface: "stage-message",
571
571
  // RE-QUOTED, NOT PARKED. The writer's conversion reworded this dictation — the
572
572
  // ask answers ride the findings RECORD now and the driver renders the labelled line into both the
@@ -590,7 +590,7 @@ export const E3_BACKLOG = [
590
590
  {
591
591
  stage: "synthesis",
592
592
  kind: "dictated-line-shape",
593
- where: "driver/stages.mjs:3077 (restated at driver/skills/prelim-search/synthesis-rules.md:428)",
593
+ where: "driver/stages.mjs:3081 (restated at driver/skills/prelim-search/synthesis-rules.md:428)",
594
594
  surface: "stage-message",
595
595
  evidence: "END that finding's actual-use line with a literal \"- **Use-check source:** <result URL | \"perplexity_research — no result\">\" line",
596
596
  reparsedBy: "driver/verify.mjs validators.narrative (spec-11 hard reject); the repair hint re-dictates the literal at driver/gateway.mjs:2153",
@@ -599,7 +599,7 @@ export const E3_BACKLOG = [
599
599
  {
600
600
  stage: "synthesis",
601
601
  kind: "dictated-line-shape",
602
- where: "driver/stages.mjs:3090 (restated at driver/skills/prelim-search/synthesis-rules.md:475)",
602
+ where: "driver/stages.mjs:3094 (restated at driver/skills/prelim-search/synthesis-rules.md:475)",
603
603
  surface: "stage-message",
604
604
  evidence: "END that finding's reasoning with a literal \"- **Own-rights source:** <record URI(s) | \"no applicant-owned registrations in the searched register material\">\" line",
605
605
  reparsedBy: "driver/own-rights.mjs:19-22 — \"This module only requires the 'Own-rights source:' line to exist\"; repair hint at driver/gateway.mjs:2361 (the `own_rights_missing` branch; re-verified 2026-08-29 — the old :1736 predated this branch and pointed into the A4 repeat-signature block)",
@@ -608,7 +608,7 @@ export const E3_BACKLOG = [
608
608
  {
609
609
  stage: "synthesis",
610
610
  kind: "exactly-these-keys",
611
- where: "driver/stages.mjs:3292",
611
+ where: "driver/stages.mjs:3296",
612
612
  surface: "stage-message",
613
613
  evidence: "add it to the top-level \"context_notes\" array — each object EXACTLY {\"type\":\"famous-neighbour-ungrounded\",\"mark\",\"owner\",\"context\"}",
614
614
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson",
@@ -617,7 +617,7 @@ export const E3_BACKLOG = [
617
617
  {
618
618
  stage: "synthesis",
619
619
  kind: "literal-json-skeleton",
620
- where: "driver/stages.mjs:3180",
620
+ where: "driver/stages.mjs:3184",
621
621
  surface: "stage-message",
622
622
  evidence: "- owner: {\"name\",\"country\",\"registrations\":[...]}. … Each registration: {\"uri\", optionally \"classes\":[\"9\",\"41\"],\"status\",\"filed\",\"expiry\",\"jurisdiction\"}. The \"uri\" is the ONLY field that matters: the driver BINDS classes/status/filed/expiry/jurisdiction AND the owner name from the FETCHED record ke",
623
623
  reparsedBy: "driver/findings-model.mjs:813 parseFindingsJson + the record-binding join. Six of the seven keys are stated in the prompt and overwritten by code in the same sentence",
@@ -626,7 +626,7 @@ export const E3_BACKLOG = [
626
626
  {
627
627
  stage: "case-law",
628
628
  kind: "literal-json-skeleton",
629
- where: "driver/stages.mjs:3462",
629
+ where: "driver/stages.mjs:3466",
630
630
  surface: "stage-message",
631
631
  evidence: "ALSO write the RETRIEVAL RECORD to <path> — a JSON OBJECT with EXACTLY these keys: {\"schema_version\":1,\"queries\":[{\"query\":\"<the search you dispatched, verbatim>\",\"jurisdiction\":\"…\",\"results\":<how many hits it returned>}, …],\"citations\":[{\"proceeding\":\"…\",\"forum\":\"…\",\"jurisdiction\":\"…\",\"decided\":\"…\"",
632
632
  reparsedBy: "driver/verify.mjs validators.caseLaw — the ledger arm, armed by the stage-contract marker `citations` (stages.mjs:1820)",
@@ -635,7 +635,7 @@ export const E3_BACKLOG = [
635
635
  {
636
636
  stage: "case-law",
637
637
  kind: "dictated-line-shape",
638
- where: "driver/stages.mjs:3470",
638
+ where: "driver/stages.mjs:3474",
639
639
  surface: "stage-message",
640
640
  evidence: "EVERY \"Grounded profile\" section MUST start its body with the line \"- ord: <N>\" naming which finding it grounds (use the ordinal from this list; a profile that grounds no listed finding omits the line)",
641
641
  reparsedBy: "driver/publish/parse.mjs:339 parseCaseLawProfiles (\"the optional '- ord: <N>' first body line … gives an EXACT join\"); driver/findings-model.mjs:273 /^-\\s*ord:\\s*(\\d+)\\s*$/m; driver/publish/index.mjs:778 runOrigins",
@@ -669,7 +669,7 @@ export const E3_BACKLOG = [
669
669
  {
670
670
  stage: "narrative-refutation",
671
671
  kind: "dictated-line-shape",
672
- where: "driver/stages.mjs:3602",
672
+ where: "driver/stages.mjs:3606",
673
673
  surface: "stage-message",
674
674
  // RE-QUOTED BY CONVERSION 9. The LINE-TOKEN half is gone — no "anywhere on the line", no "[kind: …]
675
675
  // token", no "a line with no token is treated as fact", because a kind is a typed field now and an
@@ -684,7 +684,7 @@ export const E3_BACKLOG = [
684
684
  // because an un-anchorable row lands in the NOT-CHECKED slice, and that is coverage lost rather than
685
685
  // a pass.
686
686
  evidence: "is ONE of coverage-disposition | fact | rating | narrative — pick the one your own legal read says the correction IS: coverage-disposition (a coverage row / disposition placement is wrong or dishonest)",
687
- reparsedBy: "driver/verify.mjs:829 CORRECTION_KIND_RE = /\\[kind:\\s*([a-z][a-z-]*)\\s*\\]/i → parseCorrectionKinds (verify.mjs:1052), consumed in pipelineInner() in pipeline.mjs for the run.jsonl `correction-kinds` histogram, which since #1558 also carries `kindChannelOk` — the counts are DERIVED from the parsed rows, and that key states whether the reviewer's kind channel produced anything at all rather than leaving a reader to infer it by comparing untyped against total. Telemetry only today",
687
+ reparsedBy: "driver/verify.mjs CORRECTION_KIND_RE = /\\[kind:\\s*([a-z][a-z-]*)\\s*\\]/i → parseCorrectionKinds (verify.mjs), consumed in pipelineInner() in pipeline.mjs for the run.jsonl `correction-kinds` histogram, which since #1558 also carries `kindChannelOk` — the counts are DERIVED from the parsed rows, and that key states whether the reviewer's kind channel produced anything at all rather than leaving a reader to infer it by comparing untyped against total. Telemetry only today",
688
688
  removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
689
689
  },
690
690
  {
@@ -697,7 +697,7 @@ export const E3_BACKLOG = [
697
697
  // `[on: -]` case went from a value to an ABSENCE — you omit the field — which is the one part a
698
698
  // reader could get wrong from the old wording, since there is no value meaning "no finding".
699
699
  evidence: "**AND EVERY FLAG CARRIES WHICH FINDING IT IS ABOUT** — the `on` field, an array of ordinals. Same rule as `kind`: you send the values, the driver renders the token.",
700
- reparsedBy: "driver/verify.mjs:846 CORRECTION_ON_RE = /\\[on:\\s*([0-9,\\s-]*?)\\s*\\]/i. SKILL-FILE ONLY — the stage message at stages.mjs:1842-1877 never mentions `[on:]`. This is #850's \"the element shape is in the skill file, not the stage message\" in its purest form: an E3 lint reading stages.mjs alone sees the [kind:] token and misses its twin",
700
+ reparsedBy: "driver/verify.mjs:864 CORRECTION_ON_RE = /\\[on:\\s*([0-9,\\s-]*?)\\s*\\]/i. SKILL-FILE ONLY — the stage message at stages.mjs:1842-1877 never mentions `[on:]`. This is #850's \"the element shape is in the skill file, not the stage message\" in its purest form: an E3 lint reading stages.mjs alone sees the [kind:] token and misses its twin",
701
701
  removedByMove: "NOTHING ON THE #850 PLAN REMOVES THIS",
702
702
  },
703
703
  {
@@ -768,7 +768,7 @@ export const E3_BACKLOG = [
768
768
  {
769
769
  stage: "report-card",
770
770
  kind: "literal-json-skeleton",
771
- where: "driver/stages.mjs:3911",
771
+ where: "driver/stages.mjs:3915",
772
772
  surface: "stage-message",
773
773
  evidence: "The finding's OWN record — the ONLY source for this card …:\\n```json\\n<JSON.stringify(finding, null, 2)>\\n```",
774
774
  reparsedBy: "none — this is the INPUT side, and that is why it belongs in the survey: a full JSON object rendered into the prompt is exactly the mechanism #850 proves produced R-RECEIPT (the model pattern-matches a shown shape). E3's clause 1 as written (\"a code fence or inline example showing the exact object shape the model must emit\") does not reach an injected record, so the lint needs an explicit rule for shown-but-not-owed structure",
@@ -858,7 +858,7 @@ export const E3_EVIDENCE_UNRESOLVED = [
858
858
  // absorbed. It was the narrative "## Answers to your instructions" row deleted above: its dictation is
859
859
  // gone, so there is no un-anchorable quote left to be unresolved. The one that REMAINS is a live row
860
860
  // whose quote spans a template line. Measured before deleting, not predicted — two rows shared
861
- // `where: "driver/stages.mjs:3045"`, so which one occupied this slot could not be read off the strings.
861
+ // `where: "driver/stages.mjs:3049"`, so which one occupied this slot could not be read off the strings.
862
862
  "synthesis|driver/stages.mjs",
863
863
  ];
864
864
 
@@ -17,12 +17,12 @@
17
17
  //
18
18
  // D1 verify.mjs:940 fail(`connotation_${reason}:…`) — reason iterates the table at line 894
19
19
  // D2 verify.mjs fail(String(e.message)) — parseFindingsJson throws token-first
20
- // D3 verify.mjs:1210 checkJson: fail(String(e.message)) — FIVE parsers reach this one site
20
+ // D3 verify.mjs:1228 checkJson: fail(String(e.message)) — FIVE parsers reach this one site
21
21
  // D4 verify.mjs parseCoverageLedgerJson, same shape
22
22
  // D5 verify.mjs:1504 fail(`${unaccounted[0].token}:…`) — token minted in a DATA ROW
23
23
  // D6 verify.mjs:1567 fail(`${violations[0].token}…`) — validatePlanFeasibility in register-plan.mjs
24
- // D7 verify.mjs:1558 fail(`${v2[0].token}${detail}…`) — register-plan.mjs:2018 disclosureTextByAxis
25
- // D8 verify.mjs:2425 caseLawLedgerFail fail(caseLawLedgerFail(…)) — token built in case-law-ledger.mjs:204 caseLawLedgerFail
24
+ // D7 verify.mjs:1558 fail(`${v2[0].token}${detail}…`) — register-plan.mjs:2183 disclosureTextByAxis
25
+ // D8 verify.mjs:2470 caseLawLedgerFail fail(caseLawLedgerFail(…)) — token built in case-law-ledger.mjs:195 caseLawLedgerFail
26
26
  //
27
27
  // A partition built on the 60 tokens a regex CAN see would run green while blind to the rest, which is
28
28
  // worse than having no E2 at all: it certifies a partition it never checked. So the census is authored
@@ -70,7 +70,7 @@ export const VOCABULARY = [
70
70
  // ── common-law / common-law-half ───────────────────────────────────────────────────────────────────
71
71
  { token: "declared_unavailable", stages: CL, site: "driver/verify.mjs" },
72
72
  { token: "grid_spec_unreadable", stages: CL, site: "driver/verify.mjs:257" },
73
- { token: "grid_ledger_missing", stages: CL, site: "driver/verify.mjs:297" },
73
+ { token: "grid_ledger_missing", stages: CL, site: "driver/verify.mjs commonLawMeaningSeat" },
74
74
  { token: "grid_ledger_unparseable", stages: CL, site: "driver/verify.mjs:266" },
75
75
  { token: "connotation_query_unrecorded", stages: ["common-law-half"], site: "driver/verify.mjs" },
76
76
  { token: "profile_unparseable", stages: ["common-law"], site: "driver/verify.mjs" },
@@ -102,6 +102,36 @@ export const VOCABULARY = [
102
102
  { token: "finding", stages: ["synthesis"], site: "driver/verify.mjs", family: "driver/findings-model.mjs (token-first throws; `finding_*` and `findings_*`)", dynamic: "D2" },
103
103
 
104
104
  // ── register-digest ────────────────────────────────────────────────────────────────────────────────
105
+ // The per-record accounting family, raised at the EXIT as well as at the call. The call-time refusal
106
+ // is scoped to the batch it judges, which is what lets a dense band be recorded at all; the exit gate
107
+ // is where that is paid for, because once any batch is accepted a document exists and half a band is
108
+ // the same SHAPE as a whole one. All three are armed by the era stamp, so an archived run raises none.
109
+ { token: "registerdigest_unaccounted_records", stages: ["register-digest"], site: "driver/verify.mjs, and driver/register-digest-record.mjs at the call" },
110
+ { token: "registerdigest_accounting_unreadable", stages: ["register-digest"], site: "driver/verify.mjs — driver-written, not a model defect" },
111
+ { token: "registerdigest_model_missing", stages: ["register-digest"], site: "driver/verify.mjs — driver-written, not a model defect" },
112
+ // ── THE TYPED TRANSPORT'S OWN FAMILY (conversion 11) ──────────────────────────────────────────────
113
+ //
114
+ // These are raised by `register-digest-record.mjs` at the ACCEPTANCE BOUNDARY, not by verify.mjs, and
115
+ // they became visible to this census only when verify.mjs began reaching into that module for the
116
+ // digest's exit gate. They existed and were emitted for months before that; nothing was wrong with
117
+ // them, and nothing here changes behaviour. What changes is that the census can now see the family,
118
+ // which is the point of listing the module: a family the tripwire cannot read can grow a member no
119
+ // row covers, and nobody finds out.
120
+ { token: "registerdigest_uri_missing", stages: ["register-digest"], site: "driver/register-digest-record.mjs — every row joins to a band record by its uri" },
121
+ { token: "registerdigest_uri_unknown", stages: ["register-digest"], site: "driver/register-digest-record.mjs — a uri this run's band does not carry" },
122
+ { token: "registerdigest_flag_reason_missing", stages: ["register-digest"], site: "driver/register-digest-record.mjs — the judgment the row exists to carry" },
123
+ { token: "registerdigest_verify_invalid", stages: ["register-digest"], site: "driver/register-digest-record.mjs — one bare token of yes/no" },
124
+ { token: "registerdigest_drop_reason_missing", stages: ["register-digest"], site: "driver/register-digest-record.mjs — a drop with no stated reason is a silent recall loss" },
125
+ { token: "registerdigest_drop_ground_invalid", stages: ["register-digest"], site: "driver/register-digest-record.mjs — the closed ground token" },
126
+ { token: "registerdigest_drop_ground_contradicted", stages: ["register-digest"], site: "driver/register-digest-record.mjs — the ground contradicts this run's own screen verdict" },
127
+ { token: "registerdigest_instructed_incomplete", stages: ["register-digest"], site: "driver/register-digest-record.mjs — every instructed check carries ask AND answer" },
128
+ { token: "registerdigest_adjudication_invalid", stages: ["register-digest"], site: "driver/register-digest-record.mjs — one bare token of ADOPTED/OVERRODE" },
129
+ { token: "registerdigest_adjudication_incomplete", stages: ["register-digest"], site: "driver/register-digest-record.mjs — an override quotes the reason it contradicts" },
130
+ { token: "registerdigest_nothing_judged", stages: ["register-digest"], site: "driver/register-digest-record.mjs — a digest that ends no record has not read the band" },
131
+ // The batching members, added with the batched accounting itself.
132
+ { token: "registerdigest_batch_unknown", stages: ["register-digest"], site: "driver/register-digest-record.mjs — a batch number this run's split does not hold" },
133
+ { token: "registerdigest_double_counted", stages: ["register-digest"], site: "driver/register-digest-record.mjs — a record ended under one batch cannot be ended under another" },
134
+ { token: "registerdigest_model_write_failed", stages: ["register-digest"], site: "driver/register-digest-record.mjs — driver-written: the accumulator was lost mid-batch" },
105
135
  { token: "coverage_form_damaged", stages: ["register-digest"], site: "driver/verify.mjs" },
106
136
  { token: "coverage_form_engine_vocabulary", stages: ["register-digest"], site: "driver/verify.mjs" },
107
137
  { token: "coverage_form_axis_invalid", stages: ["register-digest"], site: "driver/verify.mjs" },
@@ -109,10 +139,10 @@ export const VOCABULARY = [
109
139
  { token: "coverage_form_missing", stages: ["register-digest"], site: "driver/verify.mjs" },
110
140
  { token: "coverage_form_empty", stages: ["register-digest"], site: "driver/verify.mjs" },
111
141
  { token: "coverage_status_offenum", stages: ["register-digest"], site: "driver/verify.mjs:2050" },
112
- { token: "coverage_deferred_unaccounted", stages: ["register-digest"], site: "driver/verify.mjs:1536 coverageFormFail", family: "driver/register-plan.mjs:1642 PROVIDER_HARD_ERROR_PREFIX — token on a data row", dynamic: "D5" },
113
- { token: "coverage_clean_unexecuted", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:1417 validatePlanFeasibility", dynamic: "D6" },
114
- { token: "coverage_clean_skipped", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:1766 searchedJurisdictionsFromPlan", dynamic: "D6" },
115
- { token: "coverage_clean_unverified_incomplete", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:2018 disclosureTextByAxis", dynamic: "D7" },
142
+ { token: "coverage_deferred_unaccounted", stages: ["register-digest"], site: "driver/verify.mjs coverageFormFail", family: "driver/register-plan.mjs:1860 PROVIDER_HARD_ERROR_PREFIX — token on a data row", dynamic: "D5" },
143
+ { token: "coverage_clean_unexecuted", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:1594 validatePlanFeasibility", dynamic: "D6" },
144
+ { token: "coverage_clean_skipped", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:1955 searchedJurisdictionsFromPlan", dynamic: "D6" },
145
+ { token: "coverage_clean_unverified_incomplete", stages: ["register-digest"], site: "driver/verify.mjs, the matterContext validator", family: "driver/register-plan.mjs:2183 disclosureTextByAxis", dynamic: "D7" },
116
146
  { token: "coverage_clean_tainted", stages: ["register-digest"], site: "driver/verify.mjs" },
117
147
  { token: "coverage_ledger_", stages: ["register-digest"], site: "driver/verify.mjs", family: "driver/coverage-ledger.mjs (parseCoverageLedgerJson token-first throws)", dynamic: "D4" },
118
148
  { token: "coverage_key_unknown", stages: ["register-digest"], site: "driver/verify.mjs", family: "driver/coverage-ledger.mjs", dynamic: "D4" },
@@ -128,9 +158,9 @@ export const VOCABULARY = [
128
158
  { token: "variantmodel_romanization_missing", stages: ["prelim-variants"], site: "driver/verify.mjs" },
129
159
  { token: "variantmodel_family_incomplete", stages: ["prelim-variants"], site: "driver/verify.mjs" },
130
160
  { token: "variantmodel_term_markup", stages: ["prelim-variants"], site: "driver/verify.mjs" },
131
- { token: "variantmodel_missing", stages: ["prelim-variants"], site: "driver/verify.mjs:1153, 1212" },
161
+ { token: "variantmodel_missing", stages: ["prelim-variants"], site: "driver/verify.mjs:1171 checkFindingsSibling, 1230 checkJson" },
132
162
  // Recovered during E2 authoring, absent from the draft census: variant-manifest.json is strict-parsed
133
- // through checkSiblingJson (verify.mjs:1223) → checkJson (:742), so the WHOLE variantmodel_* family
163
+ // through checkSiblingJson (verify.mjs:1241) → checkJson (:742), so the WHOLE variantmodel_* family
134
164
  // reaches prelim-variants, not just the four literal tokens above.
135
165
  // CONVERSION 3 widened this family's SOURCE without widening its prefix. `acceptPrelimVariants` raises
136
166
  // `variantmodel_scope_layer_invalid`, `_scope_status_invalid`, `_scope_item_missing` and `_scope_pipe`
@@ -142,7 +172,7 @@ export const VOCABULARY = [
142
172
  // `fail(` / `throw new Error(` / `=>` string literals, and every record module returns
143
173
  // `{ok: false, reason}` instead — measured, all four extract ZERO tokens. So this row is authored, not
144
174
  // extracted, and nothing re-derives it if the module grows a member. Filed as.
145
- { token: "variantmodel_", stages: ["prelim-variants"], site: "driver/verify.mjs:1153 → 742 (JSON family); driver/prelim-variants-record.mjs acceptPrelimVariants (scope-ledger transport family)", family: "driver/variant-manifest-model.mjs (token-first throws) + driver/prelim-variants-record.mjs", dynamic: "D3" },
175
+ { token: "variantmodel_", stages: ["prelim-variants"], site: "driver/verify.mjs:1171 checkFindingsSibling → 742 (JSON family); driver/prelim-variants-record.mjs acceptPrelimVariants (scope-ledger transport family)", family: "driver/variant-manifest-model.mjs (token-first throws) + driver/prelim-variants-record.mjs", dynamic: "D3" },
146
176
  { token: "blindframe_", stages: ["blind-frame"], site: "driver/verify.mjs blindFrame → checkJson", family: "driver/blind-frame-model.mjs", dynamic: "D3" },
147
177
  // — THE SKEPTIC TRANSPORT FAMILY, WHICH HAD NO ROW AT ALL. Nine tokens minted by acceptSkeptic
148
178
  // and not one of them was covered here: the conversion that moved them to the acceptance boundary moved
@@ -417,33 +447,33 @@ export const TRIPWIRE_OUT_OF_SCOPE = [
417
447
  export const INNER_CODES = Object.freeze([
418
448
  // ── connotation-search.mjs — namespaced one-for-one by verify.mjs ────────────────────────────────
419
449
  //
420
- // CONNOTATION_FORM_REASONS at connotation-search.mjs:1731 is `CONNOTATION_REASONS` minus
450
+ // CONNOTATION_FORM_REASONS at connotation-search.mjs:1776 is `CONNOTATION_REASONS` minus
421
451
  // `no_recorded_queries`, and the `connotation_` family row (dynamic D1) is declared against exactly
422
452
  // that list. The four call codes are folded by a template — `connotation_${callFail.reason}` at
423
453
  // verify.mjs — so they are namespaced by construction rather than one branch at a time.
424
- { code: "call_never_made", mints: ["driver/connotation-search.mjs:2007"], rollsUpTo: ["connotation_call_never_made"],
454
+ { code: "call_never_made", mints: ["driver/connotation-search.mjs:2052"], rollsUpTo: ["connotation_call_never_made"],
425
455
  why: "CALL_AUDIT_ROWS. The typed transport's four call states, handed in by disposition-call-audit.mjs and namespaced at verify.mjs." },
426
- { code: "call_truncated", mints: ["driver/connotation-search.mjs:2008"], rollsUpTo: ["connotation_call_truncated"],
456
+ { code: "call_truncated", mints: ["driver/connotation-search.mjs:2053"], rollsUpTo: ["connotation_call_truncated"],
427
457
  why: "As call_never_made — same table, same projection." },
428
- { code: "call_schema_violation", mints: ["driver/connotation-search.mjs:2009"], rollsUpTo: ["connotation_call_schema_violation"],
458
+ { code: "call_schema_violation", mints: ["driver/connotation-search.mjs:2054"], rollsUpTo: ["connotation_call_schema_violation"],
429
459
  why: "As call_never_made — same table, same projection." },
430
- { code: "call_partial", mints: ["driver/connotation-search.mjs:2010"], rollsUpTo: ["connotation_call_partial"],
460
+ { code: "call_partial", mints: ["driver/connotation-search.mjs:2055"], rollsUpTo: ["connotation_call_partial"],
431
461
  why: "As call_never_made — same table, same projection. This is the pair #1211 cites as its worked example: the composite is covered, the bare form reaches no stage." },
432
- { code: "quote_unbound", mints: ["driver/connotation-search.mjs:2141"], rollsUpTo: ["connotation_quote_unbound"],
433
- why: "The ruled-but-unbound row. Projected at verify.mjs:1099, and reported only once nothing is unruled." },
434
- { code: "token_absent", mints: ["driver/connotation-search.mjs:2168"], rollsUpTo: ["connotation_token_absent"],
462
+ { code: "quote_unbound", mints: ["driver/connotation-search.mjs:2186"], rollsUpTo: ["connotation_quote_unbound"],
463
+ why: "The ruled-but-unbound row. Projected at verify.mjs:1450 unbound, and reported only once nothing is unruled." },
464
+ { code: "token_absent", mints: ["driver/connotation-search.mjs:2213"], rollsUpTo: ["connotation_token_absent"],
435
465
  why: "#592 split this out of no_ruling. Row-level only — repairs.mjs:352 says so in as many words: `never a top-level token`." },
436
- { code: "cite_absent", mints: ["driver/connotation-search.mjs:2177"], rollsUpTo: ["connotation_cite_absent"],
466
+ { code: "cite_absent", mints: ["driver/connotation-search.mjs:2222"], rollsUpTo: ["connotation_cite_absent"],
437
467
  why: "#592, as token_absent. repairs.mjs:353: `row-level only — never a top-level token`." },
438
- { code: "no_ruling", mints: ["driver/connotation-search.mjs:2184"], rollsUpTo: ["connotation_no_ruling"],
468
+ { code: "no_ruling", mints: ["driver/connotation-search.mjs:2229"], rollsUpTo: ["connotation_no_ruling"],
439
469
  why: "The residual the other two split off from, and it has representatives — see the mint site. Declared as a corrective token at repairs.mjs:308 and in stages.mjs's E1 rows, always namespaced." },
440
470
  // THE ONE THAT IS RENAMED, NOT NAMESPACED — and it is the reason this table stores the composite as
441
471
  // data rather than deriving it. Every derivation anyone would write is `connotation_` + the code, and
442
472
  // for this row that produces `connotation_no_recorded_queries`, which nothing mints and nothing covers.
443
473
  // verify.mjs:912-913 states the ruling: a sweep that did not RUN is a canonical-only decision with its
444
- // own token and its own remedy, so the projector at verify.mjs:909 deliberately does not handle it.
445
- { code: "no_recorded_queries", mints: ["driver/connotation-search.mjs:2025"], rollsUpTo: ["connotation_search_missing"],
446
- why: "RENAMED, not namespaced: verify.mjs emits `connotation_search_missing`. It is excluded from CONNOTATION_FORM_REASONS at connotation-search.mjs:1731 for exactly this reason." },
474
+ // own token and its own remedy, so the projector beside verify.mjs's CORRECTIONS_SECTION_RE deliberately does not handle it.
475
+ { code: "no_recorded_queries", mints: ["driver/connotation-search.mjs:2070"], rollsUpTo: ["connotation_search_missing"],
476
+ why: "RENAMED, not namespaced: verify.mjs emits `connotation_search_missing`. It is excluded from CONNOTATION_FORM_REASONS at connotation-search.mjs for exactly this reason." },
447
477
 
448
478
  // ── case-law-ledger.mjs — ONE token, the codes as census payload ─────────────────────────────────
449
479
  //
@@ -489,7 +519,7 @@ export const INNER_CODES = Object.freeze([
489
519
  // the census output would have been half a ruling. verify.mjs:1075 already states the rule this row
490
520
  // records: `coverage_form_damaged`, never a bare `form_damaged`.
491
521
  { code: "form_damaged",
492
- mints: ["driver/connotation-search.mjs:2030", "driver/connotation-search.mjs:2106", "driver/coverage-form.mjs:818"],
522
+ mints: ["driver/connotation-search.mjs:2075", "driver/connotation-search.mjs:2151", "driver/coverage-form.mjs:818"],
493
523
  rollsUpTo: ["connotation_form_damaged", "coverage_form_damaged"],
494
524
  why: "Minted in two lanes and namespaced per lane: verify.mjs:1019 for the meaning sweep, verify.mjs:1119 for the register digest. The namespacing is what keeps them apart — see verify.mjs:1075." },
495
525
  ]);
@@ -526,6 +556,10 @@ export const COVERED_SOURCES = [
526
556
  "report-overview-record.mjs",
527
557
  // Conversion 5 — the fan-out transport; it mints its own family including the bound-index refusals.
528
558
  "report-card-record.mjs",
559
+ // Conversion 11 — verify.mjs now reaches `digestAccountingGap`, the digest's exit gate, so the
560
+ // tripwire must read this module's token literals too. Without it the accounting family could grow a
561
+ // member that no vocabulary row covers and nothing would notice, which is this list's whole subject.
562
+ "register-digest-record.mjs",
529
563
  ];
530
564
 
531
565
  /**
@@ -41,7 +41,9 @@
41
41
  import { resolveEffectiveProfile, recipeProseGuard, platformEntryErrors } from "./profiles.mjs";
42
42
  import { wantsPortalRoute, PORTAL_ROUTE_UNAVAILABLE } from "./enqueue-schema.mjs";
43
43
  import { gateResolvedPolicy, loadRecipes } from "./search-policy.mjs";
44
- import { readFlagSnapshot, registerTerritoriesFor } from "./flag-snapshot.mjs";
44
+ import { resolveTerritories } from "./effective-scope.mjs";
45
+ import { uncoveredTerritories, registerReachRefusal } from "./register-coverage.mjs";
46
+ import { readFlagSnapshot, registerTerritoriesFor, registerLabelFor } from "./flag-snapshot.mjs";
45
47
  import { config } from "./driver.config.mjs";
46
48
  import { resolveRequest } from "./resolve-request.mjs";
47
49
  import { checkResolvedProduct } from "./scope-rules.mjs";
@@ -56,10 +58,14 @@ import { checkResolvedProduct } from "./scope-rules.mjs";
56
58
  * `readable` says whether the profile store answered at all — the input `checkClearanceScopeRules`
57
59
  * needs to tell "this account has no default territories" apart from "we could not read the account".
58
60
  */
59
- /** The wired register's covered territories, read once per gate call. Never throws: a door that cannot
60
- * read the snapshot must still open. */
61
- function snapshotTerritories() {
62
- try { return registerTerritoriesFor(readFlagSnapshot(config.poolRootOrNull)); } catch { return undefined; }
61
+ /** The wired register as a door needs it: what it covers, and what to CALL it in a sentence a client
62
+ * reads. One read, both answers. Never throws — a door that cannot read the snapshot must still open,
63
+ * and `territories: undefined` is the fail-open answer every layer below already speaks. */
64
+ function snapshotRegister() {
65
+ try {
66
+ const snap = readFlagSnapshot(config.poolRootOrNull);
67
+ return { territories: registerTerritoriesFor(snap), label: registerLabelFor(snap) };
68
+ } catch { return { territories: undefined, label: null }; }
63
69
  }
64
70
 
65
71
  export function resolveForDoor(job) {
@@ -92,8 +98,12 @@ export function resolveForDoor(job) {
92
98
  * products.mjs and search-policy.mjs, for every door.
93
99
  */
94
100
  export function gateResolvedRequest({ job = null, profile = null, resolved = null, readable = true } = {},
95
- { availability = true, registerTerritories = undefined } = {}) {
101
+ { availability = true, registerTerritories = undefined, registerLabel = undefined } = {}) {
96
102
  const out = { errors: [], warnings: [], byCheck: {} };
103
+ // Read at most once per gate call, and not at all when both arms were given their answer — a test
104
+ // driving a Signa-shaped deployment must not need a snapshot on disk to do it.
105
+ let snapshot;
106
+ const register = () => (snapshot ??= snapshotRegister());
97
107
  // A resolution that could not be taken is not a refusal — see the fail-open note in the header.
98
108
  if (!resolved) return out;
99
109
  // A CLARIFY IS RELAYED VERBATIM. It is already an actionable sentence naming the selector that could
@@ -114,10 +124,34 @@ export function gateResolvedRequest({ job = null, profile = null, resolved = nul
114
124
  //
115
125
  // `undefined` is the fail-open answer at every layer below, so an unreadable or absent snapshot
116
126
  // leaves this arm silent and the runner's wall still decides — the door rule stated in the header.
117
- const terr = registerTerritories !== undefined ? registerTerritories : snapshotTerritories();
127
+ const terr = registerTerritories !== undefined ? registerTerritories : register().territories;
118
128
  const gateMsg = gateResolvedPolicy(resolved, { registerTerritories: terr });
119
129
  if (gateMsg) { out.errors.push(gateMsg); return out; }
120
130
  }
131
+ // ── A TERRITORY THIS REQUEST NAMES THAT THE WIRED REGISTER CANNOT SEARCH ──────────────────────────
132
+ //
133
+ // OUTSIDE the availability block, and that placement is the whole correctness of this arm. The portal
134
+ // and plan_run pass `availability:false` because they word an unavailable PRODUCT in their own words
135
+ // (the header's staff-prose split) — so an arm written inside that block cannot fire at the two doors
136
+ // a client actually orders through, and it would fail to fire SILENTLY, green, on the case the ruling
137
+ // of 2026-09-17 is about. This refusal carries no switch name and no internal key, so unlike the
138
+ // availability twin it is the same sentence on every surface and needs no client-facing rewording.
139
+ //
140
+ // THE TERRITORIES ARE RESOLVED HERE, NOT THREADED IN. `resolveTerritories` is the same ladder
141
+ // effective-scope.mjs runs for the scope a door prints beside this refusal, so the two cannot
142
+ // disagree. Asking each of the six doors to pass its own scope would let one forget the argument and
143
+ // fail open in silence — the exact shape `register-coverage-doors.test.mjs` exists to catch one layer
144
+ // up. One call, in the one gate they all share, covers every door by construction.
145
+ //
146
+ // Fail-open on a throw, the door's rule: an unreadable profile store must not stop somebody searching.
147
+ {
148
+ let named = [];
149
+ try { named = resolveTerritories(job ?? {}, profile, resolved?.recipeScope ?? null).jurisdictions ?? []; } catch { named = []; }
150
+ const terr = registerTerritories !== undefined ? registerTerritories : register().territories;
151
+ const label = registerLabel !== undefined ? registerLabel : register().label;
152
+ const refusal = registerReachRefusal(uncoveredTerritories(named, terr), label);
153
+ if (refusal) { out.errors.push(refusal); return out; }
154
+ }
121
155
  const gates = checkResolvedProduct({ job, profile, resolved, profileReadable: profile !== null && readable });
122
156
  out.errors.push(...gates.errors);
123
157
  out.warnings.push(...gates.warnings);