clearotron 0.4.0-beta.2 → 0.4.0-beta.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 (49) hide show
  1. package/THIRD-PARTY-NOTICES.md +5 -5
  2. package/build-info.json +2 -2
  3. package/driver/CHANGELOG.md +9 -0
  4. package/driver/coverage-form.mjs +6 -0
  5. package/driver/coverage-ledger.mjs +14 -2
  6. package/driver/driver.config.mjs +24 -7
  7. package/driver/engine/mcp/stdio-server.mjs +12 -1
  8. package/driver/package.json +1 -1
  9. package/driver/pipeline-knockout.mjs +29 -8
  10. package/driver/pipeline.mjs +58 -8
  11. package/driver/progress.mjs +6 -1
  12. package/driver/publish/knockout.mjs +16 -3
  13. package/driver/publish/render-knockout.mjs +38 -11
  14. package/driver/record-carry.mjs +16 -0
  15. package/driver/reference-strip-signatures.mjs +11 -1
  16. package/driver/register-plan.mjs +7 -3
  17. package/driver/register-served.mjs +91 -0
  18. package/driver/remedy-accounting.mjs +38 -9
  19. package/driver/score-redaction.mjs +389 -20
  20. package/driver/skills/clearance-register/SKILL.md +0 -8
  21. package/driver/skills/clearance-register/digest.md +1 -1
  22. package/driver/skills/clearance-register/providers/corsearch.md +1 -1
  23. package/driver/skills/clearance-register/register-recipes.md +3 -9
  24. package/driver/skills/clearance-search/SKILL.md +2 -2
  25. package/driver/skills/clearance-search/phase2-execution.md +1 -1
  26. package/driver/skills/knockout-assess/SKILL.md +2 -0
  27. package/driver/stages-knockout.mjs +22 -0
  28. package/driver/suite-census.json +120 -18
  29. package/driver/unit-inventory.mjs +38 -43
  30. package/mcp-server/CHANGELOG.md +4 -0
  31. package/mcp-server/package.json +1 -1
  32. package/node_modules/brace-expansion/index.js +78 -22
  33. package/node_modules/brace-expansion/package.json +1 -1
  34. package/node_modules/readdir-glob/node_modules/brace-expansion/index.js +78 -22
  35. package/node_modules/readdir-glob/node_modules/brace-expansion/package.json +1 -1
  36. package/package.json +1 -1
  37. package/portal-ui/package.json +2 -2
  38. package/providers/jx/src/core.js +0 -1
  39. package/providers/jx/src/judge.js +0 -1
  40. package/providers/jx/src/nativeread.js +0 -1
  41. package/providers/oauth-mcp-bridge/CHANGELOG.md +4 -0
  42. package/providers/oauth-mcp-bridge/package.json +1 -1
  43. package/providers/signa/src/core.js +37 -14
  44. package/scripts/e2e-first-time.mjs +12 -4
  45. package/scripts/e2e-scenario-ops.mjs +25 -2
  46. package/scripts/e2e.mjs +113 -15
  47. package/scripts/mint-reference-strip-backlog.mjs +36 -2
  48. package/scripts/score.mjs +102 -29
  49. package/shared/identifier-scan.mjs +31 -1
