clearotron 0.2.1 → 0.2.3

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 (676) hide show
  1. package/.env.example +82 -1
  2. package/.nvmrc +1 -1
  3. package/CONTRIBUTING.md +3 -3
  4. package/INSTALL.md +64 -58
  5. package/README.md +11 -16
  6. package/THIRD-PARTY-NOTICES.md +1 -1
  7. package/bin/brandowner.mjs +1 -1
  8. package/bin/clearotron.mjs +26 -4
  9. package/bin/connect.mjs +2 -2
  10. package/bin/example.mjs +31 -11
  11. package/bin/grant.mjs +3 -3
  12. package/bin/key.mjs +1 -1
  13. package/bin/onboard.mjs +252 -136
  14. package/bin/start.mjs +176 -33
  15. package/bin/stop.mjs +65 -3
  16. package/bin/update.mjs +7 -7
  17. package/bin/uspto-sync.mjs +1 -1
  18. package/build-info.json +2 -2
  19. package/demo/full-country-search/run/_driver/framework.json +1 -1
  20. package/demo/global-preliminary-search/run/_driver/framework.json +1 -1
  21. package/demo/knockout-search/run/_driver/framework.json +1 -1
  22. package/demo/multi-country-focus-search/run/_driver/framework.json +1 -1
  23. package/docs/DELIVERY.md +6 -2
  24. package/docs/E2E.md +5 -5
  25. package/docs/PORTAL.md +2 -2
  26. package/docs/README.md +5 -4
  27. package/docs/SECURITY.md +17 -0
  28. package/docs/architecture/01-product-overview.md +2 -2
  29. package/docs/architecture/02-architecture.md +2 -2
  30. package/docs/architecture/04-configuration-reference.md +8 -3
  31. package/docs/architecture/05-config-governance.md +52 -5
  32. package/docs/architecture/05-customer-profiles.md +2 -2
  33. package/docs/architecture/06-operations-runbook.md +13 -1
  34. package/docs/architecture/09-security-and-data.md +1 -1
  35. package/docs/configuration.md +4 -3
  36. package/docs/decisions/0004-documentation-structure.md +1 -1
  37. package/driver/CHANGELOG.md +121 -1
  38. package/driver/README.md +2 -2
  39. package/driver/ask-ledger.mjs +3 -3
  40. package/driver/authority-trees.mjs +1 -1
  41. package/driver/call-capture.mjs +1 -1
  42. package/driver/card-frame.mjs +1 -1
  43. package/driver/case-law-ledger.mjs +1 -1
  44. package/driver/claim-liveness.mjs +1 -1
  45. package/driver/common-law-receipts.mjs +2 -2
  46. package/driver/commonlaw-carry.mjs +1 -1
  47. package/driver/config-inventory.mjs +1 -1
  48. package/driver/config-staleness.mjs +1 -1
  49. package/driver/connotation-search.mjs +12 -12
  50. package/driver/contract-audit.mjs +5 -5
  51. package/driver/contract-dictation-registry.mjs +4 -4
  52. package/driver/contract-dictation.mjs +2 -2
  53. package/driver/contract-e3-backlog.mjs +6 -6
  54. package/driver/contract-vocabulary.mjs +3 -3
  55. package/driver/corrections-feedforward.mjs +1 -1
  56. package/driver/coverage-form-io.mjs +2 -2
  57. package/driver/coverage-form.mjs +4 -4
  58. package/driver/coverage-ledger.mjs +3 -3
  59. package/driver/coverage-union.mjs +1 -1
  60. package/driver/declination-call.mjs +35 -3
  61. package/driver/declination-duty.mjs +1 -1
  62. package/driver/deliver-trigger.sh +3 -3
  63. package/driver/deploy-live-run-guard.mjs +6 -2
  64. package/driver/dev-portal.mjs +3 -3
  65. package/driver/disposition-call.mjs +4 -4
  66. package/driver/disposition-tool.mjs +4 -4
  67. package/driver/disposition-union.mjs +2 -2
  68. package/driver/doc-constants.mjs +1 -1
  69. package/driver/door-gates.mjs +2 -2
  70. package/driver/doubt-selection.mjs +2 -2
  71. package/driver/drainer-identity.mjs +1 -1
  72. package/driver/driver.config.mjs +64 -12
  73. package/driver/e2e-rounds.mjs +2 -2
  74. package/driver/effort-model.mjs +2 -2
  75. package/driver/engine/anthropic-agent.mjs +24 -24
  76. package/driver/engine/auth.mjs +1 -1
  77. package/driver/engine/cli-version.mjs +103 -0
  78. package/driver/engine/common.mjs +1 -1
  79. package/driver/engine/deny-authority-write.mjs +1 -1
  80. package/driver/engine/jx-turn.mjs +1 -1
  81. package/driver/engine/mcp/clarivate-server.mjs +1 -1
  82. package/driver/engine/mcp/corsearch-server.mjs +1 -1
  83. package/driver/engine/mcp/declination-server.mjs +1 -1
  84. package/driver/engine/mcp/dispositions-server.mjs +1 -1
  85. package/driver/engine/mcp/euipo-server.mjs +1 -1
  86. package/driver/engine/mcp/fetch-server.mjs +1 -1
  87. package/driver/engine/mcp/free-tier-server.mjs +2 -2
  88. package/driver/engine/mcp/gather-config.mjs +11 -11
  89. package/driver/engine/mcp/perplexity-server.mjs +1 -1
  90. package/driver/engine/mcp/recording-server.mjs +8 -4
  91. package/driver/engine/mcp/signa-server.mjs +1 -1
  92. package/driver/engine/mcp/uspto-local-server.mjs +1 -1
  93. package/driver/engine/openai-agent.mjs +2 -2
  94. package/driver/engine-build.mjs +2 -2
  95. package/driver/enqueue-schema.mjs +10 -10
  96. package/driver/enqueue.mjs +1 -1
  97. package/driver/envelope-settle.mjs +1 -1
  98. package/driver/evidence-claim-invariant.mjs +2 -2
  99. package/driver/feedback-store.mjs +1 -1
  100. package/driver/findings-model.mjs +60 -10
  101. package/driver/flag-snapshot.mjs +20 -0
  102. package/driver/floor-duty.mjs +1 -1
  103. package/driver/form-neighbourhood.mjs +1 -1
  104. package/driver/framework.mjs +2 -2
  105. package/driver/gateway.mjs +45 -23
  106. package/driver/grounds-grammar.mjs +1 -1
  107. package/driver/hit-list.mjs +1 -1
  108. package/driver/jurisdiction-systems.mjs +1 -1
  109. package/driver/jx-lanes.mjs +1 -1
  110. package/driver/jx-units.mjs +1 -1
  111. package/driver/jx.mjs +3 -3
  112. package/driver/knockout-assess-record.mjs +5 -1
  113. package/driver/narrative-refutation-record.mjs +3 -3
  114. package/driver/numeric-setting.mjs +1 -1
  115. package/driver/owner-use-check.mjs +184 -0
  116. package/driver/package.json +4 -4
  117. package/driver/party-facts.mjs +2 -2
  118. package/driver/phase0.mjs +2 -2
  119. package/driver/pipeline-knockout.mjs +52 -4
  120. package/driver/pipeline.mjs +180 -67
  121. package/driver/placement-diff.mjs +2 -2
  122. package/driver/placement-form.mjs +4 -4
  123. package/driver/placement-union.mjs +1 -1
  124. package/driver/plain-register.mjs +120 -0
  125. package/driver/portal-access.mjs +1 -1
  126. package/driver/portal-acks.mjs +1 -1
  127. package/driver/portal-config-view.mjs +42 -3
  128. package/driver/portal-families.mjs +1 -1
  129. package/driver/portal-local-auth.mjs +1 -1
  130. package/driver/portal-report.mjs +7 -7
  131. package/driver/portal-service.mjs +41 -22
  132. package/driver/portal-upstream.mjs +2 -2
  133. package/driver/predelivery-lint.mjs +149 -11
  134. package/driver/prelim-variants-record.mjs +2 -2
  135. package/driver/profile-page.html +11 -3
  136. package/driver/profile-selection.mjs +1 -1
  137. package/driver/profile-service.mjs +6 -6
  138. package/driver/profiles/README.md +3 -3
  139. package/driver/profiles.mjs +145 -13
  140. package/driver/progress.mjs +6 -6
  141. package/driver/provider-usage.mjs +1 -1
  142. package/driver/publish/demo-marking.mjs +1 -1
  143. package/driver/publish/index.mjs +49 -8
  144. package/driver/publish/knockout.mjs +42 -14
  145. package/driver/publish/parse.mjs +4 -4
  146. package/driver/publish/publish-inputs.mjs +2 -2
  147. package/driver/publish/register-presence.mjs +1 -1
  148. package/driver/publish/render-knockout.mjs +646 -144
  149. package/driver/publish/render.mjs +2 -2
  150. package/driver/publish/report-data.mjs +13 -3
  151. package/driver/queue-watch-probe.mjs +1 -1
  152. package/driver/queue-watch-verdict.mjs +1 -1
  153. package/driver/recall-reconciliation.mjs +1 -1
  154. package/driver/recipe-service.mjs +1 -1
  155. package/driver/record-carry.mjs +5 -5
  156. package/driver/recording-agreement.mjs +3 -3
  157. package/driver/reference-score.mjs +7 -7
  158. package/driver/reference-strip-signatures.mjs +20 -0
  159. package/driver/refusal-bound.mjs +3 -3
  160. package/driver/register-availability.mjs +2 -2
  161. package/driver/register-count.mjs +1 -1
  162. package/driver/register-grant-vocabulary.mjs +2 -2
  163. package/driver/register-plan.mjs +8 -8
  164. package/driver/register-records.mjs +2 -2
  165. package/driver/registry-fidelity.mjs +3 -3
  166. package/driver/remedy-accounting.mjs +1 -1
  167. package/driver/repair-composers.mjs +2 -2
  168. package/driver/repair-digest.mjs +3 -3
  169. package/driver/repairs.mjs +6 -6
  170. package/driver/replay-archive.mjs +2 -0
  171. package/driver/report-card-record.mjs +2 -2
  172. package/driver/result-noun-fields.mjs +10 -3
  173. package/driver/run-economics.mjs +2 -2
  174. package/driver/run-integrity.mjs +1 -1
  175. package/driver/runner.mjs +22 -22
  176. package/driver/scope-rules.mjs +1 -1
  177. package/driver/search-policy.mjs +5 -5
  178. package/driver/skeptic-search.mjs +1 -1
  179. package/driver/skills/blind-frame/SKILL.md +2 -2
  180. package/driver/skills/case-law-citation/SKILL.md +2 -2
  181. package/driver/skills/knockout-assess/SKILL.md +94 -4
  182. package/driver/skills/matter-frame/SKILL.md +6 -6
  183. package/driver/skills/matter-frame/watchlist-reference.md +2 -2
  184. package/driver/skills/prelim-common-law/SKILL.md +1 -1
  185. package/driver/skills/prelim-search/SKILL.md +3 -3
  186. package/driver/skills/prelim-search/report-prose.md +82 -0
  187. package/driver/skills/prelim-search/risk-framework-demo.manifest.json +1 -1
  188. package/driver/skills/prelim-search/risk-framework-triage.manifest.json +1 -1
  189. package/driver/skills/prelim-search/risk-framework.manifest.json +1 -1
  190. package/driver/skills/prelim-search/synthesis-rules.md +1 -1
  191. package/driver/skills/prelim-search/template-formatting.md +1 -1
  192. package/driver/skills/prelim-search/templates/email/generic.md +1 -1
  193. package/driver/skills/prelim-search/worked-examples.md +1 -1
  194. package/driver/skills/prelim-variants/SKILL.md +5 -5
  195. package/driver/stage-context.mjs +1 -1
  196. package/driver/stages-knockout.mjs +55 -4
  197. package/driver/stages.mjs +101 -44
  198. package/driver/stray-artifacts.mjs +2 -2
  199. package/driver/suite-census.json +275 -65
  200. package/driver/synthesis-record.mjs +1 -1
  201. package/driver/systemd/clearotron-client-mcp.service +1 -1
  202. package/driver/systemd/clearotron-portal.service +1 -1
  203. package/driver/systemd/render-units.mjs +1 -1
  204. package/driver/tokens.mjs +1 -1
  205. package/driver/tool-calls.mjs +1 -1
  206. package/driver/turnaround-bands.mjs +1 -1
  207. package/driver/unit-file-drift.mjs +1 -1
  208. package/driver/unit-inventory.mjs +297 -80
  209. package/driver/unit-state-verdict.mjs +20 -12
  210. package/driver/verify-knockout.mjs +10 -2
  211. package/driver/verify.mjs +13 -13
  212. package/driver/whatif-memo-run.mjs +72 -9
  213. package/driver/whatif-memo.mjs +19 -1
  214. package/driver/whatif-queue.mjs +1 -1
  215. package/driver/whatif-worker.mjs +1 -1
  216. package/examples/README.md +2 -2
  217. package/examples/grants.example.json +6 -7
  218. package/mcp-server/CHANGELOG.md +6 -0
  219. package/mcp-server/README.md +3 -3
  220. package/mcp-server/http-server.mjs +44 -1
  221. package/mcp-server/key-socket.mjs +184 -0
  222. package/mcp-server/lib/audit-view.mjs +69 -2
  223. package/mcp-server/lib/brief.mjs +15 -0
  224. package/mcp-server/lib/driver.mjs +7 -1
  225. package/mcp-server/lib/events.mjs +1 -1
  226. package/mcp-server/lib/http-handler.mjs +1 -1
  227. package/mcp-server/lib/knockout.mjs +435 -0
  228. package/mcp-server/lib/ops.mjs +4 -4
  229. package/mcp-server/lib/options.mjs +1 -1
  230. package/mcp-server/lib/plan.mjs +1 -1
  231. package/mcp-server/lib/runs.mjs +1 -1
  232. package/mcp-server/lib/scrub.mjs +2 -2
  233. package/mcp-server/lib/whatif.mjs +5 -5
  234. package/mcp-server/mint-token.mjs +1 -1
  235. package/mcp-server/package.json +2 -2
  236. package/mcp-server/packs/ops/EXAMPLES.md +2 -2
  237. package/mcp-server/server.mjs +77 -12
  238. package/package.json +30 -12
  239. package/portal-ui/dist/assets/{index-Ct3iQtZ2.css → index-1ziUJX1E.css} +43 -2
  240. package/portal-ui/dist/assets/{index-BUGgiYtF.js → index-CEYvXdqH.js} +226 -49
  241. package/portal-ui/dist/index.html +2 -2
  242. package/portal-ui/package.json +1 -1
  243. package/providers/_shared/enumerate.mjs +1 -1
  244. package/providers/_shared/ledger-path.mjs +3 -3
  245. package/providers/_shared/ledger.mjs +1 -1
  246. package/providers/_shared/result-shape.mjs +3 -3
  247. package/providers/_shared/term-shape.mjs +2 -2
  248. package/providers/corsearch/src/core.js +1 -1
  249. package/providers/jx-subclass/BUILDING.md +1 -1
  250. package/providers/oauth-mcp-bridge/CHANGELOG.md +6 -0
  251. package/providers/oauth-mcp-bridge/package.json +1 -1
  252. package/providers/oauth-mcp-bridge/stdin-guard.mjs +2 -2
  253. package/providers/uspto-local/src/index-store.js +2 -2
  254. package/scripts/README.md +1 -1
  255. package/scripts/added-reference-check.mjs +29 -1
  256. package/scripts/authority-boundary-probe.mjs +1 -1
  257. package/scripts/backfill-started-at.mjs +1 -1
  258. package/scripts/citation-line-check.mjs +124 -5
  259. package/scripts/compare.mjs +2 -2
  260. package/scripts/contract-dictation-scan.mjs +2 -2
  261. package/scripts/dead-names.mjs +1 -1
  262. package/scripts/drain-preflight.mjs +5 -5
  263. package/scripts/e2e-unread-terminals.mjs +1 -1
  264. package/scripts/e2e.mjs +8 -8
  265. package/scripts/env-audit.mjs +7 -7
  266. package/scripts/env-classify.mjs +206 -18
  267. package/scripts/freeze-example-run.mjs +3 -3
  268. package/scripts/head-arrived-gated.mjs +1 -1
  269. package/scripts/headless-page.mjs +51 -2
  270. package/scripts/live-surface-check.mjs +129 -19
  271. package/scripts/main-health.mjs +1 -1
  272. package/scripts/merge-presence-check.mjs +3 -3
  273. package/scripts/mint-suite-census.mjs +6 -6
  274. package/scripts/nightly-notice.mjs +1 -3
  275. package/scripts/preinstall-node-check.mjs +24 -0
  276. package/scripts/reconcile-runs.mjs +1 -1
  277. package/scripts/release-await-cut.mjs +6 -4
  278. package/scripts/release-version-pr-checks.mjs +1 -1
  279. package/scripts/release-version.mjs +2 -2
  280. package/scripts/render-check.mjs +66 -7
  281. package/scripts/report-frame-check.mjs +1 -1
  282. package/scripts/report-screenshot.mjs +1 -1
  283. package/scripts/revisit-render-check.mjs +1 -1
  284. package/scripts/score.mjs +4 -4
  285. package/scripts/strip-tracker-citations.mjs +139 -0
  286. package/scripts/test-run.mjs +19 -3
  287. package/scripts/third-party-notices.mjs +3 -3
  288. package/scripts/travelling-predicates.mjs +3 -3
  289. package/scripts/unexecuted-asserts.mjs +2 -2
  290. package/scripts/verify-publishable.mjs +2 -2
  291. package/scripts/write-up-form-census.mjs +1 -1
  292. package/shared/access-audience.mjs +1 -1
  293. package/shared/anon-overlay.mjs +3 -3
  294. package/shared/brand.mjs +13 -13
  295. package/shared/citation-scan.mjs +1 -1
  296. package/shared/client-door.mjs +7 -7
  297. package/shared/customer-store.mjs +1 -1
  298. package/shared/driver-dir.mjs +1 -1
  299. package/shared/env-aliases.mjs +0 -48
  300. package/shared/env-local.mjs +1 -1
  301. package/shared/identifier-scan.mjs +3 -3
  302. package/shared/invocation.mjs +29 -1
  303. package/shared/names-in-force.mjs +4 -0
  304. package/shared/node-floor.mjs +97 -0
  305. package/shared/product-owned-names.mjs +1 -1
  306. package/shared/register-selection.mjs +1 -1
  307. package/shared/scope.mjs +5 -5
  308. package/shared/server-units.mjs +4 -4
  309. package/shared/staff-domain.mjs +154 -0
  310. package/shared/store-in-repo.mjs +25 -4
  311. package/shared/suite-census.mjs +4 -4
  312. package/shared/tty-style.mjs +1 -1
  313. package/shared/uspto-index-size.mjs +1 -1
  314. package/shared/vacuous-pass.mjs +1 -1
  315. package/skills/clearotron-account/SKILL.md +42 -13
  316. package/skills/clearotron-ops/SKILL.md +1 -1
  317. package/driver/recipes/README.md +0 -49
  318. package/driver/skills/prelim-search/risk-framework-aurora.manifest.json +0 -19
  319. package/driver/skills/prelim-search/risk-framework-aurora.md +0 -77
  320. package/driver/skills/prelim-search/risk-framework-zephyr.manifest.json +0 -14
  321. package/driver/skills/prelim-search/risk-framework-zephyr.md +0 -33
  322. package/driver/skills/prelim-search/worked-examples-aurora.md +0 -10
  323. package/driver/skills/prelim-search/worked-examples-zephyr.md +0 -10
  324. package/driver/systemd/prelim-driver.path +0 -69
  325. package/driver/systemd/prelim-driver.service +0 -86
  326. package/driver/systemd/prelim-driver.timer +0 -14
  327. package/driver/systemd/prelim-outbox.path +0 -27
  328. package/driver/systemd/prelim-outbox.service +0 -37
  329. package/driver/systemd/prelim-outbox.timer +0 -21
  330. package/node_modules/exceljs/README_zh.md +0 -2878
  331. package/node_modules/exceljs/dist/LICENSE +0 -22
  332. package/node_modules/exceljs/dist/es5/csv/csv.js +0 -182
  333. package/node_modules/exceljs/dist/es5/csv/csv.js.map +0 -1
  334. package/node_modules/exceljs/dist/es5/csv/line-buffer.js +0 -68
  335. package/node_modules/exceljs/dist/es5/csv/line-buffer.js.map +0 -1
  336. package/node_modules/exceljs/dist/es5/csv/stream-converter.js +0 -110
  337. package/node_modules/exceljs/dist/es5/csv/stream-converter.js.map +0 -1
  338. package/node_modules/exceljs/dist/es5/doc/anchor.js +0 -73
  339. package/node_modules/exceljs/dist/es5/doc/anchor.js.map +0 -1
  340. package/node_modules/exceljs/dist/es5/doc/cell.js +0 -961
  341. package/node_modules/exceljs/dist/es5/doc/cell.js.map +0 -1
  342. package/node_modules/exceljs/dist/es5/doc/column.js +0 -274
  343. package/node_modules/exceljs/dist/es5/doc/column.js.map +0 -1
  344. package/node_modules/exceljs/dist/es5/doc/data-validations.js +0 -18
  345. package/node_modules/exceljs/dist/es5/doc/data-validations.js.map +0 -1
  346. package/node_modules/exceljs/dist/es5/doc/defined-names.js +0 -173
  347. package/node_modules/exceljs/dist/es5/doc/defined-names.js.map +0 -1
  348. package/node_modules/exceljs/dist/es5/doc/enums.js +0 -49
  349. package/node_modules/exceljs/dist/es5/doc/enums.js.map +0 -1
  350. package/node_modules/exceljs/dist/es5/doc/image.js +0 -69
  351. package/node_modules/exceljs/dist/es5/doc/image.js.map +0 -1
  352. package/node_modules/exceljs/dist/es5/doc/modelcontainer.js +0 -16
  353. package/node_modules/exceljs/dist/es5/doc/modelcontainer.js.map +0 -1
  354. package/node_modules/exceljs/dist/es5/doc/note.js +0 -64
  355. package/node_modules/exceljs/dist/es5/doc/note.js.map +0 -1
  356. package/node_modules/exceljs/dist/es5/doc/range.js +0 -229
  357. package/node_modules/exceljs/dist/es5/doc/range.js.map +0 -1
  358. package/node_modules/exceljs/dist/es5/doc/row.js +0 -382
  359. package/node_modules/exceljs/dist/es5/doc/row.js.map +0 -1
  360. package/node_modules/exceljs/dist/es5/doc/table.js +0 -443
  361. package/node_modules/exceljs/dist/es5/doc/table.js.map +0 -1
  362. package/node_modules/exceljs/dist/es5/doc/workbook.js +0 -202
  363. package/node_modules/exceljs/dist/es5/doc/workbook.js.map +0 -1
  364. package/node_modules/exceljs/dist/es5/doc/worksheet.js +0 -900
  365. package/node_modules/exceljs/dist/es5/doc/worksheet.js.map +0 -1
  366. package/node_modules/exceljs/dist/es5/exceljs.bare.js +0 -14
  367. package/node_modules/exceljs/dist/es5/exceljs.bare.js.map +0 -1
  368. package/node_modules/exceljs/dist/es5/exceljs.browser.js +0 -36
  369. package/node_modules/exceljs/dist/es5/exceljs.browser.js.map +0 -1
  370. package/node_modules/exceljs/dist/es5/exceljs.nodejs.js +0 -15
  371. package/node_modules/exceljs/dist/es5/exceljs.nodejs.js.map +0 -1
  372. package/node_modules/exceljs/dist/es5/index.js +0 -15
  373. package/node_modules/exceljs/dist/es5/stream/xlsx/hyperlink-reader.js +0 -90
  374. package/node_modules/exceljs/dist/es5/stream/xlsx/hyperlink-reader.js.map +0 -1
  375. package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-comments-writer.js +0 -94
  376. package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-comments-writer.js.map +0 -1
  377. package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-rels-writer.js +0 -94
  378. package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-rels-writer.js.map +0 -1
  379. package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-reader.js +0 -362
  380. package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-reader.js.map +0 -1
  381. package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-writer.js +0 -347
  382. package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-writer.js.map +0 -1
  383. package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-reader.js +0 -392
  384. package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-reader.js.map +0 -1
  385. package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-writer.js +0 -652
  386. package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-writer.js.map +0 -1
  387. package/node_modules/exceljs/dist/es5/utils/auto-drain.js +0 -18
  388. package/node_modules/exceljs/dist/es5/utils/auto-drain.js.map +0 -1
  389. package/node_modules/exceljs/dist/es5/utils/browser-buffer-decode.js +0 -15
  390. package/node_modules/exceljs/dist/es5/utils/browser-buffer-decode.js.map +0 -1
  391. package/node_modules/exceljs/dist/es5/utils/browser-buffer-encode.js +0 -18
  392. package/node_modules/exceljs/dist/es5/utils/browser-buffer-encode.js.map +0 -1
  393. package/node_modules/exceljs/dist/es5/utils/cell-matrix.js +0 -149
  394. package/node_modules/exceljs/dist/es5/utils/cell-matrix.js.map +0 -1
  395. package/node_modules/exceljs/dist/es5/utils/col-cache.js +0 -258
  396. package/node_modules/exceljs/dist/es5/utils/col-cache.js.map +0 -1
  397. package/node_modules/exceljs/dist/es5/utils/copy-style.js +0 -43
  398. package/node_modules/exceljs/dist/es5/utils/copy-style.js.map +0 -1
  399. package/node_modules/exceljs/dist/es5/utils/encryptor.js +0 -58
  400. package/node_modules/exceljs/dist/es5/utils/encryptor.js.map +0 -1
  401. package/node_modules/exceljs/dist/es5/utils/iterate-stream.js +0 -46
  402. package/node_modules/exceljs/dist/es5/utils/iterate-stream.js.map +0 -1
  403. package/node_modules/exceljs/dist/es5/utils/parse-sax.js +0 -47
  404. package/node_modules/exceljs/dist/es5/utils/parse-sax.js.map +0 -1
  405. package/node_modules/exceljs/dist/es5/utils/shared-formula.js +0 -42
  406. package/node_modules/exceljs/dist/es5/utils/shared-formula.js.map +0 -1
  407. package/node_modules/exceljs/dist/es5/utils/shared-strings.js +0 -32
  408. package/node_modules/exceljs/dist/es5/utils/shared-strings.js.map +0 -1
  409. package/node_modules/exceljs/dist/es5/utils/stream-base64.js +0 -66
  410. package/node_modules/exceljs/dist/es5/utils/stream-base64.js.map +0 -1
  411. package/node_modules/exceljs/dist/es5/utils/stream-buf.js +0 -343
  412. package/node_modules/exceljs/dist/es5/utils/stream-buf.js.map +0 -1
  413. package/node_modules/exceljs/dist/es5/utils/string-buf.js +0 -73
  414. package/node_modules/exceljs/dist/es5/utils/string-buf.js.map +0 -1
  415. package/node_modules/exceljs/dist/es5/utils/string-builder.js +0 -32
  416. package/node_modules/exceljs/dist/es5/utils/string-builder.js.map +0 -1
  417. package/node_modules/exceljs/dist/es5/utils/stuttered-pipe.js +0 -61
  418. package/node_modules/exceljs/dist/es5/utils/stuttered-pipe.js.map +0 -1
  419. package/node_modules/exceljs/dist/es5/utils/typed-stack.js +0 -23
  420. package/node_modules/exceljs/dist/es5/utils/typed-stack.js.map +0 -1
  421. package/node_modules/exceljs/dist/es5/utils/under-dash.js +0 -168
  422. package/node_modules/exceljs/dist/es5/utils/under-dash.js.map +0 -1
  423. package/node_modules/exceljs/dist/es5/utils/utils.js +0 -171
  424. package/node_modules/exceljs/dist/es5/utils/utils.js.map +0 -1
  425. package/node_modules/exceljs/dist/es5/utils/xml-stream.js +0 -151
  426. package/node_modules/exceljs/dist/es5/utils/xml-stream.js.map +0 -1
  427. package/node_modules/exceljs/dist/es5/utils/zip-stream.js +0 -79
  428. package/node_modules/exceljs/dist/es5/utils/zip-stream.js.map +0 -1
  429. package/node_modules/exceljs/dist/es5/xlsx/defaultnumformats.js +0 -230
  430. package/node_modules/exceljs/dist/es5/xlsx/defaultnumformats.js.map +0 -1
  431. package/node_modules/exceljs/dist/es5/xlsx/rel-type.js +0 -18
  432. package/node_modules/exceljs/dist/es5/xlsx/rel-type.js.map +0 -1
  433. package/node_modules/exceljs/dist/es5/xlsx/xform/base-xform.js +0 -139
  434. package/node_modules/exceljs/dist/es5/xlsx/xform/base-xform.js.map +0 -1
  435. package/node_modules/exceljs/dist/es5/xlsx/xform/book/defined-name-xform.js +0 -85
  436. package/node_modules/exceljs/dist/es5/xlsx/xform/book/defined-name-xform.js.map +0 -1
  437. package/node_modules/exceljs/dist/es5/xlsx/xform/book/sheet-xform.js +0 -32
  438. package/node_modules/exceljs/dist/es5/xlsx/xform/book/sheet-xform.js.map +0 -1
  439. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-calc-properties-xform.js +0 -24
  440. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-calc-properties-xform.js.map +0 -1
  441. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-properties-xform.js +0 -27
  442. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-properties-xform.js.map +0 -1
  443. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-view-xform.js +0 -51
  444. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-view-xform.js.map +0 -1
  445. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-xform.js +0 -234
  446. package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-xform.js.map +0 -1
  447. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comment-xform.js +0 -103
  448. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comment-xform.js.map +0 -1
  449. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comments-xform.js +0 -76
  450. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comments-xform.js.map +0 -1
  451. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-position-xform.js +0 -35
  452. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-position-xform.js.map +0 -1
  453. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-protection-xform.js +0 -32
  454. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-protection-xform.js.map +0 -1
  455. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-anchor-xform.js +0 -53
  456. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-anchor-xform.js.map +0 -1
  457. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-client-data-xform.js +0 -97
  458. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-client-data-xform.js.map +0 -1
  459. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-notes-xform.js +0 -107
  460. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-notes-xform.js.map +0 -1
  461. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-shape-xform.js +0 -92
  462. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-shape-xform.js.map +0 -1
  463. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-textbox-xform.js +0 -61
  464. package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-textbox-xform.js.map +0 -1
  465. package/node_modules/exceljs/dist/es5/xlsx/xform/composite-xform.js +0 -51
  466. package/node_modules/exceljs/dist/es5/xlsx/xform/composite-xform.js.map +0 -1
  467. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-heading-pairs-xform.js +0 -30
  468. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-heading-pairs-xform.js.map +0 -1
  469. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-titles-of-parts-xform.js +0 -27
  470. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-titles-of-parts-xform.js.map +0 -1
  471. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-xform.js +0 -93
  472. package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-xform.js.map +0 -1
  473. package/node_modules/exceljs/dist/es5/xlsx/xform/core/content-types-xform.js +0 -112
  474. package/node_modules/exceljs/dist/es5/xlsx/xform/core/content-types-xform.js.map +0 -1
  475. package/node_modules/exceljs/dist/es5/xlsx/xform/core/core-xform.js +0 -158
  476. package/node_modules/exceljs/dist/es5/xlsx/xform/core/core-xform.js.map +0 -1
  477. package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationship-xform.js +0 -23
  478. package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationship-xform.js.map +0 -1
  479. package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationships-xform.js +0 -65
  480. package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationships-xform.js.map +0 -1
  481. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/base-cell-anchor-xform.js +0 -47
  482. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/base-cell-anchor-xform.js.map +0 -1
  483. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-fill-xform.js +0 -61
  484. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-fill-xform.js.map +0 -1
  485. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-xform.js +0 -40
  486. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-xform.js.map +0 -1
  487. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pic-pr-xform.js +0 -35
  488. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pic-pr-xform.js.map +0 -1
  489. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pr-xform.js +0 -62
  490. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pr-xform.js.map +0 -1
  491. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/cell-position-xform.js +0 -82
  492. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/cell-position-xform.js.map +0 -1
  493. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/drawing-xform.js +0 -98
  494. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/drawing-xform.js.map +0 -1
  495. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-lst-xform.js +0 -40
  496. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-lst-xform.js.map +0 -1
  497. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-xform.js +0 -38
  498. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-xform.js.map +0 -1
  499. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/hlink-click-xform.js +0 -38
  500. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/hlink-click-xform.js.map +0 -1
  501. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/nv-pic-pr-xform.js +0 -59
  502. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/nv-pic-pr-xform.js.map +0 -1
  503. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/one-cell-anchor-xform.js +0 -63
  504. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/one-cell-anchor-xform.js.map +0 -1
  505. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/pic-xform.js +0 -67
  506. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/pic-xform.js.map +0 -1
  507. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/sp-pr.js +0 -30
  508. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/sp-pr.js.map +0 -1
  509. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/two-cell-anchor-xform.js +0 -62
  510. package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/two-cell-anchor-xform.js.map +0 -1
  511. package/node_modules/exceljs/dist/es5/xlsx/xform/list-xform.js +0 -91
  512. package/node_modules/exceljs/dist/es5/xlsx/xform/list-xform.js.map +0 -1
  513. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/auto-filter-xform.js +0 -40
  514. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/auto-filter-xform.js.map +0 -1
  515. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cell-xform.js +0 -451
  516. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cell-xform.js.map +0 -1
  517. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cf-rule-xform.js +0 -275
  518. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cf-rule-xform.js.map +0 -1
  519. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cfvo-xform.js +0 -25
  520. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cfvo-xform.js.map +0 -1
  521. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/color-scale-xform.js +0 -38
  522. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/color-scale-xform.js.map +0 -1
  523. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formatting-xform.js +0 -45
  524. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formatting-xform.js.map +0 -1
  525. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formattings-xform.js +0 -77
  526. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formattings-xform.js.map +0 -1
  527. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/databar-xform.js +0 -42
  528. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/databar-xform.js.map +0 -1
  529. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/ext-lst-ref-xform.js +0 -71
  530. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/ext-lst-ref-xform.js.map +0 -1
  531. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/formula-xform.js +0 -22
  532. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/formula-xform.js.map +0 -1
  533. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/icon-set-xform.js +0 -43
  534. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/icon-set-xform.js.map +0 -1
  535. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js +0 -28
  536. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js.map +0 -1
  537. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +0 -88
  538. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js.map +0 -1
  539. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js +0 -38
  540. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js.map +0 -1
  541. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js +0 -52
  542. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js.map +0 -1
  543. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js +0 -43
  544. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js.map +0 -1
  545. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/databar-ext-xform.js +0 -75
  546. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/databar-ext-xform.js.map +0 -1
  547. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/f-ext-xform.js +0 -22
  548. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/f-ext-xform.js.map +0 -1
  549. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js +0 -66
  550. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js.map +0 -1
  551. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js +0 -22
  552. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js.map +0 -1
  553. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/col-xform.js +0 -78
  554. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/col-xform.js.map +0 -1
  555. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/data-validations-xform.js +0 -247
  556. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/data-validations-xform.js.map +0 -1
  557. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/dimension-xform.js +0 -28
  558. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/dimension-xform.js.map +0 -1
  559. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/drawing-xform.js +0 -32
  560. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/drawing-xform.js.map +0 -1
  561. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/ext-lst-xform.js +0 -69
  562. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/ext-lst-xform.js.map +0 -1
  563. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/header-footer-xform.js +0 -126
  564. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/header-footer-xform.js.map +0 -1
  565. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/hyperlink-xform.js +0 -50
  566. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/hyperlink-xform.js.map +0 -1
  567. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merge-cell-xform.js +0 -26
  568. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merge-cell-xform.js.map +0 -1
  569. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merges.js +0 -52
  570. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merges.js.map +0 -1
  571. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/outline-properties-xform.js +0 -35
  572. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/outline-properties-xform.js.map +0 -1
  573. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-breaks-xform.js +0 -24
  574. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-breaks-xform.js.map +0 -1
  575. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-margins-xform.js +0 -46
  576. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-margins-xform.js.map +0 -1
  577. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-properties-xform.js +0 -32
  578. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-properties-xform.js.map +0 -1
  579. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-xform.js +0 -99
  580. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-xform.js.map +0 -1
  581. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/picture-xform.js +0 -32
  582. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/picture-xform.js.map +0 -1
  583. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/print-options-xform.js +0 -45
  584. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/print-options-xform.js.map +0 -1
  585. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-breaks-xform.js +0 -37
  586. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-breaks-xform.js.map +0 -1
  587. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-xform.js +0 -128
  588. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-xform.js.map +0 -1
  589. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-format-properties-xform.js +0 -51
  590. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-format-properties-xform.js.map +0 -1
  591. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-properties-xform.js +0 -83
  592. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-properties-xform.js.map +0 -1
  593. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-protection-xform.js +0 -84
  594. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-protection-xform.js.map +0 -1
  595. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-view-xform.js +0 -190
  596. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-view-xform.js.map +0 -1
  597. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/table-part-xform.js +0 -32
  598. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/table-part-xform.js.map +0 -1
  599. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/worksheet-xform.js +0 -513
  600. package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/worksheet-xform.js.map +0 -1
  601. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/boolean-xform.js +0 -27
  602. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/boolean-xform.js.map +0 -1
  603. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/date-xform.js +0 -58
  604. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/date-xform.js.map +0 -1
  605. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/float-xform.js +0 -47
  606. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/float-xform.js.map +0 -1
  607. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/integer-xform.js +0 -53
  608. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/integer-xform.js.map +0 -1
  609. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/string-xform.js +0 -47
  610. package/node_modules/exceljs/dist/es5/xlsx/xform/simple/string-xform.js.map +0 -1
  611. package/node_modules/exceljs/dist/es5/xlsx/xform/static-xform.js +0 -61
  612. package/node_modules/exceljs/dist/es5/xlsx/xform/static-xform.js.map +0 -1
  613. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/phonetic-text-xform.js +0 -98
  614. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/phonetic-text-xform.js.map +0 -1
  615. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/rich-text-xform.js +0 -92
  616. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/rich-text-xform.js.map +0 -1
  617. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-string-xform.js +0 -99
  618. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-string-xform.js.map +0 -1
  619. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-strings-xform.js +0 -114
  620. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-strings-xform.js.map +0 -1
  621. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/text-xform.js +0 -39
  622. package/node_modules/exceljs/dist/es5/xlsx/xform/strings/text-xform.js.map +0 -1
  623. package/node_modules/exceljs/dist/es5/xlsx/xform/style/alignment-xform.js +0 -139
  624. package/node_modules/exceljs/dist/es5/xlsx/xform/style/alignment-xform.js.map +0 -1
  625. package/node_modules/exceljs/dist/es5/xlsx/xform/style/border-xform.js +0 -185
  626. package/node_modules/exceljs/dist/es5/xlsx/xform/style/border-xform.js.map +0 -1
  627. package/node_modules/exceljs/dist/es5/xlsx/xform/style/color-xform.js +0 -66
  628. package/node_modules/exceljs/dist/es5/xlsx/xform/style/color-xform.js.map +0 -1
  629. package/node_modules/exceljs/dist/es5/xlsx/xform/style/dxf-xform.js +0 -106
  630. package/node_modules/exceljs/dist/es5/xlsx/xform/style/dxf-xform.js.map +0 -1
  631. package/node_modules/exceljs/dist/es5/xlsx/xform/style/fill-xform.js +0 -308
  632. package/node_modules/exceljs/dist/es5/xlsx/xform/style/fill-xform.js.map +0 -1
  633. package/node_modules/exceljs/dist/es5/xlsx/xform/style/font-xform.js +0 -175
  634. package/node_modules/exceljs/dist/es5/xlsx/xform/style/font-xform.js.map +0 -1
  635. package/node_modules/exceljs/dist/es5/xlsx/xform/style/numfmt-xform.js +0 -59
  636. package/node_modules/exceljs/dist/es5/xlsx/xform/style/numfmt-xform.js.map +0 -1
  637. package/node_modules/exceljs/dist/es5/xlsx/xform/style/protection-xform.js +0 -53
  638. package/node_modules/exceljs/dist/es5/xlsx/xform/style/protection-xform.js.map +0 -1
  639. package/node_modules/exceljs/dist/es5/xlsx/xform/style/style-xform.js +0 -118
  640. package/node_modules/exceljs/dist/es5/xlsx/xform/style/style-xform.js.map +0 -1
  641. package/node_modules/exceljs/dist/es5/xlsx/xform/style/styles-xform.js +0 -612
  642. package/node_modules/exceljs/dist/es5/xlsx/xform/style/styles-xform.js.map +0 -1
  643. package/node_modules/exceljs/dist/es5/xlsx/xform/style/underline-xform.js +0 -46
  644. package/node_modules/exceljs/dist/es5/xlsx/xform/style/underline-xform.js.map +0 -1
  645. package/node_modules/exceljs/dist/es5/xlsx/xform/table/auto-filter-xform.js +0 -75
  646. package/node_modules/exceljs/dist/es5/xlsx/xform/table/auto-filter-xform.js.map +0 -1
  647. package/node_modules/exceljs/dist/es5/xlsx/xform/table/custom-filter-xform.js +0 -30
  648. package/node_modules/exceljs/dist/es5/xlsx/xform/table/custom-filter-xform.js.map +0 -1
  649. package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-column-xform.js +0 -89
  650. package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-column-xform.js.map +0 -1
  651. package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-xform.js +0 -28
  652. package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-xform.js.map +0 -1
  653. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-column-xform.js +0 -42
  654. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-column-xform.js.map +0 -1
  655. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-style-info-xform.js +0 -40
  656. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-style-info-xform.js.map +0 -1
  657. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-xform.js +0 -123
  658. package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-xform.js.map +0 -1
  659. package/node_modules/exceljs/dist/es5/xlsx/xlsx.js +0 -697
  660. package/node_modules/exceljs/dist/es5/xlsx/xlsx.js.map +0 -1
  661. package/node_modules/exceljs/dist/es5/xlsx/xml/theme1.js +0 -5
  662. package/node_modules/exceljs/dist/es5/xlsx/xml/theme1.js.map +0 -1
  663. package/node_modules/exceljs/dist/exceljs.bare.js +0 -55253
  664. package/node_modules/exceljs/dist/exceljs.bare.js.map +0 -761
  665. package/node_modules/exceljs/dist/exceljs.bare.min.js +0 -45
  666. package/node_modules/exceljs/dist/exceljs.bare.min.js.map +0 -1
  667. package/node_modules/exceljs/dist/exceljs.js +0 -59900
  668. package/node_modules/exceljs/dist/exceljs.js.map +0 -1083
  669. package/node_modules/exceljs/dist/exceljs.min.js +0 -45
  670. package/node_modules/exceljs/dist/exceljs.min.js.map +0 -1
  671. package/scripts/ai-page-render-check.mjs +0 -532
  672. package/scripts/clearances-render-check.mjs +0 -480
  673. package/scripts/composer-render-check.mjs +0 -1027
  674. package/scripts/deploy-test.sh +0 -309
  675. package/scripts/home-render-check.mjs +0 -526
  676. package/scripts/portal-lifecycle-check.mjs +0 -639
