Shutdown() was calling KillSession() which deleted the persisted
JSON files immediately after saveAllSessions() wrote them. Now
Shutdown() closes sessions directly without removing persistence
files, allowing restoreAllSessions() to find them on next start.
Follows the Plan 9 /net/dns pattern: per-fid request-response.
Write JSON request (or plain prefix), write blocks during LLM call,
read returns the completion result. Per-fid state means concurrent
clients get independent request/response pairs.
Also includes the Complete method, findOrCreateCopilot, and noise
stripping helpers in the session package.
Sessions are saved to ~/.local/share/ollie/sessions/active-9p/ on
shutdown and restored on startup. Core auto-saves to SessionsDir
during turns. KillSession removes persisted files.
Closes the major feature gap with the D-Bus daemon.
- ls /s/{id}/proc/ lists detached PIDs
- cat /s/{id}/proc/{pid} reads ring buffer output
- rm /s/{id}/proc/{pid} dismisses the process
- echo detach > /s/{id}/ctl detaches running process
- echo "signal {pid} [TERM|KILL]" > /s/{id}/ctl signals detached process
Walk validates PID exists in detached list before succeeding.
content() holds sess.mu.RLock, then calls CachedListModels which
tried to acquire sess.mu.Lock for cache write — classic RLock/Lock
deadlock. Fix by giving the models cache its own mutex independent
of the session mu.
- Add CachedListModels() with 24h TTL to avoid repeated Models() API calls
- Cache readdir serialized bytes per-fid (rebuild only at offset=0)
- Skip all session file size computation in makeStat (report len=0)
- Short-circuit pathType() for session paths to avoid triggering Stat
- Remove e.Info() call from subdirectory readdir (unused mtime)
- Add monotonic timer to handle() for profiling 9p operations
- Add fcallTypeName() helper
- Fix stubCore for new Detach/SaveSession interface methods
- Add tools-process.md prompt
Before: ls inside a session dir took 1.38s (kiro) / 67ms (openrouter)
After: 182µs regardless of backend (7500x improvement)
Remove a/, p/, sk/, m/, tr/, tmp/, u/, x/, and per-session t/ from the
9P namespace. These are all files on disk that the runtime reads directly
from ~/.config/ollie/ — serving them through 9P added indirection without
value.
What remains:
- /s/ (live sessions: the dynamic state that doesn't exist on disk)
- /backends, /models, /help (synthetic root files)
This brings olliesrv's scope in line with the D-Bus daemon: session
lifecycle, prompt submission, state observation, and streaming output.
Created session/mount.go with all 9P FUSE mount logic previously in core.
Changes:
- New session/mount.go with MountPathFor(), WithMount9P(), and mount lifecycle functions
- WithMount9P() returns execute.Option that wires up OnEnvSet, OnPreDispatch, OnClose hooks
- Updated session.go to use WithMount9P() and MountPathFor() instead of execute.WithMount() and execute.MountPath()
- Mount logic encapsulated in mountState struct with proper synchronization
The mount implementation is now fully contained in the 9p module.
- Wire ReadPlanStep directly from sess.plan (no filesystem read)
- Add ListHandlers to ManagerConfig; passed through to AgentCoreConfig
- Hoist skillTree in main.go; populate ListHandlers for tools+skills
- Add ListHandlers to ManagerConfig
- Add ModelCache that prefetches models from all backends at startup
- Cache models in memory, refresh on demand via Invalidate()
- Add global /ctl file with 'invalidate' command
- Add 'invalidate' ctl command and /invalidate slash command in sessions
- Fix filePerm to query rootStore for root-level file permissions
- Add 'models' to root directory listing
- NewSession subscribes to bus "event" topic for chat log writing
- Remove makePublish/handler threading from all Submit call sites
- Adapt tests to new bus-based event delivery
Remove hardcoded permission switch in makeStat and delegate to
the underlying FileTree.Stat() instead. This makes FileList in
sessionfile.go the single source of truth for session file modes.
- server.New takes server.Config (no more internal construction)
- OnRename removed: wstat handles all fid rewriting directly
- WithStrict/WithYolo removed (passed via ManagerConfig)
- Default dir functions moved to main.go
- tool.go and root.go in main package (wiring)
- Server is now a pure protocol handler