Slice 1 S6. packages/harness runs a role session under the pi or claude
adapter behind a tool gate, and packages/seat holds the session and its
process. The bus host gains a launch socket: `mosaic bus start
<business> --pm <harness>:<model>` runs the PM without a window, the PM
launches role sessions through the broker within the business file's
`launch.max`, and every launch, refusal and end is a launch-log line and
a broker event. `mosaic talk`, `mosaic launches off|on|list` and
`mosaic stop <run>` are new CLI verbs. packages/bus gains the IPC ops
identity, authorize, refuse, endLaunch and credentialStatus, plus
Broker.endLaunch (decision 77); no socket verb, event kind or schema
changed. The session environment is an allowlist, and the runner exits
before claiming if a founder credential reaches it.
Filbert built it (agents/filbert/work/s6). Darkwing reviewed on #1523:
round 1 changes (26991/26995), round 2 changes (27004/27010), round 3
changes (27012/27032), round 4 approve (27033/27034) on manifest
08a78972, 42 paths.
Sage's gate on 64b0f9f1 (12:32Z), sequential and teed: node suites
business 60, bus 74, cli 83, control-board 124, conversation 182,
discord 178, harness 56, ledger 78, mosaic 69, queue 149, runs 41,
seat 27, tasks 51, webui 39, every one 0 failed; test-auth 15,
test-conductor 17, test-config 24, test-discord 66,
test-extension-package 18, test-foundation 44, test-queue 27,
test-release 14, test-task 98 and 26 without Docker, all 0 failed.
64b0f9f1..ee7f909b touches none of the 42 paths. It landed after the
Q14 hold ended at 2026-10-11T17:19:23.857Z. The recorded PM-to-coder
run on a scratch data root is still owed before row 41 moves to done.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
115 lines
4.4 KiB
Bash
115 lines
4.4 KiB
Bash
#!/bin/sh
|
|
# Pi adapter: implements the Mosaic adapter contract for the pinned
|
|
# @earendil-works/pi-coding-agent CLI.
|
|
#
|
|
# Contract: see /opt/mosaic/adapters/README.md.
|
|
# Headless (default): stdout = response only; stderr = diagnostics; exit 0.
|
|
# Interactive (MOSAIC_INTERACTIVE=1): full pi TUI on the attached terminal.
|
|
set -eu
|
|
|
|
[ -n "${MOSAIC_SYSTEM_PROMPT_FILE:-}" ] || { echo "pi adapter: MOSAIC_SYSTEM_PROMPT_FILE is required" >&2; exit 2; }
|
|
[ -r "$MOSAIC_SYSTEM_PROMPT_FILE" ] || { echo "pi adapter: system prompt not readable: $MOSAIC_SYSTEM_PROMPT_FILE" >&2; exit 2; }
|
|
# MOSAIC_AGENT_NAME is optional in headless mode (identity section is then
|
|
# omitted); interactive launches always set it via scripts/agent.sh.
|
|
|
|
: "${PI_PROVIDER:?pi adapter: PI_PROVIDER is required}"
|
|
: "${PI_MODEL:?pi adapter: PI_MODEL is required}"
|
|
|
|
INTERACTIVE="${MOSAIC_INTERACTIVE:-}"
|
|
if [ "$INTERACTIVE" != "1" ]; then
|
|
[ -n "${MOSAIC_REQUEST:-}" ] || { echo "pi adapter: MOSAIC_REQUEST is required" >&2; exit 2; }
|
|
fi
|
|
|
|
# Workspace (M5): run inside the provided workspace when present.
|
|
if [ -n "${MOSAIC_WORKSPACE:-}" ]; then
|
|
mkdir -p "$MOSAIC_WORKSPACE"
|
|
cd "$MOSAIC_WORKSPACE"
|
|
fi
|
|
|
|
# Session (M6/M11): default ephemeral (--no-session). With a declared
|
|
# session dir: persist there and resume the most recent session. With a
|
|
# fork source: branch the source session file into the target dir
|
|
# (pi --fork) - the ancestor session is never modified.
|
|
SESSION_FLAGS="--no-session"
|
|
if [ -n "${MOSAIC_SESSION_FORK:-}" ]; then
|
|
[ -n "${MOSAIC_SESSION_DIR:-}" ] || { echo "pi adapter: session fork requires MOSAIC_SESSION_DIR" >&2; exit 2; }
|
|
mkdir -p "$MOSAIC_SESSION_DIR"
|
|
SESSION_FLAGS="--fork $MOSAIC_SESSION_FORK --session-dir $MOSAIC_SESSION_DIR"
|
|
elif [ -n "${MOSAIC_SESSION_DIR:-}" ]; then
|
|
mkdir -p "$MOSAIC_SESSION_DIR"
|
|
SESSION_FLAGS="--session-dir $MOSAIC_SESSION_DIR"
|
|
if [ -n "$(ls -A "$MOSAIC_SESSION_DIR" 2>/dev/null)" ]; then
|
|
SESSION_FLAGS="$SESSION_FLAGS -c"
|
|
fi
|
|
fi
|
|
|
|
# Capabilities (M5): explicit allowlist or no tools.
|
|
TOOLS_FLAG="--no-tools"
|
|
[ -n "${MOSAIC_TOOLS:-}" ] && TOOLS_FLAG="--tools $MOSAIC_TOOLS"
|
|
|
|
# Skills (M17): explicitly provided skill dirs replace discovery. When none
|
|
# are provided the agent runs with --no-skills (nothing ambient to find).
|
|
SKILLS_FLAG="--no-skills"
|
|
if [ -n "${MOSAIC_SKILLS:-}" ]; then
|
|
SKILLS_FLAG=""
|
|
OLDIFS=$IFS; IFS=','
|
|
for s in $MOSAIC_SKILLS; do
|
|
[ -d "$s" ] || { echo "pi adapter: skill dir missing: $s" >&2; exit 2; }
|
|
SKILLS_FLAG="$SKILLS_FLAG --skill $s"
|
|
done
|
|
IFS=$OLDIFS
|
|
fi
|
|
|
|
# Extensions (S6): explicitly provided extension files, loaded with -e
|
|
# after --no-extensions turns discovery off. A missing file refuses here;
|
|
# pi itself also refuses to start on a missing or broken -e (row S0 line 3).
|
|
EXT_FLAGS=""
|
|
if [ -n "${MOSAIC_EXTENSIONS:-}" ]; then
|
|
OLDIFS=$IFS; IFS=','
|
|
for e in $MOSAIC_EXTENSIONS; do
|
|
[ -f "$e" ] || { echo "pi adapter: extension missing: $e" >&2; exit 2; }
|
|
EXT_FLAGS="$EXT_FLAGS -e $e"
|
|
done
|
|
IFS=$OLDIFS
|
|
fi
|
|
|
|
# Mode (M13): interactive TUI or one-shot print.
|
|
PRINT_MODE="-p"
|
|
REQUEST_ARG=""
|
|
if [ "$INTERACTIVE" = "1" ]; then
|
|
PRINT_MODE=""
|
|
else
|
|
REQUEST_ARG="$MOSAIC_REQUEST"
|
|
fi
|
|
|
|
# All flags documented in the pi package README (CLI Reference):
|
|
# -p/--print one-shot mode: print the response and exit (omitted in
|
|
# interactive TUI mode)
|
|
# --system-prompt replace the default prompt with the generated one
|
|
# --no-* no ambient context/skills/extensions/templates/themes
|
|
# EXT_FLAGS the explicitly provided extensions only (-e)
|
|
# SESSION_FLAGS ephemeral | persistent | forked (per env)
|
|
# TOOLS_FLAG per capabilities
|
|
# --offline no startup network operations (update checks/telemetry)
|
|
# --no-approve ignore project-local .pi/ files (settings, SYSTEM.md)
|
|
# whatever trust is saved for the workspace
|
|
PROMPT_CONTENT="$(cat "$MOSAIC_SYSTEM_PROMPT_FILE")"
|
|
set -- \
|
|
--offline \
|
|
--no-approve \
|
|
--no-extensions \
|
|
$EXT_FLAGS \
|
|
$SKILLS_FLAG \
|
|
--no-prompt-templates \
|
|
--no-themes \
|
|
--no-context-files \
|
|
$TOOLS_FLAG \
|
|
$SESSION_FLAGS \
|
|
--provider "$PI_PROVIDER" \
|
|
--model "$PI_MODEL" \
|
|
--system-prompt "$PROMPT_CONTENT"
|
|
# One-shot mode appends -p and the request (both safely quoted);
|
|
# interactive mode appends nothing - clean TUI.
|
|
[ "$INTERACTIVE" = "1" ] || set -- "$@" -p "$MOSAIC_REQUEST"
|
|
exec pi "$@"
|