clearotron 0.3.3 → 0.4.0-beta.1

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 (142) hide show
  1. package/.env.example +9 -0
  2. package/INSTALL.md +1 -14
  3. package/bin/brandowner.mjs +5 -5
  4. package/bin/connect.mjs +4 -4
  5. package/bin/onboard.mjs +5 -7
  6. package/bin/start.mjs +20 -5
  7. package/bin/update.mjs +6 -1
  8. package/build-info.json +2 -2
  9. package/docs/architecture/04-configuration-reference.md +2 -6
  10. package/driver/CHANGELOG.md +28 -0
  11. package/driver/ask-ledger.mjs +2 -2
  12. package/driver/band-shape.mjs +8 -8
  13. package/driver/blind-frame-model.mjs +1 -1
  14. package/driver/common-law-receipts.mjs +2 -2
  15. package/driver/commonlaw-carry.mjs +2 -2
  16. package/driver/company-bundle.mjs +11 -18
  17. package/driver/connotation-search.mjs +4 -4
  18. package/driver/contract-e3-backlog.mjs +3 -3
  19. package/driver/declination-call.mjs +1 -1
  20. package/driver/declination-tool.mjs +1 -1
  21. package/driver/dev-portal.mjs +1 -1
  22. package/driver/door-call-verdict.mjs +27 -0
  23. package/driver/driver.config.mjs +17 -11
  24. package/driver/e2e/README.md +1 -1
  25. package/driver/engine/mcp/clarivate-server.mjs +2 -1
  26. package/driver/engine/mcp/corsearch-server.mjs +1 -0
  27. package/driver/engine/mcp/euipo-server.mjs +1 -0
  28. package/driver/engine/mcp/free-tier-server.mjs +1 -1
  29. package/driver/engine/mcp/gather-config.mjs +1 -1
  30. package/driver/engine/mcp/perplexity-server.mjs +1 -1
  31. package/driver/engine/mcp/recording-server.mjs +1 -1
  32. package/driver/engine/mcp/signa-server.mjs +1 -0
  33. package/driver/engine/mcp/supplemental.mjs +1 -1
  34. package/driver/engine/mcp/uspto-local-server.mjs +1 -0
  35. package/driver/enqueue-schema.mjs +2 -2
  36. package/driver/feedback-issues.mjs +1 -1
  37. package/driver/feedback-store.mjs +1 -1
  38. package/driver/findings-model.mjs +3 -3
  39. package/driver/flag-snapshot.mjs +1 -1
  40. package/driver/floor-duty.mjs +2 -2
  41. package/driver/form-neighbourhood.mjs +47 -15
  42. package/driver/frame-diff-model.mjs +3 -3
  43. package/driver/gateway.mjs +5 -5
  44. package/driver/jx-lanes.mjs +1 -1
  45. package/driver/known-conflicts.mjs +18 -0
  46. package/driver/log.mjs +2 -2
  47. package/driver/package.json +1 -1
  48. package/driver/pipeline-knockout.mjs +129 -95
  49. package/driver/pipeline.mjs +69 -32
  50. package/driver/placement-carry.mjs +2 -2
  51. package/driver/placement-form.mjs +1 -1
  52. package/driver/portal-mcp-client.mjs +1 -1
  53. package/driver/portal-request-origin.mjs +79 -0
  54. package/driver/portal-service.mjs +45 -17
  55. package/driver/predelivery-lint.mjs +10 -10
  56. package/driver/profile-page.html +9 -13
  57. package/driver/profile-service.mjs +25 -13
  58. package/driver/profiles.mjs +17 -4
  59. package/driver/progress.mjs +1 -1
  60. package/driver/provider-usage.mjs +24 -1
  61. package/driver/publish/index.mjs +17 -5
  62. package/driver/publish/knockout.mjs +3 -2
  63. package/driver/publish/render-knockout.mjs +1 -1
  64. package/driver/publish/render.mjs +14 -3
  65. package/driver/publish/search-depth.mjs +4 -2
  66. package/driver/recall-reconciliation.mjs +1 -1
  67. package/driver/record-carry.mjs +6 -6
  68. package/driver/recording-agreement.mjs +2 -2
  69. package/driver/reference-score.mjs +27 -27
  70. package/driver/register-count.mjs +56 -1
  71. package/driver/register-digest-record.mjs +1 -1
  72. package/driver/register-plan.mjs +5 -5
  73. package/driver/register-records.mjs +10 -1
  74. package/driver/registry-fidelity.mjs +4 -4
  75. package/driver/repair-composers.mjs +6 -6
  76. package/driver/run-economics.mjs +8 -19
  77. package/driver/screen-gate.mjs +1 -1
  78. package/driver/skills/blind-frame/SKILL.md +2 -2
  79. package/driver/skills/clearance-common-law/SKILL.md +2 -2
  80. package/driver/skills/clearance-common-law/perplexity-prompts.md +4 -4
  81. package/driver/skills/clearance-register/digest.md +1 -1
  82. package/driver/skills/clearance-register/unit.md +1 -1
  83. package/driver/skills/clearance-search/report-prose.md +5 -5
  84. package/driver/skills/clearance-search/synthesis-rules.md +4 -4
  85. package/driver/skills/clearance-variants/SKILL.md +2 -2
  86. package/driver/skills/clearance-variants/transliteration-scripts.md +1 -1
  87. package/driver/skills/frame-diff/SKILL.md +2 -2
  88. package/driver/skills/knockout-assess/SKILL.md +9 -9
  89. package/driver/skills/matter-frame/watchlist-reference.md +1 -1
  90. package/driver/skills/narrative-refutation/SKILL.md +2 -2
  91. package/driver/skills/placement-inquiry/SKILL.md +1 -1
  92. package/driver/stage-context.mjs +4 -4
  93. package/driver/stages.mjs +23 -15
  94. package/driver/suite-census.json +138 -42
  95. package/driver/systemd/clearotron-client-mcp.service +24 -0
  96. package/driver/systemd/clearotron-mcp-face.service +24 -0
  97. package/driver/systemd/clearotron-portal.service +24 -0
  98. package/driver/systemd/clearotron-worker.service +24 -0
  99. package/driver/tokens.mjs +26 -17
  100. package/driver/turnaround-bands.mjs +1 -1
  101. package/driver/unit-inventory.mjs +3 -3
  102. package/driver/variant-manifest-model.mjs +1 -1
  103. package/driver/verify.mjs +2 -2
  104. package/driver/whatif-memo-run.mjs +1 -1
  105. package/mcp-server/CHANGELOG.md +8 -0
  106. package/mcp-server/lib/audit.mjs +9 -2
  107. package/mcp-server/lib/http-handler.mjs +7 -3
  108. package/mcp-server/mint-token.mjs +8 -6
  109. package/mcp-server/package.json +1 -1
  110. package/mcp-server/server.mjs +11 -1
  111. package/package.json +1 -1
  112. package/portal-ui/dist/assets/{index-GBbbyQxc.js → index-D_O_55vK.js} +59 -9
  113. package/portal-ui/dist/index.html +1 -1
  114. package/portal-ui/package.json +1 -1
  115. package/providers/_shared/README.md +1 -1
  116. package/providers/_shared/answer-memory.mjs +199 -0
  117. package/providers/_shared/ledger-path.mjs +1 -1
  118. package/providers/_shared/ledger.mjs +47 -5
  119. package/providers/_shared/script-form.mjs +24 -5
  120. package/providers/_shared/term-shape.mjs +5 -5
  121. package/providers/clarivate/src/capabilities.js +11 -0
  122. package/providers/clarivate/src/core.js +140 -13
  123. package/providers/jx-subclass/lookup.mjs +1 -1
  124. package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
  125. package/providers/oauth-mcp-bridge/package.json +1 -1
  126. package/providers/signa/src/capabilities.js +24 -0
  127. package/providers/signa/src/core.js +66 -0
  128. package/scripts/deprecate-below.mjs +114 -2
  129. package/scripts/freeze-example-run.mjs +1 -1
  130. package/scripts/live-surface-check.mjs +11 -2
  131. package/scripts/release-entry-catch-up.mjs +211 -0
  132. package/scripts/release-note-required.mjs +102 -6
  133. package/scripts/release-rehearsal-version.mjs +60 -0
  134. package/scripts/release-sbom.mjs +104 -0
  135. package/scripts/release-visible-check.mjs +7 -5
  136. package/scripts/score.mjs +3 -3
  137. package/shared/brand.mjs +1 -1
  138. package/shared/client-door.mjs +15 -8
  139. package/shared/driver-dir.mjs +20 -9
  140. package/shared/names-in-force.mjs +2 -0
  141. package/shared/scope.mjs +25 -10
  142. package/shared/store-in-repo.mjs +38 -17
