C.O.D.E Dev Environment Runbook

The Phenom C.O.D.E (Collaborative Online Development ENvironment): per-developer browser code-servers with PAI/LifeOS + Code:Talker on the Mac Studio, fronted by an app-rendered Cognito terminal login (ADR-003). Architecture, deployment, operations, and current state.
Audit stamp: Partially Verified, 2026-09-11, Phenom AI Agent
Partially Verified · 2026-09-11 · Phenom AI Agent
Source: Reconciled against the Phenom-earth/sablier-weblogon source of record. The route-to-box wiring flagged [PLANNED]/unimplemented in the 2026-07-11 pass is now shipped and tested: box-router (persona/box-router.ts + persona/boxes.ts with unit tests) landed in #10 (closes the post-login 404), the Cognito id_token to box bridge for Synapse login in #13/#14, and #18 (2026-07-22) added auto-provisioning of a box for any nest-access Cognito member. Verified from the merged, tested access-layer code, not from a fresh live logged-in session this pass, so state stays partial pending a live re-probe. 2026-09-11: documented the Code:Talker roster-avatar sync (sablier-weblogon's persona-provisioner pulling each dev's NEST avatar via phenom-backend's GET /api/codetalker/avatar at login) and fixed a bug in phenom-backend/admin_sandbox/nest-api/src/auth.ts where that self-scoped route was missing from SELF_SERVICE_ROUTES, 401ing the sync for any dev not in the nest-access Cognito group — added a red/green test (auth.test.ts) and confirmed the full 292-test suite passes; fix verified but not yet committed/pushed.
C2PA signed · SanMarcSoft AI content credential

What it is

C.O.D.E — Collaborative Online Development ENvironment. Each developer gets an isolated browser-based code-server (VS Code) on the Phenom Mac Studio (lbb), pre-loaded with the React Native / Expo toolchain, Claude Code + PAI (LifeOS), and the Code:Talker voice bridge running that developer’s persona. Everyone signs in at the single domain code.thephenom.app through an app-rendered Cognito terminal login (ADR-003), then lands on their own code-server.

Distinct from the staging/prod tiers — that runbook is about dev-nest vs nest. This one is the developer workstation platform.

Architecture

