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
package/.env.example CHANGED
@@ -1,7 +1,7 @@
1
1
  # =============================================================================
2
2
  # example.com-trademark — canonical environment contract (.env.example)
3
3
  # =============================================================================
4
- # The prelim-search product reads all of its configuration + credentials from
4
+ # The clearance-search product reads all of its configuration + credentials from
5
5
  # the environment. In production these live in the systemd EnvironmentFile
6
6
  # (`~/.env`, loaded as whichever service account runs the engine); in dev they are
7
7
  # exported before the run. This file is the DOCUMENTED CONTRACT — copy it to
@@ -86,6 +86,7 @@ CLEAROTRON_AI=anthropic-agent
86
86
  # write the path of setup's copy here: it would become the forced copy, and one installed later would never
87
87
  # be used. A path set here must be ABSOLUTE: stage subprocesses run with cwd set to the run directory.
88
88
  # Only the live engine's value is read, so a machine that runs both engines can set both.
89
+ # effect: setup
89
90
  CLEAROTRON_CLAUDE_PATH=claude
90
91
 
91
92
  # ── openai-agent (codex) knobs — ONLY read when CLEAROTRON_AI=openai-agent ────────────────────────
@@ -93,7 +94,9 @@ CLEAROTRON_CLAUDE_PATH=claude
93
94
  # overwriting the other — these were one variable until that collapse met a box needing two different
94
95
  # paths, and this file shipped two live rows for the single name until then (a last-wins assignment in
95
96
  # the copied `.env`, not a choice).
97
+ # effect: setup
96
98
  CLEAROTRON_CODEX_PATH=codex
99
+
97
100
  CLEAROTRON_WORK_DIR=
98
101
  # Customer/project config store (loadProfiles). Unset ⇒ driver's built-in profiles dir.
99
102
  CLEAROTRON_CUSTOMERS_DIR=
@@ -103,15 +106,28 @@ CLEAROTRON_INSTRUCTIONS_DIR=
103
106
  # REQUIRED — the code default was removed. Unset, the engine refuses and names this variable instead
104
107
  # of falling back to /srv/trademark-archive, which on a deployed box is real client matter.
105
108
  CLEAROTRON_REPORTS_DIR=/srv/trademark-archive
106
- # Run-slot lock dir. Default = $CLEAROTRON_WORK_DIR/prelim-run-locks. Every run takes a slot here,
109
+ # Run-slot lock dir. Default = $CLEAROTRON_WORK_DIR/clearance-run-locks. Every run takes a slot here,
107
110
  # whether the runner dispatched it or somebody launched it by hand, so this is what bounds concurrency
108
111
  # across an install rather than within one process. The portal also reads it to find the worker
109
112
  # heartbeat; two installs pointed at one lock dir would share a cap they do not expect to.
110
113
  # effect: deployment
111
114
  CLEAROTRON_RUN_LOCK_DIR=
112
- # Delivery outbox dir (instant handoff-mode delivery wake). Default = $CLEAROTRON_WORK_DIR/prelim-outbox.
115
+ # Delivery outbox dir (instant handoff-mode delivery wake). Default = $CLEAROTRON_WORK_DIR/clearance-outbox.
116
+ # Was `prelim-outbox`. A box that never set this keeps its markers there and they are still read and drained;
117
+ # new markers are written under the new name. Nothing to move.
113
118
  # effect: deployment
114
119
  CLEAROTRON_OUTBOX_DIR=
120
+ # Where the shared register CALL ledger lives — the per-query record the register spend is counted from.
121
+ # Default = ~/trademark/telemetry/register-calls.jsonl. An install that moves or clears it changes what a
122
+ # later cost read can account for, and nothing else records where it went.
123
+ # effect: deployment
124
+ CLEAROTRON_REGISTER_CALL_LOG=
125
+ # Where the register RECORD log lives — the fetched-record store a "verified from the record" claim on a
126
+ # report joins against. Resolved by EXISTENCE over several directories and filenames, not by name alone,
127
+ # so that an install which inherited an older path keeps reading its own ledger; setting this overrides
128
+ # that ladder outright. An install pointed at an empty path reports no fetched records and no fault.
129
+ # effect: deployment
130
+ CLEAROTRON_REGISTER_RECORD_LOG=
115
131
  # HEADLESS intake: one explicit queue dir (no agent workspaces needed) — the enqueue CLI + ops-MCP
116
132
  # start_run write here and the runner drains it (additive to the workspace scan). See docs/INTAKE.md.
117
133
  CLEAROTRON_QUEUE_DIR=
@@ -481,6 +497,21 @@ CLEAROTRON_CUT_REF=
481
497
  # effect: tuning
482
498
  CLEAROTRON_RELEASE_WAIT_MS=
483
499
 
500
+ # Whether this release run was dispatched to cut. The workflow sets `true` on a `workflow_dispatch` that
501
+ # is not a rehearsal, and `false` otherwise. Set, a wait that expires with no version published is a
502
+ # failure that names why, because the one thing the run was dispatched for did not happen; a push or the
503
+ # schedule asks nothing of the wait, so expiry there stays a quiet success. Read by
504
+ # scripts/release-await-cut.mjs.
505
+ # effect: tuning
506
+ CLEAROTRON_CUT_REQUESTED=
507
+
508
+ # The number of the version pull request the same run opened, so a failed wait reads why that pull
509
+ # request did not merge rather than guessing. The workflow sets it from the version job's output. Unset,
510
+ # or not a whole number, a dispatched wait says it found no pull request to wait on. Read by
511
+ # scripts/release-await-cut.mjs.
512
+ # effect: tuning
513
+ CLEAROTRON_CUT_PR=
514
+
484
515
  # A GitHub token carrying Actions read and write. The release workflow supplies it from a repository
485
516
  # secret so that a cut does not wait for a person to approve the version pull request's parked CI run:
486
517
  # that run is authored by the repository's own Actions bot, and GitHub parks bot-authored runs as
package/CONTRIBUTING.md CHANGED
@@ -54,7 +54,7 @@ Four more things run for free:
54
54
  | Command | What it proves |
55
55
  |---|---|
56
56
  | `node mcp-server/smoke.mjs` | Drives the real MCP server over stdio against a built fixture. Prints `SMOKE OK`. |
57
- | `node driver/dev-portal.mjs` | Serves a pool at `http://127.0.0.1:18899/` — archive index, reports, customer pages. Loopback only; it refuses any other host. Needs a pool to point at (`CLEAROTRON_REPORTS_DIR`). |
57
+ | `node driver/dev-portal.mjs` | Serves a pool at `http://127.0.0.1:18899/` — archive index, reports, company pages. Loopback only; it refuses any other host. Needs a pool to point at (`CLEAROTRON_REPORTS_DIR`). |
58
58
  | The $0 mock pipeline | A full run — intake, every stage, publish, delivery packet — on a mocked engine. Recipe in [docs/E2E.md § Tier 1](docs/E2E.md). Follow it as written; the absolute-path trap in it catches everybody. |
