AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
Steward는 풀 리퀘스트를 의사결정 과정으로 바꾸어, 에이전트가 포크에서 경쟁하고 심판이 후보를 제시하면 사용자가 최종 선택한다
Steward turns the pull request into a decision: agents race in their own forks, a judge proposes one candidate, and a person decides.
개발 도구TypeScript · JavaScriptGitHub @craigm26온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기The pull request, as a decision: agents race in their own forks, a judge proposes one, and a person decides. Built on Cloudflare Workers, Durable Objects, Workflows, Workers AI and Artifacts.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Steward turns the pull request into a decision. Agents race in their own forks, a judge proposes one candidate, and a person, the steward, decides. Auto-merge is earned path by path and revoked when the judge drifts from the steward.
Code is now cheap and judgment is not, so the core object here is the decision, not the diff. It runs entirely on Cloudflare: Workers, Durable Objects, Workflows, Workers AI, Workers Builds and Previews, and Artifacts, Cloudflare's Git-speaking storage.
Live demo: steward.craigm26.workers.dev. Anyone can watch; changing anything needs the steward key.README 전문 보기 ↗Steward turns the pull request into a decision. Agents race in their own forks, a judge proposes one candidate, and a person, the steward, decides. Auto-merge is earned path by path and revoked when the judge drifts from the steward.
Code is now cheap and judgment is not, so the core object here is the decision, not the diff. It runs entirely on Cloudflare: Workers, Durable Objects, Workflows, Workers AI, Workers Builds and Previews, and Artifacts, Cloudflare's Git-speaking storage.
Live demo: steward.craigm26.workers.dev. Anyone can watch; changing anything needs the steward key.
| The question | Steward's answer |
|---|---|
| How do agents know what others are working on? | A claims board shows who holds which files. |
| What happens when changes conflict? | Overlapping claims become rival candidates in one decision. |
| How do you review everything agents produce? | A mechanical gate checks all of it; the steward only makes taste calls. |
| How do you keep track of why a change was made? | Every merge writes a ledger entry, and why-blame reads it back for any line. |
flowchart LR
subgraph agents [Agents]
A1[model agents<br/>Workers AI, one Workflow each]
A2[outside agents<br/>steward-agent CLI]
end
A1 & A2 -- claim files --> B[(Board<br/>Durable Object)]
B -- fork + a token for that fork only --> F[(Agent forks<br/>Artifacts)]
A1 & A2 -- git push --> F
F -- cf.artifacts.repo.pushed --> G[Gate 1<br/>Workflow]
G -- promote --> R[(App repo<br/>cand/task/agent)]
R -- Workers Builds --> P[Preview per candidate]
G -- done checks --> P
G -- every candidate settled --> D[Decide<br/>Workflow]
D --> J[Judge<br/>Clef on Workers AI]
D --> X[Referee<br/>Workers AI]
D -- card --> S{{Steward}}
S -- ship one, a reason if not the judge's --> M[Squash merge<br/>one commit per decision]
M --> L[(Record repo<br/>decisions, ledger, grants)]
C[The check<br/>weekly + on demand] -- replays the judge on past decisions --> L
C -- grant or suspend auto-merge --> D
cand/<task>/<agent> on the app repo, waits for Workers Builds to run the build and tests and publish a Preview of exactly that commit, then probes the Preview with the task's checks and the path's regression checks. An agent that claims done and fails is bounced before anyone sees it, with the failing checks attached. A hedged summary ("I think this should work") counts as not done. An agent may change only the files it claimed.Steward-Decision trailers; Steward's working files never reach main.ledger.jsonl. Why-blame walks main's history in the Worker and opens the decision behind any line: the task, the rivals it beat, the judge, the objection, who decided and why.The judge is Clef, Cloudflare's decision model on Workers AI: it answers a typed question (which candidate ships, and which taste rule decided it) with calibrated probabilities in about half a second, through the same AI binding the agents use, so no key and nothing outside Cloudflare. The judgment pieces around it come from PlatAtlas, unchanged: the judgment contract (Jev's API, which Clef speaks), the thresholds reader, the grants rules, and the check report (see vendor/platatlas). The rules about done, the referee, budgets, committed plans and evidence-first cards follow Anthropic's Claude-shaped science.
Your repos stay in your account, and an Artifacts namespace keeps every repo in the US or the EU, as you choose when you create it.
You need a Cloudflare account on Workers Paid (Artifacts requires it), Node 20 or later, and git.
git clone https://github.com/craigm26/steward && cd steward
npm install # pins wrangler 4.146; Artifacts needs 4.145 or later
npx wrangler login
Edit wrangler.jsonc: set WORKERS_SUBDOMAIN to your workers.dev subdomain. The namespace (steward), the app (larkspur-ap) and the record repo (larkspur-ap.record) can stay as they are. Then:
npx wrangler deploy
openssl rand -base64 32 | tr -d '\n' | npx wrangler secret put STEWARD_ADMIN_KEY
printf 'STEWARD_URL=https://steward.<your-subdomain>.workers.dev\nSTEWARD_ADMIN_KEY=<the same key>\n' > .dev.vars
node scripts/seed-app.mjs --jurisdiction us # namespace, demo app repo, its Worker, the record
Then, once, in the dashboard: Workers & Pages → larkspur-ap → Settings → Builds → Connect, pick the Artifacts namespace and the larkspur-ap repo, set the build command to npm run build, save, and turn on Builds for Preview branches. (Connecting a Worker to an Artifacts repo is a dashboard step today.) Until it is connected, node scripts/preview-runner.mjs does the same job from your machine: it builds each candidate in a bubblewrap sandbox with no network and publishes its Preview with wrangler preview.
Open the board, sign in with the steward key, open a task (or one of the two demo tasks), and press Start the model agents.
The judge's engine is judge.engine in the record's steward.yaml: clef (the default), clef-flash (faster, a little less accurate here), typesafe (Jev, with npx wrangler secret put TYPESAFE_API_KEY), or mock (a deterministic rubric that needs nothing). A different judge can earn or lose auto-merge on different paths, so compare before switching: node scripts/judge-eval.mjs --engines mock,clef,clef-flash --live replays each on every decision a person made and saves nothing. On the demo's 24 such decisions, Clef and the rubric fail the same checks (payment rules 1 of 10 against the steward, the invoice queue page 3 of 8, translations 0 of 6), but Clef agreed with the steward's overrule on the terms race that the rubric got wrong. Jev (typesafe) has not been run on these decisions yet; TYPESAFE_API_KEY=... node scripts/judge-eval.mjs --engines clef,typesafe --live is the comparison.
agents/steward-agent.mjs: tasks, claim <task> --dir <folder> (clones your fork with its token), status, done <task> --summary "…", withdraw. An admin key registers an agent with register <name>. In the explainer's run, Claude Code raced the six models this way and the board labeled it an outside agent.agents/scripted.mjs) push known variants, including a wrong one, to rehearse the loop without a model. They are labeled scripted everywhere they appear.POST /api/admin/scale) puts six scripted agents on each of 20 translation tasks, 120 in all, inside Cloudflare. A translation is data, so its checks read the file at the candidate's commit and no Preview is built. Measured: every agent settled within about two minutes; the 80 broken files bounced at gate 1; on the Translations path, which had earned auto-merge, the judge merged 16 decisions alone and sent 4 to the steward.| Path | What it holds |
|---|---|
steward.yaml | The app, its Worker, the stewards, the judge's engine |
thresholds.yaml | What the judge may decide alone |
playbooks/<path>.yaml | Per path: its steward, files, done checks, budget, taste rules, auto-merge |
decisions/<id>.json | One decision: the candidates, their evidence, the judge, the referee, the steward |
ledger.jsonl | One line per merge: who decided and what merged |
checks/<path>/last-report.json | The latest check of the judge against the steward |
preferences/grants.jsonl | Auto-merge grants, append-only: earned, suspended, revoked |
synthetic: true and shown as synthetic.engine: mock it is instead a rubric that scores evidence against the playbook's taste rules, deterministic and labeled mock, with a heuristic confidence.Everything runs on Workers Paid ($5 a month), which includes generous allowances. At the demo's scale (a few races a day) usage stays inside them, except Workers AI.
| Service | Paid plan allowance | Beyond it |
|---|---|---|
| Artifacts (billing from Oct 14, 2026) | 10,000 operations and 1 GB a month | $0.15 per 1,000 operations; $0.50 per GB-month |
| Workers AI | 10,000 Neurons a day | $0.011 per 1,000 Neurons |
| Workflows | 500,000 steps and 30 million CPU ms a month | $0.80 per 100,000 steps |
| Durable Objects | 1 million requests a month | $0.15 per million |
A race of six model agents makes two to four model calls per agent; most of its cost is those calls.
npm run typecheck
npx vitest run --pool=forks --maxWorkers=1
node scripts/watch.mjs --task t1 # the board from a terminal
node scripts/admin.mjs check rules # run the check now
node scripts/judge-eval.mjs --live # each judge engine against the steward's past picks, nothing saved
docs/DEMO.md covers recording a demo beat by beat, and rendering the explainer film from a recorded run.
Apache-2.0 (see LICENSE and NOTICE). The files in vendor/platatlas keep their MIT License.