Skip to content

A finished coding run is unauditable over MCP — 13 coding tools, none reads coding_timeline, and coding_session_capture answers an ended session with an empty pane #527

Description

@serge-ivo

The gap

An autonomous coding run's conversation with the engine is persisted forever in coding_timeline (migration 0023, append-only, seq-ordered) and served by GET /v1/instances/:id/coding/sessions/:sid/timeline. No MCP tool reads it. So the one surface built for auditing an agent — the MCP server, whose agent_trace description calls itself "the primary tool for debugging or improving an agent" — cannot see what an agent actually said to a coding CLI once the session has ended.

Measured

Thirteen coding_* tools are registered (grep -o '"coding_[a-z_]*"' workers/mcp/src):

coding_diagnostics · coding_loop_start · coding_loop_status · coding_loop_stop · coding_overseer · coding_repo_add · coding_repos_list · coding_session_capture · coding_session_end · coding_session_fresh · coding_session_message · coding_session_restart · coding_sessions_list

None reads the timeline. The closest, on an ended session:

coding_session_capture(instance_id: "bd43f4de-…", session_id: "csess_92b2130d-…")
→ { "sessionId": "csess_92b2130d-…", "runState": "idle", "pane": "" }

csess_92b2130d is a real 6-minute run with 5 Pilot instructions and a push to main. The tool answers with an empty pane and idle, which is indistinguishable from a session that never did anything.

agent_trace does not fill the gap either. On this instance, 186 events: 149 from chat, and all 33 coding-source events are act.consequential — the consequential-act record (#294), not the instruction stream. So the trace can tell you a run pushed to main; it cannot tell you what the run was told to do.

coding_sessions_list returns the session rows, so an MCP client can name the sessions it cannot read.

Why it matters, concretely

This is not hypothetical scope. Auditing #505's post-fix recurrence required reading the exact instructions the Pilot sent — the byte-identical ## Testing block across steps 3/4/5 and the escalation to "the project owner has explicitly requested this exact wording". Every one of those facts came from the REST route with a hand-made curl and the CLI's session token. Over MCP the run is a black box: three chat messages saying **Loop → engine** (step N): followed by the first 120 characters of the instruction (describe() in lib/coding-loop.ts truncates there before it reaches chat), and nothing else.

Every finding in that audit that concerns what the Pilot said is therefore unreachable from the surface the platform offers for exactly this purpose.

What to do

Register coding_session_timeline as a thin proxy — the same shape as list_instance_tools, which is nine lines around authedCall:

coding_session_timeline(instance_id, session_id, limit?)  → GET /v1/instances/:id/coding/sessions/:sid/timeline

Scope read, no confirmation, no dry run. It belongs in workers/mcp/src/instance-tools/coding.ts beside coding_session_capture, and needs a row in contract.test.ts's per-tool table (["coding", "read", null, null, "instance_id,session_id,token"]).

Two details worth deciding at write time:

Alternatives rejected

Acceptance

  • coding_session_timeline on csess_92b2130d-… returns the five command rows with their full text, in seq order.
  • coding_session_capture's description tells a caller where to look for an ended session.
  • contract.test.ts covers the new tool's scope/confirmation/dry-run row.

Regression risk

Low — a read proxy over an existing owner-scoped route. The one thing to get right is response size: an unbounded timeline can exceed the MCP client's token budget, which turns a debugging tool into a wall of truncated JSON.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendBackend / Worker / API workenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions