clearotron 0.4.1 → 0.5.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +1 -0
  2. package/THIRD-PARTY-NOTICES.md +1 -1
  3. package/bin/start.mjs +33 -8
  4. package/build-info.json +2 -2
  5. package/driver/CHANGELOG.md +23 -0
  6. package/driver/ask-ledger.mjs +86 -15
  7. package/driver/band-shape.mjs +61 -11
  8. package/driver/band-size.mjs +10 -0
  9. package/driver/close-verify.mjs +29 -2
  10. package/driver/common-law-coverage-status.mjs +1 -1
  11. package/driver/connotation-search.mjs +7 -9
  12. package/driver/contract-e3-backlog.mjs +34 -34
  13. package/driver/contract-e3-baseline.json +5 -5
  14. package/driver/contract-vocabulary.mjs +12 -12
  15. package/driver/corrections-delivered.mjs +113 -0
  16. package/driver/corrections-feedforward.mjs +16 -6
  17. package/driver/corrective-arm.mjs +11 -8
  18. package/driver/coverage-form.mjs +3 -0
  19. package/driver/coverage-union.mjs +11 -2
  20. package/driver/digest-queue.mjs +1 -1
  21. package/driver/disposition-call.mjs +1 -1
  22. package/driver/document-coverage.mjs +3 -2
  23. package/driver/effective-scope.mjs +2 -2
  24. package/driver/engine/mcp/band-server.mjs +77 -13
  25. package/driver/engine/mcp/dispositions-server.mjs +2 -2
  26. package/driver/engine/mcp/recording-server.mjs +10 -6
  27. package/driver/findings-model.mjs +16 -4
  28. package/driver/floor-duty.mjs +9 -0
  29. package/driver/gate-metrics.mjs +7 -1
  30. package/driver/gateway.mjs +28 -14
  31. package/driver/goods-evidence.mjs +295 -0
  32. package/driver/knockout-assess-record.mjs +1 -1
  33. package/driver/narrative-refutation-record.mjs +40 -2
  34. package/driver/package.json +1 -1
  35. package/driver/pipeline.mjs +1945 -314
  36. package/driver/placement-decisions.mjs +243 -0
  37. package/driver/placement-form.mjs +42 -8
  38. package/driver/placement-union.mjs +14 -6
  39. package/driver/provider-usage.mjs +10 -7
  40. package/driver/publish/audit-from-spine.mjs +5 -2
  41. package/driver/publish/index.mjs +19 -4
  42. package/driver/publish/xlsx.mjs +6 -6
  43. package/driver/recall-reconciliation.mjs +15 -5
  44. package/driver/record-carry.mjs +70 -6
  45. package/driver/record-discard.mjs +7 -1
  46. package/driver/record-fold.mjs +14 -0
  47. package/driver/record-goods.mjs +101 -5
  48. package/driver/register-plan.mjs +89 -0
  49. package/driver/registry-fidelity.mjs +34 -3
  50. package/driver/remedy-accounting.mjs +52 -14
  51. package/driver/repair-composers.mjs +265 -105
  52. package/driver/repair-scope.mjs +327 -0
  53. package/driver/repair-targets.mjs +92 -0
  54. package/driver/result-noun-fields.mjs +3 -3
  55. package/driver/screen-gate.mjs +96 -0
  56. package/driver/skills/clearance-common-law/SKILL.md +8 -0
  57. package/driver/skills/clearance-register/SKILL.md +5 -5
  58. package/driver/skills/clearance-register/digest.md +14 -14
  59. package/driver/skills/clearance-register/unit.md +3 -3
  60. package/driver/skills/clearance-search/delivery-contract.md +2 -58
  61. package/driver/skills/clearance-search/report-prose.md +12 -3
  62. package/driver/skills/clearance-search/risk-framework-triage.md +1 -1
  63. package/driver/skills/clearance-search/synthesis-rules.md +10 -13
  64. package/driver/skills/clearance-variants/SKILL.md +4 -4
  65. package/driver/skills/knockout-assess/SKILL.md +9 -14
  66. package/driver/skills/knockout-frame/SKILL.md +5 -5
  67. package/driver/skills/narrative-refutation/SKILL.md +1 -1
  68. package/driver/skills/placement-inquiry/SKILL.md +1 -1
  69. package/driver/skills/whatif-memo/SKILL.md +1 -1
  70. package/driver/stage-context.mjs +2 -1
  71. package/driver/stages-knockout.mjs +1 -1
  72. package/driver/stages.mjs +95 -60
  73. package/driver/suite-census.json +367 -19
  74. package/driver/synthesis-record.mjs +310 -8
  75. package/driver/terminal-clamp.mjs +53 -2
  76. package/driver/verify-knockout.mjs +22 -4
  77. package/driver/verify.mjs +23 -3
  78. package/mcp-server/CHANGELOG.md +4 -0
  79. package/mcp-server/lib/driver.mjs +5 -0
  80. package/mcp-server/lib/events.mjs +25 -4
  81. package/mcp-server/lib/findings.mjs +4 -2
  82. package/mcp-server/package.json +1 -1
  83. package/package.json +1 -1
  84. package/portal-ui/package.json +1 -1
  85. package/providers/jx/src/core.js +3 -4
  86. package/providers/jx/src/judge.js +2 -2
  87. package/providers/jx/src/nativeread.js +1 -2
  88. package/providers/oauth-mcp-bridge/CHANGELOG.md +4 -0
  89. package/providers/oauth-mcp-bridge/package.json +1 -1
  90. package/scripts/e2e-first-time.mjs +29 -12
@@ -97,10 +97,8 @@ unit screened candidates out via a provider batch-screen tool (Corsearch: `regis
97
97
  contribution into `negative_rows` — one entry per dropped candidate. A batch-dropped candidate with no
98
98
  entry vanishes from the published audit — a **silent recall loss** — and a drop with no stated reason is
99
99
  refused on the call. **Never** batch-drop a `surface:in-scope-live` / `surface:all-class`
100
- row on goods/services (brand-json lacks G&S) — those fall through to `record_fetch` and are decided on real
101
- goods; **never** drop a Slice-A exact-in-class-live candidate or class-drop an `all_class` row. **Never** batch-drop a `surface:in-scope-live` / `surface:all-class`
102
- row on goods/services (brand-json lacks G&S) — those fall through to `record_fetch` and are decided on real
103
- goods; **never** drop a Slice-A exact-in-class-live candidate or class-drop an `all_class` row.
100
+ row on goods/services (brand-json lacks G&S) — those are decided on the record's goods, read with `band_record`;
101
+ **never** drop a Slice-A exact-in-class-live candidate or class-drop an `all_class` row.
104
102
 
105
103
  **Fetch the SENIOR leg.** When a kept conflict's owner holds SEVERAL
106
104
  registrations of the same mark (a multi-country family), deep-fetch the **senior live leg** — the
@@ -119,8 +117,10 @@ THIS table, in the column shape the deterministic audit builder parses — so it
119
117
  `# Negative Results` (the internal/senior-facing workbook's defensibility record of what was considered and
120
118
  ruled out). Do **not** put these under a separate "audit-only" heading: a heading `buildAuditMd` does not parse
