Skip to content

feat(TaskScheduler): introduce semaphore-based task scheduler (Epic 3, Story 3.1)#1031

Draft
edelauna wants to merge 4 commits into
mainfrom
issue/368
Draft

feat(TaskScheduler): introduce semaphore-based task scheduler (Epic 3, Story 3.1)#1031
edelauna wants to merge 4 commits into
mainfrom
issue/368

Conversation

@edelauna

@edelauna edelauna commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Related GitHub Issue

Closes: #358

Description

Introduces TaskScheduler, a semaphore-based concurrency gate that wraps the existing TaskSemaphore utility, and wires it into ClineProvider as the single launch path for all tasks.

Key changes:

  • TaskScheduler (src/core/task/TaskScheduler.ts): thin wrapper around TaskSemaphore; schedule(task, run) acquires a permit, checks task.abort || task.abandoned before executing, and always releases in finally. Ships at maxConcurrency=1 (identical to current serial behaviour — raising it later enables fan-out without touching gate logic). cancelQueued() is called from ClineProvider.dispose() to drain the semaphore on teardown.

  • Task.run() (src/core/task/Task.ts): awaitable twin of Task.start(); returns the in-flight _runPromise if already running, or a resolved promise if _started is set (guards against double-invocation from constructor, start(), or a second run() call). ClineProvider now calls task.run() through the scheduler instead of task.start() directly.

  • ClineProvider (src/core/webview/ClineProvider.ts): holds a TaskScheduler instance; all task launch sites (createTask, delegateParentAndOpenChild) use void this.taskScheduler.schedule(task, () => task.run()). dispose() calls cancelQueued() before clearing the stack.

  • Tests: TaskScheduler.spec.ts (8 cases: immediate run, serial queuing, parallel at maxConcurrency=2, permit release on throw, cancelQueued, abort guard, abandoned guard, default concurrency); Task.dispose.test.ts gains a Task.run() idempotency describe (3 cases); provider-delegation.spec.ts and single-open-invariant.spec.ts updated to carry taskScheduler on provider stubs.

  • AGENTS.md: adds an ESLint Suppressions section documenting that counts must never increase, when as any is acceptable, and the prune-suppressions maintenance command. eslint-suppressions.json count for Task.dispose.test.ts reduced from 8 → 3.

No behaviour change at maxConcurrency=1 — tasks still run serially. The scheduler is the expand step of an expand-contract migration; fan-out (Story 3.2b) raises the limit without changing this gate logic.

Test Procedure

# Unit tests
pnpm --filter=zoo-code test -- --run core/task/__tests__/TaskScheduler.spec.ts
pnpm --filter=zoo-code test -- --run core/task/__tests__/Task.dispose.test.ts
pnpm --filter=zoo-code test -- --run __tests__/provider-delegation.spec.ts
pnpm --filter=zoo-code test -- --run __tests__/single-open-invariant.spec.ts

# Types + lint
pnpm --filter=zoo-code check-types
pnpm --dir src exec eslint --max-warnings=0 core/task/TaskScheduler.ts core/task/Task.ts core/webview/ClineProvider.ts

Pre-Submission Checklist

  • Issue Linked: Closes [Epic 3] TaskScheduler + Subtask Fan-out #358
  • Scope: TaskScheduler + Task.run() only; no fan-out logic yet (Story 3.2b is next)
  • Self-Review: Done
  • Testing: Unit tests added for scheduler, idempotency, and provider integration
  • Visual Snapshot: N/A — no UI changes
  • Documentation Impact: AGENTS.md updated with ESLint suppression guidance
  • Contribution Guidelines: Read and agreed

Summary by CodeRabbit

  • New Features

    • Added task scheduling to control concurrent task execution.
    • Added promise-based task launching with idempotent repeated calls.
    • Queued tasks can now be canceled, while active tasks continue safely.
    • Tasks are prevented from starting after disposal or when marked inactive.
  • Bug Fixes

    • Improved task delegation sequencing and rollback behavior.
    • Ensured scheduling permits are released when task execution fails.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 235b8e59-2cb9-4f20-8d6b-ce1384627b7a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

Adds idempotent promise-based task execution, a semaphore-backed TaskScheduler, and provider integration for scheduled task startup and shutdown cancellation. Tests now validate concurrency, ordering, rollback, and updated task mocks.

Changes

Task scheduling

Layer / File(s) Summary
Promise-based task execution
src/core/task/Task.ts, src/core/task/__tests__/Task.dispose.test.ts, AGENTS.md, src/eslint-suppressions.json
Task.run() tracks and reuses its execution promise; disposal tests use typed event constants and cover idempotency, while lint guidance and suppression counts are updated.
Concurrency scheduler
src/core/task/TaskScheduler.ts, src/core/task/__tests__/TaskScheduler.spec.ts
TaskScheduler limits concurrency, skips aborted or abandoned tasks, releases permits on completion or failure, and cancels queued work.
Provider scheduling integration
src/core/webview/ClineProvider.ts
Task creation and delegated child execution use TaskScheduler.schedule, and provider disposal cancels queued tasks.
Provider flow validation
src/__tests__/provider-delegation.spec.ts, src/__tests__/single-open-invariant.spec.ts
Provider mocks and assertions now cover scheduled run() calls, microtask timing, execution ordering, and rollback behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: awaiting-review

Suggested reviewers: hannesrudolph

Sequence Diagram(s)

sequenceDiagram
  participant ClineProvider
  participant TaskScheduler
  participant Task
  ClineProvider->>TaskScheduler: schedule(task, task.run)
  TaskScheduler->>Task: run()
  Task-->>TaskScheduler: resolve or reject
  TaskScheduler->>TaskScheduler: release concurrency permit
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the main change: adding a semaphore-based TaskScheduler.
Description check ✅ Passed The description follows the template and includes the linked issue, implementation summary, test procedure, and checklist.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue/368

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@edelauna edelauna changed the title Issue/368 feat(TaskScheduler): introduce semaphore-based task scheduler (Epic 3, Story 3.1) Jul 26, 2026
@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.84848% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/core/webview/ClineProvider.ts 69.23% 2 Missing and 2 partials ⚠️
src/core/task/Task.ts 88.88% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/webview/ClineProvider.ts`:
- Around line 3191-3199: Update createTaskWithHistoryItem so its implicit task
startup uses taskScheduler.schedule(task, () => task.run()) instead of invoking
task.run directly, preserving the startTask: false opt-out and matching
createTask’s concurrency-gated startup behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9116becd-95dc-49c3-a4a2-4822b1a6ac95

📥 Commits

Reviewing files that changed from the base of the PR and between 2db2af0 and 7fc3e4b.

📒 Files selected for processing (9)
  • AGENTS.md
  • src/__tests__/provider-delegation.spec.ts
  • src/__tests__/single-open-invariant.spec.ts
  • src/core/task/Task.ts
  • src/core/task/TaskScheduler.ts
  • src/core/task/__tests__/Task.dispose.test.ts
  • src/core/task/__tests__/TaskScheduler.spec.ts
  • src/core/webview/ClineProvider.ts
  • src/eslint-suppressions.json

Comment thread src/core/webview/ClineProvider.ts
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.

[Epic 3] TaskScheduler + Subtask Fan-out

1 participant