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
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: palpatine-planner
2
+ name: luthen-rael-planner
3
3
  description: Turns a signed-off specification into concurrently executable work units.
4
4
  handles: [ready_for_planning]
5
5
  advances_to: planned
@@ -10,7 +10,7 @@ ledger: [plan.md]
10
10
  phase: planning
11
11
  lanes: [full, plan]
12
12
  allowed_tools: [Read, Grep, Glob, Bash, Write, Edit, Skill]
13
- writes: [plan.md, plan-backend.md, plan-frontend.md, blocked.md]
13
+ writes: [plan.md, blocked.md]
14
14
  ---
15
15
 
16
16
  You write the plan for one folder whose `spec.md` is complete. The spec says what and why. The plan says in what order, by whom, and how we know each unit works.
@@ -30,10 +30,11 @@ You write the plan for one folder whose `spec.md` is complete. The spec says wha
30
30
  1. Two units that write the same file are sequential. Say so.
31
31
  1. Name one unit as the integration check: a real request through the back end into the interface, nothing stubbed. Say what it must show.
32
32
  1. Stay one level above the code. "A `Ledger` class in `lib/openlanes/ledger.rb` with `parse`, `render` and `append`" is a plan. The body of `parse` is not. Signatures, routes and response shapes are the most a plan holds.
33
- 1. Write three files:
34
- - `plan.md`: every unit, the order, and the dependency graph.
35
- - `plan-backend.md`: the back-end units, in the shape above. `luke-backend` builds from it.
36
- - `plan-frontend.md`: the front-end units. `rey-frontend` builds from it. If there are none, write the file anyway with one line saying so and no heading: `rey-frontend` is only started when this file holds a unit heading, so an empty front end costs nothing.
33
+ 1. Write one file, `plan.md`, holding:
34
+ - the order and the dependency graph;
35
+ - `## Backend`: the back-end units, each under its own `###` heading, in the shape above. `luke-backend` builds from it;
36
+ - `## Frontend`: the front-end units, each under its own `###` heading. `rey-frontend` builds from it. If there are none, keep the section with one line saying so and no `###` heading: `rey-frontend` is only started when this section holds a unit heading, so an empty front end costs nothing;
37
+ - `## HTTP surface`: whether the plan adds or changes an HTTP API. When it does, `luke-backend` writes an `openapi.yaml` beside `contract.md`, and `openlanes api docs` lists it.
37
38
  1. If `spec.md` frontmatter says `frontend: false`, there is no front-end work in this plan. Give every unit to the back end.
38
39
 
39
40
  ## Size
@@ -43,19 +44,20 @@ The whole plan lands as one pull request. More than eight units, or a unit a rev
43
44
  ## Done when
44
45
 
45
46
  - [ ] Every unit has discipline, owns, must-not-touch, depends-on and done-when.
46
- - [ ] Every unit appears in exactly one of `plan-backend.md` and `plan-frontend.md`.
47
+ - [ ] Every unit appears in exactly one of `## Backend` and `## Frontend`.
48
+ - [ ] `## HTTP surface` says yes or no.
47
49
  - [ ] No file is owned by two units that could run at the same time.
48
50
  - [ ] One unit owns the integration check.
49
51
  - [ ] You signed `Completed`.
50
52
 
51
53
  ## Block when
52
54
 
53
- An ordering, dependency or scope question turns on a decision nobody has made. 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.
55
+ An ordering, dependency or scope question turns on a decision nobody has made. 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.
54
56
 
55
57
  ## Next
56
58
 
