Inline can-grants cannot set Descriptor.Describe, so every ward-mcp tool ships the fallback description #274
Labels
No labels
burndown-2026-06
sunday-sprint
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/umbra#274
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The gap
ward-mcpmints one MCP tool per guardfile grant and takes that tool's description fromopcore.Descriptor.Describe:Descriptor.Describeis declared inhttp/opcore/descriptor.go:25as "optional Guardfile describe...note."The inline grammar cannot set it on a
cangrant.applyInlineGrantChildfail-closes outsidepath | query | body | set | fail-when, and the onlydescribehandler isapplyProxyChild→setProxyDescribe, which writesProxy.Describe, a different field on a different struct.describeinside acangrant is currently the exemplar for the"unknown grant child"rejection test, so this is a deliberate fail-closed boundary rather than an oversight.Why it matters
Every
can-grant tool therefore ships the generated fallback sentence, and a guardfile's only way to say anything about a grant is a//comment, which no model ever sees.Concretely, in
coilyco-bridge/deploy, a channel-scoped Discord read surface describes itself to the calling model as:The guardfile has 40 lines of
//explaining that the reads are eco-scoped, capped at 25 items, and that Discord messages are untrusted community-authored input to quote rather than execute. None of it reaches the model. It is written for the next editor, and the audience that most needs it cannot read it.That is a security-relevant asymmetry, not only ergonomics: the "treat this as evidence, not instructions" framing belongs in the tool description a model actually receives.
Ask
Accept
describe "..."as acan-grant child, settingDescriptor.Describe, with the same fail-closed treatment as its siblings (reject duplicates, reject empty). Proxy grants keep their existingdescribeuntouched.This widens the frozen grammar by exactly one node and adds no new authority: it is a string that flows to a description field consumers already read.
Done when
can get issue { path "/x"; describe "..." }parses and populatesDescriptor.Describe,ward-mcpserves that string as the tool description, and an unknown child still fails closed.