Skip to content

feat(automation): decouple schedules from project selection - #1274

Merged
Astro-Han merged 33 commits into
devfrom
codex/i1271-process-scheduler
Jun 12, 2026
Merged

feat(automation): decouple schedules from project selection#1274
Astro-Han merged 33 commits into
devfrom
codex/i1271-process-scheduler

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

Decouple Automation scheduling from the currently selected project by introducing one process-owned scheduler that scans scoped automation definitions and enters project instances only when a run fires.

This also retires the temporary cross-project move workaround for fresh automations: moving now updates the existing automation in place, preserving its id, schedule, pause state, and run history.

The Automations detail Project row now reuses the existing workspace-picker experience even when only one project is open: fresh automations stay clickable, the menu includes the current project plus the existing Open project footer action, and opening another project from this surface does not navigate away from Automations. Continue automations remain read-only because they are bound to their source conversation.

Automation detail hover states are also unified: internal Project / Repeats / Model controls and the continue source-session jump use the same 30px row-hover surface with the default cursor, with underline reserved for external-link semantics.

Why

Closes #1271.

Scheduled automations were tied to project instance lifetime, so switching or closing a project could cancel scheduler-owned runs and closed projects had no scheduler watching their due times. The user promise should instead be: automations run while PawWork is open, regardless of which project is visible.

The Automations Project row also had a one-project trap: with only one project open it became plain text, so users could not reach the same Open project affordance that already exists in the composer workspace picker.

Related Issue

Closes #1271

Human Review Status

Pending

Review Focus

Please focus on the ownership boundary: the process scheduler should own due-fire decisions globally, while actual execution still enters the target project instance and keeps the existing writer / active-run guards intact.

Also check the native fresh move path: source stores should receive a tombstone, target stores should receive the moved definition, and continue automations should remain bound to their source conversation.

For the UI follow-up, check that the Automations Project row is just an extension of the existing workspace-picker path: fresh automations can open the picker with one project, Open project adds to the available projects without leaving Automations, and continue automations remain read-only. Internal detail-page controls should use the same 30px row-hover feedback and default cursor, not underline or web-link pointer treatment.

Risk Notes

  • Scheduler ownership moved from instance lifetime to process lifetime, so server start/stop and stale-run reconciliation are the main risk surfaces. Review follow-ups now make owner settle wait for the initial scan, clean up the bound listener if settle fails during startup, resolve moved automation run outcomes through one shared current-scope refresh/publish path before scheduling, and keep scheduler GlobalBus handler failures isolated from event publishers, and preserve timer scope when a moved automation keeps the same schedule, and stop in-flight startup scans before they write missed schedules after shutdown, and clarify the internal move/update helper options so expected scope and target owner directory cannot be confused, and keep scheduler-owned run stopping private behind stop({ stopRuns }).
  • Fresh move now updates ownership in place. Moves are blocked for continue automations and active runs to avoid cross-project conversation or live-run ambiguity.
  • The Automations Project row now has visible picker affordance changes. It reuses workspace chip copy and picker CSS, with a new no-navigation wrapper around the existing project chooser for this surface. Internal detail controls now share the same 30px row-hover target and default cursor to keep the surface app-like rather than link-like.
  • The full Open project directory-selection chain is delegated to the existing project chooser; the focused E2E now clicks the footer from the Automations picker and pins the popover-close, dialog-open, and no-navigation behavior, while the routing unit coverage pins the no-navigation branch.
  • Removed unused scheduler stop wrappers (stopDirectoryOwnedRuns, stopCurrentOwnedRuns, stopAllOwnedRuns) after grep found no callers; the remaining explicit entry point is stopProcess({ stopRuns }).
  • Docs/release/dependency checklist left unticked: no docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or committed local files changed.

How To Verify

bun --cwd packages/opencode test test/server/server-listen.test.ts test/server/automation-scheduler.test.ts test/server/automation-routes.test.ts
Result: 47 passed after the scheduler Interface cleanup. Covers listen cleanup after scheduler settle failure, moved automation outcomes arriving from the old scope, owner settle waiting for the initial closed-project scan, native fresh move, unknown-target move rejection, active-run move rejection with a live run lease, and continue move rejection.

