Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,18 @@ _Avoid_: port forward (as a concept name), launchd tunnel

### Surfaces

**Work Column**:
The session-scoped auxiliary surface beside Chat that contains Home, Files Changed, Context, Pulse Inspector, and Preview. On desktop it may dock right, left, or bottom of Chat or move into a paired panel-only VS Code editor tab; every host presents the same logical state and features.
_Avoid_: Side panel, sidebar, editor

**Detached Work Column**:
The panel-only VS Code editor-tab host for a Work Column record. It is fully connected to its bound Chat and session, owns the record's live lease while detached, and exposes the same features as an attached Work Column; it is never a copied view or a separate Chat.
_Avoid_: Floating chat, copied panel, separate chat

**Suspended Work Column**:
A durable Work Column record with no live host after its source Chat and detached panel have closed. A matching Chat may recover it without losing acknowledged state.
_Avoid_: Discarded panel, orphaned window

**Home**:
The always-present first tab in the Work Column that renders the user's widget grid — profile cards, run status, problem summaries, and custom agent-authored widgets. The single canonical surface for widgets; replaces the standalone home page. Internally powered by the widget kernel (WidgetGrid, WidgetFrame, the bridge protocol, `/amicode/widgets` + `/amicode/dashboard` endpoints).
_Avoid_: Dashboard (as the surface name), widget panel
Expand Down
8 changes: 7 additions & 1 deletion docs/adr/0013-preview-workspace-split-panes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ Preview — previously a single-file companion viewer that replaced its content