@@ -23,6 +23,11 @@
23
23
  // | recipe-service | — | — | yes | yes |
24
24
  // | portal-service | — | — | yes | NO |
25
25
  //
26
+ // THAT TABLE IS THE 2026-08-11 READING AND IS NOT REFRESHED. Two of its rows name units that no longer
27
+ // exist: `prelim-driver` and `prelim-outbox` were retired with the path-watcher drain posture and their
28
+ // files left the tree once production was rebuilt. They stay in the table because it records what was
29
+ // measured on that date, and a measurement edited to match today is no longer a measurement.
30
+ //
26
31
  // TWO CORRECTIONS TO THE ISSUE ARE BAKED INTO THIS TABLE, and one of them inverts a fix. lists
27
32
  // `profile-service` and `prelim-outbox` under "tracked and never run". That reading comes from the test
28
33
  // box, where neither is installed. PRODUCTION RUNS BOTH — so deleting their tracked files as dead
@@ -52,7 +57,7 @@
52
57
  // each was already in the tree, in `mcp-server/remote/`. The repo's own governance doc names BOTH
53
58
  // directories (`docs/architecture/05-config-governance.md`, tier 2); the guard named one.
54
59
  //
55
- // That is the same defect one layer up from the one this file was built to fix. 's inline array made
60
+ // That is the same defect one layer up from the one this file was built to fix. That inline array made
56
61
  // a unit's membership of the guarantee an omission; the hardcoded directory made a FILE's membership an
