Skip to content

fix(project): async drafting, working clarifying questions, path-glob bug, warmer UX#228

Merged
AVADSA25 merged 1 commit into
mainfrom
claude/conversational-project
Jul 9, 2026
Merged

fix(project): async drafting, working clarifying questions, path-glob bug, warmer UX#228
AVADSA25 merged 1 commit into
mainfrom
claude/conversational-project

Conversation

@AVADSA25

@AVADSA25 AVADSA25 commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Three real bugs found from the overnight stuck project + the "talking to a wall" feedback.

1. Crash bug (never actually worked)

_ask_user called codec_ask_user.ask(question, source=..., deadline_seconds=...) — neither kwarg exists on the real signature (timeout=/asked_from=), and ask() returns a plain string, not a (status, answer) tuple. The clarifying-question mechanism would TypeError the instant it fired. Fixed + verified with a real (non-mocked) ask/submit_answer round trip.

2. Architecture bug

Even fixed, POST /api/agents ran 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. Split create_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 bare root directory itself (fnmatch needs a literal separator after root a bare-dir read lacks) — so a plan could declare X/** and still block the very first list X action. 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

…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>
@AVADSA25 AVADSA25 merged commit e876b99 into main Jul 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants