Skip to content

feat: add automation PR1 contract surface#960

Merged
Astro-Han merged 29 commits into
devfrom
codex/i950-automation-pr1
May 29, 2026
Merged

feat: add automation PR1 contract surface#960
Astro-Han merged 29 commits into
devfrom
codex/i950-automation-pr1

Conversation

@Astro-Han
Copy link
Copy Markdown
Owner

@Astro-Han Astro-Han commented May 28, 2026

Summary

Adds PR1 of #950: the frozen automation contract, an in-memory definition/run store, CRUD and run-history route signatures, the hidden automate tool, replayable automation events, fixtures, and regenerated v2 SDK types.

Why

Issue #950 needs the backend/frontend seam frozen before execution, scheduler, persistence, or UI work can safely build on it. This PR intentionally does not execute automations and keeps the agent-facing tool hidden until the manageability UI slice.

Related Issue

Closes part of #950.

Human Review Status

Pending

Review Focus

Please focus on the frozen contract shape: AutomationDefinition, AutomationRun, terminal reason mapping, route operation IDs, the default-hidden automate tool boundary, and whether the replayable event snapshots are small and complete enough for PR6 frontend work.

Risk Notes

No scheduler, persistence, runNow execution, or frontend wiring is included. AutomationRun is now frozen as a six-state ledger shape: scheduled, running, awaiting_input, succeeded, failed, and stopped. failed is the count-consuming terminal failure bucket and carries a non-null run error, including hard-stop causes such as step_cap and loop_gate; stopped is the no-count terminal bucket for previous_run_awaiting_input, missed_schedule, cancelled, expired, and blocker_lost. awaiting_input is the frozen run state for both permission and question blockers; blocker.kind distinguishes permission from question, and blocker payloads carry only the locator (requestID or callID) because the run-level sessionID owns the session. runNow only creates a scheduled run record as a PR1 contract stub. The default SDK surface under src/gen is unchanged by the existing SDK build script; the app-facing/current v2 SDK surface is regenerated and type-tested. No visible UI changed, so screenshots are not applicable.

How To Verify

Focused opencode tests: 70 passed across automation routes, automate tool, replay, event fixtures, and Identifier timestamp coverage.
Command: bun test test/server/automation-routes.test.ts test/session/id-monotonicity.test.ts test/tool/automate.test.ts test/server/automation-event-fixtures.test.ts test/server/event-replay.test.ts --timeout 30000

SDK generation and type compile: passed; v2 OpenAPI SDK regenerated with the closed automation run, definition, and input contracts.
Command: bun --cwd packages/sdk/js build
Command: bun --cwd packages/sdk/js run typecheck

Opencode typecheck: passed.
Command: bun --cwd packages/opencode typecheck

Screenshots or Recordings

Not applicable: no visible UI changes.

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

    • Full automation system: create/list/get/update/pause/resume/delete automations, trigger runs, and view run history
    • REST endpoints and OpenAPI schemas for automation management
    • New CLI/tool command to create automations
    • Added automation-related event types to replay and event streams
    • Enhanced identifier handling to support automation IDs
    • Validation surface: semantic/field errors surfaced in API and tool responses
  • Tests

    • Comprehensive tests and frozen fixtures for automation routes, events, tools, and ID behavior

Review Change Stack

@Astro-Han Astro-Han added enhancement New feature or request P2 Medium priority app Application behavior and product flows labels May 28, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a9a98dd-ba64-49e0-a0a7-57ae2c54f2d1

📥 Commits

Reviewing files that changed from the base of the PR and between a87cbd2 and 17f7141.

