ollie/doc/boot-sequence.md

55 lines
2.4 KiB
Markdown

# Boot Sequence
How `olliesrv` starts up, from `main()` to serving 9P requests.
## Call chain
```
main()
│
├── env.EnsureDefaults() — populate $XDG_CONFIG_HOME/ollie/ if missing
├── olog.NewSink() — stderr/stdout log sink
├── fs.NewModelCache() — async LLM model list (prefetched later)
│
├── fs.NewRoot(cfg) ← composition root
│ │
│ ├── session.Init(...) — set package-level config (ctx, dirs, logger)
│ ├── build RootState — allocate SessionNodes map
│ ├── fsedsl.BuildTree(spec) — walk fs/spec.go, produce *Tree with lazy resolution
│ └── session.RestoreAllSessions()
│ └── for each .json in sessions/active/
│ ├── unmarshal PersistedSession
│ ├── rebuild Session + Agents (paused)
│ └── register in session registry
│
├── bypass.NewBroker(...) — start bypass socket (sandbox escape approval)
├── New(serverCfg) — create 9P server wrapping the tree
├── net.Listen("unix", sockPath) — bind the 9P socket
└── accept loop — each conn gets srv.Start(conn)
```
## Why `fs.NewRoot` is the composition root
The 9P filesystem IS the runtime. Every session, agent, and tool server is
reachable only through the namespace. So the filesystem package owns
initialization: it creates the tree, initializes the session registry, and
restores persisted state — all before a single 9P connection is accepted.
`main.go` is deliberately thin: parse flags, set up logging, call `fs.NewRoot`,
start the listener. All domain logic lives in the packages.
## Key ordering constraints
1. `session.Init()` must be called before `RestoreAllSessions()` (sets pkg config).
2. `RootState` must be allocated before `BuildTree()` (closures capture the pointer).
3. `BuildTree()` must complete before `RestoreAllSessions()` (restored sessions
create nodes in the tree).
4. The bypass broker starts AFTER the tree is built but BEFORE the accept loop
(tool execution needs the broker socket).
## Session restoration
Restored sessions come back **paused**. They have agents with history but no
running tool server or LLM connection. The first `Resume` (via ctl write)
re-dials the tool server and reconnects the backend.