57
62
  // omission, and the result was three statements of fact that were false with nothing able to contradict
58
63
  // them. The tracked-file lookup is now a repo-wide walk (driver/unit-files.mjs), and `unitInventoryVerdict`
@@ -70,7 +75,7 @@
70
75
  /** Where a unit is expected to be installed. "none" is a claim, not an absence — see ORPHANED below. */
71
76
  export const BOXES = Object.freeze(["prod", "test", "dev"]);
72
77
 
73
- // ── RESOLVED UNITS (, owner ruling 2026-08-25 — option B) ──────────────────────
78
+ // ── RESOLVED UNITS (owner ruling 2026-08-25 — option B) ──────────────────────
74
79
  //
75
80
  // `resolved: [...]` names tracked files the INSTALLER rewrites before installing. Three units carry
76
81
  // `@NAME@` placeholders because configuration cannot reach them: a `.path` unit reads no environment at
@@ -98,6 +103,13 @@ export const BOXES = Object.freeze(["prod", "test", "dev"]);
98
103
  // 2026-08-26), so the rebuild is the event that releases the files, and until then entry and tree
99
104
  // disagree ON PURPOSE.
100
105
  //
106
+ // THE REBUILD HAPPENED, and the first two entries this field ever carried have gone with their files.
107
+ // Measured on the production install 2026-09-07 (tracker issue 265): seven units, all under the current
108
+ // names, none of the retired ones, with a clearance delivered end to end. `prelim-driver.*` and
109
+ // `prelim-outbox.*` left the tree in the same change that removed their entries. Read the paragraph
110
+ // above as the rule and this one as the event that discharged it — without this line a reader concludes
111
+ // the files are still owed and that their absence is the drift.
112
+ //
101
113
  // Two consumers, so this is not prose: `unitInventoryVerdict` reports a retired unit's absence as