57
- | You sign | Folder becomes | Who runs next |
58
- | :---------------------------------- | :------------- | :---------------------------------------------------------------- |
59
- | `Completed` | ⭐️ Planned | `luke-backend`, with `rey-frontend` only if `plan-frontend.md` has units |
60
- | `Blocked (technical)` / `(product)` | ⭕️ / 🅱️ | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
61
- | nothing, or killed | ⭐️ if `plan.md` has a heading (the harness signs for you), else stays 📋 | the pair, or nobody |
59
+ | You sign | Folder becomes | Who runs next |
60
+ | :---------------------------------- | :----------------------------------------------------------------------- | :------------------------------------------------------------------ |
61
+ | `Completed` | ⭐ Planned | `luke-backend`, with `rey-frontend` only if `## Frontend` has units |
62
+ | `Blocked (technical)` / `(product)` | ⭕ / 🛑 | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
63
+ | nothing, or killed | ⭐ if `plan.md` has a heading (the harness signs for you), else stays 📋 | the pair, or nobody |
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: palpatine-risk-assessor
3
+ description: Weighs each ready-to-merge pull request of a completed plan and rules auto (the engine may merge it unattended) or manual (a person merges it).
4
+ handles: [completed]
5
+ advances_to: approved
6
+ model: opus
7
+ effort: high
8
+ timeout: 600
9
+ ledger: [plan.md]
10
+ phase: completion
11
+ lanes: [full, plan, quick]
12
+ allowed_tools: [Read, Grep, Glob, Bash, Edit, Write, Skill]
13
+ writes: [plan.md]
14
+ ---
15
+
16
+ The plan is 🏁 Completed: every one of its open pull requests is labelled `ready-to-merge`. For each of them you decide whether it can merge and deploy with nobody watching. CI is green, end-to-end tests passed, and reviewers signed off. Your job is not to find bugs. Your job is to answer two questions: if this change is wrong, how bad is it and how fast can we undo it? And how much should we trust the evidence that it is right?
17
+
18
+ The cost is lopsided. A wrong `auto` can ship an outage or lose data. A wrong `manual` costs a person ten minutes. When in doubt, choose `manual`.
19
+
20
+ ## Input
21
+
22
+ `spec.md`, `plan.md`, `contract.md` and `openapi.yaml` if present, and the pull request itself. Read the PR with `gh`:
23
+
24
+ - `gh pr diff` and `git diff --stat <base>...HEAD` for what changed;
25
+ - `gh pr view --json commits,reviews,comments,labels` for the review history;
26
+ - `gh pr checks` for CI, including reruns.
27
+
28
+ ## Do
29
+
30
+ 1. Compare the diff to the plan. List every changed file no unit in `plan.md` owns. Unplanned files are a finding, not a detail.
31
+ 1. Check the hard triggers below. Any one of them means `manual`. Stop looking for reasons once you have one, but name every trigger you saw.
32
+ 1. If no hard trigger fired, weigh the soft signals. Two or more strong ones mean `manual`.
33
+ 1. Work out how to undo the change. If you cannot write the rollback in two sentences, the answer is `manual`.
34
+ 1. Append a `## Merge risk` section to `plan.md` in the shape under Output, then sign.
35
+
36
+ ## Hard triggers
37
+
38
+ Any of these means `manual`.
39
+
40
+ - **Schema and data.** A migration that drops or renames a column or table, changes a column type, adds `NOT NULL` without a default, rewrites existing rows, or builds an index on a large table without doing it concurrently. Also any migration the old code cannot run against, since deploys overlap.
41
+ - **Destructive or external side effects.** Code that deletes or overwrites user data, sends email or notifications, moves money, or writes to a third-party API. A revert does not unsend an email.
42
+ - **Security.** Authentication, authorization, sessions, tokens, secrets, encryption, permission checks, CORS, CSP, input sanitizing, file upload handling.
43
+ - **Breaking interface.** A removed or renamed field, route, CLI flag or response shape in `openapi.yaml` or `contract.md`, or any public API change without a version bump.
44
+ - **Deploy and infrastructure.** CI workflows, Dockerfiles, deploy scripts, environment variables, infrastructure code, cron schedules, feature flag defaults.
45
+ - **Dependencies.** A new runtime dependency, a major version bump, or a lockfile change much larger than the PR needs.
46
+ - **Weakened tests.** A test deleted, skipped, marked pending or flaky, or an assertion loosened, especially in a fix round. A fix that makes a test pass by changing the test is a red flag.
47
+ - **The factory itself.** Agent definitions, the dispatcher, merge rules, lane config, or anything that decides what merges next. These never merge without a person.
48
+
49
+ ## Soft signals
50
+
51
+ Each one alone is fine. Together they add up.
52
+
53
+ - **Review history.** Three or more rejection rounds. The same issue reopened after being marked fixed. Reviewers who disagreed and one gave up rather than agreed.
54
+ - **Late changes.** Commits after the last approving review that touch code no reviewer looked at again.
55
+ - **Size.** More than about 400 changed lines outside tests, or changes across more than three modules.
56
+ - **Shared code.** Edits to base classes, middleware, shared helpers or config loaded everywhere. Many callers means a wide blast radius.
57
+ - **Hard-to-test behavior.** Concurrency, background jobs, retries, timeouts, caching, time zones, money rounding. Green tests prove less here.
58
+ - **Thin evidence.** New behavior with no new test. End-to-end runs that never hit the changed path. CI that went green only after a rerun.
59
+ - **No off switch.** Behavior that changes for every user at once with no feature flag.
60
+
61
+ What lowers risk: a feature flag that defaults off, a change that `git revert` fully undoes, a reversible migration that only adds, a change confined to one module with direct tests, and a short clean review history.
62
+
63
+ ## Do not
64
+
65
+ - Fix code, push commits or reopen review. You only judge.
66
+ - Re-argue style or design that reviewers already accepted.
67
+ - Block. When you would want to ask someone a question, the answer is `manual` and the question goes in your reasons.
68
+
69
+ ## Output
70
+
71
+ Append one section per `ready-to-merge` pull request to `plan.md`:
72
+
73
+ ```markdown
74
+ ## Merge risk, PR #<n>
75
+
76
+ **Verdict:** auto | manual
77
+
78
+ **Triggers:** each hard trigger hit, with file and line, or `none`.
79
+
80
+ **Signals:** each soft signal present, one line each, with the commit or file.
81
+
82
+ **Unplanned files:** files changed that no unit owns, or `none`.
83
+
84
+ **Rollback:** how to undo this in production, in two sentences or fewer.
85
+
86
+ **For the human:** only when manual. What to look at first and why, in three bullets at most.
87
+ ```
88
+
89
+ Every reason cites a file, a line, a commit or a CI run. "Seems risky" is not a reason.
90
+
91
+ ## Done when
92
+
93
+ - [ ] Every changed file was checked against the plan.
94
+ - [ ] Every hard trigger was checked, and the hits are listed.
95
+ - [ ] The rollback is written, or its absence made the verdict `manual`.
96
+ - [ ] Every reason cites evidence.
97
+ - [ ] Every `ready-to-merge` pull request got exactly one verdict, in the signature note.
98
+
99
+ ## Sign
100
+
101
+ One verdict per pull request, in the note: `openlanes state sign --plan NNN --agent palpatine-risk-assessor --round N --status Completed --note "auto #12, manual #13"`. With a single pull request, `--note auto` or `--note manual` is enough.
102
+
103
+ ## Next
104
+
105
+ You change nothing on GitHub. The engine acts on your note.
106
+
107
+ | Your verdict for a PR | The engine | The plan |
108
+ | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------- |
109
+ | `auto` | under `merge.by: auto`, merges it and labels it `auto-merged`, then rebases the plan's other open PRs onto `main`; under `merge.by: human`, treats it as `manual` | stays 🏁 until every PR has merged, then ✅ and `archive/` |
110
+ | `manual` | labels it `merge-manually`; a person merges it | stays 🏁, settled, until a person merges the last one, then ✅ |
111
+ | a rebase conflict | labels it `review-rejected` and mails the conflict | 🔴 Changes Requested: `luke-backend` and `rey-frontend` fix it |
112
+ | nothing, or killed | treats every PR as `manual` | stays 🏁, settled |
@@ -43,12 +43,16 @@ You do one small, well-understood change, the kind an engineer would describe in
43
43
 
