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
32 changes: 32 additions & 0 deletions specs/0001-sessions-are-the-core-unit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0001-sessions-are-the-core-unit

Status: accepted
Date: 2026-05-30
Area: architecture
Scope: Applies to user-visible work, orchestration, persistence, and client rendering.

## Decision

agentd models active work as sessions. A session is the durable unit for identity, transcript, runtime status, UI state, cwd, harness ownership, grouping, and user interaction.

## Reason

Users operate on long-running agents, not isolated command invocations. Treating each agent run as a session lets clients reconnect, inspect history, resume work, and coordinate multiple agents without inventing separate abstractions for every surface.

This also gives all clients a shared mental model. The TUI, web UI, CLI, MCP tools, and harness adapters can describe the same object when they list, select, pin, rename, reorder, interrupt, or delete work.

## Consequences

Features that look like UI affordances should first be evaluated as session features. If the feature has transcript, status, input, persistence, or ownership, it probably belongs on a session rather than in a separate global UI channel.

Sessions need stable identity across reconnects and daemon restarts. Clients should preserve the user's selected session and avoid treating reconnect as a new run.

This makes sessions a broad abstraction. Future changes must be careful not to overload session state with unrelated global settings, and should keep cross-session concepts explicit.

## Non-Goals

This does not mean every small UI preference belongs in session state. Pure client-local layout choices can stay local when they do not need to survive across clients or daemon restarts.

## Examples

A terminal-backed worker, a chat-style agent, and the orchestrator command surface are all sessions, even though clients render them differently.
32 changes: 32 additions & 0 deletions specs/0002-orchestrator-is-a-session.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0002-orchestrator-is-a-session

Status: accepted
Date: 2026-05-30
Area: architecture
Scope: Applies to the fleet command surface, operator UI, approvals, and orchestration behavior.

## Decision

The orchestrator is a real session, not a special command bar. It should use the same persistence, transcript, input, resume, rendering, and approval mechanics as other sessions, while clients may present it in a specialized location.

## Reason

The orchestrator needs to reason about and act on the fleet over time. Making it a session avoids a parallel stack for history, queued input, tool calls, approval rendering, restart behavior, and harness-specific behavior.

This keeps orchestration extensible. New session capabilities automatically become available to the orchestrator unless there is a deliberate reason to exclude them.

## Consequences

Future orchestrator features should be implemented as session features by default. Special global UI paths should be reserved for display placement or selection policy, not for distinct behavior.

The orchestrator may be hidden from ordinary session lists while still retaining all session semantics. Clients should distinguish between "not shown in the normal list" and "not a session."

The user-facing label for this role should be operational and contextually consistent with agentd's Matrix-inspired aesthetic. The accepted label is "operator."

## Non-Goals

This does not require every client to render the orchestrator in the same screen position. It only requires the underlying behavior to remain session-based.

## Examples

An approval requested by the orchestrator should appear in the orchestrator's own interaction stream rather than taking over an unrelated global prompt.
32 changes: 32 additions & 0 deletions specs/0003-session-widgets-are-ui-state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0003-session-widgets-are-ui-state

Status: accepted
Date: 2026-05-30
Area: ux
Scope: Applies to generative widgets, widget persistence, widget rendering, and action links.

## Decision

Session widgets are session-scoped UI state, not transcript history. Agents provide semantic Markdown widget content; clients own layout, scrolling, focus, visibility controls, and rendering details.

## Reason

Agents need a compact way to show progress, decisions, and steering actions without polluting the model-facing conversation. Widgets solve that by creating a durable UI surface that can be updated or removed as task state changes.

Keeping widgets outside the transcript also lets clients rehydrate the latest widget state after reconnect without replaying conversation history.

## Consequences

Agents should update, consolidate, or delete widgets as task state changes. Stale widgets are misleading and should not be treated as permanent logs.

Clients should render current widget state from the session, including after reconnect. A missed live widget update during a disconnect must not leave the user looking at stale content once the client reconnects.

Widget actions represent user intent. They do not bypass normal permission, safety, or approval requirements.

## Non-Goals

Widgets are not a replacement for transcripts, logs, or durable project documentation. They are for current task UI.

## Examples

A checklist showing "Implement", "Validate", "Open PR", and "Merge" is a widget. The final PR discussion belongs in the transcript or repository, not in a permanent widget.
32 changes: 32 additions & 0 deletions specs/0004-widget-renderers-own-interaction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0004-widget-renderers-own-interaction

Status: accepted
Date: 2026-05-30
Area: ux
Scope: Applies to widget display in TUI and web UI clients.

## Decision

Widget producers define semantic content, while each client renderer owns interaction mechanics such as hide/show, dropdown listing, collapsed state, scrolling, focus handling, and responsive layout.

## Reason

The same widget should be useful in multiple clients with different constraints. A terminal UI, browser UI, and future clients cannot share identical layout mechanics, but they can share semantic Markdown and action intent.

