Commit 3148aee
feat: post-PR CI gate — watch, legitimate-fix, promote to ready (#57)
* feat(schemas): add check_ci config + ci_fixer role + CI-gate result schemas
Introduces the configuration surface for the post-PR CI gate without changing
runtime behaviour.
- BuildConfig.check_ci (default true) plus max_ci_fix_cycles, ci_wait_seconds,
and ci_poll_seconds caps. ExecutionConfig mirrors these so they round-trip
through to_execution_config_dict().
- New ci_fixer model role registered in ROLE_TO_MODEL_FIELD so the CI fixer
picks up the runtime base default and can be overridden via
models.ci_fixer like any other role.
- New Pydantic models — CIFailedCheck, CIWatchResult, CIFixResult — for the
watcher and fixer result envelopes. BuildResult gains ci_gate_results so
callers can inspect the gate outcome alongside pr_results.
Tests cover the new role property, the new config defaults, and round-trip
through BuildConfig -> ExecutionConfig.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(ci_gate): deterministic gh-CLI watcher + mark_pr_ready helper
The post-PR CI gate needs to poll GitHub Actions on a draft PR, fetch the
failed-job log tail, and promote the PR to ready-for-review. All of that is
shell-and-state, no LLM, so it lives in a standalone helper module that the
reasoners thinly wrap.
watch_pr_checks accepts injectable runner/sleep/now callables so the polling
loop is unit-testable without invoking gh, sleeping in real time, or hitting
GitHub. Handles the corner where `gh pr checks` exits non-zero with a valid
JSON body (its convention when any check is failing) by trusting the body.
Tests cover happy-path pass, failure with log capture, multi-poll until
conclusive, wall-clock timeout, no-checks-on-PR, gh-failure-with-no-payload,
and the mark_pr_ready success/failure paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(reasoners): add run_ci_watcher and run_ci_fixer
run_ci_watcher is a thin reasoner around watch_pr_checks — no LLM, just
polling + log capture. run_ci_fixer is the agentic counterpart: it gets the
failing checks (with truncated logs) and must produce a legitimate fix
committed and pushed to the PR's integration branch.
The CI-fixer system prompt explicitly forbids the workarounds the model
would otherwise reach for: pytest.skip / xfail / it.skip, commenting tests
out, deleting tests, loosening assertions to make red green, swallowing
errors with try/except: pass, disabling CI jobs, snapshotting the bug, or
mocking the unit under test. The agent is told to fix the production code
and asked to enumerate rejected workarounds in the response as an audit
trail. Editing the test is allowed only when it asserts something the spec
doesn't require, with explicit justification.
Both reasoners are exposed via swe_af.fast wrappers and the fast-router
reasoner-count test is updated from 8 to 10.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(build): wire post-PR CI gate into the build pipeline
After the draft PR is opened, _run_ci_gate runs a bounded
watch -> fix -> repush loop and promotes the PR with `gh pr ready` only
once CI is green. Wired into both the multi-repo and single-repo PR paths
so all PRs go through the same gate. Each repo's gate result is captured
in BuildResult.ci_gate_results for visibility.
The loop is bounded by cfg.max_ci_fix_cycles (default 2) and
cfg.ci_wait_seconds (default 1500s per watch). Failure modes are explicit
final_status values — failed_exhausted, fixer_gave_up, timed_out, error,
no_checks — so callers can distinguish "gave up after N tries" from
"never produced a fix" or "CI never ran". When the gate gives up, the PR
is left in draft so a human reviewer sees it needs attention.
Default behaviour is check_ci=true. Setting check_ci=false reverts to the
legacy "create draft PR and exit" flow.
README documents the gate behaviour, the no-workarounds contract, and the
four config knobs (check_ci, max_ci_fix_cycles, ci_wait_seconds,
ci_poll_seconds).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent d9eb2fe commit 3148aee
10 files changed
Lines changed: 1306 additions & 6 deletions
File tree
- swe_af
- execution
- fast
- prompts
- reasoners
- tests
- fast
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
512 | 512 | | |
513 | 513 | | |
514 | 514 | | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
515 | 534 | | |
516 | 535 | | |
517 | 536 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| |||
169 | 170 | | |
170 | 171 | | |
171 | 172 | | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
172 | 303 | | |
173 | 304 | | |
174 | 305 | | |
| |||
622 | 753 | | |
623 | 754 | | |
624 | 755 | | |
| 756 | + | |
625 | 757 | | |
626 | 758 | | |
627 | 759 | | |
| |||
676 | 808 | | |
677 | 809 | | |
678 | 810 | | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
679 | 830 | | |
680 | 831 | | |
681 | 832 | | |
| |||
770 | 921 | | |
771 | 922 | | |
772 | 923 | | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
773 | 943 | | |
774 | 944 | | |
775 | 945 | | |
| |||
793 | 963 | | |
794 | 964 | | |
795 | 965 | | |
| 966 | + | |
796 | 967 | | |
797 | 968 | | |
798 | 969 | | |
| |||
0 commit comments