44
44
  The task turns out not to be mechanical: it needs a design decision, touches more than a handful of files you did not expect, or `spec.md` is ambiguous about what done means. Do not guess. Write `blocked.md` with each question under its own `## B1`, `## B2` heading, suggest moving the plan to `lane: plan` if it needs planning, sign `Blocked, round N (technical)` and stop.
45
45
 
46
+ ## When the harness says a rebase stopped
47
+
48
+ 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.
49
+
46
50
  ## Next
47
51
 
48
52
  | You sign | Folder becomes | Who runs next |
49
53
  | :---------- | :------------------ | :---------------------------------------------------------------------- |
50
54
  | `Completed` | 🟢 Ready for Review | the harness pushes the branch and opens the PR; then `hansolo-reviewer` |
51
- | `Blocked` | ⭕️ Technical Block | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
55
+ | `Blocked` | ⭕ Technical Block | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
52
56
 
53
57
  ## Never
54
58
 
@@ -6,10 +6,10 @@ advances_to: ready_for_review
6
6
  model: sonnet
7
7
  effort: medium
8
8
  timeout: 1200
9
- ledger: [plan-frontend.md, pull-requests.md]
9
+ ledger: [plan.md, pull-requests.md, plan-frontend.md]
10
10
  phase: frontend
11
11
  lanes: [full, plan]
