Skip to content

refactor(task): extract checkpoint manager#106

Open
doctarock wants to merge 2 commits into
Zoo-Code-Org:mainfrom
doctarock:issue-19-checkpoint-manager
Open

refactor(task): extract checkpoint manager#106
doctarock wants to merge 2 commits into
Zoo-Code-Org:mainfrom
doctarock:issue-19-checkpoint-manager

Conversation

@doctarock

@doctarock doctarock commented May 14, 2026

Copy link
Copy Markdown
Contributor

Related GitHub Issue

Closes #19

Part of #8

Description

Extracts checkpoint state and lifecycle ownership from Task.ts into a dedicated CheckpointManager boundary in src/core/checkpoints.

  • Adds CheckpointManager to own checkpoint enablement, timeout, service instance, and initialization state
  • Removes the direct Task dependency from checkpoint helpers by introducing a smaller checkpoint runtime/context interface
  • Keeps Task public checkpoint methods and compatibility accessors in place while delegating save/restore/diff/init to the manager
  • Preserves the existing call flow, async behavior, checkpoint warning messages, telemetry calls, and failure handling

Test Procedure

  • .\.corepack-shims\pnpm.cmd --dir src check-types
  • .\.corepack-shims\pnpm.cmd --filter ./src exec vitest run core/checkpoints/__tests__/checkpoint.test.ts core/webview/__tests__/checkpointRestoreHandler.spec.ts
  • git push hook ran repo check-types successfully

Notes

No changeset added because this is an internal refactor with no user-facing package/API change.

Summary by CodeRabbit

  • Refactor
    • Reworked the checkpoint management internals: a dedicated checkpoint manager now centralizes checkpoint behavior and task instances delegate checkpoint operations to it.
    • Initialization and access to checkpoint services are now routed through the manager, with no change to end-user behavior or features.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 56bfe9bd-09fa-4be4-8891-2535584108bc

📥 Commits

Reviewing files that changed from the base of the PR and between 40c9af0 and e84db0d.

📒 Files selected for processing (1)
  • src/core/task/Task.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/task/Task.ts

📝 Walkthrough

Walkthrough

Extracts checkpoint management into a new CheckpointManager and runtime abstraction. Checkpoint helper functions (save/restore/diff, checkGitInstallation, get service) now accept CheckpointRuntime; Task delegates checkpoint state and operations through the manager and initializes its service during startup.

Changes

Checkpoint Manager Extraction

Layer / File(s) Summary
Checkpoint abstraction and CheckpointManager class
src/core/checkpoints/index.ts
CheckpointTaskContext, CheckpointRuntime, and CheckpointManagerOptions types are introduced. CheckpointManager wraps CheckpointTaskContext and exposes getService(), and the file removes the direct Task import.
Update checkpoint helper functions to CheckpointRuntime
src/core/checkpoints/index.ts
checkGitInstallation, checkpointSave, checkpointRestore, and checkpointDiff signatures are updated to accept CheckpointRuntime instead of Task.
Wire Task to use CheckpointManager
src/core/task/Task.ts
Task imports CheckpointManager, replaces per-task checkpoint fields with a checkpointManager field, initializes it in the constructor, calls checkpointManager.getService() during startup, and delegates getters/setters plus checkpointSave/checkpointRestore/checkpointDiff to the manager.

🎯 3 (Moderate) | ⏱️ ~25 minutes

"I hopped through code with tidy paws,
Moved checkpoints to a manager's laws,
Tasks now call through one neat door,
Save, restore, diff — all handled more,
A little rabbit cheers the chore." 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'refactor(task): extract checkpoint manager' clearly and concisely summarizes the main change—extracting checkpoint management logic from Task into a dedicated manager.
Description check ✅ Passed The PR description covers all required template sections: linked issues, implementation details/design choices, test procedures, and notes about changeset. It provides clear context on the refactoring approach.
Linked Issues check ✅ Passed The PR fully addresses issue #19 objectives: checkpoint methods/state are extracted into CheckpointManager, runtime interface removes Task dependency, method signatures are preserved, and async behavior/telemetry are maintained.
Out of Scope Changes check ✅ Passed All changes are directly related to extracting checkpoint management from Task.ts into CheckpointManager. No unrelated modifications or scope creep detected in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/core/task/Task.ts

Oops! Something went wrong! :(

ESLint: 9.28.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.


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 and usage tips.

@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.

🧹 Nitpick comments (1)
src/core/checkpoints/index.ts (1)

19-36: ⚡ Quick win

Weakly typed runtime/context interface loses type safety in checkpoint helpers.

CheckpointTaskContext uses any for providerRef, clineMessages, say, and combineMessages. The whole point of introducing an abstraction was to formalize the contract, but the current shape forfeits compile-time checks at every call site:

  • task.providerRef.deref()?.postMessageToWebview(...) is untyped, so typos in message types/payloads (e.g., currentCheckpointUpdated, checkpointInitWarning) won't be flagged.
  • task.clineMessages.filter(({ say }) => say === "checkpoint_saved").map(({ text }) => text!) (Line 414) loses ClineMessage field narrowing, and the text! non-null assertion can silently hide nulls.
  • task.say("checkpoint_saved", to, undefined, undefined, { from, to, suppressMessage: !!suppressMessage }, ...) (Lines 258-269) won't be validated against the actual say(type: ClineSay, ...) signature, so future ClineSay additions/removals or argument order changes will not surface here.

Consider replacing any with the existing concrete types (ClineMessage, ClineSay, a narrowed ClineProvider interface for the methods used — postMessageToWebview, log, cancelTask, context.globalStorageUri). The abstraction would still decouple from the full Task class while preserving end-to-end type checking.

♻️ Sketch of tighter typing
-export type CheckpointTaskContext = {
-	taskId: string
-	cwd?: string
-	providerRef: WeakRef<any>
-	clineMessages: any[]
-	messageManager: {
-		rewindToTimestamp: (ts: number, options: { includeTargetMessage: boolean }) => Promise<void>
-	}
-	say: (...args: any[]) => Promise<any>
-	combineMessages: (messages: any[]) => any
-}
+import type { ClineMessage, ClineSay } from "@roo-code/types"
+
+export interface CheckpointProvider {
+	postMessageToWebview: (msg: unknown) => Promise<void> | void
+	log?: (message: string) => void
+	cancelTask?: () => void
+	context: { globalStorageUri: { fsPath: string } }
+}
+
+export type CheckpointTaskContext = {
+	taskId: string
+	cwd?: string
+	providerRef: WeakRef<CheckpointProvider>
+	clineMessages: ClineMessage[]
+	messageManager: {
+		rewindToTimestamp: (ts: number, options: { includeTargetMessage: boolean }) => Promise<void>
+	}
+	say: (type: ClineSay, ...args: unknown[]) => Promise<unknown>
+	combineMessages: (messages: ClineMessage[]) => ClineMessage[]
+}
🤖 Prompt for 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.

In `@src/core/checkpoints/index.ts` around lines 19 - 36, Replace the loose any
types in CheckpointTaskContext/CheckpointRuntime with concrete interfaces:
change providerRef: WeakRef<any> to WeakRef<ClineProvider> (ClineProvider
exposing postMessageToWebview, log, cancelTask, context.globalStorageUri),
clineMessages: any[] to ClineMessage[], say: (...args: any[]) => Promise<any> to
say: (type: ClineSay, ...args: any[]) => Promise<any>, and combineMessages:
(messages: any[]) => any to combineMessages: (messages: ClineMessage[]) =>
CombinedMessageType; update referenced helpers that call
task.providerRef.deref(), task.clineMessages.filter(...), and task.say(...) to
use these types so TypeScript validates message names/payloads, removes unsafe
non-null assertions, and preserves the abstraction from the full Task class.
🤖 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.

Nitpick comments:
In `@src/core/checkpoints/index.ts`:
- Around line 19-36: Replace the loose any types in
CheckpointTaskContext/CheckpointRuntime with concrete interfaces: change
providerRef: WeakRef<any> to WeakRef<ClineProvider> (ClineProvider exposing
postMessageToWebview, log, cancelTask, context.globalStorageUri), clineMessages:
any[] to ClineMessage[], say: (...args: any[]) => Promise<any> to say: (type:
ClineSay, ...args: any[]) => Promise<any>, and combineMessages: (messages:
any[]) => any to combineMessages: (messages: ClineMessage[]) =>
CombinedMessageType; update referenced helpers that call
task.providerRef.deref(), task.clineMessages.filter(...), and task.say(...) to
use these types so TypeScript validates message names/payloads, removes unsafe
non-null assertions, and preserves the abstraction from the full Task class.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 107d8c5e-ec1f-47ff-aa30-1dc732735760

📥 Commits

Reviewing files that changed from the base of the PR and between 340f53e and 40c9af0.

📒 Files selected for processing (2)
  • src/core/checkpoints/index.ts
  • src/core/task/Task.ts

@codecov

codecov Bot commented May 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 64.70588% with 30 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/core/task/Task.ts 40.00% 18 Missing ⚠️
src/core/checkpoints/index.ts 78.18% 12 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot added the awaiting-review PR changes are ready and waiting for maintainer re-review label Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR changes are ready and waiting for maintainer re-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] Extract checkpoint management wrapper from Task.ts

1 participant