clearotron 0.3.2-beta.2 → 0.3.2-beta.4

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 (54) hide show
  1. package/.env.example +10 -0
  2. package/INSTALL.md +2 -0
  3. package/README.md +15 -10
  4. package/bin/onboard.mjs +4 -4
  5. package/build-info.json +2 -2
  6. package/docs/CLIENT-MCP.md +54 -54
  7. package/docs/DELIVERY.md +16 -15
  8. package/docs/E2E.md +8 -8
  9. package/docs/GLOSSARY.md +2 -2
  10. package/docs/INTAKE.md +11 -11
  11. package/docs/ONBOARDING.md +17 -16
  12. package/docs/PORTAL.md +18 -16
  13. package/docs/README.md +10 -10
  14. package/docs/SECURITY.md +20 -20
  15. package/docs/architecture/01-product-overview.md +17 -16
  16. package/docs/architecture/02-architecture.md +6 -6
  17. package/docs/architecture/03-run-lifecycle.md +7 -7
  18. package/docs/architecture/04-configuration-reference.md +14 -13
  19. package/docs/architecture/05-config-governance.md +30 -29
  20. package/docs/architecture/05-customer-profiles.md +35 -35
  21. package/docs/architecture/06-operations-runbook.md +20 -20
  22. package/docs/architecture/07-quality-and-audit.md +17 -17
  23. package/docs/architecture/08-development-guide.md +3 -3
  24. package/docs/architecture/09-security-and-data.md +27 -27
  25. package/docs/architecture/README.md +1 -1
  26. package/docs/branding.md +8 -3
  27. package/docs/configuration.md +18 -18
  28. package/docs/writing-standard.md +3 -3
  29. package/driver/CHANGELOG.md +36 -0
  30. package/driver/package.json +1 -1
  31. package/driver/portal-service.mjs +34 -4
  32. package/driver/suite-census.json +114 -48
  33. package/mcp-server/CHANGELOG.md +8 -0
  34. package/mcp-server/package.json +1 -1
  35. package/mcp-server/packs/client/CONNECT.md +6 -6
  36. package/package.json +1 -1
  37. package/portal-ui/dist/assets/{index-BsbasHjM.js → index-5UyqAyNM.js} +3384 -2973
  38. package/portal-ui/dist/assets/{index-DNQpLYZF.css → index-CVOIvdhc.css} +992 -205
  39. package/portal-ui/dist/index.html +2 -2
  40. package/portal-ui/package.json +1 -1
  41. package/providers/_shared/script-form.mjs +2 -2
  42. package/providers/clarivate/src/core.js +18 -27
  43. package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
  44. package/providers/oauth-mcp-bridge/package.json +1 -1
  45. package/providers/signa/src/core.js +3 -3
  46. package/scripts/ask-ai-render-check.mjs +287 -105
  47. package/scripts/env-classify.mjs +6 -0
  48. package/scripts/release-note-required.mjs +16 -2
  49. package/scripts/settings-render-check.mjs +575 -0
  50. package/shared/brand.mjs +29 -0
  51. package/shared/connect-clients.mjs +99 -47
  52. package/shared/names-in-force.mjs +1 -0
  53. package/shared/stdio-connect.mjs +16 -2
  54. package/shared/writing-standard-classes.mjs +34 -3
@@ -49,8 +49,8 @@
49
49
  -->
50
50
  <link rel="preconnect" href="https://api.fontshare.com" crossorigin />
51
51
  <link href="https://api.fontshare.com/v2/css?f[]=satoshi@400,500,700,900&display=swap" rel="stylesheet" />
52
- <script type="module" crossorigin src="/portal/assets/index-BsbasHjM.js"></script>
53
- <link rel="stylesheet" crossorigin href="/portal/assets/index-DNQpLYZF.css">
52
+ <script type="module" crossorigin src="/portal/assets/index-5UyqAyNM.js"></script>
53
+ <link rel="stylesheet" crossorigin href="/portal/assets/index-CVOIvdhc.css">
54
54
  </head>
55
55
  <body>
56
56
  <div id="root"></div>
@@ -2,7 +2,7 @@
2
2
  "name": "portal-ui",
3
3
  "private": true,
4
4
  "type": "module",
5
- "version": "0.3.2-beta.2",
5
+ "version": "0.3.2-beta.4",
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": {
@@ -106,8 +106,8 @@ export function romanizationRefusal(value) {
106
106
  }
107
107
 
