Skip to content

feat: Latch Code-Surface Folder at First Open - #586

Merged
sahil-noon merged 4 commits into
mainfrom
260813-if5d-latch-code-surface-folder
Aug 13, 2026
Merged

feat: Latch Code-Surface Folder at First Open#586
sahil-noon merged 4 commits into
mainfrom
260813-if5d-latch-code-surface-folder

Conversation

@sahil-noon

Copy link
Copy Markdown
Collaborator

Meta

Change ID Type Confidence Plan Review
if5d feat 4.2/5.0 7/7 tasks, 17/17 acceptance ✓ ✓ 1 cycle
Impact +/− Net
raw +1245 / −43 +1202
true +792 / −22 +770
└ impl +540 / −22 +518
└ tests +252 / −0 +252

excludes fab/, docs/ · generated by fab-kit v2.20.1

Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr

Summary

The code lens re-derives its folder (gitRoot) from the active pane's cwd on every SSE tick, so switching panes in the terminal — or having two panes in different repos — makes the embedded editor vanish or lose in-flight state (open tabs, dirty buffers, undo stack). This change latches the folder once at the first-ever open of the code surface (per-window, localStorage), so only the editor's own File > Open Folder navigation moves it afterward; the terminal never does.

Changes

  • Per-window code-folder latch (new lib module code-folder-latch.ts)
  • Seed rule: derivation runs exactly once, at first-ever open
  • Follow rule: only the editor's own navigation moves the latch
  • Availability widens: hasCode = latch exists OR gitRoot derivable
  • Code tile render guard + tileMeta follow the latch
  • Stale latch accepted — no liveness machinery
  • Spec amendment (docs/specs/right-panel.md)
  • Tests (Vitest unit + Playwright e2e with .spec.md companion)

The code lens re-derives its folder from the active pane's cwd on every SSE tick, so switching panes in the terminal makes the embedded editor vanish or lose in-flight state. Latch the folder once at first open (localStorage, per-window) so only the editor's own File > Open Folder navigation moves it afterward.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes the embedded code surface stop tracking the terminal’s active pane by introducing a per-window “latched” code folder. The latch is seeded once (first time the code surface renders) and afterward only follows code-server’s own navigation (File > Open Folder), stabilizing the editor’s workspace and in-flight state across pane switches.

Changes:

  • Add a per-window localStorage-backed code-folder latch (read/write helpers + unit tests).
  • Plumb a latched “effective window” through availability/layout/rendering, and update CodeSurface to keep iframe src fixed per mount generation while reporting editor-driven folder navigations on load.
  • Add Playwright e2e coverage for pane-switch persistence and update specs/memory docs to reflect the latch semantics.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
fab/changes/260813-if5d-latch-code-surface-folder/plan.md Generated implementation plan and acceptance criteria for the latch feature.
fab/changes/260813-if5d-latch-code-surface-folder/intake.md Intake rationale, non-goals, and detailed behavior/spec requirements.
fab/changes/260813-if5d-latch-code-surface-folder/.status.yaml Pipeline/status metadata for the change.
fab/changes/260813-if5d-latch-code-surface-folder/.history.jsonl Pipeline history log for the change.
docs/specs/window-views.md Updates view registry “code” availability semantics to latch-or-derivable.
docs/specs/right-panel.md Updates right-panel spec to document latch seeding + follow-the-editor rules.
docs/memory/run-kit/ui-patterns.md Documents the latch behavior as a UI pattern and how it affects code-surface rendering.
docs/memory/run-kit/index.md Updates memory index description to include the latch concept.
app/frontend/tests/e2e/code-folder-latch.spec.ts New e2e test validating code tile persistence when active pane leaves repo and across reload.
app/frontend/tests/e2e/code-folder-latch.spec.md Companion spec document describing e2e scope/limits and scenarios.
app/frontend/src/lib/code-folder-latch.ts New latch storage module (keying + try/catch localStorage wrappers).
app/frontend/src/lib/code-folder-latch.test.ts Unit tests for latch keying, round-trips, empty handling, and storage failures.
app/frontend/src/components/surface-layout.tsx Threads onCodeFolderNavigated through to CodeSurface and clarifies code tile meta semantics.
app/frontend/src/components/surface-layout.test.tsx Tests that code tile header/body reflect the (latched) folder and passthrough works.
app/frontend/src/components/code-surface.tsx Holds iframe src stable per mount generation and reports editor-driven folder changes on load.
app/frontend/src/components/code-surface.test.tsx Tests src fixity, reachability remount behavior, and follow-the-editor reporting.
app/frontend/src/app.tsx Implements latch read/seed/follow wiring and substitutes a latched “effective window” across consumers.
app/frontend/src/app.test.tsx Adds unit coverage for the withLatchedCodeFolder substitution seam.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread app/frontend/src/app.tsx
Comment on lines +688 to +697
const [latchEpoch, setLatchEpoch] = useState(0);
const latchedCodeFolder = useMemo(
() => (windowParam ? readLatchedCodeFolder(server, windowParam) : undefined),
[server, windowParam, latchEpoch],
);
const latchCodeFolder = useCallback((folder: string) => {
if (!windowParam || folder.length === 0) return;
writeLatchedCodeFolder(server, windowParam, folder);
setLatchEpoch((n) => n + 1);
}, [server, windowParam]);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipped — the cited rule does not exist. Plan R1 specifies the opposite explicitly: "GIVEN localStorage is unavailable (jsdom without storage, private mode, quota) / WHEN read or write is called / THEN read returns undefined and write is a silent no-op — no throw reaches the caller." Acceptance criterion A-013's phrase "degrade to per-session behavior" is defined by its own parenthetical — "(read undefined, write noop)" — meaning unpersisted, not in-memory-latched. docs/memory/run-kit/ui-patterns.md states it directly: "Absent, empty, and storage-unavailable all read alike as 'not latched'", and the intake scopes the module to a "storage-unavailable noop".

Falling back to the live derived gitRoot when storage is unavailable is the designed degradation — the window behaves exactly as it did before the latch existed. Adding an in-memory fallback would introduce a second source of truth, contradicting the app.tsx invariant that "localStorage stays the source of truth and is read AT RENDER".

sahil87 and others added 2 commits August 13, 2026 16:31
pnpm 9 (pinned in ci.yml/release.yml) rejects a settings-only
pnpm-workspace.yaml with "packages field missing or empty"; pnpm 10+
accepts it. packages: ['.'] satisfies pnpm 9 without changing install
layout — the lockfile is byte-identical under both versions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sahil-noon
sahil-noon marked this pull request as ready for review August 13, 2026 17:29
@sahil-noon
sahil-noon merged commit e6d9d39 into main Aug 13, 2026
6 checks passed
@sahil-noon
sahil-noon deleted the 260813-if5d-latch-code-surface-folder branch August 13, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants