Skip to content

Reform pass 2: GPUI main pin, restored UI and review fixes - #505

Merged
sandersonstabo merged 11 commits into
masterfrom
reform-2
Oct 15, 2026
Merged

sandersonstabo merged 11 commits into
masterfrom
reform-2

Conversation

@sandersonstabo

@sandersonstabo sandersonstabo commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Second radical reform pass, integrated with GPUI main f82ca3fe and the restored Editor UI, followed by fixes for every finding from the codebase review.

What's in it

  • Integration: bounded content storage, native list virtualisation, shared components; GPUI main pin (native D3D11 on Windows, vendored optimized syntect/onig); the original Editor appearance restored.
  • Forge: unchecked PUT /settings/{key} closed, correct 404/409/500 mapping, policy moved from the store to forge-runs, store split into modules, migration steps instead of magic version hooks, kind_type/parent_id as indexed columns (migration 16), cached project icons and device keys, accept-loop backoff, logs with route and cause.
  • Engines/API: one approval shape on the gated item for all engines (migration 17), Forge-resolved agent-message targets, Codex frames parsed once into typed structs, one settle step instead of per-decoder memory accounting, transcript snapshot tests instead of private-state tests, artisan-api back to wire types (new forge-content, artisan-mentions), ACP sign-in by error code.
  • Editor: conversation and sidebar rows are cached views again; body preparation owned by Conversation (Bodies) with per-row splices; one text row kind; HostData split into owners; one RangeWindow with task cancellation instead of generation counters; editor-core no longer depends on editor-ui (editor-sources); theme as a GPUI global; Settings/Marketplace on shared page components; picker on shared popover/tooltip/hover primitives; theme tokens for radii and text sizes.
  • Fixes: lines stuck on "Loading content…", transcript losing its place on placeholder splits, paging flapping; Claude compaction progress no longer creates one item per frame (migration 18 removes stored repeats), and a compaction stays inside its run's work section.
  • Tool rows: plain-sentence tool rows, markdown previews per activity, received agent/session messages; subagent rows read "Agent ".

Verification

  • cargo test -p <crate> for all 21 crates: 688 passed, 0 failed (forge-store and artisan-api with --all-features).
  • cargo clippy --all-targets --no-deps: 0 errors in every crate.
  • Not done: native Windows/macOS runtime or screenshot qualification of this combination.

PROTOCOL_VERSION is 5: Editor and Forge must be updated together. Migrations 16–18 run on first start.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Second reform pass, pinned to GPUI main (native D3D11 on Windows, vendored optimized syntect/onig), with the original Editor appearance restored and fixes applied for every review finding. Protocol version is now 5, so Editor and Forge must update together.

Forge and engines

  • Policy moves from the store to forge-runs; kind_type/parent_id become indexed columns (migration 16), and approvals live on the tool/plan item they gate (AwaitingUser) for every engine — ItemKind::Approval is gone (migration 17).
  • Large authored text and collection records become immutable content-addressed references; artisan-markdown-index stores parsed Markdown leaves so prose can be replayed without owning the source.
  • Codex frames parse once into typed structs, agent messages carry a Forge-resolved target, and Item::native_id leaves the wire type; artisan-api is back to wire types.
  • Offline ae forge normalize repairs agent-message 64 KiB ranges; mention grammar ($skill/@connector) lives in the shared artisan-mentions crate.
  • Audio playback is a maintained decoder feeding a bounded PCM queue; seeks never retain the full track.

Editor

  • Conversation rows are cached views again with one text row kind and per-row splices; bodies are prepared by one owner, fixes to "Loading content…", paging flapping includes a follow check, and compaction lines stay within the run.
  • Tool-call rows read as plain sentences with markdown previews (highlighted files, diffs, command output); subagent rows read "Agent ".
  • editor-core no longer depends on editor-ui; theme becomes a GPUI global; composer picker splits into modules with cached views and shared popover/tooltip primitives.

All 21 crates pass cargo test (688 tests) and clippy with no errors; native Windows/macOS runtime and screenshot qualification are not yet done.

Written for commit 56b2c00. Summary will update on new commits.

View guided diff Turn on auto-fix

sandersonstabo and others added 9 commits October 15, 2026 05:36
Second radical reform pass (bounded content storage, collection and
source-index stores, native list virtualisation, shared components),
integrated with GPUI main f82ca3fe (native D3D11 on Windows, vendored
optimized syntect/onig highlighting) and the October 15 restoration of
the original Editor appearance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 404 messages no longer say "not found not found"; answer maps only
  refusals to 409, missing items to 404 and the rest to 500.
- PUT /settings/{key} no longer writes unchecked keys; Forge-owned
  settings go through their validated routes.
- Title, default-config and /ultracode policy move from the store to
  forge-runs; one attachment check, one draft-clearing helper.
- Item writes read the previous item once and serialize once.
- Project icons are cached by path, mtime and length; device keys are
  held in memory and reload when another process changes the database.
- Migrations are step lists (SQL or a named Rust function) instead of
  magic version hooks; migration 16 promotes kind_type and parent_id
  to indexed columns. Content triggers are defined once.
- Blob GC keeps only the lock it needs, SSE drops the 30 s auth poll,
  and the Windows editor retirement checks identity once.
- Accept loop backs off on errors; internal errors log method, path
  and cause. Dead pending/pairing helpers removed.
- forge-store/src/lib.rs is split into threads, items, sources,
  settings, pairing and blobs modules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eces

Engines and API
- Approvals live on the Tool/Plan item they gate (AwaitingUser) for every
  engine; ItemKind::Approval is gone. Migration 17 moves stored approval
  rows onto their targets. PROTOCOL_VERSION 5.