package/driver/stages.mjs CHANGED
@@ -1101,15 +1101,15 @@ const scriptFloorDirective = (job, profile) => {
1101
1101
  // ── THE SIX CATEGORY NAMES WERE GIVEN AND NONE OF THEM WAS DEFINED ───────────────────────────
1102
1102
  //
1103
1103
  // An evidence run scored 7 of 9 found, 2 lost, **withheld 0**. Nothing was
1104
- // retrieved and dropped — DELPHI SCIENTIFIC and DELFITY were never searched for. The variant dispatch
1104
+ // retrieved and dropped — KORPHI SCIENTIFIC and KORFITY were never searched for. The variant dispatch
1105
1105
  // named a closed enum of seven categories and defined not one of them, so the model inferred what six
1106
1106
  // words meant from the words themselves and generated against its own inference:
1107
1107
  //
1108
- // DELPHI SCIENTIFIC stem + descriptor. Nothing said a composite is drawn from words that could
1108
+ // KORPHI SCIENTIFIC stem + descriptor. Nothing said a composite is drawn from words that could
1109
1109
  // plausibly follow the distinctive element ON THE GOODS IN SCOPE, so the model
1110
1110
  // produced seven descriptors and every one came from the applicant's own biotech
1111
1111
  // sector — the one place a conflicting mark is least likely to be hiding.
1112
- // DELFITY a fuzzy neighbour. Nothing said how far `phonetic` reaches, or that a shortened
1112
+ // KORFITY a fuzzy neighbour. Nothing said how far `phonetic` reaches, or that a shortened
1113
1113
  // or elided middle is inside it.
1114
1114
  //
1115
1115
  // One absence, seen twice. The ruling (design agent, 2026-08-06) is explicit that the fix is a BETTER
@@ -1565,7 +1565,7 @@ export const STAGES = {
1565
1565
  // filings by their transliteration refused every one — the axis returned no coverage at all). The
1566
1566
  // driver carries BOTH forms on the entry and each provider expresses the one it can answer, so the
1567
1567
  // model's ONE job is to state the pair; it never chooses which form gets searched.
1568
- `ROMANIZATION (MANDATORY on every non-Latin variant value, FORBIDDEN on a Latin one): a variant whose "value" is written in ANY non-Latin script — Han, Katakana, Hangul, Arabic, Cyrillic, Devanagari, Thai, Greek — MUST also carry "romanization": its Latin-script form, syllable-separated by single spaces, PLAIN ASCII LETTERS AND DIGITS ONLY (no tone marks, no diacritics, no leftover characters): 华威豹 → "HUA WEI BAO", ティキスラッシュ → "TIKI SURASSHU", 티키 슬러시 → "TIKI SEULLEOSI", Тики Слаш → "TIKI SLASH". Put each romanization on the row whose OWN value it romanises — never on a neighbouring row, never as a row of its own — and never romanise a value that is already Latin (that row is refused as an orphan). Half the registers we search hold non-Latin filings ONLY under their transliteration and cannot answer the characters at all, so a non-Latin variant without its romanization is a term we cannot search anywhere. WHEN THE MARK OR THE DOMINANT ELEMENT IS ITSELF NON-LATIN, list it as a "core" variant carrying its romanization too — "mark" and "dominant_element" have no romanization slot of their own, and the driver reads every term's romanization off the variant that states it.`,
1568
+ `ROMANIZATION (MANDATORY on every non-Latin variant value, FORBIDDEN on a Latin one): a variant whose "value" is written in ANY non-Latin script — Han, Katakana, Hangul, Arabic, Cyrillic, Devanagari, Thai, Greek — MUST also carry "romanization": its Latin-script form, syllable-separated by single spaces, PLAIN ASCII LETTERS AND DIGITS ONLY (no tone marks, no diacritics, no leftover characters): 华威豹 → "HUA WEI BAO", ワボスラッシュ → "WABO SURASSHU", 와보 슬러시 → "WABO SEULLEOSI", Ваво Слаш → "VAVO SLASH". Put each romanization on the row whose OWN value it romanises — never on a neighbouring row, never as a row of its own — and never romanise a value that is already Latin (that row is refused as an orphan). Half the registers we search hold non-Latin filings ONLY under their transliteration and cannot answer the characters at all, so a non-Latin variant without its romanization is a term we cannot search anywhere. WHEN THE MARK OR THE DOMINANT ELEMENT IS ITSELF NON-LATIN, list it as a "core" variant carrying its romanization too — "mark" and "dominant_element" have no romanization slot of their own, and the driver reads every term's romanization off the variant that states it.`,
1569
1569
  // A7 — the completeness floor the validator holds this output to (armed via the stage contract
1570
1570
  // above). The FAMILY must be stated in full; which member bites stays judgment's call downstream.
1571
1571
  `FAMILY COMPLETENESS (MANDATORY): the variants[] array must state the mark's WHOLE search family, never a single row — at MINIMUM one "core" variant (the mark / a spacing-punctuation form of it), one "phonetic" variant and one "visual" variant; and when the mark, the dominant element or any elements[] value is non-Latin, at least one "transliteration" variant as well (the transliteration-numeric register axis compiles ONLY from transliteration/numeric rows — with none stated, that axis runs empty, silently). A manifest missing any of these fails the stage. State the family completely and let the searches say what is out there — completeness here is structural, it is NOT a ranking, and it never pre-judges which neighbour matters.`,
@@ -2527,7 +2527,7 @@ export const STAGES = {
2527
2527
  },
2528
2528
  "adopt-or-override each placement by engaging its reason, and the `### Disagreement resolutions` rows (one per surfaced disagreement and per borderline:true, each ADOPTED/OVERRODE in writing)": {
2529
2529
  class: "judgment", tokens: ["registerdigest_adjudication_invalid", "registerdigest_adjudication_incomplete"],
2530
- why: "Answering the promotion question the other way, in writing, against a reason another stage authored. #850 keeps it J. The row's SUBJECT is handed over as data (the driver appends the PLACEMENT RULINGS TAIL block, pipeline.mjs:3584), so nothing here is a fetch. [citation unverified]",
2530
+ why: "Answering the promotion question the other way, in writing, against a reason another stage authored. A ruling keeps it J. The row's SUBJECT is handed over as data (the driver appends the PLACEMENT RULINGS TAIL block in pipeline.mjs `digestDispatchExtra`), so nothing here is a fetch.",
2531
2531
  },
2532
2532
  // ── REWRITTEN, NEVER DELETED (the ruling) — AND THE ROW THAT COST THIS CONVERSION A DESIGN ──
2533
2533
  //
@@ -2781,7 +2781,7 @@ export const STAGES = {
2781
2781
  },
2782
2782
  "dominant_element — bound by the driver from the blind model; the seat is not asked for it": {
2783
2783
  class: "mechanical:pre-bound", tokens: [],
2784
- why: "BOUND (#1169) — the classification is now true rather than aspirational. It read \"echo the blind model's, verbatim\" and was WORSE THAN UNREAD: the driver held two copies and preferred the echo over both, so a transcription slip retargeted applyDominantBackstop's spine test — the gate that forces dominant_element_gap true — with no token speaking about it. Now `boundDominantElement` (frame-diff-record.mjs) reads blind-frame-model.json, falling back to the manifest's `Dominant element:` line, and stamps the value into frame-diff.json; the tool's input schema has NO such property, so the field cannot arrive from a seat at all. The artifact keeps carrying it because the parser, the render and the archive all read it — what changed is who writes it",
2784
+ why: "BOUND — the classification is now true rather than aspirational. It read \"echo the blind model's, verbatim\" and was WORSE THAN UNREAD: the driver held two copies and preferred the echo over both, so a transcription slip retargeted applyDominantBackstop's spine test — the gate that forces dominant_element_gap true — with no token speaking about it. Now `boundDominantElement` (frame-diff-record.mjs) reads blind-frame-model.json, falling back to the manifest's `Dominant element:` line, and stamps the value into frame-diff.json; the tool's input schema has NO such property, so the field cannot arrive from a seat at all. The artifact keeps carrying it because the parser, the render and the archive all read it — what changed is who writes it",
2785
2785
  },
2786
2786
  "dominant_element_gap — boolean": {
2787
2787
  class: "judgment", tokens: [],
@@ -3201,7 +3201,7 @@ export const STAGES = {
3201
3201
  // two mechanical marks (semicolon, arrow) are now refused by the parser (findings_net_chained) and
3202
3202
  // named by the pre-delivery lint (net-conclusion-form); the reasoning MOVES to the two positions
3203
3203
  // below, which is why the "do not shorten" rule survives the change unaltered.
3204
- `- net: THE FINDING SENTENCE — MANDATORY on every finding that reaches a reader (the parser REFUSES the file without it: finding_net_missing). It is the single sentence a reader sees before anything else on this finding's card, the sentence the grouped-negative line states, and the one the client brief lists it by. Since #243 it is the ONLY per-finding summary anywhere in the report: the card no longer authors its own one-liner and there is no "The read" section — a finding with no net reaches the reader with a risk chip and no sentence. IT IS A CONCLUSION, NOT A CHAIN (#469): ONE sentence answering the one question a lawyer asks of this finding — IS THIS A PROBLEM FOR ME. Name the parties and the territory and state the outcome as a likelihood ("Veltra Labs' registered VELTRA is more likely than not to prevail against VELTRA PHARMA in the United States."; "Nothing on the German register reaches the applicant's class-9 goods."). NO SEMICOLON-CHAIN, NO "→", NO CONSEQUENCE CLAUSE ON THE END — the parser REFUSES a net carrying a semicolon or an arrow (findings_net_chained). If the sentence needs one to hold together, what you are writing is reasoning, and reasoning goes in legal_position / practical_position, which the reader opens the moment this sentence says yes. THE REASONING MOVES, IT NEVER DISAPPEARS: every clause the retired chain carried — territories, the goods paraphrased to the WORST overlap ("(among broad goods)" as the scope-limiter), the owner's actual business, status and use history, revocation exposure — is still owed IN FULL in those two positions. A net that got shorter because the reasoning got thinner is the one rewrite this ruling rejects. DO NOT RESTATE THE BAND: the band word is the verdict and renders as the card's own chip beside this sentence; say what is true of the world instead. NEVER AN ACTION PRESCRIPTION: no recommended step, no "the practical path is…", no imperative aimed at the reader — the reader is a lawyer who layers their own advice on top, and what a human must do lives in the typed actions register. A standalone sentence: capital letter, full stop, and read it back for number agreement. There is NO length cap and none is coming — a conclusion is short because it is a conclusion, never because it was trimmed; never drop a fact to fit, move it below. ITS SHAPE is specified in synthesis-rules.md → "The finding sentence — the shape of the typed net" (#253, re-ruled #469). Read that section before writing your first net.`,
3204
+ `- net: THE FINDING SENTENCE — MANDATORY on every finding that reaches a reader (the parser REFUSES the file without it: finding_net_missing). It is the single sentence a reader sees before anything else on this finding's card, the sentence the grouped-negative line states, and the one the client brief lists it by. It is the ONLY per-finding summary anywhere in the report: the card no longer authors its own one-liner and there is no "The read" section — a finding with no net reaches the reader with a risk chip and no sentence. IT IS A CONCLUSION, NOT A CHAIN: ONE sentence answering the one question a lawyer asks of this finding — IS THIS A PROBLEM FOR ME. Name the parties and the territory and state the outcome as a likelihood ("Veltra Labs' registered VELTRA is more likely than not to prevail against VELTRA PHARMA in the United States."; "Nothing on the German register reaches the applicant's class-9 goods."). NO SEMICOLON-CHAIN, NO "→", NO CONSEQUENCE CLAUSE ON THE END — the parser REFUSES a net carrying a semicolon or an arrow (findings_net_chained). If the sentence needs one to hold together, what you are writing is reasoning, and reasoning goes in legal_position / practical_position, which the reader opens the moment this sentence says yes. THE REASONING MOVES, IT NEVER DISAPPEARS: every clause the retired chain carried — territories, the goods paraphrased to the WORST overlap ("(among broad goods)" as the scope-limiter), the owner's actual business, status and use history, revocation exposure — is still owed IN FULL in those two positions. A net that got shorter because the reasoning got thinner is the one rewrite this ruling rejects. DO NOT RESTATE THE BAND: the band word is the verdict and renders as the card's own chip beside this sentence; say what is true of the world instead. NEVER AN ACTION PRESCRIPTION: no recommended step, no "the practical path is…", no imperative aimed at the reader — the reader is a lawyer who layers their own advice on top, and what a human must do lives in the typed actions register. A standalone sentence: capital letter, full stop, and read it back for number agreement. There is NO length cap and none is coming — a conclusion is short because it is a conclusion, never because it was trimmed; never drop a fact to fit, move it below. ITS SHAPE is specified in synthesis-rules.md → "The finding sentence — the shape of the typed net". Read that section before writing your first net.`,
3205
3205
  // CHANGE 2 (disposition) — the per-finding PLACEMENT enum the report bands by. You ALREADY reason this in
3206
3206
  // the narrative ("a documented coexistence stands on the record", "distinguished by the house mark",
3207
3207
  // "same token, different field"); name it as a typed token. It sets PLACEMENT/ORDER ONLY and NEVER touches the
@@ -3225,7 +3225,7 @@ export const STAGES = {
3225
3225
  `- off_field_ground (MANDATORY on every off-field finding, FORBIDDEN on every other disposition): EXACTLY one bare token of: ${OFF_FIELD_GROUNDS.join(" / ")}. "different-field" = the goods/services genuinely do not meet — a claim ABOUT THE GOODS, and the validator checks it against your own meters: a different-field finding whose goods_proximity is not "low" is REJECTED, because one record cannot say "a different commercial field" and "the goods are proximate" at the same time. "no-material-risk" = the framework's clear win — a conflict ${framework ? framework.entity_label : "the client"} plainly wins, worth the client knowing, carrying no field claim at all. THE LABEL FOLLOWS THE ARGUMENT: if what separates you from this mark is the MARK — its sound, rhythm, syllable count, orthography, connotation — then the disposition is "distinguished", NOT off-field, whatever the fields are. "Placed off-field on rhythm" is a mark argument wearing a sector label, and a reader who is told a proprietor is not in our field when the goods wording covers ours has been given a conclusion with the wrong reason attached. Where the goods overlap and the marks are argued apart, say "distinguished" and rate it.`,
3226
3226
  `- manageable (MANDATORY on every notable-but-manageable finding — dispositions coexistence-partner / distinguished): {"category":"<EXACTLY one of large-competitor / commercial-partner / troll / well-known-enforcer>","reason":"<one-two lines: WHY this finding is manageable for THIS client — the fact that makes it notable-but-not-blocking>"}. PROMOTE-OR-OMIT: a finding you would place in the manageable band that fits NONE of the four categories is either relevant enough to drive the read (make it disposition adversarial — it belongs in the on-field section) or not worth the lawyer's line (omit it) — never a category-less parking spot. Never put manageable on an adversarial or off-field finding. FACTS THAT CONDITION, NEVER ADVICE (the overall_caption rule, same voice): these fields render VERBATIM on the report — they state what IS, never a step to take. NEVER prescribe ("narrow the goods", "seek consent before filing", "file first", "add a disclaimer") and NEVER use advice grammar ("we recommend", "you should", "the practical path is") — every forward ask lives in the actions register, code-built from it; a prescription typed here is a delivery defect the lint flags.`,
3227
3227
  `COMMON-LAW PARITY: a common-law / marketplace finding gets THE SAME rating machinery as a register finding — the framework's band by the same method, the same meters, the same legal_position / practical_position split, the same disposition logic (and manageable where it applies). The renderer keeps common-law in its own section (a different LEGAL BASIS — unregistered rights), but the section split is presentation: never leave a common-law conflict unrated, half-metered, or rated on a softer scale because its source is marketplace/web rather than a register.`,
3228
- `CROWDING IS PER-MARKET ONLY (§L): every crowd / dilution / "crowded field" statement — in the narrative, a finding's reasoning, legal_position, or coverage prose — NAMES the market it was counted in (jurisdiction × goods lane: "the US class-32 register carries ~N live TIKI-formative marks"), because that is the only lane where the dilution is earned (the WP-56 rule above). A GLOBAL crowd statement ("the field is crowded", "TIKI is diluted worldwide") is FORBIDDEN on every surface — volume elsewhere earns nothing here, and a global sentence is how it leaks.`,
3228
+ `CROWDING IS PER-MARKET ONLY (§L): every crowd / dilution / "crowded field" statement — in the narrative, a finding's reasoning, legal_position, or coverage prose — NAMES the market it was counted in (jurisdiction × goods lane: "the US class-32 register carries ~N live WAVO-formative marks"), because that is the only lane where the dilution is earned (the WP-56 rule above). A GLOBAL crowd statement ("the field is crowded", "WAVO is diluted worldwide") is FORBIDDEN on every surface — volume elsewhere earns nothing here, and a global sentence is how it leaks.`,
3229
3229
  // RATING CALIBRATION CHALLENGE (judgment-not-rules): symmetric self-check answered BEFORE committing each finding's band. The engine's guardrails all police OVER-rating; this adds the missing UNDER-rating probe and forces the band to match the prose, both directions. Not a formula — a question the reasoning must answer.
3230
3230
  `RATING CALIBRATION CHALLENGE — for EACH rated finding, before you commit its band, answer the one that applies (this is symmetric: it catches BOTH over- and under-rating, and the band MUST match your own prose):
3231
3231
  (a) OVER-RATING check — if this finding's own reasoning says the marks are "distinguishable as wholes", or "better-than-even is not reached", or there is no real commercial overlap (the senior's actual use does not meet ours), or the shared dominant element is a heavily-diluted crowded element, then the read belongs in the framework's LOWEST band — or is not a rated conflict at all — never the middle band: a crowded field is a CEILING that lets you reach the client-favoured read, never a FLOOR that parks an over-threshold mark in the middle (synthesis-rules.md → "the band follows the words" posture + "Crowded field analysis"). Do not pull a mark down one band and then stop when the same reasoning carries it lower.
@@ -3300,7 +3300,7 @@ export const STAGES = {
3300
3300
  // A1 — the home for a famous neighbour the famous-neighbour rule keeps but no record grounds. WITHOUT
3301
3301
  // this, such a mark was forced into findings[] with an empty-uri registration, which the F-14 URI guard
3302
3302
  // (rightly) hard-rejects — the crash this fix closes. Keep it OUT of findings[]; never fake a registration.
3303
- `FAMOUS-NEIGHBOUR / UNGROUNDED REFERENCE (context_notes): a mark you carry for diligence because it is a famous one-keystroke or homophone NEIGHBOUR of the searched mark (the famous-neighbour rule — never dropped) but for which you fetched NO register record AND cited NO common-law record — i.e. it is known only from general knowledge (e.g. CHROME on a KROME clearance) — is NOT a finding. Do NOT put it in findings[], and NEVER invent a registration for it: an empty-uri registration, or a register source_type on a knowledge-only mark, is REJECTED (no finding may ship without a fetched record). Instead add it to the top-level "context_notes" array — each object EXACTLY {"type":"famous-neighbour-ungrounded","mark","owner","context"}: mark = the neighbour verbatim; owner = the holder if known (omit the key if not); context = one line on why it is noted and why it is not a grounded conflict (the field divergence / no record fetched). A context note carries NO band/meters and NEVER moves the overall rating. If the neighbour IS a real conflict, do the opposite — GROUND it (fetch a representative registration so it carries a real uri) and keep it as a normal finding.`,
3303
+ `FAMOUS-NEIGHBOUR / UNGROUNDED REFERENCE (context_notes): a mark you carry for diligence because it is a famous one-keystroke or homophone NEIGHBOUR of the searched mark (the famous-neighbour rule — never dropped) but for which you fetched NO register record AND cited NO common-law record — i.e. it is known only from general knowledge (e.g. KODAK on a CODAK clearance) — is NOT a finding. Do NOT put it in findings[], and NEVER invent a registration for it: an empty-uri registration, or a register source_type on a knowledge-only mark, is REJECTED (no finding may ship without a fetched record). Instead add it to the top-level "context_notes" array — each object EXACTLY {"type":"famous-neighbour-ungrounded","mark","owner","context"}: mark = the neighbour verbatim; owner = the holder if known (omit the key if not); context = one line on why it is noted and why it is not a grounded conflict (the field divergence / no record fetched). A context note carries NO band/meters and NEVER moves the overall rating. If the neighbour IS a real conflict, do the opposite — GROUND it (fetch a representative registration so it carries a real uri) and keep it as a normal finding.`,
3304
3304
  // judgment-relocation (revised 2026-06-24): the SUFFICIENCY decision lives HERE, in judgment — never in the
3305
3305
  // funnel. You read the complete band + the `incomplete` crowd descriptors and decide whether the dangerous
3306
3306
  // picture is complete enough to SIGN. Your decision drives the VERDICT only: if a material slice is not
@@ -3308,7 +3308,7 @@ export const STAGES = {
3308
3308
  // re-loop and NO no-deliver halt: a lawyer always gets a report unless something technically breaks.
3309
3309
  // WP-56 B2 — the standing "mark itself" read: every report carries it whether or not the brief asks
3310
3310
  // (a staff lawyer, teal-lattice). Typed field → code-rendered at the TOP of the report on both variants.
3311
- `MARK ASSESSMENT (MANDATORY top-level field of the findings record you send): emit "mark_assessment": {"distinctiveness":"<1-2 sentences>","connotation":"<1-2 sentences>"} — your standing read of the APPLICANT'S OWN mark, in your own lawyer voice. §L BUDGET: ONE OR TWO SENTENCES EACH, and the detail goes into the typed rows of the STRUCTURED FORM below rather than into a longer paragraph — the block ran 854 words on the delivered report and its job is two short reads. CONNOTATION LEADS WITH THE FLAGGED READING: if a loaded, subcultural or offensive secondary reading surfaced, it is the FIRST thing the field says; when the sweep genuinely came back clean, state that once as a data point and STOP. Never open with a list of what the mark is NOT ("no offensive reading, no gang association, no adverse political connotation, no…") — an inventory of absent problems is the most recognisable machine tell there is, and it buries the one reading that matters when there is one. It is advisory (for the reviewing lawyer to assess), frames the report, and NEVER moves any band or rating. distinctiveness: where the mark sits on the spectrum (coined / arbitrary / suggestive / descriptive) in the applicant's field, its dominant element, any obvious registrability flag (descriptive / generic / laudatory / geographic / deceptive — or "plainly distinctive, no flag"), AND the per-market read of the manifest's translated/transliterated forms (the variant manifest's "Distinctiveness & registrability" section is your input — carry its judgment forward or better it: e.g. "descriptive once translated in <market>"). connotation: what the mark READS as — English AND non-English (the meaning sweep's results incl. the non-Latin/translated forms): any loaded / subcultural / offensive secondary reading, or the clean result stated as a DATA POINT ("no adverse readings surfaced across <the languages/scripts searched>") — never an unsearched assertion, never a sweep dump. Plain client English ("coined and strong"). Real PR/reputational HITS still live in their own section — this block is the standing read, not the incident report. STRUCTURED FORM (preferred when your read carries per-class / per-market / counter-registration detail): either field may instead be an OBJECT {"read":"<1-2 SHORT sentences — the consequence for the client, e.g. \\"A weak name to own. SLUSH is simply what the product is, so the whole mark rests on TIKI.\\">","spectrum":"<the one-line placement>","per_class":[{"class":"5","note":"…"}],"per_market":[{"market":"CN","note":"…"}],"counter_registrations":[{"mark":"…","uri":"/mark/…","note":"…"}],"acquired":"<optional>","note":"<optional residual>"} — typed rows instead of one wall paragraph. ALWAYS include "read" on the structured form: it is the ONLY prose the reader sees up front (the report collapses the rows behind toggles; the audit workbook renders the rows in full). NEVER pack per-class/per-market rows into a single prose string when you have them as rows.`,
3311
+ `MARK ASSESSMENT (MANDATORY top-level field of the findings record you send): emit "mark_assessment": {"distinctiveness":"<1-2 sentences>","connotation":"<1-2 sentences>"} — your standing read of the APPLICANT'S OWN mark, in your own lawyer voice. §L BUDGET: ONE OR TWO SENTENCES EACH, and the detail goes into the typed rows of the STRUCTURED FORM below rather than into a longer paragraph — the block ran 854 words on the delivered report and its job is two short reads. CONNOTATION LEADS WITH THE FLAGGED READING: if a loaded, subcultural or offensive secondary reading surfaced, it is the FIRST thing the field says; when the sweep genuinely came back clean, state that once as a data point and STOP. Never open with a list of what the mark is NOT ("no offensive reading, no gang association, no adverse political connotation, no…") — an inventory of absent problems is the most recognisable machine tell there is, and it buries the one reading that matters when there is one. It is advisory (for the reviewing lawyer to assess), frames the report, and NEVER moves any band or rating. distinctiveness: where the mark sits on the spectrum (coined / arbitrary / suggestive / descriptive) in the applicant's field, its dominant element, any obvious registrability flag (descriptive / generic / laudatory / geographic / deceptive — or "plainly distinctive, no flag"), AND the per-market read of the manifest's translated/transliterated forms (the variant manifest's "Distinctiveness & registrability" section is your input — carry its judgment forward or better it: e.g. "descriptive once translated in <market>"). connotation: what the mark READS as — English AND non-English (the meaning sweep's results incl. the non-Latin/translated forms): any loaded / subcultural / offensive secondary reading, or the clean result stated as a DATA POINT ("no adverse readings surfaced across <the languages/scripts searched>") — never an unsearched assertion, never a sweep dump. Plain client English ("coined and strong"). Real PR/reputational HITS still live in their own section — this block is the standing read, not the incident report. STRUCTURED FORM (preferred when your read carries per-class / per-market / counter-registration detail): either field may instead be an OBJECT {"read":"<1-2 SHORT sentences — the consequence for the client, e.g. \\"A weak name to own. SLUSH is simply what the product is, so the whole mark rests on WAVO.\\">","spectrum":"<the one-line placement>","per_class":[{"class":"5","note":"…"}],"per_market":[{"market":"CN","note":"…"}],"counter_registrations":[{"mark":"…","uri":"/mark/…","note":"…"}],"acquired":"<optional>","note":"<optional residual>"} — typed rows instead of one wall paragraph. ALWAYS include "read" on the structured form: it is the ONLY prose the reader sees up front (the report collapses the rows behind toggles; the audit workbook renders the rows in full). NEVER pack per-class/per-market rows into a single prose string when you have them as rows.`,
3312
3312
  // P5 (charter 2026-07-30 + Round-2 §4) — the four answers as DATA where computable. Judgment
3313
3313
  // tokens are lawyer-authored with a stated basis, never a computed score (ROUND2-FINDINGS B11);
3314
3314
  // an answer the run cannot ground is OMITTED, never faked — the narrative carries the honest
@@ -3322,7 +3322,7 @@ export const STAGES = {
3322
3322
  // code-rendered FROM this register, so bucket prose and disposition can never drift apart.
3323
3323
  `ACTIONS REGISTER (MANDATORY top-level field of the findings record you send): emit "actions": [...] — ONE object per forward step your opinion names that a HUMAN must still take, each EXACTLY {"id","kind","text","ordinals"} plus an OPTIONAL "deadline" and an OPTIONAL "condition". RULE: if your narrative, your overall reasoning, or any finding names a forward legal step (consent, coexistence, territorial delimitation, narrowing the goods, changing the mark, responding to an examiner objection or opposition, clearing a senior right, a required in-jurisdiction counsel opinion), that step MUST exist here as a typed action whose kind matches your own words — a prose-only condition is a delivery defect the reviewer flags. id: 1-based unique integer. kind: EXACTLY one of — CONDITIONS (a forward legal act must happen before the client can rely on a clean result; any one of these makes the run deliver CONDITIONAL): consent / coexistence-agreement / territorial-delimitation / goods-amendment / mark-modification / senior-clearance / proceeding-response / counsel-opinion-required; ADVISORY (never gates a clean result): client-fact (a fact only the client holds — their own prior filing, intended markets; renders as a labelled open question) / commercial-decision (a risk-appetite call that is theirs) / monitoring / filing-routine (ordinary filing mechanics — the "nothing beyond ordinary filing" home). DECLARE the kind from your legal read of what must happen, never from how severe the band is — the kind, not the band, decides CLEAR vs CONDITIONAL. text: ONE client-plain sentence starting with a capital letter that a lay client can act on — it renders VERBATIM and WHOLE in the email's "subject to:" box and the report's action list, so nothing you write here is dropped and nothing is summarised for you. IT MUST FIT ONE LINE OF THE VERDICT STATEMENT: the delivered sentence every surface joins reads "<Tier> — conditional on: <this> (and N more)." and clips at ${STATEMENT_CLAUSE_MAX} characters with an ellipsis, so an ask longer than that ends "…" on the index, the run status, the report hero, the email headline and the workbook. A delivered report carried asks of 350-600 characters. THE ASK IS THE STEP, NOT THE ARGUMENT FOR IT: the reasoning belongs in the finding this action closes (its "ordinals"), where a reader who wants it will look. If the step will not fit in one short sentence, it is not yet clear enough to ask for. LAWYER ENGLISH, NEVER ENGINE ENGLISH (§L): write what a lawyer would actually say to a client — "Investigate whether <owner> is using the mark in <market>", never "Test for non-use". An ask may NEVER name one of this system's own mechanisms as the step: no "rerun the watchlist owner-by-owner screen", no "close the script gaps by the transliteration index route", no "read the N unread registry documents". Reading this run's own records is the ENGINE's job and was owed before delivery — printing it as something the reader must do is a defect, not an action. Test each one: if it does not read as a sentence a lawyer would say aloud to a client, it is not an action — it is either work this run owed, or it is nothing. condition (OPTIONAL, CONDITION kinds only): the SAME demand restated as the factual open-state it closes — a FACT, never an instruction, and a fact THIS RUN ESTABLISHED (§L — never assume the client's own file): "No consent from <owner> appears on the record searched", "The examiner's objection is unanswered". Do NOT write "consent is not in hand" or "no coexistence agreement is in place": the client may hold one and no search this run ran could see it — say what the record shows, scoped to the record. The delivered verdict statement's "conditional on:" lede prefers this field over the imperative text, so type it whenever the fact reads better than the ask. ordinals: the findings[] ordinals this action closes ([] for a run-level action). deadline: {"kind","date"} (ISO date) whenever the action has a hard date — an opposition window, a statement-of-use date; a recorded register deadline that demands action must ride here, never only in prose. A clean run with nothing beyond ordinary filing legitimately emits "actions": [] — never invent an action, and never leave a named one out.`,
3324
3324
  `COVERAGE JUDGMENT (MANDATORY top-level field of the findings record you send): emit "coverage_judgment": {"sufficient":<bool>, "reason":"<one line: what you have seen of the dangerous category and why it is / is not enough to sign>"} — EXACTLY those two keys. Do NOT emit "rows": the driver writes that register itself, one row per open slice, from the coverage ledger and the plan-execution receipt you were handed above; anything you type there is replaced wholesale. Retyping a slice identifier is how a slice comes to be named two ways that nothing makes agree — the machine writes the row, you rule on it. Decide it on the RISK PICTURE, never a count. Its ONLY effect: sufficient:false clamps the verdict CLEAR→CONDITIONAL (the report still ships, carrying your reason). Do NOT emit commands[] or halt — there is no re-enumeration loop and no human-halt; you deliver a conditional instead:`,
3325
- `- An `+"`incomplete`"+` crowd that is IMMATERIAL to the dangerous category (off-field noise, a saturated everyday-word substring pile that is not the named band) → sufficient:true. That is you, the lawyer, deciding it is enough; the run delivers clean (subject to the findings). spec-49 doctrine: a crowd-gated SKIPPED fringe (#361) is not itself a coverage hole, and a crowd descriptor is risk-REDUCING dilution evidence for your per-mark reasoning (cap-as-ceiling, synthesis-rules §Crowded field analysis) — only a MATERIAL uncleared slice (exact/near-identical named variant × in-scope class × material jurisdiction) drives sufficient:false, with the per-mark reason named. The descriptor's existence alone NEVER makes the verdict conditional.`,
3325
+ `- An `+"`incomplete`"+` crowd that is IMMATERIAL to the dangerous category (off-field noise, a saturated everyday-word substring pile that is not the named band) → sufficient:true. That is you, the lawyer, deciding it is enough; the run delivers clean (subject to the findings). A crowd-gated SKIPPED fringe is not itself a coverage hole, and a crowd descriptor is risk-REDUCING dilution evidence for your per-mark reasoning (cap-as-ceiling, synthesis-rules §Crowded field analysis) — only a MATERIAL uncleared slice (exact/near-identical named variant × in-scope class × material jurisdiction) drives sufficient:false, with the per-mark reason named. The descriptor's existence alone NEVER makes the verdict conditional.`,
3326
3326
  `- An `+"`incomplete`"+` band that IS material (the exact mark / a near-identical named variant in an in-scope class was NOT enumerated to has_more:false, or a material jurisdiction's named band is unfinished) → sufficient:false, with a reason that NAMES the un-cleared slice specifically ("the exact-NOVA PULSE × cl.9 live slice returned ~N,NNN hits and could not be fully enumerated"). The run ships CONDITIONAL and names the un-cleared dangerous slice in the RISK READ as a substantive verdict input — analysis: you, the lawyer, stating what you could not fully clear and why it bears on the answer — NOT as a "[Gap] we should close" caveat in # Actions (doc-35: the report states its reasoned view, it does not narrate an unfinished search as a client to-do). Be specific — name the slice, not "coverage limited".`,
3327
3327
  // crowd-context (2026-07-22) — the ubiquity path: ADDITIVE to the material path above, licensed
3328
3328
  // ONLY when the driver's crowd-context artifact is on disk and actually covers the slice. It moves
@@ -3331,7 +3331,7 @@ export const STAGES = {
3331
3331
  // carry an explicit ubiquity read". The counts remain evidence; the lawyer's named reasoning decides.
3332
3332
  `- A MATERIAL un-enumerated slice WHERE the driver's CROWD CONTEXT is present (${P.crowdContext}, readable mirror ${P.crowdContextMd} — gathered precisely because the slice was too large to enumerate: per-term live counts, the same counts restricted to the in-scope classes, and the exact/near-identical subset FULLY enumerated when it was small enough) → the crowded-field/ubiquity path is OPEN to you: you may reach sufficient:true by EXPLICIT crowded-field/ubiquity reasoning that NAMES those counts and the clean enumerated sample in your reason ("the exact/near-identical <TERM> × cl.<N> subset — M records — was fully enumerated and every record is cleared or distinguished in the findings; the formative term rides ~N,NNN live registrations register-wide and ~N,NNN in the in-scope classes — ubiquity the per-mark confusion analysis already prices in"). The counts are evidence for the reasoning, never a threshold: no number makes the picture sufficient by itself — your reasoning over the named counts and the actually-seen sample does. It stays sufficient:false when the enumerated exact/near-identical sample is ABSENT (the subset was itself too large to enumerate, or no slice in the artifact matches the gap) or when that sample contains a mark your findings have NOT cleared — an unseen or uncleared dangerous subset is exactly the doubt the previous path exists for. With NO crowd-context artifact on disk, the previous path stands unchanged: a material un-enumerated slice is sufficient:false.`,
3333
3333
  `- The band is COMPLETE and you are satisfied → sufficient:true → the run delivers (clear, subject to findings). NOTE: an OPEN JUDGMENT (the search IS complete but the legal/commercial answer genuinely admits more than one defensible call — "coexistence with a partner is the client's commercial call"; "get a second opinion on the EU class-25 angle") is NOT a coverage gap: it does NOT set sufficient:false. Surface it as reasoning in the narrative + # Actions and SHIP it. The test is "is the uncertainty about whether I LOOKED (→ sufficient:false, conditional), or about what the COMPLETE picture MEANS (→ open judgment, ships)?"`,
3334
- // VOICE / PRIORITISATION (the Razer-headline fix). Lead with the genuine top risk, not a partner by default.
3334
+ // VOICE / PRIORITISATION (the Korvane-headline fix). Lead with the genuine top risk, not a partner by default.
3335
3335
  // P6 — the house prose contract (word budgets, each fact once at its rank, no prescriptions,
3336
3336
  // no disclaimers, one reader, the §L language rules). Carried by the four stages that author
3337
3337
  // reader-facing prose; the level-2 skill files above teach the same contract, never a variant.
@@ -3774,7 +3774,7 @@ export const STAGES = {
3774
3774
  `Send \`overall_caption\` — the WHOLE summary, ONE line, at most 3 sentences of plain legal English: the one driver + what conditions reliance (the decisive OPEN FACT, never a prescribed step). Every other front-matter key is the driver's and is stamped from what it already holds; you never type one.`,
3775
3775
  // CHANGE 3 (voice / codes) — overall_caption carries ZERO risk codes. CHANGE 1 — it never LEADS with a coverage gap.
3776
3776
  `overall_caption VOICE: write plain CONSEQUENCE + the FACT that conditions it, with ZERO risk codes — no retired "Level C" / "Composite 3" codes, no bare "Horse Trade" / "Paper Conflict" / "Classic" / "Nuisance" dispute-type tokens, no engineering register ("axes", "Option D", query/fetch counts). Say what it MEANS and what STATE OF THE WORLD determines exposure ("one owner holds a near-identical mark for the same goods and is likely to object — no coexistence or consent appears on the record searched"), not the code. NOTE the shape of that example (§L): the conditioning fact is scoped to what this run SAW. Never write "consent is not in hand" or "coexistence is not in place" — the client may hold either, and no search this run ran could see it. FACTS THAT CONDITION, NEVER ADVICE: the caption names the driver + what conditions reliance; it NEVER prescribes a step ("narrow the goods", "seek consent before filing") and never uses advice grammar ("we recommend", "the practical path is") — the forward asks are code-built from the findings.json actions register, and a caption that repeats them as instructions is a defect. No terse code tag anywhere — the driver renders each card's risk chip from its record; captions carry plain consequence only. And do NOT LEAD the caption with a coverage gap — lead with the substantive risk and the driving finding; a genuinely un-cleared dangerous slice is named in the risk read as analysis (and a genuine human-only step rides the actions register), never the headline and never a closeable-search caveat.`,
3777
- // judgment-relocation (2026-06-23): the Razer-headline fix — lead with the GENUINE top risk, not a partner.
3777
+ // judgment-relocation (2026-06-23): the Korvane-headline fix — lead with the GENUINE top risk, not a partner.
3778
3778
  `LEAD WITH THE GENUINE TOP RISK: the caption + the order of # Actions must headline the conflict that actually drives the verdict (the bare / near-identical mark in a core class whose owner can and would block — disposition adversarial, the most severe band). Do NOT lead with a commercial partner / coexistence-relationship finding just because it is prominent or familiar — that finding is surfaced RISK-FIRST: the band consequence leads and the conditioning FACTS follow ("a rated <band> conflict — the coexistence is documented and neither party has challenged it; continuing it is the client's commercial call" — §L: say what "undisturbed" MEANS, in plain words; a right or an arrangement is never described as "undisturbed" on a reader surface); a path/response clause ("the realistic path is …", "the practical path is …") is retired voice — it may never appear, never LEAD a finding's line and never stand in for its rating. It is not the headline unless it genuinely IS the top risk. Reflect the synthesis prioritisation; never re-order by who the reader recognises.`,
3779
3779
  `There are no sections for you to lay out and no headings to emit — the driver renders them. Send \`actions\` (the checks and what they found) and, only when there is a genuine scope note to make, \`methodology\`. Coverage is built deterministically from the typed coverage[] states in findings.json and is never yours. Mark an internal-only note by sending that bullet with \`internal: true\`; do not type a ::p:: marker.`,
3780
3780
  // spec 64 — "### Only you can close these" is NO LONGER authored here: the driver CODE-BUILDS it
@@ -3941,7 +3941,7 @@ export const STAGES = {
3941
3941
  // A card that still ARRIVES with a head renders the old way, so archived runs and a drifted seat
3942
3942
  // are byte-identical rather than gaining a second head. See carriesOwnFrame().
3943
3943
  `WRITE THE CARD'S DETAIL ONLY — NO HEAD, NO META LINES. Your output STARTS at "### Full detail" and contains nothing above it: no "## …" heading, and none of "- ord:", "- group:", "- source:", "- net:", "- one:", "- label:", "- open:". Every one of those is composed by the driver from the record above, where they are already typed — a line you write there is discarded, not read.`,
3944
- `Emit NO "### The read" narrative — RETIRED (#243). It was a THIRD condensation of the same finding, beside this card's own one-liner and the typed net. The legal read and the enforcement read are already TYPED on the record (legal_position / practical_position) and render from there; the one-clause summary is the typed net. Your whole output is the \`full_detail\` entries — filing, portfolio, the risk assessment, enforcement — and the driver builds the section around them.`,
3944
+ `Emit NO "### The read" narrative — RETIRED. It was a THIRD condensation of the same finding, beside this card's own one-liner and the typed net. The legal read and the enforcement read are already TYPED on the record (legal_position / practical_position) and render from there; the one-clause summary is the typed net. Your whole output is the \`full_detail\` entries — filing, portfolio, the risk assessment, enforcement — and the driver builds the section around them.`,
3945
3945
  // The SOURCE bullet is gone from the ask entirely. It was the transcription class in its purest
3946
3946
  // form: a seat composing a URL from a host table it is not even given (providers/<name>.md is NOT
3947
3947
  // in this stage's skillReads) plus a path on the record. The driver reads `source.resolved_link`
@@ -3963,7 +3963,7 @@ export const STAGES = {
3963
3963
  // passes (the lint-repair redo was a deterministic ~2-generation tax on 83% of runs).
3964
3964
  `LINT CONTRACTS (the delivery lint fails a card that breaks these — state them right the first time): state an owner's registration COUNT at most once, and only as the number of registrations in the record above (unsure ⇒ name the owner without a count). NEVER pair a WIPO/Madrid/international registration with "worldwide"/"global" reach language — name the designated countries or omit the reach claim.`,
3965
3965
  // P6 — the house prose contract. This card is the surface where "each fact once, at its rank"
3966
- // actually bites: the delivered report told TIKI PUNCH in six sections, and 43% of it was
3966
+ // actually bites: the delivered report told WAVO PUNCH in six sections, and 43% of it was
3967
3967
  // on-field conflict prose. delivery-contract.md (this stage's skill read) carries the same rules.
3968
3968
  PROSE_VOICE,
3969
3969
  `THIS CARD IS THE FACT'S RANK. Everything you write here belongs to THIS finding and is written ONCE, here: do not restate the overall verdict, do not re-narrate another finding, and do not repeat what the summary above already said about this one. If the reader needs a neighbouring finding, name it by ordinal and stop.`,
@@ -4143,6 +4143,12 @@ const directiveLine = (d) => `- [${d.layer}${d.severity === "dominant-element" ?
4143
4143
  export const supplementalLaneResumeLine = (P, axis) =>
4144
4144
  `Any ADDITIONAL register sub-query this needs: PROPOSE it via register_propose_supplemental ({"axis": "${axis}", "output_path": "${P.registerBand(axis)}", "proposals": […]}) — the tool executes it and merges the band itself. You never run register coverage via register_enumerate and never author band blocks. ${SUPPLEMENTAL_LANE_STEERING}`;
4145
4145
 
4146
+ // A follow-up to a unit whose axis has already run. Without `qids`, register_execute_plan runs every entry on
4147
+ // the axis again and re-fetches every record the axis holds; on a register that bills per request the run
4148
+ // pays for all of it twice. Measured on production follow-ups that closed deferred rows: 39 of the 45
4149
+ // questions they sent had been asked before in the same run.
4150
+ export const PLAN_ENTRY_RERUN_RULE = `This axis's plan has already run. Do not call register_execute_plan without "qids": that runs every entry on the axis again. To ask one plan entry again, name only that entry in "qids".`;
4151
+
4146
4152
  // Step-2.6 skeptic escalated this axis → resume its session to defend or adjust.
4147
4153
  export function buildEscalationFollowup({ paths: P, axis, flags, supplementalLane = false }) {
4148
4154
  return lines(
@@ -4150,6 +4156,7 @@ export function buildEscalationFollowup({ paths: P, axis, flags, supplementalLan
4150
4156
  supplementalLane ? supplementalLaneResumeLine(P, axis) : "",
4151
4157
  `Do NOT restart the search from scratch. The Step-2.6 skeptic raised the concerns below. For EACH concern relevant to THIS axis: either (a) defend your existing finding using evidence already in your context, or (b) run ONLY the narrow additional sub-query the concern requires, then revise.`,
4152
4158
  `Every finding the concerns do not touch stays exactly as it is.`,
4159
+ PLAN_ENTRY_RERUN_RULE,
4153
4160
  ``,
4154
4161
  `Skeptic concerns:`,
4155
4162
  flags,
@@ -4167,6 +4174,7 @@ export function buildEnvelopeCloseFollowup({ paths: P, axis, rows, supplementalL
4167
4174
  supplementalLane ? supplementalLaneResumeLine(P, axis) : "",
4168
4175
  `The Coverage ledger records DEFERRED (planned but never run) work owned by this axis — the deadline envelope permits closing it NOW, before the analysis is written:`,
4169
4176
  rows || `(deferred row(s) for ${axis} — see the Coverage ledger)`,
4177
+ PLAN_ENTRY_RERUN_RULE,
4170
4178
  `Run ONLY those deferred sub-queries and update each closed row to confirmed-clean or coverage-limited with the honest reason. Nothing else in the digest changes.`,
4171
4179
  UNIT_NOTE_REPAIR_TAIL,
4172
4180
  );