Features

What Ståge actually does, in the order a person meets it. Each row names the mechanism and the file that owns it; the deep pages are Architecture and The engine.

Talking to it

FeatureWhat it isOwner
Threads, many and cheapevery conversation is a lane; N threads are N views over one socket. Creating one writes a row and a roster entryStore.kt, wire/Roster.kt
Attach with rehydrateopening a thread asks the host for a snapshot; the bounded per-lane journal answers, and says truncated = true when it cannot reach far enough. Never a silent gaploom/LaneJournal.kt, Pages.kt
The roster is ordered by attentionwaiting → working → unread → settled, then activity descending — a daemon-global counter, because seq is per-lane and incomparableclient/Fold.kt, Activity.kt
Streaming answerstext, reasoning, tool calls and usage arrive as typed events on one NDJSON stream; heartbeats carry a counter, not a timestampwire/Wire.kt, net/NdjsonStream.kt
Steeringyour hand lands at a safe checkpoint, never between two wires: a sentence is appended to a running turn and consumed at the next boundarySteer.kt, TurnSteer.kt, MessageStore.kt
Abortstops the turn, keeps what landed; a partial answer is a readingTurnMachine.kt
Approvalsevery approval-required call parks until a human answers it on the deck; the request carries the effect class so the decision is informedApprovalGate.kt, EventRecorder.kt
Searchserver-side over thread titles and the text of prompts and answersSearch.kt
Model listwhat this daemon can run, and whether it may — read from the provider at boot, not rememberedModels.kt, provider/Targets.kt
Usageper-turn sums across rounds, plus the one lane reading that says how full the window isTurnUsage.kt, TurnUsageAccumulator.kt

Working with it

FeatureWhat it isOwner
The planthe turn's spine, declared by the agent and read by the human; abandoned steps are sent as dropped, never silently omittedPlan.kt
The deskthe thread's workdesk page — the procedure the reader follows while the work runs. A write replaces the whole page; the tool is bound to its lane and refuses to guess oneWorkdesk.kt
Files, anchored by digestfile_read returns the digest the next file_edit must cite. A stale edit is refused, never applied to content the model did not seeFileTools.kt, FileState.kt
Search before readfile_find / file_search are how the model locates; a content search never returns a file body, only path + line + clipped lineFindTools.kt, FileLocate.kt
Skillsoperational know-how as plain Markdown cards on disk — listed when unsure, loaded whole when the trigger matches. A card dropped in the directory appears on the next call, no restart, nothing to buildSkillTools.kt
The command linebash: one command through /bin/bash -lc, executed exactly as written, in one of three sandbox modes stated at boot (product / bench / off)Bash.kt, BashSandbox.kt
The gates, reachabledev_check runs one script/check-*.sh inside a dev tree's copy of a repository, and reads the resultDevCheck.kt
The railsbank_search, bank_get, librarian, research — four reads that reach the knowledge store and the open web, each offered only when its credential existsrail/
Compactiona long turn's request is a projection of the record, not a summary invented on the way inCompact.kt, TurnCompaction.kt
Continuationa turn that stopped short walks on instead of dying, with the state it reached namedContinuation.kt
Sensesa local, opt-in record of what this daemon actually did — the nervous system, on this machineSenses.kt
The stand-inwhat answers when no client is attached, under a posture that decides what it may decide aloneStandIn.kt

Working with others

FeatureWhat it isOwner
Delegationtask spawns one bounded child. The child is a contract, not a transcript: it returns a typed envelope — status, taskId, childThreadId, summary, findings with refs, usage — and the parent never sees the child's contextDelegation.kt
The deckthe waiting room between a child that cannot move without its parent and the human who answers there. The parent never sees the exchangeDeck.kt
The workforcebackground workers as one pure state machine: statuses, an admission with budgets, typed outcomes. Every rule the gate names is one boolean in WorkerRules.ktWorkers.kt, WorkerModels.kt, WorkerRules.kt
Verificationa verifier reads the artifact, not the builder's summary. One verifier child per task.verify, on its own thread and its own context; the builder never certifies itselfVerification.kt, Verifier.kt
Write childrena child that must change a file gets a disposable worktree cut at clean HEAD, worktree-bound instruments only, and returns a diff with a digest. It never applies it and cannot run bash or testsWriteChild.kt, WriteSession.kt, Worktrees.kt, WriteTools.kt
One writerapply_change re-checks the stored bytes against the digest, the checkout's HEAD against the base, every patched path against a clean status, and git apply --check — then applies once. A second apply is write.already_applied; a moved base is write.staleWriteTools.kt
The tool profilea prompt may switch a tool off for its own turn; a child's set is a subset of its parent's by constructionToolProfile.kt

Owning it

FeatureWhat it isOwner
The bearera token from the environment or a named file. There is deliberately no --token: argv is printed by ps, pgrep -f and any listing over a pipeDaemon.kt, TokenBoundary.kt
The store is oursSQLite, our schema, migrations from the first commit; one connection, one writer; the bearer is not workspace-readableDb.kt, Schema.kt, StoreRoles.kt
The environment is scrubbedcredential-shaped variables removed by shape, not by a list of names, before a sandboxed command sees the environmentEnvScrub.kt
Entitlement, offlinea licence is an Ed25519-signed payload verified without a network, a clock or a key server; the two facts (parseable, entitled) are returned separatelylicense/
Determinismno artifact reads a clock or a random number; the same input is byte-identical output, proven by hashClock.kt, Digest.kt, check-determinism.sh

The shape of a turn, end to end

prompt ──► TurnExecutor.begin  ──► TurnMachine (named states)
             │                        │
             ├─ provider round ───────┤ text / reasoning / tool_use events
             │   (SSE, adapters)      │
             ├─ Toolset.catalog ──────┤ what the model may call this turn
             ├─ ApprovalGate ─────────┤ parked until the human answers
             ├─ TurnTools ────────────┤ one result per call, in order
             └─ EventRecorder ────────┤ persist, then fan out
                                      ▼
                              store + lane bus ──► surface ──► clients