108
108
  /** The two spellings a register may hold for one romanisation — syllable-separated as the record
109
- * writes it, and run together as a searcher would type it. Probed: identical counts on CN/TW/GR/KR/TH,
110
- * but EG differs (7 vs 10), so BOTH are emitted and OR-joined rather than picking one. */
109
+ * writes it, and run together as a searcher would type it. On most scripts a register holds the two
110
+ * spellings alike, but not on all of them — so BOTH are emitted and OR-joined rather than picking one. */
111
111
  export function romanizationSpellings(value) {
112
112
  const spaced = String(value ?? "").normalize("NFC").trim().replace(/\s+/g, " ");
113
113
  if (!spaced) return [];
@@ -220,8 +220,8 @@ export function assertSingleMarkShape(rawTerm) {
220
220
  }
221
221
  return tokens;
222
222
  }
223
- // Read as OPERATORS wherever they stand alone in a value string, case-insensitively ("monster adj
224
- // energy" = 67), with an optional proximity digit (ADJ2 = 72).
223
+ // Read as OPERATORS wherever they stand alone in a value string, case-insensitively, with an
224
+ // optional proximity digit.
225
225
  const RESERVED_TOKEN_RE = /^(?:AND|OR|NOT|ADJ|NEAR)\d*$/i;
226
226
  const PUNCT_ONLY_RE = /^[^\p{L}\p{N}]+$/u;
227
227
 
@@ -229,22 +229,18 @@ const PUNCT_ONLY_RE = /^[^\p{L}\p{N}]+$/u;
229
229
  * An operator word inside a phrase is DROPPED, and the gap it leaves is spanned by widening that one
230
230
  * adjacency to `ADJ<n+1>`.
231
231
  *
232
- * The obvious move — make the word lexically stop being an operator with an interior `?` — is WRONG,
233
- * and measurably so. Registers write these marks with an ampersand, not the word:
234
- *
235
- * *BLACK ADJ A?D ADJ DECKER* 0 ← what the `?` escape asks for, and nothing is named that
236
- * *BLACK ADJ DECKER* 55 ← BLACK & DECKER
237
- * *BLACK ADJ2 DECKER* 55 ← identical: the connector is not indexed, so spanning costs nothing
238
- * *BEN ADJ A?D ADJ JERRYS* 0 vs *BEN ADJ JERRYS* 25
232
+ * The obvious move — make the word lexically stop being an operator with an interior `?` — is WRONG.
233
+ * Registers write these marks with an ampersand and not the word, so the escaped form names NOTHING,
234
+ * while the plain adjacency finds the mark and the widened adjacency finds exactly the same set.
239
235
  *
240
236
  * A zero over a mark that exists is the failure this whole contract is built to prevent, so the escape
241
237
  * is gone. Dropping + `ADJ2` is right whether or not the index holds the word: if it is a stopword the
242
- * neighbours are already adjacent (55 == 55 above), and if some register does index it the widened
243
- * adjacency still reaches across. It is a superset of the literal phrase — safe in the direction a
244
- * clearance sweep needs, which fails by MISSING a mark and never by surfacing an extra one.
238
+ * neighbours are already adjacent — plain and widened return the same set — and if some register does
239
+ * index it the widened adjacency still reaches across. It is a superset of the literal phrase — safe in
240
+ * the direction a clearance sweep needs, which fails by MISSING a mark and never by surfacing an extra one.
245
241
  *
246
- * `ADJ<n>` is real and probed: MONSTER ADJ ENERGY = 67, MONSTER ADJ2 ENERGY = 72, SALT ADJ PEPPER = 27
247
- * vs SALT ADJ2 PEPPER = 52 — so the widening is genuinely a widening, not a no-op we cannot see.
242
+ * `ADJ<n>` is real: the widened form returns strictly more than the tighter one, so the widening is
243
+ * genuinely a widening and not a no-op we cannot see.
248
244
  */