bun --cwd packages/opencode typecheck
Result: passed after the scheduler Interface cleanup.

bun turbo test:ci --filter=opencode
Result: 3887 passed, 9 skipped, 1 todo, 0 failed.

bun --cwd packages/app test src/context/global-sync/automation-store.test.ts
Result: 16 passed after the move-target cache guard. Covers stale target mismatch falling back to the source update instead of tombstoning the source into the wrong target store.

bun --cwd packages/app test src/pages/layout/pawwork-routing-actions.test.ts
Result: 7 passed after the Open project routing coverage. Covers `openProject(..., false)` opening the project without route navigation.

bun --cwd packages/app run test:e2e e2e/automations/automations-panel.spec.ts -g "detail project picker stays available"
Result: 1 passed after the Open project footer coverage. Covers the real Automations footer click path: the workspace popover closes, the Open project dialog appears, and the route stays on `/automations`.

bun --cwd packages/app typecheck
Result: passed after the app review follow-ups.

bun --cwd packages/app run test:e2e e2e/automations/automations-panel.spec.ts -g "detail project picker stays available|continue automation project stays read-only"
Result: RED before the final hover-target fix because Project still used cursor:pointer and the source-session hover target was 21px tall; GREEN after the fix with 2 passed. Covers one-open-project detail picker availability, 30px internal hover targets, default cursor, no underline on internal controls, current project menu item, Open project footer presence, continue automation read-only behavior, and source-session hover behavior.

bun --cwd packages/app run test:e2e e2e/automations/automations-panel.spec.ts -g "detail moves an automation"
Result: 1 passed, covering the existing cross-project move path after the picker change.

bun --cwd packages/app run snap automations-surface
Result: 1 passed; reviewed the generated automations-surface grid for the detail Project row, Repeats / Model rows, source-session row, and create-card folder picker.

Screenshots or Recordings

Visual check performed with bun --cwd packages/app run snap automations-surface; reviewed the generated grid at docs/design/preview/screenshots/automations-surface.png locally. The snap shows the Automations detail Project row as a picker, the detail hover targets using the same row surface, and the create card still using the same folder picker surface.

Checklist

How to use this checklist:

  • Tick a box by replacing [ ] with [x]. Do not edit, add, or remove items.
  • The bot-applied label items can only be honestly ticked AFTER the PR is opened and the labeler / priority-triage bots have run — return to the PR description and tick them then.
  • Most items are required. The few that are conditional are explicitly marked (conditional); for those, leave unticked if they truly do not apply and explain why in Risk Notes. All other items must be ticked before requesting human review.
  • Type label — this PR carries exactly one of bug, enhancement, task, documentation. Type labels are author-added; the labeler bot does NOT assign them. Add the label in the GitHub UI, then tick this.
  • Routing labels — this PR carries at least one of app, ui, platform, harness, ci. The labeler bot assigns these on PR open based on changed paths. Confirm the bot's choice (or override if wrong), then tick this.
  • Priority label — this PR carries exactly one of P0, P1, P2, P3. The priority-triage bot suggests one on PR open. Confirm or override, then tick this.
  • Human Review Status above is set to Pending, Approved by @<reviewer>, or Not required: <reason> (default is Pending; "not required" is restricted to bot-authored low-risk PRs).
  • I linked the related issue, or stated in Summary why there is no issue.
  • I described the review focus and any meaningful risks.
  • I replaced the example block in How To Verify with the real verification steps and the key result for each.
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope.
  • (conditional) I manually checked visible UI or copy changes when needed, with screenshots or recordings. Leave unticked only if no visible UI or copy changed.
  • (conditional) I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes. Leave unticked only if no platform/packaging surface was touched.
  • (conditional) I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant. Leave unticked only if none of those surfaces was touched.
  • I reviewed the final diff for unrelated changes and suspicious dependency changes.
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English.

