# Fornace pi setup & update

Ecosystem source repository: `~/works/repos/pi-fornace` (GitHub `Fornace/pi-fornace`). The `pi-setup` repository is a deployment mirror of `setup/public/`.

You are setting up or updating this machine's pi installation to match Francesco's reference setup. Work autonomously, adapt paths to this machine, skip what is already present, and report anything that needs a human (credentials, OAuth).

## Versioning & The Update Flow

To support frequent updates without re-downloading unchanged components, the setup follows a strict versioning protocol using `manifest.json`.

1. **Fresh setup:** the page's setup one-liner, or `/fornace install` inside an already running Pi after the Fornace extension is present.
2. **Update:** `/fornace update` inside Pi. This reruns the hosted idempotent setup and always reconciles DramaFoundry, even when its account already exists.
3. **Fetch Remote Manifest**: Always start by fetching `https://onboarding.fornace.app/manifest.json`.
4. **Read Local Manifest**: Check for `~/.pi/agent/pi-setup-manifest.json`.
5. **Compare**: Compare the version strings of each component in the remote manifest against the local one.
6. **Apply Changes**: If a component's version differs (or if the local manifest doesn't exist), download its path and follow the component-specific installation steps below. If the version matches, skip it.
7. **Update Manifest**: Once all updates are applied, save the new remote `manifest.json` to `~/.pi/agent/pi-setup-manifest.json`.

## Source of truth

All assets are hosted at `https://onboarding.fornace.app` and cataloged in the manifest:

