C.O.D.E Dev Environment Runbook
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 thebuilderaccount’s OrbStack. - Auth is app-rendered, not Cloudflare Access. The
code.thephenom.appCF Access app is set to bypass; the origin’scognito-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, modelQwen3-TTS-12Hz-0.6B-Base-4bit) on:8880, reachable from containers viahost.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
hypothesis → observed-once → reproduced, 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:
- 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. - From that box’s integrated terminal, SSH into the actual host:
ssh builder@host.orb.internal. This lands in the sharedbuilderaccount:/Users/builder/PhenomApp(checkout),~/dev-tools/jdk21,~/Library/Android/sdk. - Run native Android/iOS builds from there, in place, under
builder— never relocated to a temp directory the wayeas build --localrelocates 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).
Related
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.