102
114
  // EXPECTED rather than as drift, and a claimed-but-missing tracked file is a fault whatever the
103
115
  // retirement says. That pair is what asks for — absent-and-expected-to-be told
@@ -110,40 +122,23 @@ export const UNIT_INVENTORY = Object.freeze([
110
122
  // rather than the day it first runs, because a unit file no entry claims is exactly what this file
111
123
  // exists to make impossible — and a mechanism that installs itself is the easiest kind to ship
112
124
  // undeclared.
113
- unit: "clearotron-deploy", runsOn: [],
125
+ unit: "clearotron-deploy", runsOn: ["test"],
126
+ measured: "2026-09-08, the test deployment: the timer and its service are installed for that deployment's own user, the timer is enabled and ACTIVE, and it last fired within the hour — `systemctl --user list-timers`. The service's own state says nothing about this: it is `inactive` between runs and `inactive` when the timer has been stopped. The timer's ActiveState is what says anything will start it again.",
114
127
  tracked: ["clearotron-deploy.service", "clearotron-deploy.timer"],
115
- note: "the install's own updater. Ships tracked, runs nowhere yet.",
116
- orphanReason: "SHIPPED AND PLACED ON NO BOX YET, which is a THIRD kind of orphan and not either of "
117
- + "the other two: courtlistener-mcp runs on production under another name, feedback-mint was "
118
- + "deliberately switched off, and this one has simply never been installed. `runsOn` gains "
119
- + "\"test\" the day a test deploy places it and \"prod\" when the owner asks for it. Until then it "
120
- + "stays out of CHECKED_UNITS, because asking systemd about a unit nobody installed produces a "
121
- + "\"not compared\" row that reads like a fault and is not one. It goes on with "
122
- + "`systemctl --user enable --now clearotron-deploy.timer` once bin/onboard.mjs has written both files.",
123
- },
124
- {
125
- unit: "prelim-driver", runsOn: ["prod", "test"],
126
- tracked: ["prelim-driver.service", "prelim-driver.path", "prelim-driver.timer"],
127
- resolved: ["prelim-driver.path"], // option B see RESOLVED below
128
- retired: {
129
- ruled: "2026-08-26, restated 2026-08-31",
130
- filesStayUntil: "prod",
131
- why: "the path-watcher/timer drain posture is retired (tracker issue 1863): the built-in worker "
132
- + "is the product's drain, and a hosted deployment gets ONE plain service unit invoking the "
133
- + "entrypoint directly rather than a oneshot woken by a timer and a queue glob. Absence on any "
134
- + "box is now the EXPECTED direction rather than drift. The replacement is deliberately not "
135
- + "named here — a pointer outlives the file it points at, which is why `supersedes:` was "
136
- + "removed from this file once already; the pinned background list is where the current drain "
137
- + "is stated, and it is code rather than prose.",
138
- },
139
- note: "the driver itself — the one unit the drift check has always been able to compare. "
140
- + "SETTLED (tracker issue 1888, measured on the owner's fresh production install 2026-08-31): "
141
- + "the documented install creates NO units at all — not even the unit directory — and a knockout "
142
- + "delivered end to end without them, so units are the hosted-deployment OPT-IN step, never the "
143
- + "install's output. Absent on a box is the install's normal state; present means someone ran the "
144
- + "hosted step there. `runsOn` lists exactly the boxes MEASURED to carry it, which is why absence "
145
- + "anywhere else is not drift — the earlier expectation that the .path unit ships with the install "
146
- + "was the wrong half of the disagreement.",
128
+ note: "the install's own updater. Placed on the test deployment, where it pulls hourly; production takes it when the owner asks.",
129
+ // IT WAS AN ORPHAN, AND THE CONDITION IT NAMED HAS BEEN MET. This entry carried an `orphanReason`
130
+ // saying it had been shipped and installed nowhere, and that `runsOn` would gain "test" the day a
131
+ // deploy placed it. It has: the timer is installed, enabled and firing, and `runsOn` says so. The prose
132
+ // stayed behind the field, which is the ordinary way a declaration and its explanation come apart
133
+ // and it matters more here than usual, because this entry is now what puts a real timer into the
134
+ // timer list. An entry describing itself as installed nowhere, whose timer the check asks systemd
135
+ // about by name, is a contradiction a reader has to resolve before trusting either half.
136
+ //
137
+ // AND THE POSTURE IS NOW STATED, because it is a change in what a red means rather than in code: a
138
+ // STOPPED deploy timer FAILS. The service reads `inactive` between runs and `inactive` when nothing
139
+ // will ever run it again, so the timer's own state is the only thing separating a deployment that
140
+ // tracks the main branch from one quietly frozen on whatever it last built. If the timer is ever
141
+ // held deliberately, a check that says so for as long as the hold lasts is the behaviour to want.
147
142
  },
148
143
  {
149
144
  // ── `tracked` WAS A CLAIM ABOUT A FILE THAT HAS NEVER EXISTED (tracker issue 175) ──────────────
@@ -153,10 +148,23 @@ export const UNIT_INVENTORY = Object.freeze([
153
148
  // `live-surface-check` FAILED on a healthy box — the worst kind of red, because it teaches a reader
154
149
  // to scroll past the check that would catch a unit genuinely gone missing.
155
150
  //
156
- // THE ROW STAYS, AND DELETING IT WOULD HAVE BEEN THE WRONG FIX. The unit is LIVE ON PRODUCTION, as
157
- // the note below has said all along. Removing the entry would make this inventory stop knowing about
158
- // something that is running — the same failure it exists to prevent, pointed the other way. What was
159
- // false is the `tracked` claim, not the unit.
151
+ // THE ROW STAYS, AND DELETING IT WOULD HAVE BEEN THE WRONG FIX. What was false then was the
152
+ // `tracked` claim, not the row. Removing the entry would make this inventory stop knowing about a
153
+ // unit it ships nothing for — the same failure it exists to prevent, pointed the other way.
154
+ //
155
+ // ── AND THE OTHER HALF OF THAT PARAGRAPH HAS NOW BEEN MEASURED FALSE TOO ───────────────────────
156
+ //
157
+ // It read "The unit is LIVE ON PRODUCTION, as the note below has said all along", and it had been
158
+ // said all along without ever being enumerated. Production was read on 2026-09-08 — every account
159
+ // on the machine, unit file names and enable state — and no unit of this name exists under any of
160
+ // them. An earlier reading the same day reached the same answer from the other direction while
161
+ // closing a different question.
162
+ //
163
+ // So `runsOn` is empty and the note says what was measured. This is a change to what this
164
+ // repository CLAIMS about production, made because a reading contradicted the claim, and not a
165
+ // statement that production should not run it — that is a deployment question and it is the
166
+ // owner's. If the answer is yes, `runsOn` gains "prod" in the change that deploys it, against a
167
+ // fresh enumeration, which is this file's own rule rather than an exception to it.
160
168
  //
161
169
  // Declared the way its siblings are: `tracked: null` with the reason, which this file's own header
162
170
  // calls the sanctioned way to say the repo does not carry one.
@@ -167,16 +175,31 @@ export const UNIT_INVENTORY = Object.freeze([
167
175
  // is a change which ADDS a file, measured against the deployed copy, and it is not this one. Two
168
176
  // prose references in driver/systemd/render-units.mjs also describe this file as though it were in
169
177
  // the tree; they are stale today either way.
170
- unit: "profile-service", runsOn: ["prod"], tracked: null,
178
+ unit: "profile-service", runsOn: [],
179
+ measured: "2026-09-08: production read by account — the deployment account carries six clearotron-* "
180
+ + "unit files and the doctrine-sync timer, the legacy account carries five units belonging to the "
181
+ + "other product plus unloadable residue, and no unit of THIS name is under either. Names and enable "
182
+ + "state only; no unit contents were read.",
183
+ tracked: null,
171
184
  untrackedReason: "the repository has never carried this file — `git log --all` on the path is empty. "
172
- + "It deploys from the production box's own copy, in the same CF Access template family as "
173
- + "trademark-portal and trademark-ops-mcp. Whether a placeholder should now ship is open: see above.",
185
+ + "It was described as deploying from a copy held on the deployment itself, in the same "
186
+ + "identity-provider template family as two other pre-rename names; the 2026-09-08 reading finds no "
187
+ + "such copy under any account, so that description is history rather than current state. Whether a "
188
+ + "placeholder should now ship is open: see above.",
174
189
  // NO LONGER RESOLVED AT INSTALL. It carried `@CLEAROTRON_CHECKOUT_DIR@` because
175
190
  // it loaded no EnvironmentFile and so had no `${VAR}` systemd could expand. The owner's one-config-
176
191
  // per-server-box ruling gives it `EnvironmentFile=%h/.env` like every other service, which makes the
177
192
  // checkout path an ordinary systemd expansion and leaves no placeholder to render.
178
- note: "LIVE ON PRODUCTION. #685's body lists it as never run; that is true of the test box only. "
179
- + "Was a TEMPLATE unit carrying CF Access values inline; generic since tracker issue 1925.",
193
+ note: "NOT RUNNING ANYWHERE, measured 2026-09-08. This row said LIVE ON PRODUCTION for as long as it "
194
+ + "existed and no enumeration ever supported it. Was a TEMPLATE unit carrying identity-provider "
195
+ + "values inline; generic since tracker issue 1925.",
196
+ orphanReason: "CLAIMED A DEPLOYMENT IT WAS NEVER MEASURED ON, which is a FOURTH kind of orphan and "
197
+ + "the only one that was ever a wrong claim rather than a waiting decision: the other three run "
198
+ + "under another name, were deliberately switched off, or have simply never been installed. This "
199
+ + "one was declared live and read as absent. The row is kept because the deployment question is "
200
+ + "open and belongs to the owner — whether production should run this service at all — and an "
201
+ + "inventory that deleted the row would lose the only place that question is written down. It "
202
+ + "gains a deployment the day an enumeration shows it, never the day someone intends it.",
180
203
  },
181
204
  {
182
205
  // RUNS ON NO BOX YET, AND THAT IS THE HONEST DECLARATION. `runsOn: ["prod"]` is a claim about a
@@ -185,7 +208,8 @@ export const UNIT_INVENTORY = Object.freeze([
185
208
  // say "the repo ships this, nothing runs it, and here is the decision it waits on" — orphans are
186
209
  // REPORTED, never a fault, for exactly this case. It becomes `["prod"]` in the change that DEPLOYS
187
210
  // it, against a fresh enumeration, which is the ratchet working rather than being edited around.
188
- unit: "clearotron-portal", runsOn: [], tracked: ["clearotron-portal.service"],
211
+ unit: "clearotron-portal", runsOn: ["test"], tracked: ["clearotron-portal.service"],
212
+ measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
189
213
  note: "NEW, tracker issue 1925, SHIPPED BUT NOT YET DEPLOYED. The portal had NO unit at all — it "
190
214
  + "and the MCP face are the two children bin/start.mjs supervises, and neither ran under systemd, "
191
215
  + "so a hosted deployment kept them alive with a hand launcher and `clearotron start` had nothing "
@@ -201,7 +225,8 @@ export const UNIT_INVENTORY = Object.freeze([
201
225
  {
202
226
  // Same as clearotron-portal above: shipped, running nowhere, declared as an orphan rather than
203
227
  // asserting a production state no enumeration has ever shown.
204
- unit: "clearotron-mcp-face", runsOn: [], tracked: ["clearotron-mcp-face.service"],
228
+ unit: "clearotron-mcp-face", runsOn: ["test"], tracked: ["clearotron-mcp-face.service"],
229
+ measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
205
230
  note: "NEW, tracker issue 1925, SHIPPED BUT NOT YET DEPLOYED. The engine door the portal calls over "
206
231
  + "MCP; the other of the two processes that had no unit.",
207
232
  orphanReason: "THE ENGINE DOOR THE PORTAL CALLS, shipped with no box carrying it yet. Same kind as "
@@ -218,7 +243,7 @@ export const UNIT_INVENTORY = Object.freeze([
218
243
  // are then enabled like anything else. This one is shipped and DELIBERATELY NOT INSTALLED BY ANY
219
244
  // INSTALL PATH — `clearotron start` neither installs nor starts it, and a rebuild must not either.
220
245
  //
221
- // ── IT INSTALLS WITH THE PRODUCT SINCE 2026-09-03 (, settled point 2) ────────
246
+ // ── IT INSTALLS WITH THE PRODUCT SINCE 2026-09-03 (settled point 2) ────────
222
247
  //
223
248
  // Until then it was an orphan BY DESIGN: `clearotron connect` installed and started it on demand,
224
249
  // because starting it turned on client-account access and a unit that came up with everything else
@@ -229,7 +254,8 @@ export const UNIT_INVENTORY = Object.freeze([
229
254
  // So it is now an orphan of the FIRST kind, awaiting a box, exactly like the portal and the engine
230
255
  // door beside it: it is in SERVER_INSTALL_SET, and it leaves this list on the day a measured
231
256
  // enumeration of a box shows it running.
232
- unit: "clearotron-client-mcp", runsOn: [], tracked: ["clearotron-client-mcp.service"],
257
+ unit: "clearotron-client-mcp", runsOn: ["test"], tracked: ["clearotron-client-mcp.service"],
258
+ measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
233
259
  note: "tracker issue 1976, and INSTALLED WITH THE PRODUCT since tracker issue 2148. The client door "
234
260
  + "— the one surface that accepts an account-scoped key, and a separate process from the engine "
235
261
  + "door, which refuses one outright.",
@@ -246,7 +272,8 @@ export const UNIT_INVENTORY = Object.freeze([
246
272
  // supervises the portal, the engine door and this worker; 1925 shipped units for the first two.
247
273
  // Written as part of retiring the path-watcher posture, because retiring `prelim-driver.*` without
248
274
  // it leaves a hosted box healthy-looking and draining nothing.
249
- unit: "clearotron-worker", runsOn: [], tracked: ["clearotron-worker.service"],
275
+ unit: "clearotron-worker", runsOn: ["test"], tracked: ["clearotron-worker.service"],
276
+ measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
250
277
  note: "NEW, tracker issue 1863. The drain, as one plain service unit invoking the entrypoint "
251
278
  + "directly (owner ruling 2026-08-31). Ships tracked, runs nowhere yet — production takes it at "
252
279
  + "its rebuild, which is the same event that lets the retired units' files leave the tree.",
@@ -256,21 +283,11 @@ export const UNIT_INVENTORY = Object.freeze([
256
283
  + "alternatives, and running both puts a second claimant on one queue.",
257
284
  },
258
285
  {
259
- unit: "prelim-outbox", runsOn: ["prod"],
260
- tracked: ["prelim-outbox.service", "prelim-outbox.path", "prelim-outbox.timer"],
261
- retired: {
262
- ruled: "2026-08-31",
263
- filesStayUntil: "prod",
264
- why: "the timer retires with the watcher it backstopped, by name in the ruling. That watcher also "
265
- + "carried the last dead OpenClaw literal in the tree. Channel delivery is the "
266
- + "integrator's (INSTALL.md §9), so retiring these takes away nothing the product promises — "
267
- + "the worked example moves into the document rather than being deleted with them.",
268
- },
269
- note: "LIVE ON PRODUCTION (path and timer active-waiting). Was absent from the health check's unit "
270
- + "list, so its drift was never checked despite being tracked.",
271
- },
272
- {
273
- unit: "trademark-portal", runsOn: ["prod", "test"], tracked: null,
286
+ unit: "trademark-portal", runsOn: [],
287
+ orphanReason: "THE PRE-RENAME PORTAL. The deployment account runs `clearotron-portal`; this name is "
288
+ + "what that service used to be called, and the 2026-09-08 reading finds no unit of this name under "
289
+ + "any account. It ran on production until the rename and the entry was never re-measured after it.",
290
+ measured: "2026-09-08: production read by account — the deployment account carries six clearotron-* unit files and the doctrine-sync timer, the legacy account carries five units of the other product plus unloadable residue, and no unit of THIS name is under either. Names and enable state only. This line previously carried a 2026-09-07 reading of the test deployment — LoadState=not-found there, with the production claim left alone because production had not been measured. It has been now, and this is that reading.", tracked: null,
274
291
  untrackedReason: "the deployed copy carries real Cloudflare Access team/AUD/domain values inline. "
275
292
  + "A tracked file would be the placeholder TEMPLATE, merged by hand after a "
276
293
  + "diff — writing one carelessly replaces working auth with placeholders that look configured.",
@@ -281,11 +298,19 @@ export const UNIT_INVENTORY = Object.freeze([
281
298
  supersededName: "portal-service.service (deleted, owner-ruled 2026-08-14)",
282
299
  },
283
300
  {
284
- unit: "trademark-ops-mcp", runsOn: ["prod", "test"], tracked: null,
301
+ unit: "trademark-ops-mcp", runsOn: [],
302
+ orphanReason: "THE PRE-RENAME OPERATOR DOOR. The deployment account runs `clearotron-mcp-face`; the "
303
+ + "2026-09-08 reading finds no unit of this name under any account. Same rename as the portal it "
304
+ + "serves, and the same claim carried across it unmeasured.",
305
+ measured: "2026-09-08: production read by account — the deployment account carries six clearotron-* unit files and the doctrine-sync timer, the legacy account carries five units of the other product plus unloadable residue, and no unit of THIS name is under either. Names and enable state only. This line previously carried a 2026-09-07 reading of the test deployment — LoadState=not-found there, with the production claim left alone because production had not been measured. It has been now, and this is that reading.", tracked: null,
285
306
  untrackedReason: "same CF Access inline-values shape as the portal it serves.",
286
307
  },
287
308
  {
288
- unit: "client-mcp", runsOn: ["prod", "test"], tracked: ["client-mcp.service"],
309
+ unit: "client-mcp", runsOn: [],
310
+ orphanReason: "THE PRE-RENAME CLIENT DOOR. `clearotron-client-mcp` runs on both the production and "
311
+ + "the test deployments; the 2026-09-08 reading finds no unit of THIS name under any account. The "
312
+ + "tracked template stays because the repository still ships it — see the note.",
313
+ measured: "2026-09-08: production read by account — the deployment account carries six clearotron-* unit files and the doctrine-sync timer, the legacy account carries five units of the other product plus unloadable residue, and no unit of THIS name is under either. Names and enable state only. This line previously carried a 2026-09-07 reading of the test deployment — LoadState=not-found there, with the production claim left alone because production had not been measured. It has been now, and this is that reading.", tracked: ["client-mcp.service"],
289
314
  note: "TRACKED, in mcp-server/remote/ — this entry said it had no file, and the file was there. It is "
290
315
  + "a banner-marked TEMPLATE, so the live copy differing from it is the arrangement, not drift. "
291
316
  + "#1147 ADDED THE TEST BOX (2026-08-18): the client surface ran nowhere but production, so the test "
@@ -296,18 +321,79 @@ export const UNIT_INVENTORY = Object.freeze([
296
321
  + "not the default.",
297
322
  },
298
323
  {
299
- unit: "client-mcp-apikey", runsOn: ["prod"], tracked: ["client-mcp-apikey.service"],
324
+ unit: "client-mcp-apikey", runsOn: ["test"],
325
+ measured: "2026-09-08, read by account: enabled and present on the TEST deployment, beside the "
326
+ + "renamed `clearotron-client-mcp`. Absent from production under any account. The entry declared "
327
+ + "production and the reading puts it on the other deployment — the claim was not stale, it named "
328
+ + "the wrong machine. Why it runs there at all beside the renamed door is a separate question.",
329
+ tracked: ["client-mcp-apikey.service"],
300
330
  note: "TRACKED, in mcp-server/remote/. Same correction as client-mcp: the old reason claimed the live "
301
331
  + "key made a tracked file impossible, and the tracked TEMPLATE — which holds no key — already existed.",
302
332
  },
303
333
  {
304
- unit: "trademark-artifacts-http", runsOn: ["prod"], tracked: ["trademark-artifacts-http.service"],
334
+ unit: "trademark-artifacts-http", runsOn: [],
335
+ orphanReason: "A PRE-RENAME NAME OF THE RETIRED DEPLOYMENT, and the one of them whose tracked file "
336
+ + "is GENERIC rather than a template — so the file is ready to be compared against a live copy the "
337
+ + "day something runs it, and nothing does. Read as absent under every account on 2026-09-08.",
338
+ measured: "2026-09-08: production read by account — no unit of this name is under the deployment account or the legacy one. Names and enable state only; no unit contents were read.", tracked: ["trademark-artifacts-http.service"],
305
339
  note: "TRACKED, in mcp-server/remote/. GENERIC, not a template: it carries no banner and no "
306
340
  + "placeholder, and defers its CF Access values to the EnvironmentFile — so its live copy is "
307
341
  + "expected to MATCH the tracked file, and a difference is real drift.",
308
342
  },
309
343
  {
310
- unit: "client-access", runsOn: ["prod"], tracked: null,
344
+ unit: "clearotron-mcp-local", runsOn: ["prod"], tracked: null,
345
+ untrackedReason: "the fifth hand-made door on production, on 18793, kept as it is by ruling while "
346
+ + "the product fix lands. Known and hand-made is not the same as declared: it was running on "
347
+ + "production and named by no inventory, no unit file and no line of code in this repo, so the "
348
+ + "health check could not see it and nothing would have said if it stopped. Declared here to end "
349
+ + "that, not to bless the arrangement.",
350
+ },
351
+ {
352
+ unit: "clearotron-doctrine-sync", runsOn: ["prod"], tracked: null,
353
+ // WHAT SYSTEMD KNOWS THIS UNIT AS, which `tracked` cannot say here. For a tracked unit the file
354
+ // list carries the suffixes — `clearotron-deploy` names its `.service` AND its `.timer` — so a
355
+ // reader deriving systemd queries from the entry gets both. An UNTRACKED unit ships no files, so
356
+ // `tracked: null` leaves nothing to derive from and the bare name silently means `.service`.
357
+ // Stated separately so the two questions stay apart: `tracked` is what this repo SHIPS,
358
+ // `systemdUnits` is what the box RUNS.
359
+ systemdUnits: ["clearotron-doctrine-sync.service", "clearotron-doctrine-sync.timer"],
360
+ // ── THE ONE WHOSE SILENCE REACHES A CLIENT ────────────────────────────────────────────────────
361
+ //
362
+ // This is the timer half of production's doctrine refresh. The stages read doctrine to decide what
363
+ // they do, so if it stops, production runs clearances against whatever doctrine last landed and NO
364
+ // SURFACE ANYWHERE SAYS SO — the client receives a report that looks exactly like a current one.
365
+ //
366
+ // That is a client-facing failure with no detector, which is what the drift check exists for, and
367
+ // the drift check could not see this unit because the unit was in no list.
368
+ //
369
+ // BEING IN THIS LIST IS NOT YET DETECTION, AND SAYING SO IS THE POINT OF THIS PARAGRAPH. Every name
370
+ // here is bare, and `systemctl show <bare>` answers for the `.service`. For a timer-driven unit that
371
+ // service is `inactive` BETWEEN RUNS and `inactive` when its timer has been stopped — the same
372
+ // answer to both questions. So the health check can now say this unit exists and cannot say whether
373
+ // anything still starts it, which is the failure the entry was written for.
374
+ //
375
+ // The signal lives on `clearotron-doctrine-sync.timer`, whose ActiveState separates `active`
376
+ // (waiting) from `inactive` (stopped). What is missing is not the NAME — `systemdUnits` below
377
+ // carries it — but a consumer: the check derives its queries from the bare unit rather than from
378
+ // that field, so the timer is written down and never asked about.
379
+ //
380
+ // WHEN THE CHECK DERIVES ITS QUERIES FROM `systemdUnits` RATHER THAN FROM THE BARE NAME, THIS
381
+ // PARAGRAPH IS OBSOLETE — and the field below is what it will read. Stated as a condition rather
382
+ // than as a pointer to where it is being done, because a condition is self-verifying: a reader
383
+ // confirms or refutes it by looking at the check today, and the day the derivation lands this reads
384
+ // as history instead of as an open item.
385
+ untrackedReason: "the doctrine refresh on production, timer-driven, running from no file in "
386
+ + "driver/systemd/ and named nowhere in this repo. It CAN be tracked — it carries no "
387
+ + "identity-edge value — and nobody wrote it down. Until it is, its absence is at least no "
388
+ + "longer silent.",
389
+ },
390
+ {
391
+ unit: "client-access", runsOn: [],
392
+ orphanReason: "NOT THIS REPOSITORY'S SERVICE, and no longer running under this name: the legacy "
393
+ + "account holds it only as `client-access.service.retired-20260904`, a suffix systemd never reads. "
394
+ + "Declared here so a unit sharing a machine with ours is not invisible, and now declared as gone.",
395
+ measured: "2026-09-08: present on the legacy account ONLY as a retired-suffixed filename, which "
396
+ + "systemd does not load. No loadable unit of this name under any account.", tracked: null,
311
397
  untrackedReason: "it is not this repo's service. Its ExecStart runs a script from a different "
312
398
  + "product's checkout on the same box, not under this clone — so there is no code here to "
313
399
  + "template, and the old reason (CF Access values inline) would send the next reader hunting for a "
@@ -415,13 +501,21 @@ export const UNIT_INVENTORY = Object.freeze([
415
501
  + "checkout's bridge, not this clone's.",
416
502
  },
417
503
  {
418
- unit: "trademark-test-deploy", runsOn: ["test"], tracked: null,
504
+ unit: "trademark-test-deploy", runsOn: [],
505
+ measured: "2026-09-07, test box: LoadState=not-found. The hourly deploy runs as clearotron-deploy.timer, which has its own entry; this name is what that one used to be called.", tracked: null,
506
+ // AN EMPTY runsOn OWES A REASON, and this one is a supersession rather than an orphan: the hourly
507
+ // deploy still runs on the test box, under the name `clearotron-deploy`, which has its own entry and
508
+ // its own measurement. This name is what that unit used to be called. It is kept rather than deleted
509
+ // because the unit FILE is still tracked and an inventory of what ships should account for every
510
+ // tracked file — deleting the entry would make the file unaccounted for, which is the ratchet this
511
+ // file exists to keep shut.
512
+ orphanReason: "SUPERSEDED, NOT RETIRED — the hourly deploy of the test instance runs as `clearotron-deploy`, measured active there on 2026-09-07. This entry is the pre-rename name for the same job, so it runs on no box under THIS name and the boxes moved to the entry that replaced it. The tracked file stays until production is rebuilt, which is the same disposition the other retired units carry.",
419
513
  untrackedReason: "the hourly --ff-only deploy of the TEST instance. It exists on the test box only "
420
514
  + "and by design: production never auto-deploys, so a tracked file shipped to both would be a unit "
421
515
  + "production must be trusted never to enable.",
422
516
  },
423
517
  // register-ledger-prune is DELIBERATELY not listed, and the sequence is worth keeping because the
424
- // row was right until the moment it was wrong. 's nightly rotation was retired in code by:
518
+ // row was right until the moment it was wrong. That nightly rotation was retired in code by:
425
519
  // bin/register-ledger-prune.mjs is deleted, record bodies now live in each run's own directory and
426
520
  // are purged with the run, so there is no global file left to rotate. The row stayed here on
427
521
  // purpose while the TIMER was still installed on the test box — dropping it first would have made
@@ -463,6 +557,59 @@ export const CHECKED_UNITS = Object.freeze(
463
557
  UNIT_INVENTORY.filter((u) => u.runsOn.length > 0).map((u) => u.unit),
464
558
  );
465
559
 
560
+ /**
561
+ * The TIMER units this deployment claims to have, by name, as systemd spells them.
562
+ *
563
+ * ── WHY A SECOND LIST AND NOT MORE NAMES IN THE ONE ABOVE ───────────────────────────────────────────
564
+ *
565
+ * `CHECKED_UNITS` holds BARE names, and that is load-bearing rather than an accident: the verdict
566
+ * appends the suffixes itself when matching what a box is running, so one entry answers for a unit's
567
+ * service, timer and path alike. The health check then asks `systemctl show <bare>`, and systemd
568
+ * resolves a bare name to the `.service`.
569
+ *
570
+ * For a timer-driven unit that is the wrong question, and it is wrong in the direction that hides the
571
+ * failure. The service of a timer-driven unit reads `ActiveState=inactive` **between runs** — it is
572
+ * meant to — and it reads `inactive` when its timer has been STOPPED. Identical strings, opposite
573
+ * meanings, and the check could report the unit exists while being unable to say whether anything
574
+ * still starts it. That is the whole of what a timer entry is for.
575
+ *
576
+ * The signal lives on the `.timer`, whose `ActiveState` separates `active` (armed and waiting) from
577
+ * `inactive` (stopped, and nothing will fire the service again).
578
+ *
579
+ * ── WHERE THE NAMES COME FROM ───────────────────────────────────────────────────────────────────────
580
+ *
581
+ * From `tracked`, which already lists the files an entry accounts for, so a shipped timer is covered
582
+ * with nothing new to declare and cannot be forgotten. An UNTRACKED unit has no file list to read, so
583
+ * it says so with `systemdUnits:` — the systemd names to ask about, which is a different fact from the files
584
+ * the repository ships and is why it is not folded into `tracked`. Claiming a tracked file that does
585
+ * not exist is a fault; naming a unit this deployment runs is a claim about a box.
586
+ */
587
+ export const CHECKED_TIMERS = Object.freeze(
588
+ UNIT_INVENTORY.filter((u) => u.runsOn.length > 0)
589
+ .flatMap((u) => (u.systemdUnits ?? u.tracked ?? []).filter((f) => f.endsWith(".timer")))
590
+ .sort(),
591
+ );
592
+
593
+ /**
594
+ * Judge the timers. PURE — the caller reads systemd.
595
+ *
596
+ * `inactive` is the finding here, which inverts the reflex a reader brings from services. A stopped
597
+ * timer breaks nothing now and nothing fails: the service simply never fires again, and every surface
598
+ * that reports on the service keeps saying `inactive`, which is what it says when the timer is working.
599
+ */
600
+ export function timerVerdict(timers, { probeFailed = null } = {}) {
601
+ if (probeFailed) return { state: "unknown", stopped: [], absent: [], message: `could not ask systemd about the timers: ${probeFailed}. That is this check failing to look, not a report about them.` };
602
+ const rows = timers ?? [];
603
+ if (!rows.length) return { state: "pass", stopped: [], absent: [], message: "no timer is declared for this box" };
604
+ const absent = rows.filter((t) => t.load === "not-found").map((t) => t.unit).sort();
605
+ const stopped = rows.filter((t) => t.load !== "not-found" && t.active !== "active").map((t) => t.unit).sort();
606
+ const parts = [`${rows.length} declared timer(s)`];
607
+ if (stopped.length) parts.push(`STOPPED: ${stopped.join(", ")} — the service each one drives will not fire again, and its own state stays 'inactive' either way`);
608
+ if (absent.length) parts.push(`${absent.length} declared timer(s) do not exist on this box`);
609
+ if (!stopped.length && !absent.length) parts.push("all armed");
610
+ return { state: stopped.length ? "fail" : "pass", stopped, absent, message: parts.join("; ") };
611
+ }
612
+
466
613
  /** Every tracked file the inventory accounts for, flattened. */
467
614
  export const ACCOUNTED_FILES = Object.freeze(
468
615
  UNIT_INVENTORY.flatMap((u) => u.tracked ?? []),
@@ -489,6 +636,11 @@ export const ACCOUNTED_FILES = Object.freeze(
489
636
  */
490
637
  export function unitInventoryVerdict({
491
638
  live = [], files = [], collisions = [], filesError = null, box = null, probe = { ok: true },
639
+ // INJECTED so the retirement branch can be PLANTED. `retired:` has no members today — the two it
640
+ // carried left with their files — so `absentByRetirement` and the line it feeds are unreachable
641
+ // against the real table, and a branch nothing exercises is a branch that will not fire the next
642
+ // time somebody retires a unit. That is this file's own failure mode pointed at itself.
643
+ inventory = UNIT_INVENTORY,
492
644
  } = {}) {
493
645
  if (!probe.ok) {
494
646
  return { state: "skip", undeclared: [], orphaned: [], absent: [], misdeclared: [],
@@ -496,7 +648,7 @@ export function unitInventoryVerdict({
496
648
  + "A failure to look is not a finding about the deployment." };
497
649
  }
498
650
  const base = (u) => String(u).replace(/\.(service|timer|path|socket|target|mount|slice)$/, "");
499
- const known = new Set(UNIT_INVENTORY.map((u) => u.unit));
651
+ const known = new Set(inventory.map((u) => u.unit));
500
652
  const liveBases = [...new Set(live.map(base))];
501
653
 
502
654
  const undeclared = liveBases.filter((u) => !known.has(u)).sort();
@@ -506,7 +658,20 @@ export function unitInventoryVerdict({
506
658
  // reason attached, and the difference is the whole point of writing the reasons down.
507
659
  const accounted = new Set(ACCOUNTED_FILES);
508
660
  const unaccountedFiles = files.filter((f) => !accounted.has(f)).sort();
509
- const orphaned = UNIT_INVENTORY.filter((u) => u.runsOn.length === 0).map((u) => u.unit).sort();
661
+ const orphaned = inventory.filter((u) => u.runsOn.length === 0).map((u) => u.unit).sort();
662
+
663
+ // RUNNING HERE, DECLARED TO RUN NOWHERE. The defect the rename to clearotron-* left behind: the new
664
+ // units shipped WITH entries, those entries kept `runsOn: []`, and the pre-rename names kept the
665
+ // boxes. Every arm scoped to CHECKED_UNITS — which filters on a NON-EMPTY runsOn — therefore asked
666
+ // systemd about sixteen names that mostly named nothing and reported "0 active; 16 at rest", while
667
+ // four services ran under names no entry claimed. Measured on the test box 2026-09-07.
668
+ //
669
+ // This needs NO knowledge of which box it is running on, which is what makes it the right shape: an
670
+ // entry saying a unit runs on no box is contradicted by that unit running HERE, wherever here is.
671
+ // The mirror — declared for a box and absent from it — cannot be judged without a box identity this
672
+ // tree does not carry, and is reported as information rather than as a verdict.
673
+ const orphanSet = new Set(orphaned);
674
+ const runningButDeclaredNowhere = liveBases.filter((u) => orphanSet.has(u)).sort();
510
675
 
511
676
  // THE RATCHET THAT MAKES THIS FILE'S OWN DEFECT UNREPRESENTABLE. An entry with no tracked file states
512
677
  // a fact about the tree, and until the lookup went repo-wide it was a fact nothing could check —
@@ -514,7 +679,7 @@ export function unitInventoryVerdict({
514
679
  // is why writing one is dangerous" while the tracked file sat one directory over. A reader asking what
515
680
  // configuration the client door runs was told, with confidence, to look at nothing.
516
681
  const trackedNames = new Set(files);
517
- const misdeclared = UNIT_INVENTORY
682
+ const misdeclared = inventory
518
683
  .filter((u) => !u.tracked)
519
684
  .filter((u) => ["service", "timer", "path"].some((s) => trackedNames.has(`${u.unit}.${s}`)))
520
685
  .map((u) => u.unit).sort();
@@ -529,7 +694,7 @@ export function unitInventoryVerdict({
529
694
  // It matters now because the retirement above deletes unit files on a schedule set by production's
530
695
  // rebuild rather than by this PR, so entry and tree are deliberately going to disagree for a while,
531
696
  // and the disagreement must be the kind that gets reported rather than the kind that is invisible.
532
- const claimedAbsent = files.length === 0 || filesError ? [] : UNIT_INVENTORY
697
+ const claimedAbsent = files.length === 0 || filesError ? [] : inventory
533
698
  .flatMap((u) => (u.tracked ?? []).map((f) => ({ unit: u.unit, file: f })))
534
699
  .filter((c) => !trackedNames.has(c.file))
535
700
  .map((c) => `${c.file} (claimed by ${c.unit})`).sort();
@@ -538,16 +703,16 @@ export function unitInventoryVerdict({
538
703
  // reporting every production unit missing on a dev box is a false alarm, and it would train a reader
539
704
  // to skim this check. But an arm that did not run is not an arm that passed — this file's whole
540
705
  // thesis — so an unnameable box is STATED rather than silently skipped.
541
- // ABSENT-AND-EXPECTED-TO-BE vs ABSENT-AND-SHOULD-NOT-BE (, criterion 3). A retired
706
+ // ABSENT-AND-EXPECTED-TO-BE vs ABSENT-AND-SHOULD-NOT-BE (criterion 3). A retired
542
707
  // unit that is gone from a box is the ruling taking effect, not drift; reporting it as a fault trains
543
708
  // a reader to skim the arm that would have caught a real one. Both are still REPORTED — the
544
709
  // distinction is which of them is a fault.
545
710
  const declaredHere = (u) => box && u.runsOn.includes(box) && !liveBases.includes(u.unit);
546
711
  const absent = box
547
- ? UNIT_INVENTORY.filter((u) => declaredHere(u) && !u.retired).map((u) => u.unit).sort()
712
+ ? inventory.filter((u) => declaredHere(u) && !u.retired).map((u) => u.unit).sort()
548
713
  : [];
549
714
  const absentByRetirement = box
550
- ? UNIT_INVENTORY.filter((u) => declaredHere(u) && u.retired).map((u) => u.unit).sort()
715
+ ? inventory.filter((u) => declaredHere(u) && u.retired).map((u) => u.unit).sort()
551
716
  : [];
552
717
  const boxLine = box ? "" : " The box could not be named, so 'declared here and not running' was NOT "
553
718
  + "checked — that half did not run, which is not the same as passing.";
@@ -572,6 +737,11 @@ export function unitInventoryVerdict({
572
737
  + "A unit nothing declares is compared against nothing and reported by nothing — add it to "
573
738
  + "driver/unit-inventory.mjs, tracked or with the reason it is not.");
574
739
  }
740
+ if (runningButDeclaredNowhere.length) {
741
+ faults.push(`${runningButDeclaredNowhere.join(", ")} — ${runningButDeclaredNowhere.length} unit(s) are `
742
+ + `RUNNING on this box while their inventory entry declares runsOn: [], so every check scoped to `
743
+ + `the declared list is judging a population that excludes them`);
744
+ }
575
745
  if (misdeclared.length) {
576
746
  faults.push(`${misdeclared.length} entr(y/ies) claim NO tracked file while a unit file of that name is `
577
747
  + `in the tree: ${misdeclared.join(", ")}. The entry is not merely incomplete, it is false — and a `
@@ -618,8 +788,8 @@ export function unitInventoryVerdict({
618
788
  return {
619
789
  state: "pass", undeclared, orphaned, absent, misdeclared, claimedAbsent, absentByRetirement,
620
790
  message: `${liveBases.length} live unit(s), all declared; `
621
- + `${UNIT_INVENTORY.filter((u) => u.tracked).length} entr(y/ies) tracked, `
622
- + `${UNIT_INVENTORY.filter((u) => u.runsOn.length && !u.tracked).length} live-and-untracked BY DECLARATION `
791
+ + `${inventory.filter((u) => u.tracked).length} entr(y/ies) tracked, `
792
+ + `${inventory.filter((u) => u.runsOn.length && !u.tracked).length} live-and-untracked BY DECLARATION `
623
793
  + `with a stated reason.${retiredLine}${orphanLine}${boxLine}${filesLine}`,
624
794
  };
625
795
  }
@@ -641,6 +811,53 @@ export function unitInventoryVerdict({
641
811
  * @param {string|null} raw the value `systemctl show -p WorkingDirectory` printed
642
812
  * @returns {{path: string|null, prefixes: string, why: string|null}}
643
813
  */
814
+ /**
815
+ * Which checkout is a unit actually serving — and which piece of evidence said so.
816
+ *
817
+ * A unit can be attributed two ways and they are not equally good.
818
+ *
819
+ * `WorkingDirectory` is a DECLARATION. It is what the unit file asks for, and it is frequently not a
820
+ * checkout at all: a unit written as `WorkingDirectory=~` reports `!/home/<user>`, which resolves to a
821
+ * home directory that is not a git tree, and the unit then drops out of the comparison entirely. That is
822
+ * not a rare shape — it is what a unit looks like when its author put the checkout in `ExecStart=`
823
+ * instead, which is the normal thing to do, because systemd cannot expand a variable in
824
+ * `WorkingDirectory=` and can in `ExecStart=`.
825
+ *
826
+ * The RUNNING COMMAND LINE is an OBSERVATION: the absolute path the live process was actually started
827
+ * with. So it wins, and that order is the point rather than a preference. The incident this comparison
828
+ * exists for is a deployment that served its portal from one clone while running its runner from
829
+ * another — and in that state the declaration and the process disagree, with the process telling the
830
+ * truth. Preferring the declaration would take the wrong side of exactly the case the check is for.
831
+ *
832
+ * WHEN BOTH RESOLVE AND DISAGREE, that IS the finding, and it is returned rather than quietly resolved:
833
+ * a unit whose declared tree and running tree differ has been repointed since it started, and it is
834
+ * serving the older one until something restarts it.
835
+ *
836
+ * PURE — the caller does the reading (systemd, the unit file, the process table) and this decides.
837
+ *
838
+ * @param {object} a
839
+ * @param {string|null} a.declaredTree a git tree resolved from `WorkingDirectory`, or null
840
+ * @param {string|null} a.runningTree a git tree resolved from the live process's argv, or null
841
+ * @param {string|null} a.declaredWhy why the declaration gave nothing, if it gave nothing
842
+ * @param {string|null} a.runningWhy why the process gave nothing, if it gave nothing
843
+ * @returns {{clone: string|null, source: string|null, disagreement: string|null, why: string|null}}
844
+ */
845
+ export function unitClone({ declaredTree = null, runningTree = null, declaredWhy = null, runningWhy = null } = {}) {
846
+ const norm = (p) => String(p ?? "").replace(/\/+$/, "") || null;
847
+ const declared = norm(declaredTree);
848
+ const running = norm(runningTree);
849
+ const disagreement = declared && running && declared !== running
850
+ ? `the unit declares ${declared} and its running process was started from ${running} — it is serving the second until something restarts it`
851
+ : null;
852
+ if (running) return { clone: running, source: "the running command line", disagreement, why: null };
853
+ if (declared) return { clone: declared, source: "WorkingDirectory", disagreement, why: null };
854
+ // BOTH REASONS, never the first one that came to hand. A caller that reports only "no WorkingDirectory"
855
+ // sends the next reader to fix a unit file when the process table was the half that could not be read.
856
+ const parts = [declaredWhy, runningWhy].filter(Boolean);
857
+ return { clone: null, source: null, disagreement: null,
858
+ why: parts.length ? parts.join("; and ") : "neither the unit's WorkingDirectory nor its running command line named a checkout" };
859
+ }
860
+
644
861
  export function unitWorkingDirectory(raw) {
645
862
  const s = String(raw ?? "").trim();
646
863
  if (!s) return { path: null, prefixes: "", why: "the unit reported no WorkingDirectory" };