clearotron 0.3.2-beta.8 → 0.3.2-beta.9

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 (238) hide show
  1. package/.env.example +34 -3
  2. package/CONTRIBUTING.md +8 -8
  3. package/INSTALL.md +6 -6
  4. package/SECURITY.md +3 -3
  5. package/bin/brandowner.mjs +3 -3
  6. package/bin/framework-preflight.mjs +1 -1
  7. package/bin/start.mjs +18 -4
  8. package/build-info.json +2 -2
  9. package/docs/DELIVERY.md +2 -1
  10. package/docs/INTAKE.md +1 -1
  11. package/docs/ONBOARDING.md +1 -1
  12. package/docs/architecture/03-run-lifecycle.md +6 -6
  13. package/docs/architecture/04-configuration-reference.md +6 -3
  14. package/docs/architecture/05-config-governance.md +6 -1
  15. package/docs/architecture/05-customer-profiles.md +2 -2
  16. package/docs/architecture/06-operations-runbook.md +3 -3
  17. package/docs/architecture/08-development-guide.md +6 -6
  18. package/docs/configuration.md +5 -5
  19. package/docs/decisions/0003-credential-model.md +1 -1
  20. package/docs/writing-standard.md +4 -0
  21. package/driver/CHANGELOG.md +48 -0
  22. package/driver/README.md +3 -3
  23. package/driver/binding-layers.mjs +1 -1
  24. package/driver/citation-census.json +3 -3
  25. package/driver/{prelim-variants-record.mjs → clearance-variants-record.mjs} +24 -24
  26. package/driver/common-law-receipts.mjs +2 -2
  27. package/driver/company-bundle.mjs +3 -3
  28. package/driver/compose-read.mjs +8 -14
  29. package/driver/consumption-ledger.mjs +2 -2
  30. package/driver/contract-arm2-baseline.json +2 -3
  31. package/driver/contract-dictation-registry.mjs +19 -19
  32. package/driver/contract-e3-backlog.mjs +19 -19
  33. package/driver/contract-e3-baseline.json +14 -14
  34. package/driver/contract-vocabulary.mjs +24 -17
  35. package/driver/deliver-trigger.sh +16 -16
  36. package/driver/demo-container.mjs +3 -3
  37. package/driver/dev-portal.mjs +3 -3
  38. package/driver/disposition-call.mjs +1 -1
  39. package/driver/doubt-ledger.mjs +2 -2
  40. package/driver/drainer-identity.mjs +34 -8
  41. package/driver/driver.config.mjs +95 -45
  42. package/driver/engine/mcp/README.md +1 -1
  43. package/driver/engine/mcp/dispositions-server.mjs +3 -3
  44. package/driver/engine/mcp/gather-config.mjs +9 -9
  45. package/driver/engine/mcp/perplexity-server.mjs +2 -2
  46. package/driver/engine/mcp/recording-server.mjs +5 -5
  47. package/driver/enqueue-schema.mjs +6 -2
  48. package/driver/findings-model.mjs +5 -2
  49. package/driver/flag-snapshot.mjs +6 -3
  50. package/driver/form-neighbourhood.mjs +54 -7
  51. package/driver/framework.mjs +4 -4
  52. package/driver/gateway.mjs +12 -6
  53. package/driver/jx-lanes.mjs +2 -2
  54. package/driver/jx-units.mjs +1 -1
  55. package/driver/jx.mjs +30 -2
  56. package/driver/knockout-review-record.mjs +56 -4
  57. package/driver/known-conflicts.mjs +1 -1
  58. package/driver/named-band.mjs +1 -33
  59. package/driver/ordinary-words.mjs +51 -0
  60. package/driver/outbox-backoff.mjs +31 -16
  61. package/driver/package.json +1 -1
  62. package/driver/partial-payload-baseline.json +2 -2
  63. package/driver/phase0.mjs +3 -3
  64. package/driver/pipeline-knockout.mjs +5 -5
  65. package/driver/pipeline.mjs +206 -68
  66. package/driver/placement-form.mjs +77 -1
  67. package/driver/placement-model.mjs +1 -1
  68. package/driver/portal-report.mjs +92 -5
  69. package/driver/portal-service.mjs +34 -8
  70. package/driver/portal-upstream.mjs +1 -1
  71. package/driver/preserve-merge.mjs +3 -3
  72. package/driver/product-rows.mjs +2 -2
  73. package/driver/products.mjs +1 -1
  74. package/driver/profiles/README.md +3 -3
  75. package/driver/profiles/demo-brand-owner.json +2 -2
  76. package/driver/profiles.mjs +55 -17
  77. package/driver/progress.mjs +18 -8
  78. package/driver/provider-usage.mjs +8 -8
  79. package/driver/publish/index.mjs +110 -5
  80. package/driver/publish/knockout.mjs +29 -4
  81. package/driver/publish/pool-admin.mjs +1 -1
  82. package/driver/publish/publish-inputs.mjs +18 -2
  83. package/driver/publish/render-knockout.mjs +115 -24
  84. package/driver/publish/render.mjs +153 -34
  85. package/driver/publish/search-depth.mjs +133 -4
  86. package/driver/publish/templates/report.css +60 -3
  87. package/driver/publish/xlsx.mjs +8 -1
  88. package/driver/queue-order.mjs +2 -2
  89. package/driver/recording-agreement.mjs +1 -1
  90. package/driver/reference-score.mjs +1 -1
  91. package/driver/register-count.mjs +50 -5
  92. package/driver/register-coverage.mjs +67 -0
  93. package/driver/register-grant-vocabulary.mjs +1 -1
  94. package/driver/register-plan.mjs +19 -2
  95. package/driver/registry-fidelity.mjs +3 -3
  96. package/driver/repair-composers.mjs +1 -1
  97. package/driver/repair-contract.mjs +1 -1
  98. package/driver/replay-archive.mjs +6 -6
  99. package/driver/report-overview-record.mjs +2 -2
  100. package/driver/run-requirements.mjs +3 -3
  101. package/driver/runner.mjs +2 -2
  102. package/driver/scope-facts.mjs +20 -5
  103. package/driver/scope-ledger.mjs +5 -5
  104. package/driver/search-policy.mjs +22 -12
  105. package/driver/skills/README.md +15 -15
  106. package/driver/skills/blind-frame/SKILL.md +2 -2
  107. package/driver/skills/case-law-citation/SKILL.md +4 -4
  108. package/driver/skills/case-law-citation/sources/eurlex.md +1 -1
  109. package/driver/skills/{prelim-common-law → clearance-common-law}/SKILL.md +22 -22
  110. package/driver/skills/{prelim-common-law → clearance-common-law}/perplexity-prompts.md +1 -1
  111. package/driver/skills/{prelim-register → clearance-register}/SKILL.md +10 -10
  112. package/driver/skills/{prelim-register → clearance-register}/digest.md +2 -2
  113. package/driver/skills/{prelim-register → clearance-register}/providers/README.md +1 -1
  114. package/driver/skills/{prelim-register → clearance-register}/providers/clarivate.md +37 -35
  115. package/driver/skills/{prelim-register → clearance-register}/providers/corsearch.md +20 -11
  116. package/driver/skills/{prelim-register → clearance-register}/providers/signa.md +5 -5
  117. package/driver/skills/{prelim-register → clearance-register}/register-recipes.md +3 -3
  118. package/driver/skills/{prelim-register → clearance-register}/status-rules.md +2 -2
  119. package/driver/skills/{prelim-register → clearance-register}/stealth-filer-indicators.md +1 -1
  120. package/driver/skills/{prelim-register → clearance-register}/unit.md +2 -2
  121. package/driver/skills/{prelim-search → clearance-search}/SKILL.md +31 -31
  122. package/driver/skills/{prelim-search → clearance-search}/delivery-contract.md +1 -1
  123. package/driver/skills/{prelim-search → clearance-search}/phase2-execution.md +18 -18
  124. package/driver/skills/{prelim-search → clearance-search}/synthesis-rules.md +7 -7
  125. package/driver/skills/{prelim-variants → clearance-variants}/SKILL.md +18 -18
  126. package/driver/skills/{prelim-variants → clearance-variants}/transliteration-scripts.md +5 -5
  127. package/driver/skills/frame-diff/SKILL.md +1 -1
  128. package/driver/skills/knockout-assess/SKILL.md +10 -7
  129. package/driver/skills/matter-frame/SKILL.md +3 -3
  130. package/driver/skills/narrative-refutation/SKILL.md +9 -9
  131. package/driver/skills/placement-inquiry/SKILL.md +5 -5
  132. package/driver/stage-context.mjs +1 -1
  133. package/driver/stages-knockout.mjs +4 -4
  134. package/driver/stages.mjs +53 -53
  135. package/driver/status-snapshot.mjs +2 -2
  136. package/driver/suite-census.json +218 -92
  137. package/driver/surface-exit-verdict.mjs +58 -0
  138. package/driver/systemd/README.md +2 -2
  139. package/driver/systemd/clearotron-worker.service +1 -1
  140. package/driver/terminal-clamp.mjs +2 -0
  141. package/driver/usage-ledger.mjs +1 -1
  142. package/driver/variant-manifest-model.mjs +4 -4
  143. package/driver/verify-knockout.mjs +27 -0
  144. package/driver/verify.mjs +67 -6
  145. package/driver/whatif-queue.mjs +1 -1
  146. package/driver/wordlists/en.txt +63906 -0
  147. package/mcp-server/CHANGELOG.md +4 -0
  148. package/mcp-server/README.md +1 -1
  149. package/mcp-server/lib/README.md +1 -1
  150. package/mcp-server/lib/options.mjs +8 -7
  151. package/mcp-server/lib/plan.mjs +18 -2
  152. package/mcp-server/lib/runs.mjs +1 -1
  153. package/mcp-server/lib/usage.mjs +3 -3
  154. package/mcp-server/lib/whatif.mjs +1 -1
  155. package/mcp-server/package.json +1 -1
  156. package/mcp-server/server.mjs +3 -0
  157. package/package.json +12 -11
  158. package/portal-ui/dist/assets/{index-CVOIvdhc.css → index-CtvwLCti.css} +207 -3
  159. package/portal-ui/dist/assets/{index-6jzO9HiX.js → index-EVaSo5-g.js} +1459 -482
  160. package/portal-ui/dist/index.html +2 -2
  161. package/portal-ui/package.json +1 -1
  162. package/providers/README.md +1 -1
  163. package/providers/_shared/enumerate.mjs +6 -6
  164. package/providers/_shared/execute-plan.mjs +3 -3
  165. package/providers/_shared/ledger.mjs +119 -5
  166. package/providers/_shared/provider-text.mjs +2 -2
  167. package/providers/_shared/screen.mjs +2 -2
  168. package/providers/_shared/script-form.mjs +3 -3
  169. package/providers/_shared/territory-codes.mjs +23 -3
  170. package/providers/clarivate/README.md +1 -1
  171. package/providers/clarivate/src/capabilities.js +12 -12
  172. package/providers/clarivate/src/core.js +37 -43
  173. package/providers/corsearch/README.md +1 -1
  174. package/providers/corsearch/src/capabilities.js +5 -5
  175. package/providers/corsearch/src/core.js +3 -3
  176. package/providers/oauth-mcp-bridge/CHANGELOG.md +4 -0
  177. package/providers/oauth-mcp-bridge/package.json +1 -1
  178. package/providers/perplexity/src/core.js +1 -1
  179. package/providers/signa/README.md +1 -1
  180. package/providers/signa/src/capabilities.js +42 -49
  181. package/providers/signa/src/core.js +106 -29
  182. package/providers/uspto-local/src/sync.js +1 -1
  183. package/scripts/README.md +1 -0
  184. package/scripts/ask-ai-render-check.mjs +127 -1
  185. package/scripts/authority-boundary-probe.mjs +4 -4
  186. package/scripts/backfill-started-at.mjs +2 -2
  187. package/scripts/census-merge-driver.mjs +33 -2
  188. package/scripts/citation-anchor-report.mjs +181 -0
  189. package/scripts/dead-names.mjs +1 -1
  190. package/scripts/deprecate-below.mjs +66 -8
  191. package/scripts/drain-preflight.mjs +1 -1
  192. package/scripts/e2e.mjs +174 -0
  193. package/scripts/env-audit.mjs +27 -0
  194. package/scripts/env-classify.mjs +20 -2
  195. package/scripts/freeze-example-run.mjs +20 -10
  196. package/scripts/live-surface-check.mjs +124 -41
  197. package/scripts/markdown-link-check.mjs +1 -1
  198. package/scripts/merge-shape-check.mjs +242 -0
  199. package/scripts/mint-names-in-force.mjs +5 -5
  200. package/scripts/mint-offered-territories.mjs +72 -0
  201. package/scripts/mint-public-residue.mjs +2 -2
  202. package/scripts/mint-reference-strip-backlog.mjs +2 -2
  203. package/scripts/mint-suite-census.mjs +75 -2
  204. package/scripts/mint-writing-standard-backlog.mjs +2 -2
  205. package/scripts/purge-runs.mjs +7 -7
  206. package/scripts/reconcile-runs.mjs +2 -2
  207. package/scripts/release-approve-parked.mjs +20 -2
  208. package/scripts/release-await-cut.mjs +120 -1
  209. package/scripts/release-note-required.mjs +76 -8
  210. package/scripts/report-header-render-check.mjs +164 -0
  211. package/shared/brand.mjs +27 -0
  212. package/shared/connect-clients.mjs +39 -11
  213. package/shared/env-aliases.mjs +1 -1
  214. package/shared/identifier-scan.mjs +65 -9
  215. package/shared/identifier-sentinels.mjs +22 -0
  216. package/shared/names-in-force.mjs +3 -1
  217. package/shared/offered-territories.json +738 -0
  218. package/shared/pre-rename-spellings.mjs +53 -0
  219. package/shared/reference-guard-classes.mjs +40 -2
  220. package/shared/stdio-connect.mjs +39 -4
  221. package/shared/tree-commit.mjs +48 -0
  222. /package/driver/skills/{prelim-register → clearance-register}/providers/euipo.md +0 -0
  223. /package/driver/skills/{prelim-register → clearance-register}/providers/free-tier.md +0 -0
  224. /package/driver/skills/{prelim-register → clearance-register}/providers/uspto-local.md +0 -0
  225. /package/driver/skills/{prelim-search → clearance-search}/field-doctrine-pharma.md +0 -0
  226. /package/driver/skills/{prelim-search → clearance-search}/firm-wide-reasoning.md +0 -0
  227. /package/driver/skills/{prelim-search → clearance-search}/report-prose.md +0 -0
  228. /package/driver/skills/{prelim-search → clearance-search}/risk-framework-demo.manifest.json +0 -0
  229. /package/driver/skills/{prelim-search → clearance-search}/risk-framework-demo.md +0 -0
  230. /package/driver/skills/{prelim-search → clearance-search}/risk-framework-triage.manifest.json +0 -0
  231. /package/driver/skills/{prelim-search → clearance-search}/risk-framework-triage.md +0 -0
  232. /package/driver/skills/{prelim-search → clearance-search}/risk-framework.manifest.json +0 -0
  233. /package/driver/skills/{prelim-search → clearance-search}/risk-framework.md +0 -0
  234. /package/driver/skills/{prelim-search → clearance-search}/template-formatting.md +0 -0
  235. /package/driver/skills/{prelim-search → clearance-search}/templates/email/generic.md +0 -0
  236. /package/driver/skills/{prelim-search → clearance-search}/templates/search-request-form.html +0 -0
  237. /package/driver/skills/{prelim-search → clearance-search}/worked-examples-demo.md +0 -0
  238. /package/driver/skills/{prelim-search → clearance-search}/worked-examples.md +0 -0
