Adopt Effect internally for typed errors and configurable resilience - #23
Conversation
Replace the scattered try/catch adapters with Effect-based boundaries while keeping the public API Promise-based: - New ts-autocode-training resilience module: named per-operation policies (propose/evaluate/store) composing a per-attempt timeout (typed OperationTimeoutError) with jittered exponential-backoff retries via Effect Schedule, wired through the additive TrainingSettings.resilience field. Without a policy every operation behaves exactly as before. - Training runtime routes all background failures (capture, store, evolve) through one #report boundary into onError; JSON fallbacks become attempt() one-liners. - Harness dispatchAction becomes a linear Effect pipeline whose failure records are best-effort tapError taps; original errors are rethrown unwrapped. AgentActionDeniedError gains a _tag. - Sandbox file operations map errors to their typed fallback values declaratively; ax provider scoring/parsing fallbacks likewise. - rewrite package, loop.ts, and the execution.ts try/finally are left as-is: each is already a minimal, intentional boundary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4PmJx4HSwBjFnCuGXdfwK
|
Warning Review limit reached
Next review available in: 17 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughChangesTraining resilience
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Training
participant withPolicy
participant Engine
participant TrainingStore
Training->>withPolicy: run propose policy
withPolicy->>Engine: call optimize with attempt signal
Engine-->>withPolicy: proposal or failure
withPolicy-->>Training: proposal or retryable failure
Training->>withPolicy: run store policy
withPolicy->>TrainingStore: append training record
TrainingStore-->>withPolicy: persisted record or failure
withPolicy-->>Training: completion or reported store error
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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/harness/src/attempt.ts`:
- Around line 1-17: Synchronize the duplicated attempt helpers in
packages/harness/src/attempt.ts, packages/training/src/attempt.ts, and
src/attempt.ts by making each export the complete shared API: errorMessage,
attempt, and attemptAsync. Preserve the existing implementations and update each
file consistently so the header’s “keep the copies in sync” contract is
accurate.
In `@packages/training/src/attempt.ts`:
- Around line 1-22: Update the `attempt` helper to use the object form of
`Effect.try` with an identity `catch`, so its `fallback` callback receives the
original thrown value rather than an `UnknownException`; leave `attemptAsync`
unchanged.
🪄 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: 984026d9-4087-4af0-9899-da4cf2f26a39
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (16)
README.mdpackage.jsonpackages/harness/package.jsonpackages/harness/src/attempt.tspackages/harness/src/dispatch.tspackages/harness/src/sandbox.tspackages/training/package.jsonpackages/training/src/attempt.tspackages/training/src/index.tspackages/training/src/resilience.tspackages/training/src/training.tspackages/training/test/resilience.test.tspackages/training/test/training.test.tssrc/attempt.tssrc/index.tssrc/providers/ax.ts
Address review findings: the Effect.try shorthand wrapped sync throws in UnknownException, so attempt()'s fallback (and therefore onError in the capture phase) received the wrapper instead of the original error. Use the object form with an identity catch, add a regression test locking the raw-value contract, and make the three duplicated attempt.ts copies byte-identical (errorMessage + attempt + attemptAsync) as their headers promise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4PmJx4HSwBjFnCuGXdfwK
Summary
There was too much scattered try/catch. This adopts the Effect library internally — the public API stays Promise-based and continues to throw/reject — replacing ad-hoc error handling with typed errors at integration boundaries and brand-new, configurable per-operation resilience.
New: injectable resilience policies (
packages/training/src/resilience.ts)Effect-style named policies, exposed as plain config through the additive
TrainingSettings.resiliencefield:timeoutMsfails with a typedOperationTimeoutError(Data.TaggedError, retryable by default) and aborts the attempt'sAbortSignal.Schedule: jittered exponential backoff, capped delay,retryablepredicate, never retried after the caller's signal aborts.withPolicysettles back into an ordinary promise and rethrows the original error unwrapped — no Effect types or fiber wrappers leak to consumers.Simplified error handling
#reportboundary intoTrainingSettings.onError; JSON serialize/parse fallbacks becomeattempt()one-liners; the duplicatederrorMessagehelpers are deduped.dispatchAction: the two record-then-rethrow try/catch blocks become a linearEffect.genpipeline where failure records are best-efforttapErrortaps;AgentActionDeniedErrorgains a_tagdiscriminant.permission_denied,file_not_found,false).execution.tstry/finally (resource cleanup),loop.ts(already a single observer-error boundary), and the rewrite package's three best-effort load-time guards.effect@^3.21.4is added to root,ts-autocode-training, andts-autocode-harness; the rewrite package stays dependency-free. New public exports:OperationTimeoutError,withPolicy,defaultRetry, and theResiliencePolicy/RetryOptions/ResilienceSettings/ErrorPhasetypes.Testing
npm run checkpasses: all four project typechecks, the full Vitest suite (16 files, 93 tests), and the core build.packages/training/test/resilience.test.tscovers passthrough identity, retry-until-success, original-error rethrow on exhaustion, non-retryable predicates, typed timeout with attempt-signal abort, timeout-then-retry, and prompt caller-abort during backoff.onError, no-policy store failure still routes toonError(err, "store"), and a rate-limited engine proposal succeeds under aproposeretry policy.🤖 Generated with Claude Code
https://claude.ai/code/session_01W4PmJx4HSwBjFnCuGXdfwK
Generated by Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests