Files
turnstone/docs
Patrick Buckley 7d6b31e18a fix(coord): close gaps an operator's harness shakedown surfaced (#444)
* fix(coord): close gaps an operator's harness shakedown surfaced

Operator-driven shakedown of the coordinator tool surface flagged
five issues; this commit addresses all of them plus the review
findings against the initial fix.

1. Cancelled-mid-stream partial assistant content now carries a
   "[generation cancelled before completion]" marker.  Without it,
   ``inspect_workstream`` / ``wait_for_workstream`` callers and the
   next coord-LLM turn read the truncated text as a complete answer.
   ``_cancelled_partial_msg`` no longer ships ``_provider_content``
   (Anthropic would otherwise read that lane verbatim and bypass the
   marker; partial tool_use blocks could also leak through).

2. ``spawn_workstream`` / ``spawn_batch`` no longer surface the
   routing-proxy ``status`` field (always HTTP 200 on the success
   path).  The tool description claimed it was "lifecycle state at
   creation"; code that did ``if result["status"] == "idle"``
   silently never matched.  Lifecycle state lives on the workstream
   row — ``inspect_workstream`` is the read.  Tool JSON descriptions
   plus docs/coordinator-skills.md and docs/bulk-endpoints.md
   examples updated to match.

3. ``inspect_workstream`` not-found error string is bare ("workstream
   not found"); the structured ``ws_id`` field carries the queried
   id.  Pre-fix the error STRING echoed the id back at the caller
   who just sent it — redundant and out of step with the rest of the
   surface.  Cross-tenant + missing rows still return the same shape,
   preserving the existence-leak guarantee.

4. ``tasks(...)`` is now rejected when called in a parallel tool
   batch.  The prior shape relied on a docstring warning ("a list
   paralleled with writes can reflect pre-write state") that put
   cognitive overhead on every model invocation; turning the silent
   footgun into an explicit error means the model only thinks about
   the rule the moment it actually breaks it.  Warning dropped from
   the tasks tool description.  ``_PARALLEL_INCOMPATIBLE_TOOLS``
   constant in session.py is the extension point for any future
   tool with the same read-after-write hazard.

Plus the multi-stage code review's findings against the initial
fix (q-1 / q-2 docs drift, q-3 idiom, q-4 keys-assertion, q-5
duplicate guard) — all addressed in the same pass.

Tests: 4752 pass, +6 net since the pre-fix baseline.  Ruff + mypy
clean.  Three new tests pin the parallel-batch-rejection behaviour
on tasks (rejected when batched, runs alone, sibling tools
unaffected); existing cancel + spawn + inspect tests updated to
match the new shape.

* fix(coord): close two copilot review gaps on PR 444

Copilot review on PR 444 flagged two follow-ups:

1. Empty-content cancel divergence — when ``GenerationCancelled``
   races BEFORE the first content token, the prior shape skipped
   ``save_message`` and only appended an empty-content msg in
   memory.  In-memory and storage diverged: a rehydrate would see
   nothing in storage but the session would carry an empty
   assistant turn.  Both branches now persist; on the empty-content
   shape the marker becomes the entire message
   ("[generation cancelled before completion]") so storage matches
   the in-memory history.

2. Test stub cleanup — three new tests injected ``ui.approve_tools``
   via ad-hoc ``lambda + type: ignore[attr-defined]``.  Replaced
   with a permissive ``approve_tools`` method on ``_StubUI`` so the
   stub matches the SessionUI surface the dispatcher actually
   reads.  Tests that exercise approval pathways can still override
   per-instance.

Tests: 4752 pass.  Ruff + mypy clean.
2026-04-28 12:52:36 -07:00
..