PR: #654: feat(documents): anchored margins v1 — ink highlight, Mira notes, privileged marker [Story-2509] by @ankitmaheshwari-com
View PR →

Story 2509: Anchored margins v1

Manifest T5a · Wave W5 · RFD-DOC-006 Extraction Record. Covers ER-05, ER-10 and ER-26 (I-14). The two anchored margins — the machine's findings on the left, the conversation on the right — already ship from Story-2281 / Story-2294. T5a adds the three behaviours that make those margins act on the exact ink: click a marker to light the passage it rests on, turn a Mira answer into a pinned note, and mark privileged material wherever it is voiced.

ER-05 — findings are sparse and pinned to exact ink

The sparse markers are unchanged — one pill per signal kind, top-aligned to the section's rail. What is new: clicking a marker (or a finding's quote) lights the exact block the finding rests on, not the whole section box.

finding.anchor { pageNumber, blockIndex, tone }
  → blockBoxForAnchor(blocks, anchor)      // the block's stored bbox, as page %
  → <FindingInkHighlight box />            // mix-blend-multiply over the ink

Geometry by reference (D3): the box is unioned from the block's bounding box at render, never stored. A page-level anchor with no block resolves to null and no box is drawn — provenance-is-law, never a guessed rectangle. ink-highlight-presentation.test.ts pins the resolver, including the withhold cases.

ER-10 — Mira answers on the selected passage, saveable as a note

Counsel drags a passage and asks Mira; her answer lands in the right (conversation) gutter as a MiraPassageAnswer card, anchored to the same passage and carrying the AGENT tag. "Save as note" pins it — turning an ephemeral answer into a durable, byte-anchored note through the existing optimistic annotations create.

ER-26 / I-14 — privileged material is marked, everywhere it is voiced

A Mira answer or a machine finding that draws on privileged material carries the PrivilegedContentMarker: a crimson 🔒 that says Privileged · Not exportable. The team sees the truth and the hard rule — the content never leaves the surface. It is distinct from the register's document-level flag: this marks a specific answer or finding, not a whole document.

What counsel sees

Surface Behaviour
Left gutter marker Click → the gutter expands to the cards AND the first finding's exact block lights in the document. Clicking a card's quote moves the light.
Right gutter Mira answer Passage-scoped answer with a "Save as note" action; saved answers become pinned notes anchored to the same passage.
Privileged marker 🔒 Privileged · Not exportable, rendered on any finding or Mira answer whose material is privileged.

Storybook states

Cutover law

Per RFD-DOC-006 the new path is fixture-only until the W5 wave cutover; the serving Original lens stays authoritative. The ER-05 highlight is live-wired (it resolves from the same Anchor-view blocks the gutters already read). Two seams are fixture-first, gated on their upstream contract and stated here honestly:

Files changed

51 file(s), +3752 / -5 lines

Path Role + -
messages/en.jsonConfig+15-0
messages/hi.jsonConfig+15-0
openapi/app-api.jsonConfig+533-0
openapi/permission-map.jsonConfig+27-0
src/components/documents/viewer/document-original-lens.tsxComponent+21-0
src/components/documents/viewer/finding-ink-highlight.stories.tsxComponent+75-0
src/components/documents/viewer/finding-ink-highlight.tsxComponent+46-0
src/components/documents/viewer/ink-highlight-presentation.test.tsComponent+62-0
src/components/documents/viewer/ink-highlight-presentation.tsComponent+56-0
src/components/documents/viewer/mira-passage-answer.stories.tsxComponent+70-0
src/components/documents/viewer/mira-passage-answer.tsxComponent+112-0
src/components/documents/viewer/privileged-content-marker.stories.tsxComponent+25-0
src/components/documents/viewer/privileged-content-marker.tsxComponent+53-0
src/components/documents/viewer/section-finding-card.stories.tsxComponent+22-0
src/components/documents/viewer/section-finding-card.tsxComponent+38-4
src/components/documents/viewer/section-gutter-row.tsxComponent+5-0
src/components/documents/viewer/section-machine-gutter.stories.tsxComponent+6-0
src/components/documents/viewer/section-machine-gutter.tsxComponent+15-1
src/components/documents/viewer/sections-presentation.tsComponent+30-0
src/components/documents/viewer/use-section-labels.tsComponent+9-0
src/gen/client/appConfirmDocumentRelationship.tsGenerated contract+70-0
src/gen/client/appReleaseDocumentFamilyWave.tsGenerated contract+73-0
src/gen/client/appRevokeDocumentRelationship.tsGenerated contract+70-0
src/gen/client/index.tsGenerated contract+3-0
src/gen/hooks/index.tsGenerated contract+12-0
src/gen/hooks/useAppConfirmDocumentRelationship.tsGenerated contract+166-0
src/gen/hooks/useAppReleaseDocumentFamilyWave.tsGenerated contract+177-0
src/gen/hooks/useAppRevokeDocumentRelationship.tsGenerated contract+166-0
src/gen/index.tsGenerated contract+99-0
src/gen/schemas/authorityCited.jsonGenerated contract+74-0
src/gen/schemas/documentInsightBrief.jsonGenerated contract+370-0
src/gen/schemas/documentRelationshipView.jsonGenerated contract+71-0
src/gen/schemas/familyWaveReleaseView.jsonGenerated contract+24-0
src/gen/schemas/insightPin.jsonGenerated contract+74-0
src/gen/schemas/positionAdmission.jsonGenerated contract+74-0
src/gen/schemas/punchCard.jsonGenerated contract+148-0
src/gen/schemas/silence.jsonGenerated contract+74-0
src/gen/types/AppConfirmDocumentRelationship.tsGenerated contract+81-0
src/gen/types/AppReleaseDocumentFamilyWave.tsGenerated contract+86-0
src/gen/types/AppRevokeDocumentRelationship.tsGenerated contract+81-0
src/gen/types/DocumentRelationshipView.tsGenerated contract+64-0
src/gen/types/FamilyWaveReleaseView.tsGenerated contract+27-0
src/gen/types/InsightPin.tsGenerated contract+5-0
src/gen/types/index.tsGenerated contract+46-0
src/gen/zod/appConfirmDocumentRelationshipSchema.tsGenerated contract+97-0
src/gen/zod/appReleaseDocumentFamilyWaveSchema.tsGenerated contract+98-0
src/gen/zod/appRevokeDocumentRelationshipSchema.tsGenerated contract+97-0
src/gen/zod/documentRelationshipViewSchema.tsGenerated contract+25-0
src/gen/zod/familyWaveReleaseViewSchema.tsGenerated contract+15-0
src/gen/zod/index.tsGenerated contract+38-0
src/gen/zod/insightPinSchema.tsGenerated contract+12-0