- AgentMessage carries a Forge-resolved target ItemId instead of an
  English recipient label; the Editor no longer joins on Claude agentIds.
- Codex frames are parsed once into typed structs; unknown fields and
  item types never fail a run.
- Decoder memory accounting is one settle step around feed instead of
  15-21 call sites per decoder; the 32 MiB retention budget is dropped.
- Private-state decoder tests are replaced by transcript snapshots;
  acp/decode.rs is split into modules.
- artisan-api is back to wire types: content compaction moves to the new
  forge-content crate, mentions to artisan-mentions, resident-size
  accounting to editor-core; Item.native_id leaves the wire type.
- ACP sign-in is detected by error code; adapter logs carry thread, run
  and engine ids.

UI
- ArtisanTheme is a GPUI global; the unreachable light palette is removed
  and WorkspaceColors merges into ColorTokens.
- Settings and Marketplace use editor_ui::page; the composer picker is
  split into modules on shared popover, tooltip and hover primitives.
- One hover-fill entry point; keyboard highlight in mentions uses the
  highlight fill. Radii and text sizes use theme tokens.
- Visible sidebar rows are cached entities again.
- One measured-bounds helper replaces per-site Rc<RefCell<Bounds>>.
- Markdown pool limits live in one budget module; dead paths removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Conversation rows are cached views again, uncached only while a row
  animates or just changed; image updates and source pruning leave the
  per-row render path.
- Preparation and paint feedback re-expand rows instead of refolding;
  reveal draws rows behind the frontier at zero height instead of
  deciding which rows exist.
- Shared caches use typed (ItemId, Slot) keys; five redundant row kinds
  are folded away.
- Test-only hooks leave Conversation; dropping the page task cancels it.
  tests.rs is split by topic.
- HostData keeps Forge state; images, repositories and read acks are
  their own owners. live and live_epochs are one map.
- One generic RangeWindow replaces the content and collection windows;
  generation fences are replaced by task ownership.
- editor-core no longer depends on editor-ui: image decoding is
  injected, and ContentText and CollectionBrowser move to the new
  editor-sources crate.
- Keyboard movement in the composer's axis menu uses the highlight
  fill; the hover pill stays with the pointer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…erer

Collapsed ifs, type aliases for closure types, test modules after
items and similar mechanical fixes; behaviour unchanged.

Also carries the first part of the tool-call rows work from a parallel
session: AgentMessage gains a direction so messages received from agents
and other sessions can be shown, and forge-runs no longer treats
Claude's replay of an incoming message as delivery of a user steer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tool-call rows (from a parallel session)
- Rows read as sentences ("Ran cargo test", "Read src/main.rs:40-140",
  "Edited tool.rs +12 -3"); tense shows status, only failures add an
  ending. Messages received from agents and other sessions, handbacks,
  ListAgents, TaskStop, Monitor and Codex wait/sleep get real rows.
- Each activity opens on a markdown preview (preview.rs): highlighted
  files, diffs, commands with output, grouped grep results, web pages,
  pretty-printed tool input and results; code blocks stop at 400 lines.

Subagent rows read "Agent  <task>" like Command rows: no icon, generated
name or status text.

Conversation rework
- Tests observe painted rows (row:<selector> debug selectors), painted
  state markers, the clipboard, Forge unread state and the visible
  range instead of reading Conversation internals.
- Master's user-message spacing rules are restored in fold::gaps.
- Waiting leaf fetches are always woken when a fetch slot frees.
- editor-conversation and the markdown renderer are clippy-clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Body preparation moves out of render into Bodies, owned by
  Conversation; rows draw a prepared Body set through set-and-notify,
  and the shared RefCell bag is gone.
- splice_rows re-expands only the body that changed; one Row::Text kind
  and one draw path replace the prose, formatted and plain kinds.
- Fixes lines stuck on "Loading content..." (busy preparers now retry
  turned-away requests), the transcript losing its place when a
  placeholder row splits, and paging flapping at both window edges.
- Markdown parsing and shaping share one worker; visible shaping goes
  ahead of queued parsing.
- Claude repeats its compacting status as progress; the decoder now
  keeps one compaction item per compaction and marks failed ones, and
  migration 18 removes the stored repeats.
- A compaction during a run is a line of that run's work section
  ("Compacted the conversation - 966k -> 15k tokens") instead of a
  divider that split the run into two sections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
artisan-api's tls feature needs base64's std error impls when built on
its own, and the store tests name the AgentMessage direction field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…llation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cubic-dev-ai

cubic-dev-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown

This PR is large and would use a significant portion of your monthly review quota. Comment @cubic-dev-ai review this to confirm that you want cubic to review it.

The signed archives stay `nix build .#release`; apps and packages are
separate flake outputs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cubic-dev-ai

cubic-dev-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown

This PR is large and would use a significant portion of your monthly review quota. Comment @cubic-dev-ai review this to confirm that you want cubic to review it.

The sidebar's working dot and the inspector's running-agent dot used a
repeating with_animation, which re-rendered the whole workspace every frame
and held a CPU core at 100%. They now use gpui-ce's with_pulse, so frames
re-present the scene instead of rebuilding it. Pins gpui-ce at bbb193ad.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cubic-dev-ai

cubic-dev-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown

This PR is large and would use a significant portion of your monthly review quota. Comment @cubic-dev-ai review this to confirm that you want cubic to review it.

@sandersonstabo
sandersonstabo merged commit 7c26ddf into master Oct 15, 2026
2 of 8 checks passed
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.

1 participant