@@ -150,6 +150,28 @@ export const KNOCKOUT_WEB = Object.freeze({ preset: "pro-search", reasoning: Obj
150
150
  */
151
151
  export const KNOCKOUT_MINUTES_BAR = 10;
152
152
 
153
+ /**
154
+ * The bar's verdict for one run, from the run's own two timestamps. PURE, and it lives beside the constant
155
+ * so the comparison and the number it compares against cannot drift apart.
156
+ *
157
+ * AN UNREADABLE OR ABSENT START IS NOT "UNDER THE BAR". `runMinutes` and `overBar` are both null then, and
158
+ * `barNotMeasured` says why — a run whose span could not be read must not record a verdict that reads as a
159
+ * pass. That is the whole reason this returns three fields rather than a boolean.
160
+ *
161
+ * @param {{startedAt?: string|null, deliveredAt?: string|null}} span the run's own ISO timestamps
162
+ */
163
+ export function knockoutBarVerdict({ startedAt = null, deliveredAt = null } = {}) {
164
+ const a = startedAt ? Date.parse(startedAt) : NaN;
165
+ const b = deliveredAt ? Date.parse(deliveredAt) : NaN;
166
+ if (!Number.isFinite(a) || !Number.isFinite(b) || b < a)
167
+ return { runMinutes: null, overBar: null,
168
+ barNotMeasured: !Number.isFinite(a) ? "the run's own startedAt could not be read"
169
+ : !Number.isFinite(b) ? "the run has no delivery time to measure to"
170
+ : "the run's delivery time is before its start" };
171
+ const runMinutes = Number(((b - a) / 60000).toFixed(1));
172
+ return { runMinutes, overBar: runMinutes > KNOCKOUT_MINUTES_BAR };
173
+ }
174
+
153
175
  /** The territories the request ordered, as the job carries them; empty for a worldwide screen. PURE. */
154
176
  export const orderedTerritories = (job) =>
155
177
  (Array.isArray(job?.jurisdictions) ? job.jurisdictions.map((s) => String(s).trim()).filter(Boolean) : []);
@@ -93,6 +93,12 @@
93
93
  "skips": 0,
94
94
  "todos": 0
95
95
  },
96
+ "a-cap-of-zero-is-not-a-register-outcome.test.mjs": {
97
+ "tests": 3,
98
+ "asserts": 6,
99
+ "skips": 0,
100
+ "todos": 0
101
+ },
96
102
  "a-capability-gap-is-decided-once-per-run.test.mjs": {
97
103
  "tests": 4,
98
104
  "asserts": 17,
@@ -279,6 +285,12 @@
279
285
  "skips": 0,
280
286
  "todos": 0
281
287
  },
288
+ "a-coverage-row-carries-the-count-it-was-given.test.mjs": {
289
+ "tests": 4,
290
+ "asserts": 11,
291
+ "skips": 0,
292
+ "todos": 0
293
+ },
282
294
  "a-credential-file-is-written-one-way.test.mjs": {
283
295
  "tests": 4,
284
296
  "asserts": 13,
@@ -615,6 +627,12 @@
615
627
  "skips": 0,
616
628
  "todos": 0
617
629
  },
630
+ "a-job-matched-by-name-elsewhere-keeps-its-name.test.mjs": {
631
+ "tests": 2,
632
+ "asserts": 2,
633
+ "skips": 0,
634
+ "todos": 0
635
+ },
618
636
  "a-job-on-the-older-goods-spelling-scopes-the-same.test.mjs": {
619
637
  "tests": 10,
620
638
  "asserts": 23,
@@ -729,6 +747,12 @@
729
747
  "skips": 0,
730
748
  "todos": 0
731
749
  },
750
+ "a-mark-named-only-in-prose-is-withheld.test.mjs": {
751
+ "tests": 6,
752
+ "asserts": 9,
753
+ "skips": 0,
754
+ "todos": 0
755
+ },
732
756
  "a-mark-too-short-for-contains-is-asked-exactly.test.mjs": {
733
757
  "tests": 12,
734
758
  "asserts": 57,
@@ -778,8 +802,8 @@
778
802
  "todos": 0
779
803
  },
780
804
  "a-model-of-the-current-generation-is-named-in-every-spelling.test.mjs": {
781
- "tests": 4,
782
- "asserts": 13,
805
+ "tests": 8,
806
+ "asserts": 29,
783
807
  "skips": 0,
784
808
  "todos": 0
785
809
  },
@@ -922,8 +946,8 @@
922
946
  "todos": 0
923
947
  },
924
948
  "a-program-already-here-is-checked-against-the-floor.test.mjs": {
925
- "tests": 9,
926
- "asserts": 38,
949
+ "tests": 12,
950
+ "asserts": 44,
927
951
  "skips": 3,
928
952
  "todos": 0
929
953
  },
@@ -1065,6 +1089,12 @@
1065
1089
  "skips": 0,
1066
1090
  "todos": 0
1067
1091
  },
1092
+ "a-refused-call-records-which-field-was-missing.test.mjs": {
1093
+ "tests": 3,
1094
+ "asserts": 12,
1095
+ "skips": 0,
1096
+ "todos": 0
1097
+ },
1068
1098
  "a-refused-mcp-call-is-not-a-call-nobody-made.test.mjs": {
1069
1099
  "tests": 7,
1070
1100
  "asserts": 19,
@@ -1191,6 +1221,12 @@
1191
1221
  "skips": 0,
1192
1222
  "todos": 0
1193
1223
  },
1224
+ "a-run-records-which-register-served-it.test.mjs": {
1225
+ "tests": 9,
1226
+ "asserts": 22,
1227
+ "skips": 0,
1228
+ "todos": 0
1229
+ },
1194
1230
  "a-run-that-cannot-settle-says-so.test.mjs": {
1195
1231
  "tests": 4,
1196
1232
  "asserts": 12,
@@ -1311,6 +1347,12 @@
1311
1347
  "skips": 0,
1312
1348
  "todos": 0
1313
1349
  },
