clearotron 0.3.2-beta.10 → 0.3.2-beta.11
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.
- package/CONTRIBUTING.md +1 -0
- package/INSTALL.md +49 -46
- package/README.md +8 -7
- package/bin/onboard.mjs +44 -13
- package/bin/start.mjs +31 -6
- package/build-info.json +2 -2
- package/docs/architecture/05-config-governance.md +1 -1
- package/driver/CHANGELOG.md +400 -388
- package/driver/engine/mcp/recording-server.mjs +20 -0
- package/driver/package.json +1 -1
- package/driver/phase0.mjs +16 -7
- package/driver/pipeline.mjs +48 -1
- package/driver/portal-local-auth.mjs +14 -4
- package/driver/portal-service.mjs +12 -3
- package/driver/publish/attr.mjs +36 -0
- package/driver/publish/index.mjs +10 -10
- package/driver/publish/parse.mjs +1 -1
- package/driver/publish/render.mjs +9 -9
- package/driver/publish/xlsx.mjs +7 -1
- package/driver/queue-watch-verdict.mjs +1 -1
- package/driver/suite-census.json +59 -23
- package/driver/unit-inventory.mjs +7 -7
- package/mcp-server/CHANGELOG.md +23 -19
- package/mcp-server/lib/audit-view.mjs +4 -4
- package/mcp-server/lib/trace.mjs +1 -1
- package/mcp-server/package.json +1 -1
- package/package.json +2 -2
- package/portal-ui/package.json +1 -1
- package/providers/jx/README.md +2 -2
- package/providers/jx-subclass/README.md +1 -1
- package/providers/oauth-mcp-bridge/CHANGELOG.md +4 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/scripts/README.md +5 -10
- package/scripts/citation-line-check.mjs +2 -2
- package/scripts/e2e.mjs +8 -8
- package/scripts/generated-files-are-current.mjs +35 -4
- package/scripts/live-surface-check.mjs +17 -17
- package/scripts/release-code-scanning-check.mjs +114 -0
- package/scripts/release-visible-check.mjs +117 -0
- package/shared/invocation.mjs +2 -2
- package/shared/register-selection.mjs +4 -1
- package/shared/root-doc-commands.mjs +10 -4
- package/shared/scope.mjs +2 -2
package/driver/suite-census.json
CHANGED
|
@@ -394,8 +394,8 @@
|
|
|
394
394
|
"todos": 0
|
|
395
395
|
},
|
|
396
396
|
"a-gone-session-meets-a-door-not-a-json-body.test.mjs": {
|
|
397
|
-
"tests":
|
|
398
|
-
"asserts":
|
|
397
|
+
"tests": 6,
|
|
398
|
+
"asserts": 22,
|
|
399
399
|
"skips": 0,
|
|
400
400
|
"todos": 0
|
|
401
401
|
},
|
|
@@ -411,6 +411,18 @@
|
|
|
411
411
|
"skips": 0,
|
|
412
412
|
"todos": 0
|
|
413
413
|
},
|
|
414
|
+
"a-hostile-line-is-read-in-linear-time.test.mjs": {
|
|
415
|
+
"tests": 3,
|
|
416
|
+
"asserts": 7,
|
|
417
|
+
"skips": 0,
|
|
418
|
+
"todos": 0
|
|
419
|
+
},
|
|
420
|
+
"a-hostile-value-stays-inside-its-attribute.test.mjs": {
|
|
421
|
+
"tests": 6,
|
|
422
|
+
"asserts": 16,
|
|
423
|
+
"skips": 0,
|
|
424
|
+
"todos": 0
|
|
425
|
+
},
|
|
414
426
|
"a-jq-program-in-a-js-string-keeps-its-backslash.test.mjs": {
|
|
415
427
|
"tests": 2,
|
|
416
428
|
"asserts": 6,
|
|
@@ -453,6 +465,12 @@
|
|
|
453
465
|
"skips": 0,
|
|
454
466
|
"todos": 0
|
|
455
467
|
},
|
|
468
|
+
"a-link-in-the-workbook-is-not-banned-vocabulary.test.mjs": {
|
|
469
|
+
"tests": 2,
|
|
470
|
+
"asserts": 5,
|
|
471
|
+
"skips": 0,
|
|
472
|
+
"todos": 0
|
|
473
|
+
},
|
|
456
474
|
"a-local-install-hands-its-stores-to-every-reader.test.mjs": {
|
|
457
475
|
"tests": 1,
|
|
458
476
|
"asserts": 10,
|
|
@@ -532,8 +550,8 @@
|
|
|
532
550
|
"todos": 0
|
|
533
551
|
},
|
|
534
552
|
"a-new-install-signs-in-with-its-own-passphrase.test.mjs": {
|
|
535
|
-
"tests":
|
|
536
|
-
"asserts":
|
|
553
|
+
"tests": 10,
|
|
554
|
+
"asserts": 57,
|
|
537
555
|
"skips": 1,
|
|
538
556
|
"todos": 0
|
|
539
557
|
},
|
|
@@ -759,6 +777,12 @@
|
|
|
759
777
|
"skips": 0,
|
|
760
778
|
"todos": 0
|
|
761
779
|
},
|
|
780
|
+
"a-release-is-announced-only-once-a-stranger-can-install-it.test.mjs": {
|
|
781
|
+
"tests": 8,
|
|
782
|
+
"asserts": 19,
|
|
783
|
+
"skips": 0,
|
|
784
|
+
"todos": 0
|
|
785
|
+
},
|
|
762
786
|
"a-release-note-cannot-be-counted-twice.test.mjs": {
|
|
763
787
|
"tests": 12,
|
|
764
788
|
"asserts": 33,
|
|
@@ -885,6 +909,12 @@
|
|
|
885
909
|
"skips": 0,
|
|
886
910
|
"todos": 0
|
|
887
911
|
},
|
|
912
|
+
"a-stable-is-published-only-over-a-clean-code-scan.test.mjs": {
|
|
913
|
+
"tests": 9,
|
|
914
|
+
"asserts": 19,
|
|
915
|
+
"skips": 0,
|
|
916
|
+
"todos": 0
|
|
917
|
+
},
|
|
888
918
|
"a-stale-classification-names-the-rows-that-moved.test.mjs": {
|
|
889
919
|
"tests": 6,
|
|
890
920
|
"asserts": 24,
|
|
@@ -1510,8 +1540,8 @@
|
|
|
1510
1540
|
"todos": 0
|
|
1511
1541
|
},
|
|
1512
1542
|
"codename-freshness.test.mjs": {
|
|
1513
|
-
"tests":
|
|
1514
|
-
"asserts":
|
|
1543
|
+
"tests": 6,
|
|
1544
|
+
"asserts": 9,
|
|
1515
1545
|
"skips": 0,
|
|
1516
1546
|
"todos": 0
|
|
1517
1547
|
},
|
|
@@ -1714,8 +1744,8 @@
|
|
|
1714
1744
|
"todos": 0
|
|
1715
1745
|
},
|
|
1716
1746
|
"coverage-disclosure-carries-no-engine-output.test.mjs": {
|
|
1717
|
-
"tests":
|
|
1718
|
-
"asserts":
|
|
1747
|
+
"tests": 9,
|
|
1748
|
+
"asserts": 25,
|
|
1719
1749
|
"skips": 0,
|
|
1720
1750
|
"todos": 0
|
|
1721
1751
|
},
|
|
@@ -2573,7 +2603,7 @@
|
|
|
2573
2603
|
},
|
|
2574
2604
|
"free-tier-credential-sites.test.mjs": {
|
|
2575
2605
|
"tests": 5,
|
|
2576
|
-
"asserts":
|
|
2606
|
+
"asserts": 14,
|
|
2577
2607
|
"skips": 0,
|
|
2578
2608
|
"todos": 0
|
|
2579
2609
|
},
|
|
@@ -2872,8 +2902,8 @@
|
|
|
2872
2902
|
"todos": 0
|
|
2873
2903
|
},
|
|
2874
2904
|
"matter-frame-record.test.mjs": {
|
|
2875
|
-
"tests":
|
|
2876
|
-
"asserts":
|
|
2905
|
+
"tests": 25,
|
|
2906
|
+
"asserts": 88,
|
|
2877
2907
|
"skips": 0,
|
|
2878
2908
|
"todos": 0
|
|
2879
2909
|
},
|
|
@@ -2974,8 +3004,8 @@
|
|
|
2974
3004
|
"todos": 0
|
|
2975
3005
|
},
|
|
2976
3006
|
"no-test-writes-inside-the-checkout.test.mjs": {
|
|
2977
|
-
"tests":
|
|
2978
|
-
"asserts":
|
|
3007
|
+
"tests": 17,
|
|
3008
|
+
"asserts": 38,
|
|
2979
3009
|
"skips": 0,
|
|
2980
3010
|
"todos": 0
|
|
2981
3011
|
},
|
|
@@ -3005,7 +3035,7 @@
|
|
|
3005
3035
|
},
|
|
3006
3036
|
"onboard-wizard.test.mjs": {
|
|
3007
3037
|
"tests": 77,
|
|
3008
|
-
"asserts":
|
|
3038
|
+
"asserts": 294,
|
|
3009
3039
|
"skips": 2,
|
|
3010
3040
|
"todos": 0
|
|
3011
3041
|
},
|
|
@@ -3173,7 +3203,7 @@
|
|
|
3173
3203
|
},
|
|
3174
3204
|
"pipeline.mock.test.mjs": {
|
|
3175
3205
|
"tests": 98,
|
|
3176
|
-
"asserts":
|
|
3206
|
+
"asserts": 820,
|
|
3177
3207
|
"skips": 0,
|
|
3178
3208
|
"todos": 0
|
|
3179
3209
|
},
|
|
@@ -3455,7 +3485,7 @@
|
|
|
3455
3485
|
},
|
|
3456
3486
|
"provider-neutral-prose.test.mjs": {
|
|
3457
3487
|
"tests": 4,
|
|
3458
|
-
"asserts":
|
|
3488
|
+
"asserts": 8,
|
|
3459
3489
|
"skips": 0,
|
|
3460
3490
|
"todos": 0
|
|
3461
3491
|
},
|
|
@@ -3731,7 +3761,7 @@
|
|
|
3731
3761
|
},
|
|
3732
3762
|
"register-ledger-rename.test.mjs": {
|
|
3733
3763
|
"tests": 12,
|
|
3734
|
-
"asserts":
|
|
3764
|
+
"asserts": 33,
|
|
3735
3765
|
"skips": 0,
|
|
3736
3766
|
"todos": 0
|
|
3737
3767
|
},
|
|
@@ -3749,7 +3779,7 @@
|
|
|
3749
3779
|
},
|
|
3750
3780
|
"register-provider-required.test.mjs": {
|
|
3751
3781
|
"tests": 10,
|
|
3752
|
-
"asserts":
|
|
3782
|
+
"asserts": 28,
|
|
3753
3783
|
"skips": 0,
|
|
3754
3784
|
"todos": 0
|
|
3755
3785
|
},
|
|
@@ -3808,8 +3838,8 @@
|
|
|
3808
3838
|
"todos": 0
|
|
3809
3839
|
},
|
|
3810
3840
|
"release-pipeline.test.mjs": {
|
|
3811
|
-
"tests":
|
|
3812
|
-
"asserts":
|
|
3841
|
+
"tests": 120,
|
|
3842
|
+
"asserts": 452,
|
|
3813
3843
|
"skips": 0,
|
|
3814
3844
|
"todos": 0
|
|
3815
3845
|
},
|
|
@@ -4277,7 +4307,7 @@
|
|
|
4277
4307
|
},
|
|
4278
4308
|
"seat-outputs-outside-driver-tree.test.mjs": {
|
|
4279
4309
|
"tests": 5,
|
|
4280
|
-
"asserts":
|
|
4310
|
+
"asserts": 12,
|
|
4281
4311
|
"skips": 0,
|
|
4282
4312
|
"todos": 0
|
|
4283
4313
|
},
|
|
@@ -4335,6 +4365,12 @@
|
|
|
4335
4365
|
"skips": 0,
|
|
4336
4366
|
"todos": 0
|
|
4337
4367
|
},
|
|
4368
|
+
"setup-promises-a-login-shell-only-when-one-adds-the-directory.test.mjs": {
|
|
4369
|
+
"tests": 3,
|
|
4370
|
+
"asserts": 8,
|
|
4371
|
+
"skips": 0,
|
|
4372
|
+
"todos": 0
|
|
4373
|
+
},
|
|
4338
4374
|
"shipped-brand-is-the-product.test.mjs": {
|
|
4339
4375
|
"tests": 7,
|
|
4340
4376
|
"asserts": 24,
|
|
@@ -4606,8 +4642,8 @@
|
|
|
4606
4642
|
"todos": 0
|
|
4607
4643
|
},
|
|
4608
4644
|
"test-full-runs-every-corpus-or-names-the-one-it-did-not.test.mjs": {
|
|
4609
|
-
"tests":
|
|
4610
|
-
"asserts":
|
|
4645
|
+
"tests": 18,
|
|
4646
|
+
"asserts": 61,
|
|
4611
4647
|
"skips": 0,
|
|
4612
4648
|
"todos": 0
|
|
4613
4649
|
},
|
|
@@ -228,7 +228,7 @@ export const UNIT_INVENTORY = Object.freeze([
|
|
|
228
228
|
// checkout path an ordinary systemd expansion and leaves no placeholder to render.
|
|
229
229
|
note: "NOT RUNNING ANYWHERE, measured 2026-09-08. This row said LIVE ON PRODUCTION for as long as it "
|
|
230
230
|
+ "existed and no enumeration ever supported it. Was a TEMPLATE unit carrying identity-provider "
|
|
231
|
-
+ "values inline; generic since
|
|
231
|
+
+ "values inline; generic since the product installed its own units.",
|
|
232
232
|
orphanReason: "CLAIMED A DEPLOYMENT IT WAS NEVER MEASURED ON, which is a FOURTH kind of orphan and "
|
|
233
233
|
+ "the only one that was ever a wrong claim rather than a waiting decision: the other three run "
|
|
234
234
|
+ "under another name, were deliberately switched off, or have simply never been installed. This "
|
|
@@ -246,7 +246,7 @@ export const UNIT_INVENTORY = Object.freeze([
|
|
|
246
246
|
// it, against a fresh enumeration, which is the ratchet working rather than being edited around.
|
|
247
247
|
unit: "clearotron-portal", runsOn: ["test"], tracked: ["clearotron-portal.service"],
|
|
248
248
|
measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
|
|
249
|
-
note: "NEW,
|
|
249
|
+
note: "NEW, SHIPPED BUT NOT YET DEPLOYED. The portal had NO unit at all — it "
|
|
250
250
|
+ "and the MCP face are the two children bin/start.mjs supervises, and neither ran under systemd, "
|
|
251
251
|
+ "so a hosted deployment kept them alive with a hand launcher and `clearotron start` had nothing "
|
|
252
252
|
+ "to refuse in favour of.",
|
|
@@ -263,7 +263,7 @@ export const UNIT_INVENTORY = Object.freeze([
|
|
|
263
263
|
// asserting a production state no enumeration has ever shown.
|
|
264
264
|
unit: "clearotron-mcp-face", runsOn: ["test"], tracked: ["clearotron-mcp-face.service"],
|
|
265
265
|
measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
|
|
266
|
-
note: "NEW,
|
|
266
|
+
note: "NEW, SHIPPED BUT NOT YET DEPLOYED. The engine door the portal calls over "
|
|
267
267
|
+ "MCP; the other of the two processes that had no unit.",
|
|
268
268
|
orphanReason: "THE ENGINE DOOR THE PORTAL CALLS, shipped with no box carrying it yet. Same kind as "
|
|
269
269
|
+ "clearotron-portal beside it and as clearotron-deploy — never installed — and distinct from "
|
|
@@ -292,11 +292,11 @@ export const UNIT_INVENTORY = Object.freeze([
|
|
|
292
292
|
// enumeration of a box shows it running.
|
|
293
293
|
unit: "clearotron-client-mcp", runsOn: ["test"], tracked: ["clearotron-client-mcp.service"],
|
|
294
294
|
measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
|
|
295
|
-
note: "
|
|
295
|
+
note: "INSTALLED WITH THE PRODUCT since 2026-09-03. The client door "
|
|
296
296
|
+ "— the one surface that accepts an account-scoped key, and a separate process from the engine "
|
|
297
297
|
+ "door, which refuses one outright.",
|
|
298
|
-
orphanReason: "Awaiting a box. It joined the install set on 2026-09-03
|
|
299
|
-
+ "
|
|
298
|
+
orphanReason: "Awaiting a box. It joined the install set on 2026-09-03, superseding the "
|
|
299
|
+
+ "on-demand posture it shipped under, so `render-units.mjs --apply` "
|
|
300
300
|
+ "and `clearotron start --background` both place and enable it. It REFUSES TO START without "
|
|
301
301
|
+ "CLIENT_MCP_TOKEN_ONLY=1, CLIENT_MCP_ACCOUNT_ACCESS=1, the allow-list, the signing secret and "
|
|
302
302
|
+ "CLEAROTRON_ACCESS_FILE in the box's `%h/.env` (it otherwise demands an OIDC audience and an "
|
|
@@ -310,7 +310,7 @@ export const UNIT_INVENTORY = Object.freeze([
|
|
|
310
310
|
// it leaves a hosted box healthy-looking and draining nothing.
|
|
311
311
|
unit: "clearotron-worker", runsOn: ["test"], tracked: ["clearotron-worker.service"],
|
|
312
312
|
measured: "2026-09-07, test box, `systemctl --user show` with a working user bus: ActiveState=active, UnitFileState=enabled, fragment under ~/.config/systemd/user/.",
|
|
313
|
-
note: "NEW
|
|
313
|
+
note: "NEW. The drain, as one plain service unit invoking the entrypoint "
|
|
314
314
|
+ "directly (owner ruling 2026-08-31). Ships tracked, runs nowhere yet — production takes it at "
|
|
315
315
|
+ "its rebuild, which is the same event that lets the retired units' files leave the tree.",
|
|
316
316
|
orphanReason: "AWAITING A BOX, not an orphan by design. It is the hosted posture's drainer, and the "
|
package/mcp-server/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# trademark-artifacts-mcp
|
|
2
2
|
|
|
3
|
+
## 0.3.2-beta.11
|
|
4
|
+
|
|
5
|
+
No changes in this release.
|
|
6
|
+
|
|
3
7
|
## 0.3.2-beta.10
|
|
4
8
|
|
|
5
9
|
### Patch Changes
|
|
6
10
|
|
|
7
|
-
-
|
|
11
|
+
- Fixed: An assistant connected with nothing configured is now told which settings are missing, instead of being shown an empty list of searches.
|
|
8
12
|
|
|
9
13
|
## 0.3.2-beta.9
|
|
10
14
|
|
|
@@ -50,16 +54,16 @@ No changes in this release.
|
|
|
50
54
|
|
|
51
55
|
### Patch Changes
|
|
52
56
|
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
57
|
+
- Fixed: A clearance for a new client can be ordered through an assistant connector without setting up a company first.
|
|
58
|
+
- Fixed: Removing somebody's access now ends their assistant's connection on its next request. Until now an assistant that had already connected kept the access it started with for up to half an hour.
|
|
59
|
+
- Fixed: Ask your assistant for a client's recent searches by the client's name and it finds them. Every search in the list now says which client it was for, and which project. A search whose own record cannot be read says so, instead of appearing to belong to nobody.
|
|
60
|
+
- Fixed: A clearance that stops now always records that its notice is still owed, so a failure cannot be passed over as already handled.
|
|
61
|
+
- Fixed: Sending an access key to the engine's network address now gets a refusal that says so. It reports that the address takes an identity from the sign-in proxy and never a key.
|
|
58
62
|
|
|
59
63
|
Fixed: That refusal also names the local door where a key is accepted. Before, it reported only a missing sign-in assertion, which sent operators to the wrong configuration.
|
|
60
64
|
|
|
61
65
|
For operators: A program on the same machine can now reach the engine's local key door without setting a host name for it. The local door no longer applies a browser protection that only a network address needs.
|
|
62
|
-
-
|
|
66
|
+
- New: The free preview of a search lists, for each territory ordered, which registers legally bind it.
|
|
63
67
|
|
|
64
68
|
## 0.3.1-beta.4
|
|
65
69
|
|
|
@@ -69,20 +73,20 @@ No changes in this release.
|
|
|
69
73
|
|
|
70
74
|
### Patch Changes
|
|
71
75
|
|
|
72
|
-
-
|
|
73
|
-
-
|
|
76
|
+
- Fixed: Removing somebody's access now ends their assistant's connection on its next request. Until now an assistant that had already connected kept the access it started with for up to half an hour.
|
|
77
|
+
- Fixed: Ask your assistant for a client's recent searches by the client's name and it finds them. Every search in the list now says which client it was for, and which project. A search whose own record cannot be read says so, instead of appearing to belong to nobody.
|
|
74
78
|
|
|
75
79
|
## 0.3.1-beta.2
|
|
76
80
|
|
|
77
81
|
### Patch Changes
|
|
78
82
|
|
|
79
|
-
-
|
|
80
|
-
-
|
|
83
|
+
- Fixed: A clearance for a new client can be ordered through an assistant connector without setting up a company first.
|
|
84
|
+
- Fixed: Sending an access key to the engine's network address now gets a refusal that says so. It reports that the address takes an identity from the sign-in proxy and never a key.
|
|
81
85
|
|
|
82
86
|
Fixed: That refusal also names the local door where a key is accepted. Before, it reported only a missing sign-in assertion, which sent operators to the wrong configuration.
|
|
83
87
|
|
|
84
88
|
For operators: A program on the same machine can now reach the engine's local key door without setting a host name for it. The local door no longer applies a browser protection that only a network address needs.
|
|
85
|
-
-
|
|
89
|
+
- New: The free preview of a search lists, for each territory ordered, which registers legally bind it.
|
|
86
90
|
|
|
87
91
|
## 0.3.1-beta.1
|
|
88
92
|
|
|
@@ -92,7 +96,7 @@ No changes in this release.
|
|
|
92
96
|
|
|
93
97
|
### Patch Changes
|
|
94
98
|
|
|
95
|
-
-
|
|
99
|
+
- Fixed: A clearance that stops now always records that its notice is still owed, so a failure cannot be passed over as already handled.
|
|
96
100
|
|
|
97
101
|
## 0.3.0
|
|
98
102
|
|
|
@@ -122,7 +126,7 @@ No changes in this release.
|
|
|
122
126
|
|
|
123
127
|
### Patch Changes
|
|
124
128
|
|
|
125
|
-
-
|
|
129
|
+
- Fixed: On an install run with `clearotron start`, a connected assistant now lists the same saved searches as the portal, including Generic's. `clearotron doctor` no longer says working saved searches are off, and it names one place profiles come from.
|
|
126
130
|
|
|
127
131
|
## 0.3.0-beta.4
|
|
128
132
|
|
|
@@ -136,13 +140,13 @@ No changes in this release.
|
|
|
136
140
|
|
|
137
141
|
### Patch Changes
|
|
138
142
|
|
|
139
|
-
-
|
|
143
|
+
- Fixed: An assistant reading a knockout's filings through the connector now gets each filing's page at the trade mark office, as the report does. Where that register publishes no page for a single record, it gets the office and the number instead. Before, it got a reference that opens nowhere.
|
|
140
144
|
|
|
141
145
|
## 0.3.0-beta.1
|
|
142
146
|
|
|
143
147
|
### Patch Changes
|
|
144
148
|
|
|
145
|
-
-
|
|
149
|
+
- Fixed: A company you create in the browser now appears in your assistant's list of companies straight away.
|
|
146
150
|
|
|
147
151
|
It used to appear only after the service restarted, although a search could already be started for it. Its projects were missing from the list in the same way, and so was its account in the search options.
|
|
148
152
|
|
|
@@ -186,7 +190,7 @@ No changes in this release.
|
|
|
186
190
|
|
|
187
191
|
### Patch Changes
|
|
188
192
|
|
|
189
|
-
-
|
|
193
|
+
- New: Ask a what-if about a delivered report and get a supplementary memo over its archived evidence, without touching the report.
|
|
190
194
|
|
|
191
195
|
## 0.1.3
|
|
192
196
|
|
|
@@ -196,12 +200,12 @@ No changes in this release.
|
|
|
196
200
|
|
|
197
201
|
### Patch Changes
|
|
198
202
|
|
|
199
|
-
-
|
|
203
|
+
- Fixed: An assistant connected to Clearotron no longer asks permission before reading; it still asks before starting or stopping a search.
|
|
200
204
|
|
|
201
205
|
## 0.1.1-beta.1
|
|
202
206
|
|
|
203
207
|
### Patch Changes
|
|
204
208
|
|
|
205
|
-
-
|
|
209
|
+
- An assistant connected to Clearotron no longer asks permission before reading; it still asks before starting or stopping a search.
|
|
206
210
|
|
|
207
211
|
## 0.1.1-beta.0
|
|
@@ -261,10 +261,10 @@ export function accountTrace(result) {
|
|
|
261
261
|
out.auditTrailNote = result.auditTrailNote ?? null;
|
|
262
262
|
}
|
|
263
263
|
// `note` is NOT forwarded, and this is the one place a raw string looked harmless and was not. trace's
|
|
264
|
-
// verdict branch returns a hard-coded sentence
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
//
|
|
264
|
+
// verdict branch returns a hard-coded sentence written for whoever operates the engine, not for a
|
|
265
|
+
// client — a literal, so no prose filter would ever catch what it says: the scrub transforms MODEL
|
|
266
|
+
// output, and this is ours. The fact it carries is worth keeping, so it is restated here in client
|
|
267
|
+
// words rather than dropped: what the verdict is FOR.
|
|
268
268
|
if (result.note) out.note = result.resolvedAs?.kind === "verdict"
|
|
269
269
|
? "The verdict gates delivery: a reviewer reads the narrative against the source records and rules CLEAR, CONDITIONAL or BLOCKING. Anything short of CLEAR sends the work back for a corrective pass, and an unresolved concern is raised rather than withheld."
|
|
270
270
|
: clean(result.note);
|
package/mcp-server/lib/trace.mjs
CHANGED
|
@@ -242,7 +242,7 @@ export function trace(run, target, { depth = 2, shallow = false } = {}) {
|
|
|
242
242
|
out.auditTrail = relatedAuditRows(findings.audit, f);
|
|
243
243
|
out.auditTrailNote = "Best-effort match of audit-trail rows to this finding; the full audit trail is available via list_findings(kind:'audit').";
|
|
244
244
|
} else if (resolved.kind === "verdict") {
|
|
245
|
-
out.note = "The verdict gates delivery: the refutation reviewer reads narrative + the source files and writes CLEAR / CONDITIONAL / BLOCKING. A non-CLEAR verdict triggers a corrective re-synthesis; unresolved concerns are surfaced to
|
|
245
|
+
out.note = "The verdict gates delivery: the refutation reviewer reads narrative + the source files and writes CLEAR / CONDITIONAL / BLOCKING. A non-CLEAR verdict triggers a corrective re-synthesis; unresolved concerns are surfaced to the reader (never withheld).";
|
|
246
246
|
}
|
|
247
247
|
return out;
|
|
248
248
|
}
|
package/mcp-server/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trademark-artifacts-mcp",
|
|
3
|
-
"version": "0.3.2-beta.
|
|
3
|
+
"version": "0.3.2-beta.11",
|
|
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.",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clearotron",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.3.2-beta.
|
|
4
|
+
"version": "0.3.2-beta.11",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/CordilleraSarl/clearotron/issues"
|
|
13
13
|
},
|
|
14
|
-
"description": "
|
|
14
|
+
"description": "Trademark clearance engine. Searches the registers and the open web, rates the conflicts, and delivers a written report with the record behind every finding.",
|
|
15
15
|
"keywords": [
|
|
16
16
|
"trademark",
|
|
17
17
|
"trademark-clearance",
|
package/portal-ui/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "portal-ui",
|
|
3
3
|
"private": true,
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.3.2-beta.
|
|
5
|
+
"version": "0.3.2-beta.11",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"description": "The unified trademark portal UI. One address, one login: who you are decides what you see. Built as a static bundle, served by driver/portal-service.mjs — the browser never reaches profile-service or recipe-service.",
|
|
8
8
|
"engines": {
|
package/providers/jx/README.md
CHANGED
|
@@ -4,14 +4,14 @@ Three pure modules, **one non-agentic structured turn each, per mark × lane**,
|
|
|
4
4
|
configured for. Not an agent: no tools, no MCP, no skills, no resume — one prompt in, one JSON object out,
|
|
5
5
|
validated at parse.
|
|
6
6
|
|
|
7
|
-
## What these lanes
|
|
7
|
+
## What these lanes are, and what runs them
|
|
8
8
|
|
|
9
9
|
**One vendor, one billing mode, decided by the run and not by this directory.** The lanes go through
|
|
10
10
|
`engine.runTurn()` — the same door all fourteen agentic stages use — via
|
|
11
11
|
[`../../driver/engine/jx-turn.mjs`](../../driver/engine/jx-turn.mjs). Whatever program the customer configured
|
|
12
12
|
(`CLEAROTRON_AI`) and whatever billing mode the run is on (subscription, API key or, for Claude, a cloud account)
|
|
13
13
|
carries these calls too.
|
|
14
|
-
That is the
|
|
14
|
+
That is the product's rule — *one reasoning provider per run, API or subscription, never a mix* — and until 2026-08-20
|
|
15
15
|
these three lanes were the one place in the product that broke it: they POSTed to the Anthropic Messages API on
|
|
16
16
|
`ANTHROPIC_API_KEY` at a hardcoded cheap tier no matter what the rest of the run was doing.
|
|
17
17
|
|
|
@@ -72,7 +72,7 @@ class 44) and `351918` (cosmetics retail, class 35). A class-3 search finds neit
|
|
|
72
72
|
goods that have a Nice basic number (609), so validating a relation's target group against it would drop
|
|
73
73
|
real relations without a word. The authority is `tw/tw-group-codes.json`, taken from TIPO's group headers.
|
|
74
74
|
|
|
75
|
-
## Korea
|
|
75
|
+
## Korea
|
|
76
76
|
|
|
77
77
|
KIPO publishes 「유사상품 심사기준(니스 제13판)」 as a direct download: **21.8 MB, 1,011 pages, full text
|
|
78
78
|
layer** (`kpoContFileDown.do?seq=30&fileNum=25`, Referer header required).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trademark-oauth-mcp-bridge",
|
|
3
|
-
"version": "0.3.2-beta.
|
|
3
|
+
"version": "0.3.2-beta.11",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"private": true,
|
|
6
6
|
"description": "OAuth 2.1 MCP stdio bridge used by the engine's case-law gather stage (courtlistener / legaldatahunter).",
|
package/scripts/README.md
CHANGED
|
@@ -13,7 +13,7 @@ The axis is *what the script assumes exists*, not where it happens to be run.
|
|
|
13
13
|
| Script | What it does |
|
|
14
14
|
|---|---|
|
|
15
15
|
| `test-run.mjs` | Gives a test run its own `TMPDIR` and deletes it at exit. **Load-bearing** — every workspace's `npm test` shells out to it, so `scripts/` can never be dropped wholesale. |
|
|
16
|
-
| `render-check.mjs` | Renders a published report **inside the portal's iframe** in a real browser — the height bridge, the scrollbar loop, the sticky topbar. Needs a published run: point it at a pool with `--pool`, or pass `--fixture-pool` to replay `demo/` into a throwaway one.
|
|
16
|
+
| `render-check.mjs` | Renders a published report **inside the portal's iframe** in a real browser — the height bridge, the scrollbar loop, the sticky topbar. Needs a published run: point it at a pool with `--pool`, or pass `--fixture-pool` to replay `demo/` into a throwaway one. Run by CI on a fixture pool. Its interior assertions measure deterministically: real time plus an explicit readiness signal, and `--plant-overflow` proves it still catches a broken report. |
|
|
17
17
|
| `home-render-check.mjs` | Draws the portal Home in a real browser, every state, both themes. Run by CI. |
|
|
18
18
|
| `composer-render-check.mjs` | Lays out the New Clearance composer and checks the levers reach the wire. Run by CI. |
|
|
19
19
|
| `clearances-render-check.mjs` | Checks the `/portal/clearances` columns hold together. Run by CI. |
|
|
@@ -80,15 +80,10 @@ settling on the first try every time, and the slack figures that looked like a l
|
|
|
80
80
|
147px against a 15-24 band) turned out to be the stale probe too. The sandbox is byte-identical to
|
|
81
81
|
`Result.tsx`'s and `allow-same-origin` was never added.
|
|
82
82
|
|
|
83
|
-
**
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Read the other six with that in mind: they are outer-document measurements — does the page scroll, is
|
|
88
|
-
the header pinned, is Export reachable — and every one would pass against **an iframe that loaded
|
|
89
|
-
nothing**, because the frame is styled to a fixed height. A green from this check would have meant
|
|
90
|
-
almost nothing. The step is backed out and the script is declared, with the measurement, rather than
|
|
91
|
-
quietly dropped.
|
|
83
|
+
**CI runs it**, on a pool replayed from `demo/` into a throwaway directory:
|
|
84
|
+
`node scripts/render-check.mjs --fixture-pool`. Its outer-document assertions — does the page scroll, is
|
|
85
|
+
the header pinned, is Export reachable — would pass against an iframe that loaded nothing, because the
|
|
86
|
+
frame is styled to a fixed height; the interior ones above are what make a green mean something.
|
|
92
87
|
|
|
93
88
|
**Which check runs where is now checked, not just written here.** A test in the driver suite
|
|
94
89
|
reads `.github/workflows/ci.yml` and requires every `scripts/*-check.mjs` to be either invoked by a job
|
|
@@ -79,10 +79,10 @@ export const EXEMPT_TARGETS = [
|
|
|
79
79
|
{ target: /^driver\/(x|a|f|nope)\.mjs$/, why: "planted names in contract-audit.test.mjs — the test feeds the auditor a citation to a file that does not exist ON PURPOSE" },
|
|
80
80
|
{ target: /^driver\/skills\/[ab]\/(rules|SKILL)\.md$/, why: "planted skill paths in contract-audit.test.mjs, same shape" },
|
|
81
81
|
{ target: /^planted\//, why: "THE NAMESPACE for a fixture path that must not exist. publication-scrub.test.mjs plants an undeclared path to prove the scrubber sees it, and cut-vendor-keys.test.mjs plants one to prove the record-key detector reports a location. Unlike the namespaced entries below, this one is deliberately shared: `planted/` names the class rather than one test's fixtures, so a new test planting a non-existent path uses it instead of inventing a second convention — and a bare invented name is what reports as a dangling citation to a file nobody meant to create" },
|
|
82
|
-
{ target: /^diffcase-[a-z]+\.mjs$/, why: "SYNTHETIC DIFF FIXTURE FILENAMES in pushed-content-guard.test.mjs
|
|
82
|
+
{ target: /^diffcase-[a-z]+\.mjs$/, why: "SYNTHETIC DIFF FIXTURE FILENAMES in pushed-content-guard.test.mjs. That test feeds `addedLines` a hand-written unified diff, so line 4 of `keep.mjs` is DIFF DATA the guard must parse, not a citation to anything. Same class as the contract-audit planted names directly above: a test that must contain a file reference to a file that does not exist, on purpose. NAMESPACED `diffcase-` deliberately: a first cut exempted the bare names `keep|dropped|gone|zz` and SWALLOWED two of this file's own controls, which plant line 12 of `gone.mjs` — an exemption wide enough to cover somebody else's known-bad turns their arm green while it proves nothing" },
|
|
83
83
|
{ target: /^driver\/engine\/mcp\/planted-server\.mjs$/, why: "a planted server module name in contract-audit.test.mjs" },
|
|
84
84
|
{ target: /^srv\/app\//, why: "SYNTHETIC DEPLOYMENT STACK TRACES. The house rule for fixtures is to use a `/srv/…` path and never a real `/home/<name>/` one (deployment-hostnames.test.mjs polices the other half), so a hand-written trace like \"TypeError: x is not a function at /srv/app/driver/pipeline.mjs:2411:9\" is test DATA the parser under test must read — the line number is the datum, not a claim about our tree. It passed for as long as it did by luck: this resolver strips the prefix and lands on the real driver/pipeline.mjs, so the fixture went green while whatever line it happened to name was real code, and reported BLANK the first time an unrelated edit made that line a brace. NAMESPACED to `srv/app/` for the reason the diffcase- entry gives — nothing in this repo ships under srv/, and a wider prefix would swallow a genuine citation someone writes tomorrow" },
|
|
85
|
-
{ target: /^(?:driver\/)?driftcase-[a-z-]+\.mjs$/, why: "SYNTHETIC DRIFT FIXTURE FILENAMES in citation-drift-at-the-diff.test.mjs
|
|
85
|
+
{ target: /^(?:driver\/)?driftcase-[a-z-]+\.mjs$/, why: "SYNTHETIC DRIFT FIXTURE FILENAMES in citation-drift-at-the-diff.test.mjs. That test feeds the drift report a hand-built corpus in which line 40 of `driftcase-target.mjs` is the DATUM being classified — the thing whose movement is measured — not a citation to anything. Same class as the planted names above, and NAMESPACED under `driver/` for the reason the `diffcase-` entry gives: an exemption wide enough to cover another test's known-bad turns their arm green while it proves nothing. The directory prefix is OPTIONAL because one arm cites the BARE BASENAME on purpose: that is the exact shape that made `resolveCited` short-circuit on an always-true `exists` and print a clean tick, so the arm cannot be written any other way. `driftcase-` carries the namespacing on its own — nothing else in this tree uses the prefix" },
|
|
86
86
|
{ target: /^common-law-findings\.md$/, why: "a RUN ARTIFACT, written into a run directory at execution time. It is cited by name in doubt-ledger and audit-from-spine tests because that is what the artifact is called; it is not and never will be a tracked file" },
|
|
87
87
|
// ✕ REMOVED: `codex/dist/(helper|cli).js` — a captured CODEX stack trace in
|
|
88
88
|
// exit-cause-survives-the-digest.test.mjs. Both of its citations carry a COLUMN, so `citationsIn`
|
package/scripts/e2e.mjs
CHANGED
|
@@ -922,7 +922,7 @@ export async function enqueueViaMcp(job, { clientPrincipal = false, forwarder =
|
|
|
922
922
|
// harness named the door that BEHAVED as the defect. Two hours later the codex arm hit no 429 and the
|
|
923
923
|
// same case was clean — so the finding also reads as a flake, which is the worst of both.
|
|
924
924
|
//
|
|
925
|
-
// The rule the asymmetry check encodes
|
|
925
|
+
// The rule the door-asymmetry check encodes is sound: for a case both doors should refuse, the one
|
|
926
926
|
// that accepted is the bug. It rests on an assumption nobody wrote down — that a refusal is a
|
|
927
927
|
// PRODUCT-SCOPE JUDGMENT. A 429 or a 5xx is not a judgment. The request died in the transport, before
|
|
928
928
|
// `start_run` ran a single scope check, so that door holds no opinion about this case at all.
|
|
@@ -945,7 +945,7 @@ export function doorAnswerClass(answer) {
|
|
|
945
945
|
}
|
|
946
946
|
|
|
947
947
|
/**
|
|
948
|
-
* The
|
|
948
|
+
* The door-asymmetry verdict, over the doors that actually answered.
|
|
949
949
|
* Returns { agreed, compared, unavailable, reducedCoverage } — `agreed` is TRUE when fewer than two
|
|
950
950
|
* doors answered, because one opinion is not a disagreement and must never be reported as one.
|
|
951
951
|
*/
|
|
@@ -2141,7 +2141,7 @@ async function cmdRun(id) {
|
|
|
2141
2141
|
|
|
2142
2142
|
const jobs = s.job ? [{ id: s.id, job: s.job, kase: {} }] : (s.cases ?? []).map((c) => ({ id: c.id, job: c.job, what: c.what, oneMatterAcrossDoors: c.oneMatterAcrossDoors === true, expectTerminal: (c.expect ?? {}).terminal ?? null, kase: c }));
|
|
2143
2143
|
|
|
2144
|
-
// door: "all" is the point of R0 — a rule enforced in one door and not another is exactly the
|
|
2144
|
+
// door: "all" is the point of R0 — a rule enforced in one door and not another is exactly the door
|
|
2145
2145
|
// asymmetry. Every case goes through EVERY drivable door and the answers are compared. runner.mjs's
|
|
2146
2146
|
// claimAndPrep is the wall they all land on, so they must agree; if they ever do not, the door that
|
|
2147
2147
|
// admits is the bug, not the door that refuses. A case that declares `doors` goes through those alone
|
|
@@ -2662,7 +2662,7 @@ function printPreviousRoundNotice(s) {
|
|
|
2662
2662
|
}
|
|
2663
2663
|
|
|
2664
2664
|
// `run` records what each door answered, because `report` runs later in a different process and cannot
|
|
2665
|
-
// otherwise know. A rule enforced in one door and waved through by another is exactly the
|
|
2665
|
+
// otherwise know. A rule enforced in one door and waved through by another is exactly the door asymmetry,
|
|
2666
2666
|
// and it is invisible unless the answers are compared.
|
|
2667
2667
|
//
|
|
2668
2668
|
// — the receipt's PATH and FORMAT moved to driver/e2e-rounds.mjs (`receiptPath`, `readReceipt`),
|
|
@@ -2686,7 +2686,7 @@ function printPreviousRoundNotice(s) {
|
|
|
2686
2686
|
export function doorRefusal(receipt, ref, expect = null) {
|
|
2687
2687
|
const rc = (receipt?.cases ?? []).find((c) => c.ref === ref) ?? null;
|
|
2688
2688
|
const recorded = rc?.answers ?? [];
|
|
2689
|
-
// — ONLY THE DOORS THAT ANSWERED. `doorAsymmetry` has excluded unavailable doors from the
|
|
2689
|
+
// — ONLY THE DOORS THAT ANSWERED. `doorAsymmetry` has excluded unavailable doors from the door
|
|
2690
2690
|
// comparison since, but this function did not, and it is the one that prints
|
|
2691
2691
|
// "refused at the door by cli, ops-mcp". A door that was never asked was listed there as a refuser,
|
|
2692
2692
|
// so a case where one door refused correctly and the other did not exist read EXACTLY like a case
|
|
@@ -3175,7 +3175,7 @@ async function cmdReport(id, { round: requestedToken = null } = {}) {
|
|
|
3175
3175
|
// notice is OWED depends on the terminal, and the terminal is what could not be established.
|
|
3176
3176
|
const owesNotice = q.terminal === "clarify" || q.terminal === "duplicate" || q.terminal === "failed" || q.undetermined;
|
|
3177
3177
|
if (owesNotice) {
|
|
3178
|
-
// The contract
|
|
3178
|
+
// The contract: a refusal must PARK *and NOTIFY*, never fail silently.
|
|
3179
3179
|
console.log(` requester notified: ${
|
|
3180
3180
|
q.packets.length ? q.packets.join(", ")
|
|
3181
3181
|
: q.packetsUnreadable ? `CANNOT TELL — ${q.packetsUnreadable}`
|
|
@@ -3342,7 +3342,7 @@ async function cmdReport(id, { round: requestedToken = null } = {}) {
|
|
|
3342
3342
|
// CASE-level asserts are evaluated too. They were declared and never reached: this loop read only
|
|
3343
3343
|
// `s.expect.assert`, and `kase` was consulted solely for `terminal` and `reasonMatches`. R0 has no
|
|
3344
3344
|
// scenario-level asserts at all, so R0 ran ZERO assertions — and R0e's `profileKey == "generic"`,
|
|
3345
|
-
// the only substantive check in the whole scenario and the entire point of the
|
|
3345
|
+
// the only substantive check in the whole scenario and the entire point of the roster-blindness
|
|
3346
3346
|
// case, was silently dead. Same class of defect as the artifacts key above: declared, never asked.
|
|
3347
3347
|
for (const a of [...(s.expect?.assert ?? []), ...(kase?.expect?.assert ?? [])]) {
|
|
3348
3348
|
const r = evalAssertion(a, runDir);
|
|
@@ -3405,7 +3405,7 @@ async function cmdReport(id, { round: requestedToken = null } = {}) {
|
|
|
3405
3405
|
}
|
|
3406
3406
|
// ── did every door give the same answer? ────────────────────────────────────────────────────────────
|
|
3407
3407
|
// Only R0 drives more than one door. A rule enforced at one door and waved through by another is the
|
|
3408
|
-
//
|
|
3408
|
+
// door asymmetry, and it is invisible unless the answers are compared — so `run` records them and this
|
|
3409
3409
|
// reads the receipt. No receipt is reported as "cannot tell", never as agreement.
|
|
3410
3410
|
if (s.door === "all") {
|
|
3411
3411
|
// — read THIS ROUND's answers, and distinguish the three ways they can be missing: no receipt
|