SessionStore accepts paths like id/file, id/t/tool, new, idx.
All /s/ dispatch logic removed from server handlers.
Remaining /s/ refs are metadata only (makeStat, fileOwnerGroup).
- SessionStore.Stat/Open/Delete/Rename/Create handle hierarchical paths
- SessionStore.ListDir for subdirectory listing
- Tool idx filtering moved into SessionStore.openEntry
- SessionStore.MkdirAll delegates to ToolStore
- Removed: sessionFileStore, sessionAllowTools, filterToolIndex,
OpenFiltered, storeReadCtx, storeBlockingRead from server.go
- routeStore passes full suffix (not pathBase) to stores
Session uname is now a numeric UID (>=10000) separate from the session
name. Rename no longer affects identity — the mount keeps working with
the same principal.
- SessionStore uses atomic.Uint32 for UID generation
- Session.Uname() returns the immutable principal
- SessionByUname() lookup for attach-time group assignment
- fileOwnerGroup uses principal, not session name
- WithMount() passed from createSession
Session files now have owner=session_id, group=agent. Permission
checking is enforced on open for session files only:
prompt/fifo.in: mode 0022 (group+other write, owner cannot)
ctl: mode 0222 (everyone can write)
Self-prompt rejection is now a natural consequence of the permission
model — the session (owner) has no write bit on its own prompt file.
Cross-agent prompting works via group 'agent' write bit. User access
works via 'other' write bit.
On attach, sessions are added to group 'agent', other users to 'user'.
Removed the explicit self-prompt check from clunk.
Store Uname from Tattach on each connection. Reject writes to
s/{id}/prompt when the connection's uname matches the target session
(self-prompt). Cross-agent prompting remains allowed.
Add ollie-9p-mount: a FUSE-to-9P proxy that attaches with a custom
uname derived from $OLLIE_SESSION_ID. Each session gets a transparent
mount — tools use ordinary file I/O and the identity is carried by the
underlying 9P connection.
Also adds a group registry (AddGroup/RemoveGroup/InGroup) on the server
for future access control use cases.
When cwd was passed with ~ or $HOME (e.g. ~/src/myproj), it was used
unexpanded in BuildAgentEnv -> resolvePrompt, causing prompt commands
to fail silently (invalid cmd.Dir) and producing an empty system prompt.
Apply os.ExpandEnv + paths.ExpandHome before cwd is used anywhere.
Fixes a race where the client starts a new chatwait read after the
turn has ended (EnsureTrailingNewline already fired), causing a
5-second blocking delay before the shell prompt reappears.
Replaces polling with a blocking file that returns new bytes as they
are appended to the session log. Unblocks immediately on end-of-turn
(EnsureTrailingNewline) so frontends exit cleanly.
Fids opened OWRITE or ORDWR with zero bytes written were silently
dropped on clunk — the old writeBuf-length guard prevented handleWrite
from being called, leaving the previous file content intact.
Track writable by open mode instead, and remove the blanket empty-input
early return in handleWrite. /s/new retains its own empty guard since
a zero-byte write there is meaningless.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
s/new routes to BatchStore (one-and-done lifecycle) when the write
contains a \n---\n separator, and to SessionStore (multi-turn) otherwise.
Document both dirspecs separately: batch jobs have spec/state/statewait/
result/usage/ctxsz/log; interactive sessions have the full file set.
Also add missing params file to session dirspec.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All /b/ routing removed from pathType, read, remove, handleWrite,
readDir, and makeStat. The batchStore field is gone from Server;
SessionStore now handles both session and batch job lifecycle.
-154 lines from server.go.
- Replace Get/Put calls with storeRead/storeWrite helpers
- Replace Wait calls with storeBlockingRead helper
- Wrapper types override Open instead of Get
- Use OpenStore for session/batch child stores
- All store fields typed as Store
- FlatDirStore alias points to BlobStore
- Server fields use BlobStore for flat stores
- Replace JobStore/SessionFileStore with Open
- Type-assert for Wait/LogInfo where needed
- Rename store variable to sfs to avoid package shadowing
Server no longer owns sessions map or session lifecycle methods.
SessionStore and SessionFileStore are type aliases to core.
Fid path rewriting on rename handled via OnRename callback.