clearotron 0.3.2-beta.6 → 0.3.2-beta.8
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/.env.example +24 -23
- package/INSTALL.md +142 -75
- package/README.md +3 -3
- package/bin/onboard.mjs +637 -216
- package/bin/start.mjs +133 -23
- package/bin/update.mjs +82 -11
- package/build-info.json +2 -2
- package/docs/architecture/04-configuration-reference.md +26 -11
- package/docs/architecture/05-config-governance.md +17 -7
- package/driver/CHANGELOG.md +83 -0
- package/driver/band-size.mjs +59 -0
- package/driver/config-inventory.mjs +112 -9
- package/driver/connotation-search.mjs +45 -0
- package/driver/contract-arm2-baseline.json +1 -3
- package/driver/contract-e3-backlog.mjs +29 -29
- package/driver/contract-vocabulary.mjs +59 -25
- package/driver/door-gates.mjs +41 -7
- package/driver/driver.config.mjs +272 -59
- package/driver/engine/CONTRACT.md +10 -3
- package/driver/engine/README.md +2 -2
- package/driver/engine/anthropic-agent.mjs +77 -21
- package/driver/engine/auth.mjs +129 -10
- package/driver/engine/jx-turn.mjs +7 -6
- package/driver/engine/mcp/recording-server.mjs +13 -0
- package/driver/engine/openai-agent.mjs +4 -2
- package/driver/engine/probe.mjs +110 -23
- package/driver/findings-model.mjs +1 -1
- package/driver/flag-snapshot.mjs +28 -5
- package/driver/gateway.mjs +30 -21
- package/driver/jx-lanes.mjs +21 -2
- package/driver/jx-units.mjs +6 -3
- package/driver/jx.mjs +4 -2
- package/driver/matter-frame-record.mjs +90 -1
- package/driver/named-band.mjs +34 -2
- package/driver/package.json +1 -1
- package/driver/pipeline.mjs +391 -26
- package/driver/portal-config-view.mjs +30 -1
- package/driver/portal-report.mjs +15 -1
- package/driver/portal-service.mjs +46 -6
- package/driver/predelivery-lint.mjs +12 -2
- package/driver/publish/index.mjs +46 -5
- package/driver/publish/knockout.mjs +10 -1
- package/driver/publish/render-knockout.mjs +69 -7
- package/driver/publish/render.mjs +170 -59
- package/driver/publish/report-data.mjs +4 -1
- package/driver/publish/report-topbar.mjs +58 -0
- package/driver/publish/templates/report.css +28 -2
- package/driver/publish/xlsx.mjs +13 -1
- package/driver/register-availability.mjs +2 -2
- package/driver/register-coverage.mjs +94 -1
- package/driver/register-digest-record.mjs +236 -11
- package/driver/register-plan.mjs +170 -0
- package/driver/result-noun-fields.mjs +7 -4
- package/driver/run-economics.mjs +41 -10
- package/driver/run-requirements.mjs +173 -9
- package/driver/runner.mjs +3 -3
- package/driver/stages.mjs +12 -8
- package/driver/suite-census.json +162 -72
- package/driver/systemd/README.md +7 -4
- package/driver/terminal-clamp.mjs +107 -1
- package/driver/tokens.mjs +169 -3
- package/driver/unit-environment.mjs +42 -15
- package/driver/unit-inventory.mjs +19 -2
- package/driver/verify.mjs +50 -5
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/http-server.mjs +4 -0
- package/mcp-server/lib/audit.mjs +11 -1
- package/mcp-server/lib/http-handler.mjs +6 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/server.mjs +16 -2
- package/package.json +1 -1
- package/portal-ui/dist/assets/{index-5UyqAyNM.js → index-6jzO9HiX.js} +155 -79
- package/portal-ui/dist/index.html +1 -1
- package/portal-ui/package.json +1 -1
- package/providers/clarivate/src/capabilities.js +5 -5
- package/providers/clarivate/src/core.js +1 -1
- package/providers/corsearch/src/core.js +2 -2
- package/providers/jx/README.md +2 -1
- package/providers/jx/src/turn-envelope.mjs +8 -3
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/perplexity/src/core.js +3 -3
- package/providers/signa/src/capabilities.js +5 -6
- package/providers/signa/src/core.js +1 -1
- package/providers/uspto-local/README.md +1 -1
- package/scripts/authority-boundary-probe.mjs +4 -2
- package/scripts/env-audit.mjs +12 -6
- package/scripts/freeze-example-run.mjs +49 -16
- package/scripts/generated-files-are-current.mjs +69 -4
- package/scripts/release-duplicate-notes.mjs +246 -0
- package/scripts/release-publish-guard.mjs +64 -6
- package/scripts/report-print-check.mjs +194 -0
- package/scripts/settings-render-check.mjs +75 -2
- package/scripts/test-full.mjs +96 -3
- package/scripts/test-run.mjs +10 -0
- package/shared/deployment-box.mjs +7 -2
- package/shared/driver-dir.mjs +1 -1
- package/shared/names-in-force.mjs +1 -1
|
@@ -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
|
-
|
|
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 */ }
|
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.8",
|
|
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/mcp-server/server.mjs
CHANGED
|
@@ -31,7 +31,7 @@ import { join, basename } from "node:path";
|
|
|
31
31
|
import { driverDir } from "../shared/driver-dir.mjs"; //
|
|
32
32
|
import { fileURLToPath } from "node:url";
|
|
33
33
|
|
|
34
|
-
import { enumerateRuns, resolveRun, runAccountKey, runOrganisation, runProfileFacts } from "./lib/runs.mjs";
|
|
34
|
+
import { enumerateRuns, resolveRun, runAccountKey, runOrganisation, runProfileFacts, productIdentityFor } from "./lib/runs.mjs";
|
|
35
35
|
import { ORDERABLE_PRODUCTS } from "../driver/search-policy.mjs";
|
|
36
36
|
import { PRODUCTS } from "../driver/products.mjs";
|
|
37
37
|
|
|
@@ -193,6 +193,20 @@ function runSummary(run) {
|
|
|
193
193
|
? { key: facts.account, name: facts.clientName }
|
|
194
194
|
: { key: null, name: null, known: false, note: "this run's client could not be read from its own record" },
|
|
195
195
|
project: facts.projectKey ? { key: facts.projectKey, name: facts.projectName ?? facts.projectKey } : null,
|
|
196
|
+
// WHAT KIND OF SEARCH IT WAS, on every row, and it is the same defect as the client above one turn
|
|
197
|
+
// later. A mark and a date do not name one run: on the bundled demo data alone, one mark and one day
|
|
198
|
+
// return nine rows across four products — a full country search, a multi-country focus search, a
|
|
199
|
+
// global preliminary search and two knockouts. A session bound to one report is safe whatever the
|
|
200
|
+
// row says, because the scope carries the runId; an account-scoped session has only these rows, and
|
|
201
|
+
// nothing in them told the two apart except the runId string, which is an internal slug a client has
|
|
202
|
+
// never seen and which this tool's own description warns is not theirs to read.
|
|
203
|
+
//
|
|
204
|
+
// RESOLVED AT READ TIME THROUGH THE REGISTRY, never a stored string, for the reason `runs.mjs` gives
|
|
205
|
+
// where this resolver lives: a run freezes its product ID and the name is today's name, so the row,
|
|
206
|
+
// the brief and the report masthead cannot disagree and a renamed product renames everywhere at
|
|
207
|
+
// once. null where the registry cannot name it — the row says nothing rather than guessing, because
|
|
208
|
+
// a hardcoded fallback is how a knockout once announced itself as a product it provably was not.
|
|
209
|
+
product: productIdentityFor(run),
|
|
196
210
|
state: run.state, location: run.location, verdict: run.verdict, url: run.url,
|
|
197
211
|
markName: run.markName, ref: run.ref, classes: run.classes,
|
|
198
212
|
step: s.stepN ? `${s.stepN}/${s.stepTotal} ${s.stepLabel ?? ""}`.trim() : null,
|
|
@@ -1096,7 +1110,7 @@ if (isMain) {
|
|
|
1096
1110
|
// route. On an install with no hosted client door the reader IS the operator, which is the same
|
|
1097
1111
|
// split `stdioConnectOffer` already trusts, so that fact answers the question by itself; on a
|
|
1098
1112
|
// hosted install it answers for nobody and the portal ignores it.
|
|
1099
|
-
appendAudit({ email: null, sub: null, body: { method: "initialize" }, status: "connected", transport: "stdio" });
|
|
1113
|
+
appendAudit({ email: null, sub: null, body: { method: "initialize" }, status: "connected", transport: "stdio", door: "local" });
|
|
1100
1114
|
})
|
|
1101
1115
|
.catch((e) => { log(`fatal: ${e?.stack ?? e}`); process.exit(1); });
|
|
1102
1116
|
}
|
package/package.json
CHANGED
|
@@ -11926,6 +11926,7 @@ var api = {
|
|
|
11926
11926
|
};
|
|
11927
11927
|
}),
|
|
11928
11928
|
...!("territories" in b) ? {} : { registerTerritories: b["territories"] === null ? null : asArray(b["territories"]).filter((t) => typeof t === "string") },
|
|
11929
|
+
...asString(b["registerLabel"]) ? { registerLabel: asString(b["registerLabel"]) } : {},
|
|
11929
11930
|
recipes: asArray(b["recipes"]).map((x) => {
|
|
11930
11931
|
const r = x;
|
|
11931
11932
|
return {
|
|
@@ -12193,11 +12194,38 @@ var api = {
|
|
|
12193
12194
|
billing: {
|
|
12194
12195
|
mode: asString(bill["mode"]) ?? "unknown",
|
|
12195
12196
|
apiBilled: bill["apiBilled"] === true,
|
|
12196
|
-
missing: asStrings(bill["missing"])
|
|
12197
|
+
missing: asStrings(bill["missing"]),
|
|
12198
|
+
cloud: asString(bill["cloud"]),
|
|
12199
|
+
cloudName: asString(bill["cloudName"]),
|
|
12200
|
+
reason: bill["reason"] != null ? (() => {
|
|
12201
|
+
const raw = bill["reason"];
|
|
12202
|
+
const r = typeof raw === "object" && !Array.isArray(raw) ? asRecord(raw) : {};
|
|
12203
|
+
return {
|
|
12204
|
+
kind: asString(r["kind"]) ?? "unclassified",
|
|
12205
|
+
mode: asString(r["mode"]),
|
|
12206
|
+
defaulted: r["defaulted"] === true,
|
|
12207
|
+
setting: asString(r["setting"]) ?? "",
|
|
12208
|
+
clouds: asArray(r["clouds"]).flatMap((c) => {
|
|
12209
|
+
const x = asRecord(c);
|
|
12210
|
+
const name = asString(x["name"]);
|
|
12211
|
+
const setting = asString(x["setting"]);
|
|
12212
|
+
return name && setting ? [{
|
|
12213
|
+
name,
|
|
12214
|
+
setting
|
|
12215
|
+
}] : [];
|
|
12216
|
+
}),
|
|
12217
|
+
modes: asStrings(r["modes"]),
|
|
12218
|
+
gateway: asString(r["gateway"]),
|
|
12219
|
+
engineSetting: asString(r["engineSetting"]),
|
|
12220
|
+
engineChoice: asString(r["engineChoice"])
|
|
12221
|
+
};
|
|
12222
|
+
})() : null
|
|
12197
12223
|
},
|
|
12198
12224
|
binaryPresent: e["binaryPresent"] === true,
|
|
12199
12225
|
program: asString(e["program"]),
|
|
12200
|
-
install: asString(e["install"])
|
|
12226
|
+
install: asString(e["install"]),
|
|
12227
|
+
programSetting: asString(e["programSetting"]),
|
|
12228
|
+
setupRoute: e["setupRoute"] === "packaged" ? "packaged" : e["setupRoute"] === "checkout" ? "checkout" : null
|
|
12201
12229
|
};
|
|
12202
12230
|
})() : null,
|
|
12203
12231
|
providers: Array.isArray(b["providers"]) ? asArray(b["providers"]).map((p) => {
|
|
@@ -12330,13 +12358,6 @@ var NAV = [
|
|
|
12330
12358
|
icon: "panel-left",
|
|
12331
12359
|
scope: "account"
|
|
12332
12360
|
},
|
|
12333
|
-
{
|
|
12334
|
-
id: "ai",
|
|
12335
|
-
label: "Connect your AI",
|
|
12336
|
-
path: "/portal/ai",
|
|
12337
|
-
icon: "sparkles",
|
|
12338
|
-
scope: "account"
|
|
12339
|
-
},
|
|
12340
12361
|
{
|
|
12341
12362
|
id: "people",
|
|
12342
12363
|
label: "People",
|
|
@@ -12424,6 +12445,14 @@ var NAV = [
|
|
|
12424
12445
|
}
|
|
12425
12446
|
]
|
|
12426
12447
|
},
|
|
12448
|
+
{
|
|
12449
|
+
id: "ai",
|
|
12450
|
+
label: "Connect your AI",
|
|
12451
|
+
path: "/portal/ai",
|
|
12452
|
+
icon: "sparkles",
|
|
12453
|
+
scope: "account",
|
|
12454
|
+
rail: "below"
|
|
12455
|
+
},
|
|
12427
12456
|
{
|
|
12428
12457
|
id: "new-company",
|
|
12429
12458
|
label: "New company",
|
|
@@ -12463,11 +12492,12 @@ function navFor(who, entries = NAV) {
|
|
|
12463
12492
|
children: e.children.filter((c) => visible(c, who) && !c.hidden)
|
|
12464
12493
|
} : e);
|
|
12465
12494
|
}
|
|
12495
|
+
var railSideOf = (e) => e.rail ?? ((e.scope ?? "account") === "account" ? "above" : "below");
|
|
12466
12496
|
function navGroupsFor(who, entries = NAV) {
|
|
12467
12497
|
const visibleEntries = navFor(who, entries);
|
|
12468
12498
|
return {
|
|
12469
|
-
account: visibleEntries.filter((e) => (e
|
|
12470
|
-
owner: visibleEntries.filter((e) => e
|
|
12499
|
+
account: visibleEntries.filter((e) => railSideOf(e) === "above"),
|
|
12500
|
+
owner: visibleEntries.filter((e) => railSideOf(e) === "below")
|
|
12471
12501
|
};
|
|
12472
12502
|
}
|
|
12473
12503
|
function scopeOf(id, entries = NAV) {
|
|
@@ -13818,6 +13848,7 @@ function readableFailure(failedStage, reason) {
|
|
|
13818
13848
|
var EMPTY_DRAFT = {
|
|
13819
13849
|
product: null,
|
|
13820
13850
|
territories: [],
|
|
13851
|
+
replacesOwnTerritories: false,
|
|
13821
13852
|
nativeLanguage: false
|
|
13822
13853
|
};
|
|
13823
13854
|
var REGIONS = [
|
|
@@ -13941,9 +13972,6 @@ function reachesTerritory(name, covered) {
|
|
|
13941
13972
|
if (!Array.isArray(covered)) return true;
|
|
13942
13973
|
return covered.includes(name);
|
|
13943
13974
|
}
|
|
13944
|
-
function vocabularyFor(product, covered) {
|
|
13945
|
-
return offerableFor(product).filter((n) => reachesTerritory(n, covered));
|
|
13946
|
-
}
|
|
13947
13975
|
function territoryMatches(query, chosen, product, limit = 8, _covered) {
|
|
13948
13976
|
return matchTerritoriesIn(offerableFor(product), query, chosen, limit);
|
|
13949
13977
|
}
|
|
@@ -13959,8 +13987,9 @@ function matchTerritoriesIn(vocabulary, query, chosen, limit = 8) {
|
|
|
13959
13987
|
};
|
|
13960
13988
|
return vocabulary.filter((n) => !taken.has(n.toLowerCase()) && hit(n)).slice(0, limit);
|
|
13961
13989
|
}
|
|
13962
|
-
function addTerritory(d, name, product,
|
|
13990
|
+
function addTerritory(d, name, product, covered) {
|
|
13963
13991
|
if (!offerableFor(product).includes(name)) return d;
|
|
13992
|
+
if (!reachesTerritory(name, covered)) return d;
|
|
13964
13993
|
if (d.territories.includes(name)) return d;
|
|
13965
13994
|
if (product?.geography === "exactly one country") return {
|
|
13966
13995
|
...d,
|
|
@@ -13977,14 +14006,35 @@ function removeTerritory(d, name) {
|
|
|
13977
14006
|
territories: d.territories.filter((t) => t !== name)
|
|
13978
14007
|
};
|
|
13979
14008
|
}
|
|
13980
|
-
function
|
|
13981
|
-
|
|
14009
|
+
function notAvailableLine(names, registerLabel) {
|
|
14010
|
+
const named = names.join(", ");
|
|
14011
|
+
const who = typeof registerLabel === "string" && registerLabel.trim() ? registerLabel.trim() : null;
|
|
14012
|
+
return `${named ? `${named} \u00b7 ` : ""}not available${who ? ` with register ${who}` : ""}`;
|
|
14013
|
+
}
|
|
14014
|
+
function takeOverOwnTerritories(d, own, without) {
|
|
14015
|
+
return {
|
|
14016
|
+
...d,
|
|
14017
|
+
territories: own.filter((t) => t !== without),
|
|
14018
|
+
replacesOwnTerritories: true
|
|
14019
|
+
};
|
|
14020
|
+
}
|
|
14021
|
+
function geographyFor(d, product = null, resolved = []) {
|
|
14022
|
+
if (product?.geography === "worldwide, and nothing else") return {
|
|
14023
|
+
mode: "worldwide",
|
|
14024
|
+
territories: []
|
|
14025
|
+
};
|
|
14026
|
+
if (d.territories.length) return {
|
|
13982
14027
|
mode: "named",
|
|
13983
14028
|
territories: [...d.territories]
|
|
13984
|
-
}
|
|
14029
|
+
};
|
|
14030
|
+
if (d.replacesOwnTerritories) return {
|
|
13985
14031
|
mode: "worldwide",
|
|
13986
14032
|
territories: []
|
|
13987
14033
|
};
|
|
14034
|
+
return {
|
|
14035
|
+
mode: "account-default",
|
|
14036
|
+
territories: [...resolved]
|
|
14037
|
+
};
|
|
13988
14038
|
}
|
|
13989
14039
|
function nativeLanguageControl(product) {
|
|
13990
14040
|
if (product?.nativeLanguage === "offered") return "toggle";
|
|
@@ -14003,6 +14053,7 @@ function chooseProduct(d, product) {
|
|
|
14003
14053
|
return {
|
|
14004
14054
|
product: product?.key ?? null,
|
|
14005
14055
|
territories,
|
|
14056
|
+
replacesOwnTerritories: d.replacesOwnTerritories,
|
|
14006
14057
|
nativeLanguage: nativeLanguageControl(product) === "toggle" ? d.nativeLanguage : false
|
|
14007
14058
|
};
|
|
14008
14059
|
}
|
|
@@ -14485,6 +14536,7 @@ function draftFromSaved(recipe, products) {
|
|
|
14485
14536
|
return chooseProduct({
|
|
14486
14537
|
product: base,
|
|
14487
14538
|
territories: Array.isArray(scope["jurisdictions"]) ? scope["jurisdictions"].filter((j) => typeof j === "string") : [],
|
|
14539
|
+
replacesOwnTerritories: false,
|
|
14488
14540
|
nativeLanguage: recipe["nativeLanguage"] === true
|
|
14489
14541
|
}, product);
|
|
14490
14542
|
}
|
|
@@ -15510,7 +15562,7 @@ function resumeWording(iso) {
|
|
|
15510
15562
|
});
|
|
15511
15563
|
return t.toDateString() === new Date().toDateString() ? `at ${time}` : `${t.toLocaleDateString([], { weekday: "long" })} at ${time}`;
|
|
15512
15564
|
}
|
|
15513
|
-
function StatusCell({ state, step,
|
|
15565
|
+
function StatusCell({ state, step, reason, failedStage, pausedKind = null, resetsAt = null, stopRequestedAt = null, detailed = false, count = null }) {
|
|
15514
15566
|
if (stopRequestedAt && state !== "delivered" && state !== "failed" && state !== "cancelled") return (0, import_jsx_runtime.jsxs)("span", { children: [(0, import_jsx_runtime.jsxs)("span", {
|
|
15515
15567
|
className: "status",
|
|
15516
15568
|
children: [(0, import_jsx_runtime.jsx)("span", {
|
|
@@ -15577,7 +15629,7 @@ function StatusCell({ state, step, stepN, stepTotal, reason, failedStage, paused
|
|
|
15577
15629
|
] });
|
|
15578
15630
|
}
|
|
15579
15631
|
const label = state === "queued" ? "Queued" : state === "paused" ? "Paused" : "Running";
|
|
15580
|
-
const detail = state === "paused" ? pausedKind === "recovering" ? "Held after a problem — retrying on its own" : pausedKind === "operator" ? "Paused by a system restart — resumes on its own" : resetsAt ? `Paused by a provider limit — resumes ${resumeWording(resetsAt)}` : "Paused by a provider limit — resumes on its own" : step
|
|
15632
|
+
const detail = state === "paused" ? pausedKind === "recovering" ? "Held after a problem — retrying on its own" : pausedKind === "operator" ? "Paused by a system restart — resumes on its own" : resetsAt ? `Paused by a provider limit — resumes ${resumeWording(resetsAt)}` : "Paused by a provider limit — resumes on its own" : step;
|
|
15581
15633
|
return (0, import_jsx_runtime.jsxs)("span", { children: [(0, import_jsx_runtime.jsxs)("span", {
|
|
15582
15634
|
className: "status",
|
|
15583
15635
|
children: [(0, import_jsx_runtime.jsx)("span", { className: `dot ${state}` }), count ? (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
@@ -15602,7 +15654,7 @@ function allowanceLine(usage, brand) {
|
|
|
15602
15654
|
if (left == null) return null;
|
|
15603
15655
|
if (left > 5) return null;
|
|
15604
15656
|
const who = operatorName(brand);
|
|
15605
|
-
if (left === 0) return `You have used all ${usage?.dailyRuns ?? 0} of this account's searches for today. The allowance resets at midnight UTC — or ask
|
|
15657
|
+
if (left === 0) return `You have used all ${usage?.dailyRuns ?? 0} of this account's searches for today. The allowance resets at midnight UTC — or ask ${who} to run this one for you.`;
|
|
15606
15658
|
return `${left} search${left === 1 ? "" : "es"} left today. The allowance resets at midnight UTC, or ask ${who} to run one for you.`;
|
|
15607
15659
|
}
|
|
15608
15660
|
//#endregion
|
|
@@ -16688,8 +16740,6 @@ function FamilyRows({ family, isOpen, onToggle, go, picking, showOwner = false,
|
|
|
16688
16740
|
}) : (0, import_jsx_runtime.jsx)(StatusCell, {
|
|
16689
16741
|
state: family.state,
|
|
16690
16742
|
step: null,
|
|
16691
|
-
stepN: null,
|
|
16692
|
-
stepTotal: null,
|
|
16693
16743
|
reason: null,
|
|
16694
16744
|
failedStage: null
|
|
16695
16745
|
}) }),
|
|
@@ -16798,8 +16848,6 @@ function MarkRow({ mark, open, onToggle, go, indent = false, picking = false, sh
|
|
|
16798
16848
|
(0, import_jsx_runtime.jsx)("td", { children: (0, import_jsx_runtime.jsx)(StatusCell, {
|
|
16799
16849
|
state: run.state,
|
|
16800
16850
|
step: run.step,
|
|
16801
|
-
stepN: run.stepN,
|
|
16802
|
-
stepTotal: run.stepTotal,
|
|
16803
16851
|
reason: run.reason,
|
|
16804
16852
|
failedStage: run.failedStage,
|
|
16805
16853
|
pausedKind: run.pausedKind,
|
|
@@ -16936,8 +16984,6 @@ function ReadRow({ read, go, picking, indent, showOwner = false, latest = false,
|
|
|
16936
16984
|
(0, import_jsx_runtime.jsx)("td", { children: (0, import_jsx_runtime.jsx)(StatusCell, {
|
|
16937
16985
|
state: read.state,
|
|
16938
16986
|
step: read.step,
|
|
16939
|
-
stepN: read.stepN,
|
|
16940
|
-
stepTotal: read.stepTotal,
|
|
16941
16987
|
reason: read.reason,
|
|
16942
16988
|
failedStage: read.failedStage,
|
|
16943
16989
|
stopRequestedAt: read.stopRequestedAt,
|
|
@@ -17764,26 +17810,68 @@ function Missing({ go, reason }) {
|
|
|
17764
17810
|
}
|
|
17765
17811
|
//#endregion
|
|
17766
17812
|
//#region src/contract/engineState.ts
|
|
17813
|
+
var SETUP_COMMAND = "`npx clearotron install`";
|
|
17814
|
+
var listed = (xs, and = "and") => xs.length <= 1 ? xs[0] ?? "" : `${xs.slice(0, -1).join(", ")} ${and} ${xs[xs.length - 1]}`;
|
|
17815
|
+
var PAID_BY = {
|
|
17816
|
+
subscription: "subscription",
|
|
17817
|
+
"api-key": "an API key",
|
|
17818
|
+
cloud: "a cloud account"
|
|
17819
|
+
};
|
|
17820
|
+
var paidBy = (mode) => mode !== null && Object.hasOwn(PAID_BY, mode) ? PAID_BY[mode] : mode ?? "a way of paying";
|
|
17821
|
+
var COUNT = [
|
|
17822
|
+
"no",
|
|
17823
|
+
"one",
|
|
17824
|
+
"two",
|
|
17825
|
+
"three",
|
|
17826
|
+
"four"
|
|
17827
|
+
];
|
|
17828
|
+
var NAMES_CLOUDS = new Set([
|
|
17829
|
+
"switch-beside-mode",
|
|
17830
|
+
"two-clouds",
|
|
17831
|
+
"no-cloud"
|
|
17832
|
+
]);
|
|
17833
|
+
function billingRefusalSentence(r) {
|
|
17834
|
+
const setting = r.setting || "the billing setting";
|
|
17835
|
+
const generic = `Searches will be refused over how this machine is set to pay. Check ${setting} and the settings beside it.`;
|
|
17836
|
+
if (NAMES_CLOUDS.has(r.kind) && r.clouds.length === 0) return generic;
|
|
17837
|
+
const paid = r.defaulted ? `${paidBy(r.mode)}, the default while ${setting} is not set` : `set to ${paidBy(r.mode)}`;
|
|
17838
|
+
switch (r.kind) {
|
|
17839
|
+
case "switch-beside-mode": {
|
|
17840
|
+
const one = r.clouds.length === 1;
|
|
17841
|
+
const names = listed(r.clouds.map((c) => c.name));
|
|
17842
|
+
const switches = listed(r.clouds.map((c) => c.setting));
|
|
17843
|
+
const keep = r.mode === "api-key" ? "to pay with the API key" : "to pay by subscription";
|
|
17844
|
+
return `Searches will be refused: payment is ${r.defaulted ? "by " : ""}${paid}, but the ${names} ${one ? "switch" : "switches"} (${switches}) ${one ? "is" : "are"} also on. ` + (one ? `Turn ${switches} off ${keep}, or set ${setting} to cloud to pay through ${names}.` : `Turn them off ${keep}, or set ${setting} to cloud and leave one on.`);
|
|
17845
|
+
}
|
|
17846
|
+
case "two-clouds": return `Searches will be refused: payment is set to a cloud account, but ${COUNT[r.clouds.length] ?? r.clouds.length} clouds are switched on, ${listed(r.clouds.map((c) => `${c.name} (${c.setting})`))}. Turn off all but the one you pay through.`;
|
|
17847
|
+
case "no-cloud": return `Searches will be refused: payment is set to a cloud account, but no cloud is chosen. Turn on your cloud's switch (${listed(r.clouds.map((c) => `${c.setting} for ${c.name}`), "or")}) with the settings that cloud needs` + (r.gateway ? `, set ${r.gateway} for a gateway,` : ",") + ` or set ${setting} to subscription.`;
|
|
17848
|
+
case "not-a-mode": return `Searches will be refused: ${setting} is set to a word Clearotron does not know. Set it to ${listed(r.modes, "or")}.`;
|
|
17849
|
+
case "cloud-on-codex": return `Searches will be refused: payment is set to a cloud account, which pays only for Claude, and this machine runs the Codex engine. Set ${setting} to ${listed(r.modes, "or")}` + (r.engineSetting && r.engineChoice ? `, or set ${r.engineSetting} to ${r.engineChoice} to pay for Claude through your cloud.` : ".");
|
|
17850
|
+
default: return generic;
|
|
17851
|
+
}
|
|
17852
|
+
}
|
|
17767
17853
|
function engineRowFaults(engine, { programDisputed = false } = {}) {
|
|
17854
|
+
const reason = engine.billing.reason ?? null;
|
|
17768
17855
|
return [
|
|
17769
17856
|
...engine.known ? [] : [`This build does not ship an engine called ${engine.id}.`],
|
|
17770
17857
|
...engine.billing.missing.length ? ["Set to bill an API key, and no key is set — a run is refused rather than billed to the subscription."] : [],
|
|
17771
|
-
...
|
|
17772
|
-
...
|
|
17858
|
+
...reason && !engine.billing.missing.length ? [billingRefusalSentence(reason)] : [],
|
|
17859
|
+
...engine.binaryPresent ? [] : engine.program ? [`The engine program \`${engine.program}\` cannot be found or run on this machine. Run the setup wizard, ${SETUP_COMMAND}: it offers to install the program and proves it with one turn. Then restart Clearotron's services, which look for the program when they start.`] : ["The engine program cannot be found or run on this machine."],
|
|
17860
|
+
...programDisputed && engine.binaryPresent ? [`The engine program is on this machine, but the engine could not find it when it last started — so a new search will refuse. Restart the engine service so it looks again. If it still cannot find it, set ${engine.programSetting ?? "the engine's program setting"} to the program's full path in the settings file the service reads, then restart it again.`] : []
|
|
17773
17861
|
];
|
|
17774
17862
|
}
|
|
17775
17863
|
function engineNotice({ programDisputed }) {
|
|
17776
17864
|
if (programDisputed === true) return {
|
|
17777
17865
|
state: "disputed",
|
|
17778
17866
|
headline: "The engine program is on this machine, but the engine could not find it when it last started.",
|
|
17779
|
-
before: "So a new search will refuse. Restart the engine service,
|
|
17867
|
+
before: "So a new search will refuse. Restart the engine service so it looks again. If it still cannot find it, set the engine's program setting to the program's full path in the settings file the service reads — installing it again where it already is will not change this.",
|
|
17780
17868
|
namesSetupCommand: false,
|
|
17781
17869
|
after: ""
|
|
17782
17870
|
};
|
|
17783
17871
|
return {
|
|
17784
17872
|
state: "absent",
|
|
17785
17873
|
headline: "No search engine is attached to this install.",
|
|
17786
|
-
before: "Everything else works — the example report, its audit trail and the assistant connection are live right now.
|
|
17874
|
+
before: "Everything else works — the example report, its audit trail and the assistant connection are live right now. The setup wizard offers to install a reasoning CLI if this machine has none, and asks how it is paid for. To start new searches, run the setup wizard",
|
|
17787
17875
|
namesSetupCommand: true,
|
|
17788
17876
|
after: "Then restart the service: this reading was taken when it started, and it will not notice a new install until it starts again."
|
|
17789
17877
|
};
|
|
@@ -17794,7 +17882,7 @@ function engineRow(engine, { programDisputed = false } = {}) {
|
|
|
17794
17882
|
ok: faults.length === 0,
|
|
17795
17883
|
name: engine.vendor ?? engine.id,
|
|
17796
17884
|
mono: engine.id,
|
|
17797
|
-
state: engine.billing.apiBilled ? "API key" : "Subscription",
|
|
17885
|
+
state: engine.billing.missing.length || engine.billing.reason ? "Refused" : engine.billing.cloudName ?? (engine.billing.apiBilled ? "API key" : "Subscription"),
|
|
17798
17886
|
faults
|
|
17799
17887
|
};
|
|
17800
17888
|
}
|
|
@@ -18270,6 +18358,7 @@ function NewClearance({ ctx }) {
|
|
|
18270
18358
|
const { result: usageRes } = useLoad(() => api.usage(account), [account]);
|
|
18271
18359
|
const levels = searches?.kind === "ok" ? searches.value.products : [];
|
|
18272
18360
|
const registerTerritories = searches?.kind === "ok" ? searches.value.registerTerritories : void 0;
|
|
18361
|
+
const registerLabel = searches?.kind === "ok" ? searches.value.registerLabel : void 0;
|
|
18273
18362
|
const savedSearches = searches?.kind === "ok" ? searches.value.recipes : [];
|
|
18274
18363
|
const readCan = searches?.kind === "ok" ? searches.value.read : {
|
|
18275
18364
|
available: false,
|
|
@@ -18387,10 +18476,11 @@ function NewClearance({ ctx }) {
|
|
|
18387
18476
|
setSaveNote(null);
|
|
18388
18477
|
};
|
|
18389
18478
|
const setPick = (next) => edit({ pick: next });
|
|
18390
|
-
const recommendation = (0, import_react.useMemo)(() => recommendSearch(levels, names.length, draft.pick.territories), [
|
|
18479
|
+
const recommendation = (0, import_react.useMemo)(() => recommendSearch(levels, names.length, draft.pick.territories.length ? draft.pick.territories : own.territories), [
|
|
18391
18480
|
levels,
|
|
18392
18481
|
names.length,
|
|
18393
|
-
draft.pick.territories
|
|
18482
|
+
draft.pick.territories,
|
|
18483
|
+
own.territories
|
|
18394
18484
|
]);
|
|
18395
18485
|
(0, import_react.useEffect)(() => {
|
|
18396
18486
|
if (pickedByHand || draft.savedSearch || editingSlug || !recommendation) return;
|
|
@@ -18427,7 +18517,7 @@ function NewClearance({ ctx }) {
|
|
|
18427
18517
|
deadline: d.deadline
|
|
18428
18518
|
};
|
|
18429
18519
|
let after = applyRead(before, read, own.classes, { worldwide });
|
|
18430
|
-
const fits = recommendSearch(levels, parseNames(after.names).length, after.draft.territories);
|
|
18520
|
+
const fits = recommendSearch(levels, parseNames(after.names).length, after.draft.territories.length ? after.draft.territories : own.territories);
|
|
18431
18521
|
if (read.product == null && !pickedByHand && !d.savedSearch && fits) after = {
|
|
18432
18522
|
...after,
|
|
18433
18523
|
draft: chooseProduct(after.draft, fits.product)
|
|
@@ -18456,7 +18546,7 @@ function NewClearance({ ctx }) {
|
|
|
18456
18546
|
...draft.savedSearch ? { recipeKey: draft.savedSearch } : draft.pick.product ? { product: draft.pick.product } : {},
|
|
18457
18547
|
...draft.project ? { projectKey: draft.project } : {},
|
|
18458
18548
|
...draft.pick.territories.length ? { jurisdictions: [...draft.pick.territories] } : {},
|
|
18459
|
-
geography: { mode: geographyFor(draft.pick).mode },
|
|
18549
|
+
geography: { mode: geographyFor(draft.pick, activeLevel, own.territories).mode },
|
|
18460
18550
|
...marketplacesApply && parseList(draft.platforms).length ? { platforms: parseList(draft.platforms) } : {},
|
|
18461
18551
|
...!draft.savedSearch && nativeControl === "toggle" && draft.pick.nativeLanguage ? { nativeLanguage: true } : {},
|
|
18462
18552
|
...draft.ref.trim() ? { ref: draft.ref.trim() } : {},
|
|
@@ -18795,10 +18885,20 @@ function NewClearance({ ctx }) {
|
|
|
18795
18885
|
gap: 6,
|
|
18796
18886
|
margin: "9px 0 12px"
|
|
18797
18887
|
},
|
|
18798
|
-
children: draft.pick.territories.length === 0 ? own.territories.length ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [own.territories.map((t) => (0, import_jsx_runtime.
|
|
18799
|
-
className: "chip",
|
|
18888
|
+
children: draft.pick.territories.length === 0 ? own.territories.length ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [own.territories.map((t) => (0, import_jsx_runtime.jsxs)("span", {
|
|
18800
18889
|
"data-anon": "mark",
|
|
18801
|
-
|
|
18890
|
+
className: reachesTerritory(t, registerTerritories) ? "chip" : "chip chip-deferred",
|
|
18891
|
+
title: reachesTerritory(t, registerTerritories) ? void 0 : notAvailableLine([t], registerLabel),
|
|
18892
|
+
children: [reachesTerritory(t, registerTerritories) ? t : notAvailableLine([t], registerLabel), (0, import_jsx_runtime.jsx)("button", {
|
|
18893
|
+
type: "button",
|
|
18894
|
+
"aria-label": `Remove ${t}`,
|
|
18895
|
+
className: "chip-x",
|
|
18896
|
+
onClick: () => setPick(takeOverOwnTerritories(draft.pick, own.territories, t)),
|
|
18897
|
+
children: (0, import_jsx_runtime.jsx)(Icon, {
|
|
18898
|
+
name: "x",
|
|
18899
|
+
size: 13
|
|
18900
|
+
})
|
|
18901
|
+
})]
|
|
18802
18902
|
}, t)), (0, import_jsx_runtime.jsx)("span", {
|
|
18803
18903
|
style: {
|
|
18804
18904
|
fontSize: 11,
|
|
@@ -18811,21 +18911,17 @@ function NewClearance({ ctx }) {
|
|
|
18811
18911
|
children: "Worldwide"
|
|
18812
18912
|
}) : draft.pick.territories.map((t) => (0, import_jsx_runtime.jsxs)("span", {
|
|
18813
18913
|
className: reachesTerritory(t, registerTerritories) ? "chip chip-own" : "chip chip-own chip-deferred",
|
|
18814
|
-
title: reachesTerritory(t, registerTerritories) ? void 0 :
|
|
18815
|
-
children: [
|
|
18816
|
-
|
|
18817
|
-
|
|
18818
|
-
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
|
|
18823
|
-
children: (0, import_jsx_runtime.jsx)(Icon, {
|
|
18824
|
-
name: "x",
|
|
18825
|
-
size: 13
|
|
18826
|
-
})
|
|
18914
|
+
title: reachesTerritory(t, registerTerritories) ? void 0 : notAvailableLine([t], registerLabel),
|
|
18915
|
+
children: [reachesTerritory(t, registerTerritories) ? t : notAvailableLine([t], registerLabel), (0, import_jsx_runtime.jsx)("button", {
|
|
18916
|
+
type: "button",
|
|
18917
|
+
"aria-label": `Remove ${t}`,
|
|
18918
|
+
className: "chip-x",
|
|
18919
|
+
onClick: () => setPick(removeTerritory(draft.pick, t)),
|
|
18920
|
+
children: (0, import_jsx_runtime.jsx)(Icon, {
|
|
18921
|
+
name: "x",
|
|
18922
|
+
size: 13
|
|
18827
18923
|
})
|
|
18828
|
-
]
|
|
18924
|
+
})]
|
|
18829
18925
|
}, t))
|
|
18830
18926
|
}),
|
|
18831
18927
|
(0, import_jsx_runtime.jsx)("div", {
|
|
@@ -18845,33 +18941,18 @@ function NewClearance({ ctx }) {
|
|
|
18845
18941
|
className: "typeahead",
|
|
18846
18942
|
children: territoryMatches(territoryQuery, draft.pick.territories, whereLevel, 8, registerTerritories).map((t) => (0, import_jsx_runtime.jsxs)("button", {
|
|
18847
18943
|
type: "button",
|
|
18944
|
+
disabled: !reachesTerritory(t, registerTerritories),
|
|
18848
18945
|
onClick: () => {
|
|
18849
18946
|
setPick(addTerritory(draft.pick, t, whereLevel, registerTerritories));
|
|
18850
18947
|
setTerritoryQuery("");
|
|
18851
18948
|
},
|
|
18852
18949
|
children: [t, reachesTerritory(t, registerTerritories) ? null : (0, import_jsx_runtime.jsx)("span", {
|
|
18853
18950
|
className: "typeahead-note",
|
|
18854
|
-
children:
|
|
18951
|
+
children: notAvailableLine([], registerLabel)
|
|
18855
18952
|
})]
|
|
18856
18953
|
}, t))
|
|
18857
18954
|
}) : null]
|
|
18858
18955
|
}),
|
|
18859
|
-
Array.isArray(registerTerritories) ? (0, import_jsx_runtime.jsxs)("p", {
|
|
18860
|
-
className: "section-hint",
|
|
18861
|
-
style: { marginTop: 10 },
|
|
18862
|
-
children: [
|
|
18863
|
-
"The trademark register wired to this deployment reaches",
|
|
18864
|
-
" ",
|
|
18865
|
-
vocabularyFor(whereLevel, registerTerritories).length,
|
|
18866
|
-
" of the",
|
|
18867
|
-
" ",
|
|
18868
|
-
offerableFor(whereLevel).length,
|
|
18869
|
-
" territories you can name here:",
|
|
18870
|
-
" ",
|
|
18871
|
-
vocabularyFor(whereLevel, registerTerritories).join(", "),
|
|
18872
|
-
". Anywhere else can still be ordered — it is disclosed in the report as deferred coverage rather than searched at the register."
|
|
18873
|
-
]
|
|
18874
|
-
}) : null,
|
|
18875
18956
|
whereLevel?.geography === "exactly one country" && draft.pick.territories.length === 1 ? (0, import_jsx_runtime.jsxs)("div", {
|
|
18876
18957
|
className: "callout-accent",
|
|
18877
18958
|
children: [draft.pick.territories[0], " — naming another country replaces it, because this search reads one at a time."]
|
|
@@ -19397,6 +19478,7 @@ function NewClearance({ ctx }) {
|
|
|
19397
19478
|
plan ? (0, import_jsx_runtime.jsx)(ReviewDialog, {
|
|
19398
19479
|
uses: runCount(effort),
|
|
19399
19480
|
left: searchesLeft(usage),
|
|
19481
|
+
registerLabel,
|
|
19400
19482
|
plan,
|
|
19401
19483
|
busy,
|
|
19402
19484
|
owner: ownerLabel,
|
|
@@ -19933,7 +20015,7 @@ function PickRow({ selected, onPick, title, tagline, description, chips, recomme
|
|
|
19933
20015
|
}) : null]
|
|
19934
20016
|
});
|
|
19935
20017
|
}
|
|
19936
|
-
function ReviewDialog({ plan, busy, owner, project, names, goods, nativeOn, onStart, onBack, failure, onReview, uses, left }) {
|
|
20018
|
+
function ReviewDialog({ plan, busy, owner, project, names, goods, nativeOn, onStart, onBack, failure, onReview, uses, left, registerLabel }) {
|
|
19937
20019
|
(0, import_react.useEffect)(() => {
|
|
19938
20020
|
const on = (e) => {
|
|
19939
20021
|
if (e.key === "Escape") onBack();
|
|
@@ -20018,13 +20100,7 @@ function ReviewDialog({ plan, busy, owner, project, names, goods, nativeOn, onSt
|
|
|
20018
20100
|
}),
|
|
20019
20101
|
(0, import_jsx_runtime.jsx)(Row$3, {
|
|
20020
20102
|
label: "Registers to search",
|
|
20021
|
-
children: plan.coverage ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [plan.coverage.reached.length ? joinAnd(plan.coverage.reached) : "None", plan.coverage.missing.length ? (0, import_jsx_runtime.jsxs)(Muted, { children: [
|
|
20022
|
-
". ",
|
|
20023
|
-
joinAnd(plan.coverage.missing),
|
|
20024
|
-
" ",
|
|
20025
|
-
plan.coverage.missing.length === 1 ? "is" : "are",
|
|
20026
|
-
" not reached by the register wired here, and will be disclosed in the report as deferred coverage rather than searched."
|
|
20027
|
-
] }) : null] }) : places.length ? joinAnd(places) : "Worldwide"
|
|
20103
|
+
children: plan.coverage ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [plan.coverage.reached.length ? joinAnd(plan.coverage.reached) : "None", plan.coverage.missing.length ? (0, import_jsx_runtime.jsxs)(Muted, { children: [". ", notAvailableLine(plan.coverage.missing, registerLabel)] }) : null] }) : places.length ? joinAnd(places) : "Worldwide"
|
|
20028
20104
|
}),
|
|
20029
20105
|
scope && scope.classes.length ? (0, import_jsx_runtime.jsxs)(Row$3, {
|
|
20030
20106
|
label: "Classes",
|
|
@@ -25476,7 +25552,7 @@ function About() {
|
|
|
25476
25552
|
(0, import_jsx_runtime.jsx)("dt", { children: "Copyright" }),
|
|
25477
25553
|
(0, import_jsx_runtime.jsx)("dd", { children: info.copyright.replace(/^Copyright\s+/i, "") }),
|
|
25478
25554
|
(0, import_jsx_runtime.jsx)("dt", { children: "Model access" }),
|
|
25479
|
-
(0, import_jsx_runtime.jsx)("dd", { children: "This runs on your own model access — a subscription or your own
|
|
25555
|
+
(0, import_jsx_runtime.jsx)("dd", { children: "This runs on your own model access — a subscription, an API key, or your own cloud account — and the paid registers on your own agreements with those providers. The reasoning stages are a third-party command-line program, Claude Code (proprietary) or the Codex CLI (Apache-2.0), that you install and license under that vendor’s own terms; this licence grants nothing over any of them." }),
|
|
25480
25556
|
(0, import_jsx_runtime.jsx)("dt", { children: "Trade marks" }),
|
|
25481
25557
|
(0, import_jsx_runtime.jsxs)("dd", { children: [
|
|
25482
25558
|
(0, import_jsx_runtime.jsx)("strong", { children: info.name }),
|
|
@@ -49,7 +49,7 @@
|
|
|
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-
|
|
52
|
+
<script type="module" crossorigin src="/portal/assets/index-6jzO9HiX.js"></script>
|
|
53
53
|
<link rel="stylesheet" crossorigin href="/portal/assets/index-CVOIvdhc.css">
|
|
54
54
|
</head>
|
|
55
55
|
<body>
|
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.8",
|
|
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
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
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
|
-
//
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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) {
|