**Why:** The single-file companion model (#931) optimized for a different problem — one file at a time, driven externally, no navigation chrome competing with the Sidebar. In practice, researchers comparing two files (a script and its output, a spec and its implementation) lost their place every time a second file replaced the first. The companion model traded away exactly the capability multi-file work needs. Sidebar remains the project-wide file tree; the breadcrumb is a narrower, contextual navigation aid scoped to the currently open file's siblings, not a second file browser.

**Conditions of acceptance:** Files opened via Sidebar single-click or a Chat file pill accumulate as inner tabs in the focused pane rather than replacing the current file; re-opening an already-open file (from any entry point, including breadcrumb sibling navigation) focuses its existing tab instead of duplicating it — enforced workspace-wide, not just within one pane. Tabs close via an explicit control and are drag-reorderable. A breadcrumb bar shows the active file's project-relative path as clickable segments, each expanding to a sibling dropdown. Dragging a tab to a pane's edge splits that pane (horizontal or vertical); splits are recursive, subject to a 150px minimum pane dimension that refuses drops which would violate it and clamps resizes at the same floor. Each pane carries independent zoom and preview/edit-toggle state. The entire workspace — every pane, every tab, all per-tab state including unsaved edits — survives switching to another outer side-panel tab and back. Double-click-to-open-in-VS-Code and the outer tab bar are unchanged.
**Conditions of acceptance:** Files opened via Sidebar single-click or a Chat file pill accumulate as inner tabs in the focused pane rather than replacing the current file; re-opening an already-open file (from any entry point, including breadcrumb sibling navigation) focuses its existing tab instead of duplicating it — enforced workspace-wide, not just within one pane. Tabs close via an explicit control and are drag-reorderable. A breadcrumb bar shows the active file's project-relative path as clickable segments, each expanding to a sibling dropdown. Dragging a tab to a pane's edge splits that pane (horizontal or vertical); splits are recursive, subject to a 150px minimum pane dimension that refuses drops which would violate it and clamps resizes at the same floor. Each pane carries independent zoom; each document carries its own preview/edit-toggle state. The entire workspace — every pane, every tab, all per-tab state including unsaved edits — survives switching to another outer side-panel tab and back. Double-click-to-open-in-VS-Code and the outer tab bar are unchanged.

**Accepted costs:** The workspace reintroduces navigation surface (the breadcrumb) that #931 deliberately removed — a future reader of #931's history will see this as a partial reversal, not a straight line; the ADR exists so that reversal reads as deliberate. Per-pane state (zoom, mode, scroll, unsaved content) roughly doubles or triples the state `SessionPreviewTab` used to hold for a single file, now split across `PreviewWorkspace`/`PreviewPane`. The workspace store must be lifted into the layout context (above `session-side-panel.tsx`'s `<Show when={activeTab() === SESSION_PREVIEW_TAB}>` gate) rather than owned locally, because SolidJS disposes a `<Show>` branch's reactive scope on every toggle — the single-file `SessionPreviewTab` already loses its local state this way today, and a multi-file, multi-pane workspace makes that loss far more costly if inherited unfixed. At the 330px minimum panel width (`WORK_COLUMN_WIDTH_MIN`), only one horizontal split is practically usable before panes drop below a comfortable reading width — accepted as a constraint of the side-panel form factor. Splitting, cross-pane tab transfer, and pane resizing are pointer/drag-only in this version; there is no keyboard-accessible path for any of the three.

**Considered:** (A) Extend `SessionPreviewTab` in place with tab/breadcrumb/split logic (rejected: the component is 119 lines today, but tab-bar, pane-tree, and breadcrumb logic are three distinct responsibilities that would tangle together as each grows independently — not a current-size problem but a projected-shape one); (B) **new `PreviewWorkspace`/`PreviewPane`/`PreviewBreadcrumb` component tree** (chosen: clean separation, each component independently testable, `SessionPreviewTab` shrinks to a thin shell); (C) a generic `SplitPaneLayout` primitive built first and specialized for Preview (rejected for now: speculative reuse — no other surface has asked for splitting yet — and the abstraction would be guessed at rather than derived from a second real use; extracting it from B later is straightforward if that need materializes).

**Flip condition:** If a second surface (e.g. Files Changed) independently needs split-pane viewing, extract the pane-tree logic from `PreviewWorkspace` into the generic primitive considered as option C, rather than duplicating the tree/drag machinery. If the side panel's minimum width increases substantially in a future layout pass, revisit the 150px pane minimum and how many practical splits it should allow.

## Amendment: Cross-Webview Ownership (2026-09-10)

The ownership implied above is made explicit for detachable Work Column hosts. The workspace owns the pane tree, including split-node direction, ratio, and child structure, plus outer-canvas scroll. A Preview leaf owns tab order, active tab, focus, and zoom. A Preview document owns mode, draft, selections, editor history, pending save or close state, conflict state, and renderer scroll.

Ordinary movement within one document preserves physical renderer identity. Cross-webview Work Column transfer is a separate transactional path: it preserves the same logical document state through a versioned checkpoint and hydration, but necessarily creates a new physical renderer instance. File reads and writes use content revisions so a restored draft cannot be silently overwritten by a late read or stale save result.
24 changes: 24 additions & 0 deletions docs/adr/0014-dockable-work-column.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 0014 - Make the Work Column dockable and transactionally detachable

Status: proposed (2026-09-10)

Tracking: harmoniqs/amicode#977

The Work Column remains the app-owned auxiliary surface, but its desktop host may dock right, left, or bottom of Chat or move into a paired panel-only VS Code editor tab. Attached and detached modes are exclusive hosts for one durable Work Column record. They provide the same features and logical state, including Preview editing, rather than presenting copied or degraded views.

## Decision

Use an extension-owned, durable Work Column journal with generation-fenced host leases. Every transfer-relevant mutation is write-ahead journaled and acknowledged before the host treats it as committed. The attached host drains to a checksummed checkpoint, the destination hydrates read-only, and the durable lease compare-and-swaps to the destination only after an exact acknowledgement. Reattachment is the same transaction in reverse. Native panel disposal restores from the journal rather than attempting to extract state after close.

The source Chat is chat-only while detached. Its Side Panel control reports the external state and reveals the paired editor tab. If the source closes, the detached panel closes after its final checkpoint and the record becomes suspended and recoverable. No host closure discards the record by itself.

## Considered Options

1. **Durable record with transactional handoff** -- chosen. It is the only option that can preserve full functional parity and avoid drift across disposal, reload, and host failure.
2. **One-shot snapshot or renderer reparenting** -- rejected. DOM nodes, editor instances, PDF tasks, iframe runtimes, and post-close state cannot cross a webview boundary safely.
3. **Read-only detached Preview or detach refusal for dirty state** -- rejected. The detached Work Column must work exactly as attached mode, including editing.
4. **Extension-owned duplicate renderer** -- rejected. It would create two mutable implementations and a permanent state-drift risk.

## Consequences

The journal must carry serializable Preview state, editor undo/redo, pending save and close operations, widget snapshots and subscriptions, inspector sequence/replay buffers, and all relevant Work Column UI state. Widgets gain a suspend/resume contract. Cross-webview transfer is a deliberate exception to ADR 0013's in-document retained-renderer rule: normal tab moves preserve physical renderer identity, while detached moves preserve logical renderer state through checkpoint and hydration. The eight-document cap remains logical, although a transaction may briefly create source and destination renderers. Every durable record has a canonical codec version, checksum, owner identity, generation, and compare-and-swap lease predecessor so stale hosts cannot write.
Loading
Loading