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
data/bin/factory-e2e DELETED
@@ -1,157 +0,0 @@
1
- #!/usr/bin/env bash
2
- # vim: ft=bash
3
- #
4
- # The factory integration test: a throwaway git repository, `openlanes start`
5
- # serving it, and Cypress building a tic-tac-toe page through the control
6
- # room with real agents. It spends real tokens, so it refuses to run unless
7
- # OPENLANES_FACTORY_E2E=1 says so, and nothing in `just test`, `just web-e2e`
8
- # or CircleCI calls it.
9
- #
10
- # OPENLANES_FACTORY_E2E=1 just factory-e2e
11
- #
12
- # Settings, each with a default:
13
- #
14
- # FACTORY_PORT control room port (4777)
15
- # FACTORY_REDIS_URL Redis for the board and its commands (redis://localhost:6379/11)
16
- # FACTORY_MODEL model every agent runs on (haiku)
17
- # FACTORY_TIMEOUT seconds before one agent is abandoned (600)
18
- # FACTORY_MINUTES minutes Cypress waits for the build (15)
19
- #
20
- # What it leaves behind is log/factory-e2e/: the progress log, the last
21
- # board, every plan's state.json and spec.md, the built index.html, and the
22
- # tail of each agent's trace. The temp repository and the `openlanes start` it
23
- # launched are always torn down, pass or fail; nothing it did not start is
24
- # touched.
25
-
26
- set -euo pipefail
27
-
28
- repo="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
29
-
30
- if [[ "${OPENLANES_FACTORY_E2E:-}" != "1" ]]; then
31
- echo "factory-e2e runs real agents and spends real tokens." >&2
32
- echo "Set OPENLANES_FACTORY_E2E=1 to run it: OPENLANES_FACTORY_E2E=1 just factory-e2e" >&2
33
- exit 64
34
- fi
35
-
36
- port="${FACTORY_PORT:-4777}"
37
- redis_url="${FACTORY_REDIS_URL:-redis://localhost:6379/11}"
38
- model="${FACTORY_MODEL:-haiku}"
39
- timeout="${FACTORY_TIMEOUT:-600}"
40
- minutes="${FACTORY_MINUTES:-15}"
41
- artifacts="${repo}/log/factory-e2e"
42
-
43
- command -v claude >/dev/null || { echo "claude is not on PATH; the factory has no agents to run." >&2; exit 69; }
44
- if command -v redis-cli >/dev/null && ! redis-cli -u "${redis_url}" ping >/dev/null 2>&1; then
45
- echo "Redis does not answer on ${redis_url}." >&2
46
- exit 69
47
- fi
48
- # Another server on the port (the user's own `openlanes web` on 11000, say) is
49
- # left alone: the run refuses rather than share or kill it.
50
- if lsof -nP -iTCP:"${port}" -sTCP:LISTEN >/dev/null 2>&1; then
51
- echo "Port ${port} is taken; set FACTORY_PORT to a free one." >&2
52
- exit 69
53
- fi
54
- [[ -f "${repo}/web/dist/index.html" ]] || { echo "web/dist is missing; run just web-build first." >&2; exit 66; }
55
-
56
- tmp="$(mktemp -d "${TMPDIR:-/tmp}/openlanes-factory.XXXXXX")"
57
- project="${tmp}/tictactoe"
58
- started_at="${tmp}/.started"
59
- pid=""
60
-
61
- openlanes() { "${repo}/exe/openlanes" "$@"; }
62
-
63
- collect() {
64
- rm -rf "${artifacts}"
65
- mkdir -p "${artifacts}/plans" "${artifacts}/traces"
66
- curl -sf "http://127.0.0.1:${port}/api/board" -o "${artifacts}/board.json" 2>/dev/null || true
67
- cp "${tmp}/progress.log" "${artifacts}/" 2>/dev/null || true
68
- cp "${tmp}/start.log" "${artifacts}/" 2>/dev/null || true
69
- if [[ -d "${project}/.plans" ]]; then
70
- for plan in "${project}"/.plans/*/; do
71
- name="$(basename "${plan}")"
72
- mkdir -p "${artifacts}/plans/${name}"
73
- cp "${plan}"*.md "${plan}"state.json "${artifacts}/plans/${name}/" 2>/dev/null || true
74
- done
75
- fi
76
- find "${project}" -name index.html -not -path '*/.git/*' -not -path '*/node_modules/*' \
77
- -exec cp {} "${artifacts}/" \; 2>/dev/null || true
78
- (cd "${project}" 2>/dev/null && git status --short >"${artifacts}/git-status.txt") || true
79
- # The traces live outside every repository (Executor::TRACE_DIR); keep the
80
- # tail of the ones this run wrote.
81
- traces="${TMPDIR:-/tmp}"
82
- traces="${traces%/}/openlanes-traces"
83
- if [[ -d "${traces}" ]]; then
84
- find "${traces}" -type f -newer "${started_at}" | while read -r trace; do
85
- tail -n 40 "${trace}" >"${artifacts}/traces/$(basename "${trace}")"
86
- done
87
- fi
88
- }
89
-
90
- teardown() {
91
- status=$?
92
- trap - EXIT INT TERM
93
- collect || true
94
- if [[ -n "${pid}" ]] && kill -0 "${pid}" 2>/dev/null; then
95
- # TERM is `openlanes start`'s graceful stop: its agents are told to stop and
96
- # its control room goes down with it. KILL only if it outlives that.
97
- kill -TERM "${pid}" 2>/dev/null || true
98
- for _ in $(seq 1 30); do kill -0 "${pid}" 2>/dev/null || break; sleep 1; done
99
- kill -KILL "${pid}" 2>/dev/null || true
100
- fi
101
- rm -rf "${tmp}"
102
- echo "factory-e2e: artifacts in ${artifacts}" >&2
103
- exit "${status}"
104
- }
105
- trap teardown EXIT
106
- trap 'exit 130' INT
107
- trap 'exit 143' TERM
108
-
109
- touch "${started_at}"
110
-
111
- # A repository with one commit and `openlanes init`, and no remote: nothing this
112
- # run does can reach GitHub.
113
- mkdir -p "${project}"
114
- (
115
- cd "${project}"
116
- git init -q -b main
117
- git config user.name "Factory Test"
118
- git config user.email "factory-test@example.invalid"
119
- cat >README.md <<'MARKDOWN'
120
- # Tic Tac Toe
121
-
122
- A static web page: plain HTML, CSS and JavaScript in the repository root,
123
- opened straight from disk. There is no package manager, no build step and no
124
- test runner; check a change by reading it and opening the page.
125
- MARKDOWN
126
- git add README.md
127
- git commit -q -m "Initial commit"
128
- openlanes init -y -q --project "Tic Tac Toe" -j 1
129
- git add -A
130
- git commit -q -m "Initialize openlanes"
131
- )
132
-
133
- # `--isolation shared` is the existing local-only mode: one tree, no branch
134
- # per plan, and no publisher, so nothing is pushed and no pull request is
135
- # opened. The finished build stays at 🟡 Building, done for this run: 🟢
136
- # Ready for Review needs an open pull request.
137
- (
138
- cd "${project}"
139
- exec "${repo}/exe/openlanes" start --no-open \
140
- --port "${port}" --redis-url "${redis_url}" \
141
- --isolation shared -j 1 \
142
- --model "${model}" --timeout "${timeout}" \
143
- --log "${tmp}/progress.log"
144
- ) >"${tmp}/start.log" 2>&1 &
145
- pid=$!
146
-
147
- for _ in $(seq 1 120); do
148
- curl -sf "http://127.0.0.1:${port}/healthz" >/dev/null 2>&1 && break
149
- kill -0 "${pid}" 2>/dev/null || { echo "openlanes start exited:" >&2; cat "${tmp}/start.log" >&2; exit 1; }
150
- sleep 0.5
151
- done
152
- curl -sf "http://127.0.0.1:${port}/healthz" >/dev/null || { echo "The control room never answered on ${port}." >&2; exit 1; }
153
-
154
- cd "${repo}/web"
155
- npx cypress run --config-file cypress.factory.config.ts \
156
- --config "baseUrl=http://127.0.0.1:${port}" \
157
- --env "projectDir=${project},minutes=${minutes}"
data/bin/plan-number DELETED
@@ -1,164 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # plan-number - resolve the .plans folder a branch belongs to, or fail.
4
- #
5
- # plan-number # resolve for the current branch
6
- # plan-number -b <branch> # ...for another branch
7
- # plan-number -D <dir> # .plans lives elsewhere (default: ./.plans)
8
- # plan-number --title "Foo" # print "[003] Foo" instead of "003"
9
- # # (or "[018.01] Foo" for a retroactive plan)
10
- # plan-number --none # print "XXX": this PR implements no plan
11
- #
12
- # Exit 0 and print the number on stdout when exactly one plan can be resolved.
13
- # Exit non-zero and explain on stderr otherwise. It never picks a winner from
14
- # several candidates and never invents one.
15
- #
16
- # == Why it refuses rather than guesses
17
- #
18
- # The number ends up in a PR title, and pull-requests.md is generated pfrom those
19
- # titles. A wrong number does not announce itself: it files the work under a
20
- # plan that did not do it, and the plan that did looks untouched. That is worse
21
- # than an unprefixed title, which at least reads as "unknown" rather than as a
22
- # confident lie. Every failure below is therefore loud.
23
- #
24
- # == The two shapes of number
25
- #
26
- # NNN an ordinary plan, specified before it was built.
27
- # NNN.MM a RETROACTIVE plan: the work shipped first and the specification
28
- # was written afterwards to describe what exists. It sits in the
29
- # sequence where the work landed - 018.01 merged after 018 and
30
- # before 019.
31
- #
32
- # NNN.MM does NOT mean "part of NNN". The dot reads as containment in most
33
- # numbering schemes and here it does not: 018.01 is a sibling of 018 that
34
- # arrived later, with no relationship to its subject. See .plans/README.md.
35
- #
36
- # The decimal is ALWAYS two digits. One digit would sort into the middle of the
37
- # two-digit range - 018.09 < 018.1 < 018.10 - so a single mixed-width folder
38
- # silently reorders the index. Two digits also give 99 slots per gap, which
39
- # retires the question of running out: a gap closes the moment the next plan is
40
- # created, since nothing merging today can land between 018 and 019.
41
- #
42
- # == The resolution order, strongest signal first
43
- #
44
- # 1. The BRANCH NAME. `kig/021-add-tune-appender` says 021 and says it before a
45
- # single line is written, which is the only moment the author certainly knows
46
- # the answer. Set once, carried on the PR record forever, survives squash.
47
- #
48
- # 2. The DIFF against the base, but ONLY when it touches exactly one plan
49
- # folder. Measured across this repository's 24 merged pull requests, this
50
- # alone resolves 6 and is ambiguous or silent on 18, so it is a fallback and
51
- # never a primary. Files directly under .plans/ (BACKLOG.md, README.md,
52
- # INDEX.md) are ignored: they belong to no single plan.
53
- #
54
- # 3. Nothing else. There is no "closest match by topic", because a heuristic
55
- # that is right most of the time produces an index nobody can trust and
56
- # nobody can audit.
57
- #
58
- # XXX is deliberately NOT step 4. A PR that implements no plan is a legitimate
59
- # and common thing - dependency bumps, CI work, hotfixes - and it is marked
60
- # [XXX] so that "no plan" is visibly asserted rather than merely absent. But the
61
- # author asserts it; this script will not, because emitting XXX on a failed
62
- # lookup would launder "I could not tell" into "there is definitely none", which
63
- # is the same lie as guessing a number, told in the other direction.
64
- #
65
- # © 2026 Konstantin Gredeskoul
66
-
67
- set -euo pipefail
68
-
69
- PLANS_DIR=".plans"
70
- BRANCH=""
71
- TITLE=""
72
- NONE=0
73
- BASE="${PLAN_NUMBER_BASE:-origin/main}"
74
-
75
- die() { printf '%s\n' "$*" >&2; exit 1; }
76
-
77
- usage() {
78
- cat >&2 <<'USAGE'
79
- Usage: plan-number [-D <plans-dir>] [-b <branch>] [--base <ref>] [--title <text>] [--none]
80
-
81
- Prints the plan number for the branch (NNN, or NNN.MM when the plan was written
82
- retroactively), or fails loudly.
83
-
84
- With --title, prints "[NNN] <text>" ready to hand to `gh pr create -t`.
85
- With --none, prints XXX: an assertion that this PR implements no plan.
86
- USAGE
87
- exit 2
88
- }
89
-
90
- while [[ $# -gt 0 ]]; do
91
- case "$1" in
92
- -D|--dir) PLANS_DIR="${2:?}"; shift 2 ;;
93
- -b|--branch) BRANCH="${2:?}"; shift 2 ;;
94
- --base) BASE="${2:?}"; shift 2 ;;
95
- -t|--title) TITLE="${2:?}"; shift 2 ;;
96
- -n|--none) NONE=1; shift ;;
97
- -h|--help) usage ;;
98
- *) die "plan-number: unknown argument: $1" ;;
99
- esac
100
- done
101
-
102
- # The three-digit number, optionally followed by one retroactive digit.
103
- NUM_RE='[0-9]{3}(\.[0-9]{2})?'
104
-
105
- if [[ "$NONE" == "1" ]]; then
106
- if [[ -n "$TITLE" ]]; then printf '[XXX] %s\n' "$TITLE"; else printf 'XXX\n'; fi
107
- exit 0
108
- fi
109
-
110
- [[ -d "$PLANS_DIR" ]] || die "plan-number: no $PLANS_DIR here. Run this from the repository root, or pass -D."
111
-
112
- # Every plan number that actually exists on disk. A resolved number is checked
113
- # against this, so a typo in a branch name fails here rather than in the index
114
- # six weeks later.
115
- existing="$(find "$PLANS_DIR" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; \
116
- | grep -oE "^${NUM_RE}" | sort -u)"
117
- [[ -n "$existing" ]] || die "plan-number: $PLANS_DIR holds no NNN[.MM]-<status>-<slug> folders."
118
-
119
- exists() { printf '%s\n' "$existing" | grep -qx "$1"; }
120
-
121
- emit() {
122
- local n="$1"
123
- exists "$n" || die "plan-number: resolved $n, but $PLANS_DIR has no folder $n-*.
124
- Existing plans: $(printf '%s' "$existing" | tr '\n' ' ')"
125
- if [[ -n "$TITLE" ]]; then printf '[%s] %s\n' "$n" "$TITLE"; else printf '%s\n' "$n"; fi
126
- exit 0
127
- }
128
-
129
- [[ -n "$BRANCH" ]] || BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
130
-
131
- # 1. The branch name. Matches 021 in kig/021-slug, 021-slug and feature/021_slug,
132
- # and 018.01 in kig/018.01-slug. Longest match wins, so a retroactive branch
133
- # does not silently resolve to its whole-number neighbour.
134
- if [[ "$BRANCH" =~ (^|/|-|_)([0-9]{3}(\.[0-9]{2})?)($|[-_]) ]]; then
135
- emit "${BASH_REMATCH[2]}"
136
- fi
137
-
138
- # 2. The diff, and only when it is unambiguous.
139
- if git rev-parse --verify --quiet "$BASE" >/dev/null 2>&1; then
140
- touched="$(git diff --name-only "$(git merge-base "$BASE" HEAD)"..HEAD -- "$PLANS_DIR" 2>/dev/null \
141
- | awk -F/ 'NF>2 {print $2}' | grep -oE "^${NUM_RE}" | sort -u || true)"
142
- count="$(printf '%s' "$touched" | grep -c . || true)"
143
-
144
- if [[ "$count" == "1" ]]; then
145
- emit "$touched"
146
- elif [[ "${count:-0}" -gt 1 ]]; then
147
- die "plan-number: this branch touches several plans and none is obviously primary:
148
- $(printf '%s' "$touched" | tr '\n' ' ')
149
- Name the branch after the one it implements (kig/NNN-slug), or pass the title yourself."
150
- fi
151
- fi
152
-
153
- die "plan-number: cannot resolve a plan for branch '${BRANCH:-<detached>}'.
154
-
155
- It carries no NNN in its name and its diff touches no single plan folder.
156
-
157
- - If it implements a plan, rename the branch: git branch -m ${USER}/NNN-slug
158
- - If it implements no plan, say so explicitly: plan-number --none --title '...'
159
- gives you [XXX]. Infrastructure, dependency bumps and hotfixes are not
160
- features, and [XXX] is the right answer for them - but it is your assertion
161
- to make, not this script's guess.
162
-
163
- Refusing rather than guessing: pull-requests.md is generated from these titles,
164
- and a wrong number files the work under a plan that did not do it."
data/bin/setup DELETED
@@ -1,26 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- set -euo pipefail
4
- IFS=$'\n\t'
5
- # set -v
6
-
7
- command -v just>/dev/null || brew install just
8
- command -v rbenv>/dev/null || brew install rbenv
9
-
10
- ruby_version="$(cat .ruby-version | tr -d '\n')"
11
- current_ruby_version="$(ruby -e 'puts RbConfig::CONFIG["RUBY_PROGRAM_VERSION"]')"
12
-
13
- if [[ ${ruby_version} != ${current_ruby_version} ]]; then
14
- bash -c "$(curl -fsSL https://bit.ly/ruby-install-0-2-1)" -- ${ruby_version}
15
- else
16
- echo -e "\e[0;33m[OK]\e[0m Ruby version ${ruby_version} is installed and current."
17
- fi
18
-
19
- rbenv versions | grep -q ${ruby_version} || {
20
- echo -e "\e[1;31mCan't find ruby version ${ruby_version} after an attempted install.\e[0m"
21
- exit 1
22
- }
23
-
24
- bundle check>/dev/null && {
25
- echo -e "\e[0;33m[OK]\e[0m Gemfile dependencies are already satisfied."
26
- } || bundle install -j 12
@@ -1,8 +0,0 @@
1
- # Plan
2
-
3
- Implement duplicate detection.
4
-
5
- > [!NOTE]
6
- >
7
- > [2026-09-04 01:10:00 PM PDT] [ agent: palpatine-planner status: Started, round 1 ]
8
- > [2026-09-04 01:14:30 PM PDT] [ agent: palpatine-planner status: Completed, round 1 ]
@@ -1,12 +0,0 @@
1
- # Plan
2
-
3
- Six units, U6 is the integration check.
4
-
5
- ## Order
6
-
7
- U1, then U2 to U5 in parallel, then U6.
8
-
9
- > [!NOTE]
10
- >
11
- > [2026-09-04 01:10:00 PM PDT] [ agent: palpatine-planner status: Started, round 1 ]
12
- > [2026-09-04 01:14:30 PM PDT] [ agent: palpatine-planner status: Completed, round 1 ]
Binary file