121
119
  never leaves the spine, so the drop vanishes from the delivered audit. An **in-scope-live** off-field drop
122
- (verdict `surface:in-scope-live` / `surface:all-class`) must rest on a `record_fetch` of the real goods, never
123
- a batch-row guess — the driver's acceptance gate **rejects the digest** if such a URI was never fetched. Carry
120
+ (verdict `surface:in-scope-live` / `surface:all-class`) must rest on the official record's goods, read with
121
+ `band_record`, never a batch-row guess. This tool reads evidence already held; it does not fetch. If the required
122
+ record is missing or unavailable, leave the gap explicit. The driver applies the existing fetch-and-recheck
123
+ recovery; an unresolved gap remains disclosed. Carry
124
124
  the **`screen_verdict`, `class`, and `status`** into Notes so the gate can identify the row.
125
125
 
126
126
  **ONE ROW PER RECORD — the row is the unit of DISMISSAL, so it is one record (floor-critical).** A drop row
@@ -187,7 +187,7 @@ rule.
187
187
 
188
188
  You are JUDGMENT (Layer B), not the funnel. The funnel handed up the band in **two states only**: `enumerated`
189
189
  (paged to `has_more:false` — complete) or `incomplete` (a crowd descriptor it could not exhaust). The funnel wrote
190
- **no** clearance verdict — **you** read the complete band and author this per-slice coverage reconciliation. The
190
+ **no** clearance verdict — **you** author this per-slice coverage reconciliation from the band evidence and placement's recorded decisions. The
191
191
  decider of "does an `incomplete` gap matter" is your judgment on the risk picture, **never** a count threshold.
192
192
  There is **no re-search re-loop and no halt**: a material slice you could not fully clear ships as a **CONDITIONAL**
193
193
  with an honest, specific flag — a lawyer always gets a report unless something technically breaks.
@@ -372,12 +372,12 @@ loop and never a no-deliver halt.
372
372
 
373
373
  # MODE B — DIGEST (combine the complete named band → register findings)
374
374
 
375
- You are JUDGMENT, not the machine. The funnel (the unit-mode workers) either **enumerated** a search to completion or reported it **incomplete** (a crowd descriptor). It handed you the **complete named band**; the relevance gate below is the *only* relevance gate, run over **everything that was found**, not a pre-pruned list.
375
+ You are JUDGMENT, not the machine. The funnel (the unit-mode workers) either **enumerated** a search to completion or reported it **incomplete** (a crowd descriptor). The complete named band remains available as evidence. Read the candidates placement carried forward and their supporting evidence through the band tools. Carry placement's accepted set-asides forward with their grounds and exceptions under the placement rules.
376
376
 
377
377
  Your task gives the paths to: the per-axis prose digests (`register-units/<axis>.md` — audit-trail summary only), the variant manifest, `matter-context.md`, and `placement-recommendations.md`. The **band itself is read through the band tools** — you hold `band_shape` / `band_lookup` / `band_record`, and every call you make lands in the run's reading audit (that on-the-record trail is the point: the reading layer is as auditable as the frozen search plan).
378
378
 
379
379
  **The band is the material you judge — read it through the band tools (never by slicing files with shell):**
