clearotron 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (622) hide show
  1. package/.env.example +54 -1
  2. package/CONTRIBUTING.md +3 -3
  3. package/INSTALL.md +53 -49
  4. package/bin/brandowner.mjs +1 -1
  5. package/bin/clearotron.mjs +4 -4
  6. package/bin/connect.mjs +2 -2
  7. package/bin/example.mjs +27 -11
  8. package/bin/grant.mjs +3 -3
  9. package/bin/key.mjs +1 -1
  10. package/bin/onboard.mjs +58 -118
  11. package/bin/start.mjs +22 -25
  12. package/bin/stop.mjs +65 -3
  13. package/bin/update.mjs +7 -7
  14. package/bin/uspto-sync.mjs +1 -1
  15. package/build-info.json +2 -2
  16. package/docs/DELIVERY.md +6 -2
  17. package/docs/architecture/01-product-overview.md +2 -2
  18. package/docs/architecture/02-architecture.md +2 -2
  19. package/docs/architecture/04-configuration-reference.md +6 -3
  20. package/docs/architecture/05-config-governance.md +38 -5
  21. package/docs/architecture/06-operations-runbook.md +13 -1
  22. package/docs/architecture/09-security-and-data.md +1 -1
  23. package/docs/decisions/0004-documentation-structure.md +1 -1
  24. package/driver/CHANGELOG.md +65 -1
  25. package/driver/README.md +2 -2
  26. package/driver/ask-ledger.mjs +3 -3
  27. package/driver/authority-trees.mjs +1 -1
  28. package/driver/call-capture.mjs +1 -1
  29. package/driver/card-frame.mjs +1 -1
  30. package/driver/case-law-ledger.mjs +1 -1
  31. package/driver/claim-liveness.mjs +1 -1
  32. package/driver/common-law-receipts.mjs +1 -1
  33. package/driver/commonlaw-carry.mjs +1 -1
  34. package/driver/config-inventory.mjs +1 -1
  35. package/driver/connotation-search.mjs +12 -12
  36. package/driver/contract-audit.mjs +5 -5
  37. package/driver/contract-dictation-registry.mjs +4 -4
  38. package/driver/contract-dictation.mjs +2 -2
  39. package/driver/contract-e3-backlog.mjs +6 -6
  40. package/driver/contract-vocabulary.mjs +3 -3
  41. package/driver/corrections-feedforward.mjs +1 -1
  42. package/driver/coverage-form-io.mjs +2 -2
  43. package/driver/coverage-form.mjs +4 -4
  44. package/driver/coverage-ledger.mjs +3 -3
  45. package/driver/coverage-union.mjs +1 -1
  46. package/driver/declination-call.mjs +35 -3
  47. package/driver/declination-duty.mjs +1 -1
  48. package/driver/deliver-trigger.sh +3 -3
  49. package/driver/deploy-live-run-guard.mjs +6 -2
  50. package/driver/dev-portal.mjs +1 -1
  51. package/driver/disposition-call.mjs +4 -4
  52. package/driver/disposition-tool.mjs +4 -4
  53. package/driver/disposition-union.mjs +2 -2
  54. package/driver/doc-constants.mjs +1 -1
  55. package/driver/door-gates.mjs +2 -2
  56. package/driver/doubt-selection.mjs +2 -2
  57. package/driver/drainer-identity.mjs +1 -1
  58. package/driver/driver.config.mjs +63 -11
  59. package/driver/e2e-rounds.mjs +2 -2
  60. package/driver/effort-model.mjs +2 -2
  61. package/driver/engine/anthropic-agent.mjs +24 -24
  62. package/driver/engine/auth.mjs +1 -1
  63. package/driver/engine/common.mjs +1 -1
  64. package/driver/engine/deny-authority-write.mjs +1 -1
  65. package/driver/engine/jx-turn.mjs +1 -1
  66. package/driver/engine/mcp/clarivate-server.mjs +1 -1
  67. package/driver/engine/mcp/corsearch-server.mjs +1 -1
  68. package/driver/engine/mcp/declination-server.mjs +1 -1
  69. package/driver/engine/mcp/dispositions-server.mjs +1 -1
  70. package/driver/engine/mcp/euipo-server.mjs +1 -1
  71. package/driver/engine/mcp/fetch-server.mjs +1 -1
  72. package/driver/engine/mcp/free-tier-server.mjs +2 -2
  73. package/driver/engine/mcp/gather-config.mjs +11 -11
  74. package/driver/engine/mcp/perplexity-server.mjs +1 -1
  75. package/driver/engine/mcp/recording-server.mjs +8 -4
  76. package/driver/engine/mcp/signa-server.mjs +1 -1
  77. package/driver/engine/mcp/uspto-local-server.mjs +1 -1
  78. package/driver/engine/openai-agent.mjs +2 -2
  79. package/driver/engine-build.mjs +2 -2
  80. package/driver/enqueue-schema.mjs +2 -2
  81. package/driver/enqueue.mjs +1 -1
  82. package/driver/envelope-settle.mjs +1 -1
  83. package/driver/evidence-claim-invariant.mjs +2 -2
  84. package/driver/findings-model.mjs +8 -8
  85. package/driver/floor-duty.mjs +1 -1
  86. package/driver/form-neighbourhood.mjs +1 -1
  87. package/driver/framework.mjs +1 -1
  88. package/driver/gateway.mjs +28 -23
  89. package/driver/grounds-grammar.mjs +1 -1
  90. package/driver/hit-list.mjs +1 -1
  91. package/driver/jurisdiction-systems.mjs +1 -1
  92. package/driver/jx-lanes.mjs +1 -1
  93. package/driver/jx-units.mjs +1 -1
  94. package/driver/jx.mjs +3 -3
  95. package/driver/knockout-assess-record.mjs +5 -1
  96. package/driver/narrative-refutation-record.mjs +3 -3
  97. package/driver/numeric-setting.mjs +1 -1
  98. package/driver/owner-use-check.mjs +184 -0
  99. package/driver/package.json +2 -2
  100. package/driver/phase0.mjs +1 -1
  101. package/driver/pipeline-knockout.mjs +52 -4
  102. package/driver/pipeline.mjs +175 -62
  103. package/driver/placement-diff.mjs +2 -2
  104. package/driver/placement-form.mjs +4 -4
  105. package/driver/placement-union.mjs +1 -1
  106. package/driver/portal-acks.mjs +1 -1
  107. package/driver/portal-config-view.mjs +2 -2
  108. package/driver/portal-local-auth.mjs +1 -1
  109. package/driver/portal-report.mjs +6 -6
  110. package/driver/portal-service.mjs +15 -15
  111. package/driver/predelivery-lint.mjs +28 -10
  112. package/driver/prelim-variants-record.mjs +2 -2
  113. package/driver/profile-page.html +1 -1
  114. package/driver/profile-selection.mjs +1 -1
  115. package/driver/profile-service.mjs +2 -2
  116. package/driver/profiles.mjs +1 -1
  117. package/driver/progress.mjs +6 -6
  118. package/driver/provider-usage.mjs +1 -1
  119. package/driver/publish/demo-marking.mjs +1 -1
  120. package/driver/publish/index.mjs +47 -6
  121. package/driver/publish/knockout.mjs +36 -14
  122. package/driver/publish/parse.mjs +4 -4
  123. package/driver/publish/publish-inputs.mjs +2 -2
  124. package/driver/publish/register-presence.mjs +1 -1
  125. package/driver/publish/render-knockout.mjs +198 -31
  126. package/driver/publish/report-data.mjs +13 -3
  127. package/driver/queue-watch-probe.mjs +1 -1
  128. package/driver/queue-watch-verdict.mjs +1 -1
  129. package/driver/recall-reconciliation.mjs +1 -1
  130. package/driver/recipe-service.mjs +1 -1
  131. package/driver/record-carry.mjs +5 -5
  132. package/driver/recording-agreement.mjs +3 -3
  133. package/driver/reference-score.mjs +7 -7
  134. package/driver/refusal-bound.mjs +3 -3
  135. package/driver/register-availability.mjs +2 -2
  136. package/driver/register-count.mjs +1 -1
  137. package/driver/register-grant-vocabulary.mjs +2 -2
  138. package/driver/register-plan.mjs +8 -8
  139. package/driver/register-records.mjs +2 -2
  140. package/driver/registry-fidelity.mjs +3 -3
  141. package/driver/remedy-accounting.mjs +1 -1
  142. package/driver/repair-composers.mjs +2 -2
  143. package/driver/repair-digest.mjs +3 -3
  144. package/driver/repairs.mjs +6 -6
  145. package/driver/replay-archive.mjs +2 -0
  146. package/driver/report-card-record.mjs +2 -2
  147. package/driver/result-noun-fields.mjs +10 -3
  148. package/driver/run-economics.mjs +2 -2
  149. package/driver/run-integrity.mjs +1 -1
  150. package/driver/runner.mjs +22 -22
  151. package/driver/scope-rules.mjs +1 -1
  152. package/driver/search-policy.mjs +3 -3
  153. package/driver/skeptic-search.mjs +1 -1
  154. package/driver/skills/blind-frame/SKILL.md +1 -1
  155. package/driver/skills/case-law-citation/SKILL.md +2 -2
  156. package/driver/skills/knockout-assess/SKILL.md +10 -4
  157. package/driver/skills/prelim-search/SKILL.md +2 -2
  158. package/driver/skills/prelim-search/template-formatting.md +1 -1
  159. package/driver/skills/prelim-search/templates/email/generic.md +1 -1
  160. package/driver/skills/prelim-search/worked-examples.md +1 -1
  161. package/driver/skills/prelim-variants/SKILL.md +2 -2
  162. package/driver/stage-context.mjs +1 -1
  163. package/driver/stages-knockout.mjs +55 -4
  164. package/driver/stages.mjs +97 -40
  165. package/driver/stray-artifacts.mjs +2 -2
  166. package/driver/suite-census.json +146 -32
  167. package/driver/synthesis-record.mjs +1 -1
  168. package/driver/systemd/clearotron-client-mcp.service +1 -1
  169. package/driver/systemd/clearotron-portal.service +1 -1
  170. package/driver/systemd/render-units.mjs +1 -1
  171. package/driver/tokens.mjs +1 -1
  172. package/driver/tool-calls.mjs +1 -1
  173. package/driver/turnaround-bands.mjs +1 -1
  174. package/driver/unit-file-drift.mjs +1 -1
  175. package/driver/unit-inventory.mjs +121 -61
  176. package/driver/unit-state-verdict.mjs +20 -12
  177. package/driver/verify-knockout.mjs +10 -2
  178. package/driver/verify.mjs +12 -12
  179. package/driver/whatif-memo-run.mjs +46 -5
  180. package/driver/whatif-queue.mjs +1 -1
  181. package/driver/whatif-worker.mjs +1 -1
  182. package/mcp-server/CHANGELOG.md +4 -0
  183. package/mcp-server/README.md +3 -3
  184. package/mcp-server/http-server.mjs +44 -1
  185. package/mcp-server/key-socket.mjs +184 -0
  186. package/mcp-server/lib/audit-view.mjs +69 -2
  187. package/mcp-server/lib/brief.mjs +15 -0
  188. package/mcp-server/lib/driver.mjs +7 -1
  189. package/mcp-server/lib/events.mjs +1 -1
  190. package/mcp-server/lib/http-handler.mjs +1 -1
  191. package/mcp-server/lib/knockout.mjs +435 -0
  192. package/mcp-server/lib/ops.mjs +4 -4
  193. package/mcp-server/lib/options.mjs +1 -1
  194. package/mcp-server/lib/plan.mjs +1 -1
  195. package/mcp-server/lib/runs.mjs +1 -1
  196. package/mcp-server/lib/scrub.mjs +1 -1
  197. package/mcp-server/lib/whatif.mjs +3 -3
  198. package/mcp-server/mint-token.mjs +1 -1
  199. package/mcp-server/package.json +2 -2
  200. package/mcp-server/server.mjs +76 -11
  201. package/package.json +3 -3
  202. package/portal-ui/package.json +1 -1
  203. package/providers/_shared/enumerate.mjs +1 -1
  204. package/providers/_shared/ledger-path.mjs +3 -3
  205. package/providers/_shared/ledger.mjs +1 -1
  206. package/providers/_shared/result-shape.mjs +3 -3
  207. package/providers/_shared/term-shape.mjs +1 -1
  208. package/providers/corsearch/src/core.js +1 -1
  209. package/providers/jx-subclass/BUILDING.md +1 -1
  210. package/providers/oauth-mcp-bridge/CHANGELOG.md +4 -0
  211. package/providers/oauth-mcp-bridge/package.json +1 -1
  212. package/providers/oauth-mcp-bridge/stdin-guard.mjs +2 -2
  213. package/scripts/README.md +1 -1
  214. package/scripts/added-reference-check.mjs +29 -1
  215. package/scripts/ai-page-render-check.mjs +1 -1
  216. package/scripts/authority-boundary-probe.mjs +1 -1
  217. package/scripts/backfill-started-at.mjs +1 -1
  218. package/scripts/citation-line-check.mjs +3 -3
  219. package/scripts/clearances-render-check.mjs +3 -3
  220. package/scripts/compare.mjs +2 -2
  221. package/scripts/composer-render-check.mjs +6 -6
  222. package/scripts/contract-dictation-scan.mjs +2 -2
  223. package/scripts/dead-names.mjs +1 -1
  224. package/scripts/drain-preflight.mjs +5 -5
  225. package/scripts/e2e-unread-terminals.mjs +1 -1
  226. package/scripts/e2e.mjs +8 -8
  227. package/scripts/env-audit.mjs +7 -7
  228. package/scripts/env-classify.mjs +139 -15
  229. package/scripts/freeze-example-run.mjs +3 -3
  230. package/scripts/head-arrived-gated.mjs +1 -1
  231. package/scripts/headless-page.mjs +51 -2
  232. package/scripts/home-render-check.mjs +2 -2
  233. package/scripts/live-surface-check.mjs +92 -19
  234. package/scripts/main-health.mjs +1 -1
  235. package/scripts/merge-presence-check.mjs +3 -3
  236. package/scripts/mint-suite-census.mjs +6 -6
  237. package/scripts/nightly-notice.mjs +1 -1
  238. package/scripts/portal-lifecycle-check.mjs +3 -3
  239. package/scripts/reconcile-runs.mjs +1 -1
  240. package/scripts/release-await-cut.mjs +6 -4
  241. package/scripts/release-version-pr-checks.mjs +1 -1
  242. package/scripts/release-version.mjs +2 -2
  243. package/scripts/render-check.mjs +66 -7
  244. package/scripts/report-frame-check.mjs +1 -1
  245. package/scripts/report-screenshot.mjs +1 -1
  246. package/scripts/revisit-render-check.mjs +1 -1
  247. package/scripts/score.mjs +4 -4
  248. package/scripts/strip-tracker-citations.mjs +116 -0
  249. package/scripts/test-run.mjs +3 -3
  250. package/scripts/third-party-notices.mjs +3 -3
  251. package/scripts/travelling-predicates.mjs +3 -3
  252. package/scripts/unexecuted-asserts.mjs +2 -2
  253. package/scripts/verify-publishable.mjs +2 -2
  254. package/scripts/write-up-form-census.mjs +1 -1
  255. package/shared/access-audience.mjs +1 -1
  256. package/shared/brand.mjs +13 -13
  257. package/shared/citation-scan.mjs +1 -1
  258. package/shared/client-door.mjs +7 -7
  259. package/shared/driver-dir.mjs +1 -1
  260. package/shared/env-aliases.mjs +0 -48
  261. package/shared/env-local.mjs +1 -1
  262. package/shared/identifier-scan.mjs +3 -3
  263. package/shared/invocation.mjs +1 -1
  264. package/shared/names-in-force.mjs +2 -0
  265. package/shared/product-owned-names.mjs +1 -1
  266. package/shared/register-selection.mjs +1 -1
  267. package/shared/scope.mjs +5 -5
  268. package/shared/server-units.mjs +4 -4
  269. package/shared/store-in-repo.mjs +2 -2
  270. package/shared/suite-census.mjs +4 -4
  271. package/shared/tty-style.mjs +1 -1
  272. package/shared/uspto-index-size.mjs +1 -1
  273. package/shared/vacuous-pass.mjs +1 -1
  274. package/skills/clearotron-account/SKILL.md +42 -13
  275. package/driver/systemd/prelim-driver.path +0 -69
  276. package/driver/systemd/prelim-driver.service +0 -86
  277. package/driver/systemd/prelim-driver.timer +0 -14
  278. package/driver/systemd/prelim-outbox.path +0 -27
  279. package/driver/systemd/prelim-outbox.service +0 -37
  280. package/driver/systemd/prelim-outbox.timer +0 -21
  281. package/node_modules/exceljs/README_zh.md +0 -2878
  282. package/node_modules/exceljs/dist/LICENSE +0 -22
  283. package/node_modules/exceljs/dist/es5/csv/csv.js +0 -182
  284. package/node_modules/exceljs/dist/es5/csv/csv.js.map +0 -1
  285. package/node_modules/exceljs/dist/es5/csv/line-buffer.js +0 -68
  286. package/node_modules/exceljs/dist/es5/csv/line-buffer.js.map +0 -1
  287. package/node_modules/exceljs/dist/es5/csv/stream-converter.js +0 -110
  288. package/node_modules/exceljs/dist/es5/csv/stream-converter.js.map +0 -1
  289. package/node_modules/exceljs/dist/es5/doc/anchor.js +0 -73
  290. package/node_modules/exceljs/dist/es5/doc/anchor.js.map +0 -1
  291. package/node_modules/exceljs/dist/es5/doc/cell.js +0 -961
  292. package/node_modules/exceljs/dist/es5/doc/cell.js.map +0 -1
  293. package/node_modules/exceljs/dist/es5/doc/column.js +0 -274
  294. package/node_modules/exceljs/dist/es5/doc/column.js.map +0 -1
  295. package/node_modules/exceljs/dist/es5/doc/data-validations.js +0 -18
  296. package/node_modules/exceljs/dist/es5/doc/data-validations.js.map +0 -1
  297. package/node_modules/exceljs/dist/es5/doc/defined-names.js +0 -173
  298. package/node_modules/exceljs/dist/es5/doc/defined-names.js.map +0 -1
  299. package/node_modules/exceljs/dist/es5/doc/enums.js +0 -49
  300. package/node_modules/exceljs/dist/es5/doc/enums.js.map +0 -1
  301. package/node_modules/exceljs/dist/es5/doc/image.js +0 -69
  302. package/node_modules/exceljs/dist/es5/doc/image.js.map +0 -1
  303. package/node_modules/exceljs/dist/es5/doc/modelcontainer.js +0 -16
  304. package/node_modules/exceljs/dist/es5/doc/modelcontainer.js.map +0 -1
  305. package/node_modules/exceljs/dist/es5/doc/note.js +0 -64
  306. package/node_modules/exceljs/dist/es5/doc/note.js.map +0 -1
  307. package/node_modules/exceljs/dist/es5/doc/range.js +0 -229
  308. package/node_modules/exceljs/dist/es5/doc/range.js.map +0 -1
  309. package/node_modules/exceljs/dist/es5/doc/row.js +0 -382
  310. package/node_modules/exceljs/dist/es5/doc/row.js.map +0 -1
  311. package/node_modules/exceljs/dist/es5/doc/table.js +0 -443
  312. package/node_modules/exceljs/dist/es5/doc/table.js.map +0 -1
  313. package/node_modules/exceljs/dist/es5/doc/workbook.js +0 -202
  314. package/node_modules/exceljs/dist/es5/doc/workbook.js.map +0 -1
  315. package/node_modules/exceljs/dist/es5/doc/worksheet.js +0 -900
  316. package/node_modules/exceljs/dist/es5/doc/worksheet.js.map +0 -1
  317. package/node_modules/exceljs/dist/es5/exceljs.bare.js +0 -14
  318. package/node_modules/exceljs/dist/es5/exceljs.bare.js.map +0 -1
  319. package/node_modules/exceljs/dist/es5/exceljs.browser.js +0 -36
  320. package/node_modules/exceljs/dist/es5/exceljs.browser.js.map +0 -1
  321. package/node_modules/exceljs/dist/es5/exceljs.nodejs.js +0 -15
  322. package/node_modules/exceljs/dist/es5/exceljs.nodejs.js.map +0 -1
  323. package/node_modules/exceljs/dist/es5/index.js +0 -15
  324. package/node_modules/exceljs/dist/es5/stream/xlsx/hyperlink-reader.js +0 -90
  325. package/node_modules/exceljs/dist/es5/stream/xlsx/hyperlink-reader.js.map +0 -1
  326. package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-comments-writer.js +0 -94
  327. package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-comments-writer.js.map +0 -1
  328. package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-rels-writer.js +0 -94
  329. package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-rels-writer.js.map +0 -1
  330. package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-reader.js +0 -362
  331. package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-reader.js.map +0 -1
  332. package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-writer.js +0 -347
  333. package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-writer.js.map +0 -1
  334. package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-reader.js +0 -392
  335. package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-reader.js.map +0 -1
  336. package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-writer.js +0 -652
  337. package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-writer.js.map +0 -1
  338. package/node_modules/exceljs/dist/es5/utils/auto-drain.js +0 -18
  339. package/node_modules/exceljs/dist/es5/utils/auto-drain.js.map +0 -1
  340. package/node_modules/exceljs/dist/es5/utils/browser-buffer-decode.js +0 -15
  341. package/node_modules/exceljs/dist/es5/utils/browser-buffer-decode.js.map +0 -1
  342. package/node_modules/exceljs/dist/es5/utils/browser-buffer-encode.js +0 -18
  343. package/node_modules/exceljs/dist/es5/utils/browser-buffer-encode.js.map +0 -1
  344. package/node_modules/exceljs/dist/es5/utils/cell-matrix.js +0 -149
  345. package/node_modules/exceljs/dist/es5/utils/cell-matrix.js.map +0 -1
  346. package/node_modules/exceljs/dist/es5/utils/col-cache.js +0 -258
  347. package/node_modules/exceljs/dist/es5/utils/col-cache.js.map +0 -1
  348. package/node_modules/exceljs/dist/es5/utils/copy-style.js +0 -43
  349. package/node_modules/exceljs/dist/es5/utils/copy-style.js.map +0 -1
  350. package/node_modules/exceljs/dist/es5/utils/encryptor.js +0 -58
  351. package/node_modules/exceljs/dist/es5/utils/encryptor.js.map +0 -1
  352. package/node_modules/exceljs/dist/es5/utils/iterate-stream.js +0 -46
  353. package/node_modules/exceljs/dist/es5/utils/iterate-stream.js.map +0 -1
  354. package/node_modules/exceljs/dist/es5/utils/parse-sax.js +0 -47
  355. package/node_modules/exceljs/dist/es5/utils/parse-sax.js.map +0 -1
  356. package/node_modules/exceljs/dist/es5/utils/shared-formula.js +0 -42
  357. package/node_modules/exceljs/dist/es5/utils/shared-formula.js.map +0 -1
  358. package/node_modules/exceljs/dist/es5/utils/shared-strings.js +0 -32
  359. package/node_modules/exceljs/dist/es5/utils/shared-strings.js.map +0 -1
  360. package/node_modules/exceljs/dist/es5/utils/stream-base64.js +0 -66
  361. package/node_modules/exceljs/dist/es5/utils/stream-base64.js.map +0 -1
  362. package/node_modules/exceljs/dist/es5/utils/stream-buf.js +0 -343
  363. package/node_modules/exceljs/dist/es5/utils/stream-buf.js.map +0 -1
  364. package/node_modules/exceljs/dist/es5/utils/string-buf.js +0 -73
  365. package/node_modules/exceljs/dist/es5/utils/string-buf.js.map +0 -1
  366. package/node_modules/exceljs/dist/es5/utils/string-builder.js +0 -32
  367. package/node_modules/exceljs/dist/es5/utils/string-builder.js.map +0 -1
  368. package/node_modules/exceljs/dist/es5/utils/stuttered-pipe.js +0 -61
  369. package/node_modules/exceljs/dist/es5/utils/stuttered-pipe.js.map +0 -1
  370. package/node_modules/exceljs/dist/es5/utils/typed-stack.js +0 -23
  371. package/node_modules/exceljs/dist/es5/utils/typed-stack.js.map +0 -1
  372. package/node_modules/exceljs/dist/es5/utils/under-dash.js +0 -168
  373. package/node_modules/exceljs/dist/es5/utils/under-dash.js.map +0 -1
  374. package/node_modules/exceljs/dist/es5/utils/utils.js +0 -171
  375. package/node_modules/exceljs/dist/es5/utils/utils.js.map +0 -1
  376. package/node_modules/exceljs/dist/es5/utils/xml-stream.js +0 -151
  377. package/node_modules/exceljs/dist/es5/utils/xml-stream.js.map +0 -1
  378. package/node_modules/exceljs/dist/es5/utils/zip-stream.js +0 -79
  379. package/node_modules/exceljs/dist/es5/utils/zip-stream.js.map +0 -1
  380. package/node_modules/exceljs/dist/es5/xlsx/defaultnumformats.js +0 -230
  381. package/node_modules/exceljs/dist/es5/xlsx/defaultnumformats.js.map +0 -1
  382. package/node_modules/exceljs/dist/es5/xlsx/rel-type.js +0 -18
  383. package/node_modules/exceljs/dist/es5/xlsx/rel-type.js.map +0 -1
  384. package/node_modules/exceljs/dist/es5/xlsx/xform/base-xform.js +0 -139
  385. package/node_modules/exceljs/dist/es5/xlsx/xform/base-xform.js.map +0 -1
  386. package/node_modules/exceljs/dist/es5/xlsx/xform/book/defined-name-xform.js +0 -85
  387. package/node_modules/exceljs/dist/es5/xlsx/xform/book/defined-name-xform.js.map +0 -1
  388. package/node_modules/exceljs/dist/es5/xlsx/xform/book/sheet-xform.js +0 -32
  389. package/node_modules/exceljs/dist/es5/xlsx/xform/book/sheet-xform.js.map +0 -1
  390. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-calc-properties-xform.js +0 -24
  391. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-calc-properties-xform.js.map +0 -1
  392. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-properties-xform.js +0 -27
  393. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-properties-xform.js.map +0 -1
  394. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-view-xform.js +0 -51
  395. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-view-xform.js.map +0 -1
  396. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-xform.js +0 -234
  397. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-xform.js.map +0 -1
  398. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comment-xform.js +0 -103
  399. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comment-xform.js.map +0 -1
  400. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comments-xform.js +0 -76
  401. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comments-xform.js.map +0 -1
  402. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-position-xform.js +0 -35
  403. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-position-xform.js.map +0 -1
  404. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-protection-xform.js +0 -32
  405. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-protection-xform.js.map +0 -1
  406. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-anchor-xform.js +0 -53
  407. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-anchor-xform.js.map +0 -1
  408. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-client-data-xform.js +0 -97
  409. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-client-data-xform.js.map +0 -1
  410. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-notes-xform.js +0 -107
  411. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-notes-xform.js.map +0 -1
  412. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-shape-xform.js +0 -92
  413. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-shape-xform.js.map +0 -1
  414. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-textbox-xform.js +0 -61
  415. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-textbox-xform.js.map +0 -1
  416. package/node_modules/exceljs/dist/es5/xlsx/xform/composite-xform.js +0 -51
  417. package/node_modules/exceljs/dist/es5/xlsx/xform/composite-xform.js.map +0 -1
  418. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-heading-pairs-xform.js +0 -30
  419. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-heading-pairs-xform.js.map +0 -1
  420. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-titles-of-parts-xform.js +0 -27
  421. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-titles-of-parts-xform.js.map +0 -1
  422. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-xform.js +0 -93
  423. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-xform.js.map +0 -1
  424. package/node_modules/exceljs/dist/es5/xlsx/xform/core/content-types-xform.js +0 -112
  425. package/node_modules/exceljs/dist/es5/xlsx/xform/core/content-types-xform.js.map +0 -1
  426. package/node_modules/exceljs/dist/es5/xlsx/xform/core/core-xform.js +0 -158
  427. package/node_modules/exceljs/dist/es5/xlsx/xform/core/core-xform.js.map +0 -1
  428. package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationship-xform.js +0 -23
  429. package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationship-xform.js.map +0 -1
  430. package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationships-xform.js +0 -65
  431. package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationships-xform.js.map +0 -1
  432. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/base-cell-anchor-xform.js +0 -47
  433. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/base-cell-anchor-xform.js.map +0 -1
  434. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-fill-xform.js +0 -61
  435. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-fill-xform.js.map +0 -1
  436. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-xform.js +0 -40
  437. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-xform.js.map +0 -1
  438. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pic-pr-xform.js +0 -35
  439. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pic-pr-xform.js.map +0 -1
  440. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pr-xform.js +0 -62
  441. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pr-xform.js.map +0 -1
  442. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/cell-position-xform.js +0 -82
  443. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/cell-position-xform.js.map +0 -1
  444. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/drawing-xform.js +0 -98
  445. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/drawing-xform.js.map +0 -1
  446. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-lst-xform.js +0 -40
  447. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-lst-xform.js.map +0 -1
  448. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-xform.js +0 -38
  449. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-xform.js.map +0 -1
  450. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/hlink-click-xform.js +0 -38
  451. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/hlink-click-xform.js.map +0 -1
  452. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/nv-pic-pr-xform.js +0 -59
  453. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/nv-pic-pr-xform.js.map +0 -1
  454. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/one-cell-anchor-xform.js +0 -63
  455. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/one-cell-anchor-xform.js.map +0 -1
  456. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/pic-xform.js +0 -67
  457. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/pic-xform.js.map +0 -1
  458. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/sp-pr.js +0 -30
  459. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/sp-pr.js.map +0 -1
  460. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/two-cell-anchor-xform.js +0 -62
  461. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/two-cell-anchor-xform.js.map +0 -1
  462. package/node_modules/exceljs/dist/es5/xlsx/xform/list-xform.js +0 -91
  463. package/node_modules/exceljs/dist/es5/xlsx/xform/list-xform.js.map +0 -1
  464. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/auto-filter-xform.js +0 -40
  465. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/auto-filter-xform.js.map +0 -1
  466. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cell-xform.js +0 -451
  467. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cell-xform.js.map +0 -1
  468. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cf-rule-xform.js +0 -275
  469. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cf-rule-xform.js.map +0 -1
  470. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cfvo-xform.js +0 -25
  471. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cfvo-xform.js.map +0 -1
  472. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/color-scale-xform.js +0 -38
  473. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/color-scale-xform.js.map +0 -1
  474. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formatting-xform.js +0 -45
  475. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formatting-xform.js.map +0 -1
  476. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formattings-xform.js +0 -77
  477. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formattings-xform.js.map +0 -1
  478. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/databar-xform.js +0 -42
  479. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/databar-xform.js.map +0 -1
  480. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/ext-lst-ref-xform.js +0 -71
  481. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/ext-lst-ref-xform.js.map +0 -1
  482. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/formula-xform.js +0 -22
  483. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/formula-xform.js.map +0 -1
  484. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/icon-set-xform.js +0 -43
  485. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/icon-set-xform.js.map +0 -1
  486. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js +0 -28
  487. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js.map +0 -1
  488. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +0 -88
  489. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js.map +0 -1
  490. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js +0 -38
  491. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js.map +0 -1
  492. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js +0 -52
  493. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js.map +0 -1
  494. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js +0 -43
  495. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js.map +0 -1
  496. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/databar-ext-xform.js +0 -75
  497. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/databar-ext-xform.js.map +0 -1
  498. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/f-ext-xform.js +0 -22
  499. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/f-ext-xform.js.map +0 -1
  500. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js +0 -66
  501. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js.map +0 -1
  502. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js +0 -22
  503. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js.map +0 -1
  504. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/col-xform.js +0 -78
  505. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/col-xform.js.map +0 -1
  506. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/data-validations-xform.js +0 -247
  507. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/data-validations-xform.js.map +0 -1
  508. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/dimension-xform.js +0 -28
  509. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/dimension-xform.js.map +0 -1
  510. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/drawing-xform.js +0 -32
  511. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/drawing-xform.js.map +0 -1
  512. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/ext-lst-xform.js +0 -69
  513. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/ext-lst-xform.js.map +0 -1
  514. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/header-footer-xform.js +0 -126
  515. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/header-footer-xform.js.map +0 -1
  516. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/hyperlink-xform.js +0 -50
  517. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/hyperlink-xform.js.map +0 -1
  518. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merge-cell-xform.js +0 -26
  519. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merge-cell-xform.js.map +0 -1
  520. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merges.js +0 -52
  521. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merges.js.map +0 -1
  522. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/outline-properties-xform.js +0 -35
  523. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/outline-properties-xform.js.map +0 -1
  524. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-breaks-xform.js +0 -24
  525. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-breaks-xform.js.map +0 -1
  526. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-margins-xform.js +0 -46
  527. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-margins-xform.js.map +0 -1
  528. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-properties-xform.js +0 -32
  529. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-properties-xform.js.map +0 -1
  530. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-xform.js +0 -99
  531. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-xform.js.map +0 -1
  532. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/picture-xform.js +0 -32
  533. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/picture-xform.js.map +0 -1
  534. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/print-options-xform.js +0 -45
  535. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/print-options-xform.js.map +0 -1
  536. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-breaks-xform.js +0 -37
  537. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-breaks-xform.js.map +0 -1
  538. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-xform.js +0 -128
  539. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-xform.js.map +0 -1
  540. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-format-properties-xform.js +0 -51
  541. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-format-properties-xform.js.map +0 -1
  542. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-properties-xform.js +0 -83
  543. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-properties-xform.js.map +0 -1
  544. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-protection-xform.js +0 -84
  545. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-protection-xform.js.map +0 -1
  546. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-view-xform.js +0 -190
  547. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-view-xform.js.map +0 -1
  548. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/table-part-xform.js +0 -32
  549. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/table-part-xform.js.map +0 -1
  550. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/worksheet-xform.js +0 -513
  551. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/worksheet-xform.js.map +0 -1
  552. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/boolean-xform.js +0 -27
  553. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/boolean-xform.js.map +0 -1
  554. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/date-xform.js +0 -58
  555. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/date-xform.js.map +0 -1
  556. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/float-xform.js +0 -47
  557. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/float-xform.js.map +0 -1
  558. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/integer-xform.js +0 -53
  559. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/integer-xform.js.map +0 -1
  560. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/string-xform.js +0 -47
  561. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/string-xform.js.map +0 -1
  562. package/node_modules/exceljs/dist/es5/xlsx/xform/static-xform.js +0 -61
  563. package/node_modules/exceljs/dist/es5/xlsx/xform/static-xform.js.map +0 -1
  564. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/phonetic-text-xform.js +0 -98
  565. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/phonetic-text-xform.js.map +0 -1
  566. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/rich-text-xform.js +0 -92
  567. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/rich-text-xform.js.map +0 -1
  568. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-string-xform.js +0 -99
  569. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-string-xform.js.map +0 -1
  570. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-strings-xform.js +0 -114
  571. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-strings-xform.js.map +0 -1
  572. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/text-xform.js +0 -39
  573. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/text-xform.js.map +0 -1
  574. package/node_modules/exceljs/dist/es5/xlsx/xform/style/alignment-xform.js +0 -139
  575. package/node_modules/exceljs/dist/es5/xlsx/xform/style/alignment-xform.js.map +0 -1
  576. package/node_modules/exceljs/dist/es5/xlsx/xform/style/border-xform.js +0 -185
  577. package/node_modules/exceljs/dist/es5/xlsx/xform/style/border-xform.js.map +0 -1
  578. package/node_modules/exceljs/dist/es5/xlsx/xform/style/color-xform.js +0 -66
  579. package/node_modules/exceljs/dist/es5/xlsx/xform/style/color-xform.js.map +0 -1
  580. package/node_modules/exceljs/dist/es5/xlsx/xform/style/dxf-xform.js +0 -106
  581. package/node_modules/exceljs/dist/es5/xlsx/xform/style/dxf-xform.js.map +0 -1
  582. package/node_modules/exceljs/dist/es5/xlsx/xform/style/fill-xform.js +0 -308
  583. package/node_modules/exceljs/dist/es5/xlsx/xform/style/fill-xform.js.map +0 -1
  584. package/node_modules/exceljs/dist/es5/xlsx/xform/style/font-xform.js +0 -175
  585. package/node_modules/exceljs/dist/es5/xlsx/xform/style/font-xform.js.map +0 -1
  586. package/node_modules/exceljs/dist/es5/xlsx/xform/style/numfmt-xform.js +0 -59
  587. package/node_modules/exceljs/dist/es5/xlsx/xform/style/numfmt-xform.js.map +0 -1
  588. package/node_modules/exceljs/dist/es5/xlsx/xform/style/protection-xform.js +0 -53
  589. package/node_modules/exceljs/dist/es5/xlsx/xform/style/protection-xform.js.map +0 -1
  590. package/node_modules/exceljs/dist/es5/xlsx/xform/style/style-xform.js +0 -118
  591. package/node_modules/exceljs/dist/es5/xlsx/xform/style/style-xform.js.map +0 -1
  592. package/node_modules/exceljs/dist/es5/xlsx/xform/style/styles-xform.js +0 -612
  593. package/node_modules/exceljs/dist/es5/xlsx/xform/style/styles-xform.js.map +0 -1
  594. package/node_modules/exceljs/dist/es5/xlsx/xform/style/underline-xform.js +0 -46
  595. package/node_modules/exceljs/dist/es5/xlsx/xform/style/underline-xform.js.map +0 -1
  596. package/node_modules/exceljs/dist/es5/xlsx/xform/table/auto-filter-xform.js +0 -75
  597. package/node_modules/exceljs/dist/es5/xlsx/xform/table/auto-filter-xform.js.map +0 -1
  598. package/node_modules/exceljs/dist/es5/xlsx/xform/table/custom-filter-xform.js +0 -30
  599. package/node_modules/exceljs/dist/es5/xlsx/xform/table/custom-filter-xform.js.map +0 -1
  600. package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-column-xform.js +0 -89
  601. package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-column-xform.js.map +0 -1
  602. package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-xform.js +0 -28
  603. package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-xform.js.map +0 -1
  604. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-column-xform.js +0 -42
  605. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-column-xform.js.map +0 -1
  606. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-style-info-xform.js +0 -40
  607. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-style-info-xform.js.map +0 -1
  608. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-xform.js +0 -123
  609. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-xform.js.map +0 -1
  610. package/node_modules/exceljs/dist/es5/xlsx/xlsx.js +0 -697
  611. package/node_modules/exceljs/dist/es5/xlsx/xlsx.js.map +0 -1
  612. package/node_modules/exceljs/dist/es5/xlsx/xml/theme1.js +0 -5
  613. package/node_modules/exceljs/dist/es5/xlsx/xml/theme1.js.map +0 -1
  614. package/node_modules/exceljs/dist/exceljs.bare.js +0 -55253
  615. package/node_modules/exceljs/dist/exceljs.bare.js.map +0 -761
  616. package/node_modules/exceljs/dist/exceljs.bare.min.js +0 -45
  617. package/node_modules/exceljs/dist/exceljs.bare.min.js.map +0 -1
  618. package/node_modules/exceljs/dist/exceljs.js +0 -59900
  619. package/node_modules/exceljs/dist/exceljs.js.map +0 -1083
  620. package/node_modules/exceljs/dist/exceljs.min.js +0 -45
  621. package/node_modules/exceljs/dist/exceljs.min.js.map +0 -1
  622. package/scripts/deploy-test.sh +0 -309
