config/live — a runtime-config flip, app-cached (picked up within the cache TTL), no deploy. One live pair at a time; the prior edition is superseded. The decision is an explicit human act — the advisory sim-score never auto-promotes (I8 / I10).1config/live for every reader at the next cache refresh. No deploy. One live pair at a time.config/live via getLivePrompt() / getLiveCorpus() — byte-identical baseline.5prompt.js + voice-feedback.md (a recorded reconcile intent, for version control — cf. web-pilot-reconciliation.md).7promptVersionId and corpusVersionId — never a prompt or corpus alone.4 The ledger is append-only; superseded editions are struck, never deleted — the run-of-record stays complete.
config/live { promptVersionId, corpusVersionId, staticBlock, voiceLayer } (a runtime-config flip, app-cached, no deploy). One live pair at a time; supersede-prior; full audit trail. Gated to roleOf(email)==='pioneer' — Antano & Harini only.ground(retrieval) in prompt.js) formats whatever the corpus retrieval exposes. So what goes live is a pinned (prompt × corpus) pair; every iteration / edition stamps both promptVersionId and corpusVersionId. The lock is compatibility-guarded: permitted only if the prompt's required corpus fields ⊆ the corpus version's retrievalInterface — e.g. a prompt that reads meta_scope_shift cannot be locked against a corpus that doesn't expose it.P.buildPayload, neo.retrieve), reused, never re-implemented. Both the chat path and the simulator read config/live via getLivePrompt() / getLiveCorpus() as the locked baseline, so anything tuned on the Bench is byte-identical to what ships. If they could diverge, the simulator would be a toy.prompt.js (the static + voice blocks) and voice-feedback.md (the accumulated voice-layer corrections) — so version control and the reconcile pass (web-pilot-reconciliation.md) always match what's live. The runtime flip is instant; the mirror is the durable record (reconciled manually).