clearotron 0.4.0-beta.0 → 0.4.0-beta.2
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 +9 -0
- package/INSTALL.md +4 -31
- package/README.md +5 -5
- package/bin/brandowner.mjs +1 -1
- package/bin/onboard.mjs +18 -74
- package/bin/start.mjs +58 -14
- package/bin/update.mjs +10 -2
- package/build-info.json +2 -2
- package/demo/full-country-search/run/_driver/search-policy.json +1 -1
- package/demo/full-country-search/run/status.json +1 -1
- package/demo/global-preliminary-search/run/_driver/search-policy.json +1 -1
- package/demo/global-preliminary-search/run/status.json +1 -1
- package/demo/knockout-search/run/_driver/search-policy.json +1 -1
- package/demo/knockout-search/run/status.json +1 -1
- package/demo/multi-country-focus-search/run/_driver/search-policy.json +1 -1
- package/demo/multi-country-focus-search/run/status.json +1 -1
- package/docs/README.md +1 -0
- package/docs/SECURITY-OWASP.md +298 -0
- package/docs/SECURITY.md +18 -13
- package/docs/architecture/02-architecture.md +5 -5
- package/docs/architecture/03-run-lifecycle.md +28 -29
- package/docs/architecture/04-configuration-reference.md +5 -10
- package/docs/architecture/05-config-governance.md +5 -7
- package/docs/architecture/06-operations-runbook.md +0 -12
- package/docs/architecture/07-quality-and-audit.md +12 -13
- package/docs/architecture/09-security-and-data.md +9 -4
- package/driver/CHANGELOG.md +70 -0
- package/driver/ask-ledger.mjs +4 -2
- package/driver/authority-trees.mjs +90 -8
- package/driver/band-shape.mjs +13 -13
- package/driver/blind-frame-model.mjs +1 -1
- package/driver/case-law-ledger.mjs +19 -3
- package/driver/claim-liveness.mjs +30 -1
- package/driver/clearance-variants-record.mjs +10 -3
- package/driver/common-law-receipts.mjs +64 -14
- package/driver/commonlaw-carry.mjs +2 -2
- package/driver/compare.mjs +2 -2
- package/driver/connotation-search.mjs +33 -104
- package/driver/contract-arm2-baseline.json +6 -5
- package/driver/contract-e3-backlog.mjs +62 -62
- package/driver/contract-vocabulary.mjs +38 -31
- package/driver/coverage-form-io.mjs +13 -1
- package/driver/coverage-form.mjs +42 -4
- package/driver/coverage-ledger.mjs +3 -5
- package/driver/cross-check-wait.mjs +43 -0
- package/driver/declination-call.mjs +34 -10
- package/driver/declination-tool.mjs +27 -15
- package/driver/deferral-row.mjs +139 -0
- package/driver/degraded-parts.mjs +377 -0
- package/driver/deliver-trigger.sh +1 -1
- package/driver/demo-container.mjs +4 -1
- package/driver/dev-portal.mjs +5 -5
- package/driver/dispatch-record.mjs +2 -2
- package/driver/driver.config.mjs +193 -96
- package/driver/e2e/README.md +1 -1
- package/driver/effective-scope.mjs +58 -2
- package/driver/engine/anthropic-agent.mjs +103 -27
- package/driver/engine/auth.mjs +2 -2
- package/driver/engine/child-record.mjs +11 -0
- package/driver/engine/cli-version.mjs +4 -3
- package/driver/engine/common.mjs +17 -2
- package/driver/engine/deny-authority-write.mjs +3 -1
- package/driver/engine/engine-env.mjs +174 -0
- package/driver/engine/engine-spawn.mjs +179 -0
- package/driver/engine/mcp/band-server.mjs +1 -1
- package/driver/engine/mcp/clarivate-server.mjs +2 -1
- package/driver/engine/mcp/codex-config.mjs +112 -3
- package/driver/engine/mcp/corsearch-server.mjs +1 -0
- package/driver/engine/mcp/declination-server.mjs +9 -8
- package/driver/engine/mcp/dispositions-server.mjs +2 -1
- package/driver/engine/mcp/euipo-server.mjs +1 -0
- package/driver/engine/mcp/fetch-server.mjs +14 -11
- package/driver/engine/mcp/free-tier-server.mjs +1 -1
- package/driver/engine/mcp/gather-config.mjs +23 -11
- package/driver/engine/mcp/perplexity-server.mjs +97 -17
- package/driver/engine/mcp/probe-server.mjs +43 -21
- package/driver/engine/mcp/public-fetch.mjs +195 -0
- package/driver/engine/mcp/recording-server.mjs +79 -14
- package/driver/engine/mcp/signa-server.mjs +1 -0
- package/driver/engine/mcp/supplemental.mjs +14 -14
- package/driver/engine/mcp/unit-note-server.mjs +50 -1
- package/driver/engine/mcp/uspto-local-server.mjs +1 -0
- package/driver/engine/openai-agent.mjs +109 -28
- package/driver/engine/probe.mjs +152 -19
- package/driver/enqueue-schema.mjs +5 -5
- package/driver/feedback-issues.mjs +1 -1
- package/driver/feedback-store.mjs +1 -1
- package/driver/findings-model.mjs +67 -16
- package/driver/flag-snapshot.mjs +1 -1
- package/driver/floor-duty.mjs +23 -7
- package/driver/form-neighbourhood.mjs +52 -17
- package/driver/frame-diff-model.mjs +3 -3
- package/driver/framework-method.mjs +304 -0
- package/driver/gateway.mjs +49 -21
- package/driver/hand-off-exits.mjs +129 -0
- package/driver/jx-lanes.mjs +1 -1
- package/driver/jx.mjs +8 -5
- package/driver/knockout-assess-record.mjs +7 -1
- package/driver/knockout-frame-record.mjs +96 -34
- package/driver/knockout-review-record.mjs +7 -2
- package/driver/log.mjs +2 -2
- package/driver/matter-frame-record.mjs +31 -2
- package/driver/methodology-witness.mjs +6 -3
- package/driver/named-band.mjs +1 -1
- package/driver/owner-use-check.mjs +45 -10
- package/driver/package.json +1 -1
- package/driver/partial-payload-baseline.json +4 -0
- package/driver/phase0.mjs +2 -2
- package/driver/pipeline-knockout.mjs +256 -129
- package/driver/pipeline.mjs +417 -614
- package/driver/placement-carry.mjs +22 -3
- package/driver/placement-form-io.mjs +18 -4
- package/driver/placement-form.mjs +53 -4
- package/driver/placement-union.mjs +32 -5
- package/driver/portal-report.mjs +3 -3
- package/driver/portal-service.mjs +6 -5
- package/driver/portal-static.mjs +11 -18
- package/driver/predelivery-lint.mjs +10 -10
- package/driver/profile-page.html +5 -5
- package/driver/profiles.mjs +5 -5
- package/driver/progress.mjs +6 -4
- package/driver/provider-usage.mjs +25 -2
- package/driver/publish/index.mjs +97 -25
- package/driver/publish/knockout.mjs +136 -14
- package/driver/publish/profiles-page.mjs +2 -0
- package/driver/publish/publish-inputs.mjs +10 -4
- package/driver/publish/render-knockout.mjs +48 -21
- package/driver/publish/render.mjs +13 -8
- package/driver/publish/report-data.mjs +2 -0
- package/driver/publish/search-depth.mjs +77 -4
- package/driver/publish/templates/report.css +1 -1
- package/driver/publish/xlsx.mjs +34 -15
- package/driver/reasoning-tripwires.mjs +2 -160
- package/driver/recall-receipt.mjs +27 -0
- package/driver/recall-reconciliation.mjs +1 -1
- package/driver/record-carry.mjs +14 -14
- package/driver/recording-agreement.mjs +2 -2
- package/driver/reference-score.mjs +169 -47
- package/driver/register-count.mjs +61 -4
- package/driver/register-digest-record.mjs +14 -1
- package/driver/register-plan.mjs +161 -80
- package/driver/register-records.mjs +37 -4
- package/driver/registration-scripts.mjs +22 -0
- package/driver/registry-fidelity.mjs +4 -4
- package/driver/repair-composers.mjs +23 -7
- package/driver/repair-contract.mjs +1 -1
- package/driver/repairs.mjs +5 -2
- package/driver/reviewer-open-points.mjs +33 -0
- package/driver/rule-shape.mjs +8 -8
- package/driver/run-economics.mjs +3 -3
- package/driver/run-integrity.mjs +2 -2
- package/driver/runner.mjs +17 -5
- package/driver/scope-facts.mjs +89 -12
- package/driver/score-redaction.mjs +247 -0
- package/driver/screen-gate.mjs +1 -1
- package/driver/search-policy.mjs +17 -0
- package/driver/skills/README.md +2 -2
- package/driver/skills/blind-frame/SKILL.md +2 -2
- package/driver/skills/clearance-common-law/SKILL.md +29 -36
- package/driver/skills/clearance-common-law/perplexity-prompts.md +8 -30
- package/driver/skills/clearance-register/SKILL.md +15 -16
- package/driver/skills/clearance-register/digest.md +15 -31
- package/driver/skills/clearance-register/register-recipes.md +14 -56
- package/driver/skills/clearance-register/unit.md +37 -48
- package/driver/skills/clearance-search/SKILL.md +6 -8
- package/driver/skills/clearance-search/delivery-contract.md +0 -7
- package/driver/skills/clearance-search/firm-wide-reasoning.md +5 -4
- package/driver/skills/clearance-search/phase2-execution.md +5 -6
- package/driver/skills/clearance-search/report-prose.md +5 -5
- package/driver/skills/clearance-search/risk-framework-triage.md +2 -2
- package/driver/skills/clearance-search/synthesis-rules.md +9 -9
- package/driver/skills/clearance-search/template-formatting.md +2 -2
- package/driver/skills/clearance-variants/SKILL.md +8 -8
- package/driver/skills/clearance-variants/transliteration-scripts.md +2 -2
- package/driver/skills/frame-diff/SKILL.md +2 -2
- package/driver/skills/knockout-assess/SKILL.md +40 -10
- package/driver/skills/knockout-frame/SKILL.md +42 -10
- package/driver/skills/matter-frame/SKILL.md +12 -5
- package/driver/skills/matter-frame/watchlist-reference.md +1 -1
- package/driver/skills/narrative-refutation/SKILL.md +5 -3
- package/driver/skills/placement-inquiry/SKILL.md +5 -1
- package/driver/stage-context.mjs +27 -6
- package/driver/stages-knockout.mjs +92 -79
- package/driver/stages.mjs +111 -68
- package/driver/stray-artifacts.mjs +9 -5
- package/driver/suite-census.json +696 -150
- package/driver/synthesis-record.mjs +26 -4
- package/driver/systemd/README.md +5 -6
- package/driver/systemd/clearotron-client-mcp.service +24 -0
- package/driver/systemd/clearotron-mcp-face.service +24 -0
- package/driver/systemd/clearotron-portal.service +24 -0
- package/driver/systemd/clearotron-worker.service +29 -0
- package/driver/tokens.mjs +10 -9
- package/driver/turnaround-bands.mjs +1 -1
- package/driver/unit-inventory.mjs +24 -43
- package/driver/variant-manifest-model.mjs +22 -3
- package/driver/verify-knockout.mjs +163 -4
- package/driver/verify.mjs +42 -16
- package/driver/web-grid.mjs +150 -0
- package/driver/whatif-memo-run.mjs +1 -1
- package/driver/withheld-families.mjs +113 -4
- package/driver/worker-heartbeat.mjs +13 -2
- package/mcp-server/CHANGELOG.md +8 -0
- package/mcp-server/README.md +1 -1
- package/mcp-server/lib/knockout.mjs +1 -1
- package/mcp-server/lib/ops.mjs +10 -10
- package/mcp-server/lib/scrub.mjs +1 -1
- package/mcp-server/lib/trace.mjs +3 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/server.mjs +3 -3
- package/package.json +1 -1
- package/portal-ui/dist/assets/{index-DVtz44vH.js → index-BPAUjcI0.js} +3 -2
- package/portal-ui/dist/assets/{index-5CCwiJG7.css → index-D2wrw9cH.css} +18 -2
- package/portal-ui/dist/assets/plus-jakarta-sans-BUCHxqJ-.woff2 +0 -0
- package/portal-ui/dist/index.html +2 -15
- package/portal-ui/package.json +1 -1
- package/providers/_shared/README.md +1 -1
- package/providers/_shared/answer-memory.mjs +199 -0
- package/providers/_shared/enumerate.mjs +155 -50
- package/providers/_shared/execute-plan.mjs +62 -16
- package/providers/_shared/ledger-path.mjs +1 -1
- package/providers/_shared/ledger.mjs +48 -6
- package/providers/_shared/plan-guards.mjs +7 -0
- package/providers/_shared/script-form.mjs +24 -5
- package/providers/_shared/term-shape.mjs +5 -5
- package/providers/clarivate/src/capabilities.js +11 -0
- package/providers/clarivate/src/core.js +193 -18
- package/providers/corsearch/README.md +1 -2
- package/providers/corsearch/src/core.js +2 -2
- package/providers/jx-subclass/lookup.mjs +1 -1
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/README.md +8 -7
- package/providers/oauth-mcp-bridge/bridge.mjs +21 -5
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/oauth-mcp-bridge/systemd/courtlistener-mcp.service +1 -1
- package/providers/oauth-mcp-bridge/warm-server.mjs +16 -5
- package/providers/perplexity/src/core.js +246 -21
- package/providers/signa/src/capabilities.js +24 -0
- package/providers/signa/src/core.js +93 -25
- package/scripts/README.md +2 -1
- package/scripts/added-reference-check.mjs +2 -1
- package/scripts/backup-recall-stores.mjs +5 -5
- package/scripts/demo-evidence.mjs +2 -1
- package/scripts/deprecate-below.mjs +114 -2
- package/scripts/drive-env-check.mjs +2 -1
- package/scripts/e2e-first-time.mjs +469 -0
- package/scripts/e2e-scenario-ops.mjs +441 -0
- package/scripts/e2e.mjs +104 -16
- package/scripts/env-audit.mjs +8 -0
- package/scripts/freeze-example-run.mjs +7 -7
- package/scripts/generated-files-are-current.mjs +2 -1
- package/scripts/hand-off-exits-probe.mjs +75 -0
- package/scripts/import-cycle-check.mjs +2 -1
- package/scripts/merge-shape-check.mjs +2 -1
- package/scripts/package-size-budget.mjs +2 -1
- package/scripts/record-carry-probe.mjs +1 -1
- package/scripts/release-entry-catch-up.mjs +77 -8
- package/scripts/release-install-check.mjs +4 -1
- package/scripts/release-note-required.mjs +139 -9
- package/scripts/release-rehearsal-version.mjs +60 -0
- package/scripts/release-sbom.mjs +104 -0
- package/scripts/release-visible-check.mjs +7 -5
- package/scripts/render-check.mjs +5 -2
- package/scripts/report-offline-render-check.mjs +169 -0
- package/scripts/score.mjs +79 -8
- package/scripts/strip-titles-and-attributions.mjs +2 -1
- package/scripts/strip-tracker-citations.mjs +2 -1
- package/scripts/test-full.mjs +2 -1
- package/scripts/test-run.mjs +10 -3
- package/scripts/third-party-notices.mjs +3 -1
- package/scripts/travelling-predicates.mjs +1 -1
- package/scripts/writing-standard-check.mjs +2 -1
- package/shared/brand-fonts.mjs +59 -0
- package/shared/brand.mjs +6 -6
- package/shared/browser-temp-root.mjs +3 -2
- package/shared/doctrine-overlay.mjs +1 -1
- package/shared/driver-dir.mjs +47 -11
- package/shared/fonts/OFL-fira-code.txt +93 -0
- package/shared/fonts/OFL-plus-jakarta-sans.txt +93 -0
- package/shared/fonts/README.md +37 -0
- package/shared/fonts/fira-code.woff2 +0 -0
- package/shared/fonts/plus-jakarta-sans.woff2 +0 -0
- package/shared/names-in-force.mjs +2 -0
- package/shared/npm-cli.mjs +23 -0
- package/shared/os-advice.mjs +14 -2
- package/shared/path-seps.mjs +42 -0
- package/shared/process-table.mjs +71 -3
- package/shared/reference-guard-classes.mjs +30 -6
- package/shared/root-doc-commands.mjs +6 -2
- package/shared/running-start.mjs +24 -7
- package/shared/scope.mjs +2 -2
- package/shared/wsl.mjs +1 -1
- package/driver/known-conflicts.mjs +0 -327
|
@@ -30,6 +30,7 @@ export const MIN_CELLS_PER_VARIANT = 7;
|
|
|
30
30
|
// It composes `queryKey`, which is the one author of what "the same text" means across a provider
|
|
31
31
|
// boundary, and keeps its own wrapping-quote strip because a term arrives quoted here and does not there.
|
|
32
32
|
import { queryKey } from "./connotation-search.mjs";
|
|
33
|
+
import { dictatedCells } from "../providers/perplexity/src/core.js"; // what the spec asks, product or blocks
|
|
33
34
|
|
|
34
35
|
const norm = (s) => queryKey(String(s || "").trim().replace(/^["'`\u2018\u2019\u201c\u201d]+|["'`\u2018\u2019\u201c\u201d]+$/g, ""));
|
|
35
36
|
|
|
@@ -285,6 +286,30 @@ export function findGridLedgerViolations(manifestOrTerms, ledgerRaw, { minCellsP
|
|
|
285
286
|
return shortVariants(variants, (term) => platforms.get(norm(term))?.size || 0, minCellsPerVariant);
|
|
286
287
|
}
|
|
287
288
|
|
|
289
|
+
/**
|
|
290
|
+
* — THE RECEIPTS JOIN FOR A GRID IN BLOCKS: every cell the spec dictated ran — a cell or a recorded gap in
|
|
291
|
+
* the ledger — judged cell by cell. The count and identity joins below assume every term owes every
|
|
292
|
+
* platform, which a grid the matter frame decided does not ask. Same {variant, cells, expected} shape as
|
|
293
|
+
* findGridLedgerViolations, plus the platforms still owed, so the `grid_join_missing` token is unchanged.
|
|
294
|
+
* Throws on an unparseable ledger.
|
|
295
|
+
*
|
|
296
|
+
* @returns {Array<{variant:string, cells:number, expected:number, missing:string[]}>}
|
|
297
|
+
*/
|
|
298
|
+
export function findUnranDictatedCells(spec, ledgerRaw) {
|
|
299
|
+
const map = parseGridLedger(ledgerRaw);
|
|
300
|
+
const owed = new Map(); // term → [platform, ran?]
|
|
301
|
+
for (const [term, platform] of dictatedCells(spec)) {
|
|
302
|
+
if (!owed.has(term)) owed.set(term, []);
|
|
303
|
+
owed.get(term).push([platform, map.get(norm(term))?.has(norm(platform)) === true]);
|
|
304
|
+
}
|
|
305
|
+
const out = [];
|
|
306
|
+
for (const [variant, rows] of owed) {
|
|
307
|
+
const missing = rows.filter(([, ran]) => !ran).map(([p]) => p);
|
|
308
|
+
if (missing.length) out.push({ variant, cells: rows.length - missing.length, expected: rows.length, missing });
|
|
309
|
+
}
|
|
310
|
+
return out;
|
|
311
|
+
}
|
|
312
|
+
|
|
288
313
|
// ── WS-B: platform-identity join (per-customer profiles) ────────────────────────────────────────────────
|
|
289
314
|
// The count floor proves HOW MANY distinct platforms each variant accounted for — never WHICH. With a
|
|
290
315
|
// dictated per-customer platform list, a worker on gaming habit could sweep the wrong marketplaces and
|
|
@@ -674,6 +699,10 @@ export function splitGridSpec(spec, { outputPaths = {}, dispositionsPaths = {} }
|
|
|
674
699
|
// The meaning seat sweeps no cells. `terms: []` is what makes its dispatch the meaning work and
|
|
675
700
|
// nothing else, and it is why the grid halves keep an untouched 50/50 parity split.
|
|
676
701
|
terms: isMeaning ? [] : terms[h],
|
|
702
|
+
// A grid in blocks keeps its blocks, each cut to this half's terms (a term owns all its cells in one half).
|
|
703
|
+
...(Array.isArray(spec.grids) ? { grids: spec.grids.map((g) => ({ terms: g.terms.filter((t) => !isMeaning && terms[h].includes(t)), platforms: g.platforms })).filter((g) => g.terms.length) } : {}),
|
|
704
|
+
// The famous-mark record names only the cells this seat runs.
|
|
705
|
+
...(Array.isArray(spec.famous) ? { famous: spec.famous.filter((t) => !isMeaning && terms[h].includes(t)) } : {}),
|
|
677
706
|
output_path: outputPaths[h] ?? spec.output_path,
|
|
678
707
|
// The disposition_required stamp still rides BOTH halves: it is the receipt-presence arm, and a
|
|
679
708
|
// stray pr_risk block in the non-owning half must still be judged rather than waved through.
|
|
@@ -714,7 +743,8 @@ export function splitGridSpec(spec, { outputPaths = {}, dispositionsPaths = {} }
|
|
|
714
743
|
* batch has since closed is dropped). This is the never-thinner guarantee: every dictated cell is
|
|
715
744
|
* accounted as a real cell or an HONEST gap, so a half failure can never yield a ledger that is
|
|
716
745
|
* thinner but still valid. A half's honestly-recorded gap for a cell OUTSIDE the spec (a re-keyed
|
|
717
|
-
* variant / an extra swept platform) is UNIONED in too — the spec-only recompute would erase it
|
|
746
|
+
* variant / an extra swept platform) is UNIONED in too — the spec-only recompute would erase it,
|
|
747
|
+
* except a meaning query's gap row when the merged receipts answer that query.
|
|
718
748
|
* - extras.pr_risk[]: concatenated (a then b), deduped by trimmed query — restores the full dictated
|
|
719
749
|
* meaning-receipt set from the per-half partitions. Other extras keys: arrays concatenate,
|
|
720
750
|
* anything else first-defined wins.
|
|
@@ -773,23 +803,32 @@ export function mergeGrids(a, b, { spec, halfErrors = {} } = {}) {
|
|
|
773
803
|
// gaps: recomputed against the FULL spec
|
|
774
804
|
const halfTerms = splitGridTerms(spec?.terms ?? []);
|
|
775
805
|
const gaps = [];
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
}
|
|
806
|
+
// Over the cells the spec DICTATES, never terms × platforms: a grid the frame decided is blocks, and the
|
|
807
|
+
// product of its unions would make a gap of every cell nobody asked for, which the closure pass would run.
|
|
808
|
+
for (const [term, platform] of spec ? dictatedCells(spec) : []) {
|
|
809
|
+
if (seen.has(key(term, platform))) continue;
|
|
810
|
+
const owner = halfOfTerm(halfTerms, term);
|
|
811
|
+
const error = gapErr.get(key(term, platform))?.error
|
|
812
|
+
|| (owner && halfErrors[owner]) || "cell not accounted by either half-grid";
|
|
813
|
+
gaps.push({ term, platform, error });
|
|
784
814
|
}
|
|
785
815
|
// UNION honestly-recorded NON-SPEC gap rows: a half may record a gap for a cell OUTSIDE the canonical
|
|
786
816
|
// spec (a legitimately re-keyed variant / an extra platform a half swept). The spec-only recompute above
|
|
787
817
|
// never emits those, silently erasing an honestly-recorded coverage gap — union them so an honest gap
|
|
788
818
|
// survives the merge. A cell present in cells[] still wins (a stale gap a supplementary batch has since
|
|
789
819
|
// closed is dropped exactly as for spec cells), and a gap already emitted by the spec loop is not doubled.
|
|
820
|
+
//
|
|
821
|
+
// A MEANING QUERY THE MERGED RECEIPTS ANSWER KEEPS NO GAP ROW. The grid tool records one for each dictated
|
|
822
|
+
// query its program did not return, and the engine's re-issue can answer that query later in the same
|
|
823
|
+
// ledger. Kept beside the answer, the row says a search did not complete when it did, and the closure pass
|
|
824
|
+
// takes every gap row for a store cell, so it searches the query again on a site called "connotation".
|
|
825
|
+
// Queries are matched as the receipts are (norm).
|
|
826
|
+
const answered = new Set((Array.isArray(extras.pr_risk) ? extras.pr_risk : [])
|
|
827
|
+
.map((e) => (typeof e?.query === "string" ? norm(e.query) : "")).filter(Boolean));
|
|
790
828
|
const gappedKeys = new Set(gaps.map((g) => key(g.term, g.platform)));
|
|
791
829
|
for (const [k, g] of gapErr) {
|
|
792
830
|
if (seen.has(k) || gappedKeys.has(k)) continue;
|
|
831
|
+
if (String(g.platform).toLowerCase() === "connotation" && answered.has(norm(g.term))) continue;
|
|
793
832
|
gaps.push({ term: g.term, platform: g.platform, error: g.error || "cell not accounted by either half-grid" });
|
|
794
833
|
}
|
|
795
834
|
return { cells, extras, gaps };
|
|
@@ -861,9 +900,9 @@ export function mergeCommonLawFindings(parts) {
|
|
|
861
900
|
// a present row chose.
|
|
862
901
|
//
|
|
863
902
|
// The join bug is fixed independently, because a census nobody can trust is worse than none:
|
|
864
|
-
// • TERM match is EXACT after stripping a trailing annotation ("
|
|
903
|
+
// • TERM match is EXACT after stripping a trailing annotation ("瓦波冰沙 (ZH: …)"). It used to be
|
|
865
904
|
// `rowTerm.includes(cellTerm)`, so the row for "CORAL FREEZE" was credited to the cells for "SLUSH"
|
|
866
|
-
// and even "
|
|
905
|
+
// and even "WAV", and the row for "瓦波冰沙" to the cell for "冰沙" — 71 of the 221.
|
|
867
906
|
// • a platform ROLL-UP row ("Multiple platforms") counts only when the term has no platform-specific
|
|
868
907
|
// row of its own; combined with the substring bug it used to match every platform at once.
|
|
869
908
|
// `undisposed` (title containment over raw web-search titles) is GONE: it returned 1,986 rows on the
|
|
@@ -926,7 +965,16 @@ export function findSimilarListingSignals(findingsContent) {
|
|
|
926
965
|
const signals = [];
|
|
927
966
|
const OWNER_RE = /(?:developer|publisher|seller|owner)(?:\s+|_)of(?:\s+|_)record\W{0,5}([^\n|]+)/i;
|
|
928
967
|
const OWNER_SKIP_RE = /not extracted|unknown|n\/a|none|^[\s—–-]*$/i;
|
|
968
|
+
// A table whose header lists the of-record fields matches OWNER_RE on its first label and captures the
|
|
969
|
+
// next one, so a label reached the register as an owner's name ("publisherofrecord", once its
|
|
970
|
+
// underscores were stripped). A label is never a name.
|
|
971
|
+
const OWNER_LABEL_RE = /^(?:developer|publisher|seller|owner)[\s_]*of[\s_]*record\b/i;
|
|
929
972
|
const URL_RE = /https?:\/\/[^\s)|\]">]+/;
|
|
973
|
+
// A TABLE'S HEADER ROW NAMES COLUMNS, NEVER AN OWNER, whatever column follows an of-record label ("URL",
|
|
974
|
+
// "Store"). It is the row a separator row follows, and both are table rows: a bare "---" under an owner's
|
|
975
|
+
// line is a rule, not a separator, and the owner stands.
|
|
976
|
+
const SEPARATOR_RE = /^\s*\|?\s*:?-{3,}:?\s*(?:\|\s*:?-{3,}:?\s*)*\|?\s*$/;
|
|
977
|
+
const headerRow = (ln, next) => ln.includes("|") && String(next ?? "").includes("|") && SEPARATOR_RE.test(next);
|
|
930
978
|
let inMatrix = false, inFindings = false;
|
|
931
979
|
let block = null; // { markText, owner, url }
|
|
932
980
|
const flush = () => {
|
|
@@ -935,7 +983,9 @@ export function findSimilarListingSignals(findingsContent) {
|
|
|
935
983
|
}
|
|
936
984
|
block = null;
|
|
937
985
|
};
|
|
938
|
-
|
|
986
|
+
const lines = (findingsContent || "").split("\n");
|
|
987
|
+
for (let i = 0; i < lines.length; i++) {
|
|
988
|
+
const ln = lines[i];
|
|
939
989
|
const h = ln.match(/^(#{1,6})\s+(.*)/);
|
|
940
990
|
if (h) {
|
|
941
991
|
const title = h[2];
|
|
@@ -958,10 +1008,10 @@ export function findSimilarListingSignals(findingsContent) {
|
|
|
958
1008
|
continue;
|
|
959
1009
|
}
|
|
960
1010
|
if (inFindings && block) {
|
|
961
|
-
const om = ln.match(OWNER_RE);
|
|
1011
|
+
const om = headerRow(ln, lines[i + 1]) ? null : ln.match(OWNER_RE);
|
|
962
1012
|
if (om && !block.owner) {
|
|
963
1013
|
const owner = om[1].replace(/[*_`]/g, "").trim();
|
|
964
|
-
if (owner && !OWNER_SKIP_RE.test(owner)) block.owner = owner.slice(0, 120);
|
|
1014
|
+
if (owner && !OWNER_SKIP_RE.test(owner) && !OWNER_LABEL_RE.test(om[1].trim())) block.owner = owner.slice(0, 120);
|
|
965
1015
|
}
|
|
966
1016
|
const um = ln.match(URL_RE);
|
|
967
1017
|
if (um && !block.url) block.url = um[0];
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
//
|
|
10
10
|
// ── the loss this exists to catch ────────────────────────────────────────────────────────────────────
|
|
11
11
|
//
|
|
12
|
-
//
|
|
12
|
+
// WAVO TWIST and WAVO TROPICS. Both sat in R3's own common-law records and reached no findings list, and
|
|
13
13
|
// nothing anywhere said why. `common-law-receipts.mjs`'s `findGridCandidateOmissions` already reports one
|
|
14
14
|
// class of this — a hit cell denied by the Negative-results matrix — but it is CELL-granular, and a cell
|
|
15
15
|
// carries up to eight candidates. This is the per-candidate half.
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
// ── THE NON-LATIN TRAP IS ANSWERED, NOT AVOIDED ──────────────────────────────────────────────────────
|
|
40
40
|
//
|
|
41
41
|
// `normalizeJoinText` folds every non-[A-Za-z0-9] run to a space, so it returns the EMPTY STRING for
|
|
42
|
-
//
|
|
42
|
+
// 澜珀, 冰沙, 瓦波冰沙, ワボスラッシュ and 와보 슬러시. A mark-keyed trace is structurally blind to
|
|
43
43
|
// every one of them.
|
|
44
44
|
//
|
|
45
45
|
// NOTHING HERE TOUCHES IT. A Han-script candidate joins on its ASCII/percent-encoded URL. A Han-script
|
package/driver/compare.mjs
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import { readFileSync, existsSync, readdirSync } from "node:fs";
|
|
13
13
|
import { join, basename, isAbsolute } from "node:path";
|
|
14
|
-
import { driverDir } from "../shared/driver-dir.mjs"; //
|
|
14
|
+
import { driverDir, driverFileName } from "../shared/driver-dir.mjs"; //
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
import { STAGES, paths } from "./stages.mjs";
|
|
17
17
|
import { isEntrypoint } from "../shared/is-entrypoint.mjs"; // — one entry-point test, all spellings
|
|
@@ -141,7 +141,7 @@ function outPath(dir, stage, axis) {
|
|
|
141
141
|
// last JSONL line of a stage's telemetry, tried at <dir>/<label>.jsonl (snapshot) and <dir>/_driver/<label>.jsonl.
|
|
142
142
|
function readTel(dir, stage, axis) {
|
|
143
143
|
const label = labelFor(stage, axis);
|
|
144
|
-
for (const p of [join(dir, `${label}.jsonl`), driverDir(dir, `${label}.jsonl`)]) {
|
|
144
|
+
for (const p of [join(dir, driverFileName(`${label}.jsonl`)), driverDir(dir, `${label}.jsonl`)]) {
|
|
145
145
|
try {
|
|
146
146
|
const lines = readFileSync(p, "utf8").trim().split("\n").filter(Boolean);
|
|
147
147
|
if (lines.length) return JSON.parse(lines[lines.length - 1]);
|
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
// searched-not-asserted enforcement (validator side). Sister of use-check.mjs (spec 11): a "clean" claim
|
|
5
5
|
// is sayable ONLY when a search produced it.
|
|
6
6
|
//
|
|
7
|
-
// The bug this closes (live incident: a mark reading as a benign given name one letter off the
|
|
7
|
+
// The bug this closes (live incident: a mark reading as a benign given name one letter off the Mara
|
|
8
8
|
// street-gang label): the deterministic grid runs term×platform marketplace cells only — it asks
|
|
9
9
|
// "who SELLS this name?", never "what does this name MEAN?". A marketplace grid that finds no listing for
|
|
10
10
|
// the mark is SILENT on the street-gang association; only a MEANING search surfaces it. With no machine slot
|
|
11
11
|
// for the meaning search, the model fabricated "(None identified — affirmative sweep) … no gang associations".
|
|
12
12
|
//
|
|
13
13
|
// Two halves, both PURE (no node imports → tests offline):
|
|
14
|
-
// 1.
|
|
15
|
-
// into grid-spec.json; the perplexity plugin runs them on the general web and records each into the
|
|
16
|
-
// ledger's extras.pr_risk[] (a recorded query — even with empty results — is the receipt the search ran).
|
|
14
|
+
// 1. meaningAnglesFromMatterContext — the driver dictates the meaning queries, the matter frame's own list,
|
|
15
|
+
// VERBATIM into grid-spec.json; the perplexity plugin runs them on the general web and records each into the
|
|
16
|
+
// grid ledger's extras.pr_risk[] (a recorded query — even with empty results — is the receipt the search ran).
|
|
17
17
|
// 2. findConnotationViolations — the validator: recorded meaning receipts must be disposed of, per query,
|
|
18
18
|
// citing the receipt. A PR/reputational section that ASSERTS a clean result must additionally cite a
|
|
19
19
|
// Connotation-search source line. A searched-clean (recorded queries, empty results) passes.
|
|
@@ -28,98 +28,21 @@
|
|
|
28
28
|
// section at all matched no block, so DELETING the section passed the gate. Receipts present now means
|
|
29
29
|
// receipts validated, whatever the document says.
|
|
30
30
|
|
|
31
|
-
//
|
|
32
|
-
// and
|
|
33
|
-
//
|
|
34
|
-
|
|
31
|
+
// THE SHAPES THE FIXED MEANING SWEEP ASKED, until 2026-09-25: every run searched the first 6 spellings on
|
|
32
|
+
// the five core shapes and the first 8 translated forms on the three below, about 54 web questions whatever
|
|
33
|
+
// the matter. The matter frame decides the sweep now, as it decides the stores, and no query is built from
|
|
34
|
+
// these. They stay so connotationReasonKey still reads the queries of the runs archived before.
|
|
35
35
|
export const CONNOTATION_SHAPES = ["meaning slang", "gang", "offensive", "urban dictionary", "wikipedia"];
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Build the dictated connotation queries from the mark + its near-forms (the grid variants). De-dups
|
|
39
|
-
* case-insensitively and caps the term count (the meaning search is the mark + a handful of near-forms, not
|
|
40
|
-
* the full variant explosion). Returns ["<term> <shape>", …] — run VERBATIM by the plugin's grid program. PURE.
|
|
41
|
-
*/
|
|
42
|
-
export function pickConnotationTerms(terms, maxTerms = 6) {
|
|
43
|
-
const seen = new Set();
|
|
44
|
-
const picked = [];
|
|
45
|
-
for (const t of (terms ?? [])) {
|
|
46
|
-
const v = String(t ?? "").trim();
|
|
47
|
-
if (!v) continue;
|
|
48
|
-
// KEYED THE SAME WAY THE GATES COMPARE. A producer that folds less than its consumer dictates two
|
|
49
|
-
// terms the gate can only see as one, and a seat recording either satisfies it for both — the gate
|
|
50
|
-
// then passes a query that never ran, which is the fault it exists to catch, inverted.
|
|
51
|
-
const k = queryKey(v);
|
|
52
|
-
if (seen.has(k)) continue;
|
|
53
|
-
seen.add(k);
|
|
54
|
-
picked.push(v);
|
|
55
|
-
if (picked.length >= maxTerms) break;
|
|
56
|
-
}
|
|
57
|
-
return picked;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function buildConnotationQueries(terms, { shapes = CONNOTATION_SHAPES, maxTerms = 6 } = {}) {
|
|
61
|
-
const picked = pickConnotationTerms(terms, maxTerms);
|
|
62
|
-
const queries = [];
|
|
63
|
-
for (const t of picked) for (const s of shapes) queries.push(`${t} ${s}`);
|
|
64
|
-
return queries;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// WP-56 B1 — the NON-ENGLISH half of the meaning sweep. The core bucket runs the mark + its first
|
|
68
|
-
// near-forms; the manifest's translated/transliterated forms (non-Latin script rows, "丝绸与铁 / 席尔克"
|
|
69
|
-
// packed alternates) sat beyond its cap, so a mark could ship with no meaning read in the very scripts the
|
|
70
|
-
// manifest committed to search. These forms get their OWN capped bucket with meaning-appropriate shapes —
|
|
71
|
-
// the slang / urban-dictionary shapes are Latin-web search directions; a non-Latin or translated form
|
|
72
|
-
// wants its meaning and English reading. Which forms exist stays the variants stage's judgment (the
|
|
73
|
-
// structured manifest); this stays mechanical.
|
|
74
36
|
export const CONNOTATION_SHAPES_TRANSLIT = ["meaning", "meaning in english", "offensive meaning"];
|
|
75
37
|
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
* category. " / "-packed alternates split into individual forms; forms the core bucket already queries
|
|
85
|
-
* (coreTerms, case-insensitive) are dropped; own cap (default 8, beside the core bucket's 6).
|
|
86
|
-
* Returns ["<form> <shape>", …] like buildConnotationQueries. PURE.
|
|
87
|
-
*/
|
|
88
|
-
export function buildTranslitConnotationQueries(modelVariants, { shapes = CONNOTATION_SHAPES_TRANSLIT, maxTerms = 8, coreTerms = [] } = {}) {
|
|
89
|
-
const seen = new Set((coreTerms ?? []).map((t) => queryKey(t)).filter(Boolean));
|
|
90
|
-
const picked = [];
|
|
91
|
-
for (const v of (modelVariants ?? [])) {
|
|
92
|
-
const value = String(v?.value ?? "").trim();
|
|
93
|
-
if (!value) continue;
|
|
94
|
-
const isTranslit = String(v?.category ?? "").trim().toLowerCase() === "transliteration" || NON_LATIN_LETTER_RE.test(value);
|
|
95
|
-
if (!isTranslit) continue;
|
|
96
|
-
for (const form of value.split(" / ")) {
|
|
97
|
-
const f = form.trim();
|
|
98
|
-
if (!f) continue;
|
|
99
|
-
const k = queryKey(f);
|
|
100
|
-
if (seen.has(k)) continue;
|
|
101
|
-
seen.add(k);
|
|
102
|
-
picked.push(f);
|
|
103
|
-
if (picked.length >= maxTerms) break;
|
|
104
|
-
}
|
|
105
|
-
if (picked.length >= maxTerms) break;
|
|
106
|
-
}
|
|
107
|
-
const queries = [];
|
|
108
|
-
for (const t of picked) for (const s of shapes) queries.push(`${t} ${s}`);
|
|
109
|
-
return queries;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// ── P2-C (Round-2 §8b) — the DERIVED half of the sweep's scope ─────────────────────────────────────────
|
|
113
|
-
// The fixed CONNOTATION_SHAPES floor asks generic search DIRECTIONS ("<mark> offensive") and stays — it is
|
|
114
|
-
// not a sensitivities checklist, and on the evidence run it did retrieve the cultural-criticism material.
|
|
115
|
-
// What no fixed list can ask is the PER-MATTER angle: the cultural origin a word evokes, the charged history
|
|
116
|
-
// of its imagery, the controversy specific to these goods in this market. Deriving those is judgment, so the
|
|
117
|
-
// MATTER FRAME authors them — its dictated `Meaning angles:` line (semantic field × market/industry; the
|
|
118
|
-
// stage message dictates it and the matterContext validator requires it on fresh runs, `none` allowed as an
|
|
119
|
-
// explicit reasoned emptiness). This parser is the mechanical half: extract, sanitize, cap. The queries are
|
|
120
|
-
// appended VERBATIM to grid-spec connotation.queries BESIDE the floor, so the per-query identity join
|
|
121
|
-
// (findDroppedConnotationQueries) polices their execution exactly like the floor's. NEVER a hardcoded
|
|
122
|
-
// sensitivities checklist — the angles are authored per matter; code only carries them.
|
|
38
|
+
// ── THE MATTER FRAME'S LIST IS THE WHOLE MEANING SWEEP (ruled 2026-09-25) ─────────────────────────────────
|
|
39
|
+
// Deriving what a name could mean, and to whom, is judgment, so the MATTER FRAME authors the questions: its
|
|
40
|
+
// `Meaning angles:` line — the mark's semantic field × this matter's market and goods, the languages whose
|
|
41
|
+
// buyers matter, and any slang, gang or offensive reading (the stage message dictates it and the
|
|
42
|
+
// matterContext validator requires it on fresh runs, `none` allowed as an asserted zero). A fixed floor rode
|
|
43
|
+
// beside it and is gone. This parser is the mechanical half: extract and sanitize; the frame decides how
|
|
44
|
+
// many. The queries go VERBATIM into grid-spec connotation.queries, and the per-query identity join
|
|
45
|
+
// (findDroppedConnotationQueries) polices their execution. NEVER a hardcoded sensitivities checklist.
|
|
123
46
|
|
|
124
47
|
// The frame's machine line (mirrors channelsFromMatterContext's "Search channels:" shape), ANCHORED to a
|
|
125
48
|
// line start: prose that merely MENTIONS `"Meaning angles:" line …` must never read as the line (the
|
|
@@ -167,15 +90,15 @@ function sanitizeMeaningAngle(raw) {
|
|
|
167
90
|
}
|
|
168
91
|
|
|
169
92
|
/**
|
|
170
|
-
* Parse the matter frame's `Meaning angles: <q>; <q>; …` line into sanitized
|
|
171
|
-
* Semicolon-separated (an angle phrase may contain commas); `none` (the
|
|
172
|
-
*
|
|
173
|
-
* strip WRAPPING quotes/backticks (see sanitizeMeaningAngle — a
|
|
174
|
-
* collapse whitespace, drop empties
|
|
175
|
-
*
|
|
176
|
-
*
|
|
93
|
+
* Parse the matter frame's `Meaning angles: <q>; <q>; …` line into the sanitized meaning queries.
|
|
94
|
+
* Semicolon-separated (an angle phrase may contain commas); `none` (the asserted-zero form) and a missing
|
|
95
|
+
* line both yield [], and meaningAnglesAssertedNone tells the two apart: only the first is the frame's
|
|
96
|
+
* decision. Sanitization is mechanical only: strip WRAPPING quotes/backticks (see sanitizeMeaningAngle — a
|
|
97
|
+
* phrase quote inside the angle survives), collapse whitespace, drop empties, dedupe case-insensitively
|
|
98
|
+
* (against itself and `alreadyQueried`). No cap on length or count: the frame's tool refuses an over-long
|
|
99
|
+
* question at the source, every question is run as written, and how many is the frame's call. PURE.
|
|
177
100
|
*/
|
|
178
|
-
export function meaningAnglesFromMatterContext(md, { alreadyQueried = [], maxAngles =
|
|
101
|
+
export function meaningAnglesFromMatterContext(md, { alreadyQueried = [], maxAngles = Infinity } = {}) {
|
|
179
102
|
const m = String(md || "").match(MEANING_ANGLES_RE);
|
|
180
103
|
if (!m) return [];
|
|
181
104
|
const value = m[1].trim();
|
|
@@ -188,7 +111,7 @@ export function meaningAnglesFromMatterContext(md, { alreadyQueried = [], maxAng
|
|
|
188
111
|
// quote runs at both ends unconditionally, so `"` sanitized to "" and fell out here; the wrapper rule
|
|
189
112
|
// keeps it, and a lone `"` dictated as a query is a search nobody asked for that no receipt can ever
|
|
190
113
|
// match — the failure this change exists to stop. Dropped explicitly rather than as a side effect.
|
|
191
|
-
if (!q || !/[\p{L}\p{N}]/u.test(q)
|
|
114
|
+
if (!q || !/[\p{L}\p{N}]/u.test(q)) continue;
|
|
192
115
|
const k = queryKey(q);
|
|
193
116
|
if (seen.has(k)) continue;
|
|
194
117
|
seen.add(k);
|
|
@@ -198,6 +121,12 @@ export function meaningAnglesFromMatterContext(md, { alreadyQueried = [], maxAng
|
|
|
198
121
|
return picked;
|
|
199
122
|
}
|
|
200
123
|
|
|
124
|
+
/** Whether the matter frame asserted that no meaning question applies: its `Meaning angles:` line reads `none`. PURE. */
|
|
125
|
+
export function meaningAnglesAssertedNone(md) {
|
|
126
|
+
const m = String(md || "").match(MEANING_ANGLES_RE);
|
|
127
|
+
return Boolean(m) && /^none\b/i.test(m[1].trim());
|
|
128
|
+
}
|
|
129
|
+
|
|
201
130
|
// The PR / reputational / connotation section heading (the only place the gate polices — it must not flag a
|
|
202
131
|
// clean note that appears in some other section's prose, mirroring use-check's section-scoping).
|
|
203
132
|
const SECTION_RE = /reputational|connotation/i;
|
|
@@ -1125,7 +1054,7 @@ const RECURRENT_MIN = 4;
|
|
|
1125
1054
|
// ── — THE REASON SCALE IS MEASURED HERE AND DELIBERATELY DOES NOT DECIDE ────────────────────────
|
|
1126
1055
|
// was ruled "recurrence counts independent reasons, not query strings": a dictated query is
|
|
1127
1056
|
// "<term> <shape>", the sweep asks every shape of every mark variant, so the seven queries reading
|
|
1128
|
-
//
|
|
1057
|
+
// BIOVELTRYN/BIOVELTRINO/BIOVELTRINE/ΒΙΟΒΕΛΤΡΙΝ/ΒΕΛΤΡΙΝ/ΜΠΙΟΒΕΛΤΡΙΝ/Вельтрин + "offensive meaning" that all
|
|
1129
1058
|
// return the dictionary definition of the word "offensive" are one reason asked seven ways. That
|
|
1130
1059
|
// reasoning is sound and the shape is the right way to express it. It is implemented below as
|
|
1131
1060
|
// connotationReasonKey, and it is RECORDED on every run — but it is NOT what clears the floor.
|
|
@@ -1133,7 +1062,7 @@ const RECURRENT_MIN = 4;
|
|
|
1133
1062
|
// IT WAS BUILT, MEASURED AGAINST THE THREE PRESERVED RUNS, AND REFUTED BY THEM. Making the floor read
|
|
1134
1063
|
// the reason scale inverts the signal it exists to read:
|
|
1135
1064
|
// - The 2026-07 evidence run (test/fixtures/coral-freeze-pr-risk.json, 54 recorded queries): the floor's
|
|
1136
|
-
// obligation set goes 7 → 0. `punchdrink.com/articles/problem-with-
|
|
1065
|
+
// obligation set goes 7 → 0. `punchdrink.com/articles/problem-with-wavo-bars-cultural-appropriation`
|
|
1137
1066
|
// — THE receipt this floor was invented to force onto the page — is surfaced by four queries that are
|
|
1138
1067
|
// all shape "offensive", so it scores ONE reason and drops out. The gate stops firing on the run it
|
|
1139
1068
|
// was designed for.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"the baseline tracks named elements, and a rename is a new name. Regenerate rather than work around it.",
|
|
12
12
|
"Measured 139 of 287 declared elements."
|
|
13
13
|
],
|
|
14
|
-
"total":
|
|
14
|
+
"total": 105,
|
|
15
15
|
"byStage": {
|
|
16
16
|
"matter-frame": [
|
|
17
17
|
"### Intake asks line shape — rendered by the driver from intake_asks[]",
|
|
@@ -22,14 +22,15 @@
|
|
|
22
22
|
"Class scope & adjacency — classes scoped IN with a one-line reason each, classes deliberately scoped OUT",
|
|
23
23
|
"Return shape — hand the frame back through record_matter_frame, write NO file, return ONLY a 2-3 line summary",
|
|
24
24
|
"Scope reasoning — search-wide/cite-narrow, the in-scope-by-reach routes, and the reopen trigger behind each exclusion",
|
|
25
|
-
"
|
|
25
|
+
"confusable_forms — the forms a buyer could confuse, searched on the stores",
|
|
26
|
+
"search_channels — the domains where real use of THIS matter's goods would show",
|
|
27
|
+
"set_aside — the profile stores and forms the frame does not search, each with its reason"
|
|
26
28
|
],
|
|
27
29
|
"clearance-variants": [
|
|
28
30
|
"### Scope ledger rows — {Layer, Item, Status: applied|dropped, Reason, Reopen trigger} across variant / field / source / jurisdiction",
|
|
29
31
|
"Archetype — primary (one of six) + modifiers + one-line reasoning",
|
|
30
32
|
"Cross-mark themes — shared elements, shared conceptual themes, shared industry-incumbent alerts (multi-mark requests)",
|
|
31
33
|
"Distinctiveness & registrability read — spectrum placement per market language, descriptive/generic/laudatory/geographic/deceptive/offensive flags, acquired-distinctiveness note",
|
|
32
|
-
"Famous-mark flags per element + famous_mark_calls_needed[]",
|
|
33
34
|
"Formative root: <root> — the shortest distinctive stem a family of marks would share, on its own line",
|
|
34
35
|
"Output paths + return shape — write the prose manifest and the structured model to the named absolute paths, return ONLY the path + a 2-3 line summary",
|
|
35
36
|
"Per-jurisdiction sub-queries",
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
"Verify? ✅ column on every transliteration row of the prose Variants table",
|
|
42
43
|
"Watchlist union / client-exclusion / 24-owner cap applied by the model before emitting watchlist_owners[]",
|
|
43
44
|
"elements[] — {value, kind: distinctive|common|saturated-common}",
|
|
45
|
+
"elements[].famous_mark_flag — the elements Step 2's famous-mark check flags",
|
|
44
46
|
"incumbent_classes[] — the industry-incumbent alert's Nice classes",
|
|
45
47
|
"variants[].category — one of core|phonetic|visual|transliteration|numeric|composite|other",
|
|
46
48
|
"variants[].rationale — one line per variant",
|
|
@@ -73,13 +75,12 @@
|
|
|
73
75
|
"register-unit": [
|
|
74
76
|
"`CROSS-CHECK REQUIRED: <what> — <why>` — the check that is needed and why",
|
|
75
77
|
"`CROSS-CHECK REQUIRED:` exact line shape — prefix, em-dash, mark in CAPS, own line",
|
|
76
|
-
"escalation judgement — the CROWD BOUND: attempt each dangerous-category slice once class-scoped, gate on the RESULT,
|
|
78
|
+
"escalation judgement — the CROWD BOUND: attempt each dangerous-category slice once class-scoped, gate on the RESULT, decide on a crowd, and write a block only for the distinctive anchor",
|
|
77
79
|
"final return — the absolute output path plus queries-enumerated count, incomplete-block count, records carried forward",
|
|
78
80
|
"proposal `romanization` beside a single non-Latin term — plain-ASCII Latin form, space-separated syllables",
|
|
79
81
|
"proposal class scoping — pass nice_classes:[...] AND in_scope_classes:[...] on every proposal/call",
|
|
80
82
|
"proposal envelope — predicate enum {exact, default, wildcard, phonetic, owner}, term vs terms, rationale",
|
|
81
83
|
"reading the band back and judging it — keep proposing until the axis's dangerous named band is covered",
|
|
82
|
-
"recall carry-or-justify — for each prior-confirmed conflict, a reasoned drop row written over the fetched record (primary-sweep only)",
|
|
83
84
|
"supplemental proposals — WHICH queries the manifest/frame warrant beyond the dictated set",
|
|
84
85
|
"the dictated entry list — qid, predicate, terms, owner, nice_classes, regions, when-guard, expected_kind, covered_by"
|
|
85
86
|
],
|