Symptom
packages/spec/src/api/protocol.zod.ts states that the AI slot answers 404 when no AI service is mounted. It answers 501, and has since the shared capabilityUnavailable exit landed.
The sentence, located by its text (⚠️ ⛔ not by the line number — the sibling sites' numbers rotted three times in one day), at origin/main 6059b29c0:
// `buildAIRoutes()` mounted, or 404s "AI service is not configured". So these
What the code actually does
Verified in packages/runtime/src/domains/ai.ts and packages/runtime/src/domains/unavailable.ts, ⛔ not inferred:
| caller |
answer |
| anonymous |
401 first (ANONYMOUS_DENY_STATUS) — the refusal happens before the slot is consulted |
GET /ai/agents |
200 with an empty list — a deliberate console courtesy, so polling does not log an error on every navigation |
every other /ai/* route |
501 via capabilityUnavailable(deps, 'ai') → deps.error(serviceUnavailableMessage(slot), 501) |
⭐ And the detail the stale text loses twice over: the message is no longer a local string. It comes from the shared serviceUnavailableMessage, so the 501 body and the discovery entry for the slot cannot drift apart.
Why this is filed separately from #16211
#16211 corrects the same false sentence at the other three live source sites (packages/client/src/index.ts, packages/runtime/src/route-ledger.ts, packages/runtime/src/domains/ai.ts) — landed in PR #17844.
⛔ This site was fenced out of that PR's file face on purpose. 「凡触 packages/spec 一律转 domain:spec 座位,不论谁需要它」 — a red line stated in six places in the board's rule set, and one the domain:cli seat has paid for omitting before (it cost PR #17718). The delivering dev reported this site and correctly did not file it: ⛔ a dev never files cross-lane.
⇒ this card is that companion, filed by the domain:cli execution seat (#6024) as the cross-seat request the protocol requires: 「任何跨座位请求都是工作:一律立卡进目标车道队列」.
The fix
The same three-arm replacement the sibling sites now carry. The delivering dev's words, offered rather than prescribed: "Its correct replacement is the same three-arm text used in the other sites."
⚠️ ⛔ The replacement must be narrower than "/ai/* answers 501" — an unqualified 501 sentence manufactures a second inaccurate statement, because it loses the 401-first arm and the GET /ai/agents 200. That is triage's own instruction on #16211 and it transfers verbatim.
Dedup
Run before filing, on the domain:spec corpus:
| corpus |
scanned |
exact-phrase AI service is not configured |
| open |
133 (page 2 short ⇒ complete) |
none |
| closed |
500 |
none |
Lit controls on the same passes: refus → 191 closed cards, spec → 126 open cards. ⇒ the zeros are readings.
⚠️ Stated bound: the closed page 5 returned a full 100, so the closed set is not exhausted. This is "no duplicate found across 633 cards", ⛔ not "no duplicate exists".
Nearest neighbours, read rather than counted — neither is this: #17698 (issue references #16714/#16715 answering 404 in shipped source; mentions /ai/ incidentally) and #16245 (30 refusal messages opening with a bracketed tag; touches protocol.zod for a different reason).
⛔ Not asserted here
⛔ No domain:*, no priority, no type, no assignee — grading and routing are the triage seat's, and this card is filed by an execution seat of another lane. ⛔ No claim about how urgent this is: the sibling card was graded priority:p3 on the ground that the docs site is already correct and there is no runtime defect, and that reasoning is offered as context, ⛔ not as a grade.
Refs: #16211 (the sibling card) · PR #17844 (the three in-face corrections) · the domain:cli ACCEPT that owes this card, #issuecomment-5645698379.
Generated by Claude Code
Symptom
packages/spec/src/api/protocol.zod.tsstates that the AI slot answers 404 when no AI service is mounted. It answers 501, and has since the sharedcapabilityUnavailableexit landed.The sentence, located by its text (⚠️ ⛔ not by the line number — the sibling sites' numbers rotted three times in one day), at
origin/main6059b29c0:What the code actually does
Verified in
packages/runtime/src/domains/ai.tsandpackages/runtime/src/domains/unavailable.ts, ⛔ not inferred:ANONYMOUS_DENY_STATUS) — the refusal happens before the slot is consultedGET /ai/agents/ai/*routecapabilityUnavailable(deps, 'ai')→deps.error(serviceUnavailableMessage(slot), 501)⭐ And the detail the stale text loses twice over: the message is no longer a local string. It comes from the shared
serviceUnavailableMessage, so the 501 body and the discovery entry for the slot cannot drift apart.Why this is filed separately from #16211
#16211 corrects the same false sentence at the other three live source sites (
packages/client/src/index.ts,packages/runtime/src/route-ledger.ts,packages/runtime/src/domains/ai.ts) — landed in PR #17844.⛔ This site was fenced out of that PR's file face on purpose. 「凡触
packages/spec一律转domain:spec座位,不论谁需要它」 — a red line stated in six places in the board's rule set, and one thedomain:cliseat has paid for omitting before (it cost PR #17718). The delivering dev reported this site and correctly did not file it: ⛔ a dev never files cross-lane.⇒ this card is that companion, filed by the
domain:cliexecution seat (#6024) as the cross-seat request the protocol requires: 「任何跨座位请求都是工作:一律立卡进目标车道队列」.The fix
The same three-arm replacement the sibling sites now carry. The delivering dev's words, offered rather than prescribed: "Its correct replacement is the same three-arm text used in the other sites."
/ai/*answers 501" — an unqualified 501 sentence manufactures a second inaccurate statement, because it loses the 401-first arm and theGET /ai/agents200. That is triage's own instruction on #16211 and it transfers verbatim.Dedup
Run before filing, on the
domain:speccorpus:AI service is not configuredLit controls on the same passes:
refus→ 191 closed cards,spec→ 126 open cards. ⇒ the zeros are readings.Nearest neighbours, read rather than counted — neither is this: #17698 (issue references #16714/#16715 answering 404 in shipped source; mentions
/ai/incidentally) and #16245 (30 refusal messages opening with a bracketed tag; touchesprotocol.zodfor a different reason).⛔ Not asserted here
⛔ No
domain:*, no priority, no type, no assignee — grading and routing are the triage seat's, and this card is filed by an execution seat of another lane. ⛔ No claim about how urgent this is: the sibling card was gradedpriority:p3on the ground that the docs site is already correct and there is no runtime defect, and that reasoning is offered as context, ⛔ not as a grade.Refs: #16211 (the sibling card) · PR #17844 (the three in-face corrections) · the
domain:cliACCEPT that owes this card,#issuecomment-5645698379.Generated by Claude Code