Fix: Introduce RenderPhase and isolate first-frame measurement#59
Merged
Conversation
- Pin first-frame measurement leaks: onAppear fires and .task mounts for a view that exists only in the measure pass - Pin duplicate key-handler registration when the header-correction pass re-renders the frame - Pin onChange(initial:) double-firing caused by per-frame instead of per-pass index claims - Add KeyEventDispatcher.handlerCount for tests and diagnostics - Mark desired behavior withKnownIssue until #55/#56/#57 land
- Introduce RenderPhase (.measure/.render) with documented invariants and the effect classification rule - Replace RenderContext.isMeasuring with RenderContext.phase across all 15 sites - No deprecation bridge: project is pre-release and rebuilds APIs cleanly - Update review policy overrides for the removed and added symbols - Regenerate the API compatibility manifest with the tool
- Run the first-frame header measurement with phase == .measure so lifecycle, task, and focus guards apply - Document why AppHeaderModifier stays unguarded until the pass collectors land (#56) - Add a render-phases section to the RenderLoop architecture comment - Promote the measure-pass characterization tests to hard expectations
This was referenced Jul 21, 2026
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.
Closes #55 (sub-issue of #13). Design spec:
.claude/openspec/render-phase-effect-commit.md.Summary
withKnownIssuemarkers for the parts that [P0-08b] Collect per-pass effects in scratch collectors #56/[P0-08c] Commit lifetime effects from the final tree #57 will fix)RenderContext.isMeasuringBool with an explicit, documentedRenderPhaseenum (.measure/.render) across all 15 sites — no deprecation bridge (pre-release).measure, so lifecycle, task, and focus guards stay inert for trees that never become visibleisMeasuring, addedRenderPhase+RenderContext.phaseasimplementationLeak/[P2-30] Reduce the public implementation surface and namespace TUI-only APIs #35 overrides)Test plan
./scripts/test-linux.shgreen on macOS (native, Swift 6.0.3) and Linux (Docker) — 1305 testsscripts/verify-compatibility-manifest.shbyte-identical + validRenderPhaseCharacterizationTests— measure-pass guarantees are hard expectations; correction-pass handler duplication ([P0-08b] Collect per-pass effects in scratch collectors #56) and onChange double-fire ([P0-08c] Commit lifetime effects from the final tree #57) remain known-issue markers