@@ -1,5 +1,53 @@
1
1
  # clearotron-driver
2
2
 
3
+ ## 0.3.2-beta.9
4
+
5
+ ### Patch Changes
6
+
7
+ - 09f51e0: Fixed: A country named in words now reaches its register, and naming one in words and by code no longer counts as two places.
8
+ - 09f51e0: Fixed: A search that failed can be picked up again with its codename alone. The command the engine prints when a search stops no longer names a job file that is no longer on the machine.
9
+ - 09f51e0: For operators: Resuming a failed search by its codename now works without the original job file, and refuses by name when the run's record is incomplete.
10
+ - 09f51e0: Fixed: A knockout report no longer scrolls sideways on a phone when a finding cites a long web address.
11
+ - 09f51e0: Fixed: a knockout report's Registers counted row reads "186 registers, on" the register service, without a list of territories folded under it.
12
+ - 09f51e0: New: A knockout search now delivers the engine's own assessment and findings alongside the report, as a full clearance already did.
13
+ - 09f51e0: Fixed: A report no longer says the local-language investigation did not run when the run's own record shows it did.
14
+ - 09f51e0: Fixed: On a phone, the rights-holder panel now shows a scrollbar when its rows run past the right edge.
15
+
16
+ Fixed: "Web and marketplace names" lists names again. Readings of what a mark means are carried by the connotation section, where they were already stated in full.
17
+ - 09f51e0: Fixed: when a register reports only that it holds more than a figure, the knockout counts table and workbook show that figure, not "not available".
18
+ - 09f51e0: Fixed: Preliminary searches on one register now report the registered marks the assessment found, instead of a register section left empty.
19
+
20
+ Fixed: A search whose register assessment cannot be recorded now stops with an error instead of delivering a report silent on the register.
21
+ - 09f51e0: Fixed: A report's section links now sit in the header and stay on screen while you read, instead of scrolling away.
22
+ - 09f51e0: Fixed: A report no longer reads "Case-law research could not be completed for ." when the search covered a register that does not publish per-country records.
23
+ - 09f51e0: New: A report states whether the local-language investigation ran at the depth configured for the matter.
24
+ - 09f51e0: Fixed: On a knockout report, the risk band marker no longer overlaps the words above it.
25
+ - 09f51e0: Fixed: A running search now reports the stage it is on, not the last one finished, so progress no longer appears to go backwards.
26
+ - 09f51e0: Fixed: A knockout report no longer states, for each name, whether that name should proceed to a full clearance search. It reports what the screen found.
27
+ - 09f51e0: New: A report table that continues past the right edge now shows a scrollbar, so it is clear there is more to see.
28
+ - 09f51e0: Fixed: When a register search did not finish, the verdict's condition no longer names the engine's internal label for the unfinished part.
29
+ - 09f51e0: New: a worldwide search names the register service that searches it, on the New clearance form and on the report's coverage line.
30
+ - 09f51e0: Fixed: Worldwide searches on a register that keeps no record archive now show how many register records were read and in which countries.
31
+ - 09f51e0: Fixed: Searches of a named company's own trademark portfolio now run on every register. On one register they were refused before the search was sent, and the report told the reader those holdings could not be reached.
32
+ - 09f51e0: Fixed: After upgrading, existing companies, past clearances and queued searches stay visible, with no folder to rename and no company file to edit.
33
+
34
+ Fixed: A company file that cannot be read no longer empties the company list; that company is named with the reason instead.
35
+ - 09f51e0: Fixed: each finding's "Ask AI about this finding" button in a report now opens Ask AI, with that finding's number in the question.
36
+ - 09f51e0: New: Searches no longer look up ordinary English words one letter away from the mark that sound different, such as CODE beside CORE.
37
+ - 09f51e0: Before you upgrade: reports left waiting in the delivery folder's old name are found and sent again. Nothing needs moving, and none is sent twice.
38
+ - 09f51e0: Fixed: The forward-decisions section of a clearance report is headed "What happens next", as the approved design heads it.
39
+ - 09f51e0: New: A clearance report carries a section strip along the top, so a reader can jump to the findings, the next steps or what was searched.
40
+ - 09f51e0: New: The new clearance form now offers every country a supported register can search, not a fixed list of 37.
41
+ - 09f51e0: Fixed: The new clearance form no longer repeats in paragraphs what each product row and each place already say.
42
+ - 09f51e0: Fixed: on a phone, the list of clearances made the whole page slide sideways instead of scrolling the table. The table now scrolls on its own and the page stays put.
43
+ - 09f51e0: Fixed: on a narrow window the buttons at the end of each clearance row pushed the page sideways, and every date broke onto two lines. The buttons now fit the space they are given and the date stays on one line.
44
+ - 09f51e0: Before you upgrade: the folder a finished report waits in while it is sent has been renamed. If you have never set that folder yourself, nothing needs moving. Reports already waiting in the old folder are still sent.
45
+ - 09f51e0: Fixed: Knockout reports no longer print a caveat line under the register counts table.
46
+ - 09f51e0: New: A knockout report carries a section strip along the top, so a reader can jump to the conflicts, the filings or the next steps.
47
+ - 09f51e0: Fixed: A mark whose official record could not be retrieved is no longer listed as a condition on the verdict. The report still names it where the search's coverage is set out.
48
+ - 09f51e0: Fixed: Installs inside WSL now show a second setup command, for an assistant running inside WSL as well as one on Windows.
49
+ - 09f51e0: Fixed: a clearance report's "What was searched" section shows register totals, counts per country and a link to the audit workbook, as designed.
50
+
3
51
  ## 0.3.2-beta.8
4
52
 
5
53
  ### Patch Changes
package/driver/README.md CHANGED
@@ -89,7 +89,7 @@ kind of thing a module is before you open it.
89
89
  - The `anthropic-agent` engine shells `claude -p` per stage (stream-json, blocking to the final
90
90
  result); warm retries `--resume` the same session, fresh retries start clean — see
91
91
  `engine/CONTRACT.md §3` for the model-tier map and `§8` for runtime caveats.
92
- - Stage identity keys are `prelim-<slug>-<codename>-<stage>`; telemetry ledgers record every attempt.
92
+ - Stage identity keys are `clearance-<slug>-<codename>-<stage>`; telemetry ledgers record every attempt.
93
93
  - A stage's output is judged by **file truth** (the validator on the written artifact), never by the
94
94
  engine's own success claim.
95
95
  - Retries never re-dispatch the same second an attempt failed: every retry waits
@@ -114,8 +114,8 @@ conformance → paid run).
114
114
 
115
115
  ## Single path
116
116
 
117
- prelim-search runs **only** via this driver — every intake path lands a job JSON in a queue and the
117
+ clearance-search runs **only** via this driver — every intake path lands a job JSON in a queue and the
118
118
  driver does the rest. There is no legacy spawn path and no enable/dormant flag. (The old
119
119
  LLM-orchestrator `sessions_yield` WAIT/PROCEED/SUPPRESS machinery was stripped from
120
- `skills/prelim-search/phase2-execution.md` — only the historical removal note at its head remains;
120
+ `skills/clearance-search/phase2-execution.md` — only the historical removal note at its head remains;
121
121
  the file is live methodology the stages read.)
@@ -14,7 +14,7 @@
14
14
  //
15
15
  // AND IT PRESENTED AS SEARCHED, which is the part that made it a compliance defect rather than a
16
16
  // coverage one. The disclosure machinery only describes territories the compiler recorded as
17
- // UNREACHABLE. These were recorded as reached, so there was no row to render, and `prelim-search`'s
17
+ // UNREACHABLE. These were recorded as reached, so there was no row to render, and `clearance-search`'s
18
18
  // rule against rendering a deferred jurisdiction as a clean negative had nothing to fire on.
19
19
  //
20
20
  // ── TWO FACTS, KEPT APART ON PURPOSE ────────────────────────────────────────────────────────────────
@@ -1,5 +1,5 @@
1
1
  {
2
- "citations": 545,
3
- "files": 3878,
4
- "checkable": 105
2
+ "citations": 489,
3
+ "files": 3945,
4
+ "checkable": 126
5
5
  }
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-only
2
2
  // Copyright 2026 Cordillera Sàrl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
3
- // prelim-variants-record.mjs — the recording transport for the variant manifest.
3
+ // clearance-variants-record.mjs — the recording transport for the variant manifest.
4
4
  //
5
5
  // Conversion 3, after blind-frame, skeptic, frame-diff and matter-frame. It is
6
6
  // the first conversion whose ruling includes CLASS 3, and the first that can DELETE a derivation rather
@@ -17,7 +17,7 @@
17
17
  // O3c measured the cost of that hand-formatting directly: 9 Bash calls with 4 WRITES across 15 attempts,
18
18
  // and the shape is `python3 -c` over `variant-manifest.json` — the seat pre-checking its own JSON before
19
19
  // saving it. That is CLASS 3, and the design's ruling is that such a check does not get a compute tool:
20
- // it moves to the ACCEPTANCE BOUNDARY. `acceptPrelimVariants` measures on accept and refuses with the
20
+ // it moves to the ACCEPTANCE BOUNDARY. `acceptClearanceVariants` measures on accept and refuses with the
21
21
  // measured value, so the check runs on every call instead of when a seat remembers to run it.
22
22
  //
23
23
  // ── AND IT DELETES A DERIVATION, WHICH IS THE REAL PRIZE ────────────────────────────────────────────
@@ -45,8 +45,8 @@ export const PROSE_FILE = "variant-manifest.md";
45
45
  const SCHEMA_VERSION = 1;
46
46
 
47
47
  /** Where the call's evidence lives — the driver's own record of what the seat handed it. */
48
- export function prelimVariantsCallPaths(runDir) {
49
- const dir = driverDir(runDir, "prelim-variants-calls");
48
+ export function clearanceVariantsCallPaths(runDir) {
49
+ const dir = driverDir(runDir, "clearance-variants-calls");
50
50
  return { dir, payload: join(dir, "call-001.json"), accepted: join(dir, "accepted.json") };
51
51
  }
52
52
 
@@ -107,7 +107,7 @@ export function renderScopeLedgerTable(rows) {
107
107
  * Rendering from the parsed model is what makes the two artifacts one statement: they cannot disagree
108
108
  * about a variant, because both are projections of one validated object. PURE.
109
109
  */
110
- export function renderPrelimVariants(model, scopeRows) {
110
+ export function renderClearanceVariants(model, scopeRows) {
111
111
  // ── HEADING DEPTH IS LOAD-BEARING, AND THIS IS THE ONE THING IN THIS FILE NOT TO "TIDY" ────────────
112
112
  //
113
113
  // `variantsManifestAudit` (common-law-receipts.mjs) arms a term collector on any heading matching
@@ -151,7 +151,7 @@ export function renderPrelimVariants(model, scopeRows) {
151
151
  ...model.search_floor.map((a) => `- ${a}`), "");
152
152
 
153
153
  out.push(...renderScopeLedgerTable(scopeRows));
154
- out.push("---", "", "Rendered by the driver from the stage's `record_prelim_variants` call. "
154
+ out.push("---", "", "Rendered by the driver from the stage's `record_clearance_variants` call. "
155
155
  + `The structured model in ${MODEL_FILE} is the authority for the terms, and scope-ledger.json for the `
156
156
  + "ledger; this file is their human-readable projection.", "");
157
157
  return out.join("\n");
@@ -178,8 +178,8 @@ const DECLARED = Object.freeze({
178
178
  export const refuseUndeclared = (params) => refuseUndeclaredShared(params, DECLARED, "variantmodel");
179
179
 
180
180
  /** The last ACCEPTED call for this run, or null. */
181
- export function lastAcceptedPrelimVariants(runDir) {
182
- return lastAccepted(prelimVariantsCallPaths(String(runDir ?? "")).accepted, readFileSync);
181
+ export function lastAcceptedClearanceVariants(runDir) {
182
+ return lastAccepted(clearanceVariantsCallPaths(String(runDir ?? "")).accepted, readFileSync);
183
183
  }
184
184
 
185
185
  /**
@@ -190,7 +190,7 @@ export function lastAcceptedPrelimVariants(runDir) {
190
190
  * Preserving rather than requiring, because nothing here can tell a first call from a repair and a
191
191
  * product refusal is never a pass. See preserve-merge.mjs for the class.
192
192
  */
193
- export function mergePrelimVariantsCall(stored, received) {
193
+ export function mergeClearanceVariantsCall(stored, received) {
194
194
  const base = stored ?? {};
195
195
  return {
196
196
  mark: received?.mark,
@@ -207,7 +207,7 @@ export function mergePrelimVariantsCall(stored, received) {
207
207
  };
208
208
  }
209
209
 
210
- export function acceptPrelimVariants(params) {
210
+ export function acceptClearanceVariants(params) {
211
211
  const model = {
212
212
  schema_version: SCHEMA_VERSION,
213
213
  mark: params?.mark,
@@ -250,7 +250,7 @@ export function acceptPrelimVariants(params) {
250
250
  scopeRows.push({ layer, item, status, reason, reopen_trigger });
251
251
  }
252
252
 
253
- return { ok: true, model: parsed, scopeRows, content: renderPrelimVariants(parsed, scopeRows) };
253
+ return { ok: true, model: parsed, scopeRows, content: renderClearanceVariants(parsed, scopeRows) };
254
254
  }
255
255
 
256
256
  /**
@@ -263,8 +263,8 @@ export function acceptPrelimVariants(params) {
263
263
  * the first two, so a crash between writes leaves the run with its load-bearing files and a missing
264
264
  * restatement rather than a restatement of something never stored.
265
265
  */
266
- export function recordPrelimVariants(runDir, received, { now = () => new Date().toISOString() } = {}) {
267
- const { dir, payload } = prelimVariantsCallPaths(String(runDir ?? ""));
266
+ export function recordClearanceVariants(runDir, received, { now = () => new Date().toISOString() } = {}) {
267
+ const { dir, payload } = clearanceVariantsCallPaths(String(runDir ?? ""));
268
268
  // — ONE FILE PER CALL, refusals included. This wrote a single fixed `call-001.json`,
269
269
  // so a turn refused and then re-sent kept only the survivor: the file whose header promises "including
270
270
  // calls that were refused" held the one call that was not. Sequence 1 still resolves to `call-001.json`,
@@ -288,8 +288,8 @@ export function recordPrelimVariants(runDir, received, { now = () => new Date().
288
288
  if (undeclared) {
289
289
  return { written: null, refused: undeclared, captured: closeCapture({ ok: false, refused: undeclared }), capture_failed: captureFailed };
290
290
  }
291
- const call = mergePrelimVariantsCall(lastAcceptedPrelimVariants(runDir), received);
292
- const verdict = acceptPrelimVariants(call);
291
+ const call = mergeClearanceVariantsCall(lastAcceptedClearanceVariants(runDir), received);
292
+ const verdict = acceptClearanceVariants(call);
293
293
  if (!verdict.ok) {
294
294
  return { written: null, refused: verdict.reason, captured: closeCapture({ ok: false, refused: verdict.reason }), capture_failed: captureFailed };
295
295
  }
@@ -299,7 +299,7 @@ export function recordPrelimVariants(runDir, received, { now = () => new Date().
299
299
  try {
300
300
  writeFileSync(at, JSON.stringify(verdict.model, null, 2) + "\n");
301
301
  // Step 5. BEST-EFFORT, in its own try — see report-overview-record.mjs for why.
302
- try { writeFileSync(prelimVariantsCallPaths(String(runDir ?? "")).accepted, acceptedEnvelope(call, now())); }
302
+ try { writeFileSync(clearanceVariantsCallPaths(String(runDir ?? "")).accepted, acceptedEnvelope(call, now())); }
303
303
  catch { /* a lost base is never a lost artifact */ }
304
304
  writeFileSync(proseAt, verdict.content);
305
305
  } catch (e) {
@@ -320,7 +320,7 @@ export function recordPrelimVariants(runDir, received, { now = () => new Date().
320
320
 
321
321
  /** The typed scope-ledger rows, for the driver's own serialisation. PURE — no re-parse of the table. */
322
322
  export function recordedScopeRows(received) {
323
- const v = acceptPrelimVariants(received);
323
+ const v = acceptClearanceVariants(received);
324
324
  return v.ok ? v.scopeRows : [];
325
325
  }
326
326
 
@@ -332,7 +332,7 @@ export function recordedScopeRows(received) {
332
332
  * and it carried no ledger rows" — which is a manifest with an empty ledger, not a manifest to re-parse.
333
333
  * Collapsing the two would send the driver back to the table on a run that had already answered.
334
334
  *
335
- * The rows are re-validated through `acceptPrelimVariants` rather than trusted raw out of the capture:
335
+ * The rows are re-validated through `acceptClearanceVariants` rather than trusted raw out of the capture:
336
336
  * the capture records what ARRIVED, untidied, including a refused call's params. IMPURE (reads the run).
337
337
  */
338
338
  export function recordedScopeLedgerRows(runDir) {
@@ -344,22 +344,22 @@ export function recordedScopeLedgerRows(runDir) {
344
344
  // partial does not validate on its own, so this would have returned null — "no typed call, go and
345
345
  // parse the prose" — on a run whose merged call had validated and written a manifest. The accepted
346
346
  // base IS the merged, validated call, which is exactly what this wants.
347
- const merged = lastAcceptedPrelimVariants(dir0);
347
+ const merged = lastAcceptedClearanceVariants(dir0);
348
348
  if (merged) {
349
- const v = acceptPrelimVariants(merged);
349
+ const v = acceptClearanceVariants(merged);
350
350
  if (v.ok) return v.scopeRows;
351
351
  }
352
352
  // FALLBACK: runs that predate the base, which have a capture and no accepted.json. Unchanged
353
353
  // behaviour for them, and it is why this is a fallback rather than a replacement.
354
354
  let captured;
355
- try { captured = JSON.parse(readFileSync(prelimVariantsCallPaths(dir0).payload, "utf8")); }
355
+ try { captured = JSON.parse(readFileSync(clearanceVariantsCallPaths(dir0).payload, "utf8")); }
356
356
  catch { return null; } // no call — the prose path is the answer
357
- const v = acceptPrelimVariants(captured?.params);
357
+ const v = acceptClearanceVariants(captured?.params);
358
358
  return v.ok ? v.scopeRows : null; // a refused call never wrote a manifest either
359
359
  }
360
360
 
361
361
  /** Was this run's manifest written through the typed transport? The ruled discriminator. */
362
- export function prelimVariantsWasRecorded(runDir) {
363
- try { readFileSync(prelimVariantsCallPaths(String(runDir ?? "")).payload, "utf8"); return true; }
362
+ export function clearanceVariantsWasRecorded(runDir) {
363
+ try { readFileSync(clearanceVariantsCallPaths(String(runDir ?? "")).payload, "utf8"); return true; }
364
364
  catch { return false; }
365
365
  }
@@ -46,7 +46,7 @@ function rowCells(ln) {
46
46
  * The variant terms the manifest commits the grid to search: data rows of sections whose heading
47
47
  * contains "variants" (the Variants tables). "Variant applicability" sections (category
48
48
  * dispositions, not search terms) are excluded. The term column is resolved from each table's
49
- * HEADER row — the live prelim-variants format is `| Category | Value | Rationale | Verify? |`
49
+ * HEADER row — the live clearance-variants format is `| Category | Value | Rationale | Verify? |`
50
50
  * (term in "Value"), while older/test manifests use `| Variant | ... |` (term first); default 0
51
51
  * when no recognizable header exists.
52
52
  */
@@ -842,7 +842,7 @@ export function mergeCommonLawFindings(parts) {
842
842
  // FALSE against the real ledger, and the arm failed the very run it was derived from:
843
843
  //
844
844
  // • `candidates[]` is RAW, UNJUDGED web-search output — the grid program records up to 8 candidates
845
- // per cell "without judging similarity" (skills/prelim-common-law/perplexity-prompts.md), and the
845
+ // per cell "without judging similarity" (skills/clearance-common-law/perplexity-prompts.md), and the
846
846
  // filtering is explicitly the model's. The real cell `CORAL FREEZE × vitaminshoppe.com` holds three:
847
847
  // a BCAA how-to video, a Hawaiian shaved-ice supplement and a Dallas store-locator page. The
848
848
  // model's "No results" means "no relevant listing", and no deterministic test can tell that page
@@ -44,7 +44,7 @@ import { Refusal } from "../shared/onboarding-store.mjs";
44
44
  * Broken means someone TRIED to select one and it does not resolve, and falling back there would rate a
45
45
  * client's matters under a framework nobody chose while the output said everything was fine.
46
46
  *
47
- * The profile validator checks the SHAPE of this string only (`skills/prelim-search/<file>.md`, no
47
+ * The profile validator checks the SHAPE of this string only (`skills/clearance-search/<file>.md`, no
48
48
  * escape) and never whether the file is there — so a shape-valid path to a document that does not exist
49
49
  * validates cleanly and fails at rating time, which is the wrong place to find out.
50
50
  */
@@ -58,9 +58,9 @@ export function resolveFramework(requested, {
58
58
  const path = String(requested).trim();
59
59
  // Shape first, and by the profile validator's own rule rather than a second copy of it: a path that
60
60
  // would be refused at load must be refused here, in the same words, before anything is written.
61
- if (!/^skills\/prelim-search\/[^/]+\.md$/.test(path) || path.includes(".."))
61
+ if (!/^skills\/(?:clearance|prelim)-search\/[^/]+\.md$/.test(path) || path.includes("..")) // either spelling of the folder, as the profile loader
62
62
  throw new Refusal(
63
- `--framework must name a document of the form "skills/prelim-search/<file>.md" (got ${JSON.stringify(path)}). `
63
+ `--framework must name a document of the form "skills/clearance-search/<file>.md" (got ${JSON.stringify(path)}). `
64
64
  + `A profile selects a SHIPPED framework, never an arbitrary path.`);
65
65
 
66
66
  // RESOLVED THE WAY THE RATING STAGE RESOLVES IT, never by joining the repo root. `skills/...` paths
@@ -55,6 +55,7 @@ const MAX_CLASSES = 15;
55
55
  const MAX_TERRITORIES = 20;
56
56
  const MAX_NOTES = 8;
57
57
  import { PRODUCTS, PRODUCT_IDS } from "./products.mjs";
58
+ import OFFERED from "../shared/offered-territories.json" with { type: "json" }; // the form's own list, minted by rule
58
59
 
59
60
  const MAX_STR = 600;
60
61
  const MAX_NOTE = 240;
@@ -62,22 +63,15 @@ const MAX_NOTE = 240;
62
63
  /**
63
64
  * The territory vocabulary, as offered by the composer's Where field.
64
65
  *
65
- * MIRRORS `REGIONS` + `COUNTRIES` in portal-ui/src/contract/composerProduct.ts. Kept here only so the
66
- * prompt can name it; the authority on what is selectable is the UI's own list.
66
+ * READ FROM THE SAME FILE THE FORM READS: shared/offered-territories.json, minted by rule from what the
67
+ * registers can search (scripts/mint-offered-territories.mjs). It used to be a hand-kept copy of the form's
68
+ * own list, "mirrored" by a comment, and a comment keeps nothing equal. One file read twice cannot differ.
67
69
  *
68
- * "Worldwide" LEFT THIS LIST. It is not a territory the composer offers and never was — it is a MODE,
69
- * and the read now carries it as its own boolean. Leaving it here taught the model to write a token the
70
- * form had to strip back out, which is how "everywhere" and "nowhere in particular" became the same
71
- * bytes on the wire in the first place.
70
+ * "Worldwide" is not in it. It is not a territory the composer offers and never was — it is a MODE,
71
+ * and the read carries it as its own boolean. Listing it taught the model to write a token the form had to
72
+ * strip back out, which is how "everywhere" and "nowhere in particular" became the same bytes on the wire.
72
73
  */
73
- export const PROMPT_TERRITORIES = Object.freeze([
74
- "European Union", "Benelux", "African Regional (ARIPO)",
75
- "United States", "United Kingdom", "Ireland", "France", "Germany", "Spain", "Italy", "Netherlands",
76
- "Switzerland", "Austria", "Sweden", "Norway", "Poland", "Bulgaria", "Greece", "Turkey", "Canada",
77
- "Mexico", "Brazil", "Argentina", "China", "Hong Kong", "Taiwan", "Macau", "Japan", "South Korea",
78
- "Singapore", "India", "Thailand", "Australia", "New Zealand", "United Arab Emirates", "Saudi Arabia",
79
- "South Africa",
80
- ]);
74
+ export const PROMPT_TERRITORIES = Object.freeze([...OFFERED.regions, ...OFFERED.countries].map((t) => t.name));
81
75
 
82
76
  /**
83
77
  * The shape the model must answer in.
@@ -25,7 +25,7 @@
25
25
  // follows, so an MCP tool call can read consumption without dragging the pipeline in.
26
26
 
27
27
  import { appendFileSync, readFileSync, readdirSync } from "node:fs";
28
- import { join } from "node:path";
28
+ import { join } from "node:path"; import { studioDirFor } from "../shared/pre-rename-spellings.mjs";
29
29
 
30
30
  /** Where the consumption ledger sits: beside the matter ledger, in the studio dir. */
31
31
  export function consumptionLedgerPath(studioRoot) {
@@ -158,7 +158,7 @@ export function accountConsumption({ workspaceRoot, account, now = Date.now() })
158
158
 
159
159
  const rows = [];
160
160
  for (const ws of workspaces) {
161
- const studio = join(workspaceRoot, ws, "studio", "prelim-search");
161
+ const studio = studioDirFor(join(workspaceRoot, ws));
162
162
  try {
163
163
  for (const line of readFileSync(consumptionLedgerPath(studio), "utf8").split("\n")) {
164
164
  if (!line.trim()) continue;
@@ -11,7 +11,7 @@
11
11
  "the baseline tracks named elements, and a rename is a new name. Regenerate rather than work around it.",
12
12
  "Measured 139 of 287 declared elements."
13
13
  ],
14
- "total": 105,
14
+ "total": 104,
15
15
  "byStage": {
16
16
  "matter-frame": [
17
17
  "### Intake asks line shape — rendered by the driver from intake_asks[]",
@@ -24,7 +24,7 @@
24
24
  "Scope reasoning — search-wide/cite-narrow, the in-scope-by-reach routes, and the reopen trigger behind each exclusion",
25
25
  "search_channels — the domains where real use of THIS matter's goods would show"
26
26
  ],
27
- "prelim-variants": [
27
+ "clearance-variants": [
28
28
  "### Scope ledger rows — {Layer, Item, Status: applied|dropped, Reason, Reopen trigger} across variant / field / source / jurisdiction",
29
29
  "Archetype — primary (one of six) + modifiers + one-line reasoning",
30
30
  "Cross-mark themes — shared elements, shared conceptual themes, shared industry-incumbent alerts (multi-mark requests)",
@@ -84,7 +84,6 @@
84
84
  "the dictated entry list — qid, predicate, terms, owner, nice_classes, regions, when-guard, expected_kind, covered_by"
85
85
  ],
86
86
  "placement-inquiry": [
87
- "mark / owner / records / territories / classes on a SELECTED row",
88
87
  "retract: <row_id> — withdrawing a seat row already on the form",
89
88
  "return payload — the absolute output path plus a 2-3 line summary",
90
89
  "select — one record URI of the register candidate being placed",
@@ -111,10 +111,10 @@ export function grantedToolsFor(stage) {
111
111
  //
112
112
  // SIX OF THE TEN ARE ONE SUB-CLASS NOBODY HAD NAMED: SHARED DOCTRINE, DIVERGENT GRANTS. A skill file is
113
113
  // served whole to several stages whose grants differ, so the same sentence is a correct instruction to
114
- // one seat and an order for a tool the next seat does not hold. `prelim-register/SKILL.md` goes to
115
- // register-unit and register-digest; `prelim-search/phase2-execution.md` goes to skeptic;
116
- // `prelim-search/synthesis-rules.md` goes to synthesis AND report-overview. report-overview and
117
- // prelim-variants are tool-free BY DESIGN, each with its reason written out in TOOL_FREE_STAGES;
114
+ // one seat and an order for a tool the next seat does not hold. `clearance-register/SKILL.md` goes to
115
+ // register-unit and register-digest; `clearance-search/phase2-execution.md` goes to skeptic;
116
+ // `clearance-search/synthesis-rules.md` goes to synthesis AND report-overview. report-overview and
117
+ // clearance-variants are tool-free BY DESIGN, each with its reason written out in TOOL_FREE_STAGES;
118
118
  // skeptic has since CONVERTED to the RECORDING category (its reason moved to RECORDING_STAGES) and
119
119
  // holds exactly its own record tool — still no retrieval tool, so its entries below reproduce
120
120
  // unchanged. Each of the three is currently served a document telling it to run a lookup.
@@ -124,31 +124,31 @@ export function grantedToolsFor(stage) {
124
124
  // only shrink. The test asserts every entry still reproduces, so a pair fixed in fails CI here
125
125
  // until its line is deleted.
126
126
  export const TOOL_ORDER_BACKLOG = [
127
- { stage: "register-digest", tool: "register_enumerate", site: "driver/skills/prelim-register/SKILL.md",
127
+ { stage: "register-digest", tool: "register_enumerate", site: "driver/skills/clearance-register/SKILL.md",
128
128
  closes: "#865 — shared doctrine: SKILL.md is served to register-unit (holds register) and register-digest "
129
129
  + "(holds band only, since the plan freeze retired live search from the judgment seat)." },
130
- { stage: "register-digest", tool: "register_execute_plan", site: "driver/skills/prelim-register/SKILL.md",
130
+ { stage: "register-digest", tool: "register_execute_plan", site: "driver/skills/clearance-register/SKILL.md",
131
131
  closes: "#865 — same shared file, same split grant." },
132
- { stage: "register-digest", tool: "register_batch_screen", site: "driver/skills/prelim-register/digest.md",
132
+ { stage: "register-digest", tool: "register_batch_screen", site: "driver/skills/clearance-register/digest.md",
133
133
  closes: "#865 — the digest's OWN doctrine, not a shared file: this one is the stage being told to "
134
134
  + "batch-screen with a tool its grant does not carry. gather-config.mjs:196 already records that "
135
135
  + "this stage's prompt once ordered live register checks; the order outlived the note." },
136
- { stage: "register-unit", tool: "band_record", site: "driver/skills/prelim-register/SKILL.md",
136
+ { stage: "register-unit", tool: "band_record", site: "driver/skills/clearance-register/SKILL.md",
137
137
  closes: "#865 — same shared file, same split grant." },
138
- { stage: "register-unit", tool: "band_shape", site: "driver/skills/prelim-register/SKILL.md",
138
+ { stage: "register-unit", tool: "band_shape", site: "driver/skills/clearance-register/SKILL.md",
139
139
  closes: "#865 — same shared file, same split grant." },
140
- { stage: "report-overview", tool: "band_record", site: "driver/skills/prelim-search/synthesis-rules.md",
140
+ { stage: "report-overview", tool: "band_record", site: "driver/skills/clearance-search/synthesis-rules.md",
141
141
  closes: "#865 — same shared file, same split grant." },
142
- { stage: "register-unit", tool: "band_lookup", site: "driver/skills/prelim-register/SKILL.md",
142
+ { stage: "register-unit", tool: "band_lookup", site: "driver/skills/clearance-register/SKILL.md",
143
143
  closes: "#865 — the mirror image: the band tools are the judgment stages', and the unit lane holds "
144
144
  + "register instead." },
145
- { stage: "register-unit", tool: "record_coverage", site: "driver/skills/prelim-register/SKILL.md",
145
+ { stage: "register-unit", tool: "record_coverage", site: "driver/skills/clearance-register/SKILL.md",
146
146
  closes: "#865 — same shared-spine split as the band tools above, minted by the typed coverage "
147
147
  + "transport: the spine's Coverage-ledger section (mode-scoped to DIGEST in its own words) orders "
148
148
  + "`record_coverage`, which only register-digest's grant carries — the unit lane must never hold a "
149
149
  + "writer into judgment's coverage record. Resolved the day the spine's coverage doctrine moves "
150
150
  + "wholly into digest.md, or #865 scopes shared-spine text per seat." },
151
- { stage: "register-unit", tool: "record_register_digest", site: "driver/skills/prelim-register/SKILL.md",
151
+ { stage: "register-unit", tool: "record_register_digest", site: "driver/skills/clearance-register/SKILL.md",
152
152
  closes: "#865 — the SAME shared-spine split as record_coverage above, minted by conversion 11's typed "
153
153
  + "findings transport. The spine's mode list names the tool inside its **Digest mode (judgment — "
154
154
  + "Layer B)** bullet, which is the sentence that already names record_coverage and the band tools; "
@@ -157,20 +157,20 @@ export const TOOL_ORDER_BACKLOG = [
157
157
  + "spine's digest doctrine moves wholly into digest.md, or #865 scopes shared-spine text per seat — "
158
158
  + "and NOT by granting it: the funnel must never hold a writer into judgment's findings document, "
159
159
  + "which is the same rule that keeps record_coverage off its grant." },
160
- { stage: "skeptic", tool: "perplexity_research", site: "driver/skills/prelim-search/phase2-execution.md",
160
+ { stage: "skeptic", tool: "perplexity_research", site: "driver/skills/clearance-search/phase2-execution.md",
161
161
  closes: "#865 — skeptic holds NO retrieval tool ('new search work enters via the escalation lane, never "
162
162
  + "from this seat' — it converted to the RECORDING category, gaining record_skeptic plus the "
163
163
  + "read-only, run-dir-scoped search_run_artifacts, and no retrieval tool) "
164
164
  + "and is served a document ordering a live query." },
165
- { stage: "skeptic", tool: "register_propose_supplemental", site: "driver/skills/prelim-search/phase2-execution.md",
165
+ { stage: "skeptic", tool: "register_propose_supplemental", site: "driver/skills/clearance-search/phase2-execution.md",
166
166
  closes: "#865 — same seat, same file, the supplemental mint it cannot call." },
167
- { stage: "report-overview", tool: "perplexity_research", site: "driver/skills/prelim-search/synthesis-rules.md",
167
+ { stage: "report-overview", tool: "perplexity_research", site: "driver/skills/clearance-search/synthesis-rules.md",
168
168
  closes: "#865 — synthesis-rules.md is served to synthesis (holds perplexity + band) and to "
169
169
  + "report-overview (TOOL-FREE: 'renders the shell from the settled narrative + findings')." },
170
- { stage: "report-overview", tool: "band_lookup", site: "driver/skills/prelim-search/synthesis-rules.md",
170
+ { stage: "report-overview", tool: "band_lookup", site: "driver/skills/clearance-search/synthesis-rules.md",
171
171
  closes: "#865 — same shared file, same split grant." },
172
- { stage: "prelim-variants", tool: "perplexity_research", site: "driver/skills/prelim-variants/SKILL.md",
173
- closes: "#865 — prelim-variants is TOOL-FREE by design ('pure reasoning over material already on "
172
+ { stage: "clearance-variants", tool: "perplexity_research", site: "driver/skills/clearance-variants/SKILL.md",
173
+ closes: "#865 — clearance-variants is TOOL-FREE by design ('pure reasoning over material already on "
174
174
  + "disk') and its own doctrine names a research call." },
175
175
  ];
176
176