Separating content from interaction lets clients improve ergonomics without changing agent-produced widget files.

## Consequences

Clients should provide a way to hide visible widgets and bring hidden widgets back. Hiding is a user preference over current widget visibility, not a deletion of widget state.

Dropdowns, popovers, and widget windows should remain stable while the user toggles widget visibility. A checkbox-style action should not close the surrounding widget management UI unless closing is the explicit command.

Clients should avoid nested framed surfaces and should keep widget controls consistent with the rest of that client.

## Non-Goals

This does not require pixel parity across TUI and web UI. Equivalent semantics are more important than identical presentation.

## Examples

If a user unchecks a widget in a web dropdown, the dropdown should stay open so the user can adjust multiple widgets in one pass.
32 changes: 32 additions & 0 deletions specs/0005-reconnect-must-preserve-live-terminal-state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0005-reconnect-must-preserve-live-terminal-state

Status: accepted
Date: 2026-05-30
Area: webui
Scope: Applies to web client reconnect, terminal sessions, composer resize, and mobile viewport changes.

## Decision

Reconnect and viewport changes must preserve the live terminal surface. A client must not replay transcript or PTY history into an already-live terminal just because the websocket reconnects, the composer changes size, or a mobile keyboard appears.

## Reason

Terminal surfaces are stateful. Replaying old output into an existing terminal buffer makes the user see history duplicate or jump back to the beginning, which is especially disruptive during mobile keyboard show/hide and long-running sessions.

The user's scroll position and active terminal buffer are part of their current working context.

## Consequences

For terminal sessions, reconnect should refresh side-channel UI state that can become stale, such as widgets, while avoiding terminal transcript or PTY replay into the current buffer.

Composer resize and input insertion must not force scroll-to-top, scroll-to-middle, or full terminal repaint behavior.

This creates a split between terminal and non-terminal hydration paths. Future client code should preserve that distinction.

## Non-Goals

This does not prevent a fresh client with no existing terminal buffer from hydrating initial terminal content. It only constrains reconnect and resize behavior for an already-rendered live terminal surface.

## Examples

If a phone keyboard opens and the browser reconnects, the terminal should stay where the user left it while the widget panel can still update to the latest server state.
32 changes: 32 additions & 0 deletions specs/0006-resize-and-restart-avoid-full-history-refeed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0006-resize-and-restart-avoid-full-history-refeed

Status: accepted
Date: 2026-05-30
Area: tui
Scope: Applies to TUI resize, zoom, restart, and terminal/history rendering.

## Decision

Resize should be instant and should not refeed full history. Existing content may keep its previous wrapping; new content should use the new dimensions. Restart should preserve history only when a harness can resume without repainting over an incompatible terminal state.

## Reason

Full history refeed makes resize and zoom slow for long-running sessions, and it can corrupt or duplicate terminal-like output. Users resize panes and terminals frequently; those operations must feel like layout changes, not transcript reconstruction.

Preserving old wraps is an acceptable tradeoff for speed and stability.

## Consequences

Rendering systems should be append-oriented after resize. They should avoid using resize as a reason to recompute every previous visual line.

When a harness cannot resume cleanly from prior terminal state, the daemon should prefer a clean slate over partial reuse that leaves the terminal half-rendered.

Sessions should come back at the dimensions the user currently has, not at stale creation-time dimensions.

## Non-Goals

This does not require perfect historical reflow after resize. Stable, responsive interaction is more important.

## Examples

After increasing terminal width, old lines may remain wrapped at their old width, while new output uses the wider width.
30 changes: 30 additions & 0 deletions specs/0007-session-list-actions-target-visible-user-sessions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 0007-session-list-actions-target-visible-user-sessions

Status: accepted
Date: 2026-05-30
Area: ux
Scope: Applies to session list ordering, navigation, and list actions.

## Decision

Session list actions should operate on visible user sessions, not hidden system sessions or collapsed descendants that the user cannot currently see.

## Reason

List actions should match the user's visible model. If a reorder or navigation command affects hidden rows, the result feels unpredictable and can appear broken.

Hidden orchestrator sessions and collapsed project contents are implementation or organization details from the user's current point of view.

## Consequences

Move-up, move-down, and similar list operations should skip hidden or currently collapsed items. Selection and ordering semantics should be based on the rendered user list unless a command explicitly says it is operating globally.

This may require keeping internal ordering separate from visible ordering, or translating user actions through the current visible projection.

## Non-Goals

This does not forbid commands that operate on all sessions. Such commands must be explicit about their wider scope.

## Examples

If a project is collapsed, moving a visible session down should jump over that collapsed block rather than targeting one of its hidden sessions.
32 changes: 32 additions & 0 deletions specs/0008-built-in-harness-command-overrides.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0008-built-in-harness-command-overrides