⛔ Files ignored due to path filters (1)
  • packages/sdk/js/src/v2/gen/types.gen.ts is excluded by !**/gen/**
📒 Files selected for processing (7)
  • packages/opencode/src/automation/index.ts
  • packages/opencode/src/id/id.ts
  • packages/opencode/src/server/instance/automation.ts
  • packages/opencode/src/tool/automate.ts
  • packages/opencode/test/server/automation-routes.test.ts
  • packages/opencode/test/session/id-monotonicity.test.ts
  • packages/opencode/test/tool/automate.test.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/opencode/test/tool/automate.test.ts
  • packages/opencode/src/server/instance/automation.ts
  • packages/opencode/src/tool/automate.ts
  • packages/opencode/test/server/automation-routes.test.ts
  • packages/opencode/src/automation/index.ts
  • packages/opencode/src/id/id.ts

📝 Walkthrough

Walkthrough

Adds a typed in-memory Automation feature: Zod schemas, ID types, validation, lifecycle APIs (create/list/get/update/remove/run), Hono REST routes, an "automate" tool, event publishing/replay inclusion, fixtures, SDK event typings, integration into instance routes and tool registry, and extensive tests.

Changes

Automation System Feature

Layer / File(s) Summary
ID System Extension
packages/opencode/src/id/id.ts
Added automation / automation_run prefixes, Prefix type and prefixOf() detection; updated schema(), ascending()/descending()/create() signatures and timestamp() extraction.
Automation Domain and API
packages/opencode/src/automation/index.ts
Full Automation namespace: IDs, Zod schemas for definitions/runs/events, schedule validation, ValidationError shape, in-memory state and lifecycle APIs (create, list, get, update, remove, runNow, runs), pagination, and bus publishing functions.
Validation Helpers and REST Routes
packages/opencode/src/server/instance/automation.ts
Helpers to format ValidationError/Zod issues, automationBodyValidationHook, and AutomationRoutes Hono router for list/create/get/update/pause/resume/delete and runs listing with OpenAPI/Zod wiring and publishing on mutations.
Automate Tool Implementation
packages/opencode/src/tool/automate.ts
Defines AutomateParameters, formatAutomateValidationError(), createAutomateDefinition() (injects sessionID, creates definition, publishes update), and exports AutomateTool.
Fixtures and Event Fixtures
packages/opencode/src/automation/fixtures.ts, packages/opencode/test/server/automation-event-fixtures.test.ts, packages/sdk/js/src/v2/event-types.test-d.ts
Adds parsed automation fixtures (definition, tombstone, run) and frozen event/type fixtures; adds SDK type-level fixtures and negative compile-time tests for invalid run shapes; runtime tests assert fixture parsing.
Route & Tool Registry Integration
packages/opencode/src/server/instance/index.ts, packages/opencode/src/server/routes/instance/index.ts, packages/opencode/src/tool/registry.ts, packages/opencode/script/route-inventory.ts
Wires AutomationRoutes at /automation, re-exports routes, registers AutomateTool (conditional enable), and adds automation route source to route-inventory.
Event Replay & SDK Types
packages/opencode/src/server/event-replay.ts, packages/sdk/js/src/v2/event-types.test-d.ts
Includes automation event types in REPLAYABLE_EVENT_TYPES; adds SDK type-level fixtures and negative tests for invalid Automation.Run shapes.
Comprehensive Tests
packages/opencode/test/server/automation-routes.test.ts, packages/opencode/test/tool/automate.test.ts, packages/opencode/test/server/event-replay.test.ts, packages/opencode/test/session/id-monotonicity.test.ts, packages/opencode/test/tool/registry.test.ts
Extensive Bun tests covering routes behavior, validation/error shapes, deterministic timestamps, no-op update detection, OpenAPI exposure, tool validation/execution, ID schema non-overlap, event-replay assertions, and tool registry visibility.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • Astro-Han/pawwork#949: Related route-inventory updates extending Hono route-source coverage to include new routes such as the automation router.

"🐰 I stitched a schedule with care,
Tasks that wake at dawn's first glare,
Routes and tools now hum along,
Events and IDs sing their song,
Tests keep the burrow tidy and fair."

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.56% 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 PR title 'feat: add automation PR1 contract surface' clearly and directly summarizes the main change: adding the first phase of the automation feature's frozen contract surface.
Description check ✅ Passed The PR description is comprehensive and follows the repository template. It includes all required sections: Summary, Why, Related Issue, Human Review Status, Review Focus, Risk Notes, How To Verify (with concrete test commands and results), Screenshots/Recordings (appropriately marked as N/A), and a fully completed Checklist.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/i950-automation-pr1

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.

@github-actions github-actions Bot added harness Model harness, prompts, tool descriptions, and session mechanics and removed app Application behavior and product flows labels May 28, 2026
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Suggested priority: P2 (includes non-doc, non-test paths outside the low-risk bucket).

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.

Copy link
Copy Markdown

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

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 introduces a new automation framework, including definitions, runs, API routes, and tools. It defines Zod schemas for automation definitions and runs, implements in-memory state management, registers Hono routes under /automation, and adds an automate tool along with generated SDK types and clients. The feedback highlights three key areas for improvement: resolving a pagination reset bug when a cursor is not found in runs, adding an optional now timestamp parameter to update for deterministic testing, and aligning the Effect schema constraints in the automate tool with the Zod schema to prevent unhandled validation crashes.

Comment thread packages/opencode/src/automation/index.ts Outdated
Comment thread packages/opencode/src/automation/index.ts Outdated
Comment thread packages/opencode/src/tool/automate.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 103-121: The Definition and Tombstone Zod schemas currently allow
unknown keys to be stripped; update the exported contract schemas to be strict
by adding .strict() to the object schemas so extra properties are rejected.
Specifically, make each branch of the discriminated union for Definition (the
z.object({...}) for kind "oneshot" and for kind "recurring") call .strict(), and
also call .strict() on the Tombstone z.object(...) schema so unknown fields
cause validation errors; keep the existing .meta(...) and exported type
inference unchanged.

In `@packages/opencode/src/id/id.ts`:
- Around line 95-98: The timestamp(id: string) function currently slices out hex
without validating the id shape; update timestamp to first verify the separator
(variable separator) is found (separator > -1), that the extracted hex substring
(variable hex) has the expected length (at least 12 characters) and matches a
hex regexp /^[0-9a-fA-F]+$/, and if any check fails throw a clear Error
indicating an invalid ID format; then safely convert the hex to BigInt (wrap
parse in try/catch or validate before BigInt) and proceed to compute and return
the timestamp as before.
🪄 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: 8e45e73a-b4e3-4c29-89e8-e2fa81fe81b3

📥 Commits

Reviewing files that changed from the base of the PR and between 7419037 and da5db93.

⛔ Files ignored due to path filters (2)
  • packages/sdk/js/src/v2/gen/sdk.gen.ts is excluded by !**/gen/**
  • packages/sdk/js/src/v2/gen/types.gen.ts is excluded by !**/gen/**
📒 Files selected for processing (17)
  • packages/opencode/script/route-inventory.ts
  • packages/opencode/src/automation/fixtures.ts
  • packages/opencode/src/automation/index.ts
  • packages/opencode/src/id/id.ts
  • packages/opencode/src/server/event-replay.ts
  • packages/opencode/src/server/instance/automation.ts
  • packages/opencode/src/server/instance/index.ts
  • packages/opencode/src/server/routes/instance/index.ts
  • packages/opencode/src/tool/automate.ts
  • packages/opencode/src/tool/registry.ts
  • packages/opencode/test/server/automation-event-fixtures.test.ts
  • packages/opencode/test/server/automation-routes.test.ts
  • packages/opencode/test/server/event-replay.test.ts
  • packages/opencode/test/session/id-monotonicity.test.ts
  • packages/opencode/test/tool/automate.test.ts
  • packages/opencode/test/tool/registry.test.ts
  • packages/sdk/js/src/v2/event-types.test-d.ts

Comment thread packages/opencode/src/automation/index.ts
Comment thread packages/opencode/src/id/id.ts
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

@Astro-Han Astro-Han merged commit 168950d into dev May 29, 2026
29 checks passed
@Astro-Han Astro-Han deleted the codex/i950-automation-pr1 branch May 29, 2026 05:32
Astro-Han added a commit that referenced this pull request Jun 2, 2026
Closes the backend gaps left after PR1-5 so the PR6/PR7 frontend slice can
build on a complete, stable automation contract.

Goal / change boundary:
- model { providerID, modelID } now required on every AutomationDefinition;
  runner passes it through so runs no longer depend on the runtime model
  fallback chain (which drifts across restarts).
- variant? optional reasoning/effort, validated against the live provider
  catalog on create/update; invalid variant returns 422 instead of failing
  late in the run.
- stop.kind === "condition" rejected at create/update with structured
  { field: "stop", message: "unsupported_stop_condition" } (scheduler never
  schedules condition stops, so accepting them only leaked dead UI surface).
- Derived fields nextFireAt / nextFires / failureStreak populated at
  create/update and refreshed after every terminal run; scheduler re-publishes
  automation.definition.updated with a bumped revision for global-sync.
- cron validation consolidated into src/automation/cron.ts; scheduler and
  derived both consume it.
- automate tool schema picks up model/variant + Provider-backed create-time
  validation.
- Migration 20260601100000 drops pre-release rows so model can be NOT NULL.

Verification:
- CI green on 5e177ba (unit-opencode flake on an unrelated VCS-routes
  20s timeout cleared on rerun).
- Local: 129 automation tests (routes/runner/scheduler/event-fixtures/tool/
  cron) + 35 session processor tests pass.

Review follow-ups addressed:
- codex: scheduler self-loop guard keyed by id:revision (not id alone).
- P2: recordRunOutcome retries on ConflictError instead of silently dropping
  the run outcome.
- CodeRabbit: 422 create test uses a guaranteed-invalid model; fixed sleeps
  replaced with terminal-state polling.
- Test seam for the ConflictError path moved off the public Automation API
  into an internal __test_hooks module.

Residual risk / deferred (tracked, not blocking PR6):
- needs_user_input / loop_gate run-error codes remain reserved; producing
  them needs prompt-loop semantics changes.
- Session.automationID reverse lookup deferred (session-contract migration).
- stop=condition kept in the schema layer for SDK shape parity but rejected
  at validate time; collapses once a condition evaluator lands.

Linked: issue #950; follows PR #960 #983 #984 #998 #1004; unblocks PR6/PR7.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant