Repository navigation
Description
Part of #1146 (generic OpenAI façades on the server; design: specs/2026-11-01T04-10-00Z_design_openai-facades.md §8/§10 step 3, quirk §9.3). One issue per door front — this is the design-code door's turn under Drew's 2026-11-02 order to fold ALL proxy programs into OpenCode.
Door
bin/design-code-proxy.mjs (developing-today/code), port 18746, design-code-proxy.service active/running (After/Wants codex-proxy). Front: /v1/chat/completions, /v1/models. Backend: virtual design personas routing to codex / antigravity doors + AMR upstream (https://amr-link.open-design.ai/v1 appears in the deployed config as the direct opendesign provider).
Quirk that gates this door (§9.3)
Design-code's model ids are INVENTED PERSONAS — curated primary/fallback recipes plus an injected design system prompt — not upstream models. Façade rule: personas are expressed as routes in model_routes config (the recipe) plus the system prompt supplied by the caller or an agent definition; the façade does not grow a persona concept. This door's front retires only after its persona ids exist as route names.
Current state (verified 2026-11-02)
- The deployed opencode.jsonc's design-code provider blocks on :18746 are currently COMMENTED OUT (four blocks); the AMR upstream is seated directly instead. The service still runs, and OpenClaw's HEARTBEAT.md probes :18746
/v1/modelsas a "lifeline" — a live monitoring consumer even if model traffic is zero.
Work
- Consumer inventory: grep :18746 / DESIGN_CODE_PROXY_PORT + persona model ids across repos, deployed configs, OpenClaw docs/heartbeat.
- Enumerate the persona ids from
bin/design-code-proxy.mjs; express each as amodel_routesentry (+ prompt home) in the deployed config via the normal config workflow; verify each route resolves and completes. - Repoint any front caller (incl. the heartbeat probe) to the façade/routes; live-verify.
- Close the front: unit + bin file removed from developing-today/code via merged PR; switch in the normal queue. Record which personas, if any, were deliberately NOT carried over, with the reason, on Design: generic OpenAI façades on the server — /v1/chat/completions + /v1/responses, one translation layer, proxy doors retire #1146.
Acceptance criteria
- A consumer inventory for :18746 / DESIGN_CODE_PROXY_PORT and the design-code persona ids is recorded (repos, deployed configs, OpenClaw heartbeat probe).
- Every design-code persona id exists as a
model_routesroute name in the deployed config and resolves/completes in a live check, or is explicitly recorded on issue Design: generic OpenAI façades on the server — /v1/chat/completions + /v1/responses, one translation layer, proxy doors retire #1146 as deliberately not carried over, with the reason. - All front callers, including the OpenClaw HEARTBEAT.md :18746 probe, are repointed to the façade/routes and live-verified.
- The design-code front is closed: unit and
bin/design-code-proxy.mjsremoved from developing-today/code via a merged PR.
Activity
dezren39 commentedon Nov 2, 2026
Intake review
Part of epic #1146 (OpenAI façades); design-code is the persona-gated door (§9.3 of the design spec): personas must become route names before the front retires. Filed by the proxy-fold coordinator (agent note on the issue). No open PR references this issue this run. Risks: the heartbeat 'lifeline' probe is a live consumer even at zero model traffic — repointing it is in the AC. Effort l: inventory, route authoring, and cross-repo verification.
— fleet monitor intake pass, 2026-11-02. Labels normalized (kind/source/status/priority/effort) and acceptance criteria appended to the body; original body preserved above the new section.
dezren39 commentedon Nov 2, 2026
Gate 1 — credential story for design-code-proxy (:18746) — BEFORE integration work (#1146 comment 6584974808)
Evidence gathered live on the laptop (amd-6) 2026-11-02 from the door source (
developing-today/codebin/design-code-proxy.mjs, 517 lines, identical in~/git/codeand the deployed~/codetree the unit executes), the live unit, the live process environment, and the backend doors' own sources. No credential values are recorded here — names, locations and ownership only.1. How callers authenticate to design-code itself
It doesn't authenticate them. The server accepts any (or no)
Authorizationheader for local dispatch. The header is only inspected as an AMR key carrier (below): the placeholder tokensdesign-local,local,none,dummy,test,opencodeare explicitly treated as "no key". The commented-out provider blocks in the trackedopencode.jsoncusedapiKey: "design-local"— a placeholder, not a secret. Merge consequence: the façade's own server auth (server password / Bearer, per the #1146 design §2) replaces this; no caller credential migrates, because none exists.2. Credential source today, per upstream
Content-Type/Content-Length— noAuthorizationheader at all. The door rides the codex door's own auth.tryTarget()indesign-code-proxy.mjsbuilds headers{Content-Type, Content-Length}only.https://amr-link.open-design.ai/v1)hasUpstreamKey(): (a) envOPEN_DESIGN_API_KEYorAMR_API_KEYif set (>8 chars), else (b) the caller's ownAuthorization: Bearer <token>(minus placeholders above). If a key is present, the entire request is forwarded verbatim to AMR — no persona prompt injection, no recipe routing; on upstream error it falls back to local dispatch.hasUpstreamKey()+ chat handler. Live check: the running unit'sEnvironment=is onlyDESIGN_CODE_PROXY_PORT/DESIGN_CODE_PROXY_HOST, and the live process environment contains neitherOPEN_DESIGN_API_KEYnorAMR_API_KEY— so today the AMR leg fires only when a caller supplies its own key.The AMR/Open Design key's fleet home is not the door:
secrets/opendesign.sops.yamlin developing-today/code holdsopendesign_api_key(sops-encrypted, at rest), and the OpenCode credential store (opencode.db, read-only check) holds an active credential row for integrationopendesign— that is what the directopendesignprovider (the AMR upstream seated directly in the tracked config,baseURL https://amr-link.open-design.ai/v1, noapiKeyin the tracked block) resolves through the fork's store machinery today.3. Merge pattern once personas are routes
Personas become
model_routeswhose leaves are the providers that already own the credentials:antigravity-direct(:18751, placeholderapiKey: "antigravity-direct-local"in config). Its credential never touchesopencode.db:bin/antigravity-direct.mjsreads the Antigravity CLI's OAuth token set from the OS keyring (Secret Service, servicegemini/ userantigravity) viasecret-tool, caches the access token in memory only, and never writes tokens anywhere.openai-codex(:18744, placeholderapiKey: "codex-local"). The codex door syncs the Codex CLI login (~/.codex/auth.json) into the credential store:bin/codex-proxy.mjssyncCodexTokensToOpenCode()updates the activeopenaicredential row inopencode.dbin-process (node:sqlite), at startup and every 5 minutes — the existing sync-into-store example from Design: generic OpenAI façades on the server — /v1/chat/completions + /v1/responses, one translation layer, proxy doors retire #1146.opendesign, resolving theopendesigncredential row from the store as above.So: read-in-place for antigravity-direct (keyring) and opendesign (store), sync-into-store for codex (existing door sync, unchanged). The persona routes themselves carry no credential material — exactly like every other route in the tracked config.
4. Refresh ownership + failure mode (after the door is gone)
POST https://oauth2.googleapis.com/tokenwith the keyring refresh token and the CLI's client id (Google does not rotate this refresh token, so this never invalidates the CLI's own login — verified in the door's source comments). Owner: the antigravity-direct door, unchanged by this wave. Failure mode if it lapses: antigravity leaves fail, route failover moves to the route's next target; the persona's design prompt and ordering are unaffected.openairow → codex leaves fail → failover to the antigravity leaf, same as the door's fallback today.opendesigncredential (sops file is the at-rest source). Owner: whoever rotates the Open Design key today — the door never owned it. Failure mode:opendesignleaves fail; local-door leaves of the same persona route are unaffected. Note the one behaviour that does not carry over: the door's "caller Bearer key ⇒ verbatim AMR forward, bypassing the persona" path. Under the façade a caller key is the server password, not an upstream key; callers who want raw AMR address theopendesignprovider directly, as the deployed config already does. This is recorded as a named parity diff in Gate 2, not silently dropped.Gate 1 verdict: PASS — every upstream's credential source, merge pattern, refresh owner and failure mode is stated above with evidence. Integration work proceeds on this story.
Merge pull request #1453 from developing-today/feat/1413-persona-routes
dezren39 commentedon Nov 2, 2026
Wave C wrap-up — gates passed, personas landed as routes, door NOT retired (blockers below)
Gate 1 — credential story: PASS
Posted before integration work: #1413 (comment) (no caller auth on the door; no stored AMR key in the door — caller-Bearer passthrough only, live unit env verified empty; routes resolve backend credentials in place: antigravity-direct keyring OAuth, codex sync-into-store, opendesign store row).
#1409 unblock: DONE, issue CLOSED
Code PR developing-today/code#4626 merged (mergeCommit
2f62ce6c900b4572b8a333cee708eacf70e57712), deployed to~/code, service restarted; deployeddesign-code-flashcall dispatched to127.0.0.1:18751in the service journal and returned a well-formed completion. Evidence + closure: #1409 (comment) — #1409 state CLOSED (API-verified).Personas → routes: DONE (11/11 carried over)
Fork support (the gap: routes could not carry a system prompt, and the façade Generate path did not walk route candidates on failure):
0492fcd385c15d996bf04f2f81f1ec30565ca7c2): optionalsystemonmodel_routes(schema → Definition →routing.system); Generate applies it leading the caller's system text on every candidate (door's exact composition) and suppresses the pass-through fast path for such routes; Generate complete/stream now walkrouting.fallbackcandidates in order (stream: pre-emission only), each a ledgered attempt. Tests: core typecheck clean; 327 core tests across the affected files pre-merge (237 in the final merged tree's re-run of the Generate/parity/resolver files), server facade-parity 20, schema config 21 — all pass; OpenAPI regenerated.6f36af73999fbe501aa85c578859c46879bc0849): all 11 persona ids are nowmodel_routesroute names in the trackedopencode.jsoncwith the door's recipes as ordered targets (antigravity legs onantigravity-direct:18751, codex legs onopenai-codex:18744) and the design system prompt verbatim as each route'ssystem. JSONC parse + per-route extraction verified programmatically.opendesignprovider seat (Gate 1 story).Gate 2 — parity: PARITY-WITH-NAMED-DIFFS (one real-gap)
The #1152 suite gained a design-code block (PR #1453,
packages/core/test/facade-parity.test.ts), recorded from the door's code/fixtures plus live recordings taken 2026-11-02: persona inventory (11 recipes, no :18745 leg), non-stream parity (stub + live, usage included), stream grammar parity modulo the door's relayed empty initial role frame, system-prompt composition equality (applyRouteSystemvs the door's prepend), unknown-model 400 and all-backends-fail 502 outcome classes, AMR bypass. The failover walk + prompt application are pinned end-to-end ingenerate-persona-route.test.ts(primary 500 → fallback answers, prompt leading on both candidates, stream + non-stream).named diffs: error envelopes gain the OpenAI
type(additive, §2); stream frame shift by the relayed empty role frame; AMR caller-key bypass (acceptable-by-design, Gate 1). REAL-GAP: persona routes are not advertised in the façade's/v1/models—ADVERTISED_MODELSis hardcoded to the six tier routes, so a persona route resolves/completes by name but is not listed (pinned by a parity test that fails when advertisement is fixed).Live verification (façade side)
Scratch server from the #1453 worktree (real ServerFetch handler, persona-route config, in-memory DB) against the live backends:
design-code-flashnon-stream → 200,FACADE-PERSONA-OK, usageprompt_tokens: 72(the door's same-shaped live call: 73 — the persona prompt is applied);gpt-6-lunastream → 200, persona model echo, streamed answer. Door-side live calls (pre-retirement baseline) are in the #1409 evidence.Consumer inventory for :18746 (AC)
opencode.jsonc: the design-code provider blocks are commented out (directopendesignseat active instead) — no live model caller there.home/openclaw/workspace/HEARTBEAT.mdprobeshttp://127.0.0.1:18746/v1/modelsas a lifeline;home/openclaw/workspace/TOOLS.md+README.mddocument the door;home/openclaw/default.nixlists the unit among gateway dependencies and in the gateway prompt's proxy list.home/common/default.nix: thedesign-code-proxyunit definition + a manual wrapper bin.Retirement: NOT done — precise blockers
systemfield) — the normal switch/rollout ordering owns that step.With those two cleared: repoint
HEARTBEAT.md's probe to the façade/v1/models, remove the unit +bin/design-code-proxy.mjsvia a code PR, and this issue closes. The door stays running until then (service verified active after the repoint deploy).merge: origin/main into feat/1155-muse-attestation (resolve generate.…
Merge pull request #1465 from developing-today/fix/1413-models-advert…
developing-today commentedon Nov 3, 2026
Retirement blocker #1 is removed: persona routes are now advertised at
/v1/models.PR #1465 — "fix(facade): advertise configured model_routes at /v1/models, not a hardcoded list" — merged via merge commit
24ec863054488692e8906f1a5e5061a487d06018(merged by developing-today[bot] at 2026-11-03T00:16:04Z; merge verified by API read-back).Next retirement step per the sequence recorded earlier in this issue: deploy a production server build containing this merge, then proceed with the repoint / zero-traffic window.
dezren39 commentedon Nov 3, 2026
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 7158 (triage, queued, priority 30) in repo-health-opencode-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03
dezren39 commentedon Nov 3, 2026
🤖 Agent note · triaged — CONFIRMED live, door front still standing; work is code-repo side
8e151e89):bin/design-code-proxy.mjsstill exists in developing-today/code (with its tests) and code search finds 11 references to18746there, including.opencode/opencode.jsonccaller config andbin/muse-proxy.mjs. The front has not been repointed or removed.dezren39 commentedon Nov 3, 2026
Update 2026-11-03: Drew ordered the design-code persona set removed outright — he does not run design personas ("the only design thing I have is opendesign because it has that name").
Done in developing-today/code PR anomalyco#5106 (merged
d6bf024a4a3d267f1043e1e3ca1e1b8a5d64474b), adopted on the laptop and verified live against the standing server:system, are deleted from the tracked config.The persona half of this issue's premise is therefore closed by removal rather than migration. The door program itself (code: bin/design-code-proxy.mjs) still exists; its retirement belongs to the door-retirement line, not this change.