59
59
  | `npx clearotron demo` | Replays `demo/` — a real run on a fictional mark — through the real publisher into `~/trademark-demo/pool` and serves it. No keys, no model, no engine. |
60
60
 
@@ -75,7 +75,7 @@ half did not run. `npx clearotron install` walks through both, and
75
75
  [INSTALL.md § 1](INSTALL.md#1-prerequisites) is the full list.
76
76
 
77
77
  **The scenario suite is private by design.** `scripts/e2e.mjs` scores runs against lawyer-written
78
- reference answers on real matters; the references and the config store they load from are client work
78
+ reference answers on real matters; the references and the config store they load from are company work
79
79
  product and will not be published. Its absence weakens nothing you can run — the in-repo suite covers
80
80
  the machinery, and the scenario suite covers the answers. The validation ladder, from the $0 offline
81
81
  suite to a paid live run, is [docs/E2E.md](docs/E2E.md).
@@ -130,13 +130,13 @@ The reviewer is the check. Say what you checked in the PR rather than citing a p
130
130
  **3. Types are enforced, and `vite build` does not typecheck.** `npm run typecheck -w portal-ui`
131
131
  runs as its own CI step. Run it before you push.
132
132
 
133
- **4. Every sentence a customer reads is written against the standard, and five classes of it are
133
+ **4. Every sentence a company reads is written against the standard, and five classes of it are
134
134
  checked.** The standard is [`docs/writing-standard.md`](docs/writing-standard.md); the prose rules
135
135
  under it are [`docs/writing-rules.md`](docs/writing-rules.md), and they apply first. Together they
136
136
  bind report HTML, portal screens, the README and the docs.
137
137
 
138
138
  `node scripts/writing-standard-check.mjs` refuses what your change ADDS to one of those surfaces:
139
- an engineering identifier in text a client reads, a reviewer-only marker in rendered output, a known
139
+ an engineering identifier in text a company reads, a reviewer-only marker in rendered output, a known
140
140
  caveat sentence, a screen that writes its own page heading instead of using `PageHeader`, and a lede
141
141
  whose words are all already in its title. It names the class and prints the line. It never rewrites —
142
142
  a rewritten sentence is a sentence nobody reviewed.
@@ -153,7 +153,7 @@ identifier, no caveat and no banned word and still be the thing the standard exi
153
153
  heading that restates its section, a paragraph explaining what the reader can already see, a sentence
154
154
  that only works if you know how the engine is built.
155
155
 
156
- So: **a pull request that changes text a customer reads is reviewed against the rendered page or
156
+ So: **a pull request that changes text a company reads is reviewed against the rendered page or
157
157
  report, not against the diff.** One reviewer reads it as someone who has never seen this product and
158
158
  asks one question of every new sentence — *what would a reader with zero context think this means?*
159
159
  If the answer needs the codebase, the sentence is cut or rewritten. One reviewer, one question,
@@ -288,9 +288,9 @@ narrower is usually the defect rather than the fix, and it will be read that way
288
288
 
289
289
  ### The three possible outcomes
290
290
 
291
- **Into the base layer.** Your change becomes part of what every install gets, including ours and our
292
- clients'. That is the highest bar: it has to be an improvement for the matters this doctrine is tuned
293
- for, not only for yours.
291
+ **Into the base layer.** Your change becomes part of what every install gets, including ours and the
292
+ installs we run for companies. That is the highest bar: it has to be an improvement for the matters
293
+ this doctrine is tuned for, not only for yours.
294
294
 
295
295
  **Published as a pack.** Doctrine resolves file by file — an install can point at another directory and
296
296
  have its files win, with everything it does not override falling through to ours. So a change that is
package/INSTALL.md CHANGED
@@ -153,7 +153,7 @@ passed, and nothing has driven a live register through it.
153
153
 
154
154
  **Upgrading an install made before 0.2.2: pin the agent id first.** The default agent id changed from
155
155
  `clawdi` to `localagent`, and that id is part of a path — your runs live under
156
- `<workspaceRoot>/workspace-<agent>/studio/prelim-search/`. If you never set an agent id, the upgraded
156
+ `<workspaceRoot>/workspace-<agent>/studio/clearance-search/`. If you never set an agent id, the upgraded
157
157
  install reads a workspace that does not exist yet, and an empty workspace looks like an account with no
158
158
  runs rather than like a misconfiguration. Set **both** names in your environment file before starting
159
159
  it, because the register-search servers read their own:
@@ -624,12 +624,12 @@ a bespoke risk framework. A job resolves to a profile by the **forwarder's email
624
624
  matches, the neutral Generic default applies.
625
625
 
626
626
  - **Bundled with the package** (`driver/profiles/`): `generic.json` (the Generic default) and
627
- `demo-brand-owner.json`, the account the demo runs as, so you can run and read the machinery
627
+ `demo-brand-owner.json`, the company the demo runs as, so you can run and read the machinery
628
628
  immediately. `driver/profiles/README.md` documents every field. (A clone of the repository carries
629
629
  three more, marked `testFixture` in their own files: the test suite reads them, no install offers
630
630
  them, and they are excluded from the published package as well.)
631
631
  - **Your real companies live outside the repo.** Point `CLEAROTRON_CUSTOMERS_DIR` at your own private
632
- config store and the engine loads *those* accounts instead. **Same engine, different config path** —
632
+ config store and the engine loads *those* companies instead. **Same engine, different config path** —
633
633
  the code carries no company identities.
634
634
 
635
635
  Two things go with it, and both are refusals rather than preferences:
@@ -661,7 +661,7 @@ self-contained.
661
661
  A company is not only its `<key>.json`. Two more things sit beside it, both optional, both shipped as
662
662
  working examples in `driver/profiles/`:
663
663
 
664
- - **A context pack** — `<key>.context.md`, a sibling of the profile. Free prose about the account that
664
+ - **A context pack** — `<key>.context.md`, a sibling of the profile. Free prose about the company that
665
665
  the engine attaches to the profile it loads. One ships beside a bundled demo company.
666
666
  - **Project overlays** — `projects/<customer-key>/<slug>.json`. A project is one engagement under a
667
667
  company: a launch screening, a flagship clearance, a regional push. Each may carry its own
@@ -689,7 +689,7 @@ overlay stating `defaultClasses` narrows to exactly what it states.
689
689
 
690
690
  **Setting `CLEAROTRON_CUSTOMERS_DIR` replaces the whole tree, projects included.** The engine reads your
691
691
  store's companies and your store's `projects/`, and none of ours. That is deliberate — a deployment's
692
- roster holds its own accounts and nothing of ours — but it is silent, and it is the one thing here that
692
+ roster holds its own companies and nothing of ours — but it is silent, and it is the one thing here that
693
693
  becomes an incident on a real deployment rather than a bundled one:
694
694
 
695
695
  - A job naming a project your store does not carry is **not refused**. The `projectKey` is dropped and
@@ -1364,7 +1364,7 @@ A courier is a loop over one directory, and it needs no unit of its own if you a
1364
1364
 
1365
1365
  1. **Watch the outbox** — `$CLEAROTRON_OUTBOX_DIR`. A `.pending` file appears there when a run
1366
1366
  finishes. Read the variable rather than guessing the directory: the wizard writes `<data
1367
- base>/outbox`, but an unset variable falls back to `prelim-outbox` under the workspace root
1367
+ base>/outbox`, but an unset variable falls back to `clearance-outbox` under the workspace root
1368
1368
  (`driver/driver.config.mjs`), so the two are not the same path and only one of them is where your
1369
1369
  markers are.
1370
1370
  2. **Read what it points at.** A success marker is a few bytes naming the agent, *not* the payload —
package/SECURITY.md CHANGED
@@ -26,7 +26,7 @@ affected versions, and a fix or a written decision not to fix. We will credit yo
26
26
  ask us not to.
27
27
 
28
28
  **Never attach a run artifact to a report.** Reports, audit workbooks, run directories and pool
29
- contents can carry client names, marks and matters. Describe the shape of the data instead, or
29
+ contents can carry company names, marks and matters. Describe the shape of the data instead, or
30
30
  reproduce it against the repo's synthetic fixtures.
31
31
 
32
32
  ## What is in scope
@@ -42,8 +42,8 @@ In particular, we want to hear about anything that breaks these:
42
42
  - **Fail-closed construction.** The HTTP face refuses to start without an audience, an issuer, and an
43
43
  identity gate. Any path that serves a request with authentication silently absent is in scope.
44
44
  - **The dev portal's loopback bind.** `driver/dev-portal.mjs` must refuse every non-loopback host.
45
- - **Client-facing surfaces leaking internals.** An env var name, a switch name, or an internal path
46
- rendered into a report or a client-visible error.
45
+ - **Company-facing surfaces leaking internals.** An env var name, a switch name, or an internal path
46
+ rendered into a report or a company-visible error.
47
47
  - **Traversal and injection** into artifact reads, pool paths, or run directories.
48
48
 
49
49
  [`docs/SECURITY.md`](docs/SECURITY.md) documents the whole envelope — what protects what, and where
@@ -113,7 +113,7 @@ const USAGE = `
113
113
  --domains comma-separated email domains that resolve to this owner
114
114
  --platforms comma-separated marketplaces their searches cover
115
115
  omitted ⇒ the Generic default's platforms are applied and named in the output
116
- --framework their risk framework, as skills/prelim-search/<file>.md
116
+ --framework their risk framework, as skills/clearance-search/<file>.md
117
117
  omitted ⇒ the Generic default is applied and named in the output
118
118
  --industry free text, shown on their profile
119
119
  --context a file whose contents become this owner's context pack
@@ -121,7 +121,7 @@ const USAGE = `
121
121
 
122
122
  clearotron brandowner framework <key> <path>
123
123
 
124
- Point an existing company at a risk framework, as skills/prelim-search/<file>.md.
124
+ Point an existing company at a risk framework, as skills/clearance-search/<file>.md.
125
125
  The deck is checked before anything is written: a path that does not resolve, or a
126
126
  manifest that will not load, is refused and the company is left exactly as it was.
127
127
 
@@ -298,7 +298,7 @@ export async function framework(argv, {
298
298
  } = {}) {
299
299
  const [key, path] = argv;
300
300
  if (!key) throw new Refusal(`this command needs a company key.${USAGE}`);
301
- if (!path) throw new Refusal(`this command needs a framework path, as skills/prelim-search/<file>.md.${USAGE}`);
301
+ if (!path) throw new Refusal(`this command needs a framework path, as skills/clearance-search/<file>.md.${USAGE}`);
302
302
  try { assertProfileKey(key); }
303
303
  catch (e) { throw new Refusal(e?.message ?? String(e)); }
304
304
 
@@ -20,7 +20,7 @@ import { invocationPrefix } from "../shared/invocation.mjs";
20
20
  import { preflightFramework, formatPreflight } from "../driver/framework-preflight.mjs";
21
21
 
22
22
  const USAGE = (cmd) => `
23
- ${cmd} framework <skills/prelim-search/your-framework.md>
23
+ ${cmd} framework <skills/clearance-search/your-framework.md>
24
24
 
25
25
  Reads a risk framework deck and the manifest beside it, and reports what they declare —
26
26
  the ladder, the company the deck names, the shape, and which file answered where.
package/bin/start.mjs CHANGED
@@ -113,6 +113,7 @@ export async function runTables() {
113
113
  import { spawn, spawnSync, execFileSync } from "node:child_process";
114
114
  import { storeInRepo, storeOutsideRepoMessage, storeCommitRefusal } from "../shared/store-in-repo.mjs"; //
115
115
  import { stdioConnectOffer } from "../shared/stdio-connect.mjs";
116
+ import { wslTarget } from "../shared/wsl.mjs"; // — and which distribution a row should start the server in
116
117
  import { ensureDemoProgram } from "../shared/permanent-install.mjs"; // — a demo from npx keeps its own copy
117
118
  import { mergeEnvFile } from "../shared/env-file-merge.mjs";
118
119
  import { mcpOriginFor } from "../shared/lane-address.mjs"; // — one author for the origin
@@ -2522,11 +2523,24 @@ if (isMain) {
2522
2523
  // THE WORKSPACE AND POOL THE SERVICES WERE HANDED, not this process's environment: a demo reads no env
2523
2524
  // file, so its own line named no workspace and the connector fell back to the real install's.
2524
2525
  // A demo run from npx names its own copy of the program, which a cache clean does not remove.
2525
- const connect = stdioConnectOffer({ workDir: paths.workspace, reportsDir: paths.pool, ...(demoProgramRoot ? { installRoot: demoProgramRoot } : {}) });
2526
- say(" Connect your assistant to this install — one line, no address and no sign-in:");
2527
- say("");
2528
- say(` ${connect.command}`);
2526
+ // AND WHICH SIDE OF A WSL INSTALL THE READER IS ON, because this is where he read the line from. An
2527
+ // install inside WSL can be reached from Windows and from inside the distribution, by two different
2528
+ // commands; printing one of them unheaded is how a reader pastes the wrong one. The target is read
2529
+ // here and passed, because this module is pure by design and reads no environment of its own.
2530
+ const connect = stdioConnectOffer({ workDir: paths.workspace, reportsDir: paths.pool, wsl: wslTarget(), ...(demoProgramRoot ? { installRoot: demoProgramRoot } : {}) });
2531
+ // "one line" IS DELETED RATHER THAN MADE CONDITIONAL. Under WSL two lines are printed, one per side,
2532
+ // and the count was never the point of the sentence — what it promises is no address and no sign-in,
2533
+ // which is true on both sides and on every other install.
2534
+ say(" Connect your assistant to this install — no address and no sign-in:");
2529
2535
  say("");
2536
+ // THE HEADINGS COME WITH THE PAIR, from the composer. Nothing is written here: the page prints these
2537
+ // same two words above these same two commands, and a second author is how the two surfaces drift.
2538
+ if (connect.variants) {
2539
+ for (const v of connect.variants) { say(` ${v.heading}`); say(` ${v.text}`); say(""); }
2540
+ } else {
2541
+ say(` ${connect.command}`);
2542
+ say("");
2543
+ }
2530
2544
  say(` Check it: ${connect.verify}`);
2531
2545
  say("");
2532
2546
  // ── WHERE TO TYPE THE THINGS JUST PRINTED ( — F31) ───────────────────────
package/build-info.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "commit": "7596846c65b0bd1a4dcc291732803da5fa8e9ccb",
3
- "version": "0.3.2-beta.8"
2
+ "commit": "7f7f7668374023298def34129e3007303163c5ed",
3
+ "version": "0.3.2-beta.9"
4
4
  }
package/docs/DELIVERY.md CHANGED
@@ -18,7 +18,8 @@ ignores the value.
18
18
 
19
19
  ## The outbox
20
20
 
21
- `config.outboxDir` = `CLEAROTRON_OUTBOX_DIR` (default `<CLEAROTRON_WORK_DIR>/prelim-outbox`).
21
+ `config.outboxDir` = `CLEAROTRON_OUTBOX_DIR` (default `<CLEAROTRON_WORK_DIR>/clearance-outbox`; the
22
+ earlier `clearance-outbox` is still read, so markers written before the rename still drain).
22
23
  All packets are written atomically (`.tmp` + rename) — a watcher never sees a half-written
23
24
  file. Every packet carries a `ts` ISO timestamp. Watch the dir for `*.pending` (systemd
24
25
  `.path`, inotify, or poll); a periodic scan of run `status.json` files is the recommended
package/docs/INTAKE.md CHANGED
@@ -23,7 +23,7 @@ Resolution (the runner drains **all** of these; `config.queueDirs`):
23
23
  | Source | Path | Use |
24
24
  |---|---|---|
25
25
  | `CLEAROTRON_QUEUE_DIR` env | one explicit dir | **headless deployments** (the product default; no agent workspaces needed). Jobs here run as `config.defaultAgent`. |
26
- | workspace scan | `<CLEAROTRON_WORK_DIR>/workspace-<agent>/studio/prelim-search/queue` | legacy/agent-adjacent deployments; the agent identity is derived from the queue location |
26
+ | workspace scan | `<CLEAROTRON_WORK_DIR>/workspace-<agent>/studio/clearance-search/queue` | legacy/agent-adjacent deployments; the agent identity is derived from the queue location |
27
27
 
28
28
  The enqueue CLI resolves its target the same way: `--queue-dir` flag → `CLEAROTRON_QUEUE_DIR` →
29
29
  the default agent's workspace queue.
@@ -32,7 +32,7 @@ malformed one is refused before anything is written.
32
32
  | `--name` | the legal name. Required. |
33
33
  | `--domains` | comma-separated email domains that resolve to this company |
34
34
  | `--platforms` | marketplaces their searches cover. Omitted, the default's platforms apply and are named in the output. |
35
- | `--framework` | their risk framework, as `skills/prelim-search/<file>.md`. Omitted, the default applies and is named in the output. |
35
+ | `--framework` | their risk framework, as `skills/clearance-search/<file>.md`. Omitted, the default applies and is named in the output. |
36
36
  | `--industry` | free text, shown on their profile |
37
37
  | `--context` | a file whose contents become this company's context pack |
38
38
  | `--dry-run` | say exactly what would be written, and write nothing |
@@ -27,7 +27,7 @@ Two doctrines govern everything below:
27
27
  sequenceDiagram
28
28
  autonumber
29
29
  participant A as Forwarding agent<br/>(integrator platform)
30
- participant Q as Per-agent queue dir<br/>(studio/prelim-search/queue)
30
+ participant Q as Per-agent queue dir<br/>(studio/clearance-search/queue)
31
31
  participant S as systemd<br/>(.path + 90s .timer)
32
32
  participant R as runner.mjs
33
33
  participant P as pipeline.mjs
@@ -89,7 +89,7 @@ an unknown company proceeds on the generic profile with a late-bind watch (§4).
89
89
 
90
90
  **Matter-level dedup** (`runner.mjs`). Queue-file dedup is per *message*; a "please
91
91
  proceed" reply in an already-handled thread arrives under a new message-id. The driver therefore
92
- keeps a matter ledger (`studio/prelim-search/.matter-ledger.jsonl`) and parks as `.duplicate` any
92
+ keeps a matter ledger (`studio/clearance-search/.matter-ledger.jsonl`) and parks as `.duplicate` any
93
93
  job within the window (a fixed 24 hours) that matches a prior entry by
94
94
  exact signature (`forwarder|mark|classes|customer|ref`, plus a `|level:<product>` dimension on any
95
95
  non-baseline product) or by same conversation-thread with agreeing mark *and* agreeing product. The
@@ -108,7 +108,7 @@ winner (`runner.mjs`). A `.pid` sidecar records `<pid>:<starttime>` (starttime t
108
108
  **Run identity is minted before any spend.** The codename (`adjective-noun`) is minted at dispatch
109
109
  and written atomically to `<id>.processing.meta` *before* the pipeline starts (`runner.mjs`).
110
110
  A crash anywhere after that resumes the *same* run directory instead of re-spending a fresh run.
111
- Run dirs are `<workspace>/studio/prelim-search/<slug>/<date>-<codename>`, slug =
111
+ Run dirs are `<workspace>/studio/clearance-search/<slug>/<date>-<codename>`, slug =
112
112
  `tmp<n>-<kebab-mark>` (or `noref<6-hex>-<mark>` when no reference was given; `phase0.mjs`).
113
113
 
114
114
  **Orphan reclaim** (`runner.mjs`) runs once per drain. A `.processing` whose claimer is
@@ -177,7 +177,7 @@ seeding. Frozen sidecars are never silently re-derived; a corrupt one crashes lo
177
177
  ```mermaid
178
178
  flowchart TD
179
179
  subgraph HEAD["Phase 1-2 head (fatal)"]
180
- MF[matter-frame] --> PV[prelim-variants]
180
+ MF[matter-frame] --> PV[clearance-variants]
181
181
  PV --> DER["code derivations:<br/>scope ledger · form neighbourhood ·<br/>register plan freeze · recall probes"]
182
182
  end
183
183
  DER --> GRID["grid spec dictated by code<br/>(terms × platforms × connotation; A1 split)"]
@@ -217,7 +217,7 @@ flowchart TD
217
217
 
218
218
  Reading order for the phases, with what code decides at each:
219
219
 
220
- 1. **Head stages** — `matter-frame` then `prelim-variants`, both fatal. Code then derives the
220
+ 1. **Head stages** — `matter-frame` then `clearance-variants`, both fatal. Code then derives the
221
221
  scope ledger, the *form neighbourhood* (the model picks the distinctive token; the machine
222
222
  generates the complete mechanical variant floor), freezes the register plan
223
223
  (`_driver/register-plan.json`, frozen for the life of *this run* — a resume never re-plans, and a
@@ -445,7 +445,7 @@ node pipeline.mjs --resume <codename> --experiment <stage> [--label <t>]
445
445
  - **`--from`** forces stages at or after the named ordinal even if their outputs validate; earlier
446
446
  stages still skip. A `--from synthesis` fork deliberately does *not* lock the digest.
447
447
  - **`--experiment`** runs one stage in a shadow dir (`_experiments/<ts>-<tag>/`) on copies of its
448
- inputs, under a `prelim-exp-…` session key that is excluded from the run's provider-usage
448
+ inputs, under a `clearance-exp-…` session key that is excluded from the run's provider-usage
449
449
  attribution. The canonical run is untouched.
450
450
  - **Orphan self-resume**: a manually resumed run that parks has no queue sidecars; the runner scans
451
451
  run dirs for due, payload-complete `.postponed` sentinels not owned by any queue and resumes them
@@ -74,7 +74,7 @@ does after the stage's full retry ladder fails ([03 §5](03-run-lifecycle.md#5--
74
74
  | # | Stage | Model · effort | Timeout / stall | Gated output (file truth) | Fatality |
75
75
  |---|---|---|---|---|---|
76
76
  | 1 | `matter-frame` | opus · high | 300 / 300 | `matter-context.md` | fatal |
77
- | 2 | `prelim-variants` | opus · high | 600 / 450 | `variant-manifest.md` (+ `.json` sibling, strict-parsed) | fatal |
77
+ | 2 | `clearance-variants` | opus · high | 600 / 450 | `variant-manifest.md` (+ `.json` sibling, strict-parsed) | fatal |
78
78
  | 3 | `blind-frame` | opus · high | 600 / 450 | `blind-frame-model.json` (strict-parsed; the prose twin was retired 2026-08-03 — nothing read it) | non-fatal (frame-diff skipped this run) |
79
79
  | 4 | `common-law` | haiku · low | 2250 / 1100 | `common-law-findings.md` (+ grid ledger, plugin-written) | fatal at fan-in |
80
80
  | 5 | `common-law-half` | per seat: `COMMON_LAW_SEAT_TIER` — halves `a`/`b` haiku · low; meaning seat `m` `CLEAROTRON_MEANING_SEAT_MODEL` \|\| haiku · low | 2250 / 1100 | `common-law-findings.half-{a,b,m}.md` (+ per-seat grid ledgers) | fatal at fan-in; one-half transient quarantine allowed |
@@ -201,8 +201,8 @@ deployment may override (verify live values per deployment).
201
201
  | `CLEAROTRON_REPORTS_DIR` | **none — set it** | Publish pool (web-served). **No default since: unset refuses and names the variable.** It read`/srv/trademark-archive` — a deployed server's real archive — so a forgotten export published into somebody else's clearances, and two entry points already carried hand-written defences against exactly that (`bin/onboard.mjs`, `bin/example.mjs`). Same shape as `CLEAROTRON_DATABASE` and `scripts/purge-runs.mjs`: guessing wrong is expensive, so it does not guess. Read-only surfaces (flag snapshot, status page, MCP options) degrade to "no pool" instead of throwing; anything that writes refuses. `driver/production-pool-guard.mjs` still names `/srv/trademark-archive` on purpose — that constant is a fact about where the archive is, not a default. |
202
202
  | `CLEAROTRON_REPORTS_URL` | **none — set it** | Pool base URL used in notification links. No placeholder default: unset ⇒ the link is omitted and the runner logs `deployment config MISSING` at activation. It does not gate the queue (a missing hostname costs a link, not the deliverable), so treat that log line as the alarm. |
203
203
  | `CLEAROTRON_ACCESS_DOMAIN` | unset (note omitted) | Identity domain named in the delivery email's access note ("sign in with a `<domain>` account"). Unset ⇒ the note is omitted rather than naming the wrong domain. |
204
- | `CLEAROTRON_RUN_LOCK_DIR` | `<workspaceRoot>/prelim-run-locks` | Run-slot lock dir (turn locks under `…/turns`). |
205
- | `CLEAROTRON_OUTBOX_DIR` | `<workspaceRoot>/prelim-outbox` | Delivery outbox (`<runId>.pending` wake markers). |
204
+ | `CLEAROTRON_RUN_LOCK_DIR` | `<workspaceRoot>/clearance-run-locks` | Run-slot lock dir (turn locks under `…/turns`). |
205
+ | `CLEAROTRON_OUTBOX_DIR` | `<workspaceRoot>/clearance-outbox` | Delivery outbox (`<runId>.pending` wake markers). Renamed from `clearance-outbox`; when this variable is unset the old directory is still READ, so a box that never pinned it does not orphan markers it has already written. Writers use the new name only. |
206
206
  | `CLEAROTRON_OAUTH_BRIDGE` | module-relative `providers/oauth-mcp-bridge/bridge.mjs` | Case-law MCP bridge script. (Portable since the module-relative default; set explicitly only for a bridge outside the repo tree.) |
207
207
  | `CLEAROTRON_REGISTER_CALL_LOG` | `~/trademark/telemetry/register-calls.jsonl`, or the existing file wherever it already is | Billing-grade provider-call ledger, shared by whichever ONE register provider is wired — not a vendor artifact. Every read site derives the default from`homedir()` at call time (2026-07-19: two sites had hardcoded a literal home directory, splitting the ledger under any other service account — guarded by `test/deployment-hostnames.test.mjs`). |
208
208
  | `CLEAROTRON_REGISTER_RECORD_LOG` | **runtime-injected per run**: `<runDir>/_driver/register-record-bodies.jsonl` | Citation-fidelity log: the BODY of every fetched official record. ** moved it INTO the run** — created with the run, unioned into the run's`_records/`, archived and purged with it. There is no retention setting and no cleanup job, because it no longer grows on the box: held globally it reached 432 MB in 61 days on production and needed a rotation timer on every install. **Do not set this by hand** — a fixed value pins every run's bodies to one file and restores the problem. A box upgraded across still holds its old global file; nothing writes or reads it, the driver names it once per process on stderr, and archiving it is one`mv`. An empty log cannot read as verified: the run's successful `record_fetch` rows in the (still global) call ledger are compared against the assembled record set, and a gap is reported as a failure. |
@@ -303,6 +303,8 @@ because the rule is about what PRODUCT CODE reads, not about what a run reads.
303
303
  | `CLEAROTRON_UPDATER_STAMP` | `_updater-identity.json` beside the update script, in the directory the updater runs from | The full path of the file in which the updater that deploys this box records which copy of itself ran. The updater writes it and deploy health reads it under this one name, so a box that moves the stamp sets it once for both. On a box with no updater unit, setting it says an updater exists elsewhere and is to be judged. Effect class `deployment`. |
304
304
  | `CLEAROTRON_CUT_REF` | `HEAD` | Which ref the cut decision reads the version from. **Read only by the release workflow, never set on a deployment.** The jobs that ask about `main` set it to `origin/main` explicitly, because their checkout is pinned to the run's own ref and `HEAD` there is that ref rather than the branch they are deciding about. A job that asks the wrong subject gets a confident wrong answer. |
305
305
  | `CLEAROTRON_RELEASE_WAIT_MS` | 25 minutes | How long a requested cut waits for the version pull request to merge itself before giving up. **Read only by the release workflow.** A rehearsal sets it to `0` so the wiring is exercised without holding a runner. Giving up is a quiet success by design — the scheduled run underneath catches a cut whose wait expired — so this budget failing shows up as a slow job rather than a red one. |
306
+ | `CLEAROTRON_CUT_REQUESTED` | unset (⇒ not dispatched) | Whether this release run was dispatched to cut. **Read only by the release workflow, never set on a deployment.** The workflow sets `true` on a dispatch that is not a rehearsal. Set, a wait that expires with no version published is a failure that names why; a push or the schedule leaves expiry a quiet success. Effect class `tuning`. |
307
+ | `CLEAROTRON_CUT_PR` | unset | The number of the version pull request the same run opened. **Read only by the release workflow, never set on a deployment.** A failed wait reads why that pull request did not merge from it. Unset or not a whole number, a dispatched wait says it found no pull request to wait on. Effect class `tuning`. |
306
308
  | `ACTIONS_APPROVE_TOKEN` | unset | A GitHub token with Actions read and write, used to approve the version pull request's parked CI run so a cut does not wait for a person. **Read only by the release workflow, never set on a deployment.** The built-in token cannot approve a run — GitHub blocks self-approval — so this is a second, separate credential. Unset is the ordinary case and not an error: the script names the absent token and exits successfully, and the version run waits for a person as it did before. Actions write is broader than approval alone — it also dispatches workflows, cancels any run in the repository and deletes run logs. |
307
309
  | `CLEAROTRON_AGENT_MCP_URL` | unset (⇒ `null`) | The API-key MCP door advertised to a signed-in person. Null until that door is deployed, and the UI keeps its honest empty state rather than inventing a URL. |
308
310
  | `CLEAROTRON_AGENTS` | derived | Comma-separated agent ids for `scripts/purge-runs.mjs` to sweep. |
@@ -324,6 +326,7 @@ cannot be read as one list.
324
326
  | Var | Consumer |
325
327
  |---|---|
326
328
  | `ANTHROPIC_API_KEY` | Engine child env in `api-key` mode only (deleted in subscription and cloud modes). |
329
+ | `CLAUDE_CODE_OAUTH_TOKEN` | The headless subscription sign-in's token, printed by `claude setup-token` on any machine that can sign in. Read by the Claude program itself: the engine's stage process inherits it untouched in every billing mode, which is how a browserless server authenticates the subscription lane. Setup names it as the token to paste. |
327
330
  | `CLAUDE_CODE_USE_VERTEX` / `CLAUDE_CODE_USE_FOUNDRY` / `CLAUDE_CODE_USE_BEDROCK` | **Read by the Claude program**, which sends every turn to that cloud; `1`, `true`, `yes` or `on` switches one on. Clearotron reads them to name the cloud under `CLEAROTRON_AI_BILLING=cloud` and to refuse a switch left on under `subscription` or `api-key`. Under `CLEAROTRON_AI_BILLING=cloud`, `clearotron start --background` carries the switch that is on, and every setting in the five rows below that is set, the model pins included, into `~/.env` (a switch that is set and not on stays behind); under `subscription` or `api-key` it carries none. It adds only a line `~/.env` lacks, and names any of these on which that file and its own configuration differ. A missing switch is reported by `clearotron start` and `clearotron doctor`, and refuses a search when it is ordered. Doctor and setup's proof turn carry these and the five rows below from the settings file a search reads, which is the one at the old location while an install is still configured there (`CLOUD_SETTINGS` in `driver/engine/auth.mjs`). A value in the shell wins over the file's: setup's proof turn keeps a blank one, as a run does, where doctor passes over it and takes the file's. In setup, an answer given wins over both. A run takes the whole file. |
328
331
  | `ANTHROPIC_VERTEX_PROJECT_ID` / `CLOUD_ML_REGION` / `GOOGLE_APPLICATION_CREDENTIALS` | Vertex AI's project, region and service-account key, read by the Claude program. Without the key file it uses gcloud's sign-in. |
329
332
  | `ANTHROPIC_FOUNDRY_RESOURCE` / `ANTHROPIC_FOUNDRY_API_KEY` | The Foundry resource and its key, read by the Claude program. Without the key it uses the machine's Azure sign-in. |
@@ -91,7 +91,7 @@ product doc.
91
91
  | **Job spec** (per matter): id, forwarder(+email/domain), markName/marks[], classes\|goods/use, ref, profileKey, projectKey, searchLevel/recipeKey, deliveryRoute, `customer`(+Unknown), deliverableSpec, commercialFlexibility, priorUse, dupOverride, deadline, brief | T1 | agent conversation → `start_run` MCP verb (ops token) → queue; validated by `enqueue-schema.mjs` | queue → run dir | LIVE (conversational; portal `run/plan`+`run` API exists) |
92
92
  | **Company profile** (17 keys — identity/rating/provenance: name, matchDomains, selfExclusionOwners, frameworkPath, workedExamplesPath, allowedRecipes, jxPolicy, runCaps, demoData (`true` marks the record as demo data; a real clearance is refused at the runner's admission wall); overlayable: platforms, defaultClasses, defaultJurisdictions, marketplaceDensity, delivery, riskAppetite, industry, defaultProduct) | T2 (staff) + T1 (a company's people edit its own via portal §C) | profile-service UI (staff, `/profiles/*`); the portal (own profile) | config store, git auto-commit | LIVE. Merge law: project **replaces** every overlayable key except `platforms`, which **unions** (the company's floor is never subtractable) |
93
93
  | **Project overlays** (8 overlayable keys) | T2 | profile-service UI | config store `profiles/projects/<cust>/` | LIVE. The project form deliberately withholds `defaultProduct` and both `delivery` sub-keys — for the first the sparse save path has no `""` ⇒ clear branch, so the control could only ever be turned on; for the second the engine replaces `delivery` wholesale, so a partial overlay would silently drop the company's other sub-keys. Both are company-level controls until the server side changes |
94
- | **Frameworks / skills** (risk-framework-<key>.md + .manifest.json, worked examples, SKILL.md) | T2 (senior-lawyer content) | git edits in the config store (deliberate — the prose deck is the rating authority) | config store `skills/prelim-search/` | LIVE via git; no UI by design |
94
+ | **Frameworks / skills** (risk-framework-<key>.md + .manifest.json, worked examples, SKILL.md) | T2 (senior-lawyer content) | git edits in the config store (deliberate — the prose deck is the rating authority) | config store `skills/clearance-search/` | LIVE via git; no UI by design |
95
95
  | **Recipes / saved searches** (base level + component toggles + emailTable/defaultDeadlineDays/standingInstructions) | T2 | recipe-service UI | `<recipesDir>/<cust>/<slug>.json`, git | **DARK** — code complete, no unit deployed. A saved search is honoured wherever it resolves (the `CLEAROTRON_RECIPES_MODE` door was retired 2026-07-27) |
96
96
  | **Run curation** (archive folds, republish, index regen) | T2 | `pool-admin.mjs` CLI only | pool `archive-tags.json` | LIVE, CLI-only |
97
97
  | **Allowlist** (`{version, grants:[{email, customer}]}`) | T2 | git + PR on the `CLIENT_ACCESS_MAP` file | see §2 row 4 | LIVE, file-only; surfaced read-only at `admin.access` |
@@ -527,6 +527,11 @@ up is a quiet success by design and the scheduled run underneath catches what it
527
527
  is wrong shows up as a slow job rather than a red one — which is why it is written down rather than left
528
528
  to be inferred from a timeout.
529
529
 
530
+ `CLEAROTRON_CUT_REQUESTED` and `CLEAROTRON_CUT_PR` — whether this run was dispatched to cut, and the
531
+ version pull request it opened. The workflow sets both; nothing on a deployment reads either. Together they
532
+ separate a run that set nothing in motion, whose expired wait stays a quiet success, from a dispatched cut
533
+ that published nothing, which fails and names why the pull request did not merge.
534
+
530
535
  ## 6. Drift patterns — values that are mirrored by design
531
536
 
532
537
  Wherever one value must exist in more than one place, name every copy and rotate them in one
@@ -16,7 +16,7 @@ rating is refused by pattern guards and by stage-level firewalls.
16
16
  ## The bundle
17
17
 
18
18
  A company = one git-owned JSON file `profiles/<key>.json`, plus optionally: a prose context pack
19
- (`<key>.context.md`), a per-company rating framework pair in `skills/prelim-search/`
19
+ (`<key>.context.md`), a per-company rating framework pair in `skills/clearance-search/`
20
20
  (`risk-framework-<key>.md` + its `.manifest.json`, plus worked examples), and per-engagement
21
21
  project overlays under `profiles/projects/<key>/`.
22
22
 
@@ -182,7 +182,7 @@ this source tree.
182
182
  `matchDomains` for forwarder-based fallback. A profile with empty `matchDomains` is reachable by
183
183
  profileKey only.
184
184
  - **Per-company framework** (optional; git-only, legal-team work — the UI cannot set it): add the
185
- deck + manifest + worked examples under `skills/prelim-search/`, set the two paths in the profile
185
+ deck + manifest + worked examples under `skills/clearance-search/`, set the two paths in the profile
186
186
  JSON via git. Until then the company rates under the Generic default.
187
187
  - **Per-engagement overlay** (optional): `profiles/projects/<key>/<slug>.json` with the 8
188
188
  overlayable keys; intake stamps `job.projectKey` to select it.
@@ -112,7 +112,7 @@ and the environment file holding the secrets.
112
112
  `XDG_RUNTIME_DIR` must be set for `systemctl --user` to work from cron.
113
113
  - **Pin the agent id before upgrading an install made before 0.2.2.** The default agent id changed
114
114
  from `clawdi` to `localagent`, and that id is a path segment: runs live under
115
- `<workspaceRoot>/workspace-<agent>/studio/prelim-search/`. An install that never set one starts
115
+ `<workspaceRoot>/workspace-<agent>/studio/clearance-search/`. An install that never set one starts
116
116
  reading an empty workspace, and empty reads as "no runs" rather than as an error. Set **both**
117
117
  variables in the environment file — the gather servers read their own:
118
118
 
@@ -129,7 +129,7 @@ and the environment file holding the secrets.
129
129
 
130
130
  | Surface | What it tells you |
131
131
  |---|---|
132
- | `systemctl --user status prelim-driver.{path,timer,service} prelim-outbox.{path,timer,service} profile-service` | Trigger health; remember "activating = draining" |
132
+ | `systemctl --user status prelim-driver.{path,timer,service} clearance-outbox.{path,timer,service} profile-service` | Trigger health; remember "activating = draining" |
133
133
  | `journalctl --user -u prelim-driver.service -f` | Runner notes (stderr): claims, dedup parks, preflight failures, orphan reclaims |
134
134
  | Run dir `status.json` / `run.jsonl` | Per-run state + the append-only decision trace; grep keys: `axes`, `profile`, `verdict`, `escalation`, `postponed`, `delivered`, `profile-mismatch` |
135
135
  | `_driver/<stage>.jsonl` | Per-attempt telemetry: status, fail token, kill signals, wall, tokens |
@@ -173,7 +173,7 @@ survive until terminal state.
173
173
  | Run parked with `*.tainted-N` artifacts | Timeout-taint convergence loop ([07 §3](07-quality-and-audit.md#3--completed-coverage-honesty-in-code)) | Let it converge; repeated signature goes terminal honestly |
174
174
  | Chat failure ping never arrived for a failed run | By design: nothing here sends. The failure packet IS the notice, and an integrator consumes it | Check `_driver/failure.json` + the outbox lane (the guaranteed notice) |
175
175
  | Deploy refused because a run is in flight | The in-flight guard above | Wait for the run. A force-restart of the gateway is not the answer — that is for a wedged gateway |
176
- | Everything quiet after a deploy abort | Should not happen (EXIT trap restarts triggers) — if it does: `systemctl --user start prelim-driver.{path,timer} prelim-outbox.{path,timer}` and file it |
176
+ | Everything quiet after a deploy abort | Should not happen (EXIT trap restarts triggers) — if it does: `systemctl --user start prelim-driver.{path,timer} clearance-outbox.{path,timer}` and file it |
177
177
 
178
178
  ## Selftest — retired
179
179
 
@@ -144,7 +144,7 @@ The reasoning layer dictates what it needs; a thin adapter supplies it. Concrete
144
144
  preflighted at run start. Add the id to `KNOWN_REGISTER_PROVIDERS` too, or the error message that
145
145
  tells an operator what to set will omit it. Selection is `CLEAROTRON_DATABASE` in every
146
146
  environment, production included; there is no committed default to flip.
147
- 4. **Skill doc**: `skills/prelim-register/providers/<provider>.md` — the provider-specific craft
147
+ 4. **Skill doc**: `skills/clearance-register/providers/<provider>.md` — the provider-specific craft
148
148
  the register stages read.
149
149
  5. **The empirical verification checklist** — the real work is not code volume: operator
150
150
  vocabulary and composition semantics, pagination behaviour to `has_more:false`, status-enum
@@ -157,8 +157,8 @@ The reasoning layer dictates what it needs; a thin adapter supplies it. Concrete
157
157
 
158
158
  The methodology lives in the driver's `skills/` tree — 12 top-level directories, nearly all of it
159
159
  Markdown carrying **prose only**, no executable code. The machine-parsed
160
- exceptions are the four framework manifests (`skills/prelim-search/risk-framework*.manifest.json`); one
161
- further non-Markdown file rides along, `skills/prelim-search/templates/search-request-form.html`, named
160
+ exceptions are the four framework manifests (`skills/clearance-search/risk-framework*.manifest.json`); one
161
+ further non-Markdown file rides along, `skills/clearance-search/templates/search-request-form.html`, named
162
162
  only in `publish/index.mjs`.
163
163
  The engine reads skills **in place from the git-deployed driver tree**: `absolutizeSkillRefs`
164
164
  rewrites `skills/…` tokens to absolute paths and grants `--add-dir`. Code comments saying skills
@@ -168,8 +168,8 @@ What to know before editing:
168
168
 
169
169
  - **Which stage reads what** is dictated solely by each stage message's `reads([...])` in
170
170
  `stages.mjs` — read it there rather than trusting this summary. Broadly: matter-frame,
171
- prelim-variants (+ `transliteration-scripts.md`), blind-frame, prelim-common-law (every grid seat),
172
- prelim-register spine + `unit.md` *xor* `digest.md` (mode-routed — a unit must never read
171
+ clearance-variants (+ `transliteration-scripts.md`), blind-frame, clearance-common-law (every grid seat),
172
+ clearance-register spine + `unit.md` *xor* `digest.md` (mode-routed — a unit must never read
173
173
  digest doctrine and vice versa) + the active provider's `providers/<name>.md`,
174
174
  placement-inquiry, `phase2-execution.md` §skeptic (that one section only), frame-diff,
175
175
  synthesis (synthesis-rules + per-profile framework + worked examples + conditionally
@@ -186,7 +186,7 @@ What to know before editing:
186
186
  - Several skill files are **legacy and not stage-read** (email/Excel templates, the formatting
187
187
  reference). Verify a file appears in some stage's `reads([...])` before treating its claims as
188
188
  live; where a legacy file and the code disagree, the code and `stages.mjs` win.
189
- - The pharma module (`skills/prelim-search/field-doctrine-pharma.md`, loaded by a code predicate on
189
+ - The pharma module (`skills/clearance-search/field-doctrine-pharma.md`, loaded by a code predicate on
190
190
  pharma-shaped matters) ships behind a named legal reviewer's sign-off — doctrine edits in
191
191
  regulated verticals go through the practitioner, not just review.
192
192
 
@@ -95,7 +95,7 @@ A framework is two files that travel together:
95
95
  | `risk-framework.manifest.json` | A small sidecar carrying the framework's **vocabulary**: band labels, their severity order, the entity label, provenance. |
96
96
 
97
97
  The Generic default ships at
98
- [`driver/skills/prelim-search/risk-framework.md`](../driver/skills/prelim-search/risk-framework.md)
98
+ [`driver/skills/clearance-search/risk-framework.md`](../driver/skills/clearance-search/risk-framework.md)
99
99
  with bands Very High · High · Moderate · Manageable.
100
100
 
101
101
  **Replace it with your own.** Write your rubric as prose, add a manifest naming your bands,
@@ -174,14 +174,14 @@ prints what they declare, and where the deck and the manifest disagree it names
174
174
  the deck did not do. It creates nothing, rates nothing and contacts nobody.
175
175
 
176
176
  ```
177
- clearotron framework skills/prelim-search/your-framework.md
177
+ clearotron framework skills/clearance-search/your-framework.md
178
178
  ```
179
179
 
180
180
  ```
181
- Framework: skills/prelim-search/your-framework.md
182
- deck /srv/clearotron-config/skills/prelim-search/your-framework.md
181
+ Framework: skills/clearance-search/your-framework.md
182
+ deck /srv/clearotron-config/skills/clearance-search/your-framework.md
183
183
  read from the configured store
184
- manifest /srv/clearotron-config/skills/prelim-search/your-framework.manifest.json
184
+ manifest /srv/clearotron-config/skills/clearance-search/your-framework.manifest.json
185
185
  read from the configured store
186
186
 
187
187
  It declares itself "Your firm's clearance risk framework" (your-firm-2026), a bands-shaped
@@ -32,7 +32,7 @@ disclosure are both acceptable; degrading in silence is not. Which one applies i
32
32
  | Register | refuses at preflight, by name | An unconfigured register that answered "no conflicts found" is the most dangerous output this system can produce |
33
33
  | Case law (Full country search) | runs without the bridge, and the run's ledger records that the sweep did not dispatch | Access is free but auth breaks in practice. `driver/verify.mjs` plus `case-law-citations.json` stop any report claiming "no adverse case law" when nothing was read — the disclosure is the guard |
34
34
  | Native-script lane | degrades and says so | Reached only on CJK territories |
35
- | Research sweep (open web / marketplaces) | **on a Knockout search: degrades and says so.** On the three clearance searches: **refuses at preflight, by name** | acceptance 6, 2026-08-20. A knockout carries`registerProbe: true`, so its register half is a whole product without the sweep — refusing the screen threw away an answer the deployment could give. The three clearances carry `commonLawGrid: true` and their unregistered-use half is not severable, so nothing there degrades quietly into a clearance with a missing half. -6, 2026-08-20: that clearance failure MOVED to preflight — it used to happen at the common-law stage, after every register stage had been paid for. Same outcome, no spend.`preflightResearchCredential` gates on the component, never on the pipeline: `prelim-register-only` is a clearance carrying `commonLawGrid: false` and is not refused |
35
+ | Research sweep (open web / marketplaces) | **on a Knockout search: degrades and says so.** On the three clearance searches: **refuses at preflight, by name** | acceptance 6, 2026-08-20. A knockout carries`registerProbe: true`, so its register half is a whole product without the sweep — refusing the screen threw away an answer the deployment could give. The three clearances carry `commonLawGrid: true` and their unregistered-use half is not severable, so nothing there degrades quietly into a clearance with a missing half. -6, 2026-08-20: that clearance failure MOVED to preflight — it used to happen at the common-law stage, after every register stage had been paid for. Same outcome, no spend.`preflightResearchCredential` gates on the component, never on the pipeline: `clearance-register-only` is a clearance carrying `commonLawGrid: false` and is not refused |
36
36
 
37
37
  ## Consequences
38
38
 
@@ -83,3 +83,7 @@ their problem.
83
83
  `enforcement.md` lists the classes a CI check refuses in a diff. Tone is not one of them, and no word
84
84
  list will ever catch it: a reviewer reads the rendered page as someone who has never seen this product,
85
85
  against `writing-rules.md`, and asks what they would think each sentence means.
86
+
87
+ A stylesheet that is inlined into a delivered document is delivered with it, comments included — the
88
+ reader receives the file, so a class name in a CSS comment is engineering vocabulary on a page they can
89
+ open, exactly as it would be in prose.