@hecer/yoke 0.2.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +583 -494
  3. package/bench/.runs/claude-2026-07-09T22-34-01/.yoke/config.yaml +6 -0
  4. package/bench/.runs/claude-2026-07-09T22-34-01/.yoke/context/DECISIONS.md +9 -0
  5. package/bench/.runs/claude-2026-07-09T22-34-01/.yoke/prd.yaml +38 -0
  6. package/bench/.runs/claude-2026-07-09T22-34-01/bench-verify.mjs +15 -0
  7. package/bench/.runs/claude-2026-07-09T22-34-01/package.json +9 -0
  8. package/bench/.runs/claude-2026-07-09T22-34-01/src/index.mjs +48 -0
  9. package/bench/.runs/claude-2026-07-09T22-34-01/tests/STORY-1.test.mjs +24 -0
  10. package/bench/.runs/claude-2026-07-09T22-34-01/tests/STORY-2.test.mjs +28 -0
  11. package/bench/.runs/claude-2026-07-09T22-34-01/tests/STORY-3.test.mjs +25 -0
  12. package/bench/.runs/gemini-2026-07-09T22-34-02/.yoke/config.yaml +6 -0
  13. package/bench/.runs/gemini-2026-07-09T22-34-02/.yoke/prd.yaml +32 -0
  14. package/bench/.runs/gemini-2026-07-09T22-34-02/bench-verify.mjs +15 -0
  15. package/bench/.runs/gemini-2026-07-09T22-34-02/package.json +9 -0
  16. package/bench/.runs/gemini-2026-07-09T22-34-02/src/index.mjs +3 -0
  17. package/bench/.runs/gemini-2026-07-09T22-34-02/tests/STORY-1.test.mjs +24 -0
  18. package/bench/.runs/gemini-2026-07-09T22-34-02/tests/STORY-2.test.mjs +28 -0
  19. package/bench/.runs/gemini-2026-07-09T22-34-02/tests/STORY-3.test.mjs +25 -0
  20. package/bench/README.md +42 -0
  21. package/bench/RESULTS.md +36 -0
  22. package/bench/fixtures/string-kit/.yoke/config.yaml +6 -0
  23. package/bench/fixtures/string-kit/.yoke/prd.yaml +32 -0
  24. package/bench/fixtures/string-kit/bench-verify.mjs +15 -0
  25. package/bench/fixtures/string-kit/package.json +9 -0
  26. package/bench/fixtures/string-kit/src/index.mjs +3 -0
  27. package/bench/fixtures/string-kit/tests/STORY-1.test.mjs +24 -0
  28. package/bench/fixtures/string-kit/tests/STORY-2.test.mjs +28 -0
  29. package/bench/fixtures/string-kit/tests/STORY-3.test.mjs +25 -0
  30. package/bench/results/claude-2026-07-09T22-34-01.json +40 -0
  31. package/bench/run.mjs +115 -0
  32. package/canon/loop/loop-spec.md +5 -1
  33. package/canon/manifest.yaml +3 -0
  34. package/canon/skills/yoke-retrofit/SKILL.md +1 -0
  35. package/canon/tools/claude-mem.md +15 -0
  36. package/canon/tools/ui-ux-pro-max.md +15 -0
  37. package/dist/cli.js +37 -6
  38. package/dist/loop/cleanup.js +44 -3
  39. package/dist/loop/loop.js +67 -2
  40. package/dist/loop/reporter.js +88 -4
  41. package/dist/loop/run-command.js +25 -8
  42. package/dist/loop/runner.js +133 -14
  43. package/dist/loop/watchdog.js +67 -17
  44. package/dist/retrofit/apply.js +10 -3
  45. package/dist/retrofit/config.js +9 -1
  46. package/dist/retrofit/gitignore.js +4 -0
  47. package/dist/retrofit/planners/claude.js +4 -1
  48. package/dist/retrofit/planners/gemini.js +2 -1
  49. package/dist/retrofit/preserve.js +51 -0
  50. package/dist/update/check.js +86 -0
  51. package/dist/update/refresh.js +28 -0
  52. package/dist/update/upgrade.js +30 -0
  53. package/docs/PUBLISHING.md +41 -0
  54. package/docs/superpowers/plans/2026-06-27-forge-a-canon.md +815 -0
  55. package/docs/superpowers/plans/2026-06-27-forge-b1-retrofit-claude.md +842 -0
  56. package/docs/superpowers/plans/2026-06-27-forge-b2-codex-gemini-tools.md +884 -0
  57. package/docs/superpowers/plans/2026-06-27-forge-c1-loop-engine.md +891 -0
  58. package/docs/superpowers/plans/2026-06-28-baustein-e-context-layer.md +981 -0
  59. package/docs/superpowers/plans/2026-06-28-forge-b3-settings-merge.md +364 -0
  60. package/docs/superpowers/plans/2026-06-28-forge-c2-loop-verify.md +502 -0
  61. package/docs/superpowers/plans/2026-06-28-forge-c3-multi-agent-runners.md +377 -0
  62. package/docs/superpowers/plans/2026-06-28-forge-c4-worktree-isolation.md +413 -0
  63. package/docs/superpowers/plans/2026-06-28-forge-c5-review-iteration.md +419 -0
  64. package/docs/superpowers/plans/2026-06-28-forge-cleanup-dep0190.md +233 -0
  65. package/docs/superpowers/plans/2026-06-28-forge-d-codegraph-choice-minimal-code.md +523 -0
  66. package/docs/superpowers/plans/2026-06-29-baustein-f-routing.md +258 -0
  67. package/docs/superpowers/plans/2026-06-29-baustein-g-loop-observability.md +1006 -0
  68. package/docs/superpowers/plans/2026-06-29-baustein-h-loop-robustness.md +374 -0
  69. package/docs/superpowers/plans/2026-06-30-baustein-i-visual-design-verification.md +450 -0
  70. package/docs/superpowers/plans/2026-07-02-baustein-j-cross-model-review-gstack-compose.md +645 -0
  71. package/docs/superpowers/plans/2026-07-02-baustein-k-zero-to-100-bootstrap.md +1024 -0
  72. package/docs/superpowers/plans/2026-07-02-baustein-m-flow-smoke-proofs.md +574 -0
  73. package/docs/superpowers/specs/2026-06-27-forge-cross-agent-harness-design.md +144 -0
  74. package/docs/superpowers/specs/2026-06-28-baustein-e-context-layer-design.md +146 -0
  75. package/docs/superpowers/specs/2026-06-29-baustein-f-routing-design.md +106 -0
  76. package/docs/superpowers/specs/2026-06-29-baustein-g-loop-observability-design.md +186 -0
  77. package/docs/superpowers/specs/2026-06-29-baustein-h-loop-robustness-design.md +113 -0
  78. package/docs/superpowers/specs/2026-06-30-baustein-i-visual-design-verification-design.md +98 -0
  79. package/docs/superpowers/specs/2026-07-02-baustein-j-cross-model-review-gstack-compose-design.md +137 -0
  80. package/docs/superpowers/specs/2026-07-02-baustein-k-zero-to-100-bootstrap-design.md +200 -0
  81. package/docs/superpowers/specs/2026-07-02-baustein-m-flow-smoke-proofs-design.md +155 -0
  82. package/docs/superpowers/specs/2026-07-10-companion-tools-decision.md +33 -0
  83. package/docs/superpowers/specs/2026-07-10-multi-agent-parallel-loop-design.md +99 -0
  84. package/package.json +8 -2
