fix(project): async drafting, working clarifying questions, path-glob bug, warmer UX#228
Merged
Merged
Conversation
…ob bug + warmer UX
Three real bugs found from the overnight stuck project + user's 'talking to a
wall' feedback, plus the single-approval-for-paths gap:
1. CRASH BUG: _ask_user called codec_ask_user.ask(question, source=...,
deadline_seconds=...) — neither kwarg exists on the real ask() signature
(it's timeout=/asked_from=), and ask() returns a plain answer string, not a
(status, answer) tuple. The clarifying-question mechanism has never actually
worked — it would TypeError the instant Qwen said a description was too
vague. Fixed to call the real API and map its TIMEOUT_SENTINEL/
DISABLED_SENTINEL string returns back into the (status, answer) shape
callers expect. Verified end-to-end with a real ask()/submit_answer() round
trip (no mocks).
2. ARCHITECTURE BUG: even with (1) fixed, POST /api/agents ran the ENTIRE
draft — including a clarifying-question wait of up to 10 minutes — inline
inside the HTTP handler. The browser's fetch() would just hang with no
visible question anywhere. Split create_agent() into _reserve_agent()
(fast, sync — mint agent_id + project folder + draft_pending manifest) and
_finish_draft() (slow — Qwen + clarification, run in a background thread
from the route). POST /api/agents now returns in ~2ms; the frontend polls
GET /api/agents/{id} for status and GET /api/agents/pending_questions for
any clarifying question, rendering it as a normal warm chat bubble with an
inline reply (not a cold blocking wall). Verified the full reserve ->
background-draft -> clarifying-question -> answer -> awaiting_approval
chain end-to-end with a deterministic mock LLM.
3. PATH GLOB BUG: _path_allowed's recursive grant () didn't authorize
the bare directory itself (fnmatch requires a literal separator after
that a bare-dir read doesn't have) — so a plan could declare
and STILL block the very first action, forcing a redundant manual grant. This is what made last
night's Mirror-analysis project (which reads several dotfile directories)
repeatedly stop for grants it should already have had. Fixed: a
grant now also authorizes its bare root. Narrower globs () are
unaffected — this only widens the already-declared 'everything under X'
case, verified against tests/test_path_safety.py (all 7 pass).
UX: warmed up the plan-card copy (goals shown directly in the card instead of
hidden behind 'View plan', 'Here's my plan' instead of a cold 'Project
drafted' + JSON dump), removed the Project-mode intro's odd inline examples in
favor of a short conversational line + 'Learn more -> GitHub README' link.
Verified: 146 related tests pass (agent_plan/agent_runner/path_safety/
capability_gate/runner_loop/agent_messaging), ruff clean, node --check on
inline JS, plus two from-scratch (non-pytest) end-to-end proofs of the
previously-crashing ask/answer round trip and the full async draft flow.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Three real bugs found from the overnight stuck project + the "talking to a wall" feedback.
1. Crash bug (never actually worked)
_ask_usercalledcodec_ask_user.ask(question, source=..., deadline_seconds=...)— neither kwarg exists on the real signature (timeout=/asked_from=), andask()returns a plain string, not a(status, answer)tuple. The clarifying-question mechanism wouldTypeErrorthe instant it fired. Fixed + verified with a real (non-mocked) ask/submit_answer round trip.2. Architecture bug
Even fixed,
POST /api/agentsran the entire draft — including up to a 10-minute clarifying-question wait — inline in the HTTP handler, hanging the browser's fetch with nothing visible. Splitcreate_agent()into_reserve_agent()(fast/sync) +_finish_draft()(slow, backgrounded). POST now returns in ~2ms; frontend polls for status + pending questions and renders any question as a warm chat bubble with inline reply. Verified full chain end-to-end with a deterministic mock LLM.3. Path-glob bug
_path_allowed's recursive grant (root/**) didn't authorize the barerootdirectory itself (fnmatch needs a literal separator afterroota bare-dir read lacks) — so a plan could declareX/**and still block the very firstlist Xaction. This is what made last night's project keep stopping for grants it should already have had. Fixed; narrower globs (*.md) unaffected.UX
Plan card now shows goals directly (not hidden behind "View plan"), warmer copy throughout, removed the odd inline examples for a short line + "Learn more → GitHub README" link.
Verified: 146 tests pass, ruff clean, node --check, plus two from-scratch end-to-end proofs (ask/answer round trip, full async draft flow).
🤖 Generated with Claude Code