1350
+ "a-slice-the-fold-refused-as-already-asked-is-not-a-dispatch-failure.test.mjs": {
1351
+ "tests": 10,
1352
+ "asserts": 32,
1353
+ "skips": 0,
1354
+ "todos": 0
1355
+ },
1314
1356
  "a-source-the-classifier-could-not-read-is-not-empty.test.mjs": {
1315
1357
  "tests": 9,
1316
1358
  "asserts": 14,
@@ -1708,8 +1750,8 @@
1708
1750
  "todos": 0
1709
1751
  },
1710
1752
  "an-escape-is-read-the-way-a-lexer-reads-it.test.mjs": {
1711
- "tests": 3,
1712
- "asserts": 11,
1753
+ "tests": 5,
1754
+ "asserts": 25,
1713
1755
  "skips": 0,
1714
1756
  "todos": 0
1715
1757
  },
@@ -1797,6 +1839,12 @@
1797
1839
  "skips": 0,
1798
1840
  "todos": 0
1799
1841
  },
1842
+ "an-unreadable-sidecar-is-not-an-absent-one.test.mjs": {
1843
+ "tests": 7,
1844
+ "asserts": 13,
1845
+ "skips": 0,
1846
+ "todos": 0
1847
+ },
1800
1848
  "anchor-and-script-aware-quote.test.mjs": {
1801
1849
  "tests": 12,
1802
1850
  "asserts": 40,
@@ -2789,13 +2837,13 @@
2789
2837
  },
2790
2838
  "e2e-mark-provenance.test.mjs": {
2791
2839
  "tests": 29,
2792
- "asserts": 85,
2840
+ "asserts": 97,
2793
2841
  "skips": 0,
2794
2842
  "todos": 0
2795
2843
  },
2796
2844
  "e2e-pair-workflow.test.mjs": {
2797
2845
  "tests": 14,
2798
- "asserts": 72,
2846
+ "asserts": 73,
2799
2847
  "skips": 0,
2800
2848
  "todos": 0
2801
2849
  },
@@ -2812,8 +2860,8 @@
2812
2860
  "todos": 0
2813
2861
  },
2814
2862
  "e2e-scenario-ops.test.mjs": {
2815
- "tests": 25,
2816
- "asserts": 85,
2863
+ "tests": 28,
2864
+ "asserts": 94,
2817
2865
  "skips": 0,
2818
2866
  "todos": 0
2819
2867
  },
@@ -2914,8 +2962,8 @@
2914
2962
  "todos": 0
2915
2963
  },
2916
2964
  "engine.anthropic.test.mjs": {
2917
- "tests": 65,
2918
- "asserts": 248,
2965
+ "tests": 66,
2966
+ "asserts": 250,
2919
2967
  "skips": 1,
2920
2968
  "todos": 0
2921
2969
  },
@@ -3407,7 +3455,7 @@
3407
3455
  },
3408
3456
  "jx-p4-cores.test.mjs": {
3409
3457
  "tests": 14,
3410
- "asserts": 56,
3458
+ "asserts": 58,
3411
3459
  "skips": 0,
3412
3460
  "todos": 0
3413
3461
  },
@@ -3719,7 +3767,7 @@
3719
3767
  },
3720
3768
  "onboard-wizard.test.mjs": {
3721
3769
  "tests": 77,
3722
- "asserts": 294,
3770
+ "asserts": 295,
3723
3771
  "skips": 4,
3724
3772
  "todos": 0
3725
3773
  },
@@ -5391,6 +5439,12 @@
5391
5439
  "skips": 0,
5392
5440
  "todos": 0
5393
5441
  },
5442
+ "the-bar-is-measured-against-the-run.test.mjs": {
5443
+ "tests": 3,
5444
+ "asserts": 9,
5445
+ "skips": 0,
5446
+ "todos": 0
5447
+ },
5394
5448
  "the-bar-names-no-organisation-nobody-named.test.mjs": {
5395
5449
  "tests": 6,
5396
5450
  "asserts": 13,
@@ -5613,6 +5667,12 @@
5613
5667
  "skips": 0,
5614
5668
  "todos": 0
5615
5669
  },
5670
+ "the-engine-sets-no-sampling-and-forces-no-tool.test.mjs": {
5671
+ "tests": 6,
5672
+ "asserts": 9,
5673
+ "skips": 0,
5674
+ "todos": 0
5675
+ },
5616
5676
  "the-engine-step-cannot-loop-on-a-menu-nothing-changed.test.mjs": {
5617
5677
  "tests": 17,
5618
5678
  "asserts": 45,
@@ -5763,6 +5823,12 @@
5763
5823
  "skips": 0,
5764
5824
  "todos": 0
5765
5825
  },
5826
+ "the-investigate-line-names-its-claim-by-location.test.mjs": {
5827
+ "tests": 20,
5828
+ "asserts": 57,
5829
+ "skips": 0,
5830
+ "todos": 0
5831
+ },
5766
5832
  "the-knockout-page-leads-with-the-read.test.mjs": {
5767
5833
  "tests": 39,
5768
5834
  "asserts": 125,
@@ -5877,6 +5943,12 @@
5877
5943
  "skips": 0,
5878
5944
  "todos": 0
5879
5945
  },
5946
+ "the-payload-is-redacted-as-a-structure.test.mjs": {
5947
+ "tests": 11,
5948
+ "asserts": 22,
5949
+ "skips": 0,
5950
+ "todos": 0
5951
+ },
5880
5952
  "the-people-page-can-change-and-remove-a-person.test.mjs": {
5881
5953
  "tests": 17,
5882
5954
  "asserts": 85,
@@ -5985,9 +6057,27 @@
5985
6057
  "skips": 0,
5986
6058
  "todos": 0
5987
6059
  },
5988
- "the-reference-strip-left-sentences-unfinished.test.mjs": {
6060
+ "the-redaction-folds-character-width.test.mjs": {
5989
6061
  "tests": 6,
5990
- "asserts": 15,
6062
+ "asserts": 11,
6063
+ "skips": 0,
6064
+ "todos": 0
6065
+ },
6066
+ "the-redaction-leaves-the-scaffolding-alone.test.mjs": {
6067
+ "tests": 4,
6068
+ "asserts": 7,
6069
+ "skips": 0,
6070
+ "todos": 0
6071
+ },
6072
+ "the-redaction-never-shrinks-its-own-coverage.test.mjs": {
6073
+ "tests": 5,
6074
+ "asserts": 10,
6075
+ "skips": 0,
6076
+ "todos": 0
6077
+ },
6078
+ "the-reference-strip-left-sentences-unfinished.test.mjs": {
6079
+ "tests": 7,
6080
+ "asserts": 25,
5991
6081
  "skips": 4,
5992
6082
  "todos": 0
5993
6083
  },
@@ -6124,8 +6214,8 @@
6124
6214
  "todos": 0
6125
6215
  },
6126
6216
  "the-scorer-withholds-names-unless-asked.test.mjs": {
6127
- "tests": 21,
6128
- "asserts": 46,
6217
+ "tests": 32,
6218
+ "asserts": 63,
6129
6219
  "skips": 0,
6130
6220
  "todos": 0
6131
6221
  },
@@ -6207,6 +6297,12 @@
6207
6297
  "skips": 2,
6208
6298
  "todos": 0
6209
6299
  },
6300
+ "the-totals-block-counts-a-step-that-said-nothing.test.mjs": {
6301
+ "tests": 4,
6302
+ "asserts": 8,
6303
+ "skips": 0,
6304
+ "todos": 0
6305
+ },
6210
6306
  "the-trigger-key-has-a-deadline-somebody-is-counting.test.mjs": {
6211
6307
  "tests": 5,
6212
6308
  "asserts": 23,
@@ -7649,6 +7745,12 @@
7649
7745
  "skips": 0,
7650
7746
  "todos": 0
7651
7747
  },
