Escalated by the domain:cli seat out of #14704 (PR #15065). ⭐ The dev refused a clause of its own dispatch and escalated rather than guessing, and the refusal is correct — I verified the load-bearing measurement myself before writing this card.
Why this card exists
#14704's dispatch — and the triage comment it inherited the clause from — told the implementer to converge DUPLICATE_RECORD onto the shared two-read message rule "rather than keeping its local guard". That instruction rested on a premise, and the premise is false.
Triage's stated reason: the guard exists "specifically so a sandbox-thrown registered code keeps the unwrap door's sentence". The effect is right. The mechanism is not what that sentence implies:
packages/runtime/src/sandbox/quickjs-runner.ts:1568
constructor(message, innerMessage?, info?) {
super(message);
this.name = 'SandboxError'; // ← UNCONDITIONAL, the line after super()
if (info?.code) this.code = info.code; // ← conditional
if (info?.fields) this.fields = info.fields; // ← conditional
…
}
⇒ A sandbox body throwing the registered code arrives with code === 'DUPLICATE_RECORD' and name === 'SandboxError'. No sandboxed producer can reach that arm at all, by construction. Verified on origin/main with a positive control on the same pathspec.
Two consequences, and they are why this could not be settled inside #14704:
- ⛔ Option C is provably non-viable. Keeping the gate and applying the two-read rule inside the arm gives a check that evaluates never — green forever, protecting nothing, indistinguishable from a real guard to the next reader. AGENTS.md names a phantom check as a defect in its own right.
- ⚠️ The dispatch's clause was not a message-source convergence at all.
structuredCodeAnswer holds two classes of arm, and error-response.ts's own docblock says the difference is load-bearing: relay arms pass error.message through; this is a replace arm — it substitutes a curated sentence, re-spells the wire code to UNIQUE_VIOLATION, and moves the producer's sentence into developerMessage. For a replace arm there is no producer sentence being sourced, so dropping the gate converges which producers the arm claims, not where its sentence comes from. Different question, published wire cost.
The options
A — keep the envelope gate (what PR #15065 ships). #14389 §5 stands unchanged. A sandbox or plugin producer speaking DUPLICATE_RECORD keeps its own sentence and its own code. If "one rule, one place" should be enforced mechanically, it is enforced by a structural pin — the arm is provably unreachable for a sandbox producer because SandboxError fixes name — not by widening the gate. The omission is disclosed in the new pin file's §6 allowlist rather than left silent.
B — drop the name gate; the arm keys on code alone and its developerMessage reads the shared rule. Reverses #14389 §5 and turns its two pinned cases red on purpose. Wire cost: a sandbox body throwing DUPLICATE_RECORD loses its sentence to the curated one and its code to UNIQUE_VIOLATION; a plugin merely declaring the code loses the same two. ⚠️ Needs its own contract review, and touches a code whose wire spelling is already under an open decision, #14723.
C — keep the gate and apply the rule inside it. Measured non-viable, above.
四维分析
长期健全性 —— 指向 A,而且其余三维不构成反对。 structuredCodeAnswer 里并存两类臂:relay(转发作者句子)与 replace(替换成平台句子)。两读规则收敛的是句子来源,这个概念只对 relay 臂有定义;对 replace 臂而言根本没有「被取用的作者句子」。所以 B 不是把规则收敛,而是把闸门换掉 —— 换的是「这条臂认领哪些生产者」。在一张讲消息来源的卡里回答这个问题,正是 Prime Directive #12 所警告的「第二份事实上的契约」;而且它在没有任何更高记录的情况下推翻一份 2026-09-02 已过契约复审的裁决,这超出 dev 座位、也超出本 PM 座位的权限。
真实业务需要 —— 未测到,指向 A。 B 会新捕获的那两类生产者,今天拿到的正是 #14389 为它们刻意选择的答案。仓内没有生产者、没有报告、没有卡片要求「用平台句子替换作者句子」。⇒ B 是无拉力的行为扩张。
让 AI 写的应用不易出错 —— 强烈指向 A。 应用作者在 hook 里抛出这个已注册的 code,A 下他拿回自己的措辞;B 下他的句子被静默替换、code 被改写成 UNIQUE_VIOLATION。这是消费方重写作者的声明,正是 contract-first 禁止的方向。⚠️ 更糟的是,B 之后行为取决于一个跨过 VM 边界的对象的 class —— 作者既看不见也控制不了它。
创业阶段范围纪律 —— 指向 A。 A 的成本为零、不增加任何面;B 是带已发布 wire 代价的行为扩张,落在一个拼写本身已在开放决策 #14723 里的 code 上。
建议:A。 ⛔ 若维护者仍要 B,它是一张独立决策卡 + 自己的契约复审,⛔ 不能作为任何 PR 的搭车项。
What is NOT blocked by this
#14704's actual defect — ten code-gated arms shipping the QuickJS debug wrapper as error — is closed and green in PR #15065, which implements option A (i.e. leaves DUPLICATE_RECORD untouched). Landing that PR changes nothing about this question in either direction, so this card does not hold it up.
Refs
Escalated by the
domain:cliseat out of #14704 (PR #15065). ⭐ The dev refused a clause of its own dispatch and escalated rather than guessing, and the refusal is correct — I verified the load-bearing measurement myself before writing this card.Why this card exists
#14704's dispatch — and the triage comment it inherited the clause from — told the implementer to converge
DUPLICATE_RECORDonto the shared two-read message rule "rather than keeping its local guard". That instruction rested on a premise, and the premise is false.Triage's stated reason: the guard exists "specifically so a sandbox-thrown registered code keeps the unwrap door's sentence". The effect is right. The mechanism is not what that sentence implies:
⇒ A sandbox body throwing the registered code arrives with
code === 'DUPLICATE_RECORD'andname === 'SandboxError'. No sandboxed producer can reach that arm at all, by construction. Verified onorigin/mainwith a positive control on the same pathspec.Two consequences, and they are why this could not be settled inside #14704:
structuredCodeAnswerholds two classes of arm, anderror-response.ts's own docblock says the difference is load-bearing: relay arms passerror.messagethrough; this is a replace arm — it substitutes a curated sentence, re-spells the wire code toUNIQUE_VIOLATION, and moves the producer's sentence intodeveloperMessage. For a replace arm there is no producer sentence being sourced, so dropping the gate converges which producers the arm claims, not where its sentence comes from. Different question, published wire cost.The options
A — keep the envelope gate (what PR #15065 ships). #14389 §5 stands unchanged. A sandbox or plugin producer speaking
DUPLICATE_RECORDkeeps its own sentence and its own code. If "one rule, one place" should be enforced mechanically, it is enforced by a structural pin — the arm is provably unreachable for a sandbox producer becauseSandboxErrorfixesname— not by widening the gate. The omission is disclosed in the new pin file's §6 allowlist rather than left silent.B — drop the name gate; the arm keys on code alone and its⚠️ Needs its own contract review, and touches a code whose wire spelling is already under an open decision, #14723.
developerMessagereads the shared rule. Reverses #14389 §5 and turns its two pinned cases red on purpose. Wire cost: a sandbox body throwingDUPLICATE_RECORDloses its sentence to the curated one and its code toUNIQUE_VIOLATION; a plugin merely declaring the code loses the same two.C — keep the gate and apply the rule inside it. Measured non-viable, above.
四维分析
长期健全性 —— 指向 A,而且其余三维不构成反对。
structuredCodeAnswer里并存两类臂:relay(转发作者句子)与 replace(替换成平台句子)。两读规则收敛的是句子来源,这个概念只对 relay 臂有定义;对 replace 臂而言根本没有「被取用的作者句子」。所以 B 不是把规则收敛,而是把闸门换掉 —— 换的是「这条臂认领哪些生产者」。在一张讲消息来源的卡里回答这个问题,正是 Prime Directive #12 所警告的「第二份事实上的契约」;而且它在没有任何更高记录的情况下推翻一份 2026-09-02 已过契约复审的裁决,这超出 dev 座位、也超出本 PM 座位的权限。真实业务需要 —— 未测到,指向 A。 B 会新捕获的那两类生产者,今天拿到的正是 #14389 为它们刻意选择的答案。仓内没有生产者、没有报告、没有卡片要求「用平台句子替换作者句子」。⇒ B 是无拉力的行为扩张。
让 AI 写的应用不易出错 —— 强烈指向 A。 应用作者在 hook 里抛出这个已注册的 code,A 下他拿回自己的措辞;B 下他的句子被静默替换、code 被改写成⚠️ 更糟的是,B 之后行为取决于一个跨过 VM 边界的对象的 class —— 作者既看不见也控制不了它。
UNIQUE_VIOLATION。这是消费方重写作者的声明,正是 contract-first 禁止的方向。创业阶段范围纪律 —— 指向 A。 A 的成本为零、不增加任何面;B 是带已发布 wire 代价的行为扩张,落在一个拼写本身已在开放决策 #14723 里的 code 上。
建议:A。 ⛔ 若维护者仍要 B,它是一张独立决策卡 + 自己的契约复审,⛔ 不能作为任何 PR 的搭车项。
What is NOT blocked by this
#14704's actual defect — ten code-gated arms shipping the QuickJS debug wrapper as
error— is closed and green in PR #15065, which implements option A (i.e. leavesDUPLICATE_RECORDuntouched). Landing that PR changes nothing about this question in either direction, so this card does not hold it up.Refs
classifyDataError's structured-code arms ship the QuickJS debug wrapper aserrorfor a sandboxed producer — the mirror of #11588, on the door #11588 did not touch #14704 / PR fix(rest): the by-id /data door stops shipping the QuickJS wrapper out of a declared-code arm #15065 — the card this was escalated from.mapDataErrorhas noDUPLICATE_RECORDarm: the engine's insert conflict envelope reaches the wire through the generic passthrough, dropping thefieldkey and the user-facing conflict sentence #14389 §5 — the contract-reviewed decision B would reverse; pinned inrest-duplicate-record-arm.test.ts.DUPLICATE_RECORDwhile the whole-request failure on the same route reportsUNIQUE_VIOLATION#14723 — the open decision on this code's wire spelling.handleRouteErroranswer the engine'sDUPLICATE_RECORDenvelope fromresolveErrorResponse's.statuspassthrough —fieldandobjectdropped,mapDataError's structured 409 arms never consulted #14541 / PR fix(rest): consult the bespoke structured arms before the declared-status passthrough, so both error doors answer one refusal with one body #14713 — the sharedstructuredCodeAnswerboth doors ask.