code.thephenom.app  ──(cloudflared tunnel "Logan's Mac Studio")──▶  Traefik (:80)
  /login, /assets, /auth/callback   ▶ login-static      (C.O.D.E terminal-login SPA)
  /auth/session, /auth/logout       ▶ cognito-verifier  (id_token → HttpOnly session cookie)
  /enroll/                          ▶ voice-enrollment  (first-login voice clone, gated)
  <authed root>                     ▶ box-router ▶ per-user code-server  [LIVE #10]
                                      (cognito-verify → persona-provision → Sablier wake)
Qwen3-TTS (bare metal, :8880)       ◀ per-developer cloned voices (enrollment)
  • Access layer = Phenom-earth/sablier-weblogon (ADR-003). Runs as a docker-compose stack on the Mac Studio under the builder account’s OrbStack.
  • Auth is app-rendered, not Cloudflare Access. The code.thephenom.app CF Access app is set to bypass; the origin’s cognito-verifier (ForwardAuth) mints/verifies the session cookie against the Synapse-trusted Cognito pool (us-east-1_knEL7cqS3).
  • Voice = bare-metal Qwen3-TTS (Phenom-earth/Qwen3-TTS, MLX, model Qwen3-TTS-12Hz-0.6B-Base-4bit) on :8880, reachable from containers via host.docker.internal. Each developer clones their own voice at first login.

Images (ghcr)

All access-layer images are built for linux/arm64 on ai and pushed to ghcr:

Compose service Image
traefik ghcr.io/phenom-earth/sablier-weblogon
login-static ghcr.io/phenom-earth/code-login
cognito-verifier ghcr.io/phenom-earth/cognito-verifier
persona-provisioner ghcr.io/phenom-earth/persona-provisioner
voice-enrollment ghcr.io/phenom-earth/voice-enrollment
dev code-server ghcr.io/phenom-earth/dev-environment

ghcr pull credential: a classic PAT with read:packages (the sanmarcsoft/github-pat identity smsmatt). Pull auth is written to a temp docker config to avoid the Mac’s locked login keychain.

Deploy / redeploy the access layer

On the Mac Studio, as builder, from ~/PhenomDevEnvironment/sablier-weblogon (branch main):

# docker-compose.override.yml maps build-services to their ghcr image tags, then:
docker compose pull
docker compose up -d --no-build
docker compose ps        # expect 7/7 Up (cloudflared, traefik, login-static,
                         # cognito-verifier, persona-provisioner, voice-enrollment, sablier)

Required .env keys: CLOUDFLARE_TUNNEL_TOKEN, CF_ACCESS_TEAM_DOMAIN, CF_ACCESS_AUD, SESSION_SECRET (session-cookie signing), QWEN3_TTS_DIR (~/PhenomDevEnvironment/Qwen3-TTS), TTS_URL (http://host.docker.internal:8880).

Qwen3-TTS (voice)

Runs as a LaunchAgent, not a container (needs native Apple Silicon / MLX):

cd ~/PhenomDevEnvironment/Qwen3-TTS
scripts/run-cloning-server.sh --install-launchd     # LaunchAgent com.phenom.qwen3-tts, :8880
curl -s http://localhost:8880/health                # status ok; voices:[] until enrollment

The server boots with an empty voice set; a developer’s cloned voice is added at enrollment (<id>_ref.wav dropped in the repo dir, then POST /v1/voices/reload).

Verify

curl -sI https://code.thephenom.app/login          # origin serves the SPA (no CF Access 302)
#   → HTTP/2 200, <title>C.O.D.E // Secure Terminal</title>
# On the Mac (as builder):
docker compose ps                                   # 7/7 Up
curl -s http://localhost:8880/health                # Qwen3-TTS ok

Current state (2026-07-24) & what’s left

Live: the terminal login at code.thephenom.app/login authenticates against Cognito; the access layer + Qwen3-TTS are deployed and healthy. Per-user code-server routing is shipped and tested — the box-router (persona/box-router.ts + persona/boxes.ts, with unit tests) landed in #10 and closes the post-login 404, so a logged-in developer lands in their own persistent box. The Cognito id_token to box bridge for Synapse login shipped in #13/#14, and #18 (2026-07-22) auto-provisions a box for any nest-access Cognito member (no manual box creation). Code:Talker (phenom.codetalker, per-box VS Code extension) is installed and functional: #dev roster, speech-bubble chat, and the Qwen3-TTS/Whisper voice bridge (speak + push-to-talk transcription) all work end-to-end, including PAI DA speaking into #dev via the extension’s speak-queue path. See the welcome guide for the end-user walkthrough and the codetalker-dev repo for the extension itself.

Roster avatars (2026-09-11). Code:Talker itself makes no NEST/Hasura calls — it just renders whatever avatar_url is already on each dev’s Matrix profile. That profile is kept in sync with the dev’s animated NEST avatar by sablier-weblogon’s persona-provisioner (persona/avatar-sync.ts, shipped live behind AVATAR_SYNC_LIVE=1 in #31): at every dev login it fetches the dev’s own presigned avatar from phenom-backend’s GET /api/codetalker/avatar, uploads it to Synapse media, and PUTs it onto the dev’s own Matrix profile. That endpoint is self-scoped to the caller’s own token sub (the same pattern as /api/users/me), which matters because dev-fleet devs are not all nest-access operators — this pass found and fixed a gap where /api/codetalker/avatar was missing from auth.ts’s SELF_SERVICE_ROUTES allowlist, so the sync 401’d for any dev outside nest-access. Fixed via TDD (failing test in auth.test.ts, then the SELF_SERVICE_ROUTES entry in phenom-backend/admin_sandbox/nest-api/src/auth.ts), full 292-test suite green. Not yet committed/pushed as of this writing.

Still worth reconciling: the route-to-box wiring the 2026-07-09 audit flagged as unimplemented is now the shipped box-router, but this pass verified it from the merged, tested source rather than a fresh live session, so treat live health as re-probe-on-touch. Also still open: (1) per-user container placement under /Volumes/Orbstack/dev-root/<user>/ on the phenom-access network, reconciling any duplicate scale-to-zero traefik/sablier; (2) Pulse (LifeOS, :31337) proxied per box via code-server /absproxy/31337/.

Why this is a single point of success

code.thephenom.app isn’t just “SSH without SSH keys” — it collapses three separate failure surfaces (build-environment drift, tribal knowledge, and real-time comms) into one login.

One canonical build path. Every developer’s box takes the same internal hop — ssh builder@host.orb.internal — to the same physical Mac Studio, against the same /Users/builder/PhenomApp checkout, the same ~/dev-tools/jdk21, the same ~/Library/Android/sdk. There is exactly one build environment and one toolchain in play, not N laptops with N drifting local Android SDK / Xcode setups. A build fix — like the eas build --local temp-dir relocation bug in PhenomApp#623 — gets diagnosed and fixed once, in one place, instead of re-litigated per laptop.

PAI + shared team-memory. Each box runs its own persistent Claude Code / PAI session — the developer’s own DA. All of those sessions read and write the same layered team-memory store (ChromaDB-backed, phenom-chromadb): a private per-developer layer for day-to-day notes and hypotheses, and a shared TEAM layer for confirmed knowledge. validation-status tracks hypothesisobserved-oncereproduced, and promotion to the team layer happens at reproduced. Concretely: if one engineer’s Claude session on the shared build box discovers that raw Gradle builds need SENTRY_DISABLE_AUTO_UPLOAD=true (because they don’t inherit eas.json’s env block), and that lesson gets promoted — team-memory add lesson "..." --status reproduced or team-memory promote <id> — every other developer’s DA can pull it straight out with team-memory query "..." or team-memory brief, instead of every box’s DA rediscovering the same gotcha independently.

Code:Talker / #dev. The same boxes carry the Code:Talker extension: a live, TTS-voiced chat panel wired to the shared #dev Matrix/Synapse room. It’s the fast counterpart to team-memory — an engineer can say out loud that they just found the fix and have it spoken into #dev, and any PAI DA present can speak back into the room in real time. team-memory is the durable, queryable version of the same propagation; Code:Talker is the live, social version. Same knowledge, two speeds.

One build environment, one durable knowledge store, one live channel — all reachable from the same box.

Access to the box

Day-to-day build work does not mean SSHing from a developer’s own laptop straight to the Mac Studio. The flow goes through the box:

  1. Open code.thephenom.app, sign in via the Cognito terminal login, and land in your own per-user code-server box — a container, not the bare host.
  2. From that box’s integrated terminal, SSH into the actual host: ssh builder@host.orb.internal. This lands in the shared builder account: /Users/builder/PhenomApp (checkout), ~/dev-tools/jdk21, ~/Library/Android/sdk.
  3. Run native Android/iOS builds from there, in place, under builder — never relocated to a temp directory the way eas build --local relocates a project. That relocation path is known broken: it bakes an absolute path to a DOM component during bundling that breaks once Expo copies the project to a temp dir mid-build (see Local Build Box and PhenomApp#623).