7748
+ "providers/signa/test/the-office-date-comes-first-and-signas-own-is-the-fallback.test.mjs": {
7749
+ "tests": 9,
7750
+ "asserts": 20,
7751
+ "skips": 0,
7752
+ "todos": 0
7753
+ },
7652
7754
  "providers/signa/test/the-screen-speaks-the-shared-verdicts.test.mjs": {
7653
7755
  "tests": 2,
7654
7756
  "asserts": 4,
@@ -159,9 +159,9 @@ export const UNIT_INVENTORY = Object.freeze([
159
159
  // stamped and says where its verdict lives, and driver/updater-identity.mjs makes that verdict from
160
160
  // the digests the updater records about itself.
161
161
  attribution: "stamp",
162
- 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 says the timer itself is still up. It is NOT a next elapse and does not promise one: `active` means UP, never SCHEDULED. Proving something will still fire takes a real next elapse, which `systemctl list-timers --all` supplies and `show -p ActiveState` cannot. Measured in testing 2026-09-09: a timer reading `ActiveState=active` whose `OnCalendar` names a date already past, so `list-timers` reports its next fire as null and it will never run again.",
162
+ measured: "2026-09-08, read on the test deployment: the timer and its service are installed, 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 says the timer itself is still up. It is NOT a next elapse and does not promise one: `active` means UP, never SCHEDULED. Proving something will still fire takes a real next elapse, which `systemctl list-timers --all` supplies and `show -p ActiveState` cannot. Measured in testing 2026-09-09: a timer reading `ActiveState=active` whose `OnCalendar` names a date already past, so `list-timers` reports its next fire as null and it will never run again.",
163
163
  tracked: ["clearotron-deploy.service", "clearotron-deploy.timer"],
164
- note: "the install's own updater. Placed on the test deployment, where it pulls hourly; production takes it when the owner asks.",
164
+ note: "the install's own updater.",
165
165
  // IT WAS AN ORPHAN, AND THE CONDITION IT NAMED HAS BEEN MET. This entry carried an `orphanReason`
166
166
  // saying it had been shipped and installed nowhere, and that `runsOn` would gain "test" the day a
167
167
  // deploy placed it. It has: the timer is installed, enabled and firing, and `runsOn` says so. The prose
@@ -212,10 +212,8 @@ export const UNIT_INVENTORY = Object.freeze([
212
212
  // prose references in driver/systemd/render-units.mjs also describe this file as though it were in
213
213
  // the tree; they are stale today either way.
214
214
  unit: "profile-service", runsOn: [],
215
- measured: "2026-09-08: production read by account — the deployment account carries six clearotron-* "
216
- + "unit files and the doctrine-sync timer, the legacy account carries five units belonging to the "
217
- + "other product plus unloadable residue, and no unit of THIS name is under either. Names and enable "
218
- + "state only; no unit contents were read.",
215
+ measured: "2026-09-08, read on production: no unit of this name is present. Names and enable state only; "
216
+ + "no unit contents were read.",
219
217
  tracked: null,
220
218
  untrackedReason: "the repository has never carried this file — `git log --all` on the path is empty. "
221
219
  + "It was described as deploying from a copy held on the deployment itself, in the same "
@@ -226,9 +224,9 @@ export const UNIT_INVENTORY = Object.freeze([
226
224
  // it loaded no EnvironmentFile and so had no `${VAR}` systemd could expand. The owner's one-config-
227
225
  // per-server-box ruling gives it `EnvironmentFile=%h/.env` like every other service, which makes the
228
226
  // checkout path an ordinary systemd expansion and leaves no placeholder to render.
229
- note: "NOT RUNNING ANYWHERE, measured 2026-09-08. This row said LIVE ON PRODUCTION for as long as it "
230
- + "existed and no enumeration ever supported it. Was a TEMPLATE unit carrying identity-provider "
231
- + "values inline; generic since the product installed its own units.",
227
+ note: "Was a TEMPLATE unit carrying identity-provider values inline; generic since the product "
228
+ + "installed its own units. It claimed a box for as long as it existed and no reading ever "
229
+ + "supported it — which is what the dated measurement beside it exists to prevent.",
232
230
  orphanReason: "CLAIMED A DEPLOYMENT IT WAS NEVER MEASURED ON, which is a FOURTH kind of orphan and "
233
231
  + "the only one that was ever a wrong claim rather than a waiting decision: the other three run "
234
232
  + "under another name, were deliberately switched off, or have simply never been installed. This "
@@ -245,7 +243,7 @@ export const UNIT_INVENTORY = Object.freeze([
245
243
  // REPORTED, never a fault, for exactly this case. It becomes `["prod"]` in the change that DEPLOYS
246
244
  // it, against a fresh enumeration, which is the ratchet working rather than being edited around.
247
245
  unit: "clearotron-portal", runsOn: ["test"], tracked: ["clearotron-portal.service"],
248
- measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
246
+ measured: "2026-09-07, read on the test deployment with a working user bus: ActiveState=active, UnitFileState=enabled, its fragment under the account's own unit directory.",
249
247
  note: "NEW, SHIPPED BUT NOT YET DEPLOYED. The portal had NO unit at all — it "
250
248
  + "and the MCP face are the two children bin/start.mjs supervises, and neither ran under systemd, "
251
249
  + "so a hosted deployment kept them alive with a hand launcher and `clearotron start` had nothing "
@@ -262,7 +260,7 @@ export const UNIT_INVENTORY = Object.freeze([
262
260
  // Same as clearotron-portal above: shipped, running nowhere, declared as an orphan rather than
263
261
  // asserting a production state no enumeration has ever shown.
264
262
  unit: "clearotron-mcp-face", runsOn: ["test"], tracked: ["clearotron-mcp-face.service"],
265
- measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
263
+ measured: "2026-09-07, read on the test deployment with a working user bus: ActiveState=active, UnitFileState=enabled, its fragment under the account's own unit directory.",
266
264
  note: "NEW, SHIPPED BUT NOT YET DEPLOYED. The engine door the portal calls over "
267
265
  + "MCP; the other of the two processes that had no unit.",
268
266
  orphanReason: "THE ENGINE DOOR THE PORTAL CALLS, shipped with no box carrying it yet. Same kind as "
@@ -291,7 +289,7 @@ export const UNIT_INVENTORY = Object.freeze([
291
289
  // door beside it: it is in SERVER_INSTALL_SET, and it leaves this list on the day a measured
292
290
  // enumeration of a box shows it running.
293
291
  unit: "clearotron-client-mcp", runsOn: ["test"], tracked: ["clearotron-client-mcp.service"],
294
- measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
292
+ measured: "2026-09-07, read on the test deployment with a working user bus: ActiveState=active, UnitFileState=enabled, its fragment under the account's own unit directory.",
295
293
  note: "INSTALLED WITH THE PRODUCT since 2026-09-03. The client door "
296
294
  + "— the one surface that accepts an account-scoped key, and a separate process from the engine "
297
295
  + "door, which refuses one outright.",
@@ -309,10 +307,9 @@ export const UNIT_INVENTORY = Object.freeze([
309
307
  // Written as part of retiring the path-watcher posture, because retiring `prelim-driver.*` without
310
308
  // it leaves a hosted box healthy-looking and draining nothing.
311
309
  unit: "clearotron-worker", runsOn: ["test"], tracked: ["clearotron-worker.service"],
312
- measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
310
+ measured: "2026-09-07, read on the test deployment with a working user bus: ActiveState=active, UnitFileState=enabled, its fragment under the account's own unit directory.",
313
311
  note: "NEW. The drain, as one plain service unit invoking the entrypoint "
314
- + "directly (owner ruling 2026-08-31). Ships tracked, runs nowhere yet — production takes it at "
315
- + "its rebuild, which is the same event that lets the retired units' files leave the tree.",
312
+ + "directly (owner ruling 2026-08-31). Ships tracked and runs nowhere yet.",
316
313
  orphanReason: "AWAITING A BOX, not an orphan by design. It is the hosted posture's drainer, and the "
317
314
  + "hosted posture is an opt-in step no install performs. It must NOT be "
318
315
  + "started beside `clearotron start`, which supervises its own worker — the two postures are "
@@ -320,10 +317,10 @@ export const UNIT_INVENTORY = Object.freeze([
320
317
  },
321
318
  {
322
319
  unit: "trademark-portal", runsOn: [],
323
- orphanReason: "THE PRE-RENAME PORTAL. The deployment account runs `clearotron-portal`; this name is "
320
+ orphanReason: "THE PRE-RENAME PORTAL. Production runs `clearotron-portal`; this name is "
324
321
  + "what that service used to be called, and the 2026-09-08 reading finds no unit of this name under "
325
322
  + "any account. It ran on production until the rename and the entry was never re-measured after it.",
326
- 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,
323
+ measured: "2026-09-08, read on production: no unit of this name is present. 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,
327
324
  untrackedReason: "the deployed copy carries real Cloudflare Access team/AUD/domain values inline. "
328
325
  + "A tracked file would be the placeholder TEMPLATE, merged by hand after a "
329
326
  + "diff — writing one carelessly replaces working auth with placeholders that look configured.",
@@ -335,10 +332,10 @@ export const UNIT_INVENTORY = Object.freeze([
335
332
  },
336
333
  {
337
334
  unit: "trademark-ops-mcp", runsOn: [],
338
- orphanReason: "THE PRE-RENAME OPERATOR DOOR. The deployment account runs `clearotron-mcp-face`; the "
335
+ orphanReason: "THE PRE-RENAME OPERATOR DOOR. Production runs `clearotron-mcp-face`; the "
339
336
  + "2026-09-08 reading finds no unit of this name under any account. Same rename as the portal it "
340
337
  + "serves, and the same claim carried across it unmeasured.",
341
- 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,
338
+ measured: "2026-09-08, read on production: no unit of this name is present. 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,
342
339
  untrackedReason: "same CF Access inline-values shape as the portal it serves.",
343
340
  },
344
341
  {
@@ -346,22 +343,20 @@ export const UNIT_INVENTORY = Object.freeze([
346
343
  orphanReason: "THE PRE-RENAME CLIENT DOOR. `clearotron-client-mcp` runs on both the production and "
347
344
  + "the test deployments; the 2026-09-08 reading finds no unit of THIS name under any account. The "
348
345
  + "tracked template stays because the repository still ships it — see the note.",
349
- 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"],
346
+ measured: "2026-09-08, read on production: no unit of this name is present. 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"],
350
347
  note: "TRACKED, in mcp-server/remote/ — this entry said it had no file, and the file was there. It is "
351
348
  + "a banner-marked TEMPLATE, so the live copy differing from it is the arrangement, not drift. "
352
- + "#1147 ADDED THE TEST BOX (2026-08-18): the client surface ran nowhere but production, so the test "
353
- + "instance exercised none of it and #764 sat merged-awaiting-e2e with no round able to settle it. "
354
- + "The issue reported that no unit shipped; a unit did ship, in mcp-server/remote/ rather than "
355
- + "driver/systemd/ — the same one-directory blind spot this file's own header records. The test "
356
- + "unit runs the same binary in dev mode on its own port; see the template for why that port is "
357
- + "not the default.",
349
+ + "It was reported as shipping no unit; a unit did ship, in mcp-server/remote/ rather than "
350
+ + "driver/systemd/ — the same one-directory blind spot this file's own header records. A "
351
+ + "deployment unit runs the same binary in dev mode on its own port; see the template for why "
352
+ + "that port is not the default.",
358
353
  },
359
354
  {
360
355
  unit: "client-mcp-apikey", runsOn: ["test"],
361
- measured: "2026-09-08, read by account: enabled and present on the TEST deployment, beside the "
362
- + "renamed `clearotron-client-mcp`, and INACTIVE — enabled with no running process. Absent from "
363
- + "production under any account. The entry declared production and the reading puts it on the "
364
- + "other deployment — the claim was not stale, it named the wrong machine.",
356
+ measured: "2026-09-08, read on the test deployment: enabled and present, beside the renamed "
357
+ + "`clearotron-client-mcp`, and INACTIVE — enabled with no running process. Absent from "
358
+ + "production. The entry declared production and the reading puts it on the other deployment "
359
+ + "— the claim was not stale, it named the wrong machine.",
365
360
  tracked: ["client-mcp-apikey.service"],
366
361
  // THE SEPARATE QUESTION, ANSWERED. The line above used to end by saying that why it runs beside the
367
362
  // renamed door was a question for somebody else. It is a survivor of the rename, not a posture
@@ -401,7 +396,7 @@ export const UNIT_INVENTORY = Object.freeze([
401
396
  orphanReason: "A PRE-RENAME NAME OF THE RETIRED DEPLOYMENT, and the one of them whose tracked file "
402
397
  + "is GENERIC rather than a template — so the file is ready to be compared against a live copy the "
403
398
  + "day something runs it, and nothing does. Read as absent under every account on 2026-09-08.",
404
- 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"],
399
+ measured: "2026-09-08, read on production: no unit of this name is present. Names and enable state only; no unit contents were read.", tracked: ["trademark-artifacts-http.service"],
405
400
  note: "TRACKED, in mcp-server/remote/. GENERIC, not a template: it carries no banner and no "
406
401
  + "placeholder, and defers its CF Access values to the EnvironmentFile — so its live copy is "
407
402
  + "expected to MATCH the tracked file, and a difference is real drift.",
@@ -455,11 +450,11 @@ export const UNIT_INVENTORY = Object.freeze([
455
450
  },
456
451
  {
457
452
  unit: "client-access", runsOn: [],
458
- orphanReason: "NOT THIS REPOSITORY'S SERVICE, and no longer running under this name: the legacy "
459
- + "account holds it only as `client-access.service.retired-20260904`, a suffix systemd never reads. "
453
+ orphanReason: "NOT THIS REPOSITORY'S SERVICE, and no longer running under this name: production holds it "
454
+ + "only under a retired-suffixed filename, a suffix systemd never reads. "
460
455
  + "Declared here so a unit sharing a machine with ours is not invisible, and now declared as gone.",
461
- measured: "2026-09-08: present on the legacy account ONLY as a retired-suffixed filename, which "
462
- + "systemd does not load. No loadable unit of this name under any account.", tracked: null,
456
+ measured: "2026-09-08, read on production: present ONLY as a retired-suffixed filename, which systemd "
457
+ + "does not load. No loadable unit of this name.", tracked: null,
463
458
  untrackedReason: "it is not this repo's service. Its ExecStart runs a script from a different "
464
459
  + "product's checkout on the same box, not under this clone — so there is no code here to "
465
460
  + "template, and the old reason (CF Access values inline) would send the next reader hunting for a "
@@ -524,12 +519,12 @@ export const UNIT_INVENTORY = Object.freeze([
524
519
  + "flag was ever captured, so stopping it dropped nothing. The decision owed, if any, is whether the "
525
520
  + "feedback machinery is removed rather than parked; driver/run-activity.mjs still carries a note "
526
521
  + "addressed to whoever picks that up, and it is still unclaimed.",
527
- note: "STOPPED. Production ran it every 30 minutes against an input nothing writes to any more"
528
- + "; the owner's word came 2026-08-20 and it was disabled the same evening.",
522
+ note: "STOPPED against an input nothing writes to any more; the owner's word came 2026-08-20 "
523
+ + "and it was disabled the same evening.",
529
524
  },
530
525
  // ── ANOTHER PRODUCT'S UNITS ARE NOT DECLARED HERE, AND THAT IS THE RULE (ruling 594, 2026-09-27) ──
531
526
  //
532
- // Five entries stood here describing a different product's services on the production box — a gateway, a
527
+ // Five entries stood here describing a different product's services on production — a gateway, a
533
528
  // notify adapter and three bridges — each with prose about how that box actually runs them. The owner's
534
529
  // rule: deployment-specific entries have no place in public open-source code, and the health check needs
535
530
  // its own services only.
@@ -549,15 +544,15 @@ export const UNIT_INVENTORY = Object.freeze([
549
544
  // deployments. Not here. This file ships.
550
545
  {
551
546
  unit: "trademark-test-deploy", runsOn: [],
552
- 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,
547
+ measured: "2026-09-07, read on the test deployment: 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,
553
548
  // AN EMPTY runsOn OWES A REASON, and this one is a supersession rather than an orphan: the hourly
554
- // deploy still runs on the test box, under the name `clearotron-deploy`, which has its own entry and
549
+ // deploy still runs on the test deployment, under the name `clearotron-deploy`, which has its own entry
555
550
  // its own measurement. This name is what that unit used to be called. It is kept rather than deleted
556
551
  // because the unit FILE is still tracked and an inventory of what ships should account for every
557
552
  // tracked file — deleting the entry would make the file unaccounted for, which is the ratchet this
558
553
  // file exists to keep shut.
559
554
  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.",
560
- untrackedReason: "the hourly --ff-only deploy of the TEST instance. It exists on the test box only "
555
+ untrackedReason: "the hourly --ff-only deploy of the TEST instance. It exists on that deployment only "
561
556
  + "and by design: production never auto-deploys, so a tracked file shipped to both would be a unit "
562
557
  + "production must be trusted never to enable.",
563
558
  },
@@ -565,7 +560,7 @@ export const UNIT_INVENTORY = Object.freeze([
565
560
  // row was right until the moment it was wrong. That nightly rotation was retired in code by:
566
561
  // bin/register-ledger-prune.mjs is deleted, record bodies now live in each run's own directory and
567
562
  // are purged with the run, so there is no global file left to rotate. The row stayed here on
568
- // purpose while the TIMER was still installed on the test box — dropping it first would have made
563
+ // purpose while the TIMER was still installed on the test deployment — dropping it first would have
569
564
  // an installed unit invisible to the very check that exists to find installed units nothing
570
565
  // describes. The timer was disabled and stopped on 2026-08-13, four hours before it would have
571
566
  // fired against the deleted script, and this row went with it. Re-listing it would re-declare a
@@ -728,7 +723,7 @@ export function unitInventoryVerdict({
728
723
  // units shipped WITH entries, those entries kept `runsOn: []`, and the pre-rename names kept the
729
724
  // boxes. Every arm scoped to CHECKED_UNITS — which filters on a NON-EMPTY runsOn — therefore asked
730
725
  // systemd about sixteen names that mostly named nothing and reported "0 active; 16 at rest", while
731
- // four services ran under names no entry claimed. Measured on the test box 2026-09-07.
726
+ // four services ran under names no entry claimed. Measured on the test deployment, 2026-09-07.
732
727
  //
733
728
  // This needs NO knowledge of which box it is running on, which is what makes it the right shape: an
734
729
  // entry saying a unit runs on no box is contradicted by that unit running HERE, wherever here is.
@@ -1,5 +1,9 @@
1
1
  # trademark-artifacts-mcp
2
2
 
3
+ ## 0.4.0-beta.3
4
+
5
+ No changes in this release.
6
+
3
7
  ## 0.4.0-beta.2
4
8
 
5
9
  No changes in this release.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trademark-artifacts-mcp",
3
- "version": "0.4.0-beta.2",
3
+ "version": "0.4.0-beta.3",
4
4
  "license": "AGPL-3.0-only",
5
5
  "private": true,
6
6
  "description": "MCP server to interrogate clearotron trademark-clearance runs — list/read artifacts, trace the full decision flow, telemetry/cost, coverage, single-run search, and a gated single-step what-if. Imports the clearotron-driver read-only; touches no driver/template/deploy files.",