- `/pi-extensions.zip` — local extensions (`fornace-setup` for `/fornace install|update`, cmux-session), agent roster in `agents/`, theme in `themes/`, `keybindings.json`, and the `guides/` the global rules link to. The runtime bundles the RTK rewrite handler itself, so the zip's standalone `rtk.ts` is never unpacked.
- `/agents-global.md` — the Fornace global operating rules as a managed block. IMPORTANT: make this block the TOP of `~/.pi/agent/AGENTS.md` (back up any existing file first; replace an existing managed block in place, otherwise prepend; never drop the user's own rules below the block). These rules matter: lean operating mode, fail loud, study before acting, brand rules, shared knowledge.
- `/pi-skills.zip` — the full reference skill library: the 23-skill ads suite, campaign-manager, scrapling-official, hammersmith, fornace-browser, task-observability, autonomous-qa, ui-audit, native-inference-perf, pi-mantice, fresh-docs, stripe, vercel and the rest of the cataloged folders (the `monitor` skill ships inside the pi-process-monitor package). The `pi-mantice` skill is reference prose only; `pi-mantice` the plugin is retired.
- `/mcp.json` — native MCP server config, `mcpServers` only, empty by policy: CLIs replace MCP (scrapling CLI, honcho CLI, Stripe CLI, Trigger.dev CLI/REST, wrangler, Lighthouse/playwright-core). The setup never adds or removes servers. Adapter-owned fields a legacy `pi-mcp-adapter` wrote into `mcp.json` (`settings`, `imports`, `claudePlugins`, legacy `mcp-servers`) migrate into `mcp-adapter.json`, the adapter's own config file since pi-mcp-adapter 4.0; conflicts fail loud and every server survives.
- `/settings.json`: settings values to merge (contains `ASK_FRANCESCO` placeholders for `banana.apiKey` and `cavallo.apiKey`). `defaultTools` enables `+codemode` and `+tool_search`. The theme is `notte`, a package-owned near-black palette with light-blue accents. The runtime installs and enforces it on startup and updates. `enabledModels` keeps the stable `mantice/fornace-*` route aliases exact, adds the runtime's virtual `fornace-router/auto` router, and uses vendor wildcard patterns (`google/gemini-*`, `openai-codex/*`, `openai/*`) because vendor model IDs come and go.
- `/configure-pi.mjs`: the shared configuration helper `configure_pi` (below). It ships as a digest-bound ecosystem binary at `~/.local/lib/fornace/configure-pi.mjs`, like every other binary, and has no curl fallback: a missing helper is a failed setup.
- `/fornace-matchbox.mjs`, `/matchbox-device.mjs`, `/matchbox-login.mjs`, `/matchbox-cli-utils.mjs`: the Matchbox CLI and its local modules. Verify all four sha256 values against the manifest. Install them together in `~/.local/bin`; the command file is mode 755 and helper modules are mode 644. A missing asset or digest is a failed setup.
- `/pi-skills.zip` makes Camoufox the local QA/UI default and includes `camoufox-agent` for persistent background assistance. `/browser-setup.sh` and `/browser-verify.py` install and verify the isolated browser environment from `ecosystem.json` `browserTooling`. Camoufox uses the Playwright Firefox API. Chromium downloads currently serve stock Scrapling `fetch` and `stealthy-fetch`, not the QA default; its documented Camoufox integration requires a custom session rather than a CLI flag. No global pip changes or account-profile resets.
- `/dramafoundry-install.sh`: idempotent DramaFoundry account and skill installer. Both fresh setup and update run it with the teammate's `FORNACE_TOKEN`; it exchanges that team identity for a persistent DramaFoundry credential and installs the `dramafoundry` skill.

Version numbers in the hosted manifest describe published artifacts for change detection and integrity verification. They are not install constraints: npm packages use `@latest`, and CDN runtime and native artifacts come from the freshly fetched release catalog.

## Onboarding order

The setup page walks a nontechnical teammate through nine numbered steps. Keep any guidance you give in this same order:

1. bootstrap, pasted in the existing Mac Terminal
2. open cmux (from now on, every command is pasted in cmux)
3. ChatGPT browser login, started from cmux
4. gateway key from the @fornaceaibot Telegram bot (/key), pasted into the page. Current keys may start with `mantice_` or `sk-`.
5. Fornace setup one-liner (the Copy setup command), pasted in cmux
6. Matchbox login when needed. The unified installer performs it during step 4; an enrolled Mac is verified without another browser login. The authenticated page's **Authorize** button confirms the displayed terminal key. Enrollment finishes inside the proof-bearing handoff, with no Access service token on the Mac.
7. Google consent, started from cmux
8. start pi in cmux
9. the main prompt, pasted in pi

## Packages to install

The package list lives in `/ecosystem.json` under `packages` (and additionally
`pi-fornace` from `runtime`). Read it from there, never from this document: a
copy here drifts and a stale copy is a defect. As of `ecosystem.json` v1 that is
`npm:pi-alibaba-models`, `npm:pi-banana`, `npm:pi-cavallo`, `npm:pi-bench` and
`npm:pi-process-monitor`, each resolved from npm's `latest` tag when setup runs.
Run `pi install` for each on every update, including packages already present.

## Fornace token (when the prompt or one-liner includes one)

The user's personal team gateway token may arrive in the prompt ("Token: ...") or
inside the one-liner as `FORNACE_TOKEN=...`. Treat it as a secret: never echo it,
never paste it into shared logs. When present, write it into pi's config directly:

1. `~/.pi/agent/auth.json` (create if missing, back up if present, mode 600 after
   writing): merge JSON entries `"mantice": {"type":"api_key","key":"<token>"}` and
   `"fornace": {"type":"api_key","key":"<token>"}`, preserving every other provider.
2. `~/.pi/agent/settings.json`: set `banana.apiKey` and `cavallo.apiKey` to the token
   only when they are missing or still the `ASK_FRANCESCO` placeholder; keep any real
   key the user already set. Mode 600 when a token was written.
3. Verify: `curl -sS -o /dev/null -w '%{http_code}' -H "Authorization: Bearer <token>"`
   against `https://llm.fornace.net/v1/models` prints 200. (Note: `pi auth check`
   does not understand package-provided providers like mantice; probe the gateway.)

4. After the gateway probe succeeds, run `/dramafoundry-install.sh update` with the same `FORNACE_TOKEN`. It creates or reconciles the colleague's account through the identity bridge, writes `~/.pi/agent/credentials/dramafoundry.json` with mode 600, and installs the `dramafoundry` skill. A provisioning failure means setup is incomplete and must remain loud.

`setup.sh` performs exactly these edits when run with `FORNACE_TOKEN=<token>`; prefer
giving the user the one-liner over editing by hand. The token never leaves the user's
machine: it is only written into these two local files.

## Google services (per-operator OAuth)

When the user wants Google access (Gmail, Drive, Sheets, Docs, Calendar) or pasted the
pi-setup Step 4 one-liner:

1. Ensure the skills component ran (google-workspace skill present under
   `~/.pi/agent/skills/google-workspace/`).
2. Run `node ~/.pi/agent/skills/google-workspace/scripts/gws.mjs auth login`:
   it opens one browser consent (loopback + PKCE) and stores the user's own
   refresh token in `~/.agent_credentials/google-user-token.json`, mode 600.
   The pi-setup equivalent is `google-auth.sh` (same flow, guarded).
3. All `gws` commands then act as the operator's account (user token wins over
   the service-account path; `GWS_IMPERSONATE` only applies to the SA path).
