Add live paired supervision as a room collaboration contract - #6
Merged
Conversation
Pair a user command into a worker Turn and a parallel watch Turn on the same root correlation. Observers get watch/steer instead of the user task, can interrupt the whole worker Turn, and cannot approve native tools or change unrestricted. Co-authored-by: bc1svmes <susyimes@gmail.com>
Prefer the running worker when resolving a watch subject, make new config fields explicit in test runtimes, and drop supervision tables when migration tests rewind older schema versions. Co-authored-by: bc1svmes <susyimes@gmail.com>
The Node 22 installer rewrote optional libc metadata; keep the existing lockfile. Co-authored-by: bc1svmes <susyimes@gmail.com>
There was a problem hiding this comment.
Pull request overview
This pull request adds a “live paired supervision” collaboration contract to GroupX: a single user command can spawn parallel worker Turn(s) plus observer Watch Turn(s) sharing the same rootCorrelationId, where observers can watch bounded milestones and steer (nudge/interrupt) the whole worker Turn without becoming an approval/governance layer.
Changes:
- Introduces
supervision: { observers, mode: "live_steer" }forPOST /api/messages, plus MCP toolswatchandsteerrestricted to Watch Turns. - Adds SQLite schema v8 supervision tables (pairs, pair-turn roles, steer counts) and store/broker plumbing to persist and enforce supervision invariants/limits.
- Updates context/memory/UI to isolate watch briefs + supervision events from room context/compaction/memory while rendering supervision cards in the timeline and adding composer controls.
Reviewed changes
Copilot reviewed 46 out of 46 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| web/styles.css | Adds styling for supervision controls and timeline cards. |
| web/index.html | Adds supervision toggle and observer picker UI elements. |
| web/app.ts | Adds client-side draft supervision payload + UI syncing + supervision event rendering. |
| tests/unit/storage/supervision.test.ts | Adds unit coverage for store-level supervision persistence + steer counts + dated-memory exclusion. |
| tests/unit/storage/sqlite-store.test.ts | Updates recovery/remigration expectations for schema v8 and drops supervision tables in repair flows. |
| tests/unit/memory/supervision-context.test.ts | Verifies watch briefs/supervision events are excluded from room context and adds watch packet note checks. |
| tests/unit/mcp/server/tools.test.ts | Adds MCP tool registration/dispatch tests for watch/steer and forbids caller-supplied from. |
| tests/unit/mcp/server/http.test.ts | Extends HTTP MCP broker stub with watch/steer methods. |
| tests/unit/core/supervision.test.ts | Adds unit tests for supervision brief building + excerpt/tool projection helpers. |
| tests/unit/contracts/supervision.test.ts | Adds contract validation tests for REST supervision and MCP steer/watch inputs. |
| tests/unit/config.test.ts | Asserts new default config values for steer limit and watch timeout. |
| tests/unit/broker/supervision.test.ts | Adds fixture coverage for parallel watch, bounded snapshots, steer interrupt/nudge, limits, and “no approval” invariants. |
| tests/unit/app/context-summarizer.test.ts | Updates summarizer config fixtures to include watchMs. |
| tests/unit/app/adapter-factory.test.ts | Updates adapter factory test fixtures to include watchMs. |
| tests/integration/app-tool-broker-api.test.ts | Adds integration coverage for tool-broker forwarding of watch/steer. |
| tests/integration/app-session-manager.test.ts | Updates session manager integration fixtures to include watchMs. |
| tests/integration/app-runtime.test.ts | Updates runtime integration config to include steersPerSubjectTurn and watchMs. |
| src/storage/types.ts | Extends accept-message/storage interfaces with supervision inputs/results and store APIs for pairs/roles/steer counts. |
| src/storage/sqlite-store.ts | Implements supervision acceptance (watch brief + pair rows) and steer-count + pair role APIs; excludes observer turns from dated-memory sources. |
| src/storage/schema.ts | Bumps schema to v8 and adds supervision tables/indexes. |
| src/memory/types.ts | Adds packetKind to support supervision watch packets. |
| src/memory/context-packet.ts | Adds supervision watch note/section and filters room context messages via isRoomContextMessage. |
| src/memory/context-messages.ts | Introduces isRoomContextMessage to exclude watch briefs (and intended supervision events) from room context. |
| src/memory/context-engine.ts | Switches room message selection logic to isRoomContextMessage and plumbs packetKind. |
| src/mcp/server/tools.ts | Registers watch and steer tools with schemas and “not approval” guidance. |
| src/mcp/server/broker-api.ts | Extends broker API interface with watch/steer. |
| src/core/supervision.ts | Adds supervision constants/types and helpers for bounded excerpts, tool name projection, and watch brief construction. |
| src/core/errors.ts | Adds supervision/steer error codes. |
| src/core/envelope.ts | Adds supervision event types and PublicProvenance.sourceKind = "supervision". |
| src/contracts/validation.ts | Adds public error messages + HTTP 400 mapping for supervision errors. |
| src/contracts/rest.ts | Adds REST request/response schema support for supervision pairs with overlap/uniqueness validation. |
| src/contracts/mcp.ts | Adds MCP schemas + parsers for watch/steer (bounded snapshot + steer request/response). |
| src/contracts/events.ts | Extends provenance schema to include supervision. |
| src/contracts/common.ts | Adds shared limits/defaults for supervision observers/steers. |
| src/config.ts | Adds config fields for steer limit and watch timeout defaults/validation. |
| src/broker/types.ts | Adds broker-facing supervision request shape and watch/steer types. |
| src/broker/broker.ts | Implements supervision dispatch/publish ordering, milestone bus, watchSubject, steerSubject, and observer routing restrictions. |
| src/app/web-broker-api.ts | Forwards REST supervision payload and returns watch turn/event IDs when present. |
| src/app/tool-broker-api.ts | Routes MCP watch/steer via active Watch Turn and blocks send/ask to watched workers. |
| src/app/runtime.ts | Selects supervision watch packet kind for observer turns and wires steer/watch limits from config into the broker. |
| README.md | Documents supervision mode and new MCP tools at a high level. |
| docs/STORAGE_AND_MEMORY.md | Documents schema v8 supervision tables and memory/compaction isolation invariants. |
| docs/PROTOCOL.md | Documents supervision routing, new events, and MCP watch/steer contract. |
| docs/IMPLEMENTATION.md | Adds M2+ supervision milestone scope and UI requirements. |
| docs/DECISIONS.md | Adds accepted D-027 decision capturing supervision ≠ approval contract and persistence invariants. |
| docs/ACCEPTANCE_TESTS.md | Adds acceptance criteria for supervision pairing/watch/steer and isolation requirements. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if (listeners?.size === 0) this.#milestoneWaiters.delete(subject.turnId); | ||
| resolve(result); | ||
| }; | ||
| const onMilestone = (): void => finish("milestone"); |
Comment on lines
+5
to
+14
| export function isRoomContextMessage(event: StoredEventRecord): boolean { | ||
| if (event.eventType !== "message.created") return false; | ||
| if (isSupervisionWatchMessage(event.body)) return false; | ||
| if (event.eventType.startsWith("supervision.")) return false; | ||
| return ( | ||
| event.body !== null && | ||
| typeof event.body === "object" && | ||
| typeof (event.body as { content?: unknown }).content === "string" | ||
| ); | ||
| } |
Comment on lines
+2189
to
+2194
| const snapshot = this.#buildSupervisionSnapshot(subject, afterSeq); | ||
| const observed = this.#store.appendDurableEvent({ | ||
| roomId: this.#defaultRoomId, | ||
| eventType: "supervision.observed", | ||
| actorId: watch.targetActorId, | ||
| targets: [subject.targetActorId], |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GroupX can now pair a user command into a worker Turn and a parallel supervisor Watch Turn on the same
rootCorrelationId. This is a room collaboration mode, not a governance or approval layer.POST /api/messagesaccepts optionalsupervision: { observers, mode: "live_steer" }.unrestrictednative contract.groupx.watch/groupx.steer.steer(interrupt)cancels the whole watched Turn, then queues a new worker Turn with public guidance. It cannot allow/deny a single native tool.supervision.*events stay out of memory, dated-memory, and room compaction.Contract
Same change set updates PROTOCOL, D-027, IMPLEMENTATION (M2+ increment, not A2A M3), STORAGE schema v8, and ACCEPTANCE fixture cases.
Implementation notes
SUPERVISION_WATCH_REQUIREDunless the caller is the pair’s observer Watch Turn.subjectTurnIdprefers a running/cancelling worker over a queued steered follow-up.CREATE TABLEstays idempotent.limits.steersPerSubjectTurnandtimeouts.watchMs.Tests
Local acceptance for this increment (2026-08-18, win32, Node v24.14.1, merge onto
mainat84fe2cd):tsc --noEmitpassvitest: 58 files / 573 tests pass, including supervision isolation fixtures20260818T062549446Z: Codex 0.147.0 and Grok 1.0.5 handshake / MCPsend/ cancel / follow-up passnot_observed:session/promptreturned JSON-RPC-32000/ HTTP 403 usage-limit. Handshake,session/new, andset_mode(auto)still succeeded. This is not treated as a supervision or protocol regression, and it is not rewritten asverifiedThis increment is accepted to proceed. It is not a Structured Gate claim and does not apply
m0:apply:structured-gate. Model-drift detection is not a release condition.