The prompter prompt tells the model to call propose_draft when the spec is
ready, but on Grok that tool didn't exist — so no draft chunk, no panel draft
card, and the human couldn't launch a task from a Grok intake chat.
- intake-tools.js: opencode plugin registering propose_draft via Hooks.tool;
the execute() only ACKs — the driver (OpencodeServeSession.normalize ->
_is_propose_draft -> _draft_from_tool_input) intercepts the tool CALL and
emits the `draft` chunk the panel renders.
- agent-grok-prompter.Dockerfile: bake the plugin, scoped to this image via
ROBOCO_OPENCODE_EXTRA_PLUGINS (delivery roles never draft).
- test: a propose_draft tool part normalizes to a draft chunk (not a tool_use).
The live tool-call -> draft-card path is flagged UNVERIFIED-LIVE for the NAS.
Builds the Grok analogue of the Claude intake/secretary live-session runtime,
satisfying the same IntakeSession seam so the existing IntakeDriver loop,
message source, relay, and StreamChunk panel contract are reused unchanged:
- OpencodeServeSession: a held-open `opencode serve` session (context persists
across turns) where each human turn is one synchronous POST /session/:id/
message; normalize_opencode_message maps the reply parts to text/thinking/
tool_use/draft/turn_end chunks (draft via a propose_draft tool part or the
fenced roboco-draft fallback). Doc-verified against opencode's server API.
- grok_intake_main / grok_secretary_main: container entrypoints mirroring the
Claude mains but yielding an OpencodeServeSession; they render opencode.json
(xAI provider + MCP + system prompt) first, then run the receiver + driver.
- roboco-agent-grok-prompter / -secretary images (FROM roboco-agent-grok) +
their builder services in all three compose files.
UNVERIFIED-LIVE: the opencode serve flow + exact Part schema + draft path need
a live run against grok-build-0.1 (the part mapping is defensive). The
orchestrator wiring that routes a GROK intake/secretary route to these images
is the next step (a design decision is open — see the handoff notes).