clearotron 0.3.2-beta.6 → 0.3.2-beta.7

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.
@@ -651,6 +651,12 @@
651
651
  "skips": 0,
652
652
  "todos": 0
653
653
  },
654
+ "a-refusal-names-the-collection-it-searched.test.mjs": {
655
+ "tests": 5,
656
+ "asserts": 13,
657
+ "skips": 0,
658
+ "todos": 0
659
+ },
654
660
  "a-refusal-names-the-file-when-the-command-it-offers-cannot-be-run.test.mjs": {
655
661
  "tests": 8,
656
662
  "asserts": 16,
@@ -677,7 +683,7 @@
677
683
  },
678
684
  "a-refused-query-says-whether-the-provider-declined-it.test.mjs": {
679
685
  "tests": 3,
680
- "asserts": 11,
686
+ "asserts": 12,
681
687
  "skips": 0,
682
688
  "todos": 0
683
689
  },
@@ -699,6 +705,12 @@
699
705
  "skips": 0,
700
706
  "todos": 0
701
707
  },
708
+ "a-release-note-cannot-be-counted-twice.test.mjs": {
709
+ "tests": 12,
710
+ "asserts": 33,
711
+ "skips": 0,
712
+ "todos": 0
713
+ },
702
714
  "a-release-note-is-written-for-its-reader.test.mjs": {
703
715
  "tests": 9,
704
716
  "asserts": 66,
@@ -3070,8 +3082,8 @@
3070
3082
  "todos": 0
3071
3083
  },
3072
3084
  "pipeline.mock.test.mjs": {
3073
- "tests": 94,
3074
- "asserts": 795,
3085
+ "tests": 97,
3086
+ "asserts": 806,
3075
3087
  "skips": 0,
3076
3088
  "todos": 0
3077
3089
  },
@@ -3706,8 +3718,8 @@
3706
3718
  "todos": 0
3707
3719
  },
3708
3720
  "release-pipeline.test.mjs": {
3709
- "tests": 99,
3710
- "asserts": 376,
3721
+ "tests": 101,
3722
+ "asserts": 384,
3711
3723
  "skips": 0,
3712
3724
  "todos": 0
3713
3725
  },
@@ -5386,8 +5398,8 @@
5386
5398
  "todos": 0
5387
5399
  },
5388
5400
  "update-refuses-on-a-packaged-install.test.mjs": {
5389
- "tests": 6,
5390
- "asserts": 21,
5401
+ "tests": 8,
5402
+ "asserts": 26,
5391
5403
  "skips": 0,
5392
5404
  "todos": 0
5393
5405
  },
@@ -5733,8 +5745,8 @@
5733
5745
  "todos": 0
5734
5746
  },
5735
5747
  "http-handler.test.mjs": {
5736
- "tests": 17,
5737
- "asserts": 40,
5748
+ "tests": 20,
5749
+ "asserts": 47,
5738
5750
  "skips": 0,
5739
5751
  "todos": 0
5740
5752
  },
@@ -5872,7 +5884,7 @@
5872
5884
  },
5873
5885
  "the-portal-can-tell-who-has-connected-an-assistant.test.mjs": {
5874
5886
  "tests": 12,
5875
- "asserts": 33,
5887
+ "asserts": 35,
5876
5888
  "skips": 0,
5877
5889
  "todos": 0
5878
5890
  },
package/driver/verify.mjs CHANGED
@@ -13,7 +13,8 @@ import { driverDir } from "../shared/driver-dir.mjs"; //
13
13
  import { findReceiptViolations, findGridLedgerViolations, findPlatformIdentityViolations, parsePrRiskQueries, MEANING_SEAT, erroredConnotationQueriesAmong } from "./common-law-receipts.mjs";
14
14
  // Conversion 2 — the discriminator the two rulings above key on. PURE-ish: one existsSync-shaped read.
15
15
  import { matterFrameWasRecorded, frameRatifiedForms } from "./matter-frame-record.mjs";
