Reuse SEQPACKET connections across requests instead of
connect/close per command. Connections are returned to a
pool (max 4 idle) after successful use and discarded on error.
superpowerd HandleConn already loops for multiple requests
per connection, so this is safe. Each ExecuteCommandStreaming
still blocks its connection until the command exits, so
concurrent commands use separate pooled connections.
The adapter is now started by the system service manager, not
on-demand from inside the sandbox. ensureElevateAdapter was
removed from core in the previous commit.
Replace subprocess-based token refresh (superpowers run-session --child-session)
with direct SEQPACKET CreateSession RPC to superpowerd. This fixes:
1. Session PID mismatch: old approach registered session to short-lived sh
subprocess PID, causing immediate pidAlive() failure on next use
2. Child session failure: --child-session fails when superpowerd restarts
(parent session gone)
3. Gentoo python-exec2c exec chain: replace os.execvp startup with direct
CreateSession call
The adapter now owns its session directly (peerPID = adapter PID), so the
session stays valid for the adapters entire lifetime.
When superpowerd returns exit 255 with no output streamed, treat it as a
suspicious session failure (same as auth error) and retry with a refreshed
token. This addresses intermittent elevated command failures where the
session silently expires mid-conversation.
Also adds stderr logging at key decision points: token refresh attempts,
retry signals, RPC errors, and non-JSON responses from superpowerd.
prime script no longer detects platform/git locally. All PRIME_*
variables are set by BuildRuntime callers and stored in the agent
for /agent reloads. Templates use PRIME_CWD instead of PWD.
Remove _start_adapter() from x/elevate (ran inside sandbox, could not
function). The Go executeElevated() now calls ensureElevateAdapter()
which runs outside the sandbox and can properly start the adapter.
core: update submodule.
Wrap _handle_inner() in try/except so unhandled exceptions always
produce an error frame instead of silently closing the connection
(which caused exit 255 with no output on the client).
elevate-adapter-superpowerd: detect auth errors from superpowerd and
automatically refresh the session token via "superpowers run-session
--child-session", retrying the request once.
x/elevate: auto-start the adapter if the socket is not available,
removing the dependency on the agentSpawn hook for adapter lifecycle.
core: update submodule (hook run/fail summary).
Replace the batch JSON request/response protocol with a streaming
frame protocol. The adapter now uses superpowerd ExecuteCommandStreaming
with SCM_RIGHTS fd-passing to stream stdout/stderr in real-time.
Protocol: client sends {cmd,cwd}+newline, server streams frames
(type byte + 4-byte length + payload). This enables elevated+detach
to capture live output in the ring buffer.
Also updates core submodule with elevated+detach support.
- agent JSONs: $OLLIE/x/ -> $OLLIE_CFG_PATH/scripts/x/
- x/prime: use $OLLIE_PROMPTS_PATH instead of $OLLIE/p/
- x/elevate-adapter-start: use $OLLIE_CFG_PATH/scripts/x/
- Update core and 9p submodules
olliesrv and agent sessions now work without FUSE. Mount remains
available as an enhancement when present.
Replace the Python raw-mode multiline hack (readmulti) with an inline
bash read -e loop using backslash continuation. Add show_new to display
the server response after /model, /agent, /backend cfg writes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- scripts/x/freeloader: track tried models per-session in freeloader-tried-$SID;
walk the full sorted :free pool in order before exiting 1; write recovery
prompt to fifo.in (not prompt) to avoid goroutine race
- core submodule: 404 tool_unsupported detection + FIFO drain on error
- tui submodule: fix mid-stream newlines from backgroundTail chatOff race
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- scripts/x/freeloader: hook-driven script; intercepts rate_limit and
tool_unsupported on :free models; auto-blacklists on tool_unsupported;
cycles to next non-blacklisted free model; exits 1 for unhandled errors
- agents: add turnError hook to all agent configs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace 'task prime' hook with inline .beads walk in all agent configs —
no wrapper script needed. Drop 'prime' subcommand from scripts/x/task.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add x/elevate-adapter-start: checks if the adapter is already listening
(connect test), starts it in the background if not. Exits 0 always so it
never blocks session startup. Wire it into agentSpawn in all agent configs
and install it via mkfile.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Python adds the script directory to sys.path[0] at startup and tries to
create a FileFinder for it. When the script lives on a 9P FUSE mount the
FileFinder init fails before any stdlib import can succeed. sys is a
builtin and loads without filesystem access, so strip the path first.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both x/elevate and elevate-adapter-superpowerd now default the socket
path to $XDG_RUNTIME_DIR/ollie/elevate.sock (falling back to
/run/user/<uid>/ollie/elevate.sock) when OLLIE_ELEVATE_SOCKET is unset.
Add OLLIE_ELEVATE_SOCKET to env sections of both sandbox configs.
Add {XDG_RUNTIME_DIR}/ollie to restricted sandbox filesystem rw rules
so x/elevate can reach the socket. Update README env block and
scripts/README socket path docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
x/elevate is now a generic client: reads OLLIE_ELEVATE_SOCKET, sends
{cmd,cwd}, reads back {stdout,stderr,exit_code}. All backend-specific
logic moves to adapters. Add elevate-adapter-superpowerd as the
reference adapter: owns the socket lifecycle, translates the ollie
protocol to superpowerd JSON-RPC ExecuteCommand. Add OLLIE_ELEVATE_SOCKET
to env docs. Update scripts/README.md with protocol spec, adapter
setup, and guide for writing custom adapters.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove Go template syntax from all prompt files (converted to envsubst
variables in prior commits). Agent agentSpawn hooks now call prime for
each prompt file explicitly, replacing the automatic Go-based directory
scan. coding agent gets 08_tool-elevate; default does not.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
prime <name> prints $OLLIE/p/<name>[.md] to stdout, which the agentSpawn
hook captures as context. Allows agent prompt composition to be driven
entirely from hook config rather than built-in Go code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Submodules have .git as a file, not a directory. -d was stopping the
walk immediately in submodule directories.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Walk up from CWD only while .git exists at each level. Stops at the
first directory without .git, preventing false positives outside the repo.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The bd wrapper walks up from CWD to find a .beads directory and sets
BEADS_DIR, so bd works from any subdirectory of a monorepo without the
model needing to know about it.
The execute server now always prepends $OLLIE/x/ to PATH for tool
subprocesses, so wrappers placed there shadow system binaries transparently.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace tools/elevate_superpowers with scripts/x/elevate — a single
self-contained plugin that bootstraps into a superpowers session and
runs the IPC. mkfile installs it to ~/.config/ollie/scripts/x/.
Update 08_tool-elevate.md to remove backend-specific language.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>