380
- - **`band_shape` FIRST** — the deterministic shape of the complete merged band (all axes, de-duped): totals, mechanical similarity tiers, **THE FLOORS** (every live in-class identical/near-identical record, listed individually and unconditionally — every floor row must end up rated, placed, or explicitly reasoned away; the list is complete by construction and no lookup pattern excuses skipping one), the class/status/registry/recency census, owner concentrations, the crowd descriptors, and the blind spots the shape mechanically cannot see. The tiers are string mechanics, never a relevance call — Step 2's relevance gate is still yours, and still the only relevance judge. A floors-heavy shape is served in PARTS (the response labels itself part N/M and names the next call): read EVERY part before reasoning — a partial shape is never the shape, and the parts split at line boundaries so every floor row arrives intact.
380
+ - **`band_shape` FIRST** — the deterministic shape of the complete merged band (all axes, de-duplicated): totals, mechanical similarity tiers, floors, class/status/registry/recency census, owner concentrations, crowd descriptors, and blind spots. A floor is marked on its line in the band; a crowded group may show only its first page. A large shape is served in parts. Read the parts and records your reasoning about the carried candidates and accepted placement decisions needs. The tiers are string mechanics, never a relevance or risk judgment. Use the existing placement rules when checking a floor's ending: a validated decision counts only for the records it covers, and an unsupported decision must be flagged.
381
381
  - **`band_lookup`** — pull the records your reasoning needs: by owner, class, tier, plan entry (`qid` — the exact join to the frozen plan's execution ledger), slice (`_query`), mark text, status. Records carry `record_id, mark_text, classes, status, owner_name, owner_country, application_date, registration_date, expiry_date, jurisdictions, screen_verdict` (+ `_query`). These are the real records — the firewall is lifted, nothing was pre-gated. Matching un-enumerated crowds ride along on every lookup, so a counted-only zone can never read back as a clean.
382
382
  - **`band_record`** — the official registry record fetched into this run for a given `record_id`, when detail beyond the band row decides a point. Read-only: an unfetched record is an honest gap to state, never a value to guess.
383
383
  - **`incomplete` crowd descriptors** (`query, total_hits, fetched, reason` — in the shape, and riding along on lookups) are NOT findings and NOT clean negatives. Each is a slice the funnel could not exhaust; you (with `placement-inquiry`'s rulings) decide whether it matters → **cleared** (immaterial noise, `confirmed-clean`) or **material gap** (`coverage-limited` → CONDITIONAL) (see "Coverage ledger" below). Never render a material crowd descriptor as `confirmed-clean`.
@@ -385,7 +385,7 @@ Your task gives the paths to: the per-axis prose digests (`register-units/<axis>
385
385
 
386
386
  Every judgment below spans the band and/or needs data a single unit cannot have, so it MUST happen here.
387
387
 
388
- **Consume `placement-recommendations.md` (from Touchpoint 2 `placement-inquiry`).** The per-candidate tiers ALSO arrive structured in `placements.json` beside the md — `{mark, owner, jurisdiction, records[], tier, reason}` per candidate (plus an optional `borderline: true` — see below), `reason` carrying placement's stated reasoning. When present, the JSON is the authoritative tier record: adopt or override each tier BY ENGAGING ITS `reason` (an override quotes the reason it contradicts — never a silent re-tier; a kept tier may tighten a label while reusing the reason). The md remains the home of the rulings tail (Disagreements, Coverage rulings, Open questions), which you carry forward exactly as below. On a corrective/repair pass do NOT re-read the whole md — the tiers are in the JSON, and the driver hands you the md's rulings tail verbatim in the dispatch (a `PLACEMENT RULINGS TAIL` block): adjudicate against it there, adopting or counter-reasoning each ruling. For each enumerated record in the complete band (the shape's census + your lookups):
388
+ **Consume `placement-recommendations.md` (from Touchpoint 2 `placement-inquiry`).** The per-candidate tiers ALSO arrive structured in `placements.json` beside the md — `{mark, owner, jurisdiction, records[], tier, reason}` per candidate (plus an optional `borderline: true` — see below), `reason` carrying placement's stated reasoning. When present, the JSON is the authoritative tier record: adopt or override each tier BY ENGAGING ITS `reason` (an override quotes the reason it contradicts — never a silent re-tier; a kept tier may tighten a label while reusing the reason). The md remains the home of the rulings tail (Disagreements, Coverage rulings, Open questions), which you carry forward exactly as below. On a corrective/repair pass do NOT re-read the whole md — the tiers are in the JSON, and the driver hands you the md's rulings tail verbatim in the dispatch (a `PLACEMENT RULINGS TAIL` block): adjudicate against it there, adopting or counter-reasoning each ruling. For each candidate `placement-inquiry` placed:
389
389
  - Find the matching entry in `placements.json` (mark text + owner + jurisdiction match; fall back to the md's tier sections on runs that predate the JSON)
390
390
  - Adopt the graduated outcome (`headline-candidate` / `sheet-2` / `watchlist-annex` / `out-of-scope-filtered`) as the placement
391
391
  - **Between `headline-candidate` and `sheet-2`, what you are adopting is an ANSWER, not a label.** Those two tiers are placement-inquiry's written answer to one question — *does this conflict change the advice, or only complete the record?* (a headline entry names what it changes; a sheet-2 entry states why the advice reads the same either way). Adopting means adopting that answer. **Overriding means answering the SAME question the other way, in writing**, in your `### Disagreement resolutions` row — never re-labelling the tier and never substituting a risk-tier argument for the question. An override that does not say what the conflict does (or does not do) to the advice has not engaged the placement
@@ -414,7 +414,7 @@ apparel block merchandising plans even when target classes are clear. If no iden
414
414
 
415
415
  ### Step 2 — Relevance gate
416
416
 
417
- **The gate decides field-relevance, never filer-importance.** Run it over **every enumerated record in the complete band** (work tier by tier / slice by slice through `band_lookup` until the shape's totals are accounted for) — the funnel pre-gated nothing, so this is the only relevance judge. For each enumerated record, ask only: **is the mark on-point — identical / near-identical, sharing the dominant element —
417
+ **The gate decides field-relevance, never filer-importance.** Run it over the candidates placement carried forward, using their supporting band evidence. Where a conclusion depends on an accepted set-aside, check its ground against the supporting evidence and flag an unsupported decision. For each carried candidate, ask only: **is the mark on-point — identical / near-identical, sharing the dominant element —
418
418
  and in or adjacent to the target field?** If yes, it is surfaced and characterised, full stop. **Who**
419
419
  filed it (a multinational, a one-person studio, a tail-market individual) and **how vulnerable** it
420
420
  looks (dormant, revocable, within the non-use grace period) are NOT gate criteria — they are Stage-2
@@ -583,12 +583,12 @@ This skill's universal logic — per-axis funnel, status filter, relevance gate,
583
583
  ## Checklist before handing off — digest mode
584
584
 
585
585
  **Digest mode:**
586
- - [ ] **Complete band read through the band tools** (`band_shape` first, then `band_lookup`/`band_record` until the shape's totals are accounted for — every floor row rated, placed, or reasoned away); any missing/unreadable band ruled a coverage failure (`coverage-limited`/`deferred` → CONDITIONAL), never called clean off the prose digest; identical-match test run over the band; class-25 merch slice checked in the band (or its absence written as an open Coverage row)
586
+ - [ ] Candidates placement carried forward read through the band tools, and accepted set-asides carried forward with their grounds and exceptions under the placement rules; any missing/unreadable band ruled a coverage failure (`coverage-limited`/`deferred` → CONDITIONAL), never called clean off the prose digest; identical-match test run over the band; class-25 merch slice checked in the band (or its absence written as an open Coverage row)
587
587
  - [ ] **Band reconciled against the expectation for THIS mark** — saturated field with no enumerated exact-owner slice ruled a material gap (`coverage-limited` → CONDITIONAL), anything famous-missing surfaced, partner-as-headline flagged for de-prioritisation
588
588
  - [ ] `matter-context.md` read and informing placement (jurisdiction attribution, off-field framing, watchlist seeds)
589
589
  - [ ] `placement-recommendations.md` read and informing tiering; each candidate's graduated outcome adopted or counter-reasoned with audit-trail justification; its coverage-commands/open-questions carried forward
590
590
  - [ ] Per-jurisdiction sub-query attribution (`_query`) carried forward in the findings file's audit trail
591
- - [ ] Relevance gate applied per archetype over the **complete enumerated set** (field-relevance only — filer size/dormancy held for Stage-2, never a drop reason); drops logged
591
+ - [ ] Relevance gate applied per archetype over the candidates placement carried forward (field-relevance only — filer size/dormancy held for Stage-2, never a drop reason); drops logged
592
592
  - [ ] Owner aggregation across the band; owner-identity conflicts flagged `Verify? ✅` (never silently picked)
593
593
  - [ ] **Every coverage-form row ruled through `record_coverage`** — the tool's answer reports nothing outstanding; every `incomplete` crowd descriptor ruled cleared/material-gap; reconciled against `matter-context`'s material-jurisdiction list (every material jurisdiction enumerated-and-cleared, or written `coverage-limited`/`deferred` → CONDITIONAL — never a self-accepted clean over an unsearched slice); rolled-up `{sufficient, reason}` stated for synthesis to emit; genuine open judgment surfaced to ship (not a coverage gap)
594
594
  - [ ] Applicant own-rights sweep run **if priority is live** (tagged `applicant_own_rights`; never a conflict / Findings row / gate)
@@ -598,5 +598,5 @@ This skill's universal logic — per-axis funnel, status filter, relevance gate,
598
598
  - [ ] Watchlist-annex candidates routed to audit-tab + optional brief narrative mention with monitor trigger
599
599
  - [ ] **Dominant-element reconciliation satisfied** — every screened-live dominant-element POSITION ends as a finding row, a drop row citing any one constituent URI, or membership of the ONE counted `dominant-element crowd` row ADDED THROUGH `record_coverage`, whose `unit` value carries `(<N> members)` with `<N>` >= the residual POSITION count (the count is read from `unit`, never from `reason`); the code-ranked closest positions ended individually
600
600
  - [ ] **Sheet-1 rows are POSITIONS** (one row per position, citing at least one constituent URI; owner-divergent pairs left as separate rows per the shape's Cross-references) — never one row per registration of the same right
601
- - [ ] Register findings file written; per-unit counts + per-jurisdiction-subquery counts + thin-unit flags in the audit trail
601
+ - [ ] `record_register_digest` called before you return; any unit that reported it shortcut its axis flagged in your `open_flags` prose
602
602
  - [ ] Open verification flags listed
@@ -61,8 +61,8 @@ is, then read that list in full and decide.
61
61
 
62
62
  1. Ask again for the identical mark, in the instructed classes, limited to the client's goods words. Read
63
63
  that list.
64
- 2. Still a crowd? Ask again with the dominant goods word alone, then one class at a time: the instructed
65
- classes first, then the incumbent's (the classes the owners crowding the list file in). Read each list.
64
+ 2. Still a crowd? Ask again with the dominant goods word alone, then one class at a time, in the instructed
65
+ classes. Read each list.
66
66
  3. Still a crowd? Ask again one question per market, in the order your dispatch names: the order's own countries;
67
67
  on a worldwide order, the customer's priority markets, else the markets the customer's field and brand
68
68
  point to, else the major markets. Read those lists.
@@ -89,7 +89,7 @@ its own count. A narrowing that does not name what it replaced leaves the crowd
89
89
  - **off-field-drop on goods** — brand-json has no goods/services text; an in-scope-class live record is carried forward and the lawyer decides on its actual goods/services. (`screen_verdict` is enrichment for judgment, not a funnel drop authority.)
90
90
  - **sample or self-accept** — no top-N, no "narrow to tractable and stop", no per-jurisdiction 3-fetch ceiling, no switch-to-exact-standalone-as-enumeration. The tool enumerates or reports incomplete — there is no in-between for you to author.
91
91
  6. **Surface dead records WITH their status — no funnel date-cutoff.** Carry every record `register_enumerate` returns **with its `status`** (live / lapsed / expired / lapse-date in the record's dates). You do **NOT** apply a recency/date threshold and you do **NOT** drop dead-except-identical. **`recently-dead` is a STATUS for judgment**, not a funnel filter: whether a recently-lapsed near-identical matters (revival window, field history, non-use vulnerability) is the lawyer's call (Layer B), made on the status + lapse date you passed through. Volume is handled by the completeness contract (step 3): if the dead-inclusive named band is bounded, `register_enumerate` returns it `enumerated`; if it is a crowd, it returns `incomplete` → descriptor. You pass the fact; judgment weighs it. (The old D4 ≤5y date-cutoff drop is **removed** — it was a funnel-side judgment.)
92
- 7. **Write the band artifact, then return.** Write `register-units/<axis>-band.json` (the named-band array, schema below) to `studio/clearance-search/<slug>/<date>/register-units/<axis>-band.json`, **before you return — returning without it is a failure** (the deterministic driver gates on this file: if it is missing after your turn it fails the stage and retries it under a fresh session key; a band that never lands as a file is lost work). Then **file your audit note by calling `record_unit_note`** — you do not write it, and the dispatch hands you no path for it: the driver renders it from your call. **The counts are not yours to type.** Queries enumerated, incomplete blocks and records carried forward are taken from the band you just wrote, so the note and the band cannot disagree; a note filed before the band exists is refused by name, because an account of a sweep that has not happened is not a short note but a wrong one. What you send is the half the band cannot say: `null_result` if this axis genuinely found nothing (refused against a band that carries records), and `note` — one short observation an auditor would want, in a lawyer's words. **The raw character-noise pile stays in this session** — what crosses the firewall is the **complete named band + crowd descriptors** (the `<axis>-band.json` array), NOT the raw rows. Do **not** apply a relevance gate, do **not** aggregate owners, do **not** decide sufficiency — those are judgment's job (Layer B).
92
+ 7. **Write the band artifact, then return.** Write `register-units/<axis>-band.json` (the named-band array, schema below) to `studio/clearance-search/<slug>/<date>/register-units/<axis>-band.json`, **before you return — returning without it is a failure** (the deterministic driver gates on this file: if it is missing after your turn it fails the stage and retries it under a fresh session key; a band that never lands as a file is lost work). Then **file your audit note by calling `record_unit_note`** — you do not write it, and the dispatch hands you no path for it: the driver renders it from your call. **The counts are not yours to type.** Queries enumerated, incomplete blocks and records carried forward are taken from the band you just wrote, so the note and the band cannot disagree; a note filed before the band exists is refused by name, because an account of a sweep that has not happened is not a short note but a wrong one. What you send is the half the band cannot say: `null_result` if this axis genuinely found nothing (refused against a band that carries records), and `note` — one short observation an auditor would want, in a lawyer's words. **The raw character-noise pile stays in this session** — what crosses the firewall is the **complete named band + crowd descriptors** (the `<axis>-band.json` array), NOT the raw rows. Do **not** aggregate owners — that is judgment's job (Layer B).
93
93
 
94
94
  ## What else your grant carries, and why you do not call it
95
95
 
@@ -11,7 +11,7 @@
11
11
  record only** (it sees no other finding — so a card can never carry another finding's body/owner/dates/link).
12
12
 
13
13
  The driver concatenates the shell + the cards (ordered by rated severity — the framework band — then ordinal) under a `# Marks` heading
14
- into `report.md`, then `audit-emit` writes **`audit.md`** (the full audit record). Deterministic code then
14
+ into `report.md`, then the deterministic audit builder writes **`audit.md`** (the full audit record). Deterministic code then
15
15
  renders these into a self-contained HTML report + a styled Excel workbook and publishes them. The combined
16
16
  `report.md` shape below is the ASSEMBLED result — `report-overview` owns everything down to `# Marks`, and each
17
17
  `## ` card is one `report-card`.
@@ -59,9 +59,7 @@ note tripped that guard in conversion 4 and again in conversion 5 — describe t
59
59
  tools.)*
60
60
 
61
61
 
62
- **Curation (the judgment):** promote genuine **on-field** conflicts as headline cards (band-1 placement,
63
- top card `open: true`); identical-mark-but-different-customer findings go **off-field**; the rest go
64
- **out-of-scope**. Mirror the run's actual data. Do **not** emit every finding as a headline card — a run
62
+ **Curation:** The finding's disposition chooses the report band a card renders in; it never recomputes the finding's rating. Mirror the run's actual data. Do **not** emit every finding as a headline card — a run
65
63
  with ~20–50 findings typically curates to a handful of headline cards. Rating vocabulary is the band words
66
64
  of the framework in force (`risk-framework.md` house default, or the profile-selected
67
65
  `risk-framework-<customer>.md`); synthesis discipline follows `synthesis-rules.md`.
@@ -268,57 +266,3 @@ rules below can still be unreadable.
268
266
  unreachable by any search: their absence is never evidence. Name the legal test in plain words
269
267
  (*"applying the well-accepted framework for confusion"*), never a court's factor template. Cut filler
270
268
  (*"session-wide notice coverage"*, *"it is worth noting that"*).
271
-
272
- ---
273
-
274
- ## `audit.md` — the full audit record (mechanical re-format; emit EVERY finding)
275
-
276
- Same forgiving labelled-block markdown. Three sections:
277
-
278
- ```
279
- # Findings
280
- ## <finding / mark text> ← block title = the finding name
281
- - source_layer: Both ← Register | Common-law | Both | Cross-pollination
282
- - type: Direct Conflict
283
- - owner: <owner>
284
- - owner_country: SG
285
- - classes: 9
286
- - status: Live (Registered; …)
287
- - dates: filed … / renewed …
288
- ← (no per-finding risk fields here — the audit is the factual record; the rating is the finding's band
289
- ← word, per the framework in force, carried in findings.json and the curated report)
290
- - source: <provider record refs>
291
- - url: <record base host>/mark/<cc>/<number> ← the composed record URL (Record-URL contract: the ACTIVE provider's base host from `clearance-register/providers/<name>.md` + `uri`); emit the full URL, never a bare /mark/… path and never a host belonging to a register this run did not search
292
- - description: <one line>
293
- - key_factors: ELEVATION: … MITIGATION: …
294
- - cross_ref: N/A
295
- - search_terms: <variants used>
296
- - verify: ✅
297
-
298
- ## <next finding> … ← ALL findings (register + common-law), not just the headline ones
299
-
300
- # Negative Results
301
- ## NR1
302
- - source_layer: Register
303
- - search_term: PROJECT NAME (exact)
304
- - platform: <provider> — worldwide
305
- - result: 0 identical hits
306
- - notes: …
307
- ## NR2 …
308
-
309
- # Audit Trail
310
- ## AT1
311
- - source_layer: Variants
312
- - step: Step 0–6: Archetype + manifest
313
- - query: …
314
- - rationale: …
315
- - source: <stage / tool>
316
- - result_summary: …
317
- - tool_call: N/A
318
- - finding_ref: Manifest
319
- ## AT2 …
320
- ```
321
-
322
- Pull Findings/Negatives/Audit-Trail straight from `register-findings.md` + `common-law-findings.md`
323
- (+ placements). This is re-formatting existing analysis into the block shape — do not re-analyse or
324
- re-search. Omit a key if the source doesn't have it; `Mark` defaults to the report's title at render time.
@@ -19,6 +19,14 @@ writes lives in that stage's own file — the finding sentence and the grouped r
19
19
  [synthesis-rules.md](synthesis-rules.md), the card and section shape in
20
20
  [delivery-contract.md](delivery-contract.md). What is below is general and is stated only here.
21
21
 
22
+ ## At every step: look at what you have before you work on it
23
+
24
+ Fifty? Read them all. A few hundred? Sort by the client's goods and markets, read the near ones first, list
25
+ the rest. A thousand or more? The field is crowded: read the identical and live ones for the client's
26
+ goods, tell the client it is crowded, and do not write up the rest. Carry forward only what a lawyer would
27
+ raise with the client. Write down what you set aside and why. This applies to the register's answer, to the
28
+ list of records, to the placements, to the off-register sweep and to the write-up alike.
29
+
22
30
  ## Two registers, and the reader of the first one is not a lawyer
23
31
 
24
32
  **The reader is a lawyer who layers advice on top — and that lawyer's client reads the same page.** The
@@ -31,9 +39,10 @@ to open something to see it.
31
39
 
32
40
  **DEFAULT-VISIBLE TEXT CARRIES NO LEGAL OR ENGINE VOCABULARY.** Default-visible means anything a reader
33
41
  meets before opening a fold: the summary and the opening line, the basis for the rating, the points for
34
- and against and what would soften them, the one sentence under each name, the four answers, the
35
- reviewer's notes, the caveats, the coverage rows and the lines saying what needs a decision. Ordinary
36
- nouns. One idea per sentence. **No visible sentence over 25 words.** The conclusion first.
42
+ and against and what would soften them, the finding sentence under each name (at most two sentences),
43
+ the four answers, the reviewer's notes, the caveats, the coverage rows and the lines saying what needs a
44
+ decision. Ordinary nouns. One idea per sentence. **No visible sentence over 25 words.** The conclusion
45
+ first.
37
46
 
38
47
  Which stored fields those are is not prose's business and is not listed here — `DEFAULT_VISIBLE_FIELDS`
39
48
  in `driver/plain-register.mjs` names them for both products, in one place, so a field renamed once does
@@ -3,7 +3,7 @@
3
3
  - **Applies to:** Knockout search runs for customers with **no configured framework** (`frameworkPath` absent). A customer's own doc-50 framework, when configured, rates their knockouts instead — this ladder is only the house fallback.
4
4
  - **Source:** ported from the interactive `knockout-searches` skill (the 5-tier rating system the reviewing lawyer calibrated), unchanged.
5
5
  - **Bands, highest to lowest:** Very High · High · Medium · Manageable · **Low**.
6
- - **What this rates:** a *triage* judgment per mark for **the client** — "is there an obvious blocker to USING this name in the market?" — from common-law/marketplace evidence only. It is NOT a clearance verdict, NOT a registrability opinion, and every rating is framed as pending register overlay.
6
+ - **What this rates:** a *triage* judgment per mark for **the client** — "is there an obvious blocker to USING this name in the market?" — from common-law/marketplace evidence and any register filings the run fetched. It is NOT a clearance verdict, NOT a registrability opinion.
7
7
 
8
8
  *The band words are the output. Sub-gradation qualifiers are allowed beside them ("Medium (low)") when a mark sits at a boundary.*
9
9
 
@@ -288,20 +288,21 @@ is earned (see *Volume is not a risk multiplier* and the use-meets-use rule); a
288
288
 
289
289
  ### The finding sentence — the shape of the typed `net`
290
290
 
291
- **One sentence. A conclusion, not a chain.** It answers the single question a lawyer asks of this
291
+ **A conclusion, not a chain.** It answers the single question a lawyer asks of this
292
292
  finding: *is this a problem for me?*
293
293
 
294
- Worked example:
295
-
296
- > Veltra Labs' registered VELTRA is more likely than not to prevail against VELTRA PHARMA in the
297
- > United States.
294
+ **The finding sentence.** At most two sentences, each at most 25 words, in words a client reads
295
+ without a glossary. The first states the outcome as a likelihood: who would win against whom, for
296
+ what goods, where. *"[Owner]'s earlier [mark] would probably win against [your mark] for [goods] in
297
+ [territory]."* The second, only when the first cannot carry it, states what the earlier right covers:
298
+ *"Their registration covers [goods]."* No "prevail". No semicolon, no arrow, no advice, no band word.
299
+ Every fact that does not fit goes in the legal and practical positions below, never dropped.
298
300
 
299
301
  **THE RULE, AND THE THREE MARKS IT FORBIDS.** No semicolon-chain. No `→`. No consequence clause
300
302
  tacked on the end. If the sentence needs a semicolon or an arrow to hold itself together, it is
301
303
  reasoning, and reasoning belongs in `legal_position` / `practical_position` — which the reader opens
302
304
  the moment this sentence says yes. **The parser rejects a `net` carrying either mark**
303
- (`findings_net_chained`), and so does the pre-delivery lint (`net-conclusion-form`). Neither checks
304
- length: there is no cap here and none is coming.
305
+ (`findings_net_chained`), and so does the pre-delivery lint (`net-conclusion-form`).
305
306
 
306
307
  **THE REASONING MOVES; IT NEVER DISAPPEARS.** This is a relocation, not a compression. Every clause
307
308
  the old chain carried — the territories, the goods paraphrased to the worst overlap, the owner's
@@ -311,11 +312,10 @@ ruling rejects. Write the conclusion here; write everything that earns it there.
311
312
 
312
313
  **DO NOT RESTATE THE BAND.** The band word is the verdict and it renders as the card's own chip, next
313
314
  to this sentence. "A Medium-risk conflict" spends the sentence saying what the reader already sees.
314
- Say what is true of the world instead: who prevails against whom, where, and on what.
315
+ Say what is true of the world instead.
315
316
 
316
317
  **WHAT A CONCLUSION LOOKS LIKE.** Name the parties and the territory, and state the outcome as a
317
- likelihood. *"Veltra Labs' registered VELTRA is more likely than not to prevail against VELTRA PHARMA
318
- in the United States."* *"Nothing on the German register reaches the applicant's class-9 goods."*
318
+ likelihood. *"Nothing on the German register reaches the applicant's class-9 goods."*
319
319
  *"Norvell Instruments — a laboratory-equipment maker — could oppose in the EU but has never asserted
320
320
  against a software filer."* Each stands alone, and each is falsifiable.
321
321
 
@@ -330,9 +330,6 @@ phrase. Where the specification is broad and you have paraphrased to its sharpes
330
330
  scope-limiter is **`(among broad goods)`** — it tells the reader you narrowed and that the rest is
331
331
  wider.
332
332
 
333
- **Still no length cap.** A conclusion is short because it is a conclusion, not because it was
334
- trimmed. Never drop a fact to fit; move it below.
335
-
336
333
  ### The grouped reasoned negative
337
334
 
338
335
  Negatives render **grouped by the ground they share** — the group heading and its parenthetical ground
@@ -18,9 +18,9 @@ description: Shared strategy + variant generation for the v3 preliminary tradema
18
18
 
19
19
  ## Spawned session
20
20
 
21
- Invoked from `clearance-search` (orchestrator) as the first stage of any preliminary trademark review. Reads `task` containing: mark(s), class(es), jurisdiction scope, product description, optional industry context. Produces a single artifact — the **variant manifest** — written to the workspace for the downstream skills to consume.
21
+ Invoked from `clearance-search` (orchestrator) as the first stage of any preliminary trademark review. Reads `task` containing: mark(s), class(es), jurisdiction scope, product description, optional industry context. Produces a single artifact — the **variant manifest** — written by the driver from your `record_clearance_variants` call for the downstream skills to consume.
22
22
 
23
- No tool calls. Pure analytical work.
23
+ Hand the manifest back by calling the `record_clearance_variants` tool. Pure analytical work.
24
24
 
25
25
  Companion files:
26
26
  - [transliteration-scripts.md](transliteration-scripts.md) — non-Latin script reference (CJK + Arabic + Cyrillic + Devanagari + Thai + Greek)
@@ -69,7 +69,7 @@ If a mark genuinely doesn't fit any archetype, document the reasoning and fall b
69
69
 
70
70
  ## Output — the variant manifest
71
71
 
72
- A single file inside the active run-dir: `studio/clearance-search/<slug>/<date>/variant-manifest.md`. Slug and date are passed in by the orchestrator (see [clearance-search/SKILL.md → Phase 1](../clearance-search/SKILL.md#phase-1--template)). Markdown by design. Consumed by both downstream skills.
72
+ `variant-manifest.md`, written by the driver from your `record_clearance_variants` call. Markdown by design. Consumed by both downstream skills.
73
73
 
74
74
  ### Format
75
75
 
@@ -474,4 +474,4 @@ Downstream skills do NOT generate their own variants — the manifest is authori
474
474
  - [ ] Watchlists populated (with client-exclusion applied)
475
475
  - [ ] Famous-mark Perplexity calls flagged (or "None")
476
476
  - [ ] Cross-mark themes captured (multi-mark only)
477
- - [ ] Manifest written to workspace
477
+ - [ ] Manifest handed back by calling the `record_clearance_variants` tool, and the tool accepted it
@@ -7,7 +7,7 @@ description: Rate every mark of a KNOCKOUT batch from its raw research payload,
7
7
 
8
8
  You rate each mark of the batch for **triage**: "is there an obvious blocker to USING this name in
9
9
  the market?" — from the mark's raw common-law research payload (`research/<mark>.md`), the frame's
10
- context framing, and nothing else. This is NOT a clearance: no register conclusions, no filing
10
+ context framing, the filings and owner searches you are handed, and nothing else. This is NOT a clearance: no register conclusions, no filing
11
11
  advice. Ratings use **the frozen framework's band vocabulary** (`_driver/framework.json` — the
12
12
  customer's own ladder when configured, else the house triage ladder). State the band WORD. The only
13
13
  sub-gradation is `ratingQualifier: "low"` — it CAPS a band ("Medium (low)", calibration rule 6) and
@@ -31,9 +31,7 @@ there is no other value: a band that needs sharpening is the band above it, stat
31
31
  `findings[]` record carries one conflicting name, its owner, its band, its evidence and its ground.
32
32
  5. **`findings[]` — one typed record per conflicting name you actually found**, ordered most blocking
33
33
  first and numbered `ordinal: 1…N` in that order (the ordinal is per MARK). The code then re-ranks on
34
- the band and renumbers, so what your order decides is the order inside a band. Every cited URL must appear in THAT mark's
35
- research payload — the receipts gate refuses a citation the driver cannot trace, at the chunk, at
36
- the merged artifact and again at publish.
34
+ the band and renumbers, so what your order decides is the order inside a band. A cited URL must appear in the mark's own research payload or in the register records supplied for that mark. The receipts gate refuses a citation the driver cannot trace, at the chunk, at the merged artifact, and again at publish.
37
35
  6. **RETIRED — you are given the filings now, so you do not estimate them.**
38
36
  This ordered an expectation sentence ("moderate volume of filings expected") and forbade a register
39
37
  conclusion, because this seat could not see the register lane. It can: the run's fetched records are
@@ -120,8 +118,8 @@ there is no other value: a band that needs sharpening is the band above it, stat
120
118
  ## Assert nothing you did not examine (non-optional at every depth)
121
119
 
122
120
  This lane screens; it does not enumerate. It holds the marketplace and common-law research payload for
123
- each mark, and — when the register component is configured — two counts per mark: how many filings are
124
- identical to the name, and how many contain it. That is the whole evidence base. Everything below
121
+ each mark, and — when the register component is configured — the filings it fetched and the owner searches
122
+ made for them. That is the whole evidence base. Everything below
125
123
  follows from writing only what it supports.
126
124
 
127
125
  1. **A survivor is never "clear".** Never "clear", "clean", "no conflicts found", "clear to proceed".
@@ -130,14 +128,14 @@ follows from writing only what it supports.
130
128
  empty there — "no exact-name energy drink was identified in the supplement and grocery
131
129
  marketplaces screened" is supportable; "there is no conflicting use" is not. `negatives[]` is
132
130
  where a scoped absence belongs, and every entry carries the `source` that bounds it.
133
- 3. **Register statements stay inside the counts.** The counts are two totals; they enumerate nothing.
134
- So no claim that the register is clear, and equally none that it is crowded — a count cannot see a
135
- field. `registerEstimate` is an EXPECTATION and must label itself as one, ending with a sentence in
131
+ 3. **No claim that the register is clear, and equally none that it is crowded.** Weigh the register
132
+ evidence supplied for each mark. The report states search coverage from the run's recorded results.
133
+ `registerEstimate` is an EXPECTATION and must label itself as one, ending with a sentence in
136
134
  the shape of "This is an expectation only, not a search result."
137
135
  4. **Crowded-field reasoning is about the field you actually screened.** Rule 2 of the calibration
138
136
  rules is judgment over the marketplace and common-law evidence in this mark's own payload and its
139
137
  `findings[]` — cite that evidence. It is never a claim about filings, families, or how many marks
140
- share a token, none of which this lane retrieves. `crowdedField: true` means "the payload I read
138
+ share a token. `crowdedField: true` means "the payload I read
141
139
  shows a crowded field", and if the payload does not show one, it is `false`.
142
140
 
143
141
  The engine appends the depth boundary to `batch.standardCaveats` itself, so never write your own
@@ -337,9 +335,6 @@ looked identical afterwards. `setAside` is where the judgment goes.
337
335
  **It stays the SHORTER digest above the per-mark assessments** — a reader opens it to decide which
338
336
  name to read about, and the mark's own page carries the full read. Keep it tighter than any one
339
337
  mark's `assessment`.
340
- The standing caveats ride `batch.standardCaveats` (chunk 0) verbatim:
341
- - "Ratings reflect our common law assessment. Register analysis may adjust ratings in either direction."
342
- - When ratings feel cautious: "Some ratings may appear cautious; they reflect worst-case common-law exposure pending register confirmation."
343
338
  - **`knockout-findings.json`** (strict, closed keys — one entry per SEARCHED mark; per-CHUNK files
344
339
  carry `chunkSummary` + this chunk's `marks`, chunk 0 also `batch` + `framework`):
345
340
 
@@ -347,7 +342,7 @@ looked identical afterwards. `setAside` is where the judgment goes.
347
342
  { "schema_version": 1,
348
343
  "framework": { "source": "<framework_key>", "ladder": ["<highest>", "..."] },
349
344
  "batch": { "productContext": "...", "standardCaveats": ["..."] },
350
- "chunkSummary": "<markdown narrative for THIS chunk's marks>",
345
+ "chunkSummary": "<markdown for THIS chunk's marks>",
351
346
  "marks": [ { "ref": null, "name": "<verbatim>", "classesSearched": [8], "beltAndBraces": [35],
352
347
  "contextFraming": "...", "rating": "<band word>", "ratingQualifier": null,
353
348
  "classesDriving": [8], "bullets": ["..."], "purpleNotes": ["..."],
@@ -8,7 +8,7 @@ description: Frame a KNOCKOUT batch — scope, belt-and-braces classes, context
8
8
  You are framing a **knockout batch**: a Stage-0 triage screen of several candidate names at once —
9
9
  broad-not-deep, kill/no-kill. Your output drives a CODE-side web search and the assessment turn. The
10
10
  search runs every spelling you name for a mark (task 2e), with the kind of use you name for it (task 2c),
11
- on every place you name for the batch (task 2d), and keeps what each search returned, with no summary. Nothing you write here searches anything.
11
+ on every place you name for it (task 2d), and keeps what each search returned, with no summary. Nothing you write here searches anything.
12
12
 
13
13
  ## Tasks, per the batch
14
14
 
@@ -58,8 +58,8 @@ on every place you name for the batch (task 2d), and keeps what each search retu
58
58
  task 2d.
59
59
 
60
60
  3. **Belt-and-braces classes** per mark: add closely-adjacent classes a prudent search would cover
61
- (e.g. retail 35 beside goods classes; food theme → 29/43). Every addition gets a purple note in
62
- the plan ("Given the use for …, Class N was added for a belt-and-braces approach"). Nice-class
61
+ (e.g. retail 35 beside goods classes; food theme → 29/43). Every addition is marked "belt-and-braces" in
62
+ `classesPlain` (task 8). Nice-class
63
63
  integers only. Scope expansion is NEVER silent.
64
64
  4. **Context framing** per mark (MANDATORY): what does this name read as in THIS context — coined,
65
65
  compound, common phrase, cultural echo? ("Coop" = chicken coop for a poultry brand, not a
@@ -94,5 +94,5 @@ on every place you name for the batch (task 2d), and keeps what each search retu
94
94
  Exactly one row per instructed mark (name parity vs instructed-scope, byte-exact after trim);
95
95
  `beltAndBraces` are Nice ints; `executionOrder` is a permutation of the names. Each mark's `places` holds
96
96
  two or more entries, with no upper limit, one of them `web` and each other a bare host; `spellings` holds 2 or 3 strings, the name among
97
- them. No tool calls, no searching, no register speculation beyond the framing sentence. Also write a
98
- 2–3 sentence scope note as `knockout-frame.md` (what the batch is, which classes, anything flagged).
97
+ them. No searching, no register speculation beyond the framing sentence. Also send a
98
+ 2–3 sentence scope note as `scope_note` (what the batch is, which classes, anything flagged).
@@ -429,7 +429,7 @@ Total flag count is NOT itself a blocking criterion. A run with many flags that
429
429
 
430
430
  - **Don't re-write the narrative.** You flag, you suggest, you don't rewrite.
431
431
  - **Don't approve marginal calls silently.** If the narrative makes a defensible-but-aggressive choice, name it as "defensible but worth surfacing" rather than ignoring.
432
- - **Don't second-guess matter-context's *framing* — but DO use its material-jurisdiction list as your coverage checklist.** You trust `matter-frame`'s strategic framing (what counts as off-field) as ground truth; you do NOT re-decide what is off-field. But its "Materially-matters jurisdictions" list IS the checklist you audit coverage against (see Coverage-ledger audit) — confirming the run actually searched, or honestly deferred, every jurisdiction it called material is your job, not second-guessing.
432
+ - **Use `matter-frame`'s material-jurisdiction list as your coverage checklist.** Confirm that the run actually searched, or honestly deferred, every jurisdiction it called material. Check the grounds of validated placement decisions against the evidence; flag an unsupported decision.
433
433
  - **Take placement-inquiry's per-candidate *facts* as input — but DO independently re-derive the headline and the top tiers.** You trust its factual inquiry, not its conclusions: if the top risk is a partner / own mark, a distinguished house-mark rated above a bare identical, or an optics-driven escalation, challenge it *even though placement-inquiry agreed* (see *Headline sanity*). Consistency with an upstream step is never, by itself, a defence.
434
434
  - **Don't soften your verdict to avoid recomposition.** If something's wrong, say BLOCKING.
435
435
 
@@ -31,7 +31,7 @@ Inherits the orchestrator's tier when invoked inline. No `sessions_spawn` — th
31
31
  - **The named band** — read through the **band tools** (every call lands in the run's reading audit; never slice band files with shell). `band_shape` first: the deterministic shape of the merged band — totals, mechanical similarity tiers, **THE FLOORS** (every live in-class identical/near-identical record, each marked on its line in the band — **every floor has a fate on the form: placed by record id, or set aside by name on its status or its territory (the row's `on`), never on its goods or its owner's customers or field; only a crowd's row of a thousand records or more in (b) covers a floor.** Discussing a floor in your prose is NOT accounting for it: the form is what the driver can check, and a floor with no fate on it is recorded as unanswered whatever the prose says. This is the one duty with no cap — see **Length target**, which bounds the general band and not this), census, owner concentrations, crowd descriptors, blind spots. A large shape is served in parts, each naming the next call. Then `band_lookup` / `band_record` for the records your inquiry needs. This is the funnel's real output, lifted across the firewall:
32
32
  - **enumerated records** — every named record the funnel paged to completion, each carrying `record_id, mark_text, classes, status, owner_name, owner_country, application_date, registration_date, expiry_date, jurisdictions, screen_verdict` (+ `_query` provenance). Nothing was pre-sampled, so your gate is the *only* gate. Fifty? Read them all. A few hundred? Sort by the client's goods and markets, read the near ones first, list the rest. A thousand or more? The field is crowded: read the identical and live ones for the client's goods, tell the client it is crowded, and do not write up the rest. Count each group the shape lists on its own, and apply this to each by its own count. Where the shape shows (a) by its first page, page every line of it with `band_lookup`'s `group` filter before its row: reading a line is not writing it up. A crowd of a thousand or more outside (a) stands on its first page read and the count. The shape lists the band in this order: (a) identical or near-identical to the mark or one of its forms, for the client's goods; (b) the same, in the ordered classes; (c) the same family as the mark, for the client's goods; (d) every other live mark in the ordered classes, for the client's goods; then the rest. The ordered classes are the instructed ones and any class the frame added. Inside each group the lines run first by the client's goods on a live record in the ordered classes, then by live records in those classes, then by goods words, then by the client's markets. In a group of a few hundred, every line is read: the near ones get the full inquiry and a row; every other line is either carried or left to the group's row with the reason, except a floor, which is placed or set aside by name.
33
33
  - **`incomplete` crowd descriptors** — a query the funnel could NOT enumerate (genuinely too large, provider cap, budget): `query, total_hits, fetched, reason`. These are NOT findings and NOT clean negatives — they are signals you must rule on (cleared / material-gap; see "Crowd-descriptor materiality" below). They ride along on matching lookups too, so a counted-only zone can never read as a clean.
34
- - The unit's compact prose digest (`register-units/<axis>.md`) still exists for the audit trail. **The band shape, the band's summary, is the material you judge from; open a record only where the judgment needs it.** Before you set a line aside by name on its goods, read its goods in `band_record`, unless its goods words already show the ground.
34
+ - The unit's compact prose digest (`register-units/<axis>.md`) still exists for the audit trail. **The band shape, the band's summary, is the material you judge from; open a record only where the judgment needs it.** Before you set a line aside by name on its goods, read its goods in `band_record`, unless its goods words already show the ground on goods established as complete. Missing words in cut goods, or in goods whose completeness is unknown, do not establish that the goods are unrelated.
35
35
  - The common-law-findings file at `studio/clearance-search/<slug>/<date>/common-law-findings.md` (common-law candidate inventory)
36
36
  - Any prior `placement-recommendations.md` from earlier rounds (for re-runs after a skeptic-flagged re-spawn)
37
37
 
@@ -16,7 +16,7 @@ gathered and saying what it means under an assumption somebody has handed you.
16
16
 
17
17
  ## What you may not do
18
18
 
19
- - **No new searching.** You have no tools here and there is nothing to call. If answering properly needs
19
+ - **No new searching.** If answering properly needs
20
20
  evidence this run did not gather, that is a LIMIT — state it, do not estimate around it.
21
21
  - **No new verdict.** You do not issue CLEAR, CONDITIONAL or BLOCKING. You say what moves and by how
22
22
  much, and what the verdict line would read if the assumption held. That is a conditional sentence, not
@@ -297,7 +297,8 @@ export const CONTEXT_DERIVATIONS = [
297
297
  // live inside these functions (band-shape.mjs: dominantElementComposites, deriveRegisterPositions,
298
298
  // buildBandShape), which is why a rig that REPLAYS a persisted band-shape.json cannot serve a
299
299
  // seeded arm: it would replay the unseeded artifact and report no movement.
300
- writes: (P) => [P.bandShape, P.bandShapeMd, P.registerPositions],
300
+ // goods-evidence.json: what each record's goods rest on, read from the same run files; no band tool serves it.
301
+ writes: (P) => [P.bandShape, P.bandShapeMd, P.registerPositions, driverDir(P.runDir, "goods-evidence.json")],
301
302
  reads: (P) => [
302
303
  { path: P.registerNamedBand, why: "the merged band the shape is derived FROM" },
303
304
  { path: P.variantManifestModel, why: "targets: the mark, its dominant element, distinctive elements and variants" },
@@ -337,7 +337,7 @@ export const KO_STAGES = {
337
337
  // reached the client as raw cards with no band. The URL rule stays and is scoped: a cited URL must
338
338
  // come from one of the two sources named here, which is the anti-confabulation rule it always was
339
339
  // and never a rule about which of the two.
340
- `Each mark's RAW research payload: the record of its web searches, every spelling on every place, with the listings each search returned and any search that could not run. It holds no summary and no judgment; the judgment is yours. A cited URL must appear in the mark's own payload or in the register records below:`,
340
+ `Each mark's RAW research payload: the record of its web searches, every spelling on every place, with the listings each search returned and any search that could not run. It holds no summary and no judgment; the judgment is yours. A cited URL must appear in the mark's own research payload or in the register records supplied for that mark.`,
341
341
  ...chunkMarks.map((m) => `- ${m.name}: ${K.research(kebab(m.name))}${m.degraded ? ` (DEGRADED: ${m.degraded} — apply the null-results doctrine, never inflate)` : ""}`),
342
342
  // THE ORDERED TERRITORIES, where the request named some. The web questions used to carry them in
343
343
  // their own scope lines and drop what fell outside; the grid returns results and judges nothing, so