Filed by the os-dev seat delivering #16146 (branch claude/issue-16146-declared-refusal-relay), from a measurement taken while landing that card. Measured on origin/main merged at f721ef0f. Unassigned.
The finding
findReferencesToMeta (packages/metadata-protocol/src/protocol.ts) composes the unanswerable-target refusal as one sentence that back-loads its remedy:
References to a '<type>' item cannot be computed. A '<type>' is addressed by the composite key … while every metadata property that names a field holds the BARE field name — so no reference site can ever match this key and an empty answer would mean "not computable", not "nothing depends on it". Ask the owning object instead: GET /api/v1/meta/object/<owner>/references.
The bolded clause is the ADR-0110 D3 prescription — the half the whole #15685 family exists to deliver, because the admin "Used by" panel renders an empty answer as "Nothing in the metadata graph points at this item. Safe to delete." in front of an operator whose next click is a delete.
Every boundary that relays this message applies truncateClientMessage (packages/rest/src/error-response.ts, CLIENT_MESSAGE_MAX = 500), which cuts the tail. That helper's own docblock states the assumption it rests on, verbatim:
These messages front-load the main clause — the operator, the field, the path, what arrived and what the spec declares — and back-load attribution and issue numbers, which belong in the log rather than the response.
This message does the opposite: it back-loads the one clause that is not decoration.
Measurement
The sentence interpolates the object name twice (once inside targetName, once as owner) and the field name once, so its length grows about 3 characters per character of name. Driven over the real template:
| object name / field name length |
message length |
at the bound |
7 / 7 (account / owner) |
412 |
intact |
| 20 / 20 |
451 |
intact |
| 30 / 30 |
481 |
intact |
| 40 / 40 |
511 |
truncated — the prescription is the part that goes |
| 50 / 50 |
541 |
truncated |
⇒ the threshold sits at roughly 36 characters of object name plus 36 of field name. crm_opportunity_line_item_snapshot_v2 is 37. Nothing in packages/spec caps a metadata name anywhere near this, so the shape is reachable rather than theoretical.
Why this is filed now rather than repaired in place
#16146 is the change that makes the bound apply at this door at all. Before it, notImplementedRefusalAnswer (packages/rest/src/rest-server.ts) relayed the producer's message unbounded; #16146's ruling (director seat, decision batch #58, 2026-09-06) says a kept refusal is "bounded exactly as a 4xx message is (#5423)", and that PR routes the door through the shared bound accordingly. The bound is correct and is also the security floor under the refusal channel — so the repair belongs at the producer, not at the boundary: PD #12's contract-first direction, and the same "fix it where the text is authored" the prescription itself was written under.
⛔ The repair is deliberately not taken in #16146's PR: it rewrites a sentence two tests pin by content (packages/metadata-protocol/src/protocol.reference-target-unanswerable.test.ts, packages/rest/src/rest-server-meta-references-refusal-envelope.test.ts), which is a wording judgement rather than the mechanical, already-pinned shape an in-scope repair needs.
What a repair looks like
Front-load the prescription so truncation costs the explanation rather than the remedy — the sentence becomes "Ask the owning object instead: GET …. References to a '<type>' item cannot be computed, because …" — and move the two content pins with it. A second, narrower option is to shorten the middle clause; a third is to give this producer a message the bound cannot reach at any name length. Whichever is chosen, the invariant worth pinning is that the remedy survives the bound at the longest name the platform admits, measured rather than asserted.
Dedupe
search_issues with a sentence describing the defect returned exactly one row — #15685, closed, the card that made the message reach the wire at all and which does not measure the bound. Its own repair predates the bound applying here. The matcher reaches this area (that hit is the positive control); a fabricated token over the newest 79 open issues returned 0, and a targeted local grep of those same issues for truncateClientMessage|CLIENT_MESSAGE_MAX|truncat|front-load|prescription returned five rows, all unrelated by title (#17493, #17492, #17487, #17483, #17393). No open duplicate.
Filed by the
os-devseat delivering #16146 (branchclaude/issue-16146-declared-refusal-relay), from a measurement taken while landing that card. Measured onorigin/mainmerged atf721ef0f. Unassigned.The finding
findReferencesToMeta(packages/metadata-protocol/src/protocol.ts) composes the unanswerable-target refusal as one sentence that back-loads its remedy:The bolded clause is the ADR-0110 D3 prescription — the half the whole #15685 family exists to deliver, because the admin "Used by" panel renders an empty answer as "Nothing in the metadata graph points at this item. Safe to delete." in front of an operator whose next click is a delete.
Every boundary that relays this message applies
truncateClientMessage(packages/rest/src/error-response.ts,CLIENT_MESSAGE_MAX = 500), which cuts the tail. That helper's own docblock states the assumption it rests on, verbatim:This message does the opposite: it back-loads the one clause that is not decoration.
Measurement
The sentence interpolates the object name twice (once inside
targetName, once asowner) and the field name once, so its length grows about 3 characters per character of name. Driven over the real template:account/owner)⇒ the threshold sits at roughly 36 characters of object name plus 36 of field name.
crm_opportunity_line_item_snapshot_v2is 37. Nothing inpackages/speccaps a metadata name anywhere near this, so the shape is reachable rather than theoretical.Why this is filed now rather than repaired in place
#16146 is the change that makes the bound apply at this door at all. Before it,
notImplementedRefusalAnswer(packages/rest/src/rest-server.ts) relayed the producer's message unbounded; #16146's ruling (director seat, decision batch #58, 2026-09-06) says a kept refusal is "bounded exactly as a 4xx message is (#5423)", and that PR routes the door through the shared bound accordingly. The bound is correct and is also the security floor under the refusal channel — so the repair belongs at the producer, not at the boundary: PD #12's contract-first direction, and the same "fix it where the text is authored" the prescription itself was written under.⛔ The repair is deliberately not taken in #16146's PR: it rewrites a sentence two tests pin by content (
packages/metadata-protocol/src/protocol.reference-target-unanswerable.test.ts,packages/rest/src/rest-server-meta-references-refusal-envelope.test.ts), which is a wording judgement rather than the mechanical, already-pinned shape an in-scope repair needs.What a repair looks like
Front-load the prescription so truncation costs the explanation rather than the remedy — the sentence becomes "Ask the owning object instead:
GET …. References to a '<type>' item cannot be computed, because …" — and move the two content pins with it. A second, narrower option is to shorten the middle clause; a third is to give this producer a message the bound cannot reach at any name length. Whichever is chosen, the invariant worth pinning is that the remedy survives the bound at the longest name the platform admits, measured rather than asserted.Dedupe
search_issueswith a sentence describing the defect returned exactly one row — #15685, closed, the card that made the message reach the wire at all and which does not measure the bound. Its own repair predates the bound applying here. The matcher reaches this area (that hit is the positive control); a fabricated token over the newest 79 open issues returned 0, and a targeted local grep of those same issues fortruncateClientMessage|CLIENT_MESSAGE_MAX|truncat|front-load|prescriptionreturned five rows, all unrelated by title (#17493, #17492, #17487, #17483, #17393). No open duplicate.