Skip to content

feat(recipes): ruflo swarm → acceptance gate via a host-side supervisor - #101

Merged
SollanSystems merged 3 commits into
mainfrom
feat/ruflo-recipe
Jul 25, 2026
Merged

SollanSystems merged 3 commits into
mainfrom
feat/ruflo-recipe

Conversation

@SollanSystems

Copy link
Copy Markdown
Owner

Closes #38.

ruflo (ruvnet/claude-flow renamed; pinned 3.32.9) integrated per the shipped recipe pattern with ZERO engine and ZERO kernel changes — via the seam that actually exists: a host-side supervisor around the blocking hive-mind spawn --claude CLI (examples/ruflo-gate/swarm_example.py), because the issue's stated hook seam does not (see the re-scope comment on #38). The swarm's success == exit 0 is SELF-REPORT the acceptance gate replaces: criteria come from the memory-export sparc-phases acceptanceCriteria, the swarm's own sparc-gates verdicts are read but never trusted, and the gate/projection/emit/doctor/metrics path executes for real against a committed fixture replay of a recorded .swarm/ tree (scripts/test_ruflo_recipe.py, deterministic, credential-free). Traps encoded from the verified dossier: Ctrl-C exits 0, so AbortedByHuman comes only from the supervisor's own SIGINT handler; ruflo verify --json is install-integrity, not a run verdict. Live mode is documented but deliberately not CI-run (needs Node + claude + credentials); the new recipe-ruflo CI job runs the fixture path.

Also lands the dossier-mandated prerequisite: the ST3 spec §5.4 ruflo snippet was fiction (ruflo.orchestrate()/.merged_diff/.converged exist nowhere) — rewritten against the real surface as a dated correction.

Rebased onto post-#94/#99 main conflict-free; recipe tests 7 passed / 1 skipped post-rebase.