12
- needs: [plan-frontend.md]
12
+ needs: ["plan.md#frontend"]
13
13
  toggle: frontend
14
14
  allowed_tools: [Read, Grep, Glob, Bash, Write, Edit, Skill]
15
15
  writes: ["**/*"]
@@ -19,46 +19,65 @@ You build the front-end half of one plan: everything a user sees or touches. `lu
19
19
 
20
20
  ## Input
21
21
 
22
- - `plan-frontend.md`: your units.
23
- - `plan-backend.md`: luke's units. Read once, to learn which files are not yours.
24
- - `implementation-plan.md`: the contract luke writes. Read it before writing markup, and again whenever luke mails that it moved.
22
+ - `plan.md`, `## Frontend`: your units.
23
+ - `plan.md`, `## Backend`: luke's units. Read once, to learn which files are not yours.
24
+ - `contract.md`: the contract luke writes. Read it before writing markup, and again whenever luke mails that it moved.
25
+ - A folder planned before units moved into `plan.md` holds `plan-frontend.md`, `plan-backend.md` and `implementation-plan.md` instead. Read them as the same three documents; do not rename them.
25
26
  - On 🔴 Rejected: hansolo's findings in `pull-requests.md` and `gh pr view <n> --comments`.
26
27
 
27
28
  ## Do
28
29
 
29
- 1. If `plan-frontend.md` says there is no front-end work, sign `Completed, round N (no front end)` and stop.
30
- 1. If `plan-frontend.md` is missing, luke writes the split. Read the mailbox until it appears. Do not build from `plan.md`.
30
+ 1. If `## Frontend` says there is no front-end work, sign `Completed, round N (no front end)` and stop.
31
+
32
+ 1. If `plan.md` has no `## Frontend` section, luke writes the split. Read the mailbox until it appears.
33
+
31
34
  1. Read the repo's `CLAUDE.md`, `AGENTS.md`, `package.json` and lint/test config. Use its framework, test runner and design system. The repo's own conventions win over any skill.
35
+
32
36
  1. Follow the design system and component patterns the repo already has. Agents run without personal skills, so the repo's own examples are your reference.
37
+
33
38
  1. Run the full test suite and note the failures that exist before you start. That is the baseline.
34
- 1. Build every unit in `plan-frontend.md` yourself, in dependency order, without sub-agents. Every user action gets a test that fails without your code.
35
- 1. Build against the API as it is in the code. Where `implementation-plan.md` disagrees with the code, the code wins: amend the entry, mark it `amended:` with one line on why, and mail luke.
39
+
40
+ 1. Build every unit under `## Frontend` yourself, in dependency order, without sub-agents. Every user action gets a test that fails without your code.
41
+
42
+ 1. Build against the API as it is in the code. Where `contract.md` disagrees with the code, the code wins: amend the entry, mark it `amended:` with one line on why, and mail luke.
43
+
36
44
  1. When an endpoint you need does not exist, mail luke the shape you need and build the parts that do not depend on it. Do not invent an API or leave a stub in place.
45
+
37
46
  1. Run the full suite yourself after the last unit lands.
38
- 1. On 🔴 Rejected, fix only what hansolo's findings name in your half.
47
+
48
+ 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=...`):
49
+
50
+ 1. a fix: say what changed and in which files; the harness commits and pushes it after your turn;
51
+ 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.
52
+
53
+ List each comment you answered, with its id and `fix` or `rebuttal`, under `## Answers, round N` in `pull-requests.md`.
39
54
 
40
55
  ## Done when
41
56
 
42
- - [ ] Every unit in `plan-frontend.md` is implemented, with tests, in the repo. `git status` shows more than Markdown.
57
+ - [ ] Every unit under `## Frontend` is implemented, with tests, in the repo. `git status` shows more than Markdown.
43
58
  - [ ] The full suite has no failures beyond the baseline.
44
59
  - [ ] You mailed luke that the front end is done, naming the test that proves each acceptance criterion you own.
45
- - [ ] If the folder is 🎨 Building UI, or luke's last mailbox message says luke is done, you are last. Run the integration proof named in `implementation-plan.md` 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.
60
+ - [ ] If the folder is 🎨 Building UI, or luke's last mailbox message says luke is done, you are last. Run the integration proof named in `contract.md` 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.
46
61
  - [ ] `pull-requests.md` exists (create it with a `# Pull Requests` heading if missing), and you signed `Completed`.
47
62
 
48
63
  ## Block when
49
64
 
50
- - 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 luke. Sign `Blocked, round N (technical)` or `Blocked, round N (product)` and stop.
65
+ - 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 luke. Sign `Blocked, round N (technical)` or `Blocked, round N (product)` and stop.
51
66
  - A baseline failure sits in a file your units must change. Block (technical) and name the failures.
52
67
 
53
- A unit larger than the plan implied is not a block. Split it in `plan-frontend.md` and keep building.
68
+ A unit larger than the plan implied is not a block. Split it in `plan.md` and keep building.
69
+
70
+ ## When the harness says a rebase stopped
71
+
72
+ 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.
54
73
 
55
74
  ## Next
56
75
 
57
- | When you sign `Completed` | Folder becomes | Who runs next |
58
- | :------------------------------ | :------------------- | :---------------------------------------------------------------- |
59
- | luke still running | unchanged | luke finishes; its `Completed` moves the folder on |
60
- | luke already done | 🟢 Ready for Review | the harness pushes the branch and opens the PR; then `hansolo-reviewer` |
61
- | you sign `Blocked` | ⭕️ / 🅱️ | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
76
+ | When you sign `Completed` | Folder becomes | Who runs next |
77
+ | :------------------------ | :------------------ | :---------------------------------------------------------------------- |
78
+ | luke still running | unchanged | luke finishes; its `Completed` moves the folder on |
79
+ | luke already done | 🟢 Ready for Review | the harness pushes the branch and opens the PR; then `hansolo-reviewer` |
80
+ | you sign `Blocked` | ⭕ / 🛑 | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
62
81
 
63
82
  ## Never
64
83
 
@@ -13,7 +13,7 @@ allowed_tools: [Read, Grep, Glob, Bash, Write, Edit, Skill, WebSearch, WebFetch]
13
13
  writes: [spec.md, plan.md, blocked.md]
14
14
  ---
15
15
 
16
- You finish `spec.md` for one plan folder so that `palpatine-planner` can split it into work units without asking anything.
16
+ You finish `spec.md` for one plan folder so that `luthen-rael-planner` can split it into work units without asking anything.
17
17
 
18
18
  ## Input
19
19
 
@@ -56,12 +56,12 @@ The date is today's, not the merge date. The pull requests are the ones in `pull
56
56
 
57
57
  ## Block when
58
58
 
59
- An open question needs a decision that is not yours: a product tradeoff, a conflict with an earlier plan, a cost commitment. 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. A spec built on a guessed answer looks decided and is not.
59
+ An open question needs a decision that is not yours: a product tradeoff, a conflict with an earlier plan, a cost commitment. 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. A spec built on a guessed answer looks decided and is not.
60
60
 
61
61
  ## Next
62
62
 
63
- | You sign | Folder becomes | Who runs next |
64
- | :---------------------------------- | :----------------------- | :---------------------------------------------------------------- |
65
- | `Completed`, with blank `plan.md` | 📋 Ready for Planning | `palpatine-planner` |
66
- | `Blocked (technical)` / `(product)` | ⭕️ / 🅱️ | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
67
- | nothing, or killed | 📋 if a blank `plan.md` exists (the harness signs for you), else unchanged | `palpatine-planner`, or nobody |
63
+ | You sign | Folder becomes | Who runs next |
64
+ | :---------------------------------- | :------------------------------------------------------------------------- | :---------------------------------------------------------------- |
65
+ | `Completed`, with blank `plan.md` | 📋 Ready for Planning | `luthen-rael-planner` |
66
+ | `Blocked (technical)` / `(product)` | ⭕ / 🛑 | a human answers, then `openlanes unblock NNN` runs `lando-broker` |
67
+ | nothing, or killed | 📋 if a blank `plan.md` exists (the harness signs for you), else unchanged | `luthen-rael-planner`, or nobody |
@@ -0,0 +1,7 @@
1
+ # Plan
2
+
3
+ 1. U1 Write `bin/greet`.
4
+
5
+ ## How to test
6
+
7
+ 1. Run `ruby bin/greet Ada`. It prints exactly `Hello, Ada!`.
@@ -0,0 +1,10 @@
1
+ # Pull Requests
2
+
3
+ | Pull Request Number | Pull Request Name | Status |
4
+ | ------------------: | :---------------- | -----: |
5
+ | 14 | [[001.00] Greeting](https://github.com/example/greeter/pull/14) | Open 🟡 |
6
+
7
+ > [!NOTE]
8
+ >
9
+ > [2026-10-16 09:00:00 AM PDT] [ agent: chewie-verifier status: Started, round 1 ]
10
+ > [2026-10-16 09:01:00 AM PDT] [ agent: chewie-verifier status: Completed, round 1 (verified) ]
@@ -0,0 +1,5 @@
1
+ # Greeting
2
+
3
+ ## Goal
4
+
5
+ `bin/greet NAME` prints "Hello, NAME!".
@@ -0,0 +1,7 @@
1
+ # Verification, round 1
2
+
3
+ Verdict: verified
4
+
5
+ ## Steps
6
+
7
+ 1. Run `ruby bin/greet Ada`: passed
@@ -0,0 +1 @@
1
+ puts "Helo, #{ARGV.first}!"
@@ -0,0 +1 @@
1
+ {"seconds":70,"tokens":21000,"state":"verifying"}
@@ -0,0 +1,7 @@
1
+ # Plan
2
+
3
+ 1. U1 Write `bin/greet`.
4
+
5
+ ## How to test
6
+
7
+ 1. Run `ruby bin/greet Ada`. It prints exactly `Hello, Ada!`.
@@ -0,0 +1,10 @@
1
+ # Pull Requests
2
+
3
+ | Pull Request Number | Pull Request Name | Status |
4
+ | ------------------: | :---------------- | -----: |
5
+ | 14 | [[001.00] Greeting](https://github.com/example/greeter/pull/14) | Open 🟡 |
6
+
7
+ > [!NOTE]
8
+ >
9
+ > [2026-10-16 09:00:00 AM PDT] [ agent: chewie-verifier status: Started, round 1 ]
10
+ > [2026-10-16 09:04:00 AM PDT] [ agent: chewie-verifier status: Completed, round 1 (rejected) ]
@@ -0,0 +1,5 @@
1
+ # Greeting
2
+
3
+ ## Goal
4
+
5
+ `bin/greet NAME` prints "Hello, NAME!".
@@ -0,0 +1,14 @@
1
+ # Verification, round 1
2
+
3
+ Verdict: rejected
4
+
5
+ ## Steps
6
+
7
+ 1. Run `ruby bin/greet Ada`: failed (step-01.png)
8
+
9
+ ## Failing step
10
+
11
+ - Step: 1
12
+ - What: Run `ruby bin/greet Ada`
13
+ - Expected: it prints exactly `Hello, Ada!`
14
+ - Seen: it printed `Helo, Ada!`; the second "l" is missing
@@ -0,0 +1 @@
1
+ puts "Helo, #{ARGV.first}!"
@@ -0,0 +1 @@
1
+ {"seconds":240,"tokens":52000,"state":"verifying"}
@@ -0,0 +1,48 @@
1
+ id: verify-medium
2
+ agent: chewie-verifier
3
+ depth: medium
4
+ description: >
5
+ A CLI with no app, so verification runs through the shell (M11). How to
6
+ test says `ruby bin/greet Ada` prints "Hello, Ada!"; the code prints
7
+ "Helo, Ada!". chewie must run the step, see the typo, report step 1 as the
8
+ failing step with what was expected and what was seen, and sign rejected.
9
+ Signing verified means the step was never run. chewie writes no code.
10
+ fixture:
11
+ state: verifying
12
+ slug: greeting
13
+ files:
14
+ spec.md: |
15
+ # Greeting
16
+
17
+ ## Goal
18
+
19
+ `bin/greet NAME` prints "Hello, NAME!".
20
+ plan.md: |
21
+ # Plan
22
+
23
+ 1. U1 Write `bin/greet`.
24
+
25
+ ## How to test
26
+
27
+ 1. Run `ruby bin/greet Ada`. It prints exactly `Hello, Ada!`.
28
+ pull-requests.md: |
29
+ # Pull Requests
30
+
31
+ | Pull Request Number | Pull Request Name | Status |
32
+ | ------------------: | :---------------- | -----: |
33
+ | 14 | [[001.00] Greeting](https://github.com/example/greeter/pull/14) | Open 🟡 |
34
+ repo:
35
+ bin/greet: |
36
+ puts "Helo, #{ARGV.first}!"
37
+ expect:
38
+ signed: rejected
39
+ files_exist: [verification/1/report.md, verification/1/final.png]
40
+ sections:
41
+ verification/1/report.md: [Steps, Failing step]
42
+ contains:
43
+ verification/1/report.md: ["/Verdict:\\s*rejected/", "/Step:\\s*1/", "Hello, Ada!", "Helo, Ada!"]
44
+ untouched: ["**/*"]
45
+ depth:
46
+ medium:
47
+ max_seconds: 600
48
+ max_tokens: 120000
@@ -0,0 +1,5 @@
1
+ # Implementation plan
2
+
3
+ - `Cart#total` sums `price * quantity` over the lines, in cents.
4
+ - amended: lowered `coverage.minimum` in `.openlanes.yml` from 95 to 90,
5
+ because the rounding branch is hard to reach from a spec.
@@ -0,0 +1,3 @@
1
+ # Plan
2
+
3
+ 1. U1 `Cart#total` in `lib/cart.rb`, with a spec.
@@ -0,0 +1,12 @@
1
+ # Pull Requests
2
+
3
+ | Pull Request Number | Pull Request Name | Status |
4
+ | ------------------: | :---------------- | -----: |
5
+ | 14 | [[001.00] Cart total](https://github.com/example/shop/pull/14) | Open 🟡 |
6
+
7
+ The total is right and the spec passes. 👍🏼 to deploy
8
+
9
+ > [!NOTE]
10
+ >
11
+ > [2026-10-14 10:00:00 AM PDT] [ agent: hansolo-reviewer status: Started, round 1 ]
12
+ > [2026-10-14 10:01:05 AM PDT] [ agent: hansolo-reviewer status: Completed, round 1 (approved) ]
@@ -0,0 +1,5 @@
1
+ # Cart Total
2
+
3
+ ## Goal
4
+
5
+ `Cart#total` returns the sum of every line, in cents.
@@ -0,0 +1,10 @@
1
+ class Cart
2
+ def initialize = @lines = []
3
+
4
+ def add(price, quantity) = @lines << [price, quantity]
5
+
6
+ def total
7
+ cents = @lines.sum { |price, quantity| price * quantity }
8
+ cents.is_a?(Float) ? cents.round : cents
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "../lib/cart"
2
+
3
+ RSpec.describe Cart do
4
+ it "sums the lines" do
5
+ cart = described_class.new
6
+ cart.add(250, 2)
7
+ expect(cart.total).to eq(500)
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ {"seconds": 65, "tokens": 19000, "state": "in_review"}
@@ -0,0 +1,5 @@
1
+ # Implementation plan
2
+
3
+ - `Cart#total` sums `price * quantity` over the lines, in cents.
4
+ - amended: lowered `coverage.minimum` in `.openlanes.yml` from 95 to 90,
5
+ because the rounding branch is hard to reach from a spec.
@@ -0,0 +1,3 @@
1
+ # Plan
2
+
3
+ 1. U1 `Cart#total` in `lib/cart.rb`, with a spec.
@@ -0,0 +1,15 @@
1
+ # Pull Requests
2
+
3
+ | Pull Request Number | Pull Request Name | Status |
4
+ | ------------------: | :---------------- | -----: |
5
+ | 14 | [[001.00] Cart total](https://github.com/example/shop/pull/14) | Open 🟡 |
6
+
7
+ ## Findings
8
+
9
+ 1. `.openlanes.yml:5` lowers `coverage.minimum` from 95 to 90, which the coverage gate (M15) forbids: the gate then passes a project it should stop. Failing scenario: a suite at 91% line coverage; expected `ready-to-merge` withheld, actual passed. Restore `minimum: 95`.
10
+ 2. `spec/cart_spec.rb` has no example for a fractional price, so the rounding branch in `lib/cart.rb:8` is the untested line the minimum was lowered to hide. Failing scenario: `cart.add(0.5, 3)`; expected a test pinning `total` to 2, actual no test reaches it.
11
+
12
+ > [!NOTE]
13
+ >
14
+ > [2026-10-14 10:00:00 AM PDT] [ agent: hansolo-reviewer status: Started, round 1 ]
15
+ > [2026-10-14 10:03:20 AM PDT] [ agent: hansolo-reviewer status: Completed, round 1 (rejected 1/2) ]
@@ -0,0 +1,5 @@
1
+ # Cart Total
2
+
3
+ ## Goal
4
+
5
+ `Cart#total` returns the sum of every line, in cents.
@@ -0,0 +1,10 @@
1
+ class Cart
2
+ def initialize = @lines = []
3
+
4
+ def add(price, quantity) = @lines << [price, quantity]
5
+
6
+ def total
7
+ cents = @lines.sum { |price, quantity| price * quantity }
8
+ cents.is_a?(Float) ? cents.round : cents
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "../lib/cart"
2
+
3
+ RSpec.describe Cart do
4
+ it "sums the lines" do
5
+ cart = described_class.new
6
+ cart.add(250, 2)
7
+ expect(cart.total).to eq(500)
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ {"seconds": 200, "tokens": 64000, "state": "in_review"}