Status: accepted
Date: 2026-05-30
Area: harness
Scope: Applies to built-in harness adapters and user configuration of child commands.

## Decision

Built-in harness adapters must support both binary-only overrides and full command-prefix overrides for the child process they spawn. Full command overrides take precedence over binary-only overrides and are still executed directly, without invoking a shell.

## Reason

Some user environments require more than replacing a binary path. They may need wrappers, launchers, version managers, or command prefixes. At the same time, shell execution would introduce quoting surprises and avoidable security risk.

Supporting direct full command overrides gives users flexibility while preserving predictable process spawning.

## Consequences

Adapters should treat command override parsing as configuration, not as shell script evaluation. Whitespace and quoting can structure arguments, but shell expansion and shell operators should not be part of the contract.

Existing binary-only override behavior should remain as a simpler fallback.

Future built-in harnesses should follow the same override shape so configuration remains consistent.

## Non-Goals

This does not make arbitrary shell snippets a supported adapter launch mechanism.

## Examples

A user can configure a harness to launch through a wrapper command, while agentd still spawns the resulting executable and arguments directly.
32 changes: 32 additions & 0 deletions specs/0009-transient-provider-errors-are-retryable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0009-transient-provider-errors-are-retryable

Status: accepted
Date: 2026-05-30
Area: harness
Scope: Applies to provider-backed agent turns, especially model provider streaming failures.

## Decision

Transient provider failures should be classified as retryable and retried automatically when retrying can preserve the user's intent without duplicating completed side effects.

## Reason

Provider APIs can fail due to rate limits, temporary overload, network interruption, server errors, or incomplete streams. Treating all such failures as fatal makes long-running sessions brittle and forces users to manually resubmit work that the system can safely continue.

At the same time, retries must avoid hiding deterministic errors or repeating actions that already happened.

## Consequences

Provider adapters should distinguish transient failures from permanent request, authentication, configuration, and policy failures.

Retry behavior should be visible enough that users can tell progress is still happening and should eventually surface a clear error if retries are exhausted.

Retried turns must preserve conversation intent. They should not duplicate tool side effects that were already accepted as complete.

## Non-Goals

This does not require infinite retries, retrying every error, or silently ignoring provider failures.

## Examples

A temporary provider overload during text generation can be retried. An invalid API key or unsupported model name should fail clearly.
32 changes: 32 additions & 0 deletions specs/0010-memory-is-durable-shared-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0010-memory-is-durable-shared-context

Status: accepted
Date: 2026-05-30
Area: persistence
Scope: Applies to global memory, project memory, agent context, and multi-harness continuity.

## Decision

Memory is durable, human-editable Markdown context shared across agent sessions and harnesses. It is separate from transcripts and should store reusable facts, preferences, workflows, decisions, commands, glossary, and pitfalls.

## Reason

Transcripts record what happened, but they are too noisy and session-specific to serve as durable operating context. Agents need a small, auditable surface for information that should influence future work.

Markdown keeps memory easy for users and agents to inspect, edit, prune, and correct.

## Consequences

Agents should load available memory before starting substantial work and update it when they learn durable information that will likely help future sessions.

Memory should use the narrowest useful scope. Cross-project preferences belong globally; repository-specific workflows or architecture belong to project memory.

Memory maintenance should be conservative. Agents should avoid storing secrets, transient task status, large command output, speculation, or facts that will quickly go stale.

## Non-Goals

Memory is not a complete knowledge base, task tracker, transcript summary, or replacement for repository documentation.

## Examples

A recurring project merge workflow belongs in project memory. A one-time CI run URL does not.
32 changes: 32 additions & 0 deletions specs/0011-tooling-is-shared-across-harnesses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 0011-tooling-is-shared-across-harnesses

Status: accepted
Date: 2026-05-30
Area: protocol
Scope: Applies to fleet-control tools, browser tools, memory access, widgets, and harness integrations.

## Decision

agentd should expose one shared tool surface across supported harnesses. Built-in and external agents should be able to access the same fleet-control, memory, widget, and browser capabilities through the integration style appropriate for that harness.

## Reason

agentd coordinates a fleet of heterogeneous agents. If each harness gets a different tool model, agents cannot reliably hand off work, inspect each other, or follow the same operating conventions.

A shared tool surface also keeps product behavior consistent. A capability should feel like an agentd capability, not like a one-off feature of a single harness.

## Consequences

New agent-facing capabilities should be designed once and then made available through all practical harness integration paths.

Harness-specific limitations are acceptable, but they should be treated as integration gaps rather than separate product semantics.

Tools should carry enough session identity and context that agents can avoid accidentally acting on themselves or using the wrong project state.

## Non-Goals

This does not require every harness to use the same transport or implementation strategy.

## Examples

An agent should be able to inspect sessions, update memory, and create task widgets whether it is using the native harness or an MCP-capable child harness.
Loading