package/README.md CHANGED
@@ -1,494 +1,583 @@
1
- <div align="center">
2
-
3
- # 🐂 Yoke
4
-
5
- ### One harness, three agents — and zero trust in "done."
6
-
7
- **Yoke** installs one curated canon of skills, **mechanical safety gates**, and tool wiring into any project — natively for **Claude Code, OpenAI Codex CLI, and Gemini CLI**. Then, when you want it, an opt-in autonomous loop ships your spec story-by-story: tested, cross-model-reviewed, committed — **with a screenshot to prove every story and a video for every failure**.
8
-
9
- [![CI](https://github.com/HECer/yoke/actions/workflows/ci.yml/badge.svg)](https://github.com/HECer/yoke/actions/workflows/ci.yml)
10
- [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](#-license)
11
- ![Node](https://img.shields.io/badge/node-%E2%89%A520-339933?logo=node.js&logoColor=white)
12
- ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)
13
- ![Tests](https://img.shields.io/badge/tests-322%20passing-brightgreen.svg)
14
- ![Agents](https://img.shields.io/badge/agents-Claude%20%7C%20Codex%20%7C%20Gemini-8A2BE2)
15
- ![Built with TDD](https://img.shields.io/badge/built%20with-TDD%20%2B%20review-ff69b4.svg)
16
-
17
- </div>
18
-
19
- > **TL;DR** — `yoke new my-app --idea="..."` scaffolds a git repo, installs the harness for all three agents, and drafts a story backlog from your idea. `yoke loop run my-app --isolate --review` then implements it story by story behind hard gates: **clean tree → acceptance criteria → your real tests green → an independent model approves → commit**. If any gate is red, nothing is committed. When a story is done, there's a photo of it in `.yoke/proof/<story>/`.
20
-
21
- ---
22
-
23
- ## Why Yoke exists
24
-
25
- Agentic coding in 2026 fails in four well-documented ways. Yoke answers each one **mechanically** — in code, not in a prompt the agent can ignore:
26
-
27
- | The pain | What actually happens | What Yoke does about it |
28
- |---|---|---|
29
- | 🎭 **The verification gap** — *"agent says done, but it isn't"* | Agents submit confidently on 100% of runs while resolving far fewer; "all tests pass" when they were never run ([silent-failures research](https://arxiv.org/pdf/2603.25764)) | The loop trusts **your verify command's exit code**, never the agent's word. A story is `passes: true` only after tests are green, the reviewer approved, and the commit landed — atomically. Plus: **screenshot proofs** per story. |
30
- | 🔀 **Three agents, three configs** | Teams hand-maintain `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, skills, and MCP wiring separately — copy-paste drift everywhere | **One canon → `yoke retrofit`** generates the idiomatic native artifacts for each agent. Change the canon once, re-retrofit everywhere. |
31
- | 🌀 **Overnight loops going off the rails** | Raw Ralph-loop users "wake up to broken codebases that don't compile" | Yoke is **"Ralph, but with gates"**: clean-worktree gate, acceptance-criteria gate, green-tests gate, review gate, per-story worktree isolation, idle-timeout watchdog, single-flight lock, commit integrity. |
32
- | 😵 **Review fatigue** | AI adoption nearly doubles PR volume and review time; humans start skimming | **`yoke review`**: a *second* model reviews the diff as a pass/fail exit-code gate — chainable into verify, pre-push, or CI. Cross-model review measurably catches what self-review misses. |
33
-
34
- **Who it's for:** anyone driving Claude Code, Codex CLI, or Gemini CLI on real projects — especially if you use more than one, want autonomous runs you can trust, or are tired of "done" meaning "probably". Greenfield (`yoke new`) and brownfield (`yoke retrofit`) both work.
35
-
36
- **Who it's not for:** if you want a chat pair-programmer with no process, you don't need a harness. Yoke is for shipping with discipline.
37
-
38
- ## ⏱️ 60 seconds: idea → tested, photographed software
39
-
40
- ```console
41
- $ yoke new reading-app --idea="a web app that tracks my reading list"
42
- ✓ reading-app bootstrapped. # git repo · harness for all agents · context · PRD drafted from the idea
43
-
44
- $ yoke prd check reading-app
45
- ✓ PRD valid — 8 stories, 0 pass
46
-
47
- $ yoke loop on reading-app
48
- $ yoke loop run reading-app --isolate --review --max=10
49
- ▶ STORY-1 (0/8) — implementing… · verifying… · reviewing… ✔ committed → 1/8
50
- ▶ STORY-2 (1/8) — implementing… · verifying… ✔ committed → 2/8
51
- ▶ STORY-3 (2/8) — implementing… · verifying… ✘ blocked: story did not verify (tests red)
52
- # nothing was committed. fix, then re-run.
53
-
54
- $ ls reading-app/.yoke/proof/STORY-2/
55
- home.png list.png # photographic evidence, labelled per story
56
- ```
57
-
58
- Every claim in that transcript is enforced by code paths with tests behind them — 322 of them, and this repo was built by its own loop and gates ([how it was built](#-why--how-it-was-built)).
59
-
60
- ## 🚀 Quickstart
61
-
62
- ```bash
63
- git clone https://github.com/HECer/yoke.git && cd yoke
64
- npm install && npm run build && npm link # → global `yoke` on your PATH
65
-
66
- # Greenfield: idea → loop-ready project in one command
67
- yoke new my-app --idea="a CLI that tracks reading lists"
68
- yoke loop on my-app && yoke loop run my-app --isolate
69
-
70
- # — or retrofit an existing project —
71
- yoke validate canon # 1) sanity-check the canon
72
- yoke retrofit /path/to/project --agent=all # 2) install (non-destructive)
73
- yoke loop on /path/to/project # 3) optional: the autonomous loop
74
- yoke loop run /path/to/project --isolate --reviewer=codex --max=20
75
- ```
76
-
77
- > Requires Node ≥ 20 and git. No global install? `node /path/to/yoke/dist/cli.js …` or `npm --prefix /path/to/yoke run yoke -- …` work too. The MCP tools (rtk, graphify/Serena, Playwright MCP) are wired by Yoke but installed separately — the generated config is a clearly-labelled, adjustable template. *(npm package `@hecer/yoke` is prepared; until it's published, clone as above.)*
78
-
79
- ## 🤖 Driving it through an agent
80
-
81
- Yoke is meant to be operated *by* your coding agent after a retrofit, the agent has the skills, the safety policy, and the routing, so it knows the methodology. Copy-paste prompts (identical wording works for Claude Code, Codex CLI, and Gemini CLI):
82
-
83
- > **Set it up** — *"Install the Yoke harness in this project: run `yoke retrofit . --agent=all`, pick the code-graph you'd recommend for this codebase, and leave the autonomous loop disabled for now. Then summarise what changed and commit it."*
84
-
85
- > **Work the disciplined way** — *"From now on follow the Yoke skills you just installed: brainstorm → spec → plan → TDD → review before merging. Use the `review` skill before any merge."*
86
-
87
- > **Run autonomously** — *"Write `.yoke/prd.yaml` with one story per task (each needs acceptance criteria — see the `authoring-prd` skill), set `verify.command` in `.yoke/config.yaml`, enable the loop with `yoke loop on .`, then run it in small visible batches: `yoke loop run . --max=5`. After each batch show me `yoke loop status .`."*
88
-
89
- > **Watch / unblock** — *"Run `yoke loop status .`. If it says BLOCKED, run the project's verify command, find the root cause, fix it without weakening tests, then continue the loop."*
90
-
91
- ### Agent cheat sheet — every command is an exit-code contract
92
-
93
- Yoke's CLI is deterministic and chainable by design: an agent (or a shell `&&`) can branch on exit codes without parsing prose.
94
-
95
- | Command | What it does | Exit codes |
96
- |---|---|---|
97
- | `yoke validate [canonDir]` | Validate the canon (schema, frontmatter, templates) | `0` valid · `1` errors |
98
- | `yoke new <dir> [--idea=] [--agent=] [--runner=] [--loop]` | Greenfield bootstrap: git init scaffold retrofit context → PRD (drafted from `--idea`) committed | `0` · `1` usage / non-empty dir / draft failed (scaffold survives) · `2` draft agent unavailable |
99
- | `yoke retrofit [dir] [--agent=claude,codex,gemini\|all] [--code-graph=graphify\|serena] [--loop]` | Install/update the harness, non-destructively | `0` |
100
- | `yoke prd draft [dir] --idea= [--runner=] [--force]` | Idea → 5–12 stories with testable acceptance criteria | `0` · `1` invalid/guarded · `2` agent unavailable |
101
- | `yoke prd check [dir]` | PRD lint gate (schema, duplicate ids, empty acceptance) | `0` valid · `1` violations |
102
- | `yoke context init\|status [dir]` | Durable context layer (`PROJECT/DECISIONS/KNOWLEDGE.md`) | `0` |
103
- | `yoke loop on\|off\|status\|run\|cleanup [dir]` | The autonomous loop (see below) | run: `0` complete · `1` blocked/cap · `2` not runnable / already locked |
104
- | `yoke review [dir] [--reviewer=] [--base=] [--focus=]` | A **second model** reviews your diff | `0` approved · `1` findings · `2` no reviewer CLI |
105
- | `yoke design-scan [dir] [--max=N] [--report]` | Static AI-slop design gate | `0` within budget · `1` over |
106
- | `yoke flow-smoke [dir] [--url=] [--label=]` | Browser gate with screenshot/video proofs | `0` green · `1` failures · `2` not runnable |
107
-
108
- A genuinely hung agent self-terminates after the idle timeout (default 20 min; `--timeout`), and `yoke loop status` shows the live phase or a `⚠ possibly stuck` hint — an autonomous run is never a black box.
109
-
110
- ## ⚖️ How it compares — superpowers · gstack · Yoke
111
-
112
- Three excellent projects, three different jobs. Honest version:
113
-
114
- | | [superpowers](https://github.com/obra/superpowers) (obra) | [gstack](https://github.com/garrytan/gstack) (Garry Tan) | **Yoke** |
115
- |---|---|---|---|
116
- | **What it is** | The canonical *skills methodology*: brainstorm → plan → TDD → review as composable skills | A *software factory* for Claude Code: ~40 role skills (QA, CSO, ship…) + a real Chromium browser layer | A *cross-agent harness*: one canon → native installs, plus a gated autonomous loop |
117
- | **Agents** | Claude Code first | Claude Code + hosts like Codex/Cursor/Kiro **no Gemini CLI** | **Claude Code, Codex CLI, Gemini CLI** from one source of truth |
118
- | **Enforcement** | Advisory — skills *describe* the discipline; following them is up to the agent | Skill-driven; browser QA is genuinely real | **Mechanical** — gates live in code: clean tree, acceptance criteria, green tests, review verdict, commit integrity |
119
- | **Autonomy** | Interactive sessions | Interactive slash-commands (`/qa`, `/ship`, ) | Opt-in **Ralph loop** with watchdog, worktree isolation, single-flight lock, per-story proofs |
120
- | **Visual QA** | — | **Best-in-class**: live browser daemon (Chromium/CDP) with deep interactive QA | Built-in `flow-smoke` gate: screenshots always, video on failure, labelled per story — lighter, but *enforced* and cross-agent |
121
- | **Cross-model review** | | `/codex` second opinion (Codex-only direction) | `yoke review` resolves **codex gemini claude**, exit-code gate, works in and outside the loop |
122
- | **Footprint** | Markdown skills (plugin) | ~230 MB with browser runtime; hourly auto-update | Node CLI + markdown canon; Playwright only if you use flow-smoke, resolved **from your project** |
123
- | **License** | MIT | MIT | MIT |
124
-
125
- **They compose — use all three where they're strongest.** Yoke's canon *ships* the superpowers methodology natively for all three agents (13 skills, [attributed](canon/skills/ATTRIBUTION.md)). And if gstack is installed, `yoke retrofit` detects it and adds a routing note to `CLAUDE.md` telling Claude to prefer gstack's live-browser `/qa`, `/cso`, and ship pipeline for what Yoke deliberately doesn't bundle — no dependency, no conflict, and Codex/Gemini artifacts stay uniform.
126
-
127
- **Choose Yoke when** you run more than one agent, want autonomy you can audit (gates + proofs + logs), or want one place to maintain your team's methodology. **Choose gstack when** you live 100% in Claude Code and want the deepest interactive browser QA. **Choose superpowers when** you want the methodology alone, interactively, in Claude Code — or just use it *through* Yoke.
128
-
129
- ## 🏗️ Architecture
130
-
131
- You curate **one source of truth** — skills, policy, and tool wiring. Yoke generates the **idiomatic, native artifacts** each agent expects, non-destructively, into any repo:
132
-
133
- ```mermaid
134
- flowchart TD
135
- Canon["📦 CANON single source of truth<br/>skills · policy · loop spec · tool wiring"]
136
- Skill["🛠️ yoke retrofit<br/>detect plan apply (backup) report"]
137
- Canon --> Skill
138
- Skill --> Claude["Claude Code<br/>.claude/skills · .mcp.json · hook"]
139
- Skill --> Codex["Codex CLI<br/>AGENTS.md · config.toml · RTK.md"]
140
- Skill --> Gemini["Gemini CLI<br/>GEMINI.md · commands · settings.json"]
141
- Loop["🤖 yoke loop — autonomous Ralph loop<br/>gates · verify · review · isolation · proofs"]
142
- Claude -. drives .-> Loop
143
- Codex -. drives .-> Loop
144
- Gemini -. drives .-> Loop
145
- ```
146
-
147
- Three layers — **Canon** (`yoke validate`) → **Retrofit** (`yoke retrofit`) → **Loop** (`yoke loop`) — on top of a durable **Context layer** (`yoke context`).
148
-
149
- ### What gets generated per agent
150
-
151
- | Agent | Artifacts |
152
- |---|---|
153
- | **Claude** | `.claude/skills/`, `AGENTS.md`, `CLAUDE.md`, `.mcp.json` (code-graph + Playwright), and an rtk `PreToolUse` hook when WSL is available |
154
- | **Codex** | `AGENTS.md` (native), `.codex/config.toml` (MCP servers), `RTK.md` |
155
- | **Gemini** | `GEMINI.md`, `.gemini/commands/*.toml` (one per skill, full body), `.gemini/settings.json` (MCP + `AGENTS.md` context) |
156
-
157
- > **rtk asymmetry, handled:** Claude can rewrite commands transparently via a hook (needs WSL on Windows); Codex and Gemini have no such hook, so they get an instruction to prefix commands with `rtk` instead.
158
-
159
- > **Composes with gstack:** if [gstack](https://github.com/garrytan/gstack) is installed (repo-local or global), `yoke retrofit` adds a short "Composed tools" routing note to **CLAUDE.md only** telling Claude to prefer gstack's skills for capabilities Yoke doesn't ship (live-browser QA `/qa`, security audit `/cso`, ship/deploy `/ship`). No bundling, no dependency; the note is never written to the Codex or Gemini artifacts.
160
-
161
- ## 🧰 What's in the canon — 27 skills
162
-
163
- `yoke retrofit` installs all of these into each agent natively. Provenance is credited in [`canon/skills/ATTRIBUTION.md`](canon/skills/ATTRIBUTION.md).
164
-
165
- To stop overlapping skills from auto-invoking against each other, `canon/AGENTS.md` carries a **skill routing & precedence** block (methodology before role; one canonical entrypoint per concern — e.g. pre-merge code review is always `review`), emitted into all three agents.
166
-
167
- **Process / methodology** *superpowers-derived discipline (13)*
168
-
169
- | Skill | What it does |
170
- |---|---|
171
- | `brainstorming` | Explore intent, requirements & design before any creative work |
172
- | `writing-plans` | Turn a spec into a bite-sized, TDD implementation plan |
173
- | `executing-plans` | Execute a written plan in a separate session with review checkpoints |
174
- | `subagent-driven-development` | Run a plan task-by-task: fresh subagent + two-stage review each |
175
- | `tdd` | Write the test first, watch it fail, write minimal code, refactor |
176
- | `systematic-debugging` | Root-cause first — no fix without a confirmed cause |
177
- | `verification-before-completion` | Prove it actually works before claiming done |
178
- | `using-git-worktrees` | Isolated worktrees for safe / parallel work |
179
- | `requesting-code-review` | Request a structured review before merging |
180
- | `receiving-code-review` | Handle review feedback with rigor, not blind agreement |
181
- | `dispatching-parallel-agents` | Fan out 2+ independent tasks concurrently |
182
- | `finishing-a-development-branch` | Merge / PR / cleanup a finished branch |
183
- | `writing-skills` | Author and verify new skills |
184
-
185
- **Roles** *gstack-derived, de-gstacked to be harness-agnostic (7)*
186
-
187
- | Skill | What it does |
188
- |---|---|
189
- | `plan-eng-review` | Architecture / edge-case review of a *plan* |
190
- | `plan-ceo-review` | Founder-mode scope & ambition review of a plan |
191
- | `review` | Single canonical pre-merge code reviewdiff safety + engineering quality (architecture, edge cases, tests, performance) |
192
- | `ship` | Ship workflow: tests → review → version → changelog → PR |
193
- | `health` | Code-quality dashboard with a composite score |
194
- | `retro` | Engineering retrospective from commit history |
195
- | `document-release` | Post-ship documentation sync (README / CHANGELOG / …) |
196
-
197
- **Yoke-native** *authored or adapted for this harness (7)*
198
-
199
- | Skill | What it does |
200
- |---|---|
201
- | `yoke-retrofit` | Set up the Yoke harness in a project (detect → plan → apply) |
202
- | `authoring-prd` | Slice a product idea into loop-ready stories with testable acceptance criteria |
203
- | `minimal-code` | Write the least code that solves the task (YAGNI; ponytail-derived) |
204
- | `maintaining-context` | Keep `.yoke/context/` the durable source of truth (the Context layer) |
205
- | `workflow` | The default order of operations, from idea to deploy |
206
- | `unslop-ui` | Detect & remove AI-slop design tells (purple gradients, neon glow, emoji-icons…) |
207
- | `visual-verification` | Widen verify to design-scan + the built-in `yoke flow-smoke` gate (screenshot proofs; video on failure) |
208
-
209
- ## 🌱 Zero to 100: `yoke new` + `yoke prd`
210
-
211
- Yoke's greenfield entrypoint one command from idea to loop-ready project:
212
-
213
- ```bash
214
- yoke new my-app --idea="a CLI that tracks reading lists" # scaffold + retrofit + context + PRD
215
- yoke loop on my-app && yoke loop run my-app --isolate # hand it to the loop
216
- ```
217
-
218
- `yoke new <dir>` refuses a non-empty directory (greenfield-only use `yoke retrofit` for
219
- existing projects), then: creates and `git init`s the directory, writes a minimal scaffold
220
- (`README.md`, `.gitignore`), runs the full **retrofit** (`--agent=` as usual), initialises the
221
- **context layer** (with `--idea` seeded into `PROJECT.md` as the north star), writes a commented
222
- **PRD template** to `.yoke/prd.yaml`, and makes the initial commit — so `--isolate` works from
223
- iteration 1. With `--idea`, it then drafts the PRD from your idea via an agent (`--runner=`,
224
- default `claude`) and commits it as a second commit (`docs: draft PRD from idea`).
225
-
226
- - **Exit codes** `0` success; `1` usage / non-empty dir / draft failure (the scaffold survives —
227
- retry with `yoke prd draft`); `2` requested draft agent unavailable.
228
-
229
- **`yoke prd draft [dir] --idea="..."`** turns an idea into 5–12 small, independently shippable
230
- stories with testable behavioral acceptance criteria (greenfield STORY-1 scaffolds the project
231
- skeleton + test suite and wires `verify.command`). An existing PRD with stories is never
232
- overwritten without `--force`; the untouched template doesn't trigger the guard. Runs through
233
- the same idle-timeout watchdog as the loop (`--timeout`).
234
-
235
- **`yoke prd check [dir]`** is the chainable pre-loop lint gate: schema validation plus
236
- duplicate-id, empty-acceptance, and zero-stories checks. Exits `0` with
237
- `✓ PRD valid — N stories, M pass`, `1` on any violation. The `authoring-prd` canon skill
238
- teaches interactive sessions the same story-slicing discipline.
239
-
240
- ## 🤖 The autonomous loop
241
-
242
- Opt-in and off by default. Each iteration starts a **fresh agent** and passes through hard gates before anything is committed:
243
-
244
- ```mermaid
245
- flowchart LR
246
- A[pick next PRD story] --> B{clean worktree?}
247
- B -- no --> X[blocked]
248
- B -- yes --> C{acceptance<br/>criteria?}
249
- C -- no --> X
250
- C -- yes --> D[agent implements<br/>one story]
251
- D --> E{tests green?}
252
- E -- no --> X
253
- E -- yes --> F{reviewer<br/>approves?}
254
- F -- no --> X
255
- F -- yes --> G[commit + mark passes:true<br/>+ proof in .yoke/proof/]
256
- G --> A
257
- ```
258
-
259
- ```bash
260
- yoke loop on . # enable (recorded in .yoke/config.yaml)
261
- yoke loop status . # show state + PRD progress
262
- yoke loop run . \
263
- --runner=codex \ # implement with Codex…
264
- --reviewer=claude \ # …review with Claude (role separation)
265
- --isolate \ # each story in a throwaway git worktree
266
- --max=20
267
- yoke loop off . # disable
268
- ```
269
-
270
- **PRD format** (`.yoke/prd.yaml`):
271
-
272
- ```yaml
273
- - id: STORY-1
274
- title: Add a health endpoint
275
- priority: 1 # lower = higher priority
276
- acceptance: # Definition of Done (required, else blocked)
277
- - GET /health returns 200
278
- passes: false # the loop sets this true only on green tests
279
- ```
280
-
281
- The loop stops when every story is `passes: true`. State lives **outside the model context** the PRD file plus git so each iteration is fresh.
282
-
283
- ### Watching a run
284
-
285
- Every iteration emits token-free, harness-side feedback (Node console + local files — **zero agent tokens**):
286
-
287
- - **Live console** `▶ S6 (19/45) — implementing… · verifying… ✔ committed → 20/45`.
288
- - **`.yoke/loop-status.json`** the current state; read it any time with `yoke loop status`:
289
- ```
290
- Loop: BLOCKED on S5 "Segment schemas"
291
- verifying · iteration 19 · 18/45 · updated 2026-06-29T10:00:00.000Z
292
- reason: story did not verify (working tree has uncommitted changes — review/clean before re-running)
293
- ```
294
- - **`.yoke/loop.log`** an append-only timeline of every phase transition.
295
-
296
- A per-iteration **idle timeout** guards against a genuinely hung agent: if the agent produces
297
- **no output at all** for `--timeout` minutes (default 20; `0` disables), the loop kills it
298
- (SIGTERM→SIGKILL) and marks the story blocked. A slow-but-working agent that keeps streaming
299
- output is **never** killed the output stream *is* the liveness signal. Set a project default
300
- with `loop.timeoutMinutes` in `.yoke/config.yaml`.
301
-
302
- The loop trusts **verify**, not the agent's exit code: a story whose tests are green is
303
- committed even if the agent process exited non-zero (a common Windows `.cmd`-wrapper ghost).
304
- A failing verify is retried up to `verify.retries` times (default 1) so a transient flake
305
- self-heals while a real failure still blocks.
306
-
307
- `.yoke/loop-status.json`, `.yoke/loop.log`, and `.yoke/loop.lock` are runtime artifacts;
308
- `yoke retrofit` gitignores them (along with `.yoke/worktrees/`, `.yoke/backup/`, and
309
- `.yoke/proof/`) so they never trip the clean-tree gate.
310
-
311
- ### Single-flight guard + cleanup
312
-
313
- Two concurrent `yoke loop run`s would race on the PRD and status files, so the loop takes a
314
- **lock** (`.yoke/loop.lock`) for the duration of a run. A second invocation exits `2` with
315
- `Another loop is already running here (pid …). If that is wrong, run: yoke loop cleanup`. A lock
316
- whose holder process is dead is taken over automatically (with a warning).
317
-
318
- **`yoke loop cleanup [dir]`** removes what a crashed loop leaves behind: every worktree under
319
- `.yoke/worktrees/` (via `git worktree remove --force` + `prune` — user-created worktrees are
320
- never touched) and a **stale** lock file. A live lock is reported and left alone. Exits `0`
321
- when everything cleaned, `1` if any removal failed.
322
-
323
- ## 🔍 Cross-model review (`yoke review`)
324
-
325
- Outside the loop, `yoke review` has a **second** model review your current diff as a
326
- pass/fail gate the interactive counterpart to the loop's `--review`/`--reviewer`.
327
-
328
- ```bash
329
- yoke review . # review the uncommitted working tree
330
- yoke review . --base=main # review the range main..HEAD instead
331
- yoke review . --reviewer=codex # force a specific reviewer
332
- yoke review . --focus="the auth layer" # steer what it scrutinises
333
- ```
334
-
335
- - **Reviewer resolution** picks the first available of **codex → gemini → claude**,
336
- preferring a model *other* than the one you drive so the review is genuinely cross-model.
337
- On a Claude-only machine it degrades to a self-review (and says so).
338
- - **Scope** — the uncommitted working tree by default, or a commit range with `--base=<ref>`.
339
- - **Exit-code gate** exits `0` when the reviewer approves, `1` when it finds a blocking
340
- issue, `2` when no (or an unavailable) reviewer CLI is found. Chain it: `... && yoke review`,
341
- or wire it into a pre-push hook.
342
- - Runs through the same idle-timeout watchdog as the loop (`--timeout`, default 20 min).
343
-
344
- ## 🎨 Visual & design verification done, with a photo
345
-
346
- Unit tests don't catch a blank page, an unwired route, or generic AI-slop design. Yoke adds three things:
347
-
348
- - **`yoke design-scan [dir]`** — a static scanner for the visual *tells* of AI-generated UIs
349
- (AI-purple gradients, gradient hero text, neon glow, emoji-as-icons, gradient overload). It
350
- scores findings and **exits non-zero over budget** (`--max`, default 4; `--report` to list only),
351
- so it drops straight into your verify pipeline.
352
- - **`yoke flow-smoke [dir]`** a built-in browser gate with **proof artifacts** (below).
353
- - **`unslop-ui` + `visual-verification` skills** — the design rubric, plus how to compose a verify
354
- pipeline (`types units design-scan flow-smoke`).
355
-
356
- Because the loop trusts **verify as the source of truth**, widening `verify.command` to include the
357
- scanner and the flow-smoke makes visual quality a real gate — not an afterthought.
358
-
359
- *Tell set informed by the MIT-licensed [vibecoded-design-tells](https://github.com/JCarterJohnson/vibecoded-design-tells) research.*
360
-
361
- ### `yoke flow-smoke [dir] [--url=<baseUrl>] [--label=<name>]`
362
-
363
- Configure your key user flows once in `.yoke/config.yaml`:
364
-
365
- ```yaml
366
- smoke:
367
- baseUrl: http://localhost:3000
368
- flows:
369
- - name: home
370
- path: /
371
- landmark: "main h1" # optional CSS selector to wait for
372
- - name: login
373
- path: /login
374
- ```
375
-
376
- For every flow, `yoke flow-smoke` loads the route against the running dev server, waits for the
377
- landmark, and fails on a non-OK response or **any console/page error**. The proof contract:
378
-
379
- - **Screenshots always** every flow (pass *or* fail) saves `.yoke/proof/<label>/<flow>.png`;
380
- the failure screenshot *is* the evidence.
381
- - **Video only on failure** each flow is recorded, but the clip is kept only when the flow
382
- goes red (`<flow>.webm`); green runs delete it.
383
- - **Labelled per story** — inside the loop, verify runs with `YOKE_STORY=<story-id>`, so proofs
384
- land in `.yoke/proof/<story-id>/` automatically. Standalone runs use `latest`, or pass
385
- `--label=`. The label dir is wiped per run evidence is always from the latest run.
386
- - **Exit codes** `0` all flows green (chain it: `... && yoke design-scan . && yoke flow-smoke .`),
387
- `1` any flow failed, `2` not runnable (no `smoke:` config, or Playwright missing).
388
- - **Playwright comes from the *target project*, never Yoke** —
389
- `npm i -D playwright && npx playwright install chromium` there. Start the dev server before
390
- verify (e.g. via `start-server-and-test`); `--url=` overrides `baseUrl`.
391
-
392
- `.yoke/proof/` is gitignored by the retrofit — proofs are runtime artifacts and never break the
393
- loop's clean-tree gate.
394
-
395
- ## 🧠 Context layer (`.yoke/context/`)
396
-
397
- Yoke keeps durable, cross-session context so a fresh-context agent is never blind:
398
-
399
- - `PROJECT.md` — the north star (goal, constraints, non-goals, success criteria).
400
- - `DECISIONS.md` — an append-only ledger. The loop adds an entry per completed story; you and agents add the *why*.
401
- - `KNOWLEDGE.md` — reusable gotchas and conventions.
402
-
403
- `yoke retrofit` scaffolds these files (non-destructively your edits are never overwritten).
404
- The loop reads them into every agent + reviewer prompt and logs decisions back on each story's
405
- commit. Manage them directly with `yoke context init` and `yoke context status`. The
406
- `maintaining-context` skill teaches agents to honour the same files during interactive work.
407
-
408
- > Commit `.yoke/context/` to git. The `--isolate` loop runs each iteration in a worktree
409
- > checked out from HEAD, so it only sees committed context.
410
-
411
- ## 🛡️ Safety model
412
-
413
- Yoke's guardrails are **mechanical, not advisory** — the loop blocks on a dirty worktree, missing acceptance criteria, red tests, or a reviewer rejection, and **none of them rely on the agent choosing to behave**.
414
-
415
- - **Commit integrity** — a story is never recorded `passes: true` without a corresponding commit; a failed commit reverts the PRD.
416
- - **Role separation** — the implementer never reviews its own work; `--reviewer` can even be a different agent.
417
- - **Isolation** — with `--isolate`, failed or partial work is discarded with the worktree and never reaches your main tree.
418
- - **Non-destructive retrofit** existing files are backed up before any change; settings are merged, not replaced.
419
- - **Independent verification** "done" means *your test command exits 0*, not "the agent said so".
420
- - **Single-flight** — a lock prevents two loops from racing the same repo; `yoke loop cleanup` recovers after crashes.
421
-
422
- ## 🧠 Choose your code-graph
423
-
424
- `yoke retrofit --code-graph=graphify|serena` (default `graphify`, remembered per project). The `yoke-retrofit` skill asks and recommends based on the project.
425
-
426
- | | **graphify** | **Serena** |
427
- |---|---|---|
428
- | Engine | tree-sitter AST + graph | real language servers (LSP) |
429
- | Strength | fast, multimodal (code + PDFs + images) | symbol-exact cross-file refactoring |
430
- | Token efficiency | ~70× reduction on large mixed repos | standard, no index to go stale |
431
- | Best for | rapid exploration / migration / onboarding | systematic refactoring in typed codebases |
432
- | Caveat | heuristic edges; static index can go stale | one language server per language |
433
-
434
- ## 🪙 Token efficiency
435
-
436
- Yoke attacks tokens on two complementary surfaces:
437
-
438
- - **rtk** compresses noisy command/tool output before it enters context (wired as a hook/instruction per agent).
439
- - The **`minimal-code`** skill installs a YAGNI / "lazy senior dev" ladder so agents write the least code that solves the task fewer output tokens, smaller review surface. *(Adapted from the MIT-licensed [ponytail](https://github.com/DietrichGebert/ponytail) ruleset.)*
440
-
441
- ## 🌱 Why & how it was built
442
-
443
- **The problem.** Coding agents are powerful, but each speaks its own dialect — Claude has skills and hooks, Codex reads `AGENTS.md` and a TOML config, Gemini wants commands and a settings file. Keeping the same skills, safety policy, and tool wiring consistent across all of them means copy-paste drift and three things to maintain. Yoke exists to keep **one** source of truth, generate the right native artifacts for each agent, and let that harness run **autonomously and safely** when you want to hand it a spec and walk away.
444
-
445
- **The inspiration.** Yoke is a synthesis of ideas already proven across the ecosystem: composable-skills methodology ([superpowers](https://github.com/obra/superpowers), [gstack](https://github.com/garrytan/gstack)); the portable [AGENTS.md](https://agents.md/) standard; the *"one source-of-truth → idiomatic per-harness artifacts"* generation pattern ([wshobson/agents](https://github.com/wshobson/agents)); spec-driven autonomous orchestration (GSD); mechanical safety gates and role separation (safe-agentic-workflow); and the **Ralph loop** (Geoff Huntley) — keep handing a *fresh* agent the next task until the spec is done. Token efficiency comes from [rtk](https://github.com/rtk-ai/rtk) and the write-less-code idea behind [ponytail](https://github.com/DietrichGebert/ponytail).
446
-
447
- **How it was built.** Yoke was built the way it's meant to be *used* — agent-driven, incremental, and test-first. The stack was chosen by **researching alternatives first** (which is how `jcodemunch` was dropped for its license and Serena was added as an option). Then every component shipped one small piece at a time through a disciplined loop: **brainstorm → spec → plan → TDD implementation → an independent two-stage review** (does it match the spec? is it well-built?) **→ merge**. Those reviews caught real bugs before they shipped — a Windows `.cmd` spawn failure, a commit-integrity hole, a path-traversal that could delete project data, a resolution bug that broke the CLI's default invocation, a TOML-escaping bug. Yoke was even **dogfooded on its own repo**, which surfaced (and fixed) a genuine Windows bug. Every spec and plan lives in [`docs/superpowers/`](docs/superpowers/).
448
-
449
- ## 🗂️ Project layout
450
-
451
- ```text
452
- canon/ # the source of truth — harness-agnostic
453
- AGENTS.md skills/ policy/ loop/ tools/ manifest.yaml
454
- src/
455
- canon/ # manifest schema + validator (yoke validate)
456
- retrofit/ # detect · plan · apply · planners (claude/codex/gemini) · tools
457
- loop/ # prd · gates · runner · verify · git/worktree · loop · run-command · lock · cleanup
458
- new/ # yoke new greenfield bootstrap
459
- prd/ # yoke prd draft|check idea stories + lint gate
460
- review/ # yoke review — cross-model diff gate
461
- smoke/ # yoke flow-smokebrowser gate with screenshot/video proofs
462
- scan/ # yoke design-scan AI-slop design gate
463
- context/ # the durable context layer
464
- docs/superpowers/ # the spec and every component's implementation plan
465
- ```
466
-
467
- ## 🗺️ Roadmap
468
-
469
- - **npm publish** (`@hecer/yoke`) one-liner `npx` install (package prepared).
470
- - **Security gate** a `cso`-style audit skill + `yoke audit` (deps, secrets, diff surface).
471
- - **Token-budget gate** per-story budget with abort; cost transparency for loop runs.
472
- - **Multi-reviewer quorum** N independent reviewers with distinct lenses (correctness / security / acceptance).
473
- - **Merge queue** — re-test against the latest main before integrating, for parallel/multi-agent loops.
474
- - **More agents** the canon→retrofit pattern generalises; OpenCode and Copilot CLI are natural next targets.
475
-
476
- ## 🧪 Development
477
-
478
- ```bash
479
- npm test # vitest (322 tests)
480
- npm run build # tsc, no emit errors
481
- npm run yoke -- validate canon
482
- ```
483
-
484
- ## 🙏 Credits & inspiration
485
-
486
- Yoke stands on the shoulders of a great ecosystem: methodology ideas from [superpowers](https://github.com/obra/superpowers) and [gstack](https://github.com/garrytan/gstack); the [AGENTS.md](https://agents.md/) standard; the generator pattern from [wshobson/agents](https://github.com/wshobson/agents); the Ralph autonomous-loop pattern; safety-gate thinking from safe-agentic-workflow; and the wired tools [rtk](https://github.com/rtk-ai/rtk), [graphify](https://github.com/safishamsi/graphify), [Serena](https://github.com/oraios/serena), and [Playwright MCP](https://github.com/microsoft/playwright-mcp). The `minimal-code` skill adapts the MIT-licensed [ponytail](https://github.com/DietrichGebert/ponytail) ruleset.
487
-
488
- ## 📄 License
489
-
490
- MIT see [`LICENSE`](LICENSE).
491
-
492
- <div align="center">
493
- <sub>Built with a disciplined loop: brainstorm → spec → plan → TDD → two-stage review → merge — and reviewed by a second model, because we don't trust "done" either.</sub>
494
- </div>
1
+ <div align="center">
2
+
3
+ # 🐂 Yoke
4
+
5
+ ### One harness, three agents — and zero trust in "done."
6
+
7
+ **Yoke** installs one curated canon of skills, **mechanical safety gates**, and tool wiring into any project — natively for **Claude Code, OpenAI Codex CLI, and Gemini CLI**. Then, when you want it, an opt-in autonomous loop ships your spec story-by-story: tested, cross-model-reviewed, committed — **with a screenshot to prove every story and a video for every failure**.
8
+
9
+ [![CI](https://github.com/HECer/yoke/actions/workflows/ci.yml/badge.svg)](https://github.com/HECer/yoke/actions/workflows/ci.yml)
10
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](#-license)
11
+ ![Node](https://img.shields.io/badge/node-%E2%89%A520-339933?logo=node.js&logoColor=white)
12
+ ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)
13
+ ![Tests](https://img.shields.io/badge/tests-322%20passing-brightgreen.svg)
14
+ ![Agents](https://img.shields.io/badge/agents-Claude%20%7C%20Codex%20%7C%20Gemini-8A2BE2)
15
+ ![Built with TDD](https://img.shields.io/badge/built%20with-TDD%20%2B%20review-ff69b4.svg)
16
+
17
+ </div>
18
+
19
+ > **TL;DR** — `yoke new my-app --idea="..."` scaffolds a git repo, installs the harness for all three agents, and drafts a story backlog from your idea. `yoke loop run my-app --isolate --review` then implements it story by story behind hard gates: **clean tree → acceptance criteria → your real tests green → an independent model approves → commit**. If any gate is red, nothing is committed. When a story is done, there's a photo of it in `.yoke/proof/<story>/`.
20
+
21
+ ---
22
+
23
+ ## Why Yoke exists
24
+
25
+ Agentic coding in 2026 fails in four well-documented ways. Yoke answers each one **mechanically** — in code, not in a prompt the agent can ignore:
26
+
27
+ | The pain | What actually happens | What Yoke does about it |
28
+ |---|---|---|
29
+ | 🎭 **The verification gap** — *"agent says done, but it isn't"* | Agents submit confidently on 100% of runs while resolving far fewer; "all tests pass" when they were never run ([silent-failures research](https://arxiv.org/pdf/2603.25764)) | The loop trusts **your verify command's exit code**, never the agent's word. A story is `passes: true` only after tests are green, the reviewer approved, and the commit landed — atomically. Plus: **screenshot proofs** per story. |
30
+ | 🔀 **Three agents, three configs** | Teams hand-maintain `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, skills, and MCP wiring separately — copy-paste drift everywhere | **One canon → `yoke retrofit`** generates the idiomatic native artifacts for each agent. Change the canon once, re-retrofit everywhere. |
31
+ | 🌀 **Overnight loops going off the rails** | Raw Ralph-loop users "wake up to broken codebases that don't compile" | Yoke is **"Ralph, but with gates"**: clean-worktree gate, acceptance-criteria gate, green-tests gate, review gate, per-story worktree isolation, idle-timeout watchdog, single-flight lock, commit integrity. |
32
+ | 😵 **Review fatigue** | AI adoption nearly doubles PR volume and review time; humans start skimming | **`yoke review`**: a *second* model reviews the diff as a pass/fail exit-code gate — chainable into verify, pre-push, or CI. Cross-model review measurably catches what self-review misses. |
33
+
34
+ **Who it's for:** anyone driving Claude Code, Codex CLI, or Gemini CLI on real projects — especially if you use more than one, want autonomous runs you can trust, or are tired of "done" meaning "probably". Greenfield (`yoke new`) and brownfield (`yoke retrofit`) both work.
35
+
36
+ **Who it's not for:** if you want a chat pair-programmer with no process, you don't need a harness. Yoke is for shipping with discipline.
37
+
38
+ ## ⏱️ 60 seconds: idea → tested, photographed software
39
+
40
+ ```console
41
+ $ yoke new reading-app --idea="a web app that tracks my reading list"
42
+ ✓ reading-app bootstrapped. # git repo · harness for all agents · context · PRD drafted from the idea
43
+
44
+ $ yoke prd check reading-app
45
+ ✓ PRD valid — 8 stories, 0 pass
46
+
47
+ $ yoke loop on reading-app
48
+ $ yoke loop run reading-app --isolate --review --max=10
49
+ ▶ STORY-1 (0/8) — implementing… · verifying… · reviewing… ✔ committed → 1/8
50
+ ▶ STORY-2 (1/8) — implementing… · verifying… ✔ committed → 2/8
51
+ ▶ STORY-3 (2/8) — implementing… · verifying… ✘ blocked: story did not verify (tests red)
52
+ # nothing was committed. fix, then re-run.
53
+
54
+ $ ls reading-app/.yoke/proof/STORY-2/
55
+ home.png list.png # photographic evidence, labelled per story
56
+ ```
57
+
58
+ Every claim in that transcript is enforced by code paths with tests behind them — 322 of them, and this repo was built by its own loop and gates ([how it was built](#-why--how-it-was-built)).
59
+
60
+ ## 🚀 Quickstart
61
+
62
+ ```bash
63
+ npm install -g @hecer/yoke # global `yoke` on your PATH
64
+ # (or from source: git clone https://github.com/HECer/yoke.git && cd yoke && npm install && npm run build && npm link)
65
+
66
+ # Greenfield: idea → loop-ready project in one command
67
+ yoke new my-app --idea="a CLI that tracks reading lists"
68
+ yoke loop on my-app && yoke loop run my-app --isolate
69
+
70
+ # — or retrofit an existing project —
71
+ yoke validate canon # 1) sanity-check the canon
72
+ yoke retrofit /path/to/project --agent=all # 2) install (non-destructive)
73
+ yoke loop on /path/to/project # 3) optional: the autonomous loop
74
+ yoke loop run /path/to/project --isolate --reviewer=codex --max=20
75
+ ```
76
+
77
+ > Requires Node ≥ 20 and git. No global install? `node /path/to/yoke/dist/cli.js …` or `npm --prefix /path/to/yoke run yoke -- …` work too. The MCP tools (rtk, graphify/Serena, Playwright MCP) are wired by Yoke but installed separately — the generated config is a clearly-labelled, adjustable template.
78
+
79
+ ### Or install the skills as a Claude Code plugin
80
+
81
+ The canon is also packaged as a Claude Code plugin — the repo is its own marketplace:
82
+
83
+ ```text
84
+ /plugin marketplace add HECer/yoke
85
+ /plugin install yoke@yoke
86
+ ```
87
+
88
+ That gives you all canon skills under the `yoke:` namespace (e.g. `yoke:tdd`, `yoke:review`) inside Claude Code — no retrofit needed. The `yoke` CLI (loop, gates, retrofit for Codex/Gemini) still comes from `npm i -g @hecer/yoke`. Gemini CLI users can likewise `gemini extensions install https://github.com/HECer/yoke`.
89
+
90
+ ### Staying up to date
91
+
92
+ Yoke checks for new releases npm/gh-style: a **non-blocking background check** (at most once a day, detached, offline-safe) prints a one-line hint when a newer version exists — upgrading itself is always an explicit act:
93
+
94
+ ```bash
95
+ yoke upgrade # npm install -g @hecer/yoke@latest
96
+ ```
97
+
98
+ Disable the check with `YOKE_NO_UPDATE_CHECK=1` (it is also silent in CI, `--json` runs, and piped output). Projects that want the loop to self-update can opt in via `.yoke/config.yaml`:
99
+
100
+ ```yaml
101
+ update:
102
+ auto: true # upgrade at loop START only never mid-run; applies from the next invocation
103
+ ```
104
+
105
+ Auto-upgrade is deliberately **not** the default: a gate harness shouldn't change itself mid-project, and unreviewed auto-installs are a supply-chain hazard.
106
+
107
+ ## 🤖 Driving it through an agent
108
+
109
+ Yoke is meant to be operated *by* your coding agent — after a retrofit, the agent has the skills, the safety policy, and the routing, so it knows the methodology. Copy-paste prompts (identical wording works for Claude Code, Codex CLI, and Gemini CLI):
110
+
111
+ > **Set it up** — *"Install the Yoke harness in this project: run `yoke retrofit . --agent=all`, pick the code-graph you'd recommend for this codebase, and leave the autonomous loop disabled for now. Then summarise what changed and commit it."*
112
+
113
+ > **Work the disciplined way** — *"From now on follow the Yoke skills you just installed: brainstorm → spec → plan → TDD → review before merging. Use the `review` skill before any merge."*
114
+
115
+ > **Run autonomously** — *"Write `.yoke/prd.yaml` with one story per task (each needs acceptance criteria — see the `authoring-prd` skill), set `verify.command` in `.yoke/config.yaml`, enable the loop with `yoke loop on .`, then run it in small visible batches: `yoke loop run . --max=5`. After each batch show me `yoke loop status .`."*
116
+
117
+ > **Watch / unblock** *"Run `yoke loop status .`. If it says BLOCKED, run the project's verify command, find the root cause, fix it without weakening tests, then continue the loop."*
118
+
119
+ > ⚠️ **Long runs from inside an agent session:** a multi-story `yoke loop run` outlives most agents' shell-tool timeouts (Claude Code's Bash tool defaults to 2 minutes). If the outer tool call is killed mid-run, you get a stale lock and possibly half-finished state — which *looks* like a hang. Rules of thumb: run the loop **in the background** (e.g. Claude Code's `run_in_background`), keep batches small (`--max=3..5`), poll with `yoke loop status`, and after any interrupted run do `yoke loop cleanup` before the next one. A `running` status with no update for 20+ minutes on a claude runner is worth checking — since 0.5.0 the runner streams continuously, so prolonged true silence is no longer normal.
120
+
121
+ > ⚠️ **Never kill agent processes by name or command-line pattern** (e.g. every process matching `dangerously-skip-permissions`): on a machine running several yoke projects, that takes down the *healthy* runners of the other projects mid-story they stall and their loops block. `yoke loop cleanup` is the scoped alternative: each watchdog records its pids in the project's `.yoke/runner.pid`, and cleanup kills exactly those recorded trees — nothing else on the machine.
122
+
123
+ ### Agent cheat sheet every command is an exit-code contract
124
+
125
+ Yoke's CLI is deterministic and chainable by design: an agent (or a shell `&&`) can branch on exit codes without parsing prose.
126
+
127
+ | Command | What it does | Exit codes |
128
+ |---|---|---|
129
+ | `yoke validate [canonDir]` | Validate the canon (schema, frontmatter, templates) | `0` valid · `1` errors |
130
+ | `yoke new <dir> [--idea=] [--agent=] [--runner=] [--loop]` | Greenfield bootstrap: git init → scaffold → retrofit → context → PRD (drafted from `--idea`) → committed | `0` · `1` usage / non-empty dir / draft failed (scaffold survives) · `2` draft agent unavailable |
131
+ | `yoke retrofit [dir] [--agent=claude,codex,gemini\|all] [--code-graph=graphify\|serena] [--loop]` | Install/update the harness, non-destructively | `0` |
132
+ | `yoke prd draft [dir] --idea= [--runner=] [--force]` | Idea → 5–12 stories with testable acceptance criteria | `0` · `1` invalid/guarded · `2` agent unavailable |
133
+ | `yoke prd check [dir]` | PRD lint gate (schema, duplicate ids, empty acceptance) | `0` valid · `1` violations |
134
+ | `yoke context init\|status [dir]` | Durable context layer (`PROJECT/DECISIONS/KNOWLEDGE.md`) | `0` |
135
+ | `yoke loop on\|off\|status\|run\|cleanup [dir]` | The autonomous loop (see below) | run: `0` complete · `1` blocked/cap · `2` not runnable / already locked · `3` paused |
136
+ | `yoke review [dir] [--reviewer=] [--base=] [--focus=]` | A **second model** reviews your diff | `0` approved · `1` findings · `2` no reviewer CLI |
137
+ | `yoke design-scan [dir] [--max=N] [--report]` | Static AI-slop design gate | `0` within budget · `1` over |
138
+ | `yoke flow-smoke [dir] [--url=] [--label=]` | Browser gate with screenshot/video proofs | `0` green · `1` failures · `2` not runnable |
139
+
140
+ A genuinely hung agent self-terminates after the idle timeout (default 20 min; `--timeout`), and `yoke loop status` shows the live phase or a `⚠ possibly stuck` hint — an autonomous run is never a black box.
141
+
142
+ ## ⚖️ How it compares — superpowers · gstack · Yoke
143
+
144
+ Three excellent projects, three different jobs. Honest version:
145
+
146
+ | | [superpowers](https://github.com/obra/superpowers) (obra) | [gstack](https://github.com/garrytan/gstack) (Garry Tan) | **Yoke** |
147
+ |---|---|---|---|
148
+ | **What it is** | The canonical *skills methodology*: brainstorm → plan → TDD → review as composable skills | A *software factory* for Claude Code: ~40 role skills (QA, CSO, ship…) + a real Chromium browser layer | A *cross-agent harness*: one canon → native installs, plus a gated autonomous loop |
149
+ | **Agents** | Claude Code first | Claude Code + hosts like Codex/Cursor/Kiro — **no Gemini CLI** | **Claude Code, Codex CLI, Gemini CLI** from one source of truth |
150
+ | **Enforcement** | Advisory — skills *describe* the discipline; following them is up to the agent | Skill-driven; browser QA is genuinely real | **Mechanical** — gates live in code: clean tree, acceptance criteria, green tests, review verdict, commit integrity |
151
+ | **Autonomy** | Interactive sessions | Interactive slash-commands (`/qa`, `/ship`, …) | Opt-in **Ralph loop** with watchdog, worktree isolation, single-flight lock, per-story proofs |
152
+ | **Visual QA** | — | **Best-in-class**: live browser daemon (Chromium/CDP) with deep interactive QA | Built-in `flow-smoke` gate: screenshots always, video on failure, labelled per story — lighter, but *enforced* and cross-agent |
153
+ | **Cross-model review** | | `/codex` second opinion (Codex-only direction) | `yoke review` resolves **codex gemini → claude**, exit-code gate, works in and outside the loop |
154
+ | **Footprint** | Markdown skills (plugin) | ~230 MB with browser runtime; hourly auto-update | Node CLI + markdown canon; Playwright only if you use flow-smoke, resolved **from your project** |
155
+ | **License** | MIT | MIT | MIT |
156
+
157
+ **They compose use all three where they're strongest.** Yoke's canon *ships* the superpowers methodology natively for all three agents (13 skills, [attributed](canon/skills/ATTRIBUTION.md)). And if gstack is installed, `yoke retrofit` detects it and adds a routing note to `CLAUDE.md` telling Claude to prefer gstack's live-browser `/qa`, `/cso`, and ship pipeline for what Yoke deliberately doesn't bundle — no dependency, no conflict, and Codex/Gemini artifacts stay uniform.
158
+
159
+ **Choose Yoke when** you run more than one agent, want autonomy you can audit (gates + proofs + logs), or want one place to maintain your team's methodology. **Choose gstack when** you live 100% in Claude Code and want the deepest interactive browser QA. **Choose superpowers when** you want the methodology alone, interactively, in Claude Code or just use it *through* Yoke.
160
+
161
+ ## 🏗️ Architecture
162
+
163
+ You curate **one source of truth** skills, policy, and tool wiring. Yoke generates the **idiomatic, native artifacts** each agent expects, non-destructively, into any repo:
164
+
165
+ ```mermaid
166
+ flowchart TD
167
+ Canon["📦 CANONsingle source of truth<br/>skills · policy · loop spec · tool wiring"]
168
+ Skill["🛠️ yoke retrofit<br/>detect → plan → apply (backup) → report"]
169
+ Canon --> Skill
170
+ Skill --> Claude["Claude Code<br/>.claude/skills · .mcp.json · hook"]
171
+ Skill --> Codex["Codex CLI<br/>AGENTS.md · config.toml · RTK.md"]
172
+ Skill --> Gemini["Gemini CLI<br/>GEMINI.md · commands · settings.json"]
173
+ Loop["🤖 yoke loop autonomous Ralph loop<br/>gates · verify · review · isolation · proofs"]
174
+ Claude -. drives .-> Loop
175
+ Codex -. drives .-> Loop
176
+ Gemini -. drives .-> Loop
177
+ ```
178
+
179
+ Three layers — **Canon** (`yoke validate`) **Retrofit** (`yoke retrofit`) → **Loop** (`yoke loop`) — on top of a durable **Context layer** (`yoke context`).
180
+
181
+ ### What gets generated per agent
182
+
183
+ | Agent | Artifacts |
184
+ |---|---|
185
+ | **Claude** | `.claude/skills/`, `AGENTS.md`, `CLAUDE.md`, `.mcp.json` (code-graph + Playwright), and an rtk `PreToolUse` hook when WSL is available |
186
+ | **Codex** | `AGENTS.md` (native), `.codex/config.toml` (MCP servers), `RTK.md` |
187
+ | **Gemini** | `GEMINI.md`, `.gemini/commands/*.toml` (one per skill, full body), `.gemini/settings.json` (MCP + `AGENTS.md` context) |
188
+
189
+ > **rtk asymmetry, handled:** Claude can rewrite commands transparently via a hook (needs WSL on Windows); Codex and Gemini have no such hook, so they get an instruction to prefix commands with `rtk` instead.
190
+
191
+ > **Composes with gstack:** if [gstack](https://github.com/garrytan/gstack) is installed (repo-local or global), `yoke retrofit` adds a short "Composed tools" routing note to **CLAUDE.md only** telling Claude to prefer gstack's skills for capabilities Yoke doesn't ship (live-browser QA `/qa`, security audit `/cso`, ship/deploy `/ship`). No bundling, no dependency; the note is never written to the Codex or Gemini artifacts.
192
+
193
+ > **Your content survives re-retrofits preserve blocks:** anything you put between
194
+ > `<!-- yoke:preserve:start -->` and `<!-- yoke:preserve:end -->` in a generated file is
195
+ > carried into the regenerated version on every future `yoke retrofit`. The generated
196
+ > `CLAUDE.md` and `GEMINI.md` ship an empty preserve block scaffold — put your project-specific
197
+ > instructions (tech stack, workflow, `@`-includes) inside it. Works in any yoke-written file;
198
+ > content *outside* the markers is still replaced (and backed up under `.yoke/backup/`).
199
+
200
+ ## 🧰 What's in the canon — 27 skills
201
+
202
+ `yoke retrofit` installs all of these into each agent natively. Provenance is credited in [`canon/skills/ATTRIBUTION.md`](canon/skills/ATTRIBUTION.md).
203
+
204
+ To stop overlapping skills from auto-invoking against each other, `canon/AGENTS.md` carries a **skill routing & precedence** block (methodology before role; one canonical entrypoint per concern — e.g. pre-merge code review is always `review`), emitted into all three agents.
205
+
206
+ **Process / methodology** *superpowers-derived discipline (13)*
207
+
208
+ | Skill | What it does |
209
+ |---|---|
210
+ | `brainstorming` | Explore intent, requirements & design before any creative work |
211
+ | `writing-plans` | Turn a spec into a bite-sized, TDD implementation plan |
212
+ | `executing-plans` | Execute a written plan in a separate session with review checkpoints |
213
+ | `subagent-driven-development` | Run a plan task-by-task: fresh subagent + two-stage review each |
214
+ | `tdd` | Write the test first, watch it fail, write minimal code, refactor |
215
+ | `systematic-debugging` | Root-cause first no fix without a confirmed cause |
216
+ | `verification-before-completion` | Prove it actually works before claiming done |
217
+ | `using-git-worktrees` | Isolated worktrees for safe / parallel work |
218
+ | `requesting-code-review` | Request a structured review before merging |
219
+ | `receiving-code-review` | Handle review feedback with rigor, not blind agreement |
220
+ | `dispatching-parallel-agents` | Fan out 2+ independent tasks concurrently |
221
+ | `finishing-a-development-branch` | Merge / PR / cleanup a finished branch |
222
+ | `writing-skills` | Author and verify new skills |
223
+
224
+ **Roles** *gstack-derived, de-gstacked to be harness-agnostic (7)*
225
+
226
+ | Skill | What it does |
227
+ |---|---|
228
+ | `plan-eng-review` | Architecture / edge-case review of a *plan* |
229
+ | `plan-ceo-review` | Founder-mode scope & ambition review of a plan |
230
+ | `review` | Single canonical pre-merge code review — diff safety + engineering quality (architecture, edge cases, tests, performance) |
231
+ | `ship` | Ship workflow: tests review version changelog PR |
232
+ | `health` | Code-quality dashboard with a composite score |
233
+ | `retro` | Engineering retrospective from commit history |
234
+ | `document-release` | Post-ship documentation sync (README / CHANGELOG / …) |
235
+
236
+ **Yoke-native** *authored or adapted for this harness (7)*
237
+
238
+ | Skill | What it does |
239
+ |---|---|
240
+ | `yoke-retrofit` | Set up the Yoke harness in a project (detect → plan → apply) |
241
+ | `authoring-prd` | Slice a product idea into loop-ready stories with testable acceptance criteria |
242
+ | `minimal-code` | Write the least code that solves the task (YAGNI; ponytail-derived) |
243
+ | `maintaining-context` | Keep `.yoke/context/` the durable source of truth (the Context layer) |
244
+ | `workflow` | The default order of operations, from idea to deploy |
245
+ | `unslop-ui` | Detect & remove AI-slop design tells (purple gradients, neon glow, emoji-icons…) |
246
+ | `visual-verification` | Widen verify to design-scan + the built-in `yoke flow-smoke` gate (screenshot proofs; video on failure) |
247
+
248
+ ## 🌱 Zero to 100: `yoke new` + `yoke prd`
249
+
250
+ Yoke's greenfield entrypoint one command from idea to loop-ready project:
251
+
252
+ ```bash
253
+ yoke new my-app --idea="a CLI that tracks reading lists" # scaffold + retrofit + context + PRD
254
+ yoke loop on my-app && yoke loop run my-app --isolate # hand it to the loop
255
+ ```
256
+
257
+ `yoke new <dir>` refuses a non-empty directory (greenfield-only — use `yoke retrofit` for
258
+ existing projects), then: creates and `git init`s the directory, writes a minimal scaffold
259
+ (`README.md`, `.gitignore`), runs the full **retrofit** (`--agent=` as usual), initialises the
260
+ **context layer** (with `--idea` seeded into `PROJECT.md` as the north star), writes a commented
261
+ **PRD template** to `.yoke/prd.yaml`, and makes the initial commit — so `--isolate` works from
262
+ iteration 1. With `--idea`, it then drafts the PRD from your idea via an agent (`--runner=`,
263
+ default `claude`) and commits it as a second commit (`docs: draft PRD from idea`).
264
+
265
+ - **Exit codes** `0` success; `1` usage / non-empty dir / draft failure (the scaffold survives —
266
+ retry with `yoke prd draft`); `2` requested draft agent unavailable.
267
+
268
+ **`yoke prd draft [dir] --idea="..."`** turns an idea into 5–12 small, independently shippable
269
+ stories with testable behavioral acceptance criteria (greenfield STORY-1 scaffolds the project
270
+ skeleton + test suite and wires `verify.command`). An existing PRD with stories is never
271
+ overwritten without `--force`; the untouched template doesn't trigger the guard. Runs through
272
+ the same idle-timeout watchdog as the loop (`--timeout`).
273
+
274
+ **`yoke prd check [dir]`** is the chainable pre-loop lint gate: schema validation plus
275
+ duplicate-id, empty-acceptance, and zero-stories checks. Exits `0` with
276
+ `✓ PRD valid N stories, M pass`, `1` on any violation. The `authoring-prd` canon skill
277
+ teaches interactive sessions the same story-slicing discipline.
278
+
279
+ ## 🤖 The autonomous loop
280
+
281
+ Opt-in and off by default. Each iteration starts a **fresh agent** and passes through hard gates before anything is committed:
282
+
283
+ ```mermaid
284
+ flowchart LR
285
+ A[pick next PRD story] --> B{clean worktree?}
286
+ B -- no --> X[blocked]
287
+ B -- yes --> C{acceptance<br/>criteria?}
288
+ C -- no --> X
289
+ C -- yes --> D[agent implements<br/>one story]
290
+ D --> E{tests green?}
291
+ E -- no --> X
292
+ E -- yes --> F{reviewer<br/>approves?}
293
+ F -- no --> X
294
+ F -- yes --> G[commit + mark passes:true<br/>+ proof in .yoke/proof/]
295
+ G --> A
296
+ ```
297
+
298
+ ```bash
299
+ yoke loop on . # enable (recorded in .yoke/config.yaml)
300
+ yoke loop status . # show state + PRD progress
301
+ yoke loop run . \
302
+ --runner=codex \ # implement with Codex…
303
+ --reviewer=claude \ # …review with Claude (role separation)
304
+ --isolate \ # each story in a throwaway git worktree
305
+ --max=20
306
+ yoke loop off . # disable
307
+ ```
308
+
309
+ **PRD format** (`.yoke/prd.yaml`):
310
+
311
+ ```yaml
312
+ - id: STORY-1
313
+ title: Add a health endpoint
314
+ priority: 1 # lower = higher priority
315
+ acceptance: # Definition of Done (required, else blocked)
316
+ - GET /health returns 200
317
+ passes: false # the loop sets this true only on green tests
318
+ ```
319
+
320
+ The loop stops when every story is `passes: true`. State lives **outside the model context** the PRD file plus git so each iteration is fresh. The PRD is re-read from disk at every story boundary, so new stories appended to `.yoke/prd.yaml` **while the loop is running** are picked up at the next iteration — no restart needed.
321
+
322
+ ### Watching a run
323
+
324
+ Every iteration emits token-free, harness-side feedback (Node console + local files — **zero agent tokens**):
325
+
326
+ - **Live console with progress + ETA**
327
+ `▶ S6 (19/45 · 42%) — implementing… · ~1h44m left (Ø 4m/story)` … `✓ S6 done in 4m28s — 20/45 (44%) · ~1h40m left`.
328
+ The estimate uses the **average duration of stories completed in this run** (current
329
+ velocity); before the first story lands it falls back to the recorded history of previous
330
+ runs (`.yoke/story-durations.json`, last 50 stories, gitignored). No data yet no estimate,
331
+ never a made-up one.
332
+ - **`.yoke/loop-status.json`** the current state (now including `percent` and an `eta`
333
+ block); read it any time with `yoke loop status`:
334
+ ```
335
+ Loop: RUNNING on S6 "Weekly digest"
336
+ implementing · iteration 20 · 19/45 (42%) · updated 30s ago
337
+ ~1h44m remaining (Ø 4m/story)
338
+ ```
339
+ - **`.yoke/loop.log`**an append-only timeline of every phase transition.
340
+ - **`--json`** machine mode for supervisors: every status write is *also* emitted as one
341
+ NDJSON line on stdout (`{"type":"status","state":"running","phase":"verifying",…}` the
342
+ same shape as `loop-status.json`), the human narrative moves off stdout (the final summary
343
+ goes to stderr), and a consumer can follow the stream line by line instead of polling the file.
344
+ With a **claude** runner, json mode also switches the agent to `--output-format stream-json`
345
+ and accounts its usage: statuses (file + stream) carry a cumulative
346
+ `tokens: { inputTokens, outputTokens, model? }` field for the whole run `model` is the
347
+ last model id seen on the stream (e.g. `claude-opus-4-6-20260501`), omitted if the CLI
348
+ never reported one.
349
+
350
+ ### Pausing a run
351
+
352
+ Drop a **`.yoke/loop.pause`** file (contents irrelevant) while the loop is running and it
353
+ stops at the **next story boundary** — the running story still finishes, verifies, and
354
+ commits; no story is ever cut off mid-flight. The loop consumes the pause file, writes
355
+ `state: "paused"` to `loop-status.json` (log label `paused`), releases the lock, and exits
356
+ with code `3`. Resume by simply running `yoke loop run` again.
357
+
358
+ A per-iteration **idle timeout** guards against a genuinely hung agent: if the agent produces
359
+ **no output at all** for `--timeout` minutes (default 20; `0` disables), the loop kills it
360
+ (SIGTERM→SIGKILL) and marks the story blocked. A slow-but-working agent that keeps streaming
361
+ output is **never** killed the output stream *is* the liveness signal. Set a project default
362
+ with `loop.timeoutMinutes` in `.yoke/config.yaml`.
363
+
364
+ ### Ambiguous stories: questions belong in planning
365
+
366
+ A loop run has nobody to ask, so the runner prompt always forbids questions. What the agent
367
+ does when an acceptance criterion is genuinely ambiguous is configurable:
368
+
369
+ - **Default (`resolve`) — never stop:** the agent picks the interpretation most consistent
370
+ with the other criteria and the existing code, states it in its final message, and the loop
371
+ keeps going.
372
+ - **Strict (`abort`):** the agent must not guess — it writes its open question(s) to
373
+ `.yoke/ambiguity.md` and stops. The loop consumes that file, skips verify (an unimplemented
374
+ story would otherwise sail through on pre-existing green tests), and blocks with the
375
+ question in the reason, e.g.
376
+ `story S6 stopped: ambiguous acceptance criteria Which auth provider should S6 use?`
377
+ Answer by sharpening the story's acceptance criteria, then re-run.
378
+
379
+ Enable strict mode per run with `yoke loop run . --on-ambiguity=abort` or per project with
380
+ `loop.onAmbiguity: abort` in `.yoke/config.yaml`. Either way, the cheapest fix is upstream:
381
+ put every clarifying question into the PRD **before** the loop starts (`yoke prd draft`
382
+ criteria must be testable and decision-free).
383
+
384
+ The loop trusts **verify**, not the agent's exit code: a story whose tests are green is
385
+ committed even if the agent process exited non-zero (a common Windows `.cmd`-wrapper ghost).
386
+ A failing verify is retried up to `verify.retries` times (default 1) so a transient flake
387
+ self-heals while a real failure still blocks.
388
+
389
+ `.yoke/loop-status.json`, `.yoke/loop.log`, `.yoke/loop.lock`, `.yoke/story-durations.json`,
390
+ and `.yoke/ambiguity.md` are runtime artifacts; `yoke retrofit` gitignores them (along with
391
+ `.yoke/worktrees/`, `.yoke/backup/`, and `.yoke/proof/`) so they never trip the clean-tree gate.
392
+
393
+ ### Single-flight guard + cleanup
394
+
395
+ Two concurrent `yoke loop run`s would race on the PRD and status files, so the loop takes a
396
+ **lock** (`.yoke/loop.lock`) for the duration of a run. A second invocation exits `2` with
397
+ `Another loop is already running here (pid …). If that is wrong, run: yoke loop cleanup`. A lock
398
+ whose holder process is dead is taken over automatically (with a warning).
399
+
400
+ **`yoke loop cleanup [dir]`** removes what a crashed loop leaves behind: every worktree under
401
+ `.yoke/worktrees/` (via `git worktree remove --force` + `prune` user-created worktrees are
402
+ never touched) and a **stale** lock file. A live lock is reported and left alone. Exits `0`
403
+ when everything cleaned, `1` if any removal failed.
404
+
405
+ ## 🔍 Cross-model review (`yoke review`)
406
+
407
+ Outside the loop, `yoke review` has a **second** model review your current diff as a
408
+ pass/fail gate the interactive counterpart to the loop's `--review`/`--reviewer`.
409
+
410
+ ```bash
411
+ yoke review . # review the uncommitted working tree
412
+ yoke review . --base=main # review the range main..HEAD instead
413
+ yoke review . --reviewer=codex # force a specific reviewer
414
+ yoke review . --focus="the auth layer" # steer what it scrutinises
415
+ ```
416
+
417
+ - **Reviewer resolution** — picks the first available of **codex gemini claude**,
418
+ preferring a model *other* than the one you drive so the review is genuinely cross-model.
419
+ On a Claude-only machine it degrades to a self-review (and says so).
420
+ - **Scope** — the uncommitted working tree by default, or a commit range with `--base=<ref>`.
421
+ - **Exit-code gate** — exits `0` when the reviewer approves, `1` when it finds a blocking
422
+ issue, `2` when no (or an unavailable) reviewer CLI is found. Chain it: `... && yoke review`,
423
+ or wire it into a pre-push hook.
424
+ - Runs through the same idle-timeout watchdog as the loop (`--timeout`, default 20 min).
425
+
426
+ ## 🎨 Visual & design verification — done, with a photo
427
+
428
+ Unit tests don't catch a blank page, an unwired route, or generic AI-slop design. Yoke adds three things:
429
+
430
+ - **`yoke design-scan [dir]`** a static scanner for the visual *tells* of AI-generated UIs
431
+ (AI-purple gradients, gradient hero text, neon glow, emoji-as-icons, gradient overload). It
432
+ scores findings and **exits non-zero over budget** (`--max`, default 4; `--report` to list only),
433
+ so it drops straight into your verify pipeline.
434
+ - **`yoke flow-smoke [dir]`** — a built-in browser gate with **proof artifacts** (below).
435
+ - **`unslop-ui` + `visual-verification` skills** — the design rubric, plus how to compose a verify
436
+ pipeline (`types units design-scan → flow-smoke`).
437
+
438
+ Because the loop trusts **verify as the source of truth**, widening `verify.command` to include the
439
+ scanner and the flow-smoke makes visual quality a real gatenot an afterthought.
440
+
441
+ *Tell set informed by the MIT-licensed [vibecoded-design-tells](https://github.com/JCarterJohnson/vibecoded-design-tells) research.*
442
+
443
+ ### `yoke flow-smoke [dir] [--url=<baseUrl>] [--label=<name>]`
444
+
445
+ Configure your key user flows once in `.yoke/config.yaml`:
446
+
447
+ ```yaml
448
+ smoke:
449
+ baseUrl: http://localhost:3000
450
+ flows:
451
+ - name: home
452
+ path: /
453
+ landmark: "main h1" # optional CSS selector to wait for
454
+ - name: login
455
+ path: /login
456
+ ```
457
+
458
+ For every flow, `yoke flow-smoke` loads the route against the running dev server, waits for the
459
+ landmark, and fails on a non-OK response or **any console/page error**. The proof contract:
460
+
461
+ - **Screenshots always**every flow (pass *or* fail) saves `.yoke/proof/<label>/<flow>.png`;
462
+ the failure screenshot *is* the evidence.
463
+ - **Video only on failure** — each flow is recorded, but the clip is kept only when the flow
464
+ goes red (`<flow>.webm`); green runs delete it.
465
+ - **Labelled per story** — inside the loop, verify runs with `YOKE_STORY=<story-id>`, so proofs
466
+ land in `.yoke/proof/<story-id>/` automatically. Standalone runs use `latest`, or pass
467
+ `--label=`. The label dir is wiped per run — evidence is always from the latest run.
468
+ - **Exit codes** — `0` all flows green (chain it: `... && yoke design-scan . && yoke flow-smoke .`),
469
+ `1` any flow failed, `2` not runnable (no `smoke:` config, or Playwright missing).
470
+ - **Playwright comes from the *target project*, never Yoke**
471
+ `npm i -D playwright && npx playwright install chromium` there. Start the dev server before
472
+ verify (e.g. via `start-server-and-test`); `--url=` overrides `baseUrl`.
473
+
474
+ `.yoke/proof/` is gitignored by the retrofit proofs are runtime artifacts and never break the
475
+ loop's clean-tree gate.
476
+
477
+ ## 🧠 Context layer (`.yoke/context/`)
478
+
479
+ Yoke keeps durable, cross-session context so a fresh-context agent is never blind:
480
+
481
+ - `PROJECT.md` the north star (goal, constraints, non-goals, success criteria).
482
+ - `DECISIONS.md` — an append-only ledger. The loop adds an entry per completed story; you and agents add the *why*.
483
+ - `KNOWLEDGE.md` — reusable gotchas and conventions.
484
+
485
+ `yoke retrofit` scaffolds these files (non-destructively — your edits are never overwritten).
486
+ The loop reads them into every agent + reviewer prompt and logs decisions back on each story's
487
+ commit. Manage them directly with `yoke context init` and `yoke context status`. The
488
+ `maintaining-context` skill teaches agents to honour the same files during interactive work.
489
+
490
+ > Commit `.yoke/context/` to git. The `--isolate` loop runs each iteration in a worktree
491
+ > checked out from HEAD, so it only sees committed context.
492
+
493
+ ## 🛡️ Safety model
494
+
495
+ Yoke's guardrails are **mechanical, not advisory** — the loop blocks on a dirty worktree, missing acceptance criteria, red tests, or a reviewer rejection, and **none of them rely on the agent choosing to behave**.
496
+
497
+ - **Commit integrity** — a story is never recorded `passes: true` without a corresponding commit; a failed commit reverts the PRD.
498
+ - **Role separation** — the implementer never reviews its own work; `--reviewer` can even be a different agent.
499
+ - **Isolation** — with `--isolate`, failed or partial work is discarded with the worktree and never reaches your main tree.
500
+ - **Non-destructive retrofit** — existing files are backed up before any change; settings are merged, not replaced.
501
+ - **Independent verification** — "done" means *your test command exits 0*, not "the agent said so".
502
+ - **Single-flight** — a lock prevents two loops from racing the same repo; `yoke loop cleanup` recovers after crashes.
503
+
504
+ ## 🧠 Choose your code-graph
505
+
506
+ `yoke retrofit --code-graph=graphify|serena` (default `graphify`, remembered per project). The `yoke-retrofit` skill asks and recommends based on the project.
507
+
508
+ | | **graphify** | **Serena** |
509
+ |---|---|---|
510
+ | Engine | tree-sitter AST + graph | real language servers (LSP) |
511
+ | Strength | fast, multimodal (code + PDFs + images) | symbol-exact cross-file refactoring |
512
+ | Token efficiency | ~70× reduction on large mixed repos | standard, no index to go stale |
513
+ | Best for | rapid exploration / migration / onboarding | systematic refactoring in typed codebases |
514
+ | Caveat | heuristic edges; static index can go stale | one language server per language |
515
+
516
+ ## 🪙 Token efficiency
517
+
518
+ Yoke attacks tokens on two complementary surfaces:
519
+
520
+ - **rtk** compresses noisy command/tool output before it enters context (wired as a hook/instruction per agent).
521
+ - The **`minimal-code`** skill installs a YAGNI / "lazy senior dev" ladder so agents write the least code that solves the task — fewer output tokens, smaller review surface. *(Adapted from the MIT-licensed [ponytail](https://github.com/DietrichGebert/ponytail) ruleset.)*
522
+
523
+ ## 🧩 Optional companions
524
+
525
+ Two external tools pair well with Yoke and are documented (not bundled) in `canon/tools/` — each has its own installer and update cadence, so Yoke wires the boundary instead of vendoring a copy:
526
+
527
+ - **[claude-mem](https://github.com/thedotmack/claude-mem)** — persistent cross-session memory for interactive work. Deliberate boundary: the autonomous loop keeps its memory **explicit and versioned** (`context/*.md` + PRD, fresh context per story), so claude-mem's automatic injection stays out of loop runs.
528
+ - **[ui-ux-pro-max](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill)** — data-driven design intelligence (styles, palettes, industry rules) for the *generation* side. Yoke's `unslop-ui`, `design-scan`, and `visual-verification` remain the *verification* side: generate with pro-max, gate with Yoke.
529
+
530
+ ## 🌱 Why & how it was built
531
+
532
+ **The problem.** Coding agents are powerful, but each speaks its own dialect — Claude has skills and hooks, Codex reads `AGENTS.md` and a TOML config, Gemini wants commands and a settings file. Keeping the same skills, safety policy, and tool wiring consistent across all of them means copy-paste drift and three things to maintain. Yoke exists to keep **one** source of truth, generate the right native artifacts for each agent, and let that harness run **autonomously and safely** when you want to hand it a spec and walk away.
533
+
534
+ **The inspiration.** Yoke is a synthesis of ideas already proven across the ecosystem: composable-skills methodology ([superpowers](https://github.com/obra/superpowers), [gstack](https://github.com/garrytan/gstack)); the portable [AGENTS.md](https://agents.md/) standard; the *"one source-of-truth → idiomatic per-harness artifacts"* generation pattern ([wshobson/agents](https://github.com/wshobson/agents)); spec-driven autonomous orchestration (GSD); mechanical safety gates and role separation (safe-agentic-workflow); and the **Ralph loop** (Geoff Huntley) — keep handing a *fresh* agent the next task until the spec is done. Token efficiency comes from [rtk](https://github.com/rtk-ai/rtk) and the write-less-code idea behind [ponytail](https://github.com/DietrichGebert/ponytail).
535
+
536
+ **How it was built.** Yoke was built the way it's meant to be *used* — agent-driven, incremental, and test-first. The stack was chosen by **researching alternatives first** (which is how `jcodemunch` was dropped for its license and Serena was added as an option). Then every component shipped one small piece at a time through a disciplined loop: **brainstorm → spec → plan → TDD implementation → an independent two-stage review** (does it match the spec? is it well-built?) **→ merge**. Those reviews caught real bugs before they shipped — a Windows `.cmd` spawn failure, a commit-integrity hole, a path-traversal that could delete project data, a resolution bug that broke the CLI's default invocation, a TOML-escaping bug. Yoke was even **dogfooded on its own repo**, which surfaced (and fixed) a genuine Windows bug. Every spec and plan lives in [`docs/superpowers/`](docs/superpowers/).
537
+
538
+ ## 🗂️ Project layout
539
+
540
+ ```text
541
+ canon/ # the source of truth — harness-agnostic
542
+ AGENTS.md skills/ policy/ loop/ tools/ manifest.yaml
543
+ src/
544
+ canon/ # manifest schema + validator (yoke validate)
545
+ retrofit/ # detect · plan · apply · planners (claude/codex/gemini) · tools
546
+ loop/ # prd · gates · runner · verify · git/worktree · loop · run-command · lock · cleanup
547
+ new/ # yoke new — greenfield bootstrap
548
+ prd/ # yoke prd draft|check — idea → stories + lint gate
549
+ review/ # yoke review — cross-model diff gate
550
+ smoke/ # yoke flow-smoke — browser gate with screenshot/video proofs
551
+ scan/ # yoke design-scan — AI-slop design gate
552
+ context/ # the durable context layer
553
+ docs/superpowers/ # the spec and every component's implementation plan
554
+ ```
555
+
556
+ ## 🗺️ Roadmap
557
+
558
+ - **npm publish** (`@hecer/yoke`) — one-liner `npx` install (package prepared).
559
+ - **Security gate** — a `cso`-style audit skill + `yoke audit` (deps, secrets, diff surface).
560
+ - **Token-budget gate** — per-story budget with abort; cost transparency for loop runs.
561
+ - **Multi-reviewer quorum** — N independent reviewers with distinct lenses (correctness / security / acceptance).
562
+ - **Merge queue** — re-test against the latest main before integrating, for parallel/multi-agent loops.
563
+ - **More agents** — the canon→retrofit pattern generalises; OpenCode and Copilot CLI are natural next targets.
564
+
565
+ ## 🧪 Development
566
+
567
+ ```bash
568
+ npm test # vitest (322 tests)
569
+ npm run build # tsc, no emit errors
570
+ npm run yoke -- validate canon
571
+ ```
572
+
573
+ ## 🙏 Credits & inspiration
574
+
575
+ Yoke stands on the shoulders of a great ecosystem: methodology ideas from [superpowers](https://github.com/obra/superpowers) and [gstack](https://github.com/garrytan/gstack); the [AGENTS.md](https://agents.md/) standard; the generator pattern from [wshobson/agents](https://github.com/wshobson/agents); the Ralph autonomous-loop pattern; safety-gate thinking from safe-agentic-workflow; and the wired tools [rtk](https://github.com/rtk-ai/rtk), [graphify](https://github.com/safishamsi/graphify), [Serena](https://github.com/oraios/serena), and [Playwright MCP](https://github.com/microsoft/playwright-mcp). The `minimal-code` skill adapts the MIT-licensed [ponytail](https://github.com/DietrichGebert/ponytail) ruleset.
576
+
577
+ ## 📄 License
578
+
579
+ MIT — see [`LICENSE`](LICENSE).
580
+
581
+ <div align="center">
582
+ <sub>Built with a disciplined loop: brainstorm → spec → plan → TDD → two-stage review → merge — and reviewed by a second model, because we don't trust "done" either.</sub>
583
+ </div>