@@ -1,10 +1,10 @@
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
- // placement-diff.mjs —: compare two runs' placement tiers, so 's repeat runs can be scored.
3
+ // placement-diff.mjs —: compare two runs' placement tiers, so the repeat runs can be scored.
4
4
  //
5
5
  // ── why this exists ──────────────────────────────────────────────────────────────────────────────────
6
6
  //
7
- // 's offline half is answered: the band-shape seam moves its input, so the branch is taken and the
7
+ // That offline half is answered: the band-shape seam moves its input, so the branch is taken and the
8
8
  // noise floor needs repeat PAID arms on one matter. Those runs are the E2E agent's. When they land there
9
9
  // is nothing to compare them with — `placement-carry.mjs` joins placements to the digest surfaces WITHIN
10
10
  // one run, and nothing in the tree diffs two `placements.json`.
@@ -13,12 +13,12 @@
13
13
  // fails `placementmodel_missing` while the structured sibling `placements.json` is absent — and the seat
14
14
  // wrote the prose first (on disk that run: md at 09:08:58, json at 09:15:50, by attempt 2). The kill
15
15
  // landed in the gap between the two files, so 31 minutes of finished work were discarded and re-derived
16
- // from scratch. Raising the wall (, `638f885`) made that less likely; it did not make finished work
16
+ // from scratch. Raising the wall (`638f885`) made that less likely; it did not make finished work
17
17
  // survivable, and this does.
18
18
  //
19
19
  // THE CURE IS AUTHORSHIP, NOT A GUARD. The seat stops writing `placements.json`. The driver renders it
20
20
  // from a FORM the seat fills, and an accumulator holds every answer across attempts, parks and process
21
- // restarts — exactly as 's disposition union and 's coverage union already do for their seats.
21
+ // restarts — exactly as the disposition union and the coverage union already do for their seats.
22
22
  // A killed attempt then keeps every tier it had already placed.
23
23
  //
24
24
  // THE ROW SOURCE IS SELECTION-BY-REFERENCE, and it was settled by measurement, not by design taste. The
@@ -127,7 +127,7 @@ export function formRowKey(row) {
127
127
  *
128
128
  * DRIVER FACTS COME FROM `canonical`, never from the submitted row. A seat that rewrote `records` or
129
129
  * `owner` on its copy cannot widen what binds; only its three judgment fields are read from `row`.
130
- * That is 's discipline and it is the reason the union cannot be talked into anything.
130
+ * That is the discipline and it is the reason the union cannot be talked into anything.
131
131
  * PURE; never throws.
132
132
  */
133
133
  export function rowIsSettled(row, canonical) {
@@ -235,7 +235,7 @@ export function buildSelectionIndex({ floors = null, positions = null } = {}) {
235
235
  floor_records: floorList.length,
236
236
  positions: posList.length,
237
237
  selectable_records: byUri.size,
238
- // An ABSENCE is recorded in the artifact rather than swallowed — 's rule. "no floors" and "the
238
+ // An ABSENCE is recorded in the artifact rather than swallowed — the rule. "no floors" and "the
239
239
  // band shape would not parse" are different facts and must not read alike.
240
240
  floors_unreadable: floors === null,
241
241
  positions_unreadable: positions === null,
@@ -102,7 +102,7 @@ export function unionPlacementForm(prior, submitted, input) {
102
102
  const consumed = new WeakSet();
103
103
  // RETRACTION IS EXPLICIT, and it is the only way a row leaves this form.
104
104
  //
105
- // 's seat rows were retracted by SILENCE — a submission that spoke owned them — and that was right
105
+ // That seat rows were retracted by SILENCE — a submission that spoke owned them — and that was right
106
106
  // there, because that seat rewrote its whole form every pass. This one does not: it writes DELTAS, so a
107
107
  // corrective attempt that re-tiers two register rows says nothing about the run's common-law
108
108
  // candidates, and silence-retraction would delete every one of them without a word. The 2026-08-09
@@ -6,7 +6,7 @@
6
6
  // On the test instance they are the dominant content — a wall of dead runs crowding out the work
7
7
  // actually running, which is the one thing that section exists to show.
8
8
  //
9
- // WHAT THIS IS NOT. It is not a state change on the run, not a delete, and NOT 's retire. Retiring
9
+ // WHAT THIS IS NOT. It is not a state change on the run, not a delete, and NOT the retire. Retiring
10
10
  // writes `archive-tags.json`, which is pool-wide: it hides a run from everyone, including the brand
11
11
  // owner. Dashboard clutter is one person's annoyance, so it gets one person's store. Giving both to one
12
12
  // control would mean a staff member tidying their own dashboard silently hiding a client's run.
@@ -162,7 +162,7 @@ const FRONTED_MODES = new Set(["auth-proxy"]);
162
162
  /**
163
163
  * The auth row — the one row on this page that is NOT snapshot-derived, and deliberately so.
164
164
  *
165
- * WHY THIS BREAKS THE PAGE'S OWN RULE ON PURPOSE (, ruled 2026-08-21). Every other row here comes
165
+ * WHY THIS BREAKS THE PAGE'S OWN RULE ON PURPOSE (ruled 2026-08-21). Every other row here comes
166
166
  * from a snapshot because the portal cannot see the engine's environment. `PORTAL_AUTH_MODE` is the
167
167
  * opposite case: the PORTAL reads it (portal-service.mjs) and acts on it, so the portal is the
168
168
  * authoritative source for its own door. Routing it through flag-snapshot.mjs would publish another
@@ -336,7 +336,7 @@ export function accessView({ grants, staffDomains = [], knownAccounts = [], gran
336
336
  * because a log is unbounded by nature and this runs inside a web request.
337
337
  */
338
338
  /**
339
- * 's outcome rows — the events that record a request being TURNED AWAY rather than done. Kept
339
+ * That outcome rows — the events that record a request being TURNED AWAY rather than done. Kept
340
340
  * beside the reader rather than in portal-service.mjs so this file has no import cycle with the
341
341
  * service that writes them; the names are the contract between the two and are asserted in the test.
342
342
  */
@@ -137,7 +137,7 @@ export function readLocalCredential(path) {
137
137
  */
138
138
  export function credentialPathFor(env = process.env, home = null) {
139
139
  // `homedir()` is resolved ON THE RETURN LINE, not as a signature default, and that is deliberate:
140
- // 's arm finds the single line naming the credential's env override and asserts the fallback
140
+ // That arm finds the single line naming the credential's env override and asserts the fallback
141
141
  // derives from homedir() rather than a literal path. A one-line decision gets a one-line check, and
142
142
  // a signature default would put the fact where that check cannot see it. `home` stays injectable.
143
143
  //
@@ -388,7 +388,7 @@ function dropConnectorToken(html) {
388
388
  //
389
389
  // That is not a subtle degradation. chrome.css is 35KB of shared typography and layout, and among the
390
390
  // rules that went missing was `.lk-flag{width:10px;height:10px}` — sizing a lockup element that has
391
- // since been retired ( applied 's ruling to this lockup too), an SVG with no intrinsic size
391
+ // since been retired ( applied the ruling to this lockup too), an SVG with no intrinsic size
392
392
  // falling back to the browser default for a replaced element and painting at 300x150. The reported
393
393
  // symptoms — "a huge flag at the bottom", "font sizings inconsistent, multiple font types" — were one
394
394
  // cause: this file did not load. The example is historical; the failure mode is not, and any sizing
@@ -463,7 +463,7 @@ html{scrollbar-gutter:stable}
463
463
  // three functions the document already exposes to its own buttons. `openAll`/`pickAll` take a boolean and
464
464
  // nothing else; `exportPDF` takes no argument at all.
465
465
  const FEEDBACK_CSS = `
466
- /* tracker issue 260 — the per-finding flag. Injected here rather than in render.mjs, which is frozen and produces
466
+ /* the per-finding flag. Injected here rather than in render.mjs, which is frozen and produces
467
467
  every report ever delivered: putting the control at SERVE time means it reaches reports baked long
468
468
  before feedback existed, and the document on disk stays exactly what was delivered. */
469
469
  .pf-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:10px;padding-top:9px;border-top:1px solid var(--line,#e5ded4)}
@@ -590,7 +590,7 @@ const EMBED_JS = `
590
590
  // <body>), so by the time it runs for an '#c<ordinal>' link the ancestors are already open and the
591
591
  // measured offset is the revealed position. preventDefault stops the frame's dead-end fragment
592
592
  // navigation for the links the document's handler does not claim (#common-law, #only-you).
593
- // tracker issue 735 — AND WHEN THERE IS NO PARENT, DO NOT CANCEL THE CLICK.
593
+ // AND WHEN THERE IS NO PARENT, DO NOT CANCEL THE CLICK.
594
594
  //
595
595
  // Everything above is right INSIDE the portal's Result screen. Un-framed it is a dead link: parent is
596
596
  // window, the message is posted to this same document, and the only 'message' listener here requires
@@ -638,7 +638,7 @@ const FEEDBACK_JS = `
638
638
  (function(){
639
639
  var TAG='cordillera-report';
640
640
  function schedule(){ try{ parent.postMessage({source:TAG,type:'height',height:document.body.scrollHeight+16},'*'); }catch(e){} }
641
- // tracker issue 260 — PER-FINDING FEEDBACK, and why it posts outward instead of fetching.
641
+ // PER-FINDING FEEDBACK, and why it posts outward instead of fetching.
642
642
  //
643
643
  // This frame has NO allow-same-origin (Result.tsx), so its origin is "null": it holds no portal
644
644
  // session, a credentials:'include' fetch sends nothing, and a request from here arrives unauthenticated.
@@ -650,11 +650,11 @@ const FEEDBACK_JS = `
650
650
  // service reads those from the run's own artifacts, so nothing typed inside this frame can decide
651
651
  // which finding a flag lands on or whose matter it is labelled with.
652
652
  //
653
- // tracker issue 487 — THE POSITION IS TWO NUMBERS ON THE KNOCKOUT LANE, and it used to be none.
653
+ // THE POSITION IS TWO NUMBERS ON THE KNOCKOUT LANE, and it used to be none.
654
654
  //
655
655
  // The clearance report numbers its findings once across the document and hangs each on a
656
656
  // div.card with id "c<ordinal>". The knockout report has neither: its conflicts render as div.ko-find,
657
- // and tracker issue 471 restarts ordinals at 1 FOR EACH MARK. So this selector matched nothing on a knockout report
657
+ // and the knockout report restarts ordinals at 1 FOR EACH MARK. So this selector matched nothing on a knockout report
658
658
  // and the control was never drawn — the channel was not merely resolving wrong, it was absent. A
659
659
  // reader could not flag a knockout finding at all.
660
660
  //
@@ -102,7 +102,7 @@ import { batchMarkName } from "./mark-name.mjs";
102
102
  import { DEFAULT_CLIENT_DAILY_RUNS, accountUsage } from "./usage-ledger.mjs";
103
103
  import { productIdentity } from "../shared/product-identity.mjs"; // AGPL §13 — one answer, three surfaces
104
104
  import { engineCommit } from "./engine-build.mjs"; // — the SAME stamp pool meta records
105
- // — siblings, on their own line: 's guard pins the line above and its subject is the JOIN
105
+ // — siblings, on their own line: the guard pins the line above and its subject is the JOIN
106
106
  // (this endpoint and pool meta stamp the same function), not the import list. Kept separate so that
107
107
  // pin keeps reading the shape it was written against.
108
108
  import { engineCommitDate, engineProvenance } from "./engine-build.mjs";
@@ -948,7 +948,7 @@ const DENIAL_REASON = Object.freeze({
948
948
  *
949
949
  * The capture path it gates is intact: `feedback-store.mjs`, `feedback-issues.mjs`, `feedback-mint.mjs`,
950
950
  * `scripts/feedback-mint.mjs` and their suites are untouched and still green. Re-enabling is this
951
- * constant, the `feedback: true` argument at the serve call site, and reverting 's portal-ui half.
951
+ * constant, the `feedback: true` argument at the serve call site, and reverting the portal-ui half.
952
952
  */
953
953
  const FEEDBACK_CAPTURE = false;
954
954
 
@@ -968,7 +968,7 @@ const NON_MUTATING_POSTS = Object.freeze(["/portal/api/compose/read", "/portal/a
968
968
  /**
969
969
  * Does a refusal on this route owe the audit log a line?
970
970
  *
971
- * ── WIDENS 's ANSWER, and the reason is on that issue ─────────────────
971
+ * ── WIDENS the ANSWER, and the reason is on that issue ─────────────────
972
972
  *
973
973
  * scoped this to `/portal/admin/*` plus the one named client write, on the reasoning that the
974
974
  * other write routes "already file a richer row" of their own. Measured, that is true of their
@@ -980,9 +980,9 @@ const NON_MUTATING_POSTS = Object.freeze(["/portal/api/compose/read", "/portal/a
980
980
  *
981
981
  * So the rule is now the PREFIX, not a list: a POST under `/portal/api` or `/portal/admin` is a write
982
982
  * unless it is named above. A route added later is covered without anybody remembering to add it,
983
- * which is the half of 's shape that kept failing.
983
+ * which is the half of the shape that kept failing.
984
984
  *
985
- * STILL REFUSALS ONLY, and 's cost argument is why that half is unchanged: `/portal/admin/observed`
985
+ * STILL REFUSALS ONLY, and the cost argument is why that half is unchanged: `/portal/admin/observed`
986
986
  * reads this log back through a fixed 256 KiB tail, so every row a success files is span that panel can
987
987
  * no longer see. The routes that file a rich success row keep filing it and nothing duplicates it.
988
988
  *
@@ -1077,7 +1077,7 @@ export function makePortalService({
1077
1077
  // — IS THE PER-FINDING FLAG CAPTURE ON? It is not, and `FEEDBACK_CAPTURE` is why (see above).
1078
1078
  //
1079
1079
  // A SEAM SO THE RETAINED PATH STAYS TESTED, which is the whole difference between disabled and
1080
- // rotting. The resolver below carries 's two-lane shape and 's disposition read; the owner
1080
+ // rotting. The resolver below carries the two-lane shape and the disposition read; the owner
1081
1081
  // ruled disable rather than delete, and code nothing can execute is code nobody can prove still works.
1082
1082
  // The eleven route tests in portal-service.test.mjs pass `feedbackCapture: true` and keep exercising it.
1083
1083
  //
@@ -1158,7 +1158,7 @@ export function makePortalService({
1158
1158
  // ── — COVERAGE RIDES BESIDE AVAILABILITY, NOT INSIDE IT ───────────
1159
1159
  //
1160
1160
  // The owner, on his own install with a partial register: "i cannot press the button for Global
1161
- // prelim search. Why. it doesnt appear disabled, no message etc — but i cant select it." The
1161
+ // clearotron search. Why. it doesnt appear disabled, no message etc — but i cant select it." The
1162
1162
  // product is orderable now (owner ruling on that issue), and what the register does not reach
1163
1163
  // is a SENTENCE on a live row rather than the reason a dead one cannot be pressed.
1164
1164
  //
@@ -1391,7 +1391,7 @@ export function makePortalService({
1391
1391
  controls: { stop: { available: stopControl.available !== false,
1392
1392
  reason: principal.role === "staff" ? (stopControl.reason ?? null) : null } } } };
1393
1393
  }
1394
- // /portal/api/about — the AGPL §13 source offer (,)
1394
+ // /portal/api/about — the AGPL §13 source offer ()
1395
1395
  //
1396
1396
  // UNAUTHENTICATED, DELIBERATELY, and it is the only route here that is. §13 obliges an operator
1397
1397
  // running a modified version to offer the source to the users interacting with it — the offer is
@@ -2500,7 +2500,7 @@ export function makePortalService({
2500
2500
  // row, and a retired-endpoint row is a different fact from a not-yours row. If an old open tab is
2501
2501
  // still clicking Flag, that is a thing worth being able to count.
2502
2502
  //
2503
- // WHAT IS DELIBERATELY STILL BELOW THIS LINE: the whole resolver — 's two-lane shape, 's
2503
+ // WHAT IS DELIBERATELY STILL BELOW THIS LINE: the whole resolver — the two-lane shape, 's
2504
2504
  // disposition read, the server-side-locator rule. The owner ruled "disable services and any code",
2505
2505
  // and the acceptance criterion says re-enabling must be a switch and not a rebuild. Deleting 130
2506
2506
  // lines of hard-won doctrine would have made it a rebuild.
@@ -2568,7 +2568,7 @@ export function makePortalService({
2568
2568
  //
2569
2569
  // JOINED ON ORDINAL **AND** MARK, and it resolves NOTHING on a mismatch. report-data projects the
2570
2570
  // same parsed findings array publish read from that same findings.json, so the ordinals are one
2571
- // set — but a wrong disposition on a lawyer's flag is worse than no disposition ('s ruling on
2571
+ // set — but a wrong disposition on a lawyer's flag is worse than no disposition (the ruling on
2572
2572
  // the batch lane, applied here), so the mark is checked rather than assumed.
2573
2573
  //
2574
2574
  // CLEARANCE ONLY, on purpose. publish/knockout.mjs emits no disposition, so `found?.disposition`
@@ -2655,7 +2655,7 @@ export function makePortalService({
2655
2655
  // report every switch as off on a box where they are on — and this page, of all pages, would be
2656
2656
  // believed.
2657
2657
  if (parts[2] === "config" && method === "GET") {
2658
- // THE AUTH ROW IS READ LIVE, HERE, and not from the snapshot (, ruled 2026-08-21).
2658
+ // THE AUTH ROW IS READ LIVE, HERE, and not from the snapshot (ruled 2026-08-21).
2659
2659
  // Everything else on this page is RENDERED from the snapshot. The reason recorded here used
2660
2660
  // to be "because this process has no engine environment", and that has not been true since
2661
2661
  // the owner's 2026-08-26 one-configuration-per-server-box ruling gave every unit the same
@@ -3212,7 +3212,7 @@ const escHtml = (t) => String(t).replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<"
3212
3212
  // mentioned. A colour literal reappearing in this function is what
3213
3213
  // `driver/test/door-pages-take-their-colours-from-brand.test.mjs` fails on.
3214
3214
  //
3215
- // The dark ground moved with that change: the block this page used to carry had guessed tracker issue 17150f/#ece5d8,
3215
+ // The dark ground moved with that change: the block this page used to carry had guessed #17150f/#ece5d8,
3216
3216
  // and brand pack §01 fixes dark at #0f0e0c near-black + #f0e8d8 parchment. The pack wins.
3217
3217
  export function loginPage({ email, error = null, signedIn = false }) {
3218
3218
  const title = signedIn ? "Signed in" : "Sign in";
@@ -3408,7 +3408,7 @@ export function makeHttpHandler({ verify, limiter, service, log = () => {}, devI
3408
3408
  // PATHNAME ONLY. `req.url` carries the query string and this row must not; parsed defensively
3409
3409
  // because the outer catch can run before `url` was successfully built.
3410
3410
  const pathOnly = (u) => { try { return new URL(String(u ?? ""), "http://localhost").pathname; } catch { return ""; } };
3411
- // SAME SCOPE AS THE ROUTER'S ('s Out of scope). Without this the door files a row for every
3411
+ // SAME SCOPE AS THE ROUTER'S (the Out of scope). Without this the door files a row for every
3412
3412
  // 302 to the login page and every rate-limited poll of /portal/api/runs — which is per-request
3413
3413
  // access logging arriving through the other entrance, and the first cut of this change did exactly
3414
3414
  // that. Computed once so a redirect and a 500 on the same request cannot disagree about it.
@@ -3669,7 +3669,7 @@ export function makeHttpHandler({ verify, limiter, service, log = () => {}, devI
3669
3669
  // THE ROW THE ISSUE WAS FILED ABOUT. Both doors throw this shape — the Cloudflare edge's verify
3670
3670
  // and the local sign-in's LocalAuthError — so one line here covers a refused write on either
3671
3671
  // deployment. Before the Accept split below, because a refusal is one event however it renders.
3672
- // A FIXED VOCABULARY, NEVER `e.message` ('s third criterion: "a refusal must not become a
3672
+ // A FIXED VOCABULARY, NEVER `e.message` (the third criterion: "a refusal must not become a
3673
3673
  // new disclosure surface"). This message comes out of `verify()` — the Cloudflare edge's JWT
3674
3674
  // check, a third-party library on some deployments — and nothing constrains what it puts in
3675
3675
  // there: a claim value, a subject, a fragment of the token it just rejected. The row is read
@@ -3929,7 +3929,7 @@ const PORT = PORT_CHOICE.port;
3929
3929
  // is what an operator reads, never mentioned the file existed.
3930
3930
  //
3931
3931
  // So triage of "I clicked Retire and it errored" looked at 17 lines of startup banner and concluded
3932
- // the request never arrived. 's own triage recorded that same absence as its central lead and
3932
+ // the request never arrived. its own triage recorded that same absence as its central lead and
3933
3933
  // called it "the first thing to explain" — there was nothing to explain, and a second investigation
3934
3934
  // spent itself on the same non-signal.
3935
3935
  //
@@ -23,8 +23,8 @@
23
23
  // report-derived cover text alone, because a gate that simply stops running is not a gate that passes.
24
24
 
25
25
  import { REGION_NAMES } from "./publish/regions.mjs";
26
- import { canonicalJurisdictionCode } from "./jurisdiction-codes.mjs"; // tracker issue 134 — one spelling of a territory code
27
- import { searchedCovers } from "./frame-diff-model.mjs"; // tracker issue 134 — one copy of the EU-reach rule
26
+ import { canonicalJurisdictionCode } from "./jurisdiction-codes.mjs"; // one spelling of a territory code
27
+ import { searchedCovers } from "./frame-diff-model.mjs"; // one copy of the EU-reach rule
28
28
  import { partyFactSources, partyFactViolations, partyFactMessage, canJudgePartyFacts } from "./party-facts.mjs"; //
29
29
  import { writeUpViolations, writeUpMessage } from "./narrative-write-ups.mjs"; //
30
30
 
@@ -72,7 +72,7 @@ const REF_ALLOWLIST = new Set([
72
72
  // ── — A TERRITORY IS NOT A PARTY, AND A MARK IS NOT A PARTY ────────────────────────────────────
73
73
  // Two production clearances flagged six "parties the action list names that no finding identifies".
74
74
  // FOUR were not parties: "European Union", "United Kingdom", "United Arab Emirates" and a mark. The
75
- // check then emitted that into the report, which is 's other half.
75
+ // check then emitted that into the report, which is the other half.
76
76
  //
77
77
  // Territory names come from `publish/regions.mjs` — the ONE naming source every render surface already
78
78
  // uses — rather than from the run's own jurisdiction list. Broader, and deliberately: a bare country
@@ -1547,7 +1547,7 @@ export function markAssessmentChecks({ markAssessment, expected }) {
1547
1547
  }
1548
1548
 
1549
1549
  /**
1550
- * The DECLARED CONTRACT VERSION (, moved out of contentModelChecks by).
1550
+ * The DECLARED CONTRACT VERSION (moved out of contentModelChecks by).
1551
1551
  *
1552
1552
  * It used to live inside contentModelChecks, whose first line is `if (!expected) return []`, where
1553
1553
  * `expected` is derived as `schema_version >= 5`. So the one check written to report a down-level
@@ -2237,7 +2237,7 @@ export function runLint({ depth, commonLawGrid, matterContext, clientPartyName,
2237
2237
  checks.push(...ownerScreenNegativeChecks({ text: clientSummaryMd, ownerScreen, markVocab, surface: "client-summary" }));
2238
2238
  }
2239
2239
  }
2240
- // tracker issue 134 — the delivered prose's coverage claims against what the run actually searched.
2240
+ // the delivered prose's coverage claims against what the run actually searched.
2241
2241
  // Top-level, NOT inside the owner-screen guard above: a coverage claim has nothing to do with whether
2242
2242
  // this run has an owner screen, and nesting it there would have silently switched the check off for
2243
2243
  // every run without one. Both prose surfaces: the narrative is where the issue measured the
@@ -2305,7 +2305,7 @@ export function runLint({ depth, commonLawGrid, matterContext, clientPartyName,
2305
2305
  // The knockout (Stage 0/0.5) lane wrote NO predelivery-lint.json at all, by a decision recorded in
2306
2306
  // docs/DELIVERY.md (2026-07-28). That decision rested on two premises this tranche has since moved:
2307
2307
  // the lint artifact is now the WORKBOOK's QC record (/), so a lane that writes none produces an
2308
- // EMPTY QC record rather than a deliberately-absent one; and 's A10 projects recorded defects onto
2308
+ // EMPTY QC record rather than a deliberately-absent one; and the A10 projects recorded defects onto
2309
2309
  // the cover note that reaches the reviewing lawyer, so a knockout defect reached nobody. What has NOT
2310
2310
  // moved is the other half of the memo: this lane's deliverable is store-rendered, and most clearance
2311
2311
  // checks read surfaces it does not produce. So the extension is a SUBSET, derived from what the lane
@@ -2454,6 +2454,13 @@ export function flagLines(failures) {
2454
2454
  // vendor vocabulary, no ids, no paths, no field names, no instructions to whoever regenerates the run,
2455
2455
  // never "certified"/"signed". deliveryVocabViolations() below enforces that mechanically.
2456
2456
  const DELIVERY_LINES = {
2457
+ // Keyed on the FULL check id, which deliveryFlagLines resolves before the base — see the note there.
2458
+ // The sentence states the CONSEQUENCE, in the receipt's own terms: not "a check failed" but "the rule
2459
+ // was applied to nothing". Eleven graded runs delivered carrying this, two of them orderable product
2460
+ // demos, and the only place it was written was one row of a fifty-odd-row receipt nobody routes.
2461
+ "narrative-write-ups:could-not-read":
2462
+ "The depth rules for the written-up findings were applied to nothing on this run — the narrative "
2463
+ + "carries no block this check can read, so neither the ranking cut nor the length cap was verified.",
2457
2464
  // template — the summary table against the names actually searched
2458
2465
  "names-cell-populated": "The summary table does not name the mark that was searched.",
2459
2466
  "assessment-row": "A searched name has no assessment of its own in the summary table.",
@@ -2555,15 +2562,26 @@ export function deliveryVocabViolations(line) {
2555
2562
  export function deliveryFlagLines(failures) {
2556
2563
  const groups = new Map();
2557
2564
  for (const f of failures ?? []) {
2558
- const base = String(f?.id ?? "").split(":")[0];
2565
+ const id = String(f?.id ?? "");
2566
+ const base = id.split(":")[0];
2559
2567
  const family = String(f?.family ?? "");
2560
- const key = base || `family/${family}`;
2561
- const g = groups.get(key) ?? { base, family, n: 0 };
2568
+ // A CHECK WHOSE DISTINCTION LIVES IN ITS SUFFIX COULD NOT BE SAID HERE (tracker issue 267).
2569
+ //
2570
+ // Grouping on `base` alone is right for the common case — a word-cap violation on nine write-ups is
2571
+ // one delivery line, not nine. But it also collapsed `narrative-write-ups:could-not-read` into the
2572
+ // same bucket as an ordinary depth violation, and those are different facts: one says a rule was
2573
+ // broken, the other says the rule was ENFORCED ON NOTHING. The second had no sentence of its own to
2574
+ // reach, so it degraded to the generic "a machine check did not pass" and became invisible.
2575
+ //
2576
+ // So: an entry keyed on the FULL id wins where one exists, and everything else groups by base
2577
+ // exactly as before. This adds no line to any run that did not already produce one.
2578
+ const key = DELIVERY_LINES[id] ? id : (base || `family/${family}`);
2579
+ const g = groups.get(key) ?? { base, family, id: DELIVERY_LINES[id] ? id : null, n: 0 };
2562
2580
  g.n += 1;
2563
2581
  groups.set(key, g);
2564
2582
  }
2565
2583
  return [...groups.values()].map((g) => {
2566
- const sentence = DELIVERY_LINES[g.base] ?? DELIVERY_FAMILY_LINES[g.family] ?? DELIVERY_GENERIC;
2584
+ const sentence = (g.id && DELIVERY_LINES[g.id]) ?? DELIVERY_LINES[g.base] ?? DELIVERY_FAMILY_LINES[g.family] ?? DELIVERY_GENERIC;
2567
2585
  // Belt and braces: a table entry that trips the house rules degrades to the generic instead of
2568
2586
  // shipping. This is what makes "no engine vocabulary reaches a reader" structural rather than a
2569
2587
  // matter of everyone remembering the rule when they add a check.
@@ -55,7 +55,7 @@ export function prelimVariantsCallPaths(runDir) {
55
55
  // The first cut of this file declared its own copy of the layer vocabulary — field, jurisdiction,
56
56
  // variant, source — under a comment saying "taken from the shipped parser, never re-chosen here", while
57
57
  // re-choosing it: the shipped parser orders the same four as variant, field, source, jurisdiction. The
58
- // comment asserted the exact property it broke, which is why a reader could not catch it and 's scan
58
+ // comment asserted the exact property it broke, which is why a reader could not catch it and the scan
59
59
  // could. That check binds every parsed declaration of a closed set to the live import, found two
60
60
  // declarations of one name, and reported the disagreement.
61
61
  //
@@ -112,7 +112,7 @@ export function renderPrelimVariants(model, scopeRows) {
112
112
  //
113
113
  // `variantsManifestAudit` (common-law-receipts.mjs) arms a term collector on any heading matching
114
114
  // /variants\b/i and closes it on the next heading AT THE SAME DEPTH OR SHALLOWER. Deeper headings are
115
- // sub-groups INSIDE the section and deliberately keep it armed — that is 's fix, for a real
115
+ // sub-groups INSIDE the section and deliberately keep it armed — that is the fix, for a real
116
116
  // manifest whose 84 variants sat under seven `####` sub-headings and parsed as zero.
117
117
  //
118
118
  // So a `## Variants` section followed by a `### Scope ledger` NEVER CLOSES, and every ledger row is
@@ -256,7 +256,7 @@ function collect() {
256
256
  // writes ABSENCE and never `false` (tracker issue 1991). It was a checkbox, which rendered absent and
257
257
  // `false` identically and wrote a boolean on every save — so a customer who had given no instruction
258
258
  // was recorded as "strip the line" the first time anybody pressed Save on an unrelated field, and
259
- // their next report shipped with no confidentiality line. That is tracker issue 761's incident on this door.
259
+ // their next report shipped with no confidentiality line. That is the incident this door has already had.
260
260
  // `true` is retired and renders as the default (shared/brand.mjs confPosture), so it folds to the same
261
261
  // option and saves as absence rather than storing a distinction the output can no longer carry.
262
262
  if ($("f_priv").value === "no") delivery.privileged = false; else delete delivery.privileged;
@@ -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
  // profile-selection.mjs — which findings the refutation seat is asked to profile, chosen by the DRIVER.
4
4
  //
5
- // 's architecture: "prefer driver selection wherever the key precedes the dispatch." The band is
5
+ // That architecture: "prefer driver selection wherever the key precedes the dispatch." The band is
6
6
  // on findings.json before narrative-refutation is dispatched, so there is nothing for a directive to
7
7
  // ask the seat to judge — the driver lists the ordinals and unlisted work is never requested.
8
8
  //
@@ -441,7 +441,7 @@ export function makeProfileService({
441
441
  // The transition is encoded in the message so the config store's git log reads as an audit trail —
442
442
  // the same three words saved searches emit (an un-archive reads as "update" there too).
443
443
  const transition = exists ? (overlayBody.archived && !priorOverlay?.archived ? "archive" : "update") : "create";
444
- const message = `chore(prelim): ${transition} project ${customer}/${project} (via config UI, by ${by})`;
444
+ const message = `chore(clearotron): ${transition} project ${customer}/${project} (via config UI, by ${by})`;
445
445
  // — the row rides IN the commit, so it no longer names a sha. shared/store-in-repo.mjs says why.
446
446
  const { commit, commitError } = commitWithAuditRow({ audit, gitCommit, files, message, by,
447
447
  row: { event: exists ? "project-update" : "project-create", key: fq, by, fields: Object.keys(overlayBody),
@@ -494,7 +494,7 @@ export function makeProfileService({
494
494
  // fault) threw out of the handler, so the user was told "Nothing was written. Try again shortly."
495
495
  // about a profile that was already governing production, and the audit() call below was skipped —
496
496
  // leaving no record of who changed it. Same guard the project branch above already carries.
497
- const message = `chore(prelim): ${exists ? "update" : "create"} customer profile ${key} (via config UI, by ${by})`;
497
+ const message = `chore(clearotron): ${exists ? "update" : "create"} customer profile ${key} (via config UI, by ${by})`;
498
498
  // — the row rides IN the commit, so it no longer names a sha. shared/store-in-repo.mjs says why.
499
499
  const { commit, commitError } = commitWithAuditRow({ audit, gitCommit, files, message, by,
500
500
  row: { event: exists ? "profile-update" : "profile-create", key, by, fields: Object.keys(effective) } });
@@ -882,7 +882,7 @@ export function resolveEffectiveProfile(job, { profiles = loadProfiles(), projec
882
882
  //
883
883
  // Attached here rather than threaded through four call sites because this is the one place that KNOWS
884
884
  // — every caller that resolves a profile now carries its provenance whether or not it thought to ask,
885
- // and 's hand-bridge at the §B2 door (`{...profile, origins }`) becomes a no-op rather than the
885
+ // and the hand-bridge at the §B2 door (`{...profile, origins }`) becomes a no-op rather than the
886
886
  // only correct call site. The sibling stays in the return for the callers that read it directly.
887
887
  return { profile: { ...profile, origins }, projectKey: overlay.projectKey, projectName: overlay.projectName, origins };
888
888
  }
@@ -8,7 +8,7 @@
8
8
  // 1. <runDir>/status.json — the machine-readable per-run truth (travels into the archive on
9
9
  // success, since the run-dir is renamed there).
10
10
  // 2. <studioRoot>/STATUS.md — a human-readable rollup of recent runs, newest-first, the ONE file
11
- // the prelim-status skill reads to answer "where is it at?".
11
+ // the clearotron-status skill reads to answer "where is it at?".
12
12
  //
13
13
  // Both writes are atomic (temp + rename) and idempotent — status is DERIVED from the current run, never
14
14
  // blindly incremented — so the resumable pipeline can re-drive a run without corrupting either file.
@@ -440,15 +440,15 @@ export function lineFor(s) {
440
440
  // 2026-07-04 incident: STATUS.md showed marble-spire as plain "delivered" and VENZY as plain
441
441
  // "FAILED" while BOTH still had their email/WhatsApp queued (sendPending) behind a wedged outbox
442
442
  // lane — so the heartbeat completion-watch read the rollup, saw nothing pending, and stood down.
443
- // The rollup now carries the send state loudly; prelim-deliver flips sendPending:false on send.
444
- const pending = s.sendPending === true ? " — 📮 SEND PENDING (email/WhatsApp NOT yet out — run prelim-deliver)" : "";
443
+ // The rollup now carries the send state loudly; clearotron-deliver flips sendPending:false on send.
444
+ const pending = s.sendPending === true ? " — 📮 SEND PENDING (email/WhatsApp NOT yet out — run clearotron-deliver)" : "";
445
445
  if (s.state === "delivered") {
446
446
  const v = s.verdict ? ` (${s.verdict})` : "";
447
447
  return `- ${head} — delivered${v}${s.url ? ` — ${s.url}` : ""}${pending}`;
448
448
  }
449
449
  if (s.state === "failed") {
450
450
  const at = s.failedStage ?? s.lastStage ?? stepTxt;
451
- return `- ${head} — ⚠️ FAILED at ${at}${s.reason ? ` — ${trunc(s.reason)}` : ""}${pending ? " — 📮 FAILURE NOTICE PENDING (run prelim-deliver)" : ""}`;
451
+ return `- ${head} — ⚠️ FAILED at ${at}${s.reason ? ` — ${trunc(s.reason)}` : ""}${pending ? " — 📮 FAILURE NOTICE PENDING (run clearotron-deliver)" : ""}`;
452
452
  }
453
453
  if (s.state === "recovering") {
454
454
  // 2026-07-04 production doctrine: a recoverable failure AUTO-RESUMES — the report is still owed.
@@ -513,8 +513,8 @@ export function rollupStatus(studioRoot) {
513
513
  .sort((a, b) => String(b.updatedAt ?? "").localeCompare(String(a.updatedAt ?? "")))
514
514
  .slice(0, MAX_RUNS);
515
515
  const agent = agentFromStudioRoot(studioRoot);
516
- const body = runs.length ? runs.map(lineFor).join("\n") : "_No prelim searches running or recently finished._";
517
- const md = `# Prelim-search status — ${agent}\n_updated ${nowISO()}_\n\n${body}\n`;
516
+ const body = runs.length ? runs.map(lineFor).join("\n") : "_No clearotron searches running or recently finished._";
517
+ const md = `# Clearotron-search status — ${agent}\n_updated ${nowISO()}_\n\n${body}\n`;
518
518
  atomicWrite(join(studioRoot, "STATUS.md"), md);
519
519
  } catch { /* never throw */ }
520
520
  }
@@ -48,7 +48,7 @@ export const KINDS = ["search", "record_fetch", "image", "phoneme", "batch_scree
48
48
  // The gateway namespaces the driver's --session-key as `agent:<agentId>:<key>` before it reaches the
49
49
  // plugin (confirmed on the first live run: sessionKey = `agent:clawdi:prelim-<slug>-<codename>-…`). Strip
50
50
  // that leading `agent:<id>:` namespace so the run prefix anchors at the real start of the caller's key —
51
- // otherwise a bare startsWith("prelim-…") matches nothing.
51
+ // otherwise a bare startsWith("clearotron-…") matches nothing.
52
52
  function stripGatewayNs(s) {
53
53
  return typeof s === "string" ? s.replace(/^agent:[^:]+:/, "") : "";
54
54
  }
@@ -74,7 +74,7 @@ export function resolveDemoData({
74
74
  /**
75
75
  * The demonstration note for a MARKDOWN surface.
76
76
  *
77
- * 's acceptance 3 asks for the banner on "the grouped knockout page … the one a
77
+ * That acceptance 3 asks for the banner on "the grouped knockout page … the one a
78
78
  * reader opens first". THAT PAGE DOES NOT EXIST: `knockout.mjs` states in its own header that a
79
79
  * multi-mark run "writes no `report.html` AT ALL — the documents are `report-<slug>.html`, one per
80
80
  * mark", and that `report.md` "is the ONLY file that names every mark together". It is also written
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-only
2
2
  // Copyright 2026 Cordillera Sàrl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
3
- // Pure-code publish step for the prelim-driver: takes a finished run's two contract markdown files
3
+ // Pure-code publish step for the clearotron-driver: takes a finished run's two contract markdown files
4
4
  // (report.md + audit.md, written by the report-synthesis / audit-emit stages) and renders + writes the
5
5
  // delivery artifacts into the pool (`config.poolRoot`, which since has NO default — unset refuses),
6
6
  // then regenerates the index.
@@ -702,7 +702,7 @@ export async function publishReport({ runId, codename, reportMd, auditMd, findin
702
702
  let findings = [], coverage = [], contextNotes = [], quarantined = [], findingsError = null, coverageJudgment = null, markAssessment = null, actionsRegister = null, askAnswers = null, correctionsDoc = null, fourAnswers = null;
703
703
  // — the DECLARED findings contract version, threaded to the renderer so the grouped
704
704
  // reasoned-negative section fires only on a v6 record. Stays null on the lenient/error paths: fail
705
- // closed, an unknown version renders the pre- section.
705
+ // closed, an unknown version renders the pre-change section.
706
706
  let findingsSchemaVersion = null;
707
707
  // — THE STORES THIS PUBLISH DID NOT FIND. Declared in publish/publish-inputs.mjs, read through
708
708
  // its three-state helper, and recorded onto meta.clientGate below. Before this list existed an absent
@@ -981,7 +981,7 @@ export async function publishReport({ runId, codename, reportMd, auditMd, findin
981
981
  // `gateViolations` — those are LOGGED for observability but never a reason to drop the download. (An earlier
982
982
  // version made the gate fatal, so a legitimately-sparse run — e.g. no bound Class — silently lost its Excel.)
983
983
  // The run's REPORT IDENTITY, off the same registry row that chose its machinery. The FROZEN policy
984
- // sidecar names WHICH level ran; the registry names what that level is called TODAY (, one
984
+ // sidecar names WHICH level ran; the registry names what that level is called TODAY (one
985
985
  // numbering system — reportIdentityFor is registry-first, sidecar label only for a level the registry
986
986
  // no longer knows). So a republished pre-renumber run renders under the current scale, deliberately.
987
987
  // A run with no sidecar (every run older than the level registry) yields undefined and renders
@@ -1189,7 +1189,10 @@ export async function publishReport({ runId, codename, reportMd, auditMd, findin
1189
1189
 
1190
1190
  const total = skipRegen ? null : regenIndex(poolRoot);
1191
1191
  if (!skipRegen) await regenSurfaces(poolRoot);
1192
- const url = poolUrl ? `${String(poolUrl).replace(/\/$/, '')}/${runId}/report.html` : null;
1192
+ // THE PORTAL ROUTE, not the pool's directory layout (tracker issue 289). This was
1193
+ // `<origin>/<runId>/report.html` — where the documents sit on disk, which is not an application route.
1194
+ // Composed rather than spelled here so the report link is built the same way the audit link always was.
1195
+ const url = reportRouteFor(poolUrl, runId);
1193
1196
  return { runId, auditFile, counts, total, url, poolRunDir, auditError, findingsError, customerKey: customerKey || 'generic', clientGate };
1194
1197
  }
1195
1198
 
@@ -1241,7 +1244,21 @@ export function accessNoteHtml(font, domain = config.accessDomain) {
1241
1244
  * the edge's own legacy-report regexp character for character, so this function admits exactly the URLs the
1242
1245
  * deployment admits and no others.
1243
1246
  */
1244
- const REPORT_PATH_RE = /^\/([A-Za-z0-9][A-Za-z0-9._-]{0,180})\/report\.html$/;
1247
+ // ── TWO SHAPES, AND THE SECOND ONE IS HISTORY (tracker issue 289) ────────────────────────────────────
1248
+ //
1249
+ // The block quoted above describes an edge rewrite that IS NOT IN FORCE ON PRODUCTION. Settled by the
1250
+ // account owner against the live deployment, signed in as a delivered run's own owner: the emailed link
1251
+ // returned the portal application's own `{"error":"not_found"}` — the app answered, so nothing rewrote
1252
+ // the path ahead of it — while the portal's own link for that same run opened. The prose above, and the
1253
+ // notes in portal-service.mjs and publish/knockout.mjs that lean on it, describe a config that does not
1254
+ // live in this repository and were transcribed when it was true somewhere. A transcription is a claim
1255
+ // about a host at the moment somebody wrote it down, not a fact about the host today.
1256
+ //
1257
+ // So reports are addressed at the portal route now (reportRouteFor), and this pattern keeps matching the
1258
+ // LEGACY shape as well for one reason: `auditUrlFor` derives the workbook link by parsing the report URL,
1259
+ // and an archived run re-published from its stored legacy URL must not silently lose its audit link. The
1260
+ // two alternatives are read in one place so a future reader cannot fix one and miss the other.
1261
+ const REPORT_PATH_RE = /^\/(?:portal\/report\/([A-Za-z0-9][A-Za-z0-9._-]{0,180})\/?|([A-Za-z0-9][A-Za-z0-9._-]{0,180})\/report\.html)$/;
1245
1262
 
1246
1263
  // The run id as the edge and the portal both spell it: one path segment, no separators, no traversal.
1247
1264
  // Same character class as REPORT_PATH_RE's capture and as portal-service's own slug gate, because a
@@ -1261,6 +1278,29 @@ export function auditRouteFor(origin, runId) {
1261
1278
  return `${String(origin).replace(/\/$/, '')}/portal/report/${runId}/audit.xlsx`;
1262
1279
  }
1263
1280
 
1281
+ /**
1282
+ * THE REPORT'S ROUTE, from an origin and a run id (tracker issue 289).
1283
+ *
1284
+ * The delivered link used to be the pool's directory layout pasted behind the public origin —
1285
+ * `<origin>/<runId>/report.html` — which is where the documents sit on disk and is not an application
1286
+ * route. It resolved only where an edge rewrite happened to claim it, and on production no such rewrite
1287
+ * is in force: the emailed link returned the portal's own `{"error":"not_found"}` for the run's OWN
1288
+ * owner. Every delivered report on both lanes carried it, on all three surfaces that quote the URL.
1289
+ *
1290
+ * Composed here, beside auditRouteFor and markReportRouteFor, so the three links a delivery carries are
1291
+ * built by three functions with one idea of where the portal lives. That is the property worth having:
1292
+ * the audit link has been correct throughout precisely because it was composed against the route instead
1293
+ * of derived from the file layout, and this makes the report link the same kind of thing.
1294
+ *
1295
+ * A link the portal will refuse is worse than none, so an unconfigured origin or a run id that is not a
1296
+ * single clean path segment yields null — the same posture auditRouteFor takes, and the caller already
1297
+ * treats null as "no link on any surface".
1298
+ */
1299
+ export function reportRouteFor(origin, runId) {
1300
+ if (!origin || !runId || !RUN_SEGMENT_RE.test(String(runId))) return null;
1301
+ return `${String(origin).replace(/\/$/, '')}/portal/report/${runId}/`;
1302
+ }
1303
+
1264
1304
  /**
1265
1305
  * ONE MARK'S DOCUMENT in a batch, at the address the portal serves it from.
1266
1306
  *
@@ -1292,7 +1332,8 @@ export function auditUrlFor(reportUrl, auditFile) {
1292
1332
  let u;
1293
1333
  try { u = new URL(String(reportUrl)); } catch { return null; }
1294
1334
  const m = REPORT_PATH_RE.exec(u.pathname);
1295
- return m ? auditRouteFor(u.origin, m[1]) : null;
1335
+ // Group 1 is the portal shape, group 2 the legacy one — exactly one of them matches.
1336
+ return m ? auditRouteFor(u.origin, m[1] ?? m[2]) : null;
1296
1337
  }
1297
1338
 
1298
1339
  /**