Skip to content

feat(tasks): background concurrency cap + graceful kill, DAG cut (M3.… - #23

Merged
wusijian007 merged 1 commit into
mainfrom
feat/m3.6-concurrency-graceful-kill
Jun 17, 2026
Merged

wusijian007 merged 1 commit into
mainfrom
feat/m3.6-concurrency-graceful-kill

Conversation

@wusijian007

Copy link
Copy Markdown
Owner

…6 / §3)

The final v3.1 item: resource control for background tasks. Two mechanisms, the task-dependency DAG explicitly NOT built (Claude Code has no DAG scheduler; it would be a parallel workflow engine against the repo's "extend primitives, no control plane" spirit — see docs/v3-kernel-roadmap.md §3 M3.6).

Concurrency cap — createTaskScheduler({ store, maxConcurrent }) is a FIFO admission semaphore: tasks beyond the cap stay "pending" (queued) until a running one reaches a terminal state and frees a slot. maxConcurrent 0 (default) = unlimited, so this is non-breaking and opt-in. The run+terminal-state logic is extracted into a shared runManagedTaskBody used by both startManagedTask (unbounded, unchanged) and the scheduler. The cap is a strong guarantee only for in-process managed tasks the scheduler admits; detached out-of-process workers are not gated across processes (known v1 limit, documented).

Graceful kill — markTaskKilled now terminates gracefully: in-process tasks cancel cooperatively via their AbortSignal (no signal sent), and a detached worker's pid gets SIGTERM -> graceMs grace -> SIGKILL only if still alive. The signal sender is injectable (signalProcess) so the escalation sequence is asserted offline without real processes. Windows has no real SIGTERM (process.kill -> TerminateProcess) so the first signal already terminates and the escalation is a documented no-op.

  • core: createTaskScheduler + TaskScheduler, runManagedTaskBody refactor, graceful markTaskKilled (KillOptions/ProcessSignaler), ToolContext.taskScheduler.
  • tools: runBackgroundSubAgent routes through context.taskScheduler when present, else startManagedTask (unchanged).
  • cli: MYAGENT_MAX_BACKGROUND_TASKS env builds the scheduler in the agent path.
  • tests: 6 new — cap+queue (deterministic via started barriers), queue-cancel, unbounded default, SIGTERM->SIGKILL escalation, SIGTERM honored (no escalation), in-process pid not signaled.
  • docs: CLAUDE.md background-tasks + env; roadmap M3.6 marked delivered.

220 tests pass (+6).

…6 / §3)

The final v3.1 item: resource control for background tasks. Two mechanisms,
the task-dependency DAG explicitly NOT built (Claude Code has no DAG scheduler;
it would be a parallel workflow engine against the repo's "extend primitives,
no control plane" spirit — see docs/v3-kernel-roadmap.md §3 M3.6).

Concurrency cap — createTaskScheduler({ store, maxConcurrent }) is a FIFO
admission semaphore: tasks beyond the cap stay "pending" (queued) until a
running one reaches a terminal state and frees a slot. maxConcurrent 0 (default)
= unlimited, so this is non-breaking and opt-in. The run+terminal-state logic is
extracted into a shared runManagedTaskBody used by both startManagedTask
(unbounded, unchanged) and the scheduler. The cap is a strong guarantee only for
in-process managed tasks the scheduler admits; detached out-of-process workers
are not gated across processes (known v1 limit, documented).

Graceful kill — markTaskKilled now terminates gracefully: in-process tasks
cancel cooperatively via their AbortSignal (no signal sent), and a detached
worker's pid gets SIGTERM -> graceMs grace -> SIGKILL only if still alive. The
signal sender is injectable (signalProcess) so the escalation sequence is
asserted offline without real processes. Windows has no real SIGTERM
(process.kill -> TerminateProcess) so the first signal already terminates and
the escalation is a documented no-op.

- core: createTaskScheduler + TaskScheduler, runManagedTaskBody refactor,
  graceful markTaskKilled (KillOptions/ProcessSignaler), ToolContext.taskScheduler.
- tools: runBackgroundSubAgent routes through context.taskScheduler when present,
  else startManagedTask (unchanged).
- cli: MYAGENT_MAX_BACKGROUND_TASKS env builds the scheduler in the agent path.
- tests: 6 new — cap+queue (deterministic via started barriers), queue-cancel,
  unbounded default, SIGTERM->SIGKILL escalation, SIGTERM honored (no escalation),
  in-process pid not signaled.
- docs: CLAUDE.md background-tasks + env; roadmap M3.6 marked delivered.

220 tests pass (+6).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wusijian007
wusijian007 merged commit 84d1f89 into main Jun 17, 2026
3 checks passed
@wusijian007
wusijian007 deleted the feat/m3.6-concurrency-graceful-kill branch June 17, 2026 04:19
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.

1 participant