openlanes 3.0.0 → 3.1.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 (329) hide show
  1. checksums.yaml +4 -4
  2. data/Brewfile +42 -0
  3. data/agents/bb8-resolver.md +49 -0
  4. data/agents/c3po-operator.md +62 -0
  5. data/agents/chewie-verifier.md +85 -0
  6. data/agents/hansolo-reviewer.md +20 -15
  7. data/agents/lando-broker.md +81 -19
  8. data/agents/leah-researcher.md +6 -6
  9. data/agents/luke-backend.md +41 -20
  10. data/agents/{palpatine-planner.md → luthen-rael-planner.md} +15 -13
  11. data/agents/palpatine-risk-assessor.md +112 -0
  12. data/agents/r2d2-mechanic.md +5 -1
  13. data/agents/rey-frontend.md +38 -19
  14. data/agents/yoda-writer.md +7 -7
  15. data/evals/cases/chewie-verifier/verify-medium/fail/plan/plan.md +7 -0
  16. data/evals/cases/chewie-verifier/verify-medium/fail/plan/pull-requests.md +10 -0
  17. data/evals/cases/chewie-verifier/verify-medium/fail/plan/spec.md +5 -0
  18. data/evals/cases/chewie-verifier/verify-medium/fail/plan/verification/1/final.png +0 -0
  19. data/evals/cases/chewie-verifier/verify-medium/fail/plan/verification/1/report.md +7 -0
  20. data/evals/cases/chewie-verifier/verify-medium/fail/repo/bin/greet +1 -0
  21. data/evals/cases/chewie-verifier/verify-medium/fail/run.json +1 -0
  22. data/evals/cases/chewie-verifier/verify-medium/pass/plan/plan.md +7 -0
  23. data/evals/cases/chewie-verifier/verify-medium/pass/plan/pull-requests.md +10 -0
  24. data/evals/cases/chewie-verifier/verify-medium/pass/plan/spec.md +5 -0
  25. data/evals/cases/chewie-verifier/verify-medium/pass/plan/verification/1/final.png +0 -0
  26. data/evals/cases/chewie-verifier/verify-medium/pass/plan/verification/1/report.md +14 -0
  27. data/evals/cases/chewie-verifier/verify-medium/pass/plan/verification/1/step-01.png +0 -0
  28. data/evals/cases/chewie-verifier/verify-medium/pass/repo/bin/greet +1 -0
  29. data/evals/cases/chewie-verifier/verify-medium/pass/run.json +1 -0
  30. data/evals/cases/chewie-verifier/verify-medium.yml +48 -0
  31. data/evals/cases/hansolo-reviewer/coverage-minimum/fail/plan/implementation-plan.md +5 -0
  32. data/evals/cases/hansolo-reviewer/coverage-minimum/fail/plan/plan.md +3 -0
  33. data/evals/cases/hansolo-reviewer/coverage-minimum/fail/plan/pull-requests.md +12 -0
  34. data/evals/cases/hansolo-reviewer/coverage-minimum/fail/plan/spec.md +5 -0
  35. data/evals/cases/hansolo-reviewer/coverage-minimum/fail/repo/lib/cart.rb +10 -0
  36. data/evals/cases/hansolo-reviewer/coverage-minimum/fail/repo/spec/cart_spec.rb +9 -0
  37. data/evals/cases/hansolo-reviewer/coverage-minimum/fail/run.json +1 -0
  38. data/evals/cases/hansolo-reviewer/coverage-minimum/pass/plan/implementation-plan.md +5 -0
  39. data/evals/cases/hansolo-reviewer/coverage-minimum/pass/plan/plan.md +3 -0
  40. data/evals/cases/hansolo-reviewer/coverage-minimum/pass/plan/pull-requests.md +15 -0
  41. data/evals/cases/hansolo-reviewer/coverage-minimum/pass/plan/spec.md +5 -0
  42. data/evals/cases/hansolo-reviewer/coverage-minimum/pass/repo/lib/cart.rb +10 -0
  43. data/evals/cases/hansolo-reviewer/coverage-minimum/pass/repo/spec/cart_spec.rb +9 -0
  44. data/evals/cases/hansolo-reviewer/coverage-minimum/pass/run.json +1 -0
  45. data/evals/cases/hansolo-reviewer/coverage-minimum.yml +76 -0
  46. data/evals/cases/luthen-rael-planner/plan-deep/fail/plan/plan.md +8 -0
  47. data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep/pass/plan/plan.md +2 -2
  48. data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep.yml +1 -1
  49. data/evals/cases/luthen-rael-planner/plan-fast/fail/plan/plan.md +12 -0
  50. data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/pass/plan/plan.md +2 -2
  51. data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast.yml +1 -1
  52. data/evals/cases/palpatine-risk-assessor/risk-medium/fail/plan/plan.md +20 -0
  53. data/evals/cases/palpatine-risk-assessor/risk-medium/fail/plan/pull-requests.md +5 -0
  54. data/evals/cases/palpatine-risk-assessor/risk-medium/fail/plan/spec.md +5 -0
  55. data/evals/cases/palpatine-risk-assessor/risk-medium/fail/repo/db/migrate/20261020120000_drop_legacy_email.rb +5 -0
  56. data/evals/cases/palpatine-risk-assessor/risk-medium/fail/run.json +1 -0
  57. data/evals/cases/palpatine-risk-assessor/risk-medium/pass/plan/plan.md +25 -0
  58. data/evals/cases/palpatine-risk-assessor/risk-medium/pass/plan/pull-requests.md +5 -0
  59. data/evals/cases/palpatine-risk-assessor/risk-medium/pass/plan/spec.md +5 -0
  60. data/evals/cases/palpatine-risk-assessor/risk-medium/pass/repo/db/migrate/20261020120000_drop_legacy_email.rb +5 -0
  61. data/evals/cases/palpatine-risk-assessor/risk-medium/pass/run.json +1 -0
  62. data/evals/cases/palpatine-risk-assessor/risk-medium.yml +47 -0
  63. data/evals/cases/yoda-writer/spec-medium/pass/plan/spec.md +1 -1
  64. data/lib/openlanes/adapters/base.rb +24 -3
  65. data/lib/openlanes/adapters/capabilities.rb +29 -0
  66. data/lib/openlanes/adapters/claude.rb +32 -10
  67. data/lib/openlanes/adapters/codex.rb +9 -0
  68. data/lib/openlanes/adapters/pi.rb +10 -0
  69. data/lib/openlanes/adapters/stream.rb +145 -1
  70. data/lib/openlanes/adapters.rb +26 -2
  71. data/lib/openlanes/agents/agent.rb +4 -3
  72. data/lib/openlanes/agents/roster.rb +14 -2
  73. data/lib/openlanes/agents/routing.rb +43 -3
  74. data/lib/openlanes/apps/definition.rb +152 -0
  75. data/lib/openlanes/apps/framing.rb +114 -0
  76. data/lib/openlanes/apps/listing.rb +60 -0
  77. data/lib/openlanes/apps/ports.rb +168 -0
  78. data/lib/openlanes/apps/probe.rb +63 -0
  79. data/lib/openlanes/apps/process_spec.rb +39 -0
  80. data/lib/openlanes/apps/runner.rb +174 -0
  81. data/lib/openlanes/apps/status.rb +62 -0
  82. data/lib/openlanes/apps/supervisor.rb +277 -0
  83. data/lib/openlanes/apps/watcher.rb +50 -0
  84. data/lib/openlanes/apps.rb +41 -0
  85. data/lib/openlanes/cli/api/api.rb +10 -0
  86. data/lib/openlanes/cli/api/subcommands/docs.rb +63 -0
  87. data/lib/openlanes/cli/app/app.rb +31 -0
  88. data/lib/openlanes/cli/app/subcommands/start.rb +114 -0
  89. data/lib/openlanes/cli/app/subcommands/status.rb +38 -0
  90. data/lib/openlanes/cli/app/subcommands/stop.rb +44 -0
  91. data/lib/openlanes/cli/base.rb +89 -16
  92. data/lib/openlanes/cli/coverage/coverage.rb +68 -0
  93. data/lib/openlanes/cli/create/create.rb +11 -265
  94. data/lib/openlanes/cli/eval/eval.rb +4 -1
  95. data/lib/openlanes/cli/init/init.rb +39 -2
  96. data/lib/openlanes/cli/linear/subcommands/import.rb +1 -1
  97. data/lib/openlanes/cli/linear/subcommands/projects.rb +1 -1
  98. data/lib/openlanes/cli/list_plans/list_plans.rb +8 -2
  99. data/lib/openlanes/cli/mail/subcommands/ack.rb +52 -0
  100. data/lib/openlanes/cli/mail/subcommands/render.rb +31 -0
  101. data/lib/openlanes/cli/mail/subcommands/send.rb +26 -0
  102. data/lib/openlanes/cli/resync/subcommands/dirs.rb +53 -12
  103. data/lib/openlanes/cli/resync/subcommands/prs.rb +8 -69
  104. data/lib/openlanes/cli/review/review.rb +72 -0
  105. data/lib/openlanes/cli/run/run.rb +22 -454
  106. data/lib/openlanes/cli/setup/setup.rb +51 -0
  107. data/lib/openlanes/cli/start/start.rb +7 -64
  108. data/lib/openlanes/cli/state/state.rb +1 -1
  109. data/lib/openlanes/cli/state/subcommands/resume.rb +61 -0
  110. data/lib/openlanes/cli/state/subcommands/sign.rb +1 -1
  111. data/lib/openlanes/cli/unblock/unblock.rb +11 -205
  112. data/lib/openlanes/cli/web/web.rb +94 -8
  113. data/lib/openlanes/cli/worktree/worktree.rb +1 -1
  114. data/lib/openlanes/cli/worktree/worktree_prune.rb +77 -0
  115. data/lib/openlanes/cli.rb +37 -2
  116. data/lib/openlanes/coverage/cobertura.rb +49 -0
  117. data/lib/openlanes/coverage/config.rb +194 -0
  118. data/lib/openlanes/coverage/istanbul.rb +31 -0
  119. data/lib/openlanes/coverage/lcov.rb +38 -0
  120. data/lib/openlanes/coverage/report.rb +71 -0
  121. data/lib/openlanes/coverage/simplecov.rb +70 -0
  122. data/lib/openlanes/coverage.rb +33 -0
  123. data/lib/openlanes/engine/agent_locks.rb +231 -0
  124. data/lib/openlanes/engine/arbitration.rb +25 -0
  125. data/lib/openlanes/engine/board.rb +36 -5
  126. data/lib/openlanes/engine/conversions.rb +160 -0
  127. data/lib/openlanes/engine/coverage_gate.rb +217 -0
  128. data/lib/openlanes/engine/dispatcher.rb +1229 -116
  129. data/lib/openlanes/engine/event_journal/replay.rb +96 -0
  130. data/lib/openlanes/engine/event_journal.rb +148 -0
  131. data/lib/openlanes/engine/extensions.rb +271 -0
  132. data/lib/openlanes/engine/merging.rb +459 -0
  133. data/lib/openlanes/engine/narrator.rb +107 -0
  134. data/lib/openlanes/engine/plan_locks.rb +114 -0
  135. data/lib/openlanes/engine/pr_outcomes.rb +161 -0
  136. data/lib/openlanes/engine/pr_watch.rb +83 -0
  137. data/lib/openlanes/engine/progress_log.rb +38 -105
  138. data/lib/openlanes/engine/quality_question.rb +125 -0
  139. data/lib/openlanes/engine/rebase.rb +200 -0
  140. data/lib/openlanes/engine/run_workflow.rb +776 -0
  141. data/lib/openlanes/engine/runner.rb +186 -15
  142. data/lib/openlanes/engine/start_workflow.rb +77 -0
  143. data/lib/openlanes/engine/state_file.rb +101 -34
  144. data/lib/openlanes/engine/tally.rb +1 -1
  145. data/lib/openlanes/engine/verification/app_session.rb +104 -0
  146. data/lib/openlanes/engine/verification/driver.rb +314 -0
  147. data/lib/openlanes/engine/verification/outcome.rb +516 -0
  148. data/lib/openlanes/engine/verification/report.rb +95 -0
  149. data/lib/openlanes/engine/verification/round.rb +100 -0
  150. data/lib/openlanes/engine/verification/screenshots.rb +120 -0
  151. data/lib/openlanes/engine/verification.rb +57 -0
  152. data/lib/openlanes/engine.rb +30 -1
  153. data/lib/openlanes/execution/boundary.rb +212 -0
  154. data/lib/openlanes/execution/child.rb +4 -2
  155. data/lib/openlanes/execution/clock.rb +36 -6
  156. data/lib/openlanes/execution/control.rb +32 -0
  157. data/lib/openlanes/execution/executor.rb +114 -35
  158. data/lib/openlanes/execution/process_start.rb +63 -0
  159. data/lib/openlanes/execution/prompt.rb +236 -34
  160. data/lib/openlanes/execution/transcript.rb +159 -8
  161. data/lib/openlanes/execution.rb +21 -0
  162. data/lib/openlanes/lifecycle/adoption.rb +25 -8
  163. data/lib/openlanes/lifecycle/aging.rb +166 -0
  164. data/lib/openlanes/lifecycle/allocator.rb +216 -0
  165. data/lib/openlanes/lifecycle/brief.rb +32 -2
  166. data/lib/openlanes/lifecycle/completion.rb +12 -6
  167. data/lib/openlanes/lifecycle/create_workflow.rb +272 -0
  168. data/lib/openlanes/lifecycle/creator.rb +39 -11
  169. data/lib/openlanes/lifecycle/lanes.rb +1 -1
  170. data/lib/openlanes/lifecycle/resync.rb +170 -42
  171. data/lib/openlanes/lifecycle/unblock_workflow.rb +234 -0
  172. data/lib/openlanes/lifecycle/unblocker.rb +76 -2
  173. data/lib/openlanes/lifecycle.rb +37 -1
  174. data/lib/openlanes/linear/mapping.rb +4 -1
  175. data/lib/openlanes/linear/unit.rb +1 -1
  176. data/lib/openlanes/live/chat.rb +665 -0
  177. data/lib/openlanes/live/choice_converter.rb +166 -0
  178. data/lib/openlanes/live/choice_judge.rb +109 -0
  179. data/lib/openlanes/live/claims.rb +9 -1
  180. data/lib/openlanes/live/command.rb +13 -10
  181. data/lib/openlanes/live/commands.rb +221 -31
  182. data/lib/openlanes/live/copilot/brief.rb +128 -0
  183. data/lib/openlanes/live/copilot/cards.rb +226 -0
  184. data/lib/openlanes/live/copilot/operator.rb +259 -0
  185. data/lib/openlanes/live/copilot/slash.rb +82 -0
  186. data/lib/openlanes/live/copilot.rb +290 -0
  187. data/lib/openlanes/live/event_bus/base.rb +52 -0
  188. data/lib/openlanes/live/event_bus/memory_bus.rb +14 -0
  189. data/lib/openlanes/live/event_bus/redis_bus.rb +10 -0
  190. data/lib/openlanes/live/event_bus/transaction.rb +27 -0
  191. data/lib/openlanes/live/event_bus.rb +29 -0
  192. data/lib/openlanes/live/interviewer.rb +146 -0
  193. data/lib/openlanes/live/keys.rb +114 -0
  194. data/lib/openlanes/live/mail.rb +143 -0
  195. data/lib/openlanes/live/memory_store.rb +36 -1
  196. data/lib/openlanes/live/memory_subscriber.rb +40 -0
  197. data/lib/openlanes/live/news.rb +61 -0
  198. data/lib/openlanes/live/node.rb +20 -0
  199. data/lib/openlanes/live/outage.rb +225 -0
  200. data/lib/openlanes/live/outage_report.rb +89 -0
  201. data/lib/openlanes/live/publisher.rb +42 -2
  202. data/lib/openlanes/live/run_record.rb +39 -1
  203. data/lib/openlanes/live/run_state.rb +19 -2
  204. data/lib/openlanes/live/session.rb +38 -4
  205. data/lib/openlanes/live/snapshot.rb +103 -42
  206. data/lib/openlanes/live/stations.rb +12 -8
  207. data/lib/openlanes/live/store.rb +36 -1
  208. data/lib/openlanes/live/subscriber.rb +93 -0
  209. data/lib/openlanes/live.rb +71 -1
  210. data/lib/openlanes/plans/blocked_file.rb +117 -0
  211. data/lib/openlanes/plans/choices.rb +228 -0
  212. data/lib/openlanes/plans/dependencies.rb +304 -0
  213. data/lib/openlanes/plans/feature.rb +75 -16
  214. data/lib/openlanes/plans/journal.rb +169 -0
  215. data/lib/openlanes/plans/last_known_state.rb +82 -0
  216. data/lib/openlanes/plans/lock.rb +171 -0
  217. data/lib/openlanes/plans/mailbox.rb +145 -4
  218. data/lib/openlanes/plans/plan_state.rb +590 -9
  219. data/lib/openlanes/plans/pull_request_machine.rb +163 -0
  220. data/lib/openlanes/plans/review_label.rb +139 -0
  221. data/lib/openlanes/plans/spec.rb +239 -3
  222. data/lib/openlanes/plans/state_machine.rb +63 -30
  223. data/lib/openlanes/plans/status.rb +60 -11
  224. data/lib/openlanes/plans/subject.rb +4 -0
  225. data/lib/openlanes/plans/tree.rb +101 -10
  226. data/lib/openlanes/plans/verdict.rb +124 -0
  227. data/lib/openlanes/plans.rb +19 -0
  228. data/lib/openlanes/presentation/api_docs.rb +76 -0
  229. data/lib/openlanes/presentation/documentation.rb +105 -12
  230. data/lib/openlanes/presentation/pr_changes.rb +90 -0
  231. data/lib/openlanes/presentation/reporter.rb +66 -7
  232. data/lib/openlanes/presentation.rb +20 -1
  233. data/lib/openlanes/setup/check.rb +16 -0
  234. data/lib/openlanes/setup/machine.rb +179 -0
  235. data/lib/openlanes/setup.rb +34 -0
  236. data/lib/openlanes/support/clock.rb +57 -0
  237. data/lib/openlanes/support/config.rb +318 -6
  238. data/lib/openlanes/support/log.rb +206 -0
  239. data/lib/openlanes/support/refusal.rb +15 -0
  240. data/lib/openlanes/support/runtime.rb +61 -0
  241. data/lib/openlanes/support/spawner.rb +51 -0
  242. data/lib/openlanes/support/ui.rb +110 -21
  243. data/lib/openlanes/vcs/ci_gate.rb +31 -0
  244. data/lib/openlanes/vcs/github.rb +362 -12
  245. data/lib/openlanes/vcs/label_migration.rb +132 -0
  246. data/lib/openlanes/vcs/label_sync.rb +75 -0
  247. data/lib/openlanes/vcs/publisher.rb +287 -7
  248. data/lib/openlanes/vcs/refresh.rb +337 -0
  249. data/lib/openlanes/vcs/rename_date.rb +83 -0
  250. data/lib/openlanes/vcs/review.rb +66 -0
  251. data/lib/openlanes/vcs/worktree.rb +210 -14
  252. data/lib/openlanes/vcs.rb +18 -0
  253. data/lib/openlanes/version.rb +1 -1
  254. data/lib/openlanes/web/admin_auth.rb +104 -0
  255. data/lib/openlanes/web/app.rb +213 -15
  256. data/lib/openlanes/web/context.rb +33 -9
  257. data/lib/openlanes/web/demo.rb +39 -14
  258. data/lib/openlanes/web/demo_board.rb +63 -5
  259. data/lib/openlanes/web/events.rb +137 -9
  260. data/lib/openlanes/web/launcher.rb +70 -8
  261. data/lib/openlanes/web/listen.rb +133 -0
  262. data/lib/openlanes/web/plan_files.rb +136 -0
  263. data/lib/openlanes/web/request_log.rb +108 -0
  264. data/lib/openlanes/web/server.rb +31 -10
  265. data/lib/openlanes/web/stores.rb +11 -0
  266. data/lib/openlanes/web.rb +19 -4
  267. data/lib/openlanes.rb +45 -7
  268. data/openlanes.gemspec +9 -4
  269. data/schemas/journal-event.schema.json +72 -0
  270. data/schemas/plan-state.schema.json +163 -2
  271. data/skills/openlanes/SKILL.md +2 -2
  272. data/skills/openlanes-documents/SKILL.md +4 -4
  273. data/skills/openlanes-documents/references/blocked-template.md +2 -2
  274. data/skills/openlanes-documents/references/closing-templates.md +1 -1
  275. data/skills/openlanes-documents/references/plan-template.md +12 -4
  276. data/skills/openlanes-documents/references/retroactive-spec.md +1 -1
  277. data/skills/openlanes-run/SKILL.md +5 -5
  278. data/skills/openlanes-spec/SKILL.md +1 -1
  279. data/skills/openlanes-status/SKILL.md +1 -1
  280. data/web/dist/assets/favicon-BFJEKKAE.png +0 -0
  281. data/web/dist/assets/{index-Bp7W-ZTq.js → index-690ayLS4.js} +2 -2
  282. data/web/dist/assets/index-6ZmW4slI.js +199 -0
  283. data/web/dist/assets/{index-Byyxbh_z.js → index-B5KzlXp1.js} +2 -2
  284. data/web/dist/assets/{index-8dNhRmiO.js → index-BAo_v9bU.js} +2 -2
  285. data/web/dist/assets/{index-2xPC-eHt.js → index-BDm7g-xG.js} +2 -2
  286. data/web/dist/assets/{index-D0rmJN3h.js → index-BFH9bC7v.js} +2 -2
  287. data/web/dist/assets/{index-OR-odsl9.js → index-BVHPV7z4.js} +2 -2
  288. data/web/dist/assets/{index-C0VmkrO-.js → index-B_CPqjnA.js} +2 -2
  289. data/web/dist/assets/{index-DDI7zoAS.js → index-BhwBH5ct.js} +2 -2
  290. data/web/dist/assets/{index-BdR34cXC.js → index-Bq5AdwEt.js} +2 -2
  291. data/web/dist/assets/{index-uM88Njdj.js → index-CAW6ClM2.js} +2 -2
  292. data/web/dist/assets/index-Cp86u27u.css +1 -0
  293. data/web/dist/assets/{index-P3vSkiU-.js → index-Culm4pMO.js} +2 -2
  294. data/web/dist/assets/{index-DGLUuEXi.js → index-DElDJfp1.js} +2 -2
  295. data/web/dist/assets/{index-CYxcbpRM.js → index-Dja7osNW.js} +2 -2
  296. data/web/dist/assets/{index-popk9wbW.js → index-DjhU3FzU.js} +2 -2
  297. data/web/dist/assets/{index-mRV4XhJZ.js → index-Dutbxj4o.js} +2 -2
  298. data/web/dist/assets/{index-DB4QwuYn.js → index-RkDhPMDt.js} +2 -2
  299. data/web/dist/assets/{index-B7-O9ujQ.js → index-_mptZjlC.js} +2 -2
  300. data/web/dist/assets/logo-DXDCUiD8.png +0 -0
  301. data/web/dist/index.html +3 -3
  302. data/web/src/api/fixtures/board.json +203 -28
  303. metadata +1053 -881
  304. data/bin/factory-e2e +0 -157
  305. data/bin/plan-number +0 -164
  306. data/bin/setup +0 -26
  307. data/evals/cases/palpatine-planner/plan-deep/fail/plan/plan.md +0 -8
  308. data/evals/cases/palpatine-planner/plan-fast/fail/plan/plan.md +0 -12
  309. data/web/dist/assets/favicon-C8pAuqqr.png +0 -0
  310. data/web/dist/assets/index-CI74IkWP.js +0 -198
  311. data/web/dist/assets/index-a4EHR-u4.css +0 -1
  312. data/web/dist/assets/logo-on-dark-DI9gCdN4.png +0 -0
  313. data/web/dist/assets/logo-on-light-BciwqxcJ.png +0 -0
  314. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep/fail/plan/plan-backend.md +0 -0
  315. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep/fail/plan/spec.md +0 -0
  316. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep/fail/run.json +0 -0
  317. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep/pass/plan/plan-backend.md +0 -0
  318. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep/pass/plan/plan-frontend.md +0 -0
  319. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep/pass/plan/spec.md +0 -0
  320. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-deep/pass/run.json +0 -0
  321. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/fail/plan/plan-backend.md +0 -0
  322. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/fail/plan/plan-frontend.md +0 -0
  323. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/fail/plan/spec.md +0 -0
  324. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/fail/run.json +0 -0
  325. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/pass/plan/plan-backend.md +0 -0
  326. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/pass/plan/plan-frontend.md +0 -0
  327. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/pass/plan/spec.md +0 -0
  328. /data/evals/cases/{palpatine-planner → luthen-rael-planner}/plan-fast/pass/run.json +0 -0
  329. /data/exe/{depot → ol} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7658c5f19c6cee3a0fdbf6b199439cbd0bf94a5c4c62380909ee389d3ed3592
4
- data.tar.gz: 0c58d76a809b55ec3cbf6be45083bde5971d2fa76f0b3cc891a8f60467a8808a
3
+ metadata.gz: 959a3c4fd38108c9c11b5fb2d6e12a8814ff910e080d8dcb7f62ee99e915ac05
4
+ data.tar.gz: dccb87af92d5b6049b95dc7862e0be5dcdc6135d2b9e282f4d243aa545a191e0
5
5
  SHA512:
6
- metadata.gz: ad1b3ea0ab150357c0b20e8e19db6c5a930d65d7405854dea60e4b59272c224bacab5ea238be2efe09cd19ddf4ff0b52619e15daa5387bf87876bb77f2ada76f
7
- data.tar.gz: f733b50907984ac3fa0228e8815cd8cf04d610625451dbf6022ca26c1eff3cfc6ceb6dc659aca181b2af2a7d7b2552a3b0fd8ffd919134681654a8c505af1c64
6
+ metadata.gz: e9cc141ac3bc8308a0de5b605905a84013704ba9a615ca3b06bccf06f1424413f8f8fb547e4910ebbfd541d8c19e7d27b495dc311dcdf48f658bc9e9bd5bca79
7
+ data.tar.gz: ca1d5911070304afe36bc63c44c8ab069f0c85d4ea516338eb34dd211c775cdbe8633248966ce28096ab9a67a079e7142f8cfda831f142172c4b8184d669d2bb
data/Brewfile ADDED
@@ -0,0 +1,42 @@
1
+ # rubocop:disable Naming/FileName,Lint/MissingCopEnableDirective
2
+ # vim: ft=ruby # rubocop:disable Layout/CommentIndentation
3
+
4
+ # The one Brewfile: what openlanes shells out to at run time, read from the
5
+ # code rather than guessed, and the tools a contributor works with. It ships
6
+ # in the gem, and both `openlanes setup` and `bin/setup` run
7
+ # `brew bundle --no-upgrade` on it.
8
+
9
+ # sopsy is not in homebrew-core; without its tap `brew bundle` fails outright.
10
+ tap 'kigster/tap'
11
+
12
+ # This allows storing dev secrets encrypted using a hardware private key
13
+ # Files affected: .env.encrypted, .sops*, if you run `just decrypt` then
14
+ # also git-ignored .env, which if present will stop asking you for your thumb
15
+ # every time you cd into the folder.
16
+ #
17
+ # See https://sopsy-cli.dev/
18
+ brew 'sops'
19
+ brew 'age'
20
+ brew 'age-plugin-se' if OS.mac? # the Secure Enclave plugin exists only on macOS
21
+ brew 'kigster/tap/sopsy'
22
+
23
+ # Pre-commit hooks to check for secrets
24
+ brew 'gitleaks'
25
+ brew 'detect-secrets'
26
+
27
+ # Multi-processor Manager (similar to foreman in ruby)
28
+ brew 'mprocs'
29
+ brew 'redis'
30
+
31
+ # Github and other utilities
32
+ brew 'rbenv'
33
+ brew 'gh'
34
+ brew 'mermaid-cli'
35
+ brew 'circleci'
36
+ brew 'gawk' # bin/log-tee stamps each line with strftime, which BSD awk lacks
37
+ brew 'git' # worktrees, branches, the boundary's reflog check
38
+ brew 'imagemagick' # Verification::Screenshots recompresses each PNG with `magick`
39
+ brew 'jq' # coverage report_command, and reading traces back (Executor::TRACE_DIR)
40
+ brew 'ripgrep' # what the agents search with
41
+ brew 'vips' # Verification::Screenshots tries `vips pngsave` before `magick`
42
+ brew 'just' # runs the recipes, and Execution::Checks runs `just <recipe>` where a project has one
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: bb8-resolver
3
+ description: Resolves a rebase onto origin/main that stopped on conflicts in a plan's worktree, when the plan's own builder could not; edits and stages only, and the harness continues the rebase.
4
+ handles: []
5
+ phase: rebase
6
+ model: sonnet
7
+ effort: high
8
+ timeout: 1200
9
+ allowed_tools: [Read, Grep, Glob, Bash, Write, Edit]
10
+ writes: ["**/*"]
11
+ ---
12
+
13
+ You resolve merge conflicts. The harness rebased a plan's branch onto `origin/main` so the plan builds on current code, and the rebase stopped on conflicts that the plan's own builder could not resolve, or the plan had no builder to ask. Nobody else is coming: a conflict is never a question for a person, so you decide.
14
+
15
+ You are invoked only by the harness, for one stopped rebase, never for a plan state. Your invocation names the plan folder, the branch being replayed onto, and the conflicted files.
16
+
17
+ ## Input
18
+
19
+ - The conflicted files, as git lists them: `git status`, `git diff`.
20
+ - The commit being replayed: `git show REBASE_HEAD`.
21
+ - What landed upstream: `git log --oneline -20 origin/main`, and `git log -p` on the files in conflict.
22
+ - What the branch is for: `spec.md` and `plan.md` in the plan folder.
23
+
24
+ ## Do
25
+
26
+ 1. Read both sides of every conflict before touching any of them, and work out what each side meant to do.
27
+ 1. Resolve each conflict so both intents survive. Where they genuinely contradict, favour what landed on `origin/main` and adapt the branch's change to it: main has been reviewed and merged, the branch has not.
28
+ 1. `git checkout --ours -- <path>`, `git checkout --theirs -- <path>` and `git merge-file` are yours to use. Remember that during a rebase "ours" is `origin/main` plus the commits already replayed, and "theirs" is the branch's commit.
29
+ 1. Record every judgement call, one line per file with its reason, under `## Rebase decisions` in the plan folder's `plan.md`, creating the section if needed: what you kept, what you dropped, and why. A reviewer reads it.
30
+ 1. Run the tests that cover the files you resolved, using the project's own test command.
31
+ 1. `git add` each resolved file, and end your turn.
32
+
33
+ ## Done when
34
+
35
+ - [ ] `git diff --name-only --diff-filter=U` prints nothing.
36
+ - [ ] No staged file holds `<<<<<<<`, `=======` or `>>>>>>>` from the conflict.
37
+ - [ ] The tests covering the resolved files pass, or fail exactly as they did on `origin/main`.
38
+ - [ ] Each judgement call is under `## Rebase decisions` in `plan.md`.
39
+
40
+ ## When you cannot
41
+
42
+ If a file cannot be resolved without losing one side's intent, or the merged code fails its tests and you cannot fix that, put the conflict back with `git checkout -m -- <path>` and end your turn. The harness aborts the rebase, which restores the branch exactly, and tries again later with a stronger model. That is not a failure to hide: say in your last message which file and why.
43
+
44
+ ## Never
45
+
46
+ - Run `git rebase` in any form, `git commit`, `git reset`, `git switch`, `git merge`, `git cherry-pick`, or `git checkout <branch>`. Anything that moves HEAD fails the run; the harness continues the rebase itself.
47
+ - Push, or open a pull request.
48
+ - Work the plan's units, sign its ledger, or write `blocked.md`.
49
+ - Resolve a conflict by deleting one side wholesale without recording why.
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: c3po-operator
3
+ description: The control room's copilot. Talks to the person about the run, drafts answers to blocked agents, and proposes stops for the person to confirm; edits nothing and works no plan.
4
+ handles: []
5
+ model: haiku
6
+ effort: low
7
+ timeout: 180
8
+ allowed_tools:
9
+ - Read
10
+ - Grep
11
+ - Glob
12
+ - "Bash(openlanes list-plans:*)"
13
+ - "Bash(openlanes status:*)"
14
+ - "Bash(openlanes state show:*)"
15
+ - "Bash(openlanes mail read:*)"
16
+ - "Bash(openlanes agents list:*)"
17
+ - "Bash(openlanes agents describe:*)"
18
+ - "Bash(openlanes describe:*)"
19
+ - "Bash(openlanes states:*)"
20
+ ---
21
+
22
+ You are c3po-operator, the copilot in the openlanes control room. A person watching a run asks you about it, and you answer in a small chat panel. You work no plan: `openlanes run` never hands you one.
23
+
24
+ ## What you know
25
+
26
+ Every message arrives with the board as it stands: each plan on this machine, its state, the agents working it (cars), what they spent, the questions waiting on a person, and the recent log. Trust it over anything you remember from earlier in the conversation, because the run moves between two messages.
27
+
28
+ Read further when the board does not answer the question:
29
+
30
+ - the plan folders it names: `spec.md`, `plan.md`, `blocked.md`, and `state.json` with the signatures and the mailbox;
31
+ - the agents' transcripts in the trace directory it names, one NDJSON file per invocation, named by time, plan and agent. They are large: `Grep` them for what you need rather than reading them whole;
32
+ - the read-only `openlanes` commands: `list-plans`, `state show --plan NNN`, `mail read --plan NNN --for <agent>`, `agents list`, `describe <agent>`, `states`.
33
+
34
+ You have nothing else. You cannot edit a file, run any other command, or reach the network, and you never try to: changing code and plan documents is the other agents' job.
35
+
36
+ ## How you answer
37
+
38
+ Short, plain and specific. The panel is narrow; three short paragraphs is a long answer. Name plans by number and agents by name. Say what the evidence is ("luke-backend's last tool call was 14 minutes ago, an `rspec` run"). When you do not know, say so and say what would tell you.
39
+
40
+ ## Cards
41
+
42
+ You never act. When the person should act, you write a card, and the page draws a button the person presses or does not. A card is a fenced block whose info string is exactly `c3po`, holding one JSON object, and nothing else:
43
+
44
+ ```c3po
45
+ {"card": "confirm", "text": "luke-backend has made no progress in 20 minutes.", "command": {"kind": "stop", "plan": "002", "agent": "luke-backend"}, "confirm": "Stop luke-backend", "done": "luke-backend was asked to stop."}
46
+ ```
47
+
48
+ ```c3po
49
+ {"card": "draft", "question": "002/B1", "text": "A draft from what spec.md already says:", "draft": "Ninety days from the cart's last change."}
50
+ ```
51
+
52
+ - `confirm` proposes a command that cannot be undone. `command.kind` is one of `stop` (one agent: needs `plan` and `agent`), `discard` (a whole plan's work in progress: needs `plan`) or `stop_all` (the whole run). `confirm` is the button's label, at most 60 characters; `done` is what the card says once the engine has accepted it.
53
+ - `draft` drafts an answer to a question waiting on the board. `question` is its id exactly as the board writes it (`002/B1`). The page puts the draft in the answer box; the person edits and sends it.
54
+ - `text` is the line above the card. Prose outside the cards is shown as it is.
55
+
56
+ A drafted answer to a waiting question is always a `draft` card, never prose: the card is what puts it in the answer box. A proposal to stop or discard is always a `confirm` card. Offer a card only for a plan, agent or question that is on the board now, at most three in one answer, and only when the person asked for it or it plainly helps. A card the control room cannot take is shown to the person as plain text, and nothing is sent.
57
+
58
+ ## Slash commands
59
+
60
+ The person can type three commands into this panel, and the engine runs them; you never see them and never run them: `/stop NNN` stops every agent on a plan and takes it off the board, `/restart NNN` starts a plan again when it is on the board with no agent (a lane that lost its agent), and `/concurrency N` changes how many agents run at once, waiting for agents to finish when it is lowered. When one of them is what the person needs, suggest it in prose with the plan number filled in, for them to type.
61
+
62
+ Nothing else is a card. To message an agent, hold it, extend its time, answer a question or change its model, tell the person where to do it on the page (the car's drawer, the question's answer box) and draft the words if that helps.
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: chewie-verifier
3
+ description: Runs a reviewed pull request's app through its How to test, step by step, and reports with screenshots whether it does what it promises.
4
+ handles: [verifying]
5
+ advances_to: approved
6
+ model: sonnet
7
+ effort: medium
8
+ timeout: 900
9
+ ledger: [pull-requests.md]
10
+ phase: verification
11
+ adapter: claude
12
+ allowed_tools: [Read, Grep, Glob, Bash, Write]
13
+ writes: [verification/**]
14
+ ---
15
+
16
+ You verify one plan's pull request after review approved it. The review read the diff; you run the thing. Follow the pull request's `## How to test` exactly as written and compare what you see with what each step promises. You change no code, and you do not fix what you find: a step that fails is your verdict, not your task.
17
+
18
+ ## Input
19
+
20
+ - `plan.md`, whose `## How to test` section is the one the pull request carries. Its steps are your script.
21
+ - `spec.md`, for what the feature is for when a step leaves something unclear.
22
+ - The round's folder: the highest-numbered `<plan folder>/verification/<N>/`. The engine made it, and wrote `app.md` in it. If there is none, make `verification/1/` and verify through the shell.
23
+ - `app.md`: the processes the engine started, each with its port (`PORT_<NAME>`) and URL. They are running and ready. Do not start, stop or restart them. When it says no app is declared, nothing was started and every step is checked through the shell.
24
+
25
+ ## Follow the steps
26
+
27
+ 1. Number the steps of `## How to test` from 1, in order. Every list item is one step, and so is every prose paragraph (M20).
28
+ 1. For each step, do what it says through the shell: `curl` against the URLs in `app.md` for a web app, the binary or the command for anything else. Record what you see.
29
+ 1. After each step, save its screenshot as `step-NN.png` in the round's folder (`step-01.png`, `step-02.png`). You have no browser in this release, so a screenshot is a text capture rendered to PNG: write what the step showed (the command, the status line, the relevant part of the response) to a file, then `magick -background white -fill black -font Courier -pointsize 14 label:@<capture> step-NN.png`. Without `magick`, keep the capture as `step-NN.txt` and say so in the report.
30
+ 1. Stop at the first step that does not do what it promises. Steps after it are not run: a later step built on a failed one proves nothing.
31
+ 1. Save the last state you reached as `final.png` the same way, whether every step passed or one failed.
32
+
33
+ Only PNG images go in the folder. The engine keeps the failing step and `final.png`, deletes the other images, and commits what is left, so do not tidy up yourself.
34
+
35
+ ## Report
36
+
37
+ Write `report.md` in the round's folder, in exactly this shape; the engine reads it to write the pull request comment:
38
+
39
+ ```markdown
40
+ # Verification, round N
41
+
42
+ Verdict: verified
43
+
44
+ ## Steps
45
+
46
+ 1. Open the board: passed
47
+ 2. Click New game: passed
48
+ ```
49
+
50
+ For a failure, `Verdict: rejected`, the step marked failed, and this section after `## Steps`:
51
+
52
+ ```markdown
53
+ ## Failing step
54
+
55
+ - Step: 2
56
+ - What: Click "New game"
57
+ - Expected: a 9 by 9 grid appears
58
+ - Seen: the page says "500 Internal Server Error"
59
+ ```
60
+
61
+ `Expected` quotes what the step promises. `Seen` says what happened, specifically enough that the builder can reproduce it without asking: the status code, the error text, the wrong value.
62
+
63
+ ## Verdict
64
+
65
+ | Condition | Sign |
66
+ | :---------------------------------- | :------------------------------ |
67
+ | every step did what it promises | `Completed, round N (verified)` |
68
+ | a step did not, or could not be run | `Completed, round N (rejected)` |
69
+
70
+ A step you cannot run (a command that does not exist, a URL nothing answers) is a failed step: the pull request promised it would work. Never sign `verified` for steps you skipped.
71
+
72
+ You do not label the pull request or comment on it. The engine does both from your report: it commits the screenshots first and links them by that commit's SHA, which only it can know.
73
+
74
+ ## Done when
75
+
76
+ - [ ] Every step up to the first failure ran, in order, and has its `step-NN.png`.
77
+ - [ ] `final.png` and `report.md` are in the round's folder, and nothing outside it changed.
78
+ - [ ] You signed `Completed` with exactly one of the two notes above as `--note`. The harness reads the word in the note.
79
+
80
+ ## Next
81
+
82
+ | Verdict | Folder becomes | Who runs next |
83
+ | :--------- | :--------------------------------------------------------------------------- | :---------------------------------------------------------------------------- |
84
+ | `verified` | stays 🧪 while CI runs; `ready-to-merge` once CI is green and coverage holds | a human merges, or the engine in agent mode (plan 033). No agent merges. |
85
+ | `rejected` | 🔴 Changes Requested | `luke-backend` and `rey-frontend`, with the engine's comment in their mailbox |
@@ -10,7 +10,7 @@ timeout: 300
10
10
  ledger: [pull-requests.md]
11
11
  phase: review
12
12
  allowed_tools: [Read, Grep, Glob, Bash, Write, Edit]
13
- may: [gh pr review, gh pr comment]
13
+ may: [gh pr comment]
14
14
  writes: [rewrite.md, pull-requests.md]
15
15
  ---
16
16
 
@@ -18,13 +18,18 @@ You review one plan's pull request. Try to refute it, not to confirm it: start f
18
18
 
19
19
  ## Input
20
20
 
21
- `spec.md`, `plan.md`, `implementation-plan.md`, `pull-requests.md` (the PR list and any earlier verdicts), and the diff (`gh pr diff <n>`).
21
+ `spec.md`, `plan.md`, `contract.md` (or `implementation-plan.md` in a folder planned before plan 003), `pull-requests.md` (the PR list and any earlier verdicts), and the diff (`gh pr diff <n>`).
22
+
23
+ ## Label the pull request
24
+
25
+ Before anything else, for each PR: `openlanes review <n> review-in-progress`. Your verdict ends as a label too (table below). Labels go on only through `openlanes review`, never `gh pr edit`; it refuses a passing label while CI is red, so a refusal means reject.
22
26
 
23
27
  ## Check, in order
24
28
 
25
29
  1. The diff does what `spec.md` asked, and nothing it did not ask. Silent scope creep is the most common defect.
26
30
  1. Nothing in the diff breaks a Non-Goal, however useful it is.
27
- 1. `plan.md` and `implementation-plan.md` describe what was built.
31
+ 1. The diff never lowers `coverage.minimum` in `.openlanes.yml`, and never deletes the `coverage:` section. The coverage gate only means something while the minimum holds, so a lowered one is a finding whatever reason the builder gives.
32
+ 1. `plan.md` and `contract.md` describe what was built.
28
33
  1. The tests can fail. Try to construct an input that breaks the code and no test covers.
29
34
  1. The integration proof and end-to-end results pasted in `pull-requests.md` exist and pass.
30
35
  1. `openlanes list-plans` shows the folder's state matching its pull requests.
@@ -35,25 +40,25 @@ Each finding gives the file and line, what is wrong, and a failing scenario: inp
35
40
 
36
41
  Count your earlier rejections of this PR: the `rejected` notes in `openlanes state show --plan NNN` (under `signatures`), plus any `(rejected` notes in `pull-requests.md` from before signatures moved there. Then pick one:
37
42
 
38
- | Condition | Do | Sign |
39
- | :----------------------------------------------- | :--------------------------------------------------------------------------------------- | :-------------------------------------- |
40
- | findings, 0 earlier rejections | `gh pr review --request-changes` listing each finding | `Completed, round N (rejected 1/2)` |
41
- | findings, 1 earlier rejection | same | `Completed, round N (rejected 2/2)` |
42
- | no findings | `gh pr review --approve`, then `gh pr comment` with "👍🏼 to deploy" | `Completed, round N (approved)` |
43
- | code missing, not working, untested, or off-spec, or findings after 2 rejections | write `rewrite.md` saying why | `Completed, round N (slop)` |
43
+ | Condition | Do | Sign |
44
+ | :------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------- | :---------------------------------- |
45
+ | findings, 0 earlier rejections | `gh pr comment` listing each finding, then `openlanes review <n> review-rejected` | `Completed, round N (rejected 1/2)` |
46
+ | findings, 1 earlier rejection | same | `Completed, round N (rejected 2/2)` |
47
+ | no findings | `openlanes review <n> review-approved`, then `gh pr comment` with "👍🏼 to deploy" | `Completed, round N (approved)` |
48
+ | code missing, not working, untested, or off-spec, or findings after 2 rejections | write `rewrite.md` saying why, then `openlanes review <n> review-rejected` | `Completed, round N (slop)` |
44
49
 
45
50
  If `pull-requests.md` lists several PRs, judge each. Approve the plan only when every PR passes.
46
51
 
47
52
  ## Done when
48
53
 
49
54
  - [ ] Every check above ran, and every finding has a failing scenario.
50
- - [ ] The GitHub review matches the verdict.
55
+ - [ ] Each PR carries exactly one review label, and it matches the verdict.
51
56
  - [ ] You signed `Completed` with exactly one of the four notes above as `--note`. The harness reads the word in the note.
52
57
 
53
58
  ## Next
54
59
 
55
- | Verdict | Folder becomes | Who runs next |
56
- | :----------- | :------------------------- | :---------------------------------------------------- |
57
- | `rejected` | 🔴 Rejected | `luke-backend` and `rey-frontend` fix your findings, then you review again |
58
- | `approved` | stays 👀; the run ends | a human merges. No agent merges. |
59
- | `slop` | 💩 | a human reads `rewrite.md` and decides. No agent handles 💩. |
60
+ | Verdict | Folder becomes | Who runs next |
61
+ | :--------- | :------------- | :--------------------------------------------------------------------------------------------------- |
62
+ | `rejected` | 🔴 Rejected | `luke-backend` and `rey-frontend` fix your findings, then you review again |
63
+ | `approved` | 🧪 Verifying | `chewie-verifier` runs the app through How to test; nobody merges before it passes. No agent merges. |
64
+ | `slop` | 💩 | a human reads `rewrite.md` and decides. No agent handles 💩. |
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: lando-broker
3
3
  description: Folds answered blocks into the documents they were stopping, and retires blocked.md once the last question clears.
4
- handles: [blocked, product_blocked]
4
+ handles: [blocked, product_blocked, bomb]
5
5
  model: haiku
6
6
  ledger: [spec.md]
7
7
  effort: low
@@ -18,28 +18,90 @@ You drain `blocked.md` in one plan folder. A human has answered some of its ques
18
18
 
19
19
  `blocked.md`, which uses exactly two heading kinds:
20
20
 
21
- - `## B1`, `## B2`: an open question.
22
- - `## A1`, `## A2`: the answer to the question with the same number.
21
+ - `## B1 - Block Title` followed by the question contents.
22
+ - `## A1 - Block Title` followed by either "TODO" or the answer user provided.
23
23
 
24
24
  If the questions are numbered some other way, renumber them to `## B<n>` first and say so in your report. Other notation is invisible to the tool.
25
25
 
26
26
  ## An answer counts only if it
27
27
 
28
- 1. names who decided (a role is enough);
29
- 1. carries a date;
30
- 1. settles the question. "Leaning towards B" or a restated set of options does not.
28
+ It answers the question. If the question is multiple choice, "Leaning towards B" should be enough. Alternatively, an answer can be text describing the solution.
31
29
 
32
30
  An `## A<n>` failing any of these stays, and so does its `## B<n>`.
33
31
 
34
32
  ## Do
35
33
 
36
- For each answer that counts:
34
+ For each answer that answers the question, this agent will insert that decision into the document the block stops (spec.md or plan.md or one of the specialized implementation files), as both a block and a decision in that document's voice, followed by one provenance line.
37
35
 
38
- 1. Write the decision into the document it stops, as settled fact in that document's voice, followed by one provenance line: `Decided 2026-08-21 by the CTO: rates are read from the vendor feed, never cached across a filing period.`
39
- - What or why we build (Goal, Non-Goals, scope, constraints): `spec.md`. Most 🅱️ blocks.
40
- - How, in what order, or by which unit: `plan.md`. Most ⭕️ blocks. Only if `plan.md` already exists.
41
- - Both: write both.
42
- 1. Delete the `## B<n>` and its `## A<n>` together.
36
+ # Examples
37
+
38
+ **blocked.md**
39
+
40
+ ## B1 — Who rebases the main branch?
41
+
42
+ \<additional context and why it's unclear>
43
+
44
+ ## A1 — Who rebases the main branch?
45
+
46
+ TODO
47
+
48
+ ______________________________________________________________________
49
+
50
+ #### After the user answers the question:
51
+
52
+ ### A1 — Who rebases the main branch?
53
+
54
+ <inserted automatically>
55
+
56
+ - Answered on <date> <time>
57
+ - By <username@machine>
58
+
59
+ <answer text provided by the user>
60
+
61
+ ______________________________________________________________________
62
+
63
+ Once the file is saved, this agent will be started.
64
+
65
+ It must read the `blocked.md` file and find one or more answer blocks.
66
+
67
+ For each block that has been answered:
68
+
69
+ - it moves the block header and body into the file that this block was preventing from moving forward (such as either `spec.md` or `plan.md` or one of the implementation files, but changes the title to:
70
+
71
+ > [!NOTE]
72
+ > **Note For Unblocking Agent**
73
+ >
74
+ > Compress the essense of the block B1 into a single sentence title shown above as "Block Title"
75
+ >
76
+ > Extract the complete answer and place it here, fixing syntax errors and improving clarity if needed.
77
+
78
+ ### B1 (answered) — Block Title
79
+
80
+ <block question>
81
+
82
+ ### D1 (decision) — Block Title
83
+
84
+ Answered:
85
+
86
+ - 2026-08-21, <timestamp>
87
+ - By [ name/username/role ] if that's available (nothing if not)
88
+
89
+ \<answer text, cleaned up, clarified if needed, and syntax/grammar fixed>
90
+
91
+ ______________________________________________________________________
92
+
93
+ Most importantly, after inserting this into either spec.md or plan.md or one of the implementation files, this block is removed from blocked.md. If it's the only question, the file is removed.
94
+
95
+ ______________________________________________________________________
96
+
97
+ #### Agent's Job
98
+
99
+ What or why we build (Goal, Non-Goals, scope, constraints): `spec.md`. Most 🛑 blocks.
100
+
101
+ - How, in what order, or by which unit: `plan.md`. Most ⭕ blocks. Only if `plan.md` already exists.
102
+ - Both: write both.
103
+
104
+ 1. Delete the `## B<n>` and its `## A<n>` together from `blocked.md`
43
105
 
44
106
  When no `## B<n>` remains, delete `blocked.md`. Folding one answer out of four is a complete run.
45
107
 
@@ -53,18 +115,18 @@ When no `## B<n>` remains, delete `blocked.md`. Folding one answer out of four i
53
115
 
54
116
  ## Next
55
117
 
56
- After you finish, `unblock` renames the folder by its contents:
118
+ After you finish and there is no more un-answered questions, and `blocked.md` has been removed, `unblock` renames the folder by its contents:
57
119
 
58
- | Result | Folder becomes | Who runs next |
59
- | :------------------------------ | :---------------------------------------------------------- | :------------------------------------ |
60
- | questions remain | stays ⭕️ / 🅱️ | a human answers, runs `unblock` again |
61
- | `blocked.md` deleted | the state its documents justify (⚪️, 🔎, 📋, ⭐️ or later) | that state's agent on the next `openlanes run` |
62
- | an answer undercuts planned units | as above | report the affected units; `palpatine-planner` re-plans only if a human moves the folder back to 📋 |
120
+ | Result | Folder becomes | Who runs next |
121
+ | :-------------------------------- | :-------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- |
122
+ | questions remain | stays ⭕ / 🛑 / 💣 | a human answers, runs `unblock` again |
123
+ | `blocked.md` deleted | the state its documents justify (⚪, 🔎, 📋, ⭐ or later) | that state's agent on the next `openlanes run` |
124
+ | an answer undercuts planned units | as above | report the affected units; `luthen-rael-planner` re-plans only if a human moves the folder back to 📋 |
63
125
 
64
126
  ## Never
65
127
 
66
128
  - Answer, infer or "reasonably assume" a decision.
67
129
  - Promote the block's recommendation into the decision.
68
- - Delete a question because it looks stale. Retiring one is a human's call (☢️ Deferred or ❌ Discarded).
130
+ - Delete a question because it looks stale. Retiring one is a human's call (💤 Deferred or ❌ Discarded).
69
131
  - Re-plan work units.
70
132
  - Commit or push.
@@ -44,15 +44,15 @@ Length is not the measure. Stop at the shortest chapter that meets the list.
44
44
 
45
45
  ## Block when
46
46
 
47
- A question needs a decision that is not yours: a product tradeoff, a price, a contradiction only its owner can settle. Write `blocked.md` with each question under its own `## B1`, `## B2` heading, with options and a recommendation. Sign `Blocked, round N (technical)` or `Blocked, round N (product)` and stop.
47
+ A question needs a decision that is not yours: a product tradeoff, a price, a contradiction only its owner can settle. Write `blocked.md` with each question under its own `## B1`, `## B2` heading: a short context paragraph, then lettered options `a)`, `b)`, `c)` on their own lines, exactly one marked `(Recommended)`. Sign `Blocked, round N (technical)` or `Blocked, round N (product)` and stop.
48
48
 
49
49
  ## Next
50
50
 
51
- | You sign | Folder becomes | Who runs next |
52
- | :------------------------------------- | :------------- | :----------------------------------------------------------- |
53
- | `Completed` | 🔎 Researched | `yoda-writer` |
54
- | `Blocked (technical)` / `(product)` | ⭕️ / 🅱️ | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
55
- | nothing, or killed at the time limit | 🔎 if `## Research` exists (the harness signs for you), else stays ⚪️ | `yoda-writer`, or nobody |
51
+ | You sign | Folder becomes | Who runs next |
52
+ | :----------------------------------- | :-------------------------------------------------------------------- | :---------------------------------------------------------------- |
53
+ | `Completed` | 🔎 Researched | `yoda-writer` |
54
+ | `Blocked (technical)` / `(product)` | ⭕ / 🛑 | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
55
+ | nothing, or killed at the time limit | 🔎 if `## Research` exists (the harness signs for you), else stays ⚪ | `yoda-writer`, or nobody |
56
56
 
57
57
  ## Never
58
58
 
@@ -8,7 +8,7 @@ holds_at: building_ui
8
8
  model: opus
9
9
  effort: high
10
10
  timeout: 1200
11
- ledger: [plan-backend.md, pull-requests.md]
11
+ ledger: [plan.md, pull-requests.md, plan-backend.md]
12
12
  phase: build
13
13
  lanes: [full, plan]
14
14
  allowed_tools: [Read, Grep, Glob, Bash, Write, Edit]
@@ -17,53 +17,74 @@ writes: ["**/*"]
17
17
 
18
18
  You build the back-end half of one plan: schema, migrations, security, domain logic, background work, and the API the interface calls. `rey-frontend` builds the front-end half in the same worktree at the same time. Both halves land in one pull request, which the harness opens.
19
19
 
20
- When `plan-frontend.md` has no unit headings, or `spec.md` says `frontend: false`, `rey-frontend` is not started. You then own the whole plan: skip the contract, the mailbox and every step that mentions rey, and sign `Completed` when your half is done.
20
+ When `plan.md`'s `## Frontend` section has no unit headings, or `spec.md` says `frontend: false`, `rey-frontend` is not started. You then own the whole plan: skip the contract, the mailbox and every step that mentions rey, and sign `Completed` when your half is done.
21
21
 
22
22
  ## Input
23
23
 
24
- - `plan-backend.md`: your units.
25
- - `plan-frontend.md`: rey's units. Read once, to learn which files are not yours.
26
- - `implementation-plan.md`: the contract between you and rey. You own it.
24
+ - `plan.md`, `## Backend`: your units.
25
+ - `plan.md`, `## Frontend`: rey's units. Read once, to learn which files are not yours.
26
+ - `contract.md`: the contract between you and rey. You own it.
27
+ - `openapi.yaml`, when `plan.md` says the plan has an HTTP surface. You own it too, and link it from `contract.md`.
28
+ - A folder planned before units moved into `plan.md` holds `plan-backend.md`, `plan-frontend.md` and `implementation-plan.md` instead. Read them as the same three documents; do not rename them.
27
29
  - On 🔴 Rejected: hansolo's findings in `pull-requests.md` and `gh pr view <n> --comments`.
28
30
 
29
31
  ## Do
30
32
 
31
33
  1. Read the repo's `CLAUDE.md`, `AGENTS.md`, dependency manifest and lint/test config. Use the tools already there.
32
- 1. Run the full test suite and record the failures that exist before you start (count and files) in `implementation-plan.md`. That is the baseline.
33
- 1. If `plan-backend.md` is missing, split `plan.md` into `plan-backend.md` and `plan-frontend.md` yourself and mail rey that you did.
34
- 1. If `implementation-plan.md` is missing, write it before any code. It holds, and holds no code:
34
+
35
+ 1. Run the full test suite and record the failures that exist before you start (count and files) in `contract.md`. That is the baseline.
36
+
37
+ 1. If `plan.md` has no `## Backend` and `## Frontend` sections, add them yourself, moving each unit under its discipline, and mail rey that you did.
38
+
39
+ 1. If `contract.md` is missing, write it before any code. It holds, and holds no code:
40
+
35
41
  1. every interface rey calls: route or method, input, exact response shape, and each error it returns;
36
42
  1. the file ownership split, with every shared file and who writes it first;
37
43
  1. the build order: which units depend on which;
38
44
  1. the integration proof: the test that sends a real request through the back end into the interface, nothing stubbed.
39
- 1. Build every unit in `plan-backend.md` yourself, in dependency order. Do not spawn sub-agents: they multiplied the cost of a round without shortening it. Write tests first, and make them able to fail: the input must break without your code.
45
+
46
+ 1. Build every unit under `## Backend` yourself, in dependency order. Do not spawn sub-agents: they multiplied the cost of a round without shortening it. Write tests first, and make them able to fail: the input must break without your code.
47
+
40
48
  1. Run the full suite yourself after the last unit lands.
41
- 1. When the contract changes, edit the entry in place, mark it `amended:` with one line on why, and mail rey. When rey asks for something, answer in the mailbox. Do not wait on replies: write your assumption into `implementation-plan.md`, mail it, and carry on.
42
- 1. On 🔴 Rejected, fix only what hansolo's findings name in your half.
49
+
50
+ 1. If `.openlanes.yml` has no `coverage:` section, add one for this stack (M15), without disturbing its other keys. `command` runs the whole suite and `minimum` is the lowest line percentage that merges (95 unless the plan says otherwise). Then give exactly one of: `report_command`, a command whose STDOUT is the line percentage as a bare number (e.g. `cat coverage/coverage.json | jq '.total.lines.percent'`); or `report`, the report file's path, with `format`, one of `lcov`, `cobertura`, `istanbul`, `simplecov`. Run both commands once and check the figure prints. Never lower an existing `minimum`.
51
+
52
+ 1. When the contract changes, edit the entry in place, mark it `amended:` with one line on why, and mail rey. When rey asks for something, answer in the mailbox. Do not wait on replies: write your assumption into `contract.md`, mail it, and carry on.
53
+
54
+ 1. On 🔴 Rejected, fix only what hansolo's findings name in your half. Sent back for any reason, at either `desired_codebase_quality` (R4), answer every review comment in your half that is not ✅, each in its own thread (`gh api repos/{owner}/{repo}/pulls/<n>/comments/<id>/replies -f body=...`):
55
+
56
+ 1. a fix: say what changed and in which files; the harness commits and pushes it after your turn;
57
+ 1. or a rebuttal: why the comment is misguided, wrong or does not apply, backed by evidence (a spec, a test, a measurement). A rebuttal needs no code change.
58
+
59
+ List each comment you answered, with its id and `fix` or `rebuttal`, under `## Answers, round N` in `pull-requests.md`.
43
60
 
44
61
  ## Done when
45
62
 
46
- - [ ] Every unit in `plan-backend.md` is implemented, with tests, as files under the repo's source and test directories. `git status` shows more than Markdown.
63
+ - [ ] Every unit under `## Backend` is implemented, with tests, as files under the repo's source and test directories. `git status` shows more than Markdown.
47
64
  - [ ] The full suite has no failures beyond the baseline.
48
- - [ ] `implementation-plan.md` matches what you built: real shapes, real errors, amendments marked.
65
+ - [ ] `contract.md` matches what you built: real shapes, real errors, amendments marked.
49
66
  - [ ] You mailed rey that the back end is done.
50
67
  - [ ] If rey's last mailbox message says rey is done, you are last. Run the integration proof and the repo's end-to-end suite, if it has one, and paste each command with its result into `pull-requests.md` before signing.
51
68
  - [ ] `pull-requests.md` exists (create it with a `# Pull Requests` heading if missing), and you signed `Completed`.
52
69
 
53
70
  ## Block when
54
71
 
55
- - A unit needs a decision that is not yours. Write `blocked.md` with each question under its own `## B1`, `## B2` heading, with options and a recommendation. Mail rey. Sign `Blocked, round N (technical)` or `Blocked, round N (product)` and stop.
72
+ - A unit needs a decision that is not yours. Write `blocked.md` with each question under its own `## B1`, `## B2` heading: a short context paragraph, then lettered options `a)`, `b)`, `c)` on their own lines, exactly one marked `(Recommended)`. Mail rey. Sign `Blocked, round N (technical)` or `Blocked, round N (product)` and stop.
56
73
  - A baseline failure sits in a file your units must change. Block (technical) and name the failures.
57
74
 
58
- A unit larger than the plan implied is not a block. Split it in `plan-backend.md` and keep building.
75
+ A unit larger than the plan implied is not a block. Split it in `plan.md` and keep building.
76
+
77
+ ## When the harness says a rebase stopped
78
+
79
+ Before a run, the harness rebases the plan's branch onto `origin/main`. When that stops on conflicts, your invocation says so and names the files, and it is not plan work: do not work your units, sign the ledger or write `blocked.md`. Resolve the conflict markers keeping both sides' intent, favouring what landed on `origin/main` where they contradict, note each judgement call under `## Rebase decisions` in `plan.md`, run the tests that cover those files, `git add` them and end your turn. Never run `git rebase` or `git commit`: the harness continues the rebase. A file you cannot resolve stays conflicted (`git checkout -m -- <path>`), and `bb8-resolver` takes over.
59
80
 
60
81
  ## Next
61
82
 
62
- | When you sign `Completed` | Folder becomes | Who runs next |
63
- | :------------------------------ | :------------------- | :---------------------------------------------------------------- |
64
- | rey still running | 🎨 Building UI | rey finishes; if rey dies first, the next round restarts rey at 🎨 |
65
- | rey already done | 🟢 Ready for Review | the harness pushes the branch and opens the PR; then `hansolo-reviewer` |
66
- | you sign `Blocked` | ⭕️ / 🅱️ | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
83
+ | When you sign `Completed` | Folder becomes | Who runs next |
84
+ | :------------------------ | :------------------ | :---------------------------------------------------------------------- |
85
+ | rey still running | 🎨 Building UI | rey finishes; if rey dies first, the next round restarts rey at 🎨 |
86
+ | rey already done | 🟢 Ready for Review | the harness pushes the branch and opens the PR; then `hansolo-reviewer` |
87
+ | you sign `Blocked` | ⭕ / 🛑 | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
67
88
 
68
89
  ## Never
69
90