Skip to content

Single-responsibility modules, harness role defaults, standard fs seam for bus storage - #17

Merged
Tyler-R-Kendrick merged 4 commits into
mainfrom
claude/interface-redundancies-consolidate-8juzw3
Jul 12, 2026
Merged

Single-responsibility modules, harness role defaults, standard fs seam for bus storage#17
Tyler-R-Kendrick merged 4 commits into
mainfrom
claude/interface-redundancies-consolidate-8juzw3

Conversation

@Tyler-R-Kendrick

@Tyler-R-Kendrick Tyler-R-Kendrick commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

Three rounds of cleanup on one branch:

  1. Boyscout pass on the bus work from Storage-agnostic agent bus, consumer-owned context, parse-don't-validate #16 and the same disease elsewhere: modules were carrying unrelated concerns, and closure factories stood where classes belong.
  2. Defaults and dependency inversion: every harness role has a default implementation, so a run needs only a student and a teacher — and createHarnessLoop no longer hardcodes any collaborator.
  3. Standard IO seam: the bespoke MemoryBusStore/FileBusStore pair is replaced by one JsonlBusStore written through the node:fs/promises API surface — the TypeScript equivalent of C#'s IFileProvider or Python's fsspec — with memfs supplying the in-memory case instead of a hand-rolled array store.

Changes

Harness package — single-responsibility modules

  • bus.ts owns only the bus: WriteAheadAgentBus, the AgentBusStore seam, and the access/settings types. All file IO, serialization, and recovery logic left the module.
  • The package entry no longer carries the run-loop implementation: defineTrainingHarness and the harness types live in harness.ts, and index.ts is a pure re-export barrel.

Harness package — bus storage over the standard filesystem seam

  • JsonlBusStore is the only shipped store: an append-only JSONL log (synced per append, resilient to an incomplete trailing line) written through BusFileSystem — the slice of node:fs/promises it uses. 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 (ZenFS and friends) for remote storage.
  • AgentBusStore stays as the entry-level seam for services that store entries natively (a database, a queue).

Harness package — role defaults

  • Only student and teacher are 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.
  • The adversary now reports AdversaryResult { challenge, feedback }, mirroring TeacherResult, so its evidence can drive the default judge.

Root package — inversion of control in the loop adapter

  • windowedContext/defaultContextWindow move out of the harness-loop adapter into their own module (src/providers/context.ts).
  • createHarnessLoop hardcodes nothing: bus is an injectable per-run factory (the file-backed write-ahead log is only the default), and judge and contextProvider are 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 the MemoryTrainingStore class (same clone-on-read/write semantics).

Docs

  • Harness README documents the two-callback minimal run, the evidence convention, and the two storage seams; the root README documents the injectable loop collaborators.

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

    • Added configurable training harness workflows with injectable message storage, judging, and context management.
    • Added rolling-window context support to limit recent activity used during training.
    • Added append-only JSONL storage with in-memory and filesystem-backed options.
    • Added adversarial review and rubric-revision handling for stronger candidate validation.
    • Replaced the memory training-store factory with a reusable MemoryTrainingStore class.
  • Documentation

    • Clarified training-round evidence requirements, configuration options, defaults, and runnable examples.

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

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Tyler-R-Kendrick, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d0a604e-de4a-4bd0-a726-6834e2c65850

📥 Commits

Reviewing files that changed from the base of the PR and between ef5c844 and be23403.

📒 Files selected for processing (3)
  • README.md
  • packages/harness/src/harness.ts
  • src/providers/harness.ts
📝 Walkthrough

Walkthrough

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

Changes

Training harness and storage

Layer / File(s) Summary
Harness contracts and round orchestration
packages/harness/src/harness.ts, packages/harness/src/index.ts, packages/harness/test/harness.test.ts, packages/harness/README.md
Defines harness types and defineTrainingHarness, adds evidence-based round and adversarial verdict handling, and updates examples and tests for structured results and defaults.
JSONL bus storage and recovery
packages/harness/src/jsonl-store.ts, packages/harness/src/bus.ts, packages/harness/test/harness.test.ts, packages/harness/package.json, packages/harness/README.md
Adds injectable JsonlBusStore persistence with in-memory filesystem support, replaces removed bus-store helpers, and tests sequence recovery across filesystem and memfs instances.
Context and harness provider wiring
src/providers/context.ts, src/providers/harness.ts, src/index.ts, README.md
Adds validated rolling-window context, injectable bus and judge options, default JSONL action logging, and structured adversary output with updated configuration documentation.
Training memory store migration
packages/training/src/records.ts, packages/training/src/training.ts, packages/training/src/index.ts, src/index.ts
Replaces createMemoryTrainingStore with the exported MemoryTrainingStore class and updates runtime construction and public exports.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main refactor themes: module separation, harness default roles, and injectable bus storage.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/interface-redundancies-consolidate-8juzw3

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.

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
@Tyler-R-Kendrick Tyler-R-Kendrick changed the title Single-responsibility modules: store classes over closure factories Single-responsibility modules, harness role defaults, injectable harness loop Jul 12, 2026
…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
@Tyler-R-Kendrick Tyler-R-Kendrick changed the title Single-responsibility modules, harness role defaults, injectable harness loop Single-responsibility modules, harness role defaults, standard fs seam for bus storage Jul 12, 2026

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 41ff6c5 and ef5c844.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (14)
  • README.md
  • packages/harness/README.md
  • packages/harness/package.json
  • packages/harness/src/bus.ts
  • packages/harness/src/harness.ts
  • packages/harness/src/index.ts
  • packages/harness/src/jsonl-store.ts
  • packages/harness/test/harness.test.ts
  • packages/training/src/index.ts
  • packages/training/src/records.ts
  • packages/training/src/training.ts
  • src/index.ts
  • src/providers/context.ts
  • src/providers/harness.ts

Comment thread packages/harness/src/harness.ts Outdated
Comment thread packages/harness/src/harness.ts
Comment thread README.md Outdated
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
@Tyler-R-Kendrick
Tyler-R-Kendrick merged commit 578c640 into main Jul 12, 2026
3 checks passed
@Tyler-R-Kendrick
Tyler-R-Kendrick deleted the claude/interface-redundancies-consolidate-8juzw3 branch July 12, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants