feat(concurrency): port ch07 concurrency gaps from TS - #16
Merged
Conversation
Closes seven gaps identified in my-docs/ch07-concurrency-gap-analysis.md between the TS StreamingToolExecutor + toolOrchestration.ts and the Python port: - G6 _execute_tool no longer mutates the executor's shared ToolContext.abort_controller; each tool now runs against a dataclasses.replace() copy with its own per-tool controller, so concurrent tools don't race on the abort field. - G1 _run_tools_concurrently no longer swallows exceptions silently; unhandled errors from run_tool_use surface as tool_use_error so the next API turn doesn't 400 on an unmatched tool_use block. - G2 partition_tool_calls + StreamingToolExecutor.add_tool now share classify_concurrency_safe(), which fail-closes on unknown tools, non-dict input, and exceptions from the per-tool classifier. - G4 the concurrent-batch context-modifier path accepts the ContextModifier dataclass shape that run_tool_use actually emits; the prior dict-only reader silently dropped modifiers. - G5 add_tool retains the ensure_future task in _pending_queue_tasks; without this asyncio could GC the scheduled coroutine mid-flight. - G7 AbortSignal.add_listener supports once=True with self-detaching semantics; create_child_abort_controller now removes its parent listener on either fire-direction so long-lived parents no longer accumulate one dead handler per child tool. - G9 get_remaining_results clears the progress-available event before the pending-progress recheck, closing the race where a producer's set() between check and clear was wiped and the wait blocked until a tool finished. Defers G3-4b (migrating query.py to call orchestrator.run_tools), G10 (StreamingToolExecutor wiring into the streaming response parser), G15 (set_has_interruptible_tool_in_progress UI hook), and G16 (with_memory_correction_hint helper) — see refactor plan. Tests: 19 new cases across 3 files (test_streaming_executor_race, test_abort_controller_once, test_orchestrator_concurrency) covering each gap's invariant. Existing tests/test_streaming_executor.py and tests/parity/test_concurrency_model.py still pass — 41 concurrency tests green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This was referenced May 10, 2026
singlaamitesh
pushed a commit
to singlaamitesh/clawcodex
that referenced
this pull request
Jul 7, 2026
…ncurrency feat(concurrency): port ch07 concurrency gaps from TS
singlaamitesh
pushed a commit
to singlaamitesh/clawcodex
that referenced
this pull request
Jul 7, 2026
… hyperlinks + frame metrics + thinking widget + per-tool permission specialization + output styles frontmatter + placeholder Resume/Doctor screens Bundle of standalone module additions across ch13 phases 4-12 that share no integration surface with each other and don't touch ``app.py``, ``screens/repl.py``, ``agent_bridge.py``, or ``agent_loop.py``. Each module ships with unit tests; cross-cutting production wiring (where present) lives in a follow-up PR so this change merges cleanly into ``main`` regardless of order. Phase 4 vim foundation (gap agentforce314#4 wave-1+2): - ``src/tui/vim_buffer.py`` — multi-line ``VimBuffer`` + ``Cursor`` + ``Range`` - ``src/tui/vim_text_objects.py`` — ``find_text_object`` for ``iw``/``aw``/``ip``/``ap``/quotes/braces - ``src/tui/vim_operators.py`` — ``parse_operator_motion`` (``d2w``, ``ciw``, ``y$``); operator dispatch d/c/y/>/< - ``src/tui/vim_visual.py`` — Visual / Visual-Line / Visual-Block selection model - ``src/tui/vim_search.py`` — ``/`` / ``?`` regex search with ``n``/``N`` repeat - 70 tests (``test_vim_multiline.py`` + ``test_vim_wave2.py``) Phase 5 transcript search module (gap agentforce314#2): - ``src/tui/widgets/transcript_search.py`` — ``TranscriptSearch`` ModalScreen + ``find_matches`` helper - 16 tests (``test_transcript_search.py``) Phase 6 IME declared cursor module (gap agentforce314#3): - ``src/tui/declared_cursor.py`` — refcounted-set registry + CSI emission - 16 tests (``test_declared_cursor.py``) Phase 7 specialized permission dialogs (gap agentforce314#8): - ``src/tui/screens/permission_modal.py`` ``_TOOL_RENDERERS`` dispatcher + per-tool renderers (Bash, Edit, Write, Read) - 16 tests (``test_permission_modal_specialization.py``) Phase 8 placeholder Resume/Doctor screens (gap agentforce314#9): - ``src/tui/screens/resume_conversation.py`` — placeholder with empty-state until persistence wiring lands - ``src/tui/screens/doctor.py`` — read-only diagnostics (env/hyperlinks/frame-metrics/storage) - 6 tests (``test_resume_doctor_screens.py``) Phase 9 output styles frontmatter (gap agentforce314#7): - ``src/outputStyles/{loader,styles}.py`` — YAML frontmatter parsing via existing ``parse_frontmatter``; auto-discovery of ``~/.claude/outputStyles/`` - 11 tests (``test_output_styles_frontmatter.py``) + parity test (``test_output_styles_parity.py``) Phase 10 OSC 8 hyperlinks (gap agentforce314#15): - ``src/tui/hyperlinks.py`` — capability detection (FORCE_HYPERLINK / TERM_PROGRAM / VTE_VERSION / truecolor) - ``src/tui/widgets/messages/tool_result.py`` wraps file paths with the negative-lookbehind regex (avoids eating sentence punctuation) - 38 tests (``test_hyperlinks.py`` + ``test_tool_result_hyperlinks.py``) Phase 11 frame-event observability (gap agentforce314#10): - ``src/tui/frame_metrics.py`` — ``FrameEvent`` shape + ``register_frame_observer`` + no-op fast path when ``CLAWCODEX_DEBUG_REPAINTS`` unset - 17 tests (``test_frame_metrics.py``) Phase 12 assistant-thinking widget (gap agentforce314#16 sub-item): - ``src/tui/widgets/messages/assistant_thinking.py`` — italic-dim styled distinct row; redacted variant - ``src/tui/widgets/transcript_view.py`` adds ``append_thinking_chunk``/``append_thinking`` shells with symmetric guard for ``append_assistant_chunk`` (Critic-flagged: prevents future thinking↔assistant mis-routing once dispatch wiring lands) - 11 tests (``test_assistant_thinking.py`` + ``test_transcript_thinking_transitions.py``) Test surface: 521 cumulative tests pass (``tests/tui/`` + ``tests/parity/test_output_styles_parity.py``). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
peroxider
pushed a commit
to peroxider/clawcodex
that referenced
this pull request
Jul 9, 2026
fix(orchestrator): P0 质量闸门 — 前提校验+诚实退出 与 回归防护 Created-by: qq_49552963 Commit-by: yeyunyao Merged-by: chadwweng Description: ## 这个 MR 解决什么 这个 MR 增加两道交付前质量门: 1. **前提检查**:issue 指向的文件或符号不存在时,直接说明无法继续,不再凭空创建文件。 2. **回归阻断**:代码改完后只要验证失败,就停止交付,不再创建 MR。 ## 关联 issue - [agentforce314#16 编排器遇到不存在文件时会伪造修复并创建 MR](https://gitcode.com/chadwweng/clawcodex/issues/16) - [agentforce314#17 编排器未阻断破坏性改动,改坏测试仍交付 MR](https://gitcode.com/chadwweng/clawcodex/issues/17) ## 验证 ### click agentforce314#21:文件不存在时正确停止 系统返回 `premise_not_met`,并明确 `No merge request was opened`。  ### click agentforce314#22:测试失败时正确阻断 系统返回 `verification_failed`,没有把失败修改当成成功交付。  See merge request: chadwweng/clawcodex!71
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.
Summary
Closes 7 of the gaps identified in
my-docs/ch07-concurrency-gap-analysis.mdbetween the TypeScript reference (StreamingToolExecutor.ts+toolOrchestration.ts) and the Python port (src/services/tool_execution/). All Tier-1 correctness fixes plus the listener-leak and progress-wake fixes; query-loop migration (G3-4b) and full speculative-execution wiring (G10) are deferred per the refactor plan.Gaps closed
_execute_toolruns against a per-tooldataclasses.replace()copy of the context — concurrent tools no longer race on the executor's sharedabort_controller._run_tools_concurrentlyno longer swallows exceptions; unhandled errors fromrun_tool_usesurface as synthetictool_use_errorso the next API turn doesn't 400 on an unmatchedtool_use.partition_tool_calls+StreamingToolExecutor.add_toolshareclassify_concurrency_safe()— fail-closed on unknown tools, non-dict input, and per-tool classifier exceptions.ContextModifierdataclass shape (the producer's actual return value); prior dict-only reader silently dropped modifiers.add_toolretains theensure_futurequeue task in_pending_queue_tasks; asyncio could otherwise GC the coroutine mid-flight.AbortSignal.add_listener(..., once=True)with self-detaching semantics;create_child_abort_controllerremoves its parent listener on either fire-direction. Long-lived parents no longer accumulate one dead handler per child tool.get_remaining_resultsclears the progress event before rechecking pending progress, closing the producer/consumer race whereset()was wiped and the wait blocked.What's deferred (and why)
src/query/query.pyto callorchestrator.run_toolsdirectly. Touches the live tool-execution path; deserves its own PR with end-to-end query-loop testing.StreamingToolExecutorinto the streaming response parser for true speculative execution. Out of scope for this chapter; touches the streaming chapter's surface.Test plan
tests/test_streaming_executor_race.py— verifies per-tool abort-controller isolation under concurrent executiontests/test_abort_controller_once.py— verifies once-fire semantics and listener-leak preventiontests/test_orchestrator_concurrency.py— verifies fail-closed classification, exception surfacing, context-modifier ordering, and submission-order invarianttests/test_streaming_executor.py(9 tests) still passestests/parity/test_concurrency_model.py(16 tests) still passesNote: 25 unrelated test failures in
tests/test_repl.pyexist onmaintoo — they require a configured API key, not affected by this PR.🤖 Generated with Claude Code