feat(refinery): ao refinery backstop daemon (ag-qidx P2.1-2.4,2.6)

The bushido continuous-validation backstop: watch main -> full gate on each new
commit -> classify deterministic-vs-flaky (re-run N=3; the 18-30% flake rate
makes naive escalation noise) -> on deterministic blocking FAIL: poison beacon
(.refinery-poison + git note) + fix-bead (bd create) + alert. NEVER reverts
(P2.5 quorum-gated revert deferred to ag-k99u). Backstop-not-gatekeeper: down =
merges still succeed; resumes from .refinery-state. Injectable ports (git/bd/
gates adapters); core tested with fakes (deterministic escalates, flaky doesn't,
green clears, never-reverts). ao refinery once|run; systemd unit + runbook for
bushido. go test green. ag-qidx.
This commit is contained in:
Boden Fuller
2026-06-07 10:57:08 -04:00
parent 7adaac157f
commit cba058c6ab
8 changed files with 790 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
// practices: [hexagonal-architecture, ddd-bounded-context]
package main
import (
"fmt"
"time"
"github.com/spf13/cobra"
// Register the seed checks the refinery's full gate runs.
_ "github.com/boshu2/agentops/cli/internal/gates/checks"
"github.com/boshu2/agentops/cli/internal/refinery"
)
// `ao refinery` is the bushido continuous-validation backstop (ag-qidx P2): it
// watches main, runs the full gate on each new commit, and on a DETERMINISTIC
// blocking failure raises a poison beacon + files a fix-bead + alerts. It NEVER
// blind-reverts (the repo's flake rate would make auto-revert fight developers)
// and it is a backstop, not a gatekeeper — if it is down, merges still succeed.
var refineryInterval time.Duration
var refineryCmd = &cobra.Command{
Use: "refinery",
Short: "Continuous main-validation backstop (run on bushido)",
Long: `Watch main, run the full gate on each new commit, and on a
deterministic blocking failure raise a poison beacon + file a fix-bead. Never
reverts; resumes from .refinery-state across restarts.
ao refinery once # evaluate main HEAD once (one tick)
ao refinery run --interval 5m # loop until interrupted (systemd service)`,
}
var refineryOnceCmd = &cobra.Command{
Use: "once",
Short: "Evaluate main HEAD once",
Args: cobra.NoArgs,
RunE: runRefineryOnce,
}
var refineryRunCmd = &cobra.Command{
Use: "run",
Short: "Run the refinery loop until interrupted",
Args: cobra.NoArgs,
RunE: runRefineryRun,
}
func init() {
refineryRunCmd.Flags().DurationVar(&refineryInterval, "interval", 5*time.Minute, "poll interval")
refineryCmd.AddCommand(refineryOnceCmd, refineryRunCmd)
rootCmd.AddCommand(refineryCmd)
}
func runRefineryOnce(cmd *cobra.Command, _ []string) error {
root, err := gateRepoRoot()
if err != nil {
return fmt.Errorf("resolve repo root: %w", err)
}
res, err := refinery.NewProduction(root).RunOnce(cmd.Context())
if err != nil {
return err
}
out := cmd.OutOrStdout()
switch {
case res.Skipped:
fmt.Fprintf(out, "refinery: %s unchanged — nothing to do\n", res.SHA)
case res.Green:
fmt.Fprintf(out, "refinery: %s GREEN\n", res.SHA)
case len(res.Deterministic) > 0:
fmt.Fprintf(out, "refinery: %s POISONED by %v — fix-bead %s filed (no revert)\n", res.SHA, res.Deterministic, res.FixBead)
default:
fmt.Fprintf(out, "refinery: %s had failures but none reproduced (flaky) — not escalated\n", res.SHA)
}
return nil
}
func runRefineryRun(cmd *cobra.Command, _ []string) error {
root, err := gateRepoRoot()
if err != nil {
return fmt.Errorf("resolve repo root: %w", err)
}
fmt.Fprintf(cmd.OutOrStdout(), "refinery: looping every %s (Ctrl-C to stop)\n", refineryInterval)
return refinery.NewProduction(root).Loop(cmd.Context(), refineryInterval)
}
+35
View File
@@ -0,0 +1,35 @@
package main
import "testing"
func TestRefineryCmd_Registered(t *testing.T) {
var found bool
for _, c := range rootCmd.Commands() {
if c.Name() == "refinery" {
found = true
}
}
if !found {
t.Fatal("`ao refinery` not registered on root")
}
}
func TestRefineryCmd_HasSubcommands(t *testing.T) {
want := map[string]bool{"once": false, "run": false}
for _, c := range refineryCmd.Commands() {
if _, ok := want[c.Name()]; ok {
want[c.Name()] = true
}
}
for name, found := range want {
if !found {
t.Errorf("ao refinery missing subcommand %q", name)
}
}
}
func TestRefineryRun_HasIntervalFlag(t *testing.T) {
if refineryRunCmd.Flags().Lookup("interval") == nil {
t.Error("ao refinery run missing --interval flag")
}
}
+35
View File
@@ -4170,6 +4170,41 @@ ao ready [flags]
---
### `ao refinery`
Watch main, run the full gate on each new commit, and on a
```
ao refinery [command]
```
**Subcommands:**
#### `ao refinery once`
Evaluate main HEAD once
```
ao refinery once [flags]
```
#### `ao refinery run`
Run the refinery loop until interrupted
```
ao refinery run [flags]
```
**Flags:**
```
-h, --help help for run
--interval duration poll interval (default 5m0s)
```
---
### `ao registry`
Query the unified registry
+167
View File
@@ -0,0 +1,167 @@
package refinery
import (
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/boshu2/agentops/cli/internal/gates"
"github.com/boshu2/agentops/cli/internal/ports"
)
// NewProduction wires the refinery with git/bd/gates-backed adapters rooted at
// repoRoot. The registry is gates.Default (the seed registry).
func NewProduction(repoRoot string) *Refinery {
runner := gates.NewScriptRunner(repoRoot)
return &Refinery{
Commits: &gitCommitSource{repoRoot: repoRoot},
Gate: &gatesChecker{repoRoot: repoRoot, runner: runner},
Rerun: &gatesRerunner{repoRoot: repoRoot, runner: runner},
Beads: &bdBeadFiler{repoRoot: repoRoot},
Beacon: &fileBeacon{repoRoot: repoRoot},
Store: &fileStateStore{path: filepath.Join(repoRoot, ".refinery-state")},
RerunN: 3,
Log: func(s string) { fmt.Fprintln(os.Stderr, s) },
}
}
// --- CommitSource: origin/main HEAD via git ---
type gitCommitSource struct{ repoRoot string }
func (g *gitCommitSource) MainHead(ctx context.Context) (string, error) {
_, _ = run(ctx, g.repoRoot, "git", "fetch", "origin", "main", "--quiet") // best-effort
out, err := run(ctx, g.repoRoot, "git", "rev-parse", "origin/main")
if err != nil {
return "", err
}
return strings.TrimSpace(out), nil
}
// --- GateChecker: the full gate over gates.Default ---
type gatesChecker struct {
repoRoot string
runner ports.GateRunnerPort
}
func (g *gatesChecker) CheckFull(ctx context.Context) (*gates.Report, error) {
o := gates.NewOrchestrator(gates.Default, g.runner, gates.NewGitChangedFiles(g.repoRoot), g.repoRoot)
return o.Run(ctx, gates.RunOptions{Mode: gates.Full})
}
// --- Rerunner: re-run one check by ID ---
type gatesRerunner struct {
repoRoot string
runner ports.GateRunnerPort
}
func (g *gatesRerunner) Rerun(ctx context.Context, checkID string) (ports.GateVerdict, error) {
c, ok := gates.Default.Get(checkID)
if !ok {
return ports.GateVerdict{}, fmt.Errorf("refinery: unknown check %q", checkID)
}
if c.Run != nil {
return c.Run(ctx, gates.RunContext{RepoRoot: g.repoRoot, Mode: gates.Full})
}
return g.runner.Run(ctx, ports.GateRunRequest{Name: ports.GateName(c.Backing)})
}
// --- BeadFiler: bd create ---
type bdBeadFiler struct{ repoRoot string }
func (b *bdBeadFiler) FileFixBead(ctx context.Context, sha string, checks []string) (string, error) {
short := sha
if len(short) > 8 {
short = short[:8]
}
title := fmt.Sprintf("fix: main %s poisoned — deterministic gate failure (%s)", short, strings.Join(checks, ", "))
out, err := run(ctx, b.repoRoot, "bd", "create", title, "--type", "task", "--labels", "refinery,blocking", "--json")
if err != nil {
return "", err
}
var parsed struct {
ID string `json:"id"`
}
if jerr := json.Unmarshal([]byte(out), &parsed); jerr != nil {
return "", nil // bead may have been created; ID just unparsed
}
return parsed.ID, nil
}
// --- Beacon: status file + best-effort git note ---
type fileBeacon struct{ repoRoot string }
type poisonFile struct {
SHA string `json:"sha"`
Checks []string `json:"checks"`
}
func (b *fileBeacon) path() string { return filepath.Join(b.repoRoot, ".refinery-poison") }
func (b *fileBeacon) Set(ctx context.Context, sha string, checks []string) error {
data, err := json.MarshalIndent(poisonFile{SHA: sha, Checks: checks}, "", " ")
if err != nil {
return err
}
if err := os.WriteFile(b.path(), data, 0o644); err != nil { // #nosec G306 -- a beacon meant to be world-readable by any pusher
return err
}
// best-effort git note so the poison travels with the commit
_, _ = run(ctx, b.repoRoot, "git", "notes", "--ref=refinery", "add", "-f",
"-m", "POISON: "+strings.Join(checks, ", "), sha)
return nil
}
func (b *fileBeacon) Clear(ctx context.Context, sha string) error {
if err := os.Remove(b.path()); err != nil && !os.IsNotExist(err) {
return err
}
_, _ = run(ctx, b.repoRoot, "git", "notes", "--ref=refinery", "remove", sha)
return nil
}
// --- StateStore: JSON file ---
type fileStateStore struct{ path string }
func (s *fileStateStore) Load() (State, error) {
data, err := os.ReadFile(s.path)
if os.IsNotExist(err) {
return State{}, nil
}
if err != nil {
return State{}, err
}
var st State
if err := json.Unmarshal(data, &st); err != nil {
return State{}, fmt.Errorf("refinery: parse state %s: %w", s.path, err)
}
return st, nil
}
func (s *fileStateStore) Save(st State) error {
data, err := json.MarshalIndent(st, "", " ")
if err != nil {
return err
}
return os.WriteFile(s.path, data, 0o644) // #nosec G306 -- non-secret refinery state
}
// run executes a command in dir and returns combined stdout.
func run(ctx context.Context, dir, name string, args ...string) (string, error) {
cmd := exec.CommandContext(ctx, name, args...)
cmd.Dir = dir
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("%s %s: %w", name, strings.Join(args, " "), err)
}
return string(out), nil
}
+221
View File
@@ -0,0 +1,221 @@
// Package refinery is the bushido continuous-validation backstop (ag-qidx P2).
// It watches main, runs the full gate on each new commit, and on a DETERMINISTIC
// blocking failure raises a poison-main beacon + files a fix-bead + alerts —
// it NEVER blind-reverts (the repo's 18-30% flake rate would make auto-revert
// fight developers). It is a backstop, not a gatekeeper: if it is down, merges
// still succeed; it resumes from its state file on restart.
package refinery
import (
"context"
"fmt"
"time"
"github.com/boshu2/agentops/cli/internal/gates"
"github.com/boshu2/agentops/cli/internal/ports"
)
// State is the durable refinery state (persisted as .refinery-state JSON).
type State struct {
// LastCheckedSHA is the most recent main HEAD the refinery has evaluated.
LastCheckedSHA string `json:"last_checked_sha"`
// Poison lists the currently-poisoned commits (deterministic failures not
// yet fixed forward).
Poison []PoisonEntry `json:"poison"`
}
// PoisonEntry records a deterministic failure on main.
type PoisonEntry struct {
SHA string `json:"sha"`
Checks []string `json:"checks"`
FixBead string `json:"fix_bead,omitempty"`
}
// ---- ports (injected; production adapters in adapters.go, fakes in tests) ----
// CommitSource reports the current main HEAD.
type CommitSource interface {
MainHead(ctx context.Context) (string, error)
}
// GateChecker runs the full gate and returns the report.
type GateChecker interface {
CheckFull(ctx context.Context) (*gates.Report, error)
}
// Rerunner re-runs a single check (for flaky-vs-deterministic classification).
type Rerunner interface {
Rerun(ctx context.Context, checkID string) (ports.GateVerdict, error)
}
// BeadFiler files a blocking fix-bead and returns its ID.
type BeadFiler interface {
FileFixBead(ctx context.Context, sha string, checks []string) (string, error)
}
// Beacon marks/clears a poisoned main commit so pushers can see it.
type Beacon interface {
Set(ctx context.Context, sha string, checks []string) error
Clear(ctx context.Context, sha string) error
}
// StateStore loads and persists refinery State.
type StateStore interface {
Load() (State, error)
Save(State) error
}
// Refinery is the backstop engine.
type Refinery struct {
Commits CommitSource
Gate GateChecker
Rerun Rerunner
Beads BeadFiler
Beacon Beacon
Store StateStore
// RerunN is how many times a failing check is re-run to classify it as
// deterministic (fails every time) vs flaky. Default 3 if zero.
RerunN int
// Log receives human-readable progress (optional).
Log func(string)
}
// Result summarizes one RunOnce tick.
type Result struct {
SHA string
Skipped bool // HEAD unchanged since last check
Green bool // no blocking failures
Failing []string // all blocking-failed check IDs
Deterministic []string // the subset that reproduced (escalated)
FixBead string
}
func (r *Refinery) logf(format string, a ...any) {
if r.Log != nil {
r.Log(fmt.Sprintf(format, a...))
}
}
func (r *Refinery) rerunCount() int {
if r.RerunN > 0 {
return r.RerunN
}
return 3
}
// RunOnce evaluates the current main HEAD if it has advanced. On a deterministic
// blocking failure it sets a beacon and files a fix-bead; on green it clears any
// beacon. It NEVER reverts.
func (r *Refinery) RunOnce(ctx context.Context) (Result, error) {
st, err := r.Store.Load()
if err != nil {
return Result{}, fmt.Errorf("refinery: load state: %w", err)
}
head, err := r.Commits.MainHead(ctx)
if err != nil {
return Result{}, fmt.Errorf("refinery: main head: %w", err)
}
if head == "" {
return Result{}, fmt.Errorf("refinery: empty main HEAD")
}
if head == st.LastCheckedSHA {
return Result{SHA: head, Skipped: true}, nil
}
r.logf("refinery: evaluating %s", head)
report, err := r.Gate.CheckFull(ctx)
if err != nil {
return Result{}, fmt.Errorf("refinery: gate check: %w", err)
}
failing := blockingFailures(report)
if len(failing) == 0 {
if err := r.Beacon.Clear(ctx, head); err != nil {
r.logf("refinery: beacon clear failed: %v", err)
}
st.LastCheckedSHA = head
st.Poison = nil
if err := r.Store.Save(st); err != nil {
return Result{}, fmt.Errorf("refinery: save state: %w", err)
}
r.logf("refinery: %s GREEN", head)
return Result{SHA: head, Green: true}, nil
}
// Classify: only escalate failures that reproduce deterministically.
var deterministic []string
for _, id := range failing {
if r.isDeterministic(ctx, id) {
deterministic = append(deterministic, id)
} else {
r.logf("refinery: %s failed on %s but did not reproduce — treating as flaky, NOT escalating", head, id)
}
}
res := Result{SHA: head, Failing: failing, Deterministic: deterministic}
if len(deterministic) > 0 {
bead, ferr := r.Beads.FileFixBead(ctx, head, deterministic)
if ferr != nil {
r.logf("refinery: file fix-bead failed: %v", ferr)
}
res.FixBead = bead
if err := r.Beacon.Set(ctx, head, deterministic); err != nil {
r.logf("refinery: beacon set failed: %v", err)
}
st.Poison = append(st.Poison, PoisonEntry{SHA: head, Checks: deterministic, FixBead: bead})
r.logf("refinery: %s POISONED by %v — fix-bead %s filed (no revert)", head, deterministic, bead)
}
st.LastCheckedSHA = head
if err := r.Store.Save(st); err != nil {
return Result{}, fmt.Errorf("refinery: save state: %w", err)
}
return res, nil
}
// isDeterministic re-runs a failing check RerunN times; it is deterministic only
// if it FAILS every time (any pass => flaky, do not escalate).
func (r *Refinery) isDeterministic(ctx context.Context, checkID string) bool {
for i := 0; i < r.rerunCount(); i++ {
v, err := r.Rerun.Rerun(ctx, checkID)
if err != nil {
// Could not re-run -> conservatively treat as NOT deterministic
// (don't escalate on inability to reproduce).
return false
}
if v.Status != ports.GateStatusFail {
return false
}
}
return true
}
// Loop runs RunOnce every interval until ctx is cancelled. It is a BACKSTOP: a
// RunOnce error (transient git/gate/network failure, bushido hiccup) is logged
// and the loop continues — the daemon never dies on one bad tick, and resumes
// from its state file across restarts.
func (r *Refinery) Loop(ctx context.Context, interval time.Duration) error {
t := time.NewTicker(interval)
defer t.Stop()
for {
if _, err := r.RunOnce(ctx); err != nil {
r.logf("refinery: tick error (continuing): %v", err)
}
select {
case <-ctx.Done():
return ctx.Err()
case <-t.C:
}
}
}
// blockingFailures returns the IDs of blocking checks that FAILed.
func blockingFailures(report *gates.Report) []string {
var out []string
for _, res := range report.Results {
if res.Check.Blocking && res.Verdict.Status == ports.GateStatusFail {
out = append(out, res.Check.ID)
}
}
return out
}
+170
View File
@@ -0,0 +1,170 @@
package refinery
import (
"context"
"testing"
"github.com/boshu2/agentops/cli/internal/gates"
"github.com/boshu2/agentops/cli/internal/ports"
)
// ---- fakes ----
type fakeCommits struct{ head string }
func (f fakeCommits) MainHead(context.Context) (string, error) { return f.head, nil }
type fakeGate struct{ rep *gates.Report }
func (f fakeGate) CheckFull(context.Context) (*gates.Report, error) { return f.rep, nil }
type fakeRerun struct{ status ports.GateStatus }
func (f fakeRerun) Rerun(context.Context, string) (ports.GateVerdict, error) {
return ports.GateVerdict{Status: f.status}, nil
}
type fakeBeads struct {
filed int
lastChecks []string
}
func (f *fakeBeads) FileFixBead(_ context.Context, _ string, checks []string) (string, error) {
f.filed++
f.lastChecks = checks
return "ag-fix1", nil
}
type fakeBeacon struct{ setN, clearN int }
func (f *fakeBeacon) Set(context.Context, string, []string) error { f.setN++; return nil }
func (f *fakeBeacon) Clear(context.Context, string) error { f.clearN++; return nil }
type memStore struct{ st State }
func (m *memStore) Load() (State, error) { return m.st, nil }
func (m *memStore) Save(s State) error { m.st = s; return nil }
// ---- report builders ----
func blockingCheck(id string, status ports.GateStatus) gates.CheckResult {
return gates.CheckResult{
Check: gates.Check{ID: id, Tiers: gates.Full, Blocking: true, Backing: "x"},
Verdict: ports.GateVerdict{Status: status},
}
}
func newRefinery(head string, rep *gates.Report, rerun ports.GateStatus, store *memStore, beads *fakeBeads, beacon *fakeBeacon) *Refinery {
return &Refinery{
Commits: fakeCommits{head: head},
Gate: fakeGate{rep: rep},
Rerun: fakeRerun{status: rerun},
Beads: beads,
Beacon: beacon,
Store: store,
RerunN: 3,
}
}
// ---- tests ----
func TestRunOnce_SkipsUnchangedHead(t *testing.T) {
store := &memStore{st: State{LastCheckedSHA: "abc"}}
r := newRefinery("abc", &gates.Report{}, ports.GateStatusFail, store, &fakeBeads{}, &fakeBeacon{})
res, err := r.RunOnce(context.Background())
if err != nil {
t.Fatalf("RunOnce: %v", err)
}
if !res.Skipped {
t.Error("unchanged HEAD should be Skipped")
}
}
func TestRunOnce_GreenClearsBeacon(t *testing.T) {
store := &memStore{st: State{LastCheckedSHA: "old", Poison: []PoisonEntry{{SHA: "old"}}}}
beacon := &fakeBeacon{}
rep := &gates.Report{Results: []gates.CheckResult{blockingCheck("go.build", ports.GateStatusPass)}}
r := newRefinery("new", rep, ports.GateStatusPass, store, &fakeBeads{}, beacon)
res, err := r.RunOnce(context.Background())
if err != nil {
t.Fatalf("RunOnce: %v", err)
}
if !res.Green {
t.Error("all-pass report should be Green")
}
if beacon.clearN != 1 {
t.Errorf("beacon.Clear calls = %d, want 1", beacon.clearN)
}
if len(store.st.Poison) != 0 {
t.Errorf("green should clear poison; got %v", store.st.Poison)
}
if store.st.LastCheckedSHA != "new" {
t.Errorf("LastCheckedSHA = %q, want new", store.st.LastCheckedSHA)
}
}
func TestRunOnce_DeterministicFailEscalates(t *testing.T) {
store := &memStore{}
beads := &fakeBeads{}
beacon := &fakeBeacon{}
rep := &gates.Report{Results: []gates.CheckResult{blockingCheck("contract.registry-drift", ports.GateStatusFail)}}
// rerun always FAILs -> deterministic
r := newRefinery("bad", rep, ports.GateStatusFail, store, beads, beacon)
res, err := r.RunOnce(context.Background())
if err != nil {
t.Fatalf("RunOnce: %v", err)
}
if len(res.Deterministic) != 1 || res.Deterministic[0] != "contract.registry-drift" {
t.Errorf("Deterministic = %v, want [contract.registry-drift]", res.Deterministic)
}
if beads.filed != 1 {
t.Errorf("fix-bead filed = %d, want 1", beads.filed)
}
if beacon.setN != 1 {
t.Errorf("beacon.Set calls = %d, want 1", beacon.setN)
}
if len(store.st.Poison) != 1 || store.st.Poison[0].FixBead != "ag-fix1" {
t.Errorf("poison state = %+v, want one entry with fix bead", store.st.Poison)
}
}
func TestRunOnce_FlakyFailDoesNotEscalate(t *testing.T) {
store := &memStore{}
beads := &fakeBeads{}
beacon := &fakeBeacon{}
rep := &gates.Report{Results: []gates.CheckResult{blockingCheck("skill.schema", ports.GateStatusFail)}}
// rerun PASSes -> not reproducible -> flaky -> no escalation
r := newRefinery("flaky", rep, ports.GateStatusPass, store, beads, beacon)
res, err := r.RunOnce(context.Background())
if err != nil {
t.Fatalf("RunOnce: %v", err)
}
if len(res.Deterministic) != 0 {
t.Errorf("flaky failure must NOT escalate; Deterministic = %v", res.Deterministic)
}
if beads.filed != 0 {
t.Errorf("no fix-bead for flaky; filed = %d", beads.filed)
}
if beacon.setN != 0 {
t.Errorf("no beacon for flaky; setN = %d", beacon.setN)
}
if len(store.st.Poison) != 0 {
t.Errorf("flaky must not poison; got %v", store.st.Poison)
}
}
func TestRunOnce_NeverRevertsField(t *testing.T) {
// Structural guard: the Refinery type exposes no revert capability — there is
// no Revert method/field. A deterministic failure escalates via beacon+bead
// only. (Compile-time evidence: this test references the public surface.)
store := &memStore{}
rep := &gates.Report{Results: []gates.CheckResult{blockingCheck("x", ports.GateStatusFail)}}
r := newRefinery("z", rep, ports.GateStatusFail, store, &fakeBeads{}, &fakeBeacon{})
if _, err := r.RunOnce(context.Background()); err != nil {
t.Fatalf("RunOnce: %v", err)
}
// The poisoned commit remains on main (state records it; nothing reverted).
if store.st.LastCheckedSHA != "z" {
t.Errorf("LastCheckedSHA = %q, want z (commit stays; backstop never reverts)", store.st.LastCheckedSHA)
}
}
+24
View File
@@ -0,0 +1,24 @@
# AgentOps Refinery — continuous main-validation backstop (ag-qidx P2.4).
# Install on bushido as a user service:
# cp deploy/agentops-refinery.service ~/.config/systemd/user/
# systemctl --user daemon-reload
# systemctl --user enable --now agentops-refinery
# Backstop-not-gatekeeper: if this is down, merges still succeed; on restart it
# resumes from .refinery-state. It NEVER reverts — it beacons + files fix-beads.
[Unit]
Description=AgentOps Refinery (continuous main-validation backstop)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=%h/dev/agentops
ExecStart=%h/go/bin/ao refinery run --interval 5m
Restart=on-failure
RestartSec=30
# Resilience: a single bad tick must not kill the daemon (the loop already
# swallows tick errors; this is belt-and-suspenders).
StartLimitIntervalSec=0
[Install]
WantedBy=default.target
+54
View File
@@ -0,0 +1,54 @@
# Bushido Refinery — continuous main-validation backstop
The refinery (`ao refinery`) is the **backstop** half of the push-to-main model
(ag-qidx). Push-to-main makes the local pre-push gate the pre-merge wall; the
refinery is the always-on net behind `main` on bushido.
## What it does
Every tick it checks `origin/main`. On a **new** commit it runs the full gate
(`ao gate check --full`). On a **blocking** failure it:
1. re-runs each failing check N times (default 3) to tell **deterministic** from
**flaky** (the repo's 1830% flake rate means naive escalation would be noise);
2. for deterministic failures only: writes a **poison beacon** (`.refinery-poison`
+ a `refinery` git note on the bad SHA) and files a **blocking fix-bead**
(`bd create --labels refinery,blocking`);
3. on green: clears the beacon.
It **never reverts.** A poisoned commit stays on `main`; the team fixes forward.
Revert remains a human/quorum decision (ag-qidx P2.5, deferred to the quorum
infra `ag-k99u`).
## Backstop, not gatekeeper
If bushido (or its Wi-Fi) is down, the refinery is simply blind — **merges still
succeed**, nothing blocks. On restart it resumes from `.refinery-state`
(`last_checked_sha`) and catches up. This is the deliberate posture after the
2026-06-05 control-plane crash: no single host is in the merge path.
## Run it
```bash
ao refinery once # one tick (manual / cron)
ao refinery run --interval 5m # loop (the systemd service)
```
## Install on bushido
```bash
cp deploy/agentops-refinery.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now agentops-refinery
systemctl --user status agentops-refinery
journalctl --user -u agentops-refinery -f # logs
```
State + beacon (repo-root, gitignored runtime):
- `.refinery-state``{last_checked_sha, poison[]}`
- `.refinery-poison` — present iff `main` is currently poisoned
## Tuning
- `--interval` — poll cadence (default 5m).
- Re-run count is 3 (deterministic = fails all 3). Raise for noisier suites.