Single-responsibility modules, harness role defaults, standard fs seam for bus storage - #17
Conversation
Boyscout pass over the recent bus work and its relatives:
- bus.ts owns only the bus and the AgentBusStore seam. The store
implementations move to their own modules as real classes:
MemoryBusStore (memory-store.ts, the default) and FileBusStore
(file-store.ts, owning all file IO, serialization, and recovery).
The createFileBusStore/createMemoryBusStore closure factories and the
implementation-specific FileBusStore interface are gone — abstractions
stay where multiple implementations justify them (AgentBusStore), and
implementations are classes.
- The harness package entry no longer carries the run loop: the
implementation lives in harness.ts and index.ts is a pure re-export
barrel, matching the training and rewrite packages.
- windowedContext moves out of the harness-loop adapter into its own
provider module (src/providers/context.ts) — context management and
loop adaptation are separate concerns.
- Training's createMemoryTrainingStore closure factory becomes the
MemoryTrainingStore class.
- The harness README example still showed the removed { file } bus
settings; corrected to the store API.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NG6fSKqgt8nD7JnEY9q245
|
Warning Review limit reached
Next review available in: 47 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 (3)
📝 WalkthroughWalkthroughThe PR adds a configurable training harness with explicit public contracts, adversarial rubric progression, injectable context and judge collaborators, JSONL bus persistence, and a class-based in-memory training store. ChangesTraining harness and storage
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant TrainingHarness
participant Teacher
participant Judge
participant Adversary
participant JsonlBusStore
Client->>TrainingHarness: run student and teacher callbacks
TrainingHarness->>Judge: gate action and verdict
TrainingHarness->>JsonlBusStore: append harness evidence
TrainingHarness->>Adversary: challenge passing candidate
Adversary-->>TrainingHarness: return challenge feedback
TrainingHarness->>Teacher: revise rubric when challenge succeeds
TrainingHarness-->>Client: return immutable harness run
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 |
Only student and teacher are required to run the harness. Every other
role defaults under one evidence convention (feedback is the verdict):
the judge passes a candidate when the teacher reports no feedback and
lets a challenge stand when the adversary reports evidence; a missing
adversary accepts passing candidates; rubric revision appends the
challenge evidence as new criteria; the bus defaults to memory and is
returned on the run result for auditing. The adversary now reports
AdversaryResult { challenge, feedback }, mirroring TeacherResult.
createHarnessLoop no longer hardcodes any collaborator: the bus is
built by an injectable factory (file-backed write-ahead log only as
the default), the judge is injectable, and the training-specific
judge/reviseRubric/candidateId boilerplate is deleted outright —
training promotes exactly when a review reports no gate failures, so
the harness defaults are equivalent by construction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NG6fSKqgt8nD7JnEY9q245
…seam MemoryBusStore and FileBusStore reinvented what the ecosystem already standardizes. JsonlBusStore is now the only shipped store: an append-only JSONL log written through BusFileSystem — the slice of the node:fs/promises API it uses, the TypeScript equivalent of C#'s IFileProvider or Python's fsspec. Inject node:fs/promises for disk (the default), a memfs volume's promises for memory (JsonlBusStore.inMemory(), the bus's default store), or any fs-compatible implementation for remote storage. The AgentBusStore seam stays for services that store entries natively. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NG6fSKqgt8nD7JnEY9q245
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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/harness.ts`:
- Around line 40-43: Update JudgeRequest and the configured judge flow to
include teacher/adversary feedback in both candidate and adversary request
variants and their constructed payloads. Type the judge callback with the
JudgeRequest union so it receives the correct request shape, while preserving
existing assessment and challenge fields and default verdict behavior.
- Around line 220-229: After the awaited dispatch in the final rubric revision
flow, check input.signal using the same cancellation handling as the other actor
calls before parsing revision.rubric or mutating state. Ensure cancellation
aborts this path instead of returning "exhausted"; leave the non-cancelled
revision behavior unchanged.
In `@README.md`:
- Around line 206-210: Update the evidence-policy wording in the README
paragraph to state that candidates pass exactly when reviews report no gate
failures by default, reflecting that a configured judge may override the
fallback decision. Keep the surrounding discussion of re-review, challenge
tightening, and baseline results 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: 1e0c8dcf-7cbc-4b55-a29d-a2a9a280fc5c
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (14)
README.mdpackages/harness/README.mdpackages/harness/package.jsonpackages/harness/src/bus.tspackages/harness/src/harness.tspackages/harness/src/index.tspackages/harness/src/jsonl-store.tspackages/harness/test/harness.test.tspackages/training/src/index.tspackages/training/src/records.tspackages/training/src/training.tssrc/index.tssrc/providers/context.tssrc/providers/harness.ts
Candidate and adversary judge requests now carry the same feedback the default verdicts weigh, and the judge callback is typed with the JudgeRequest union instead of unknown, so a configured judge can apply the evidence convention even with windowed or redacted bus context. The rubric-revision path checks the abort signal after its dispatch like every other actor call, and the root README qualifies the evidence policy as the default a configured judge may override. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NG6fSKqgt8nD7JnEY9q245
Summary
Three rounds of cleanup on one branch:
createHarnessLoopno longer hardcodes any collaborator.MemoryBusStore/FileBusStorepair is replaced by oneJsonlBusStorewritten through thenode:fs/promisesAPI surface — the TypeScript equivalent of C#'sIFileProvideror Python's fsspec — with memfs supplying the in-memory case instead of a hand-rolled array store.Changes
Harness package — single-responsibility modules
bus.tsowns only the bus:WriteAheadAgentBus, theAgentBusStoreseam, and the access/settings types. All file IO, serialization, and recovery logic left the module.defineTrainingHarnessand the harness types live inharness.ts, andindex.tsis a pure re-export barrel.Harness package — bus storage over the standard filesystem seam
JsonlBusStoreis the only shipped store: an append-only JSONL log (synced per append, resilient to an incomplete trailing line) written throughBusFileSystem— the slice ofnode:fs/promisesit uses. Injectnode:fs/promisesfor disk (the default), a memfs volume's.promisesfor memory (JsonlBusStore.inMemory(), the bus's default store), or any fs-compatible implementation (ZenFS and friends) for remote storage.AgentBusStorestays as the entry-level seam for services that store entries natively (a database, a queue).Harness package — role defaults
studentandteacherare required. Every other role defaults under one evidence convention (feedback is the verdict): the judge passes a candidate when the teacher reports no feedback and lets a challenge stand when the adversary reports evidence; a missing adversary accepts passing candidates without review; the default rubric revision appends the challenge evidence as new criteria; the bus defaults to memory and is returned on the run result for auditing; candidate identity defaults to the candidate's string form for stall detection.AdversaryResult { challenge, feedback }, mirroringTeacherResult, so its evidence can drive the default judge.Root package — inversion of control in the loop adapter
windowedContext/defaultContextWindowmove out of the harness-loop adapter into their own module (src/providers/context.ts).createHarnessLoophardcodes nothing:busis an injectable per-run factory (the file-backed write-ahead log is only the default), andjudgeandcontextProviderare injectable. The hand-written judge/reviseRubric/candidateId callbacks are deleted outright — training promotes a candidate exactly when its review reports no gate failures (promotion.ts), so the harness defaults are equivalent by construction.Training package
createMemoryTrainingStore()becomes theMemoryTrainingStoreclass (same clone-on-read/write semantics).Docs
Testing
npm run check(typecheck for all packages, full test suite — 82 tests across 15 files, and the package build) passes, including new tests for the student-plus-teacher-only run, the evidence convention, and running the JSONL store over a memfs volume.🤖 Generated with Claude Code
https://claude.ai/code/session_01NG6fSKqgt8nD7JnEY9q245
Generated by Claude Code
Summary by CodeRabbit
New Features
MemoryTrainingStoreclass.Documentation