4. Verify: `gws auth status` shows `logged in as <operator>@fornacestudio.com`.

Never distribute the shared DWD service-account key to operators (2026-09-08
incident rule). Revocation: `gws auth logout` deletes the local file; the Google
side is Account > Security > Third-party access.

## Component Installation Steps

When applying a component from the manifest (whether fresh setup or update), follow these exact rules:

1. **pi binary**: resolve `npm view @earendil-works/pi-coding-agent@latest version` on every setup and update. If Pi is missing or differs, install with `npm install -g --ignore-scripts @earendil-works/pi-coding-agent@latest`; require the launcher selected by PATH to report that resolved release.
2. **Packages**: install the package list above into the user pi directory (`~/.pi/agent`, adapt if `PI_DIR` differs).
3. **Extensions zip**: unzip into the pi directory with overwrite (`unzip -o`) so that `extensions/`, `agents/`, `themes/`, `guides/`, `keybindings.json` land in place, excluding `extensions/rtk.ts`: the runtime owns RTK rewrites, and the standalone rtk extension is a true duplicate handler. Do not overwrite existing agent files without backing them up first. `pi-fornace` owns goals, subagents, the sidebar, identity, routing, memory and RTK rewrites. Install the runtime from `ecosystem.json` (`runtime.path`, verified against `runtime.sha256`) before this step, and let its migration retire any standalone `pi-codex-goal`, `pi-message-sidebar`, `pi-subagent-extension`, `pi-identity`, `pi-frontier`, `pi-mantice` or `pi-hermes-memory` entry from `settings.json` so each handler loads once. The zip keeps the small local extensions (cmux-session and friends; cmux-session owns cmux resume bindings and the lifecycle feed, which the runtime does not duplicate); keep those, and retire only the paths named in `ecosystem.json` under `retiredPaths`.
4. **Global rules (AGENTS.md)**: back up an existing `~/.pi/agent/AGENTS.md` first. The downloaded content between `<!-- BEGIN fornace global rules v1 -->` and `<!-- END fornace global rules -->` is a managed block: replace it in place if already present, otherwise PREPEND the whole downloaded content (markers included) at the very top of `~/.pi/agent/AGENTS.md` and keep the user's own rules unchanged below it. 
5. **Skills zip**: unzip into the pi skills directory with overwrite (`unzip -o skills.zip -d ~/.pi/agent/skills/`). Ensure `autonomous-qa`, `scrapling-official` and `camoufox-agent` land correctly. Never delete skill directories or replace them with symlinks: bytes are preserved. Skills the runtime package also bundles (currently `fornace-work` and `lowswap`) are reconciled by `configure_pi skills` after extensions and skills are unpacked: the bundled runtime copy is the owner and the global copy is excluded from discovery through exact `-skills/<name>` entries in settings `skills`, written only when the runtime is actually installed. Setup and package updates run `install_browser_tooling` from the hosted `ecosystem.sh`. It installs the manifest's full browser dependencies in `~/.local/share/scrapling/venv`, creates `~/.local/bin/scrapling` and `~/.local/bin/fornace-browser-python`, and verifies actual browser launch and DOM execution before claiming readiness. A browser-only update is `sh setup.sh browser`. Reuse existing Camoufox browser assets. Metadata, addons or interrupted downloads without `.0.5_FLAG` are not proof of incompatibility: install into the versioned layout without deleting the cache; restore its marker only after validating a supported browser and executable. Never delete account profiles, switch an account's engine or automate login without the user. The Scrapling CLI replaces the retired Scrapling MCP server. If fornace-browser is included, tell the user a personal `BROWSER_MCP_TOKEN` is required, requested through hermes-sentia (the Sentia Telegram bot) and approved by Francesco; never hardcode or invent tokens.
6. **mcp.json (native MCP, adapter migration)**: `configure_pi mcp` runs on fresh setup and update. Every entry under `mcpServers` survives; the setup never deletes a user server. Adapter-owned fields a legacy `pi-mcp-adapter` wrote into `mcp.json` (`settings`, `imports`, `claudePlugins`) and any legacy `mcp-servers` object move into `~/.pi/agent/mcp-adapter.json` (the adapter's config file since pi-mcp-adapter 4.0; legacy server entries land under its `mcpServers` key, so no server is lost). If `mcp-adapter.json` already defines a different value for a migrated key or server, the step fails loud and nothing is written. If no mcp.json exists, one is created with an empty `mcpServers` object. Backups land next to the originals as `.bak`.
7. **settings.json**: `configure_pi settings` (from `install_settings`) backs it up, then merges the hosted settings. `defaultProvider` and `defaultModel` are suggestions for unset values: fresh installs use `mantice/fornace-flash`; preserve an existing user's provider and model. Hosted values win for `theme`, `defaultTools`, `defaultThinkingLevel`, `enabledModels` and `agents`. Real `banana.apiKey` and `cavallo.apiKey` values survive; hosted structure wins for the rest of those objects. Every other existing key keeps the user's value on conflict, and unknown hosted keys are added as curated defaults. Reconcile `packages` by package name: `pi-fornace` replaces older `pi-mantice` specs plus the standalone goal, sidebar, identity, frontier and memory specs, and the retirement list is `ecosystem.json` `retired`. Leave the `ASK_FRANCESCO` placeholders; do not invent keys. Keep `enabledModels` wildcards, the `fornace-router/auto` virtual router and the `mantice/fornace-*` aliases as shipped; never pin vendor model IDs that can disappear. The theme is `notte`; it is enforced for every installation.
8. **cmux appearance**: merge `{"app":{"appearance":"dark"}}` into `~/.config/cmux/cmux.json`, preserving every other key (back up the file first, create it with `schemaVersion: 1` if absent). The change applies when cmux is next launched. Never replace the whole file: the user's own cmux config must survive.
9. **Matchbox CLI**: fetch the command plus all three `matchbox-*.mjs` helper modules, verify every manifest digest, and install them together under `~/.local/bin`. If that directory is not on PATH, append the export line to `~/.zshrc` once. The teammate runs `fornace-matchbox login` once, or the unified installer starts it, then clicks **Authorize** for their identity in the authenticated page. The browser confirmation binds the displayed key thumbprint; the CLI signs its enrollment proof and the broker completes enrollment inside `/agent/handoff/claim`. Existing device keys are retained. Later calls obtain device-bound short-lived sessions and sign every request automatically. No provider token, Access service token, or operator enrollment code belongs on the teammate's Mac.
10. **DramaFoundry**: run the hosted `/dramafoundry-install.sh update` with the teammate's `FORNACE_TOKEN` on every setup and update, even if the skill archive version is unchanged. A valid existing token is reused; a missing or invalid token is rotated. Require `~/.pi/agent/credentials/dramafoundry.json` mode 600 and `~/.pi/agent/skills/dramafoundry/SKILL.md` present.
11. **Verify**: run `pi --version` and `pi list`, then start a fresh offline Pi RPC process and confirm the runtime's own tools and skills each appear exactly once: `get_goal`, `create_goal`, `update_goal`, `todo_update`, the managed agent tools, the memory tools, `skill:pi-fornace-supervisor-stack` and `skill:dramafoundry`. Load errors must be loud: Pi reports extension failures on stderr with exit 0, so check stderr for load errors rather than trusting the exit code. Existing running sessions require an idle `/reload` or restart.

## Rules

- Never print, log, or transmit API keys or tokens.
- Existing user config wins on conflicts outside the hosted keys listed in step 7; ask before overwriting anything else.
- At the end, output a short summary: what was updated, what was skipped because versions matched, and the manual follow-ups (fornace gateway key from the Telegram bot; one `fornace-matchbox login` if this Mac is not enrolled; `BROWSER_MCP_TOKEN` via hermes-sentia; Stripe CLI installed via `brew install stripe/stripe-cli/stripe` if the stripe skill is used; honcho CLI setup per the honcho-cli skill).
