You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(local-coord-mcp): role tiers, supervisor gating, quarantine queue
Tasks #5 + #6. Adds the supervision layer that makes supervised peers
(gemini / codex / vibe by default) safe to have in a shared workspace —
Tier 2+ ops land in a quarantine queue for supervisor review instead of
delivering directly.
FFI changes (local_coord_ffi.zig):
- New Role enum { supervisor, executor, supervised } stored on each Peer.
Default derived from client_kind: claude -> executor, everything else
-> supervised.
- coord_register now takes role_hint as a 2nd arg; ROLE_HINT_DEFAULT=-1
honors client_kind default; role_hint=0 (supervisor) is ALWAYS
rejected — use coord_promote_to_supervisor instead.
- coord_promote_to_supervisor gates supervisor role on the
BOJ_SUPERVISOR_TOKEN env var (constant-time compare) + at most one
supervisor rule. Env var unset = supervisor role unavailable.
- coord_set_role lets the active supervisor reassign other peers'
roles, with protection against demoting the sole supervisor.
- coord_send_gated routes Tier 2+ ops from supervised peers to a
32-entry quarantine queue; returns an encoded request_id (negative
value < -1000) instead of a direct send count.
- coord_review / coord_review_entry / coord_approve / coord_reject
are the supervisor-only review tools. approve delivers the pending
message to its target(s); reject logs the reason without delivery.
- coord_read_peer_role helper for adapter introspection.
Adapter changes (local_coord_adapter.zig):
- coord_register accepts optional `role` JSON field.
- New dispatch handlers for coord_promote_to_supervisor,
coord_send_gated, coord_review, coord_review_entry, coord_approve,
coord_reject.
- coord_review emits a JSON array with request_id + preview;
coord_review_entry returns the full message body.
MCP surface:
- cartridge.ncl declares the 6 new tools with full schemas.
- cartridge.json regenerated.
- mcp-bridge/lib/tools.js declares the same tools to clients.
- mcp-bridge/main.js dispatchTool routes the new names to
dispatchLocalCoord.
Tests (all passing):
- Default role derives from client_kind
- Register rejects role_hint=supervisor (-3)
- Promote contract documented (env-var check behaviour)
- Gated send from supervised lands in quarantine; Tier 0/1 delivers direct
- Supervisor approve delivers the message to the target
- Supervisor reject removes without delivery
- Non-supervisor cannot review/approve/reject (-1)
- Pre-existing send/receive/claim/context/suffix tests updated for new
coord_register signature.
Version bump: 0.2.0 -> 0.3.0 (new API surface).
Remaining for the coord backbone:
- Watchdog TTL on supervised claims (DD-20)
- warn_drift broadcast via Opus review on auto-release (DD-21)
- Quarantine spill to VeriSimDB when in-memory queue full (DD-21)
- VeriSimDB sidecar for durable state (Task #7)
- E2E test across 2 instances (Task #8)
Follows memory/project_coord_supervision_architecture.md.
Design log + rationale: Desktop/COORD-MCP-DESIGN-LOG.md (Parts 3-4,
Appendices A-J).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
"description": "Optional requested role. supervisor is ALWAYS rejected here — promote via coord_promote_to_supervisor. Default derived from client_kind (claude->executor, others->supervised).",
50
+
"enum": [
51
+
"executor",
52
+
"supervised"
53
+
],
54
+
"type": "string"
47
55
}
48
56
},
49
57
"required": [
@@ -152,7 +160,145 @@
152
160
"type": "object"
153
161
},
154
162
"name": "coord_status"
163
+
},
164
+
{
165
+
"description": "Promote this peer to the supervisor role. Requires the BOJ_SUPERVISOR_TOKEN env-var to be set on the server and the presented secret to match. At most one supervisor at a time. Intended for the Opus-tier Claude that holds the veto.",
166
+
"inputSchema": {
167
+
"properties": {
168
+
"secret": {
169
+
"description": "Must match BOJ_SUPERVISOR_TOKEN env var on the server",
170
+
"type": "string"
171
+
},
172
+
"token": {
173
+
"description": "Own session token from coord_register",
174
+
"type": "string"
175
+
}
176
+
},
177
+
"required": [
178
+
"token",
179
+
"secret"
180
+
],
181
+
"type": "object"
182
+
},
183
+
"name": "coord_promote_to_supervisor"
184
+
},
185
+
{
186
+
"description": "Send a message with a declared risk_tier. Tier 2+ from role=supervised peers is quarantined for supervisor review; everything else delivers directly. Returns status:quarantined + request_id when gated.",
187
+
"inputSchema": {
188
+
"properties": {
189
+
"message": {
190
+
"description": "Message content (typically an A2ML envelope per schemas/coord-messages.ncl)",
191
+
"type": "string"
192
+
},
193
+
"risk_tier": {
194
+
"description": "Declared risk tier 0-4 per the risk ladder",
195
+
"maximum": 4,
196
+
"minimum": 0,
197
+
"type": "integer"
198
+
},
199
+
"target": {
200
+
"description": "Peer ID to send to, or '*' for broadcast",
201
+
"type": "string"
202
+
},
203
+
"token": {
204
+
"description": "Session token from coord_register",
205
+
"type": "string"
206
+
}
207
+
},
208
+
"required": [
209
+
"token",
210
+
"target",
211
+
"message",
212
+
"risk_tier"
213
+
],
214
+
"type": "object"
215
+
},
216
+
"name": "coord_send_gated"
217
+
},
218
+
{
219
+
"description": "List all currently quarantined messages awaiting supervisor decision. Supervisor role only.",
220
+
"inputSchema": {
221
+
"properties": {
222
+
"token": {
223
+
"description": "Supervisor session token",
224
+
"type": "string"
225
+
}
226
+
},
227
+
"required": [
228
+
"token"
229
+
],
230
+
"type": "object"
231
+
},
232
+
"name": "coord_review"
233
+
},
234
+
{
235
+
"description": "Read the full message body of a specific quarantined entry. Supervisor role only.",
236
+
"inputSchema": {
237
+
"properties": {
238
+
"request_id": {
239
+
"description": "Request ID from coord_review or coord_send_gated",
240
+
"type": "integer"
241
+
},
242
+
"token": {
243
+
"description": "Supervisor session token",
244
+
"type": "string"
245
+
}
246
+
},
247
+
"required": [
248
+
"token",
249
+
"request_id"
250
+
],
251
+
"type": "object"
252
+
},
253
+
"name": "coord_review_entry"
254
+
},
255
+
{
256
+
"description": "Approve a quarantined message — delivers to target and removes from queue. Supervisor role only.",
257
+
"inputSchema": {
258
+
"properties": {
259
+
"request_id": {
260
+
"description": "Request ID to approve",
261
+
"type": "integer"
262
+
},
263
+
"token": {
264
+
"description": "Supervisor session token",
265
+
"type": "string"
266
+
}
267
+
},
268
+
"required": [
269
+
"token",
270
+
"request_id"
271
+
],
272
+
"type": "object"
273
+
},
274
+
"name": "coord_approve"
275
+
},
276
+
{
277
+
"description": "Reject a quarantined message with a reason — removes from queue without delivery. Supervisor role only. Reason logged for audit.",
278
+
"inputSchema": {
279
+
"properties": {
280
+
"reason": {
281
+
"description": "Reason for rejection (surfaces in audit log)",
0 commit comments