Preserve raw include diagnostic provenance and derive bands from the existing shaped editor. Retain deferred tooltip paragraphs through rendering. Include source, regression, failure and native-trial evidence; corrected native acceptance remains pending.
9.4 KiB
Annotation index and layout projection — independent static review
Reviewed uncompiled, unwired contribution by Codex-9e8r6t /root/publication_review, 2026-09-13. No edits to implementation, builds, GUI or network. Two insertion-anchor issues need a policy/correction and actual-layout tests before this foundation establishes the stated rendering contract. No admission underflow or text-mutation defect found.
Reviewed worktree: C:/ar-text-9e8r6t. Source references below use the unformatted reviewed file's line numbers.
Findings
1. Empty ranges at a removed wrap separator have no marker (source_annotations.rs:131–142). anchor accepts a containing glyph or whole-paragraph EOF only. Cosmic word wrapping can discard the separating blank glyph. For a real wrapped word word paragraph, an empty span at that discarded space then has no containing glyph in either run, is not EOF, and produces no band. This is not a malformed span or missing document: its insertion boundary is available from the neighboring visual runs. Pinned iced_graphics text/editor.rs:232–244 explicitly handles a cursor between wrapped runs at the preceding visual-line end; Cosmic shape.rs's trailing_blank branches omit the blank from layout. The contract promises small markers for empty ranges. Add a deterministic gap-boundary policy using actual paragraph/run layout, without source-text search, and ensure exactly one run owns the marker. A next-cluster preference alone does not handle a byte that belongs to neither cluster. Parent notified before report.
2. Interior-cluster empty anchors silently move to the cluster leading edge (:135–136). Admission permits every UTF-8 character boundary, including a boundary between graphemes shaped into one ligature. For a real multi-grapheme ffi/fi cluster, each interior byte currently maps to the same leading x as the cluster start. Nonempty range cluster expansion is explicitly authorized; that does not specify relocation of an empty insertion boundary. Cosmic edit/editor.rs:33–51 instead estimates an interior caret by grapheme fraction of the glyph advance and applies RTL direction at :69–86. Choose and document the diagnostic marker policy: derive an appropriate within-cluster boundary, or explicitly call a canonical cluster-edge marker an approximation. Do not claim exact logical insertion positioning while silently snapping it. Use actual shaped fixtures that assert they contain the relevant multi-grapheme cluster; a font without ligatures would be a nondiscriminating test. Combining marks inside one grapheme require a distinct, deliberate canonical policy rather than scalar-count interpolation.
These findings concern empty markers. Nonempty intervals correctly test half-open cluster intersection, retain logical diagnostic ordinals and merge only neighboring visual intervals instead of taking one bidi min/max rectangle. The policy for a zero-advance intersecting glyph is currently a one-logical-pixel band (:90); document/test that minimum width rather than describing it as literal glyph advance.
Admission and boundary reasoning
LineIter plus the trailing-empty insertion (:33–38) matches the actual Buffer::set_text ending-line rule (cosmic buffer.rs:676–709), including greedy CRLF/LFCR, standalone CR and empty text. At least one paragraph exists and its start is zero. Thus partition_point minus one at :50/:56 cannot underflow for an admitted span. For every iterated paragraph, its start is at or before last_byte, which is at or before span.end; the subtraction at :59 cannot underflow. Initial separator positions clamp to the preceding paragraph end, and an end exactly at the next paragraph start excludes that next paragraph. Reversed, out-of-bounds, foreign-path and interior-UTF8-byte spans are skipped independently, preserving valid neighbors.
The per-run exact source-slice comparison (:77) is useful defense but intentionally not publication authority: an old buffer and new source can share one unchanged paragraph. Caller admission must still bind the whole current path/source/publication; same-line equality must never upgrade stale diagnostics.
The final rectangle intersection prevents bands outside the supplied clip. The caller must supply inner editor bounds intersected with ancestor viewport in the same coordinate system; this function does not discover those bounds. The right-edge four-pixel insertion adjustment preserves its selected boundary within the resulting interval before clipping. Hover bounds are full line-height advance bands, not glyph ink. A band is entirely omitted when its underline is outside the vertical clip even if upper text remains visible (:117–119); test and describe this consequence for the partially visible bottom line rather than claiming all partly visible text remains hoverable.
Discriminating actual-layout tests to add
The four current tests exercise Index::new only; none calls bands or anchor. They are useful admission tests but provide no shaped-geometry evidence yet.
- Shape a paragraph with Word/WordOrGlyph at a width that actually omits a separating space. Inspect real runs to assert the byte gap exists; place an empty diagnostic in it. Expect one marker at the chosen visual boundary, including when the preceding run is scrolled out and when the following run is clipped. A marker duplicated on both runs or silently missing despite the boundary policy fails.
- Use a verified ligature cluster and a combining sequence. Empty spans at start, interior character/grapheme boundary and end must follow the declared policy; nonempty partial spans must expand to every visual piece of the intersected cluster. Include RTL direction and duplicate cluster glyphs/zero advances. Do not fabricate glyph metrics as the only test.
- Reuse the mixed-ending admission specimen in an actual graphics-backed Editor. Project EOF after a trailing empty paragraph, each separator-only range, a multiline range through an empty paragraph and a range ending at the next paragraph start. Assert logical ordinal and actual visual-run ownership, not just the number of bands.
- For a mixed RTL/LTR line with unrelated glyphs between logical pieces, derive the independent expected set of intersecting glyph cluster identities from the real buffer. Check their visible advance coverage and the absence of coverage over unrelated gaps. Add repeated identical source tokens to ensure matching is by byte range and line identity.
- With nonzero origin, real scroll, narrow/wide wrapping and ancestor clips, check every returned hover/underline rectangle lies inside the effective clip. Test fully hidden bands, partially clipped top/bottom lines, empty markers exactly at the right edge, and pointer negatives in ordinary blank space. An intentionally double-translated origin/scroll negative control should fail the geometry evaluator.
- Change one source paragraph while retaining another identical paragraph; bands alone may still exist for the identical line. The future wrapper's stale-publication test must suppress the entire old index. Separately pass an actually mismatched affected run and assert it has no bands.
Use the actual graphics buffer after highlighter application. No temporary selection mutation or duplicate editor is needed for production geometry; test-only independent renderer observation can establish expected origin/clip and state invariants.
Cost and scope
Index construction retains one Part per diagnostic/paragraph intersection, not one per diagnostic. Worst-case storage grows with that intersection count. Draw loops over every Part on a visible logical line and scans that run's glyphs for each; thousands of diagnostics in offscreen portions of one heavily wrapped paragraph still participate in visible-run work. It also sorts/merges matching intervals per part/run. Cosmic's visible-run iterator itself traverses hidden wraps above the vertical offset within a logical line. These are concrete complexity bounds, not measured latency findings. Measure long-line/high-diagnostic-density cases before claiming the index limits work to visible candidates; avoid a new indexing engine until those measurements justify it.
No severity filter defect: the current Severity enum contains only Error and Warning. Sorting severity, overlap presentation, modal/input admission and currentness remain wrapper/controller responsibilities and are not established by this unwired module.
Bindings
| Reviewed artifact | SHA-256 |
|---|---|
| crates/oa-desktop/src/source_annotations.rs (6566 bytes) | 0a669038144d045a68561abaf31de8aa557c08dc9011464c787ed4b0f4dc9b2a |
| crates/oa-desktop/src/source_annotations/tests.rs (2125 bytes) | 8beb64e71117033638c45a09841ee6b4c2114de027be6103a147666be1c79b91 |
| harness/text-diagnostic-rendering-contract-20260913.md (8160 bytes) | 20bde13059ec877d8683c74b847878f34ff891ca3988e3ce7f5005d5db37a5a5 |
| cosmic-text-0.15.0/src/line_ending.rs | 44e25c4d8ec372e7516efec234139aed3eb79fd0f8adbaa870072097eb686cd0 |
| cosmic-text-0.15.0/src/edit/editor.rs | 9d61a742fea99db9044fce28a253f790f6b48369c24ec9646a3209a6a69fa1cb |
| cosmic-text-0.15.0/src/shape.rs | 615110123ec7e3ab29d0dc17de8c717cab1c8ac3b02f4024fe82b54f16ddd191 |
Other pinned primary bindings are recorded in geometry-seam-critique.md: iced_graphics text/editor.rs b12c4e64…39567, cosmic buffer.rs c715f18a…647d8. Findings are static counterexamples/policy gaps, not reports of executed production failures or native acceptance.