Skip to content

feat(core-loop): scheduler decision drives harness/weight/both branch (#90) - #161

Merged
micahstubbs merged 1 commit into
mainfrom
claude/issue-90-scheduler-drives-loop
Jun 7, 2026
Merged

feat(core-loop): scheduler decision drives harness/weight/both branch (#90)#161
micahstubbs merged 1 commit into
mainfrom
claude/issue-90-scheduler-drives-loop

Conversation

@micahstubbs

Copy link
Copy Markdown
Owner

Closes #90.

The scheduler decision was recorded-only; the loop always ran the harness update. Now run_generation_with acts on it:

  • src/closed_loop.rs: ActedDecision {Harness, Weight, Both} + action_for_decision(&str) + record_acted_decision(...) (annotates scheduler_decision.json with the acted decision + weight-update summary).
  • src/orchestrator.rs: derive the acted decision from the recorded scheduler decision and branch:
    • harness → meta/feedback harness update (today's behavior),
    • weight → run the weight update (StubWeightUpdater via maybe_run_weight_update) and short-circuit the feedback step,
    • both → weight update + feedback.
      The acted decision is written back to scheduler_decision.json (SIA Studio reads it) and an **ADAPTIVE SCHEDULER DECISION** addendum is threaded into the next generation's feedback context.
  • Tests: forced weight-vs-harness decisions in tests/generation_loop.rs; closed_loop unit tests.

Backward-compat: with no scheduler decision (the default in existing tests, no results.json), action defaults to harness, the feedback agent runs as before, and nothing is appended to the parity-checked feedback text — so the default path is byte-identical and existing assertions pass unmodified.

Gate green: fmt/clippy/test (default + --features llm) + parity OK.

https://claude.ai/code/session_01WX3ZN9azxr1fyWuZAaRJ7Y


Generated by Claude Code

The adaptive scheduler (#65) + weight-update path (#19) were wired into
run_generation_with only observationally (#84): the orchestrator recorded a
per-generation scheduler_decision.json but always ran the meta/feedback harness
update and never acted on the recommendation.

Close the loop so the decision drives real control flow:

- closed_loop: add ActedDecision { Harness, Weight, Both } + action_for_decision
  (defaults unknown/empty -> Harness) and record_acted_decision, which annotates
  scheduler_decision.json with acted / harness_ran / weight_ran / weight_update
  (read by web::runs / SIA Studio). Build on #139's StubWeightUpdater.
- orchestrator: branch the per-generation action on the decision —
    harness -> run the meta/feedback harness update (today's behavior),
    weight  -> run the weight update and SKIP the feedback step,
    both    -> run both.
  The acted decision + weight outcome are recorded and threaded into the
  feedback context for the next generation (appended only when a decision
  exists, so build_feedback_context's parity-checked output is untouched).

Backward-compat: when no decision is produced (no results.json -> the default
in existing tests) the action defaults to harness and the feedback agent runs
exactly as before. The injectable target/feedback seams are unchanged.

Tests: offline integration tests drive run_generation_with with a forced
weight vs harness decision (asserting feedback skipped/called and the acted
decision recorded), plus closed_loop unit tests for the action mapping and
record_acted_decision. Full gate green (fmt, clippy default+llm, test
default+llm, parity byte-identical).

https://claude.ai/code/session_01WX3ZN9azxr1fyWuZAaRJ7Y
@micahstubbs
micahstubbs merged commit 5fb292a into main Jun 7, 2026
15 checks passed
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.

Scheduler decision is observational only — make it actually drive the generation loop

1 participant