Summary by CodeRabbit

  • New Features

    • Move automations between projects while preserving ID and run history; project picker can open a project from picker controls. Scheduler and automation APIs are now scope-aware to support per-directory/project behavior.
  • Bug Fixes

    • Paused state persists after moves; failed moves keep the source automation intact; picker remains available with one open project; improved hover/cursor visuals for picker and controls.
  • Tests

    • Expanded E2E and server tests for cross-project moves, picker behavior, scheduler lifecycle, and run resilience.

@Astro-Han Astro-Han added enhancement New feature or request P1 High priority app Application behavior and product flows harness Model harness, prompts, tool descriptions, and session mechanics labels Jun 11, 2026
@github-actions github-actions Bot added the ui Design system and user interface label Jun 11, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested priority: P2 (includes user-path files (packages/app/src/context/global-sync.tsx, packages/app/src/pages/automations/automation-detail-editors.tsx, packages/app/src/pages/automations/automation-detail.tsx)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the cross-project automation move logic to update the owner project and directory in place, preserving the automation's ID and run history. It also updates the scheduler to manage tasks across multiple project scopes globally and ensures active runs are not stopped during instance disposal. A review comment suggests wrapping the Project.get call in a try-catch block to prevent an unhandled NotFoundError from bypassing validation when a target project is not found.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/opencode/src/automation/index.ts
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Astro-Han, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 50 minutes and 27 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 98947532-b172-48f6-8705-97a953a7f852

📥 Commits

Reviewing files that changed from the base of the PR and between 9022bd8 and 78e698d.

📒 Files selected for processing (11)
  • packages/app/e2e/automations/automations-panel.spec.ts
  • packages/app/src/context/global-sync.tsx
  • packages/app/src/context/global-sync/automation-store.test.ts
  • packages/app/src/context/global-sync/automation-store.ts
  • packages/app/src/pages/automations/automation-detail.tsx
  • packages/app/src/pages/layout/pawwork-routing-actions.test.ts
  • packages/opencode/src/automation/index.ts
  • packages/opencode/src/automation/scheduler.ts
  • packages/opencode/test/server/automation-routes.test.ts
  • packages/opencode/test/server/automation-scheduler.test.ts
  • packages/opencode/test/server/server-listen.test.ts
📝 Walkthrough

Walkthrough

Adds per-directory Scope to automations, makes the scheduler process-owned and scope-aware (GlobalBus routing), implements native fresh automation moves via scoped updates, updates server startup/shutdown and instance disposal, and wires frontend folder-picker/open-project callbacks with matching E2E and server tests.

Changes

Process-level scheduling with multi-directory scopes

Layer / File(s) Summary
Scope types and scope-aware storage contracts
packages/opencode/src/automation/index.ts
Adds Scope/ScopedDefinition, scope helpers (currentScope, rowScope, scopeMatches), and updates list/get/listAll/replace/write helpers to accept and enforce scope; validateCreateInput accepts projectVcs for worktree checks.
Run lifecycle and scoped publishing
packages/opencode/src/automation/index.ts
Threads scope through run outcome recording, run leasing, reconciliation, pagination, and stop/revise paths; adds getRunAnyScope, publishDefinitionUpdatedForScope, and publishRunUpdatedForScope and surfaces them in the Effect interface.
Process-level scheduler core and event routing
packages/opencode/src/automation/scheduler.ts
Scheduler becomes scope-aware: ScheduledTask stores scope, computeNextFireAt/reschedule accept scope, GlobalBus events are routed and handled within the correct instance context (runInScope), owned-run tracking includes scope, and process-level owner settle/stopProcess logic is added.
Server and instance lifecycle integration
packages/opencode/src/server/server.ts, packages/opencode/src/project/instance.ts
Removes pre-stop of scheduler-owned runs during maintenance-mode disposal; server listen() calls settleOwner() and on failure stops the scheduler process (stopProcess({ stopRuns: false })) and attempts server shutdown; listener stop() now stops the process scheduler before stopping the server.
Automation move detection and route publishing
packages/opencode/src/automation/index.ts, packages/opencode/src/server/instance/automation.ts, packages/app/src/context/global-sync.tsx, packages/app/src/pages/automations/automation-detail.tsx
Automation.update() detects cross-project moves, validates target project/VCS, applies a deletion tombstone in the source and writes the moved definition under the target scope; route publishing now emits a tombstone for previous scope when projectID changes; frontend move flow uses globalSync.automation.update(..., { targetDirectory }) and forwards moved definitions.
Frontend folder picker and wiring
packages/app/src/pages/automations/*, packages/app/src/pages/layout*
Adds onOpenProject wiring through Surface → AutomationsSurface → CreateDialog/Detail → ProjectEditorRow; AutomationFolderPicker becomes controlled with i18n labels and optional onOpenProject action; chooseProject gains a navigate option and SurfacePageContext exposes automations.openProject; row hover/value styling adjusted.
E2E and server tests
packages/app/e2e/*, packages/opencode/test/*
E2E: hover-surface helper, id-based moved-automation polling, single-open-project picker test, paused-after-move id checks, and targeted move-failure mocking. Server tests: process-scheduler teardown changes, fresh cross-project move tests and rejection cases, stored-project scheduling tests, and a server.listen test for settleOwner failure.

Sequence Diagram(s)

sequenceDiagram
  participant UI as AutomationDetail / FolderPicker
  participant GlobalSync as globalSync.automation.update
  participant Server as Server PUT /:automationID
  participant Automation as Automation.update
  participant Scheduler as AutomationScheduler
  participant Instance as Instance (runtime / DB)

  UI->>GlobalSync: update where.projectID + targetDirectory
  GlobalSync->>Server: PUT /automation/:id (updated definition)
  Server->>Automation: update(definition, scope?)
  Automation->>Instance: write scoped definition and source tombstone
  Automation->>Scheduler: publishDefinitionUpdatedForScope / publishDefinitionDeleted
  Scheduler->>Instance: runInScope -> schedule timers / execute runs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

"I hopped and checked the clocks today,
One process watches fires that stray.
Fresh moves keep their history neat,
Closed projects don't skip a beat,
A rabbit cheers: schedule away!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(automation): decouple schedules from project selection' accurately reflects the main change: moving automation scheduling from per-project instances to a process-level scheduler, decoupling it from UI project selection.
Linked Issues check ✅ Passed The PR addresses all primary coding requirements from issue #1271: process-level scheduler implementation, scope-aware reads, on-demand instance acquisition, decoupling scheduling from UI selection, preservation of single-owner semantics, native fresh-automation moves, and interrupted-run reconciliation with focused tests.
Out of Scope Changes check ✅ Passed All code changes are directly aligned with the stated objectives: scheduler ownership transfer, scope-aware APIs, fresh-move implementation, UI picker updates, and related test/verification additions. No unrelated refactors, dependencies, or out-of-scope changes detected.
Description check ✅ Passed The PR description is comprehensive, well-structured, and follows the template with all required sections completed.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/i1271-process-scheduler

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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/opencode/src/automation/scheduler.ts (1)

645-648: 💤 Low value

Clarify or remove the unused directory parameter.

stopDirectoryOwnedRuns accepts a directory parameter but ignores it (void directory). This appears intentional per the PR design where the process scheduler owns all runs regardless of directory, but the function signature is misleading. Consider either:

  1. Removing the parameter if callers don't need directory-scoped stopping
  2. Adding a brief comment explaining why it's intentionally ignored
🤖 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 `@packages/opencode/src/automation/scheduler.ts` around lines 645 - 648, The
stopDirectoryOwnedRuns function currently accepts a directory parameter but
ignores it (void directory), which is misleading; either remove the unused
parameter from the function signature and update all callers to call
stopDirectoryOwnedRuns() (leave logic as current().stopOwnedRuns()), or keep the
parameter and add a concise comment above stopDirectoryOwnedRuns explaining that
the scheduler owns all runs and the directory is intentionally unused so callers
can remain compatible; update any type declarations accordingly and ensure
references to stopDirectoryOwnedRuns and current().stopOwnedRuns() remain
consistent.
🤖 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 `@packages/opencode/src/automation/index.ts`:
- Around line 699-701: The move-checking logic currently only blocks moves when
hasActiveRun(previous.id) and previous.context === "continue", but later code
drops reconciliation if the definition is out of scope which can miss applying
recordRunOutcome (and its failureStreak/nextFireAt) for runs that just finished;
update the move validation to, before adding "project_not_found" or dropping
reconciliation via addDetail(updateDetails,...), attempt a fallback lookup of
the definition in its current scope (e.g., resolve the definition by
previous.definitionId or caller scope) and only mark "project_not_found" or drop
reconciliation if that fallback fails; ensure this touches the same conditional
paths where previous.context, hasActiveRun(previous.id), targetProject, and
addDetail(updateDetails, ...) are used so recordRunOutcome will still be applied
when a run has just transitioned to succeeded/failed.

In `@packages/opencode/src/server/server.ts`:
- Around line 84-86: The server currently starts before the process scheduler
finishes settling; after calling built.runtime.listen(opts) you must await the
scheduler ownership settlement so startup fails if reconciliation fails—retrieve
the scheduler via AutomationScheduler.current(), call and await
automationScheduler.settleOwner(), and only then proceed (so any errors from
settleOwner are propagated and server readiness reflects the scheduler
contract).

---

Nitpick comments:
In `@packages/opencode/src/automation/scheduler.ts`:
- Around line 645-648: The stopDirectoryOwnedRuns function currently accepts a
directory parameter but ignores it (void directory), which is misleading; either
remove the unused parameter from the function signature and update all callers
to call stopDirectoryOwnedRuns() (leave logic as current().stopOwnedRuns()), or
keep the parameter and add a concise comment above stopDirectoryOwnedRuns
explaining that the scheduler owns all runs and the directory is intentionally
unused so callers can remain compatible; update any type declarations
accordingly and ensure references to stopDirectoryOwnedRuns and
current().stopOwnedRuns() remain consistent.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f41b8ca-8d67-40f0-98e4-7f8f0538875f

📥 Commits

Reviewing files that changed from the base of the PR and between 6db4738 and be76df5.

📒 Files selected for processing (11)
  • packages/app/e2e/automations/automations-panel.spec.ts
  • packages/app/src/context/global-sync.tsx
  • packages/app/src/pages/automations/automation-detail-editors.tsx
  • packages/app/src/pages/automations/automation-detail.tsx
  • packages/opencode/src/automation/index.ts
  • packages/opencode/src/automation/scheduler.ts
  • packages/opencode/src/project/instance.ts
  • packages/opencode/src/server/instance/automation.ts
  • packages/opencode/src/server/server.ts
  • packages/opencode/test/server/automation-routes.test.ts
  • packages/opencode/test/server/automation-scheduler.test.ts
💤 Files with no reviewable changes (1)
  • packages/opencode/src/project/instance.ts

Comment thread packages/opencode/src/automation/index.ts
Comment thread packages/opencode/src/server/server.ts Outdated

@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)
packages/app/e2e/automations/automations-panel.spec.ts (1)

630-630: ⚡ Quick win

Use .filter({ hasText }) for consistency with existing tests.

This file's existing move tests (lines 593-594, 693, 737) use the .filter({ hasText }) pattern. For consistency, refactor to match:

-  await surface.locator('[data-action="automation-row"]', { hasText: "Single project digest" }).first().click()
+  await surface.locator('[data-action="automation-row"]').filter({ hasText: "Single project digest" }).first().click()

Both APIs are valid in Playwright 1.57.0, but maintaining a consistent pattern within the file improves readability.

🤖 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 `@packages/app/e2e/automations/automations-panel.spec.ts` at line 630, Replace
the direct locator call that uses the hasText option with the file's established
pattern: use surface.locator('[data-action="automation-row"]').filter({ hasText:
"Single project digest" }).first().click() so it matches other tests; update the
call referencing surface.locator and the '[data-action="automation-row"]'
selector to use .filter({ hasText }) for consistency.
🤖 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 `@packages/app/e2e/automations/automations-panel.spec.ts`:
- Line 630: Replace the direct locator call that uses the hasText option with
the file's established pattern: use
surface.locator('[data-action="automation-row"]').filter({ hasText: "Single
project digest" }).first().click() so it matches other tests; update the call
referencing surface.locator and the '[data-action="automation-row"]' selector to
use .filter({ hasText }) for consistency.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 38c78c92-5070-4eb9-ba14-4be90816fbfd

📥 Commits

Reviewing files that changed from the base of the PR and between be76df5 and 52ceed9.

📒 Files selected for processing (9)
  • packages/app/e2e/automations/automations-panel.spec.ts
  • packages/app/src/pages/automations/automation-create-dialog.tsx
  • packages/app/src/pages/automations/automation-detail-editors.tsx
  • packages/app/src/pages/automations/automation-detail.tsx
  • packages/app/src/pages/automations/automation-folder-picker.tsx
  • packages/app/src/pages/automations/automations-route.tsx
  • packages/app/src/pages/automations/automations-surface.tsx
  • packages/app/src/pages/layout.tsx
  • packages/app/src/pages/layout/surface-page-context.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/app/src/pages/automations/automation-detail.tsx

@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 `@packages/opencode/src/automation/scheduler.ts`:
- Around line 468-471: The preserved timer logic needs to update the
ScheduledTask.scope when a run is moved to a different scope: after calling
refreshScopedRunOutcome(...) and before/inside scheduleNextInterval(...), detect
if nextScope differs from the current scheduled task's scope and update the
preserved timer entries so they reflect nextScope (i.e. modify the preserved
ScheduledTask.scope stored by preservePendingSchedule()/preserveDueSchedule() or
add a helper to patch those entries). Ensure both code paths that short-circuit
to preservePendingSchedule and preserveDueSchedule update the
ScheduledTask.scope to nextScope so the retained timer fires in the correct
{projectID, ownerDirectory} instead of the old source scope.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a821cbc-c11c-43f2-9bb4-ab2862714eab

📥 Commits

Reviewing files that changed from the base of the PR and between 867d9b6 and 8ec43b3.

📒 Files selected for processing (3)
  • packages/opencode/src/automation/scheduler.ts
  • packages/opencode/src/server/server.ts
  • packages/opencode/test/server/server-listen.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/opencode/src/server/server.ts

Comment thread packages/opencode/src/automation/scheduler.ts Outdated
Astro-Han added a commit that referenced this pull request Jun 12, 2026
Fix the Windows advisory flake in the prompt cancellation race tests.\n\nRoot cause:\n- The tests used a 1 second guard while waiting for cancellation-race checkpoints.\n- Windows CI can legitimately take longer than that to reach the processor-handle checkpoint.\n- The product contract is not that the checkpoint happens within one second; it is that cancellation after the checkpoint still finalizes correctly.\n\nChanges:\n- Introduce a shared 5 second checkpoint timeout for the two adjacent prompt cancellation race tests.\n- Keep the change test-only; no production behavior changes.\n\nVerification:\n- bun test --timeout 30000 test/session/prompt-effect.test.ts -t "cancel after assistant scaffold save finalizes before processor handle|cancel after processor handle creation finalizes before process starts"\n- bun test --timeout 30000 test/session/prompt-effect.test.ts\n- bun run typecheck\n- git diff --check\n- PR CI: all checks passed, including windows-advisory / unit-windows-opencode-session.\n\nFollow-up:\n- This unblocks using a clean dev base when returning to #1274.
@Astro-Han
Astro-Han merged commit a143f92 into dev Jun 12, 2026
34 checks passed
@Astro-Han
Astro-Han deleted the codex/i1271-process-scheduler branch June 12, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows enhancement New feature or request harness Model harness, prompts, tool descriptions, and session mechanics P1 High priority ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Decouple Automation scheduling and execution from UI project selection (process-level scheduler)

1 participant