The original 5.4 sketched ruflo.orchestrate() returning .visible/.holdout/
.merged_diff/.agent_trails/.converged/.rounds/.criteria_met. No such API
exists: ruflo is a Node CLI with no Python package and no result object with
those fields. The section also assumed a swarm-terminal hook to register the
gate on; the plugin HookEvent enum carries no swarm-level terminal event
(swarm:consensus-reached appears only in ruflo's docs).

Rewritten as a dated correction against the verified surfaces: the blocking
hive-mind spawn --claude invocation, the .swarm/ JSON files, the memory
export's sparc-phases criteria vocabulary, and the supervisor-owned interrupt
flag. Research dossier: review/recipes/2026-07-25-ruflo-api-research.md.
A host-side supervisor around ruflo's blocking swarm CLI, replacing the
swarm's self-report with a real gate. ruflo hive-mind spawn --claude spawns
the Claude Code CLI as the swarm's body and maps exit 0 to success; the
sparc-gates memory namespace holds the swarm's own per-phase pass rows and
truthScore. The supervisor reads only host-side surfaces, runs the withheld
holdout split plus the anticheat trajectory sweep over the agent trails,
projects through to_terminal_state and records via loop.emit. Zero ruflo
changes, zero loop/ kernel changes.

Three traps pinned by tests: ruflo exits 0 on Ctrl-C, so AbortedByHuman comes
from the supervisor's own signal flag and never from the exit code; ruflo
verify is install-integrity, not a run verdict, so it is never wired as the
gate; the sparc-gates self-verdict stays green under sabotage while the gate
refuses. Plus the false-completion invariant and a FailedSpecGap demo for a
declared criterion no check covers.

Deterministic and credential-free: the example replays the committed
examples/ruflo-gate/fixture/ recording by default (--live opts into the real
invocation), stated plainly in the README. Only the swarm is recorded - the
gate, projection, emit, doctor and metrics path all execute for real. The
opt-in live schema-drift alarm is skipped unless LOOP_RUFLO_LIVE=1.

Verified against ruflo 3.32.9 (2026-07-25).
Anchored directly after action-dogfood so a sibling recipe can land after
recipe-temporal without a conflict. No npm, no Node, no credentials: the job
installs only pyyaml/pytest/jsonschema and runs the fixture-replay recipe
suite, matching the other recipe jobs' cost profile.
Copilot AI review requested due to automatic review settings July 25, 2026 16:55
@SollanSystems
SollanSystems enabled auto-merge (squash) July 25, 2026 16:55
@SollanSystems
SollanSystems merged commit c1d5a93 into main Jul 25, 2026
13 checks passed
@SollanSystems
SollanSystems deleted the feat/ruflo-recipe branch July 25, 2026 16:56

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 93061accca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

obs = observe(ws)

gate = holdout_gate.decide(visible_checks(ws), holdout_checks(ws))
ac = anticheat_scan.scan(diff_text="", trajectory=agent_trails(obs))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Scan the live workspace diff

When a live swarm edits a gate or CI file, injects skipped tests, or adds tautological assertions, this call always supplies an empty diff, disabling every diff-based critical/high signature in anticheat_scan.scan; the trajectory scan only detects answer-path reads and cannot compensate. Such a tampered run can therefore still be projected as Succeeded, so capture and scan the host-side changes produced by the swarm.

Useful? React with 👍 / 👎.

Comment on lines +210 to +213
claim = json.loads(report_path.read_text(encoding="utf-8")) if report_path.is_file() else {}
log_lines = [line for line in log_path.read_text(encoding="utf-8").splitlines()
if line.strip()] if log_path.is_file() else []
dropped = claim.get("dropped_rows")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Verify behavior instead of trusting generated summaries

On a live run that writes the expected constants into dedupe-report.json and produces 16 suitably formatted log lines, every holdout check passes even if src/import_contacts.py is missing or completely broken, because the checks only compare two swarm-owned output summaries and never execute the work product against independent input. This recreates the self-reporting false completion that the supervisor is meant to prevent; the holdout should exercise the implementation or independently derive the expected output.

Useful? React with 👍 / 👎.


def certify(workspace: Path, run: SwarmRun) -> dict:
ws = Path(workspace)
obs = observe(ws)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Project early live interruptions before reading artifacts

When the operator interrupts a live run before ruflo creates .swarm/state.json or the memory export—or when the export command fails—this unconditional observation raises FileNotFoundError before to_terminal_state sees run.human_abort. The real Ctrl-C path therefore exits with a traceback and no AbortedByHuman contract, despite the replay-only simulation passing; handle incomplete observations and project the recorded interrupt or external failure first.

Useful? React with 👍 / 👎.

Copilot AI 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.

Pull request overview

Adds a runnable ruflo integration recipe that gates a swarm via a host-side supervisor (fixture-replay by default) so Loop Engineer’s acceptance gate, projection, emit, doctor, and metrics execute for real without requiring Node/credentials in CI.

Changes:

  • Introduce examples/ruflo-gate/ supervisor + committed .swarm/ fixture replay and documentation.
  • Add deterministic end-to-end pytest coverage for the recipe, including false-completion, interrupt, and spec-gap traps.
  • Update ST3 integration adapter spec and add a dedicated CI job for the recipe test.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
scripts/test_ruflo_recipe.py Deterministic pytest suite that exercises fixture replay and validates doctor/metrics outcomes.
examples/ruflo-gate/swarm_example.py Host-side supervisor that replays or runs a ruflo swarm and projects through to_terminal_state + loop.emit.
examples/ruflo-gate/README.md Example-level documentation explaining why the supervisor seam exists and how to run demos.
examples/ruflo-gate/fixture/src/import_contacts.py Vendored “work product” file to make touched-path trails resolve during replay.
examples/ruflo-gate/fixture/dedupe.log Fixture evidence used by holdout checks (dropped-row log).
examples/ruflo-gate/fixture/dedupe-report.json Fixture report used by visible/holdout checks and sabotage scenarios.
examples/ruflo-gate/fixture/.swarm/tasks/task-001-spec.json Fixture .swarm/ task record for replay.
examples/ruflo-gate/fixture/.swarm/tasks/task-002-implement.json Fixture .swarm/ task record for replay.
examples/ruflo-gate/fixture/.swarm/tasks/task-003-logging.json Fixture .swarm/ task record for replay.
examples/ruflo-gate/fixture/.swarm/tasks/task-004-review.json Fixture .swarm/ task record for replay.
examples/ruflo-gate/fixture/.swarm/state.json Fixture .swarm/ state used to determine “settled” status.
examples/ruflo-gate/fixture/.swarm/memory-export.json Fixture memory export providing acceptance criteria vocabulary + self-report artifacts.
examples/ruflo-gate/fixture/.swarm/coordination/consensus-2026-07-25T09-31-52Z.json Fixture coordination trail for anti-cheat trajectory input.
examples/ruflo-gate/fixture/.swarm/agents/agent-coder-02.json Fixture agent trail for replay.
examples/ruflo-gate/fixture/.swarm/agents/agent-coder-03.json Fixture agent trail for replay.
examples/ruflo-gate/fixture/.swarm/agents/agent-queen-01.json Fixture agent trail for replay.
examples/ruflo-gate/fixture/.swarm/agents/agent-reviewer-04.json Fixture agent trail for replay.
examples/ruflo-gate/fixture/.hive-mind/sessions/hive-mind-prompt-swarm-2026-07-25.txt Fixture prompt transcript to support “swarm asked vs swarm proven” narrative.
examples/ruflo-gate/fixture/.claude-flow/metrics/v3-progress.json Fixture progress snapshot (non-proof) to mirror real layout.
docs/superpowers/specs/2026-06-30-st3-integration-adapters.md Corrects the prior fictional ruflo API + documents the verified supervisor seam.
docs/integrations/ruflo.md New integration recipe doc describing surfaces, traps, and terminal mapping.
.github/workflows/ci.yml Adds a dedicated CI job to run the ruflo recipe tests via fixture replay.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/ci.yml
Comment on lines +217 to +220
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: "3.12"
Comment on lines +115 to +120
proc = subprocess.run(LIVE_COMMAND, cwd=workspace, text=True)
subprocess.run(
["npx", f"ruflo@{RUFLO_VERSION}", "memory", "export", "-o", ".swarm/memory-export.json"],
cwd=workspace, text=True, check=False,
)
return SwarmRun(returncode=proc.returncode, mode="live", human_abort=_interrupted)
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.

Integration recipe: ruflo swarm → acceptance gate

2 participants