Say "rewritten" instead of highlighting the whole plan - #192
Merged
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58811eb364
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The "changed since you last looked" highlights were making plan pages look messy in the two most common cases. Open a plan while an agent is still drafting it — or come back after a rewrite — and every section differs from your baseline, so every section lit up. The diff was right and the page said nothing. Plans::ChangedSections now reports that case as a rewrite instead of a list of keys: most of the document is new, measured against both the section count and the volume of text (either measure alone misreads a common shape — a swarm of one-line sections changing isn't a rewrite, and neither is one long section getting edited), and only for documents of four or more sections, since banding a short plan in full is a few inches of tint rather than noise. The page drops the highlights and carries one line above the content: "Rewritten since you last looked", linking to the history. Second, unrelated fix in the same feature: the controller tinted each top-level block separately, so one changed section rendered as a stack of rounded boxes with untinted gaps and a broken-up left bar. Adjacent changed blocks are now grouped into runs, and the inter-block margins inside a run become padding within the tint, so a run reads as one continuous band — rounded at the ends only, with mid-run headings keeping their breathing room inside the band instead of punching a gap through it. Verified against the real page in both states, before and after. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Codex caught a real false positive: a renamed heading files an untouched body under a new slug key, which the key-level diff can't tell from newly written text. Rename three headings in a four-section plan and both rewrite thresholds pass, so the reader is told the plan was rewritten when only three heading lines moved. Bodies that already existed somewhere in the old document are now carried over rather than written, and don't count toward "most of this is new". Matching is by exact body, one old section per new one, so repeated boilerplate can't discount two sections at once. Renamed sections still highlight — the heading did change — they just no longer argue for the notice. Also: /plans/:id redirects to the canonical browsable URL since #191, so the two request specs added here follow the rebased ones onto plan_page_path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
HamptonMakes
force-pushed
the
hampton/what-changed-highlights-plan-692aac
branch
from
August 23, 2026 14:36
58811eb to
368a6fe
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The "changed since you last looked" highlights were making plan pages look messy, and there were two separate reasons.
Saturation
The diff was correct; the message was worthless. Open a plan while an agent is still drafting it (the presence channel records the visit), or come back after a rewrite, and every section differs from your baseline — so every section lit up. "Everything changed" is what a reader already assumes on a v5 plan they half-saw once.
Plans::ChangedSectionsnow returns a small result (keys+rewritten?) instead of a bare array, and reports a rewrite when most of the document is new. "Most" is measured two ways — more than half the sections and more than half the text — because either measure alone misreads a common shape: a swarm of one-line sections changing isn't a rewrite, and neither is one long section of ten getting edited. It only applies to documents of four or more sections; below that, banding the whole thing is a few inches of tint, which is legible and more useful than a sentence about it.In that case the page drops the highlights entirely and carries one line above the content: "Rewritten since you last looked. See what changed", linking to the plan's history.
The two thresholds are
REWRITE_RATIOandREWRITE_MIN_SECTIONSin the service, easy to move once we've seen this on real plans.The barcode
Independent bug in the same feature. The Stimulus controller added
.section-changedto each top-level block, and the CSS gave each one its own tinted, rounded, left-barred box — so a single changed section of six paragraphs rendered as six stripes with untinted gutters between them and a broken-up accent bar. It looked messy even when only one section had changed.Adjacent changed blocks are now grouped into runs (
--start/--endmarkers), and within a run the inter-block margins become padding inside the tint. A run reads as one continuous band with one unbroken bar, rounded at the ends only. Mid-run headings keep their breathing room as padding inside the band rather than a gap through it. The band CSS is scoped under.markdown-renderedso it outranks the per-element markdown margins.Wrapping the run in a container div would have been simpler, but
reference_preview_controller#renderSectionwalksheading.nextElementSiblingto build section previews, so the flat structure has to stay.Screenshots
Real page, dark mode, 2×. Each pair is the same plan and the same content, with and without this change.
The rewrite case — you glanced at the plan while it was still a stub, then the agent wrote the whole thing.
Every one of the nine sections bands, and the page says nothing. After: one line above the title — "Rewritten since you last looked. See what changed" — and a clean document.
Two genuinely changed sections — "How it works" and "Themes", adjacent.
Before: four separate boxes with untinted gutters and four disconnected bar segments for one continuous stretch of changed text. After: one band, one bar, rounded at the ends only, with the mid-run "Themes" heading keeping its breathing room inside the tint.
Reviewer notes
ChangedSections.callchanged return type (array →Result). OnlyPlansController#showandshow.html.erbconsume it;NONEis the empty result for the "first visit / nothing new" paths.last_seen_at. Worth knowing while testing —PlanPresenceChannel#pingalso advances it while a plan page sits open, so a tab left on the plan will eat the highlight before you can reload.spec/services/plans/changed_sections_spec.rb, and the data attributes inspec/requests/changed_sections_highlight_spec.rb.voice_commenting_spec.rbfailedtest-postgreshere, the third flake from that file across two PRs. The cause is a race, not load — the mic control is server-rendered but inert until its Stimulus controller connects, so an example that pressed the key first went nowhere. Neither the button nor its tooltip is a usable readiness signal, sovoice_controller#connectnow setsdata-voice-readyand everyvisitin that spec waits for it. That's a one-line app change made for testability, in a PR about highlights — flagging it rather than folding it in quietly. 20/20 locally, three runs, andtest-postgresis green.🤖 Generated with Claude Code