fix(flows): check the repository the way its CI does, and never throw the work away - #98
Conversation
… the work away The generated flow ran one hard-coded recipe (npm ci && npm test behind a lockfile detector) and treated its exit code as the whole verdict, so a failing test step killed the run with the agents' finished work unpushed. Two production runs died that way: - AgentWorkforce/cloud acbe30c1: cloud's suite needs @cloud/core built first, which its CI does and the recipe did not. - AgentWorkforce/relay 139d1a46: the branch passed all 3,227 tests in a clean shell of the same sandbox, but 18 failed inside the flow, among them `transport 'file' not allowed` from Cloud's own git configuration. The check step is now language-agnostic and resilient: - The check script (.relayflow/check.sh) comes from the author's checkCommand, a committed .relayflow/check.sh, a discovery agent that reads CI config, Makefile/justfile and README, or an ecosystem default (make/just test, Node, Cargo, Go, Python, Ruby, Maven, Gradle, .NET, Mix). - Each check step prints one token and exits 0; output goes to .relayflow/*.log and its tail to stderr for the journal. The check runs without Cloud's GIT_CONFIG_* hardening and stops itself before the 15-minute f.run lease. - A repair agent (two attempts) fixes missing setup in check.sh or bugs in the change, never by weakening tests. - What still fails is compared with the base commit in a throwaway worktree. The branch is always pushed and the pull request opens as a draft with the verdict, the script and both outputs in its body. A change that breaks checks the base passes ends step_failed; a failure the base shares ends needs_human after the reviews. - Working files (summary.md, plans, reviews, .relayflow/, kit files) are excluded through .git/info/exclude and, if an agent committed them anyway, removed from the branch before every push. Both production runs had Codex commit summary.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 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 |
|
Preview deployed!
This is a Cloudflare Workers preview version of this PR's build. |
… setup
Check discovery ran once, before the implementer. On a repository with no
way to test itself it resolved "none", and a change that added the first
package.json and test script shipped without any check running: dev run
53f1bc98 opened AgentWorkforce/cloud-e2e-sandbox#31 with tests the flow
never ran ("no checks ran"). A "none" is now resolved again after the
implementer; any other answer is kept, so the base commit and the branch
are still checked the same way.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A software-factory run against a repository the size of AgentWorkforce/cloud spends most of an hour in the implementer before its CI-equivalent checks even start (dev run af3069c9: implementer still working at 39 minutes of 60, checks not started). One hour leaves no room for checks, repair and a base comparison. Cloud's own run ceiling is being raised to match in a separate AgentWorkforce/cloud PR; until that lands the hosted run is still cut at its ~55-minute cloud limit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…n macOS, own new checks Three Bugbot findings on the resilient check step: - Base comparison used a cleaner tree. The branch's checks ran in a tree the implementer had built in; the base ran in a fresh worktree, so a default that builds nothing (make test, python3 -m pytest) could fail there for missing setup and turn a real regression into "pre-existing". The base is now checked in the same tree (ignored build products stay), then the branch is restored by name and anything the base run changed in tracked files is discarded; a tree with uncommitted tracked changes still uses a worktree. - No limiter without `timeout`. macOS ships neither `timeout` nor `gtimeout`, so a hung check ran into the 15-minute f.run lease and failed the run before anything was pushed. `gtimeout` and a small Perl limiter (own process group, whole group stopped, exit 124) are now fallbacks. - Checks the change introduced read as pre-existing. When the first resolve found nothing and the change added the test setup, the base lacks those files and always fails. Such a failure is now baseline "new": reported as the change's own and ended step_failed, like a regression. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1854914. Configure here.
…it is committed The same-tree base comparison checked out the base commit in place and then ran .relayflow/check.sh from that tree. A repository that commits the script had it replaced or deleted by the checkout, so the base ran a different recipe or reported none. The branch's script is now copied aside first and both sides run it, as the worktree fallback already did. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Why
The generated software-factory flow ran one hard-coded recipe —
npm ci && npm testbehind a lockfile detector — and treated its exit code as the whole verdict.f.runhas no retry policy, so a failing test step ended the run asretries_exhaustedwith the agents' finished work unpushed and no test output anywhere a user could see. Two production runs today:acbe30c1— the test step failed onAssertionError: @cloud/core dist missing — run npm run -w @cloud/core build before this test. Cloud's CI builds core first (ci.yml:333); the recipe never did, so every run against cloud fails at this step whatever the ticket. Building core first in the same sandbox made the whole suite pass, agents' commit included.139d1a46— 18 tests failed inside the flow. In a clean shell of the same sandbox the agents' branch passed all 3,227 (base: 3,173, 0 failed). One cause is proven: Cloud's executor passes its own git hardening (protocol.allow=never,GIT_CONFIG_GLOBAL=/dev/null) to every step, which reproducesfatal: transport 'file' not allowedinsandbox-repo.test.ts. (The executor side is being fixed separately in cloud.)Also: Codex committed
summary.mdinto the branch in both runs, as in AgentWorkforce/flows#454.What changes in the generated flow
Finding the check command, for any language.
.relayflow/check.shcomes from, in order:checkCommandconstant in the flow;.relayflow/check.shthe repository commits;testtarget, Node (unchanged pnpm/Yarn/Bun/npm logic), Cargo, Go, Python (uv/poetry/pip), Ruby, Maven, Gradle, .NET, Mix;none: nothing runs, and the PR says so.Running it resiliently. Every check step prints one token (
pass/fail/timeout/none) and exits 0. Full output goes to.relayflow/*.log, and its tail goes to stderr for the journal. The script runs without Cloud'sGIT_CONFIG_*hardening, and stops itself at 14 minutes, before the 15-minutef.runlease would kill the run.Repair, then compare. On failure, a repair agent (up to 2 attempts) reads the log and fixes missing setup by editing
check.sh(as CI does) or fixes bugs in the change. It never skips or weakens tests. Whatever still fails is run on the base commit in a throwaway worktree:needs_humanneeds_humanstep_failed(the flow's verdict on its own work, like a failed review)needs_humanThe branch is always pushed; work is never thrown away. The PR body is
summary.mdplus a## Checkssection containing the verdict, the script that ran, the output tails and any repair notes. In the traditional preset, the fixer's revision is checked the same way. If it breaks checks that passed before it, it is still pushed, the PR goes back to draft with the report, and the run endsstep_failed.Working files.
summary.md, the plans and reviews,.relayflow/and the local kit files are excluded via.git/info/exclude, using root-anchored patterns so adocs/summary.mdis still committed. If an agent committed them anyway, they're removed before every push by a plumbing commit built from a private index, so staged but uncommitted work is never swept in. Only files absent from the base commit are removed, so a repository's ownsummary.mdsurvives.Local kit: START-HERE, the run requirements and the preflight exemptions are updated to match.
Verification
npx vitest run(web): 19 files, 182 tests pass. The new real-shell tests use real git repositories for resolve (every ecosystem,none), run (pass/fail/none/timeout, Cloud's git config not reaching tests with a positive control), base comparison (regression vs pre-existing, worktree cleanup, unknown base), exclude, drop (keeps a pre-existingsummary.md, never sweeps staged work, identity fallback), and the report. The generated flow is also executed with a mocked context for each branch.tsc --noEmit(web): clean.flows check: all 3 presets × cloud/local pass on 2.0.15 and 2.0.17.flows checkalso passes a flow referencing an undefined variable, so the generated flows were additionally checked with stricttscagainst the 2.0.17 surface types: all 6 clean, and a deliberately broken control fails.Follow-ups (not in this PR)
checkCommandin the flow or commit.relayflow/check.sh.🤖 Generated with Claude Code
Note
High Risk
Changes core generated flow behavior (git, push/PR, check execution, and completion reasons) across all presets; mistakes could publish wrong PR state or mis-classify check failures.
Overview
Replaces the software-factory flow’s single hard-coded npm test step with repository-aware checks via
.relayflow/check.sh, plus agents and shell helpers that resolve, run, repair, and compare results against the base commit.Check pipeline. Before implementation, the flow settles a check script from
checkCommand, a committed.relayflow/check.sh, a check-discovery agent (CI/Makefile/README), or ecosystem defaults (make, Node, Rust, Go, Python, etc.). Checks return one token (pass/fail/timeout/none) and always exit 0; logs live under.relayflow/. On failure, check-repair runs up to twice; if checks still fail, the same recipe runs on the starting commit to tell regressions from pre-existing breakage. Failed runs push draft PRs with a## Checksreport (notretries_exhaustedwith unpushed work). Regressions endstep_failed; shared base failures still open drafts and can continue to review.Git hygiene. Working artifacts (
summary.md, plans,.relayflow/, kit files) are excluded via.git/info/excludeand stripped from the branch before push if agents committed them. PR bodies use.relayflow/pr-body.md. Fixer revisions get the same check/repair path; breaking previously passing checks drafts the PR again.Product tweaks. New agent roles and onboarding labels; local/cloud wall-clock budget 1h → 2h; onboarding and START-HERE copy describe CI-aligned checks and
checkCommand. Extensive vitest coverage for the new shell commands and generated flow behavior.Reviewed by Cursor Bugbot for commit 38312f6. Bugbot is set up for automated code reviews on this repo. Configure here.