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
@@ -2,7 +2,7 @@
2
2
  // Copyright 2026 Cordillera Sàrl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
3
3
  // report-overview-record.mjs — the recording transport for the report shell.
4
4
  //
5
- // Conversion 4, after blind-frame, skeptic, frame-diff, matter-frame and prelim-variants
5
+ // Conversion 4, after blind-frame, skeptic, frame-diff, matter-frame and clearance-variants
6
6
  //. It is the FIRST conversion whose artifact a client reads. report-overview.md is not an internal
7
7
  // input that a later stage consumes — it is the front-matter and the Actions section of the delivered
8
8
  // report, so a render defect here reaches a lawyer's desk rather than a test log.
@@ -181,7 +181,7 @@ export function renderReportOverview(model, identity) {
181
181
  const id = identity ?? {};
182
182
  const fm = [
183
183
  "---",
184
- "type: prelim-clearance",
184
+ "type: clearance-clearance",
185
185
  id.matter ? `matter: ${id.matter}` : "",
186
186
  id.title ? `title: ${id.title}` : "",
187
187
  id.client ? `client: ${id.client}` : "",
@@ -235,11 +235,11 @@ export function runRequirements(env = {}, { registers = [], engines = {}, defaul
235
235
  // it, the runner logs it, and a composite name read as four more items in doctor's list of what is
236
236
  // missing. The REASON names all four, with whose each is. And the row carries all four as `anyOf`,
237
237
  // which `runRequiredNames` hands out as names to read: doctor fills its view of the services by name,
238
- // and reading only Google's switch reported a Microsoft machine's switch, held by its services, as
238
+ // and reading only Google's switch reported an Azure machine's switch, held by its services, as
239
239
  // missing.
240
240
  //
241
241
  // A SWITCH THAT IS SET AND NOT ON IS SAID, because it reads as on to a person and as off to the
242
- // program: `CLAUDE_CODE_USE_FOUNDRY=0` on a Microsoft machine was answered with Google's switch
242
+ // program: `CLAUDE_CODE_USE_FOUNDRY=0` on an Azure machine was answered with Google's switch
243
243
  // and nothing else, and the reader was left to work out why the one they set did not count.
244
244
  // And it is not an alternative to read or carry: `anyOf` is handed to the composer too, and the
245
245
  // set-and-off line would travel through it.
@@ -273,7 +273,7 @@ export function runRequirements(env = {}, { registers = [], engines = {}, defaul
273
273
  // The rows above name what is MISSING. The run door also refuses what is set wrongly: two clouds
274
274
  // switched on, a switch left on beside `subscription` or `api-key`, a word that is not a billing mode,
275
275
  // a cloud account on Codex. Each passed start's guard, the order wall and doctor, and the run was then
276
- // refused after intake. Measured 2026-09-15: a services' file holding Microsoft's switch from one start
276
+ // refused after intake. Measured 2026-09-15: a services' file holding Azure's switch from one start
277
277
  // and Google's from the next read clean everywhere and refused every search.
278
278
  //
279
279
  // ASKED OF THE RUN DOOR ITSELF, `resolveAuthMode`, over the environment being judged, and its refusal
package/driver/runner.mjs CHANGED
@@ -21,7 +21,7 @@
21
21
  import "../shared/env-local.mjs"; // side effect: apply <repo>/.env when THIS file is the CLI entry (never on library import)
22
22
  import "./engine/mcp/http-dispatcher.mjs"; // side effect: raise undici headersTimeout (code-side fetches)
23
23
  import { readdirSync, renameSync, existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, rmSync, statSync } from "node:fs";
24
- import { join, dirname, basename } from "node:path";
24
+ import { join, dirname, basename } from "node:path"; import { studioDirFor } from "../shared/pre-rename-spellings.mjs";
25
25
  import { driverDir, ensureDriverDir } from "../shared/driver-dir.mjs"; // — one definition of where `_driver/` is
26
26
  // The queue's filename vocabulary, in ONE place — the rule, extended by to the prose-sidecar and
27
27
  // claim-sidecar names, because a harness check retyped four of them from memory and false-alarmed on the
@@ -1548,7 +1548,7 @@ export function agentStudioRoots() {
1548
1548
  try {
1549
1549
  for (const name of readdirSync(config.workspaceRoot)) {
1550
1550
  if (config.agentIdFromWorkspaceName(name) == null) continue;
1551
- const s = join(config.workspaceRoot, name, "studio", "prelim-search");
1551
+ const s = studioDirFor(join(config.workspaceRoot, name));
1552
1552
  if (existsSync(s)) out.push(s);
1553
1553
  }
1554
1554
  } catch { /* workspaceRoot absent in some envs */ }
@@ -26,6 +26,7 @@
26
26
  // keys only on the neutral plan/band vocabulary, never a vendor name or vendor-shaped field.
27
27
 
28
28
  import { classTokensFromScopeText } from "./coverage-ledger.mjs";
29
+ import { capabilitiesFor } from "./register-capabilities.mjs";
29
30
 
30
31
  const clsStr = (c) => String(c ?? "").trim();
31
32
 
@@ -144,10 +145,11 @@ export function deriveScopeFacts({ instructedScope = null, plan = null, planExec
144
145
 
145
146
  const searched_jurisdictions = Array.isArray(plan?.regions) ? plan.regions.map(String) : [];
146
147
  const scope_basis = plan?.scope_basis === "worldwide" ? "worldwide" : null;
148
+ const register_service = registerServiceOf(plan);
147
149
 
148
150
  const classes_line = instructedClasses.length ? instructedClasses.join(", ") : null;
149
151
  const coverage_line = instructedClasses.length && entries.length
150
- ? buildCoverageLine(instructedClasses, per_class, { searched_jurisdictions, scope_basis, instructedScope })
152
+ ? buildCoverageLine(instructedClasses, per_class, { searched_jurisdictions, scope_basis, instructedScope, register_service })
151
153
  : null;
152
154
 
153
155
  return {
@@ -184,7 +186,7 @@ export function deriveScopeFacts({ instructedScope = null, plan = null, planExec
184
186
  // clause is word-for-word the same are stated ONCE, over the classes they are about. Nothing is pooled
185
187
  // and no number moves: the grouping is on the rendered text, so two classes only share a line when the
186
188
  // line they would each have printed is already the same string.
187
- function buildCoverageLine(classes, per_class, { searched_jurisdictions = [], scope_basis = null, instructedScope = null } = {}) {
189
+ function buildCoverageLine(classes, per_class, { searched_jurisdictions = [], scope_basis = null, instructedScope = null, register_service = null } = {}) {
188
190
  const sorted = [...classes].sort((a, b) => (Number(a) || 0) - (Number(b) || 0));
189
191
  const byBody = new Map();
190
192
  for (const c of sorted) {
@@ -197,7 +199,7 @@ function buildCoverageLine(classes, per_class, { searched_jurisdictions = [], sc
197
199
  // bodies A, B, A renders "Classes 5 and 32: A; Class 9: B", not A twice.
198
200
  const groups = [...byBody.entries()].map(([body, classes]) => ({ body, classes }));
199
201
  const head = (cs) => (cs.length === 1 ? `Class ${cs[0]}` : `Classes ${joinAnd(cs.map(String))}`);
200
- return `${groups.map((g) => `${head(g.classes)}: ${g.body}`).join("; ")}${jurisdictionTail({ searched_jurisdictions, scope_basis, instructedScope })}`;
202
+ return `${groups.map((g) => `${head(g.classes)}: ${g.body}`).join("; ")}${jurisdictionTail({ searched_jurisdictions, scope_basis, instructedScope, register_service })}`;
201
203
  }
202
204
 
203
205
  // One plain-language clause per class, routed on the COUNTS (state-agnostic), not on the state label.
@@ -263,11 +265,24 @@ const joinAnd = (parts) => (parts.length <= 1 ? parts.join("") : `${parts.slice(
263
265
  // EU US CH WO doesn't make sense". A worldwide-scoped plan (scope_basis, or a worldwide token riding
264
266
  // an instructed list) collapses the tail to the one word; only a genuinely named list is listed.
265
267
  const WORLDWIDE_TOKEN_RE = /^(worldwide|world|ww|global)$/i;
266
- function jurisdictionTail({ searched_jurisdictions = [], scope_basis = null, instructedScope = null } = {}) {
268
+
269
+ // WORLDWIDE NAMES THE SERVICE THAT SEARCHED IT (owner, 2026-09-18). "Worldwide" is eleven registers on one
270
+ // installation and 186 on another, and a reader can only tell which by being told the service. The name is
271
+ // the provider's own label from its capabilities contract — the same name the order form shows — read off
272
+ // the provider the frozen plan records. A plan that records none, or one this build does not know, keeps
273
+ // the bare word: a guessed name would be worse than none. Never a list of offices, never a count.
274
+ function registerServiceOf(plan) {
275
+ if (!plan?.provider) return null;
276
+ try { return capabilitiesFor(plan.provider).label ?? null; } catch { return null; }
277
+ }
278
+
279
+ function jurisdictionTail({ searched_jurisdictions = [], scope_basis = null, instructedScope = null, register_service = null } = {}) {
267
280
  const list = (searched_jurisdictions.length
268
281
  ? searched_jurisdictions
269
282
  : (Array.isArray(instructedScope?.jurisdictions) ? instructedScope.jurisdictions : [])).map((j) => String(j).trim()).filter((j) => j);
270
- if (scope_basis === "worldwide" || list.some((j) => WORLDWIDE_TOKEN_RE.test(j))) return " · registers: worldwide";
283
+ if (scope_basis === "worldwide" || list.some((j) => WORLDWIDE_TOKEN_RE.test(j))) {
284
+ return ` · registers: worldwide${register_service ? ` (${register_service})` : ""}`;
285
+ }
271
286
  if (!list.length) return "";
272
287
  // 2–3-letter office codes display uppercase ("us" reads as a pronoun, "US" as a jurisdiction);
273
288
  // longer names pass through untouched.
@@ -1,12 +1,12 @@
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
- // scope-ledger.mjs — the machine mirror of the prelim-variants `### Scope ledger` (the frame-omission
3
+ // scope-ledger.mjs — the machine mirror of the clearance-variants `### Scope ledger` (the frame-omission
4
4
  // design: the blind-pass framing fix, approved into this file — the code is its own record).
5
5
  //
6
- // prelim-variants emits a prose `### Scope ledger` table — one row per variant / field / source the
6
+ // clearance-variants emits a prose `### Scope ledger` table — one row per variant / field / source the
7
7
  // run CONSIDERED and DROPPED (or applied), each carrying the observation that should REOPEN it. The
8
8
  // driver CODE-DERIVES scope-ledger.json from that prose (renderScopeLedgerJson, called after
9
- // prelim-variants validates) so the JSON is authored by the driver, never the model, and matches the
9
+ // clearance-variants validates) so the JSON is authored by the driver, never the model, and matches the
10
10
  // prose BY CONSTRUCTION — exactly the coverage-ledger.mjs pattern. The blind frame-diff reads the
11
11
  // dropped set + reopen triggers to decide which omissions to escalate.
12
12
  //
@@ -115,7 +115,7 @@ export function parseScopeLedgerJson(raw) {
115
115
 
116
116
  /**
117
117
  * CODE-DERIVE the JSON scope ledger FROM the prose `### Scope ledger` table (the driver calls this after
118
- * prelim-variants validates; never-killed at the call site). PURE. Throws `scope_ledger_unparseable`
118
+ * clearance-variants validates; never-killed at the call site). PURE. Throws `scope_ledger_unparseable`
119
119
  * when the prose carries a Scope ledger heading but yields no classifiable row, so the caller's catch
120
120
  * routes to the manifest-prose-fallback path (the run still delivers). Returns a JSON ARRAY string that
121
121
  * round-trips through parseScopeLedgerJson.
@@ -136,7 +136,7 @@ export function renderScopeLedgerJson(md) {
136
136
  * MARKDOWN TABLE back out of a prose manifest a model had typed, on fixed column positions. A machine
137
137
  * artifact the downstream depends on, recovered from a table.
138
138
  *
139
- * `record_prelim_variants` now receives those rows TYPED, so the driver can serialise them directly. Both
139
+ * `record_clearance_variants` now receives those rows TYPED, so the driver can serialise them directly. Both
140
140
  * paths call THIS function, which is what makes the recorded and the archived ledger byte-identical for
141
141
  * the same rows by construction rather than by an assertion someone has to maintain — and it is why the
142
142
  * prose parse can stay for archives (the anchor rule: a new way in, never a replacement) without becoming
@@ -15,10 +15,10 @@
15
15
  // ── THE DEPTH LADDER IS GONE ─────────────────────────────────────────────────────────────────────────────────
16
16
  //
17
17
  // There used to be a second vocabulary here: a closed set of LEVELS (`knockout`, `knockout-register`,
18
- // `prelim`, `prelim-jx`) with a display face reading "Depth 1"…"Depth 5", ordered by effort. A client
18
+ // `clearance`, `clearance-jx`) with a display face reading "Depth 1"…"Depth 5", ordered by effort. A client
19
19
  // bought a level; the thing they were sold — a knockout, a worldwide preliminary, a single-country deep
20
20
  // dive — was a different word that appeared on no wire. The two disagreed in the one place it mattered:
21
- // `prelim` named THREE products depending on where it pointed, and the composer's own footer had to
21
+ // `clearance` named THREE products depending on where it pointed, and the composer's own footer had to
22
22
  // invent labels ("Deep dive — United States", "Full clearance") for distinctions "the registry has no
23
23
  // word for". The registry now has the word. The level menu, its numbering, its ordering and the
24
24
  // `searchLevel` wire field are DELETED — not deprecated, not hidden behind the product name.
@@ -61,7 +61,7 @@ export const ORDERABLE_PRODUCTS = PRODUCT_IDS;
61
61
  //
62
62
  // This is the reading that squares "no old mechanism survives its replacement" with an archive: the
63
63
  // delete rule governs the ORDERABLE path, and naming a run that already happened is not that path.
64
- export const RETIRED_PRODUCTS = ["knockout", "knockout-register", "prelim-register-only", "prelim", "prelim-jx"];
64
+ export const RETIRED_PRODUCTS = ["knockout", "knockout-register", "clearance-register-only", "clearance", "clearance-jx"];
65
65
 
66
66
  /** Saved searches dropped by the last `loadRecipes` because their base is a retired product. Rewritten on
67
67
  * every load, so it describes the CURRENT store and never accumulates. Read it to tell a reader why a
@@ -304,9 +304,9 @@ export const RETIRED_POLICIES = {
304
304
  // Retired 2026-08-06: the clearance shape with its unregistered-use half removed. That basis
305
305
  // still composes into riskStatement, and the workbook's own gate still inverts on it, because an
306
306
  // archived run of it must not re-render claiming a sweep that never ran.
307
- "prelim-register-only": { product: "prelim-register-only", stageLabel: "Depth 3", pipeline: "clearance", report: { template: "clearance", identity: "Preliminary clearance — register only" }, components: { registerProbe: false, jxLanes: false, commonLawGrid: false } },
308
- "prelim": { product: "prelim", stageLabel: "Depth 4", pipeline: "clearance", report: { template: "clearance", identity: "Preliminary clearance" }, components: { registerProbe: false, jxLanes: false, commonLawGrid: true } },
309
- "prelim-jx": { product: "prelim-jx", stageLabel: "Depth 5", pipeline: "clearance", report: { template: "clearance", identity: "Preliminary clearance with jurisdiction deep-dive" }, components: { registerProbe: false, jxLanes: true, commonLawGrid: true } },
307
+ "clearance-register-only": { product: "clearance-register-only", stageLabel: "Depth 3", pipeline: "clearance", report: { template: "clearance", identity: "Preliminary clearance — register only" }, components: { registerProbe: false, jxLanes: false, commonLawGrid: false } },
308
+ "clearance": { product: "clearance", stageLabel: "Depth 4", pipeline: "clearance", report: { template: "clearance", identity: "Preliminary clearance" }, components: { registerProbe: false, jxLanes: false, commonLawGrid: true } },
309
+ "clearance-jx": { product: "clearance-jx", stageLabel: "Depth 5", pipeline: "clearance", report: { template: "clearance", identity: "Preliminary clearance with jurisdiction deep-dive" }, components: { registerProbe: false, jxLanes: true, commonLawGrid: true } },
310
310
  };
311
311
 
312
312
  /** The report identity to print on a run's document: `{ template, identity, stageLabel, banner }`.
@@ -464,13 +464,23 @@ export function isRegisterOnly(policy) {
464
464
  * search asked for. Asking it "does this exist" is asking the wrong question — the orderability test is
465
465
  * always `ORDERABLE_PRODUCTS.includes(...)`, and a typo must fail closed against that positive list. */
466
466
  export function policyFor(product) {
467
- const k = String(product ?? "").trim().toLowerCase();
467
+ const k = productKeyAsRenamed(product);
468
468
  return PRODUCT_POLICIES[k] ?? RETIRED_POLICIES[k] ?? null;
469
469
  }
470
+ // THREE RETIRED KEYS WERE RENAMED WITH THE IDENTIFIER, and records written before it still carry the old
471
+ // spelling: an archived run's product, a saved search's base in a client's store. Read the old key as the
472
+ // new wherever a key is looked up, or an archived report loses its name and a store's saved searches fail
473
+ // to load over a base this build still knows as retired.
474
+ const PRE_RENAME_PRODUCT_KEYS = Object.freeze({ "prelim": "clearance", "prelim-register-only": "clearance-register-only", "prelim-jx": "clearance-jx" });
475
+ /** A product key, lower-cased, with a pre-rename spelling read as its current one. PURE. */
476
+ export function productKeyAsRenamed(product) {
477
+ const k = String(product ?? "").trim().toLowerCase();
478
+ return PRE_RENAME_PRODUCT_KEYS[k] ?? k;
479
+ }
470
480
 
471
481
  // What THIS build can actually execute. A resolution onto machinery a build does not carry must CLARIFY
472
482
  // at admission (never silently run the wrong-priced product — a knockout request running as a $40
473
- // prelim, or a 1.5 request running as a plain Stage 1, is the exact silent-substitution this file exists
483
+ // clearance, or a 1.5 request running as a plain Stage 1, is the exact silent-substitution this file exists
474
484
  // to forbid). These flags are flipped in CODE as each lane lands, never from the environment: there are
475
485
  // no runtime env kill switches — see the note below.
476
486
  // EXPORTED because availability is now asked about in two places, not one. The runner asks "may this
@@ -498,7 +508,7 @@ export const BUILT = { knockout: true, jxLanes: true, registerProbe: true };
498
508
  // They were not merely dead, they were actively harmful, and in exactly the way the old comment here
499
509
  // predicted: a caller outside the engine's environment reads every switch as unset, and unset was
500
510
  // indistinguishable from off. The portal was given a snapshot to work around it. The ops-MCP was not,
501
- // so `describe_options` and `plan_run` told clients that knockout, knockout-register and prelim-jx were
511
+ // so `describe_options` and `plan_run` told clients that knockout, knockout-register and clearance-jx were
502
512
  // "Not switched on for this account yet" while the engine would have run all three (2026-07-27). That is
503
513
  // the second time this service has lied for want of an environment variable — the first was the profiles
504
514
  // dir answering with a demo roster. Deleting the switch is the fix that cannot recur; plumbing a
@@ -830,7 +840,7 @@ export const CAPABILITY_SKIPPED_CAUSE = {
830
840
  * now honoured wherever it resolves, and built machinery is never "off".
831
841
  *
832
842
  * The RESOLVED policy is measured, never `policyFor(resolved.level)`: a recipe can turn jxLanes on over a
833
- * base of `prelim`, and the base registry entry would answer "available" for a resolution that is not.
843
+ * base of `clearance`, and the base registry entry would answer "available" for a resolution that is not.
834
844
  * Delegating the built arms to productAvailability is what makes the null-equivalence with
835
845
  * gateResolvedPolicy structural rather than a coincidence two edits can break (search-policy.test.mjs
836
846
  * pins it over the whole matrix).
@@ -1115,7 +1125,7 @@ export function loadRecipes({ dir = process.env.CLEAROTRON_RECIPES_DIR || null,
1115
1125
  // NOT SILENT, because unlike a retired extra this one is observable: a saved search disappears. The
1116
1126
  // skip is recorded so a caller can say why rather than leaving a lawyer's saved search gone with no
1117
1127
  // reason. Everything else still throws — a config error is still load-blocking.
1118
- if (RETIRED_PRODUCTS.includes(String(r?.base ?? "").trim().toLowerCase())) {
1128
+ if (RETIRED_PRODUCTS.includes(productKeyAsRenamed(r?.base))) {
1119
1129
  retiredBaseSkips.push({ customer, slug, base: String(r.base), why: "base names a retired search — the saved search cannot be ordered" });
1120
1130
  continue;
1121
1131
  }
@@ -1216,7 +1226,7 @@ export function checkMarkBudget(job, policy) {
1216
1226
  // THE SCOPE ITSELF.
1217
1227
  //
1218
1228
  // THAT LAST RUNG IS THE OFFERING, AND IT IS NOT A CONSTANT. The Generic default used to be the literal
1219
- // level `prelim`, which named three different products depending on where it pointed. A clearance that
1229
+ // level `clearance`, which named three different products depending on where it pointed. A clearance that
1220
1230
  // names no product IS whichever product its territories make it — `productFor(pipeline, scope)`, the one
1221
1231
  // function that answers that question anywhere — so the default is derived, not picked. The caller hands
1222
1232
  // in the RESOLVED scope (`territories`) because resolving it needs the profile and the project overlay,
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Every file here is prompt payload served to the model at runtime.** A stage is one engine turn told to read named
4
4
  files and follow them exactly, so an edit for brevity or tone changes what a clearance concludes —
5
- `prelim-search/synthesis-rules.md` is 1,025 lines of program. Never touch this tree in a documentation or tidy-up
5
+ `clearance-search/synthesis-rules.md` is 1,025 lines of program. Never touch this tree in a documentation or tidy-up
6
6
  task, and never let a mass edit reach it — the [ADR-0005](../../docs/decisions/0005-comments-carry-reasoning.md)
7
7
  comment sweep is required to exclude this tree, and that script does not exist yet, so nothing enforces it but you.
8
8
 
@@ -20,21 +20,21 @@ One directory per skill. `SKILL.md` is the entry point — YAML frontmatter (`na
20
20
  procedure. Every other file beside it is a reference the SKILL.md or the stage message names explicitly, with six
21
21
  exceptions: the four `risk-framework*.manifest.json` sidecars, whose paths the code DERIVES from the deck
22
22
  (`manifestPathFor()`, `../framework.mjs`) so validators and the renderer read band vocabulary without parsing prose;
23
- `prelim-search/risk-framework-triage.md`, the knockout lane's default ladder, named in code only
23
+ `clearance-search/risk-framework-triage.md`, the knockout lane's default ladder, named in code only
24
24
  (`../pipeline-knockout.mjs`) because the knockout stage message hands the seat the frozen `_driver/framework.json`
25
- instead; and `prelim-search/templates/search-request-form.html`, named only in `../publish/index.mjs`.
25
+ instead; and `clearance-search/templates/search-request-form.html`, named only in `../publish/index.mjs`.
26
26
 
27
27
  | Skill | What the stage does |
28
28
  |---|---|
29
29
  | `matter-frame` | Phase 0. Writes the matter's commercial context — sector, customer base, channels of trade, jurisdictions that materially matter, off-field sectors, watchlist seeds — before any search runs. `watchlist-reference.md` is enrichment, not authority. |
30
- | `prelim-variants` | Classifies the mark into one of six archetypes, derives a risk theory from that, emits the variant manifest both execution skills read. Non-Latin scripts: `transliteration-scripts.md`. |
30
+ | `clearance-variants` | Classifies the mark into one of six archetypes, derives a risk theory from that, emits the variant manifest both execution skills read. Non-Latin scripts: `transliteration-scripts.md`. |
31
31
  | `blind-frame`, `frame-diff` | Re-derives the threat model from the raw instruction alone, deliberately starved of the matter frame, then diffs that model against what the run actually scoped and emits reopen directives the driver acts on. Something has to test the frame instead of reasoning inside it. |
32
- | `prelim-common-law` | The marketplace / web / social sweep, as structured Perplexity research over the platform list the stage dictates. Prompt templates: `perplexity-prompts.md`. |
33
- | `prelim-register` | Register execution in the two modes a spawn selects: `unit.md` (the funnel — enumerate one axis to completion, decide nothing) and `digest.md` (judgment over the merged band). Plus `register-recipes.md`, `status-rules.md`, `stealth-filer-indicators.md`, `providers/`. |
32
+ | `clearance-common-law` | The marketplace / web / social sweep, as structured Perplexity research over the platform list the stage dictates. Prompt templates: `perplexity-prompts.md`. |
33
+ | `clearance-register` | Register execution in the two modes a spawn selects: `unit.md` (the funnel — enumerate one axis to completion, decide nothing) and `digest.md` (judgment over the merged band). Plus `register-recipes.md`, `status-rules.md`, `stealth-filer-indicators.md`, `providers/`. |
34
34
  | `placement-inquiry` | Applies commercial relevance per candidate — headline-candidate / sheet-2 / watchlist-annex / out-of-scope-filtered — before any tiering runs. |
35
35
  | `case-law-citation` | Grounds risk-relevant findings in precedent fetched in-session, never from memory. One thin adapter per source in `sources/`; `evals.md` defines what working means. |
36
36
  | `narrative-refutation` | Reads the finished narrative against the underlying findings files and returns CLEAR / CONDITIONAL / BLOCKING with itemised flags. Delivery is gated on the verdict. |
37
- | `prelim-search` | The doctrine the synthesis and delivery stages are held to: `synthesis-rules.md`, the `risk-framework*.md` ladders with their `.manifest.json` band vocabularies, `delivery-contract.md`, `report-prose.md`, `worked-examples.md`, `phase2-execution.md`, `field-doctrine-pharma.md`. |
37
+ | `clearance-search` | The doctrine the synthesis and delivery stages are held to: `synthesis-rules.md`, the `risk-framework*.md` ladders with their `.manifest.json` band vocabularies, `delivery-contract.md`, `report-prose.md`, `worked-examples.md`, `phase2-execution.md`, `field-doctrine-pharma.md`. |
38
38
  | `knockout-frame`, `knockout-assess` | Stages A and C of the knockout doctrine — a broad kill/no-kill triage screen over several candidate names at once (Stage B is a code-side research sweep). Not a clearance. |
39
39
 
40
40
  ## What reads it
@@ -53,25 +53,25 @@ instead; and `prelim-search/templates/search-request-form.html`, named only in `
53
53
 
54
54
  ## The provider boundary
55
55
 
56
- Operator syntax and vendor tool tokens like `corsearch_*` live only in `prelim-register/providers/`; the spine names
56
+ Operator syntax and vendor tool tokens like `corsearch_*` live only in `clearance-register/providers/`; the spine names
57
57
  the `register_*` tools, whichever vendor `CLEAROTRON_DATABASE` selects.
58
58
  `../test/provider-neutral-prose.test.mjs` holds three of that boundary's lines: no vendor-prefixed tool token
59
59
  outside `providers/` and the `engine/mcp/<provider>-server.mjs` glue; no provider record host in a provider-agnostic
60
60
  skill file (banned hosts are read FROM the provider docs, so a sixth provider is covered the day its doc lands);
61
61
  every register server registering only `register_*`, under the MCP name `register`. Field paths are the open edge —
62
62
  the matcher requires `<vendor>_` and cannot see camelCase, so no test fails on one, and
63
- `prelim-register/status-rules.md` still instructs off Corsearch's own field names (`corsearchStatusCode`,
63
+ `clearance-register/status-rules.md` still instructs off Corsearch's own field names (`corsearchStatusCode`,
64
64
  `onomaticsJurisdictionsStatuses`, the `owners[0].*` owner chain), plus one line of `register-recipes.md` off
65
- `onomaticsOppositions[]`. `prelim-register/SKILL.md`, `unit.md`, `digest.md` and everything under `prelim-search/`
65
+ `onomaticsOppositions[]`. `clearance-register/SKILL.md`, `unit.md`, `digest.md` and everything under `clearance-search/`
66
66
  are clean. The authoring rules and the empirical-verification checklist a new provider doc must pass sit in
67
- `prelim-register/providers/README.md`.
67
+ `clearance-register/providers/README.md`.
68
68
 
69
69
  ## Where to start
70
70
 
71
- `prelim-search/SKILL.md` — the orchestrator's own skill, and the one file describing the whole workflow end to end.
72
- Then `prelim-register/SKILL.md`, the more elaborated of the two execution skills: a spine plus per-mode files
73
- (`unit.md`, `digest.md`) and per-provider files (`providers/`). The other, `prelim-common-law`, is one spine plus
71
+ `clearance-search/SKILL.md` — the orchestrator's own skill, and the one file describing the whole workflow end to end.
72
+ Then `clearance-register/SKILL.md`, the more elaborated of the two execution skills: a spine plus per-mode files
73
+ (`unit.md`, `digest.md`) and per-provider files (`providers/`). The other, `clearance-common-law`, is one spine plus
74
74
  `perplexity-prompts.md`, its two grid modes (deterministic `grid_spec_path` dispatch vs. the legacy authored
75
75
  program) being sections inside it — the per-mode split and `providers/` are register-only, not a shape every
76
- execution skill shares. `prelim-search/phase2-execution.md` is methodology, not sequencing — the pipeline is
76
+ execution skill shares. `clearance-search/phase2-execution.md` is methodology, not sequencing — the pipeline is
77
77
  sequenced in code, in `../stages.mjs` and `../pipeline.mjs`.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: blind-frame
3
- description: The frame-STARVED independent re-derivation for the v3 preliminary trademark search workflow. **Invoked exclusively by the `prelim-search` orchestrator/driver**, in parallel with the gather sweeps — do not call directly. Reads ONLY the raw instruction (mark, goods, classes, territories, manner of use) and NOT the matter frame, then re-derives the threat model cold across four layers — element + neighbours both directions, field by goods-overlap, sources by real channel, ranking by goods-overlap — and emits a structured model the frame-diff stage diffs against what the run actually scoped. Its job is to test the frame, not to reason inside it.
3
+ description: The frame-STARVED independent re-derivation for the v3 preliminary trademark search workflow. **Invoked exclusively by the `clearance-search` orchestrator/driver**, in parallel with the gather sweeps — do not call directly. Reads ONLY the raw instruction (mark, goods, classes, territories, manner of use) and NOT the matter frame, then re-derives the threat model cold across four layers — element + neighbours both directions, field by goods-overlap, sources by real channel, ranking by goods-overlap — and emits a structured model the frame-diff stage diffs against what the run actually scoped. Its job is to test the frame, not to reason inside it.
4
4
  ---
5
5
 
6
6
  ## Purpose
7
7
 
8
- Every other stage in a clearotron run reasons *inside* a frame that was set early (at `matter-frame` / `prelim-variants`): the variants to chase, the field that counts as on-field, the sources worth searching. Verification then runs *on* that frame — nothing tests the frame itself. When the frame is mis-scoped, the whole run inherits the miss and the skeptic, reasoning from the same frame, certifies it.
8
+ Every other stage in a clearotron run reasons *inside* a frame that was set early (at `matter-frame` / `clearance-variants`): the variants to chase, the field that counts as on-field, the sources worth searching. Verification then runs *on* that frame — nothing tests the frame itself. When the frame is mis-scoped, the whole run inherits the miss and the skeptic, reasoning from the same frame, certifies it.
9
9
 
10
10
  You are the antidote. You are **deliberately starved of the frame**: you receive only the raw instruction, exactly as the requester wrote it, and you re-derive the threat model **cold**. Because you never see the run's conclusions, you cannot anchor to them. Your output is later **diffed** against what the run actually scoped — the gaps in that diff are the omissions the frame missed.
11
11
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: case-law-citation
3
- description: Grounds risk-relevant trademark findings in cited case law and decisions instead of asserting them. Invoked by the prelim-search orchestrator at Step 4.5 to profile an aggressive enforcer or test a likelihood-of-confusion question against precedent, and usable inline in chat for ad-hoc conflict/enforcement questions. Queries live legal sources — CourtListener (US federal incl. CAFC), EUR-Lex (EU CJEU + General Court judgments, verbatim), and Legal Data Hunter (108-country statutes and case law) — and returns, per finding, on-point authorities (case or decision, forum, date, one-line holding, stable identifier) with relevance notes, or an explicit no-precedent result. Cites only from documents fetched in the session, never from memory. Use when grounding watchlist or aggressive-enforcer hits, or when a trademark conflict, confusability, or enforcement-history question needs precedent.
3
+ description: Grounds risk-relevant trademark findings in cited case law and decisions instead of asserting them. Invoked by the clearance-search orchestrator at Step 4.5 to profile an aggressive enforcer or test a likelihood-of-confusion question against precedent, and usable inline in chat for ad-hoc conflict/enforcement questions. Queries live legal sources — CourtListener (US federal incl. CAFC), EUR-Lex (EU CJEU + General Court judgments, verbatim), and Legal Data Hunter (108-country statutes and case law) — and returns, per finding, on-point authorities (case or decision, forum, date, one-line holding, stable identifier) with relevance notes, or an explicit no-precedent result. Cites only from documents fetched in the session, never from memory. Use when grounding watchlist or aggressive-enforcer hits, or when a trademark conflict, confusability, or enforcement-history question needs precedent.
4
4
  ---
5
5
 
6
6
  # Case-law citation
@@ -40,17 +40,17 @@ Companion files (one level deep — read the one you need):
40
40
 
41
41
  Still-future adapter (drops in here with no change to this file): `sources/euipo.md` (EUIPO
42
42
  Boards-of-Appeal decisions — no free API today). EUIPO *register* lookups are a different layer
43
- (`prelim-register`), not this skill.
43
+ (`clearance-register`), not this skill.
44
44
 
45
45
  ## Trigger
46
46
 
47
- Called by `prelim-search` after synthesis flags the risk-relevant findings (Step 4.5). Also triggers in
47
+ Called by `clearance-search` after synthesis flags the risk-relevant findings (Step 4.5). Also triggers in
48
48
  chat when the user raises a trademark conflict, likelihood-of-confusion, or enforcement-history question.
49
49
  Gated and optional: if this skill is absent, clearotron skips Step 4.5 and delivers normally.
50
50
 
51
51
  ## Model
52
52
 
53
- **Sonnet, eval-gated** when spawned from the `prelim-search` Step 4.5 seam. The work is extraction
53
+ **Sonnet, eval-gated** when spawned from the `clearance-search` Step 4.5 seam. The work is extraction
54
54
  from documents fetched **this session** — the fetch-before-cite discipline (cite only what you
55
55
  fetched; read the holding from the fetched text; refuse to invent when sources are empty), not model
56
56
  recall, is what keeps citations honest. That makes it a Sonnet-tier task **provided** Sonnet reliably
@@ -65,7 +65,7 @@ successfully fetch and verify.
65
65
  would close this gap; none is wired today.)
66
66
  - **Not** the EUIPO administrative layer: **EUIPO Boards-of-Appeal decisions** have no free API and are
67
67
  not searched — report that as a coverage gap. EUIPO *register* lookups are a different layer
68
- (`prelim-register`), not this skill.
68
+ (`clearance-register`), not this skill.
69
69
 
70
70
  ## Citing convention
71
71
 
@@ -1,17 +1,17 @@
1
1
  ---
2
- name: prelim-common-law
3
- description: Common-law / marketplace execution for the v3 preliminary trademark search workflow. **Invoked exclusively by the `prelim-search` orchestrator** — do not call directly. Reads the variant manifest produced by `prelim-variants` and runs structured Perplexity research across the DICTATED platform list (the task message's PLATFORMS block names the exact store domains for this customer; the gaming default is 6 stores) plus general web, social, e-commerce, and industry press. Produces a common-law findings file consumed by the orchestrator for synthesis and Excel assembly. Runs alongside `prelim-register`.
2
+ name: clearance-common-law
3
+ description: Common-law / marketplace execution for the v3 preliminary trademark search workflow. **Invoked exclusively by the `clearance-search` orchestrator** — do not call directly. Reads the variant manifest produced by `clearance-variants` and runs structured Perplexity research across the DICTATED platform list (the task message's PLATFORMS block names the exact store domains for this customer; the gaming default is 6 stores) plus general web, social, e-commerce, and industry press. Produces a common-law findings file consumed by the orchestrator for synthesis and Excel assembly. Runs alongside `clearance-register`.
4
4
  ---
5
5
 
6
6
  ## Spawned session
7
7
 
8
- Invoked from `prelim-search` (orchestrator) alongside `prelim-register`. Reads:
9
- - The variant manifest at `studio/prelim-search/<slug>/<date>/variant-manifest.md` (produced by `prelim-variants`)
8
+ Invoked from `clearance-search` (orchestrator) alongside `clearance-register`. Reads:
9
+ - The variant manifest at `studio/clearance-search/<slug>/<date>/variant-manifest.md` (produced by `clearance-variants`)
10
10
  - The request context (classes, jurisdiction scope, industry, manner of use)
11
11
 
12
12
  Writes:
13
- - A common-law findings file at `studio/prelim-search/<slug>/<date>/common-law-findings.md`
14
- - **The machine grid ledger** at `studio/prelim-search/<slug>/<date>/common-law-grid.json` — the grid
13
+ - A common-law findings file at `studio/clearance-search/<slug>/<date>/common-law-findings.md`
14
+ - **The machine grid ledger** at `studio/clearance-search/<slug>/<date>/common-law-grid.json` — the grid
15
15
  call's stdout JSON saved **verbatim** (a single stdout object, or a JSON array of the per-batch
16
16
  stdout objects in batch order when the grid is batched). Copy it exactly as the tool returned it —
17
17
  no reformatting, no re-typing, no judging. **The driver validates grid completeness from this file**
@@ -29,7 +29,7 @@ Companion files:
29
29
 
30
30
  ## Trigger
31
31
 
32
- Called by `prelim-search` after `prelim-variants` has produced the manifest. Runs alongside `prelim-register` against the same manifest. Not invoked directly by operators.
32
+ Called by `clearance-search` after `clearance-variants` has produced the manifest. Runs alongside `clearance-register` against the same manifest. Not invoked directly by operators.
33
33
 
34
34
  ## Model
35
35
 
@@ -37,8 +37,8 @@ The model tier is set **by the deterministic driver** — `driver/stages.mjs` is
37
37
  source of truth (currently Haiku, low thinking). This worker is extraction, not open analysis: it
38
38
  fills templated Perplexity prompts from the manifest and transcribes what Perplexity returns into
39
39
  the fixed finding taxonomy. The creative variant/strategy work is already done upstream by
40
- `prelim-variants` (Opus), and the cross-cutting risk synthesis is the orchestrator's (Opus). If the
41
- orchestrator's skeptic review (prelim-search Step 2.6) finds this worker shortcut the manifest's
40
+ `clearance-variants` (Opus), and the cross-cutting risk synthesis is the orchestrator's (Opus). If the
41
+ orchestrator's skeptic review (clearance-search Step 2.6) finds this worker shortcut the manifest's
42
42
  coverage, it is re-spawned escalated to Opus.
43
43
 
44
44
  ## Tool call budget
@@ -61,7 +61,7 @@ the artifacts this stage writes, so there is nothing here to call and nothing to
61
61
 
62
62
  ## Search approval (HITL exception)
63
63
 
64
- The full HITL exception covering this workflow is declared **once** in the orchestrator at [prelim-search/SKILL.md](../prelim-search/SKILL.md#hitl-exception-shared-across-sub-skills). It is pre-approved at workflow trigger time when the requesting lawyer or a staff lawyer forwards the request email.
64
+ The full HITL exception covering this workflow is declared **once** in the orchestrator at [clearance-search/SKILL.md](../clearance-search/SKILL.md#hitl-exception-shared-across-sub-skills). It is pre-approved at workflow trigger time when the requesting lawyer or a staff lawyer forwards the request email.
65
65
 
66
66
  Operative rules for this sub-skill (Perplexity-side):
67
67
  - **Include in queries:** mark name, product type, relevant industry context
@@ -105,14 +105,14 @@ so there is **no partial-delivery fallback**:
105
105
 
106
106
  ### Out of scope (register-layer concerns)
107
107
 
108
- - USPTO / WIPO / national trademark office database searches — handled by `prelim-register`
108
+ - USPTO / WIPO / national trademark office database searches — handled by `clearance-register`
109
109
  - Class-specific register queries
110
110
  - Register statistics and filing volumes
111
111
  - Stealth-filing pattern analysis
112
112
  - Formal enforcement history analysis (organic mentions OK; targeted register-based enforcement search NOT)
113
113
  - Prior-art register-based analysis
114
114
 
115
- **Bleed rule:** if register information surfaces organically during a common-law search (e.g., a news article mentions a filing), note it briefly and flag it in the findings file's `Cross-checks suggested` section. Do not pursue it — the orchestrator hands such flags to `prelim-register` for cross-pollination.
115
+ **Bleed rule:** if register information surfaces organically during a common-law search (e.g., a news article mentions a filing), note it briefly and flag it in the findings file's `Cross-checks suggested` section. Do not pursue it — the orchestrator hands such flags to `clearance-register` for cross-pollination.
116
116
 
117
117
  ## Output — common-law findings file
118
118
 
@@ -165,14 +165,14 @@ For game-title rows, the `developer_of_record` and `publisher_of_record` columns
165
165
 
166
166
  | Finding | Source / Platform | URL | Notes |
167
167
  |---|---|---|---|
168
- | "Raising Your Play" | HP marketing | https://... | HP uses tagline for gaming hardware; no register protection found (flagged for prelim-register cross-check) |
168
+ | "Raising Your Play" | HP marketing | https://... | HP uses tagline for gaming hardware; no register protection found (flagged for clearance-register cross-check) |
169
169
  | 1,600+ "Dawn" titles on Steam | Steam | https://... | Crowded field — supportive evidence |
170
170
 
171
171
  ### Competitor intelligence
172
172
 
173
173
  | Finding | Source / Platform | URL | Notes |
174
174
  |---|---|---|---|
175
- | Sony "Pulse Elevate" portfolio | Sony products | https://... | Sony uses "Elevate" in audio products; flagged for prelim-register cross-check |
175
+ | Sony "Pulse Elevate" portfolio | Sony products | https://... | Sony uses "Elevate" in audio products; flagged for clearance-register cross-check |
176
176
  | Foxglade "Borealis" console "Raise Your Play" tagline (prior usage) | Foxglade Interactive marketing | https://... | Client's own prior use — note as supportive |
177
177
 
178
178
  ### PR / reputational risk
@@ -356,7 +356,7 @@ forms (and the gap form) — this is what the driver's receipt gate counts:
356
356
  ### Coverage ledger (feeds synthesis coverage-honesty + skeptic audit)
357
357
  <!-- clearotron:section=coverage-ledger -->
358
358
 
359
- One row per planned coverage unit (each mandatory platform; the field-scoped general search; non-Latin / transliteration platform reach), with status + one-line reason. Same three statuses as the register side (see `prelim-register/SKILL.md` → *Coverage ledger*): `confirmed-clean` (ran to completion), `coverage-limited` (the search **ran and reached the platform** but could not be exhausted — thin data, non-Latin reach), `deferred` (planned but **not run, or the platform/tool could not be reached**). Per the keystone doctrine: a could-not-reach gap (a platform/tool that was unavailable) is `deferred`, never `coverage-limited` — the latter is a searched-but-unexhausted DATA limit. This is the structured form of the Open-verification-flags prose — a `coverage-limited` row is **not** a clean negative downstream.
359
+ One row per planned coverage unit (each mandatory platform; the field-scoped general search; non-Latin / transliteration platform reach), with status + one-line reason. Same three statuses as the register side (see `clearance-register/SKILL.md` → *Coverage ledger*): `confirmed-clean` (ran to completion), `coverage-limited` (the search **ran and reached the platform** but could not be exhausted — thin data, non-Latin reach), `deferred` (planned but **not run, or the platform/tool could not be reached**). Per the keystone doctrine: a could-not-reach gap (a platform/tool that was unavailable) is `deferred`, never `coverage-limited` — the latter is a searched-but-unexhausted DATA limit. This is the structured form of the Open-verification-flags prose — a `coverage-limited` row is **not** a clean negative downstream.
360
360
 
361
361
  | Coverage unit | Status | Reason |
362
362
  |---|---|---|
@@ -364,7 +364,7 @@ One row per planned coverage unit (each mandatory platform; the field-scoped gen
364
364
  | field-scoped general search (collab / non-gaming goods) | confirmed-clean | run per matter scope |
365
365
  | non-Latin platform reach (translit variants) | coverage-limited | marketplace data thin for non-Latin scripts; absence not confirmed clean |
366
366
 
367
- ### Cross-checks suggested (handed to orchestrator for prelim-register dispatch)
367
+ ### Cross-checks suggested (handed to orchestrator for clearance-register dispatch)
368
368
 
369
369
  | Trigger | Suggested cross-check |
370
370
  |---|---|
@@ -400,7 +400,7 @@ Four steps per mark.
400
400
 
401
401
  ### Step 1 — Read variant manifest
402
402
 
403
- Open `studio/prelim-search/<slug>/<date>/variant-manifest.md`. Parse:
403
+ Open `studio/clearance-search/<slug>/<date>/variant-manifest.md`. Parse:
404
404
  - Request context: marks, classes, jurisdiction, industry, manner of use
405
405
  - Per-mark variant tables — these become the search terms in the Perplexity prompt
406
406
  - Watchlists — used for competitor intelligence framing
@@ -446,10 +446,10 @@ filling in:
446
446
 
447
447
  The tool returns the program's stdout JSON (`cells` + `extras` + `gaps`) and the program code as an
448
448
  audit receipt. **Trademark-register lookups stay out of scope** — the grid only searches
449
- marketplaces/web (the register layer is `prelim-register`'s).
449
+ marketplaces/web (the register layer is `clearance-register`'s).
450
450
 
451
451
  **LEGACY path only (no `grid_spec_path` given) — immediately after the grid call(s): save the stdout
452
- JSON verbatim** to `studio/prelim-search/<slug>/<date>/common-law-grid.json` — one call → the stdout
452
+ JSON verbatim** to `studio/clearance-search/<slug>/<date>/common-law-grid.json` — one call → the stdout
453
453
  object as-is; batched calls → a JSON array of the per-batch stdout objects, in batch order. This is a
454
454
  copy operation, not a writing task: the bytes the tool returned, unmodified. The deterministic driver
455
455
  validates the grid by exact join on this file (machine receipts) — the markdown Negative results
@@ -486,7 +486,7 @@ common word) does not. Then categorise each finding into one of:
486
486
  - **Competitor intelligence** — watchlist matches; existing partnerships major brands have in the space
487
487
  - **PR / reputational risk** — the meaning read of the mark AND its near-forms, scoped by the run's OWN dictated sweep: the fixed meaning / slang / gang / offensive / lookup shapes plus the matter frame's derived `Meaning angles:` queries (cultural origin/appropriation, charged history of the term or its imagery, category-specific controversy — as THIS matter's frame reasoned them). Never a generic sensitivities checklist — the scope IS the dictated sweep. NOT scored on legal-risk framework — separate category. **Every recorded query with results carries a ruling recorded through `record_dispositions`, whatever this section concludes** — reporting a loaded reading does not discharge the rest of the sweep (see the PR / reputational risk contract above). `None identified` is additionally a clean *receipt* ONLY when the meaning sweep ran — cite a `Connotation-search source:` line; the driver rejects an unsearched clean claim (`connotation_search_missing`) and refuses the turn while any ruling is unrecorded (the `connotation_call_*` family). A dictionary gloss is never a clearance.
488
488
  - **Negative results** — **one row for EVERY variant × platform grid cell** (the full grid accounting the driver's receipt gate counts), **plus rows for the field-scoped cells** (collab / non-gaming goods) when run. **Each row carries its receipt:** `No results` (the search returned nothing), `No similar listings (N candidates reviewed)` (returned N candidates, none prima facie similar), `Similar listing(s) found — see Findings (N candidates)` (the cell produced findings), or `not executed — coverage-limited (see ledger)` (the cell is in the grid's `gaps` — never a clean negative).
489
- - **Cross-checks suggested** — register-side checks the orchestrator should dispatch to `prelim-register` (every common-law owner found → ONE register check)
489
+ - **Cross-checks suggested** — register-side checks the orchestrator should dispatch to `clearance-register` (every common-law owner found → ONE register check)
490
490
 
491
491
  **100% URL coverage is mandatory.** Every finding row must have a clickable URL. If a finding cannot be verified with a URL, mark it as an Open verification flag and note the source.
492
492
 
@@ -514,7 +514,7 @@ This requirement applies even when the model running this skill is at the Haiku
514
514
 
515
515
  ### Step 6 — Compile common-law findings file
516
516
 
517
- Assemble `studio/prelim-search/<slug>/<date>/common-law-findings.md` per the format above. Sections (in order):
517
+ Assemble `studio/clearance-search/<slug>/<date>/common-law-findings.md` per the format above. Sections (in order):
518
518
 
519
519
  1. **Summary** — call counts, platform coverage, finding counts
520
520
  2. **Consumer-confusion risks** — gaming-industry overlap
@@ -545,6 +545,6 @@ Assemble `studio/prelim-search/<slug>/<date>/common-law-findings.md` per the for
545
545
  - [ ] Coverage ledger emitted — one row per planned coverage unit; non-Latin / thin-data reach logged `coverage-limited`, not silently clean
546
546
  - [ ] Cross-checks suggested section populated
547
547
  - [ ] Open verification flags listed (URL-404s, thin coverage, transliteration confirmations)
548
- - [ ] Common-law findings file written to `studio/prelim-search/<slug>/<date>/common-law-findings.md`
548
+ - [ ] Common-law findings file written to `studio/clearance-search/<slug>/<date>/common-law-findings.md`
549
549
  - [ ] Perplexity budget under workflow cap (15 calls)
550
550
  - [ ] No client identity, reference numbers, or contact names in any submitted Perplexity prompt
@@ -1,6 +1,6 @@
1
1
  # Perplexity prompts
2
2
 
3
- Templates for the `perplexity_research` calls in `prelim-common-law`. Prompts are **prescriptive, not exploratory** — they tell Perplexity exactly what to search for, where, and how to report.
3
+ Templates for the `perplexity_research` calls in `clearance-common-law`. Prompts are **prescriptive, not exploratory** — they tell Perplexity exactly what to search for, where, and how to report.
4
4
 
5
5
  ## Depth routing (mandatory)
6
6