Bug: reading agent files (log, chat, state, etc.) via 9P returned the
same data regardless of which session or agent ID was specified. The
server did not validate agent IDs and had out-of-bounds slice access
on when the path had fewer components than expected.
Fixes:
- fs/session/root.go: Added guard before all
checks in rootReaddir, rootStat, rootOpen.
Added guard before access in rootStat.
Added agent ID validation — returns error if the requested agent ID
doesn't match the session's actual agent.
- cmd/olliesrv/server.go: Restructured pathType() to nest agent path
checks inside a single
block, preventing proc-path checks from incorrectly matching agent
paths. Added agent ID validation (returns "" = not found).
Added agent-path support in makeStat() for Qid version tracking on
log/chat. Skip blocking files (chat, statewait) in stat-size
computation to prevent hangs.
Delete dbus/dbus.go — the entire D-Bus SessionManager service is gone.
No more 150ms poll loop, no more signal emission, no more method handlers.
- Remove ollie/dbus import, nodbus flag, dbusAdapter variable
- Remove OnSessionCreated/Killed/Renamed hooks from Config
- Remove EnableDBus from Config
- Elevation notifications connect to session bus directly (godbus stays
as a dependency solely for org.freedesktop.Notifications)
All clients now use 9P exclusively. D-Bus is dead.
- Rename 'chat' to 'log': returns last 64KB sliding window (static read).
Tail still works via Qid.Vers. Full history persisted to disk per turn.
- Add 'chat' streaming file: blocking read that delivers new output as
the agent produces it. Per-fid offset tracked via waitBase. Blocks
indefinitely between turns (no EOF). EOF only on kill/session death.
- Add LongBlock interface to File: streaming files bypass the 5s read
timeout. Server returns content directly (ignores Tread offset for
streaming files since waitBase tracks position).
- Add 'kill'/'.'' ctl aliases with FIXME: currently kills entire session.
When multi-agent-per-session lands, kill should kill agent only.
- Rewrite acme frontend (cmd/Ollie) to use 9P client directly instead
of FUSE mount. streamChat() is a blocking read loop — no polling.
All file operations (read, write, ls) go through plan9/client.
- Add 9P streaming prototype in experiments/9p-stream demonstrating
the blocking-read pattern for token delivery.
The key insight: 9P's request-response model gives natural streaming.
Server holds the Tread until data arrives, client blocks on Read().
No polling, no signals, no offset tracking needed.
skill_list and skill_load are now external shell scripts (data/tools/).
Removed from builtins: SkillList, SkillLoad, SkillActive.
Removed: toolsrv/skills.go, tools/builtin/skill.go, WithSkillsRegistry,
SkillsRegistry accessor, ListSkillsTools.
ollie-remote no longer initializes a skills registry.
The demarcation: built-ins mutate agent internals (tool schema, context
injection). Skills are just file reads — no special treatment needed.
- Embed the full sandbox/default.yaml instead of sandbox-remote.yaml
so local ollie-remote subprocesses get proper sandbox permissions
(DNS, git config, etc.)
- justfile copies sandbox/default.yaml temporarily during build
- Register builtins + ToolRegistry + SkillsRegistry on ollie-remote
- Pdeathsig: kernel auto-SIGTERMs children when parent dies
- Cleanup: SIGTERM → 3s grace → SIGKILL (guaranteed kill)
- Atomic counter for unique socket paths (no collisions)
Execution is now identical for local and remote:
- Session calls Spawn()/SpawnRemote() → owns *Process with socket
- Clients call Dial(LocalAddr(socket)) → *Conn over Unix socket
- ollie-remote serves --listen mode with multi-client accept loop
- Builtins (shell, tool_load, skill_load) run in subprocess with registries
Lifecycle:
- Pdeathsig ensures children die with parent (no orphans)
- Cleanup: SIGTERM → 3s grace → SIGKILL (guaranteed)
- Socket paths use atomic counter for uniqueness
- Session Kill() closes Process
Protocol:
- Extended RPC: set_env, set_cwd, detach, list_detached, etc.
- Shell goes through builtin dispatch (parses 'cmd' field correctly)
- Streaming output via JSON-RPC notifications
Shell results were returned as raw strings but the agent expects
structured content blocks ({content:[{type:text,text:...}]}). Fixed
shell handler to return the same format as the local Server.CallTool.
Shell errors now return as isError content blocks rather than RPC
errors, matching local behavior (output is preserved in errors).
The default RPC handler now dispatches to srv.CallTool() for any
unknown method, enabling named tools (file_read, file_grep, etc.)
from the embedded tools to be called remotely.
ExecuteInSandbox uses StreamFunc(ctx) to emit partial output. The
context passed to it lacked a WithOutputStream callback, so no output
was ever streamed back to the client.
Fix: wrap ctx with WithOutputStream that encodes output as JSON-RPC
notifications (id=0, result={data:...}). The client side already
handles these via the outputNotification path in CallTool.
Add README.md explaining the network transparency role of the mount
package. Replace 'kept as a convenience' comment with one that explains
why it exists and how it differs from local 9pfuse.
The FUSE-based 9P mount (mount/) was unused — all actual mounting
uses 9pfuse via ollie-remount. Remove the package, the olliesrv mount
subcommand, and the go-fuse dependency.
- Rewrite cmd/ollie-remote to use toolsrv.Server API (was using non-existent
ollie/pkg/tools and ollie/pkg/tools/execute packages)
- Restore tools/_lib/ from pre-flatten branch (was lost in migration)
- Remove stray go.mod/go.sum from cmd/Ollie, cmd/ollie-httpgw, cmd/ollie-remote
- Update justfile: ollie-remote target copies tools from contrib/tools/
- Remove leftover root prompts/ directory