16
- import { findConnotationViolations, parsePrRiskResults, MEANING_ANGLES_RE,
16
+ import { findConnotationViolations, parsePrRiskResults, prRiskPopulation,
17
+ CONNOTATION_UNMATCHED_MARK, CONNOTATION_NO_RESEMBLANCE_MARK, MEANING_ANGLES_RE,
17
18
  parseDispositionForm, CONNOTATION_UNRULED_REASONS, queryKey } from "./connotation-search.mjs";
18
19
  import { formSidecarName, formSidecarPath } from "./disposition-union.mjs";
19
20
  // B — the transport's own four failure states. The audit reads the run's records; this file locates them.
@@ -365,6 +366,13 @@ function commonLawMeaningSeat(p, c) {
365
366
  let recordedRaw;
366
367
  try { recordedRaw = parsePrRiskResults(ledgerRaw).map((e) => String(e?.query ?? "")); }
367
368
  catch (e) { return fail(`grid_ledger_unparseable:${String(e.message).slice(0, 80)}`); }
369
+ // THE REFUSAL NAMES THE FILE IT JOINED AGAINST, because "recorded" is not one question in a run.
370
+ // A run answers "what did this half record" in four places that each mean something different — this
371
+ // results ledger, its gap rows, the obligations sidecar, and the final-state receipts audit — and a
372
+ // sentence that says only "recorded" invites a reader to answer from whichever they happen to open.
373
+ // Two readers did exactly that on one clearance and reached three different wrong mechanisms, each
374
+ // from a true measurement of a real record.
375
+ const LEDGER = `common-law-grid.half-${MEANING_SEAT}.json`;
368
376
  const recordedQ = new Set(recordedRaw.map(queryKey));
369
377
  const dropped = dictated.filter((q) => !recordedQ.has(queryKey(q)));
370
378
  if (dropped.length) {
@@ -435,17 +443,27 @@ function commonLawMeaningSeat(p, c) {
435
443
  .flatMap((b) => (Array.isArray(b?.gaps) ? b.gaps : []));
436
444
  const reportedError = new Map(
437
445
  erroredConnotationQueriesAmong(dropped, { gaps: gapRows }).map((e) => [e.query, e.error]));
446
+ // AND IT SAYS WHEN THE READER REDUCED WHAT IT READ. `parsePrRiskResults` folds rows onto the raw
447
+ // query text, so its output is smaller than the ledger whenever a query was recorded twice. Every
448
+ // count taken during one evening's diagnosis was post-fold and nobody had named the raw population,
449
+ // which made "the seat wrote 59 rows" and "59 survived the fold" the same number and different
450
+ // facts: one query recorded twice while another was skipped reads exactly like one simply skipped.
451
+ const pop = prRiskPopulation(ledgerRaw);
452
+ const foldNote = pop.repeated > 0
453
+ ? ` (${LEDGER} carries ${pop.rows} row(s) that fold to ${pop.distinct} distinct query(ies): `
454
+ + `${pop.repeated} repeat a query already counted, so a repeat here may stand where a dictated query is missing)`
455
+ : "";
438
456
  const parts = dropped.slice(0, 3).map((q) => {
439
457
  const reported = reportedError.get(q);
440
458
  // Named separately because the remedy is different: the search was attempted and the provider
441
459
  // declined it, so re-running it unchanged is the one repair that cannot work.
442
- if (reported) return `${abbrev(q, 40)} [the provider REPORTED an error on this query: ${abbrev(reported, 60)}]`;
460
+ if (reported) return `${abbrev(q, 40)} [not recorded in ${LEDGER} because the provider REPORTED an error on it: ${abbrev(reported, 60)}]`;
443
461
  const n = nearest(q);
444
462
  return n
445
- ? `${abbrev(q, 40)} [unmatched; nearest recorded: ${abbrev(n, 40)}]`
446
- : `${abbrev(q, 40)} [no recorded query resembles this one]`;
463
+ ? `${abbrev(q, 40)} ${CONNOTATION_UNMATCHED_MARK} ${abbrev(n, 40)}] in ${LEDGER} — that is evidence a query LIKE it was recorded there, not that these two are the same query`
464
+ : `${abbrev(q, 40)} ${CONNOTATION_NO_RESEMBLANCE_MARK} in ${LEDGER}, which is the only file this gate joins against`;
447
465
  });
448
- return fail(`connotation_query_unrecorded:${parts.join(",")}${dropped.length > 3 ? ` (+${dropped.length - 3} more)` : ""}`);
466
+ return fail(`connotation_query_unrecorded:${parts.join(",")}${dropped.length > 3 ? ` (+${dropped.length - 3} more)` : ""}${foldNote}`);
449
467
  }
450
468
  if (spec?.connotation?.disposition_required === true) {
451
469
  const recorded = parsePrRiskResults(ledgerRaw);
@@ -1,5 +1,9 @@
1
1
  # trademark-artifacts-mcp
2
2
 
3
+ ## 0.3.2-beta.7
4
+
5
+ No changes in this release.
6
+
3
7
  ## 0.3.2-beta.6
4
8
 
5
9
  No changes in this release.
@@ -362,6 +362,10 @@ if (isMain) {
362
362
  // read inside it, so the factory keeps one rule and the caller names which door it is.
363
363
  createSession: (sessions, scope, owner) => createSession(sessions, scope, owner, { networkDoor: false }),
364
364
  authHeader: AUTH_HEADER, firmDomains: ALLOWED_DOMAINS, log,
365
+ // THE THIRD DOOR, and it has to name itself. It is not the staff surface and it is not the network
366
+ // client surface; a key presented here arrives over a local socket. Until this was passed, every
367
+ // audit line this door wrote carried no door at all and read as the staff surface by elimination.
368
+ door: "key",
365
369
  });
366
370
  openKeyDoor({ handler: keyHandler, path: KEY_SOCKET, log })
367
371
  .catch((e) => { log(`FATAL: could not open the key socket at ${KEY_SOCKET} — ${e.message}`); process.exit(1); });
@@ -40,6 +40,16 @@ export function summarize(body) {
40
40
  return out;
41
41
  }
42
42
 
43
+ /**
44
+ * The value written when a caller names no door. A door-less line USED TO BE POSSIBLE and one writer
45
+ * produced them: the key door built its handler without saying which surface it was, so every line it
46
+ * wrote omitted the field while the lines either side of it carried it. Absence then read as the staff
47
+ * surface, because that was the only other thing it could have been, so the trail quietly attributed a
48
+ * client's calls to staff. The field is now always written and an unnamed door is loud rather than
49
+ * missing — a reader can search for this value, which is not true of a key that is not there.
50
+ */
51
+ export const UNNAMED_DOOR = "unnamed";
52
+
43
53
  export function appendAudit({ email, sub, body, status, transport, door, path = DEFAULT_AUDIT_PATH }) {
44
54
  // `sub` = the inner-token PRINCIPAL (ops-token issuance, INSTALL.md §8) — distinguishes
45
55
  // two automations sharing a transport identity. null for internal/user sessions without a sub claim.
@@ -59,7 +69,7 @@ export function appendAudit({ email, sub, body, status, transport, door, path =
59
69
  // WRITTEN ONLY WHEN GIVEN, the same rule as `transport` and for the same reason: the existing log
60
70
  // shape must not move for records that have no answer to this. A door that does not name itself is a
61
71
  // record with no `door` key, not a record claiming to be from nowhere.
62
- const line = JSON.stringify({ ts: new Date().toISOString(), email: email ?? null, sub: sub ?? null, ...summarize(body), status: status ?? null, ...(transport ? { transport } : {}), ...(door ? { door } : {}) }) + "\n";
72
+ const line = JSON.stringify({ ts: new Date().toISOString(), email: email ?? null, sub: sub ?? null, ...summarize(body), status: status ?? null, ...(transport ? { transport } : {}), door: door || UNNAMED_DOOR }) + "\n";
63
73
  try { mkdirSync(dirname(path), { recursive: true }); appendFileSync(path, line); } catch { /* best-effort */ }
64
74
  }
65
75
 
@@ -69,7 +69,7 @@ export function evictOldest(sessions) {
69
69
  * presents another identity's mcp-session-id is refused (403) — a leaked/guessed session id must never
70
70
  * let one CF-authed person attach to another's session (which may carry an ops-scoped inner token).
71
71
  */
72
- export function makeHttpHandler({ verify, limiter, opsLimiter = null, sessions, createSession, ns = "trademark-artifacts", sessionMax = 500, maxBody = 4 * 1024 * 1024, authHeader = "cf-access-jwt-assertion", firmDomains = [], clientSurface = false, devMode = false, tokenOnly = false, keyDoorPath = null,
72
+ export function makeHttpHandler({ verify, limiter, opsLimiter = null, sessions, createSession, ns = "trademark-artifacts", sessionMax = 500, maxBody = 4 * 1024 * 1024, authHeader = "cf-access-jwt-assertion", firmDomains = [], clientSurface = false, door: doorName = null, devMode = false, tokenOnly = false, keyDoorPath = null,
73
73
  // Is this identity still on the guest list? ASKED PER REQUEST on an ACCOUNT session, cached on the
74
74
  // grants file's mtime, so it costs a stat between edits. Injected so an arm can move the answer
75
75
  // without a file; the default is the real read, because a door composed without this seam would
@@ -96,7 +96,11 @@ export function makeHttpHandler({ verify, limiter, opsLimiter = null, sessions,
96
96
  // caller who does not exist. Those lines carry no email and no principal, and say a call was refused
97
97
  // at this door at this time — which is true, and is the shape the local route already uses for the
98
98
  // same reason: a synthesized identity would match somebody who did nothing.
99
- const door = clientSurface ? "client" : undefined;
99
+ // WHICH SURFACE THIS HANDLER IS, named rather than inferred. `clientSurface` answers a scope question
100
+ // and was doing double duty as the door's name, which left the key door — built with neither
101
+ // `clientSurface` nor a name — writing lines with no door at all. A caller that knows it is a third
102
+ // thing passes `door`; the two that do not get the surface they already declare.
103
+ const door = doorName ?? (clientSurface ? "client" : "portal");
100
104
  const refuse = (res, status, obj, who = {}) => {
101
105
  try { appendAudit({ email: who.email ?? null, sub: who.sub ?? null, body: who.body ?? null, status: "refused", door }); }
102
106
  catch { /* best-effort: a write failure must never change what the caller is told */ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trademark-artifacts-mcp",
3
- "version": "0.3.2-beta.6",
3
+ "version": "0.3.2-beta.7",
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.",
@@ -1096,7 +1096,7 @@ if (isMain) {
1096
1096
  // route. On an install with no hosted client door the reader IS the operator, which is the same
1097
1097
  // split `stdioConnectOffer` already trusts, so that fact answers the question by itself; on a
1098
1098
  // hosted install it answers for nobody and the portal ignores it.
1099
- appendAudit({ email: null, sub: null, body: { method: "initialize" }, status: "connected", transport: "stdio" });
1099
+ appendAudit({ email: null, sub: null, body: { method: "initialize" }, status: "connected", transport: "stdio", door: "local" });
1100
1100
  })
1101
1101
  .catch((e) => { log(`fatal: ${e?.stack ?? e}`); process.exit(1); });
1102
1102
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "clearotron",
3
3
  "type": "module",
4
- "version": "0.3.2-beta.6",
4
+ "version": "0.3.2-beta.7",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
7
7
  "type": "git",
@@ -2,7 +2,7 @@
2
2
  "name": "portal-ui",
3
3
  "private": true,
4
4
  "type": "module",
5
- "version": "0.3.2-beta.6",
5
+ "version": "0.3.2-beta.7",
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": {
@@ -217,11 +217,11 @@ export const CAPABILITIES = Object.freeze({
217
217
  // ── WHICH FORM OF A NON-LATIN MARK DOES THE INDEX HOLD? ──────────────────────────────────────────
218
218
  // `false` = the TRANSLITERATION ONLY. The characters are not indexed, so searching them returns 0
219
219
  // with no error — the exact false-clean shape a reader calls CLEAN:
220
- // 华威豹 → 0 HUA WEI BAO → 32 (and the 32 CONTAIN 华威豹)
221
- // 小米 → 0 XIAOMI → 57632
222
- // 스타벅스 → 0
220
+ // Searching the characters of a non-Latin mark returns nothing; searching its transliteration
221
+ // returns records, and those records carry the characters. Both halves are needed to see it —
222
+ // the empty answer alone is indistinguishable from a mark nobody has filed.
223
223
  // Universal, not a CJK-specific behaviour: non-Latin records across CN/TW/JP/KR/TH/GR/UA/EG/IL/SA
224
- // carried a populated markTransliteration.
224
+ // carry a populated markTransliteration.
225
225
  //
226
226
  // This declaration is what makes the refusal a CONTRACT rather than one vendor file's hand-written
227
227
  // check: the shared executor (providers/_shared/execute-plan.mjs, via script-form.mjs) reads it and
@@ -250,7 +250,7 @@ export const CAPABILITIES = Object.freeze({
250
250
  // makeEnumerate({ capabilities: {...CAPABILITIES.kernel} }) — these values are the LIVE seam settings,
251
251
  // no longer a design note. pageGuard is 1 because /search is single-shot: there is no page 2 to
252
252
  // fetch, so the guard can only ever be a backstop. namesChunkDefault = maxOrWidth (500): the kernel
253
- // chunks a wide OR-stack to the parser's probed nesting bound before it reaches the wire.
253
+ // chunks a wide OR-stack to the parser's nesting bound before it reaches the wire.
254
254
  kernel: Object.freeze({
255
255
  countProbe: "endpoint",
256
256
  screenSource: "billed-record-fetch",
@@ -1211,7 +1211,7 @@ export async function doBatchScreen(apiKey, base, params, tctx) {
1211
1211
  // judgment was shown a native-script mark beside its own romanised query with no reading on
1212
1212
  // either and concluded they were different marks. A delivered report told a client a
1213
1213
  // jurisdiction had not been searched in its own script while the run held both the query and
1214
- // this value. On the measured round 558 of 1,937 records had one to carry.
1214
+ // this value. A large share of records carry one, so a dropped reading is not a rare edge.
1215
1215
  //
1216
1216
  // Null where the office records none, which is most Latin-script filings: this says what the
1217
1217
  // register says, and inventing a romanisation here would be this row certifying a reading
@@ -192,7 +192,7 @@ export const DEFAULT_SEARCH_FIELDS = [
192
192
  // ONE JSON envelope away: a 200 whose body is `{"message":"upstream search cluster unavailable"}`
193
193
  // is valid JSON, so parseError never fires — and the old fallback coerced "an object with no
194
194
  // totalHitCount" to 0, on a comment claiming a present body is "the provider answering". It is not.
195
- // A SEARCH RESPONSE is a body that carries the search-response shape this endpoint was probed to
195
+ // A SEARCH RESPONSE is a body that carries the search-response shape this endpoint is documented to
196
196
  // return: totalHitCount (the count), rows (the records) or nextRequest (the paging cursor). A
197
197
  // parseable body with none of the three — an error envelope, a gateway stub — is the provider
198
198
  // saying something OTHER than an answer, and it rides out as a non-answer (null total, an error
@@ -435,7 +435,7 @@ export async function doExpandPhoneme(sessionKey, params, tctx) {
435
435
  // provider); they are RE-EXPORTED here unchanged so every existing importer — engine/mcp/corsearch-server.mjs,
436
436
  // register-plan.mjs, the driver — keeps resolving them from this module with identical semantics.
437
437
  // classifyStatus carries brand-json's vocabulary (Valid/Pending/GracePeriod live; Invalid/Expired dead;
438
- // anything else AMBIGUOUS → never auto-drop). BATCH_SCREEN_CHUNK = 100 = the observed brand-json page size.
438
+ // anything else AMBIGUOUS → never auto-drop). BATCH_SCREEN_CHUNK = 100 matches the brand-json page size.
439
439
  export { BATCH_SCREEN_CHUNK, chunk, classifyStatus, isAllClass, normalizeBrandRow, screenVerdict };
440
440
 
441
441
  export async function doBatchScreen(sessionKey, params, tctx) {
@@ -1,5 +1,9 @@
1
1
  # trademark-oauth-mcp-bridge
2
2
 
3
+ ## 0.3.2-beta.7
4
+
5
+ No changes in this release.
6
+
3
7
  ## 0.3.2-beta.6
4
8
 
5
9
  No changes in this release.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trademark-oauth-mcp-bridge",
3
- "version": "0.3.2-beta.6",
3
+ "version": "0.3.2-beta.7",
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).",
@@ -523,9 +523,9 @@ export function reconcileGridLedger(stdoutStr, spec) {
523
523
  *
524
524
  * Why identity and not a count: the sandbox program TRANSCRIBES the dictated queries into its own source,
525
525
  * and a mutated string is a DIFFERENT SEARCH. The count stays right while the dictated query never ran, so
526
- * every count-based check upstream and downstream reads clean. Observed: the dictated
527
- * `提基斯拉什 offensive meaning` came back as `提基斯ラッシュ offensive meaning` — the katakana of the
528
- * sibling Japanese row fused into the Chinese transliteration. 27 dictated, 27 recorded, one never searched.
526
+ * every count-based check upstream and downstream reads clean. The substitution this catches fuses one
527
+ * row's script into another row's transliteration: the two strings differ, the dictated and recorded
528
+ * counts still match exactly, and one dictated query is never searched by anybody.
529
529
  *
530
530
  * A query that THREW and said so is not this defect — it owns a gap row (`<query> | connotation | <error>`,
531
531
  * or the reconciled object form) and the driver's merge gate weighs it separately. Only a silent
@@ -34,7 +34,7 @@
34
34
  // it beats a number that is right for one shape and wrong for the other. See
35
35
  // OWNER_SCOPED_WINDOW below, which is the machine-readable half.
36
36
  //
37
- // What IS observed about the total is separate: it saturates at 10000 and flags itself
37
+ // The total is a separate matter: it saturates at 10000 and flags itself
38
38
  // approximate there — a fact about the count, not about the window.
39
39
  //
40
40
  // PURE: no node imports, no vendor HTTP.
@@ -129,7 +129,7 @@ export const CAPABILITIES = Object.freeze({
129
129
  classFilter: "native",
130
130
  // Search rows already carry status / nice_classes / owner_name → screening is inline, zero extra calls.
131
131
  screenSource: "search-row",
132
- // No documented or observed hard result ceiling, and no total to compare one against.
132
+ // No hard result ceiling, and no total to compare one against.
133
133
  resultCeiling: null,
134
134
 
135
135
  // ── the predicates, and WHICH REQUEST SHAPE each one rides ──────────────────────────────────────
@@ -247,10 +247,9 @@ export const CAPABILITIES = Object.freeze({
247
247
  // `legacy_code`. asks for `code` to be primary, and it now is, in the one place it decides
248
248
  // anything: `SIGNA_OFFICE_CODES` is what a reader and a future translate() should reach for.
249
249
  //
250
- // THE MIGRATION IS NOT URGENT AND THE REASON IS MEASURED, not assumed. All eleven legacy keys were
251
- // sent to the live wire beside their ISO codes, and every pair returned an identical
252
- // total (cipo/CA 83, euipo/EM 80, inpi-fr/FR 19, ipau/AU 72, ipi/CH 46, ipos/SG 58, nipo/NO 42,
253
- // prv/SE 22, ukipo/GB 96, uspto/US 169, wipo/WO 68). Nothing on the wire moves if `translate` keeps
250
+ // THE MIGRATION IS NOT URGENT, AND THE REASON IS A PROPERTY OF THE REGISTER rather than a guess:
251
+ // each legacy key and its ISO code address the same office, so the two spellings are interchangeable
252
+ // for every office this deployment reaches. Nothing on the wire moves if `translate` keeps
254
253
  // emitting keys, so it does — a vocabulary swap under the executor buys nothing and risks a live
255
254
  // office lookup.
256
255
  //
@@ -316,7 +316,7 @@ export function isSearchResponseBody(body) {
316
316
  // 21, 101, 18) and — the case that matters — an empty band answered `total_count: 0, approximate:
317
317
  // false`, an EXACT zero, which is the only kind this repository is allowed to render.
318
318
  //
319
- // Every approximate answer came back as exactly 10000: it is a saturation marker, not an estimate.
319
+ // An approximate total of exactly 10000 is a saturation marker rather than an estimate.
320
320
  // The vendor is saying "at least ten thousand", and it says so on the broad sweeps (a bare owner
321
321
  // filter, `match: similar`, an unanchored `contains`) — precisely the bands a clearance cannot
322
322
  // enumerate anyway.