main · last commit
18 hours ago ·
8tmadfpi
spec-by6.3.5 Port review UI to a line-numbered unified prose diff
Past Stand
bd reopen spec-by6.3.5
| Created by | Eugene Blikh |
| Owner | bigbes@gmail.com |
| Created | 2026-07-25T11:40:01Z |
| Updated | 2026-08-05T01:11:47Z |
| Closed | 2026-08-05T01:11:47Z |
Replace the block-card review renderer with a real unified diff: line-numbered gutter, drag-select a line range, comment composer inline. Owner reviewed the card version against a live proposal and rejected it — labels ('ADDED PARAGRAPH') outweighed content on every row, every block carried identical chrome, and on a new file the whole page is green so the cards add noise and no signal. Split view was considered and dropped: prose lines are long and unified reads better for reflowed text. Approved prototype: https://claude.ai/code/artifact/a45e45cb-16b5-42ec-8108-84767ef9f465
SELECTION IS BY LINE, ANCHORING IS BY BLOCK. Lines are what the cursor lands on; block hashes are what survive a reflow. The web layer maps a selected line range to its enclosing prosediff block and stores the existing core.CommentAnchor unchanged. service/, db/ and core/ do not move. The composer states what it will anchor to, so the indirection is visible rather than magic.
THE BLOCKING PROBLEM — word marks cannot be placed on a line for free.
prosediff.Span is {Op, Text, Space} with no source offsets, and Tokenize
deliberately drops whitespace ('\n' and ' ' both collapse to Space=true) —
which is exactly what makes a rewrap invisible to the differ. So for a
ChangeModify block there is no stored answer to 'which line did this word
change on'.
Recoverable, not free: the span script consumes the old token sequence in order
(Equal+Delete) and the new one (Equal+Insert). Re-tokenize each source line of
Block.Lines, walk the script, and split a span where it crosses a line
boundary. Needs a mapper of roughly 100 lines plus tests. Equal/Insert/Delete
blocks need none of this — their lines map 1:1 and carry exact numbers.
FALLBACK IF THE MAPPER IS NOT WANTED: render a modified block as a paired
old/new region labelled by line RANGE rather than per line, keeping the word
marks. Honest and much smaller, but does not match the approved prototype.
GUTTER DETAILS SETTLED IN REVIEW: one shared rail ground for both number
tracks with a single hairline against the content (a border per cell drew a
cage); one --row-lh shared by gutter and prose so numerals sit on the text
baseline rather than floating; 34px tracks; the add/delete tint starts at the
sign column so the gutter never looks part of the change.
HEADING PATH: no per-hunk breadcrumb. It restated headings visible a few rows
above, always so on a new file. Replaced by one sticky section readout that
appears only once its heading has scrolled past. The path stays in the composer
and in each thread's anchor note, where the heading is usually off screen.
A reviewer drags across line numbers, comments, and the thread stores an anchor identical to the one the block-card UI would have stored. Word-level marks still appear inside a modified paragraph. Unchanged lines render as context and collapse. An outdated comment still appears and is never attached to a neighbouring block.
spec-by6.3
— Phase 5b: inline comments on proposals
parent-child
closed
Nothing depends on this issue.
spec-by6.3
— Phase 5b: inline comments on proposals
parent-child
closed
spec-by6
— Phase 5: comments, webhooks, mutations, vector search
parent-child
open
spec-3vz
— Phase 4: review plane — approve/reject in a browser
blocks
closed
spec-ejq
— spec.sr.ht — reviewable document storage for humans and agents
parent-child
open
spec-zqb
— Phase 3: write plane — agents propose
blocks
closed
| id | spec-by6.3.5 |
| content_hash | ad5850f9dfeb790caa01e085716a402bd3da5888d2d63e1bb407db8b8a422d79 |
| title | Port review UI to a line-numbered unified prose diff |
| description | Replace the block-card review renderer with a real unified diff: line-numbered gutter, drag-select a line range, comment composer inline. Owner reviewed the card version against a live proposal and rejected it — labels ('ADDED PARAGRAPH') outweighed content on every row, every block carried identical chrome, and on a new file the whole page is green so the cards add noise and no signal. Split view was considered and dropped: prose lines are long and unified reads better for reflowed text. Approved prototype: https://claude.ai/code/artifact/a45e45cb-16b5-42ec-8108-84767ef9f465 |
| design | SELECTION IS BY LINE, ANCHORING IS BY BLOCK. Lines are what the cursor lands on; block hashes are what survive a reflow. The web layer maps a selected line range to its enclosing prosediff block and stores the existing core.CommentAnchor unchanged. service/, db/ and core/ do not move. The composer states what it will anchor to, so the indirection is visible rather than magic. THE BLOCKING PROBLEM — word marks cannot be placed on a line for free. prosediff.Span is {Op, Text, Space} with no source offsets, and Tokenize deliberately drops whitespace ('\n' and ' ' both collapse to Space=true) — which is exactly what makes a rewrap invisible to the differ. So for a ChangeModify block there is no stored answer to 'which line did this word change on'. Recoverable, not free: the span script consumes the old token sequence in order (Equal+Delete) and the new one (Equal+Insert). Re-tokenize each source line of Block.Lines, walk the script, and split a span where it crosses a line boundary. Needs a mapper of roughly 100 lines plus tests. Equal/Insert/Delete blocks need none of this — their lines map 1:1 and carry exact numbers. FALLBACK IF THE MAPPER IS NOT WANTED: render a modified block as a paired old/new region labelled by line RANGE rather than per line, keeping the word marks. Honest and much smaller, but does not match the approved prototype. GUTTER DETAILS SETTLED IN REVIEW: one shared rail ground for both number tracks with a single hairline against the content (a border per cell drew a cage); one --row-lh shared by gutter and prose so numerals sit on the text baseline rather than floating; 34px tracks; the add/delete tint starts at the sign column so the gutter never looks part of the change. HEADING PATH: no per-hunk breadcrumb. It restated headings visible a few rows above, always so on a new file. Replaced by one sticky section readout that appears only once its heading has scrolled past. The path stays in the composer and in each thread's anchor note, where the heading is usually off screen. |
| acceptance_criteria | A reviewer drags across line numbers, comments, and the thread stores an anchor identical to the one the block-card UI would have stored. Word-level marks still appear inside a modified paragraph. Unchanged lines render as context and collapse. An outdated comment still appears and is never attached to a neighbouring block. |
| notes | |
| status | closed |
| priority | 2 |
| issue_type | feature |
| assignee | NULL |
| estimated_minutes | NULL |
| created_at | 2026-07-25T11:40:01Z |
| created_by | Eugene Blikh |
| owner | bigbes@gmail.com |
| updated_at | 2026-08-05T01:11:47Z |
| closed_at | 2026-08-05T01:11:47Z |
| closed_by_session | |
| external_ref | NULL |
| spec_id | |
| compaction_level | 0 |
| compacted_at | NULL |
| compacted_at_commit | NULL |
| original_size | NULL |
| sender | |
| ephemeral | 0 |
| wisp_type | |
| pinned | 0 |
| is_template | 0 |
| mol_type | |
| work_type | |
| source_system | |
| metadata | �{} |
| source_repo | |
| close_reason | Closed |
| event_kind | |
| actor | |
| target | |
| payload | |
| await_type | |
| await_id | |
| timeout_ns | 0 |
| waiters | |
| hook_bead | |
| role_bead | |
| agent_state | |
| last_activity | NULL |
| role_type | |
| rig | |
| due_at | NULL |
| defer_until | NULL |
| no_history | 0 |
| started_at | NULL |
| is_blocked | 0 |
| id | ce808c5f-ccd6-50c3-ba24-422984df8fa6 |
| issue_id | spec-by6.3.5 |
| type | parent-child |
| created_at | 2026-07-25T14:40:01Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | spec-by6.3 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 019f9913-3831-7bd7-8876-d352b2460c79 |
| issue_id | spec-by6.3.5 |
| event_type | created |
| actor | Eugene Blikh |
| old_value | |
| new_value | |
| comment | NULL |
| created_at | 2026-07-25T14:40:01Z |
| id | 019fcf79-fe91-74f9-aa65-e68d2fe89309 |
| issue_id | spec-by6.3.5 |
| event_type | closed |
| actor | Eugene Blikh |
| old_value | |
| new_value | Closed |
| comment | NULL |
| created_at | 2026-08-05T04:11:46Z |
No comments.
Close reason