Reviewed mission goals and swap context.
UnderstandOutlined features and parallel investigations.
PlanAnalyzed latency and reasoning frame issues with GLM models.
UnderstandTested parameter effects on GLM-4.6.
VerifyPrepared next probe requiring API keys.
PlanStep 2 — Set the worker tab
When the model tabs appear at the top of the TUI, press ctrl+N (or click) to
cycle the Worker tab until it shows:
Claude Sonnet 4.6 (Max sub) reasoning: high
Orchestrator stays on Opus 4.7 high. Validator stays on Sonnet 4.6 high.
Worker is the one to verify.
Step 3 — Paste this brief (verbatim)
MISSION 2 — teachr.live runtime LLM swap: Anthropic Claude → Z.ai GLM
CONTEXT
M1 is complete and committed. teachr.live currently routes Worker /chat
to Anthropic Claude. We're switching the runtime LLM (what students
hit when they use the deployed app) to Z.ai GLM-5.1 for ~10x cost
reduction. The mission's build-time workers continue using Claude
Sonnet 4.6 high (proven from M1) — that's unrelated to this swap.
KEEP UNCHANGED
CHANGE (in repo code only)
Z.AI API SPEC (already verified working with my key)
VALIDATION CONTRACT UPDATES
ANTI-HALLUCINATION RULES (carry forward from M1)
WORKER MODEL CONFIG (DO NOT CHANGE)
MILESTONE STRUCTURE
Single milestone (M-LLMSWAP). Six features, each with a real git commit:
F1. Worker /chat refactor
- Modify worker/src/routes/chat.ts: swap upstream URL, auth header;
keep streaming passthrough discipline (no buffering)
- Update worker/src/index.ts Env type: ANTHROPIC_API_KEY → ZAI_API_KEY
- Update worker/.dev.vars.example
- Update worker/wrangler.toml comment
- Update worker/tests/passthrough.test.ts assertions
- Local smoke: npm test passes
- Commit: "M2/F1: swap chat route upstream to Z.ai GLM"
F2. Swift LLM request body refactor
- Rebuild request body in OpenAI Chat Completions format
- System prompt placement matches OpenAI convention (first message
role=system)
- Auth path stays: Worker injects bearer; Swift sends to Worker as before
- Commit: "M2/F2: Swift LLM request body for OpenAI shape"
F3. Swift SSE parser refactor
- Parse OpenAI delta events: choices[0].delta.content
- Handle [DONE] sentinel
- Preserve sentence-chunked streaming downstream into ElevenLabs
- Update unit tests
- Commit: "M2/F3: SSE parser for OpenAI delta format"
F4. Persona verification against GLM-5.1
- Run a fixture test through the new pipeline (no live mic)
- Compare GLM-5.1 output against rubric in
docs/persona/example-exchanges.md
- If GLM drifts from the persona, document required tweaks but DO NOT
modify docs/persona/system-prompt.md without explicit user approval
- Commit: "M2/F4: persona verification report on GLM-5.1"
F5. Validation contract amendment
- Update validation-contract.md: replace Anthropic-specific language
with provider-agnostic terms
- Re-run validation/scripts/build-smoke.sh
- Update validation/M1-drift-report.md with provider-swap addendum
- Commit: "M2/F5: validation contract provider-agnostic"
F6. Local end-to-end smoke + latency capture
- Run worker locally via wrangler dev with ZAI_API_KEY in .dev.vars
- Run F9 build smoke from M1
- Single round-trip fixture test: Swift app → Worker → Z.ai → Swift
- Capture latency (median + p90) per hop
- If median > 1000ms, attribute to TTS/LLM/STT and surface; do NOT
silently fail
- Commit: "M2/F6: end-to-end Z.ai smoke + latency report"
OUT OF SCOPE
wrangler deploy manually)wrangler secret put manually withPUSH BACK ON
Begin Step 1 (Context restate) and walk through the framework.
Press Enter.
Step 4 — Argue with the orchestrator on Step 1-4 like you did for M1
Same playbook. Approve only when the plan is tight. Then it runs.
Tell me when you've pasted, and I'll watch the proxy log + commits as it goes.
Option 1 — M2 creates its own validation-contract.md, provider-agnostic
from day one. M1 contract stays sealed and untouched.
REASONING
DERIVATION RULES
M1 DRIFT REPORT ADDENDUM
REPO-LEVEL CONTRACT (optional, only if it makes sense to you orchestrator)
Continue with the next question.
Paste it. The orchestrator should now have enough to draft the mission
proposal. Tell me what comes next — likely either a final clarifying question
or the full proposal for your approval.
continue
All mission artifacts are authored. Pausing for your prerequisite per your post-approval comment. Confirmation of (a)-(d):
(a) M2 mission directory created
/Users/gaganarora/.factory/missions/dc819efb-a77f-431b-ab96-1fabff0e7a65/├── AGENTS.md 9.5KB├── features.json 20.7KB (5 features, F1-F5)├── init.sh 3.2KB (executable)├── library/│ ├── architecture.md│ ├── environment.md│ └── user-testing.md├── mission.md 18KB (auto-created on accept)├── model-settings.json├── services.yaml 1.2KB├── skills/│ ├── code-refactor-worker/SKILL.md│ ├── contract-worker/SKILL.md│ └── live-smoke-worker/SKILL.md├── validation-contract.md 17.8KB (35 assertions)└── validation-state.json 2.2KB (35 IDs pending)(b) validation-contract.md provider-agnostic from day one — assertions are organized into 7 areas + cross-area. Provider-specific language is confined to: Area A (Worker /chat route — Z.ai endpoint), Area B (Swift LLM client — glm-5.1 model literal), and Area G (latency harness — same model literal). All other areas use generic terms (LLM upstream, OpenAI-compatible streaming, delta.content channel). F4 worker explicitly re-verifies this and returns to me if it finds leakage I missed.
(c) features.json has F1-F5 with correct fulfills coverage — coverage check just ran:
Contract assertion IDs: 35Distinct fulfills IDs : 35Total fulfills entries: 35State assertion IDs : 35
DUPLICATE fulfills: NONEUNCLAIMED: NONEORPHAN: NONECONTRACT vs STATE: NONE
Per-feature fulfills: F1-worker-chat-upstream-swap 6 F2-swift-openai-shape-atomic 11 F3-persona-verification-eval 7 F5-worker-boundary-latency-capture 6 F4-validation-contract-amend-and-drift-addendum 5Order in array: F1 → F2 → F3 → F5 → F4 (F4 last so its M1 drift addendum can cite F3's verdict and F5's latency report).
(d) Worker model
{ "workerModel": "custom:Claude-Sonnet-4.6-(Max-sub)-5", "workerReasoningEffort": "high", "validationWorkerModel": "custom:Claude-Sonnet-4.6-(Max-sub)-5", "validationWorkerReasoningEffort": "high", "skipScrutiny": false, "skipUserTesting": false}Sonnet 4.6 (Max sub) at high reasoning, both worker and validator. M1 lesson preserved.
Per your post-approval comment, the next step is yours:
Once (a)-(d) confirmed, I drop the Z.ai key into
worker/.dev.varsand F1 may begin.
When you've dropped ZAI_API_KEY=[REDACTED] value> into /Users/gaganarora/Desktop/my projects/teachr.live-wt-mission-1/worker/.dev.vars, reply "key dropped" (or anything equivalent) and I'll start the mission.
Note: F1 (npm test) does not technically require the key — vitest mocks fetch. But F3 and F5 do, and init.sh will warn if the key is missing on every worker session. Cleanest is to drop it now so you don't get pinged twice.
"key dropped
/Users/gaganarora/.factory/missions/dc819efb-a77f-431b-ab96-1fabff0e7a65/├── AGENTS.md 9.5KB├── features.json 20.7KB (5 features, F1-F5)├── init.sh 3.2KB (executable)├── library/│ ├── architecture.md│ ├── environment.md│ └── user-testing.md├── mission.md 18KB (auto-created on accept)├── model-settings.json├── services.yaml 1.2KB├── skills/│ ├── code-refactor-worker/SKILL.md│ ├── contract-worker/SKILL.md│ └── live-smoke-worker/SKILL.md├── validation-contract.md 17.8KB (35 assertions)└── validation-state.json 2.2KB (35 IDs pending)Contract assertion IDs: 35Distinct fulfills IDs : 35Total fulfills entries: 35State assertion IDs : 35
DUPLICATE fulfills: NONEUNCLAIMED: NONEORPHAN: NONECONTRACT vs STATE: NONE
Per-feature fulfills: F1-worker-chat-upstream-swap 6 F2-swift-openai-shape-atomic 11 F3-persona-verification-eval 7 F5-worker-boundary-latency-capture 6 F4-validation-contract-amend-and-drift-addendum 5{ "workerModel": "custom:Claude-Sonnet-4.6-(Max-sub)-5", "workerReasoningEffort": "high", "validationWorkerModel": "custom:Claude-Sonnet-4.6-(Max-sub)-5", "validationWorkerReasoningEffort": "high", "skipScrutiny": false, "skipUserTesting": false}