249
245
  export function isReservedToken(tok) {
250
246
  return RESERVED_TOKEN_RE.test(tok);
@@ -286,21 +282,16 @@ export function compilePhraseValue(term, { pre = "", post = "", dropReserved = f
286
282
 
287
283
  // A LEADING `*` on a ONE-CHARACTER first token is a sub-query over most of the register, and inside an
288
284
  // ADJ chain the provider gives up on it: HTTP 500 "Near/Adj queries with sub queries that can return a
289
- // huge amount…". Probed — one character breaks, two do not:
290
- // *I ADJ CANT ADJ BELIEVE* 500 *IT ADJ STARTS ADJ WITH* 103
291
- // *A ADJ BAR* 500 *AN ADJ APPLE* 55
292
- // So the leading wrap is dropped for that one case, and ONLY that case. It costs a little recall at
293
- // the leading token boundary (AN ADJ APPLE* = 31 vs *AN ADJ APPLE* = 55), which is why it is not done
294
- // generally — but the alternative here is not a narrower search, it is no search at all.
285
+ // huge amount…". The refusal is specific to a first token of ONE character; two characters are answered.
286
+ // So the leading wrap is dropped for that one case, and ONLY that case. It costs a little recall at the
287
+ // leading token boundary, which is why it is not done generally — but the alternative here is not a
288
+ // narrower search, it is no search at all.
295
289
  const leadWrap = (kept.length > 1 && kept[0].length === 1) ? "" : pre;
296
290
  // AND THE SAME AT THE OTHER END, which was never added and cost a family search on a live matter. A
297
291
  // root whose LAST word is one character — a sequel number, an article, an initial — compiled to
298
292
  // `*PLAN ADJ B*`, and the trailing `B*` is the same sub-query over most of the register that the
299
- // leading rule above exists for. Probed on the test install, count calls only:
300
- // *PLAN ADJ B* 500 *PLAN ADJ B 200, 36 records
301
- // *LEVEL ADJ 2* 500 *LEVEL ADJ 2 200, 14 records
302
- // *ROB ADJ A* 500 *ROB ADJ A 200, 3 records
303
- // A delivered run planned a family search on such a root, every attempt was refused, the refusal was
293
+ // leading rule above exists for: the provider refuses that shape and answers the same query with the
294
+ // trailing star removed. A delivered run planned a family search on such a root, every attempt was refused, the refusal was
304
295
  // retried as if transient and the slice was filed as a provider gap — so a family of pending filings
305
296
  // for a third-party title went unseen and the matter was rated on what was left.
306
297
  const last = kept.length - 1;
@@ -517,8 +508,8 @@ export function hasAnyElement(p) {
517
508
 
518
509
  /**
519
510
  * Join terms into ONE value string with the EXPLICIT " OR " operator (a bare space is an implicit AND,
520
- * not an OR). ADJ binds tighter than OR, so phrase operands need no parentheses — probed:
521
- * `*MOUNTAIN ADJ DEW* OR *MONSTER ADJ ENERGY*` = 157 = 90 + 67, identical with parens.
511
+ * not an OR). ADJ binds tighter than OR, so phrase operands need no parentheses: an OR of two phrases
512
+ * returns the union of the two, and parentheses around them change nothing.
522
513
  * The width bound is the parser's document-nesting cap; the enumerate
523
514
  * kernel chunks wide `names` stacks at capabilities.kernel.namesChunkDefault (= maxOrWidth) before they
524
515
  * ever reach here, so hitting this throw means a caller bypassed the kernel.
@@ -1,5 +1,13 @@
1
1
  # trademark-oauth-mcp-bridge
2
2
 
3
+ ## 0.3.2-beta.4
4
+
5
+ No changes in this release.
6
+
7
+ ## 0.3.2-beta.3
8
+
9
+ No changes in this release.
10
+
3
11
  ## 0.3.2-beta.2
4
12
 
5
13
  No changes in this release.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trademark-oauth-mcp-bridge",
3
- "version": "0.3.2-beta.2",
3
+ "version": "0.3.2-beta.4",
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).",
@@ -793,9 +793,9 @@ export async function doCountHits(apiKey, base, params, tctx, { mock = false } =
793
793
  const parsed = JSON.parse(r.text);
794
794
  // ── this is a COUNT now, and it was a presence probe ──────────────────────────────────
795
795
  // `include_total` returns the corpus total on the same call, so the smallest request the API will
796
- // take — limit 1 — carries the whole answer: probed, `limit:1` returned total 685, identical to the
797
- // paged query's. Stage 0.5 (driver/register-count.mjs) refused to run on this provider at all; it
798
- // now gets the number it exists to ask for.
796
+ // take — limit 1 — carries the whole answer: the total it reports is the one the paged query reports.
797
+ // Stage 0.5 (driver/register-count.mjs) refused to run on this provider at all; it now gets the
798
+ // number it exists to ask for.
799
799
  //
800
800
  // THE ZERO RULE IS UNCHANGED AND IS THE REASON THIS IS SAFE. `total_hits` is null unless the vendor
801
801
  // counted exactly — an approximation and a non-answer both report unknown. So the only 0 this can