forge-workflow 0.0.9 → 0.1.0-beta.2

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 (479) hide show
  1. package/.claude/rules/{greptile-review-process.md → review-process.md} +56 -41
  2. package/.claude/scripts/{greptile-resolve.sh → review-resolve.sh} +13 -3
  3. package/.cursor/rules/permissions-guidance.mdc +2 -2
  4. package/.forge/hooks/check-tdd.js +3 -0
  5. package/.forge/hooks/forge-native-hook.js +245 -0
  6. package/.forge/protected-paths.yaml +157 -0
  7. package/AGENTS.md +151 -61
  8. package/CHANGELOG.md +681 -0
  9. package/CLAUDE.md +9 -106
  10. package/QUICKSTART.md +171 -0
  11. package/README.md +271 -363
  12. package/bin/forge-cmd.js +120 -9
  13. package/bin/forge-preflight.js +26 -5
  14. package/bin/forge.js +466 -489
  15. package/docs/INDEX.md +93 -0
  16. package/docs/PROJECT_DESIGN.md +685 -0
  17. package/docs/architecture/index.md +66 -0
  18. package/docs/architecture/notes/README.md +35 -0
  19. package/docs/architecture/subsystems/README.md +46 -0
  20. package/docs/{TOOLCHAIN.md → forge/TOOLCHAIN.md} +56 -47
  21. package/docs/forge/VALIDATION.md +82 -0
  22. package/docs/{AGENT_INSTALL_PROMPT.md → guides/AGENT_INSTALL_PROMPT.md} +3 -3
  23. package/docs/guides/BEADS_GITHUB_SYNC.md +32 -0
  24. package/docs/{ENHANCED_ONBOARDING.md → guides/ENHANCED_ONBOARDING.md} +16 -12
  25. package/docs/guides/GREPTILE_SETUP.md +46 -0
  26. package/docs/guides/MANUAL_REVIEW_GUIDE.md +58 -0
  27. package/docs/guides/MIGRATION.md +56 -0
  28. package/docs/guides/SETUP.md +118 -0
  29. package/docs/guides/SUPPORT.md +185 -0
  30. package/docs/guides/WORKFLOW_TEMPLATES.md +74 -0
  31. package/docs/guides/memory-backends.md +183 -0
  32. package/docs/reference/ADAPTERS.md +128 -0
  33. package/docs/reference/AGENT_SKILL_PARITY.md +175 -0
  34. package/docs/reference/COMMANDS.md +205 -0
  35. package/docs/reference/DECISION_DRIFT_GUARDS.md +97 -0
  36. package/docs/{EXAMPLES.md → reference/EXAMPLES.md} +7 -5
  37. package/docs/reference/FORGE_KERNEL_STORAGE_MODEL.md +135 -0
  38. package/docs/reference/HERMES_INTEGRATION.md +118 -0
  39. package/docs/reference/INSIGHTS_RECAP.md +63 -0
  40. package/docs/reference/INSTALL.md +164 -0
  41. package/docs/reference/KERNEL_TAXONOMY_VALIDATION.md +161 -0
  42. package/docs/reference/PROTECTED_PATH_MANIFEST.md +25 -0
  43. package/docs/reference/RELEASE.md +68 -0
  44. package/docs/reference/RESEARCH_TEMPLATE.md +292 -0
  45. package/docs/{ROADMAP.md → reference/ROADMAP.md} +12 -9
  46. package/docs/reference/SKILLS.md +35 -0
  47. package/docs/reference/STATUS_BOARD.md +80 -0
  48. package/docs/reference/TEMPLATES.md +106 -0
  49. package/docs/reference/TOOLCHAIN.md +658 -0
  50. package/docs/reference/VALIDATION.md +82 -0
  51. package/docs/reference/agent-permissions.md +169 -0
  52. package/docs/reference/beads-to-kernel-migration-ux.md +61 -0
  53. package/docs/reference/control-plane-guarantees.md +125 -0
  54. package/docs/reference/dependency-chain.md +331 -0
  55. package/docs/reference/forge-kernel-issue-command-contract.md +161 -0
  56. package/docs/reference/forge-kernel-schema.md +72 -0
  57. package/docs/reference/kernel-conflict-evaluators.md +27 -0
  58. package/docs/reference/patch-md-format.md +77 -0
  59. package/docs/reference/protected-state-surfaces.md +59 -0
  60. package/docs/reference/shepherd.md +115 -0
  61. package/docs/reference/superpowers-analysis.md +320 -0
  62. package/docs/reference/superpowers-integration-options.md +404 -0
  63. package/docs/reference/test-environment.md +519 -0
  64. package/docs/reference/upgrade-safety.md +59 -0
  65. package/lefthook.yml +18 -0
  66. package/lib/adapter-cli.js +307 -0
  67. package/lib/adapters/beads-issue-adapter.js +127 -0
  68. package/lib/adapters/beads-kernel-compat.js +1042 -0
  69. package/lib/adapters/greptile-review-adapter.js +141 -0
  70. package/lib/adapters/kernel-issue-adapter.js +101 -0
  71. package/lib/adapters/pr-state-adapter.js +484 -0
  72. package/lib/adoption-profiles.js +126 -0
  73. package/lib/agents/README.md +2 -6
  74. package/lib/agents/claude.plugin.json +3 -8
  75. package/lib/agents/codex.plugin.json +9 -1
  76. package/lib/agents/cursor.plugin.json +2 -6
  77. package/lib/agents/hermes.plugin.json +22 -0
  78. package/lib/agents-config.js +39 -1236
  79. package/lib/audit-evidence.js +282 -0
  80. package/lib/beads-setup.js +225 -28
  81. package/lib/beads-sync-scaffold.js +36 -107
  82. package/lib/codex-skills.js +51 -1
  83. package/lib/commands/_issue.js +744 -70
  84. package/lib/commands/_manifest.js +91 -0
  85. package/lib/commands/_registry.js +85 -34
  86. package/lib/commands/_resolve-command-opts.js +261 -0
  87. package/lib/commands/_serve-security.js +270 -0
  88. package/lib/commands/adapter.js +12 -0
  89. package/lib/commands/add.js +118 -0
  90. package/lib/commands/audit.js +70 -0
  91. package/lib/commands/blocked.js +5 -0
  92. package/lib/commands/board.js +64 -0
  93. package/lib/commands/claim.js +21 -2
  94. package/lib/commands/claims.js +7 -0
  95. package/lib/commands/clean.js +485 -75
  96. package/lib/commands/close.js +2 -2
  97. package/lib/commands/comment.js +5 -0
  98. package/lib/commands/control.js +148 -0
  99. package/lib/commands/create.js +2 -2
  100. package/lib/commands/dev.js +185 -7
  101. package/lib/commands/doc-gate.js +336 -0
  102. package/lib/commands/doctor.js +156 -0
  103. package/lib/commands/explain.js +15 -0
  104. package/lib/commands/export.js +237 -0
  105. package/lib/commands/gate.js +192 -0
  106. package/lib/commands/hooks.js +242 -0
  107. package/lib/commands/inbox.js +118 -0
  108. package/lib/commands/init.js +598 -0
  109. package/lib/commands/insights.js +79 -0
  110. package/lib/commands/issue.js +12 -1
  111. package/lib/commands/issues.js +66 -0
  112. package/lib/commands/lint.js +5 -0
  113. package/lib/commands/list.js +2 -2
  114. package/lib/commands/merge.js +312 -0
  115. package/lib/commands/migrate.js +523 -0
  116. package/lib/commands/new.js +12 -0
  117. package/lib/commands/options.js +241 -0
  118. package/lib/commands/orient.js +13 -0
  119. package/lib/commands/orphans.js +5 -0
  120. package/lib/commands/patch.js +67 -0
  121. package/lib/commands/plan.js +436 -24
  122. package/lib/commands/preflight.js +211 -0
  123. package/lib/commands/prime.js +13 -0
  124. package/lib/commands/push.js +69 -2
  125. package/lib/commands/ready.js +2 -2
  126. package/lib/commands/recall.js +116 -0
  127. package/lib/commands/recap.js +61 -0
  128. package/lib/commands/recommend.js +22 -2
  129. package/lib/commands/release.js +91 -0
  130. package/lib/commands/remember.js +74 -0
  131. package/lib/commands/role.js +99 -0
  132. package/lib/commands/serve.js +581 -0
  133. package/lib/commands/setup.js +851 -979
  134. package/lib/commands/shepherd.js +436 -0
  135. package/lib/commands/ship.js +23 -1
  136. package/lib/commands/show.js +2 -2
  137. package/lib/commands/stage.js +192 -0
  138. package/lib/commands/stale.js +5 -0
  139. package/lib/commands/status.js +329 -11
  140. package/lib/commands/sync.js +34 -46
  141. package/lib/commands/team.js +15 -2
  142. package/lib/commands/test.js +58 -7
  143. package/lib/commands/update.js +2 -2
  144. package/lib/commands/upgrade.js +47 -0
  145. package/lib/commands/validate.js +56 -25
  146. package/lib/commands/worktree.js +308 -128
  147. package/lib/config-writer.js +202 -0
  148. package/lib/control-plane.js +236 -0
  149. package/lib/core/runtime-graph.js +946 -0
  150. package/lib/dep-guard/keyword-ripple.js +184 -0
  151. package/lib/deprecated-sync-cleanup.js +362 -0
  152. package/lib/detect-agent.js +2 -28
  153. package/lib/detect-worktree.js +42 -17
  154. package/lib/doc-gate/declaration.js +177 -0
  155. package/lib/doc-gate/detect.js +289 -0
  156. package/lib/doc-gate/gate.js +375 -0
  157. package/lib/doc-gate/okf-config.js +128 -0
  158. package/lib/doc-gate/okf.js +429 -0
  159. package/lib/docs-command.js +1161 -6
  160. package/lib/forge-issues.js +697 -0
  161. package/lib/forge-lock.js +262 -0
  162. package/lib/gate-events.js +193 -0
  163. package/lib/global-flags.js +74 -0
  164. package/lib/greptile-match.js +7 -63
  165. package/lib/harness-capability-matrix.js +380 -0
  166. package/lib/hook-global-installer.js +347 -0
  167. package/lib/hook-renderer.js +451 -0
  168. package/lib/inbox.js +391 -0
  169. package/lib/insights.js +397 -0
  170. package/lib/issue-adapter.js +156 -0
  171. package/lib/issue-backend.js +145 -0
  172. package/lib/issue-render.js +220 -0
  173. package/lib/issue-sync/authority.js +100 -0
  174. package/lib/issue-sync/github-pull.js +184 -0
  175. package/lib/issue-sync/import-primitives.js +98 -0
  176. package/lib/issue-sync/legacy-link-bridge.js +436 -0
  177. package/lib/issue-sync/link-store.js +292 -0
  178. package/lib/issue-sync/project-github.js +123 -0
  179. package/lib/issue-sync/reconcile.js +195 -0
  180. package/lib/issue-sync/schema.js +126 -0
  181. package/lib/kernel/backing-issue.js +305 -0
  182. package/lib/kernel/broker.js +1218 -0
  183. package/lib/kernel/cli-broker-factory.js +130 -0
  184. package/lib/kernel/conflict-signal.js +82 -0
  185. package/lib/kernel/evaluators.js +195 -0
  186. package/lib/kernel/fs-class.js +495 -0
  187. package/lib/kernel/issue-command-contract.js +559 -0
  188. package/lib/kernel/issue-id-resolver.js +186 -0
  189. package/lib/kernel/lease-enforcer.js +158 -0
  190. package/lib/kernel/migrations.js +333 -0
  191. package/lib/kernel/planning-buckets-schema.js +109 -0
  192. package/lib/kernel/projection-jsonl-writer.js +450 -0
  193. package/lib/kernel/readiness-model.js +329 -0
  194. package/lib/kernel/schema.js +356 -0
  195. package/lib/kernel/sqlite-driver.js +2504 -0
  196. package/lib/kernel/taxonomy-validator.js +394 -0
  197. package/lib/lefthook-check.js +8 -4
  198. package/lib/lefthook-wiring.js +413 -0
  199. package/lib/mcp-config-renderer.js +288 -0
  200. package/lib/memory/graphiti-mcp.js +106 -0
  201. package/lib/memory/router.js +387 -0
  202. package/lib/memory/typed-api.js +102 -0
  203. package/lib/memory-digest.js +195 -0
  204. package/lib/merge-rules.js +395 -0
  205. package/lib/migrate-dry-run.js +466 -0
  206. package/lib/orientation.js +863 -0
  207. package/lib/package-manager-remediation.js +103 -0
  208. package/lib/package-root.js +381 -0
  209. package/lib/patch-intent.js +890 -0
  210. package/lib/plugin-catalog.js +3 -4
  211. package/lib/plugin-manager.js +0 -5
  212. package/lib/pr-bundle.js +186 -0
  213. package/lib/pr-monitor/differ.js +195 -0
  214. package/lib/pr-monitor/events.js +0 -0
  215. package/lib/pr-monitor/gather.js +124 -0
  216. package/lib/pr-monitor/journal.js +299 -0
  217. package/lib/pr-monitor/monitor.js +146 -0
  218. package/lib/pr-monitor/render-sticky.js +157 -0
  219. package/lib/pr-monitor/watch-lifecycle.js +95 -0
  220. package/lib/pr-monitor/watch.js +247 -0
  221. package/lib/pr-pull.js +1273 -0
  222. package/lib/pr-shepherd.js +494 -0
  223. package/lib/pr-state-validator.js +59 -0
  224. package/lib/preflight/gates.js +237 -0
  225. package/lib/preflight/runner.js +116 -0
  226. package/lib/project-discovery.js +0 -53
  227. package/lib/project-memory.js +166 -0
  228. package/lib/protected-path-manifest.js +281 -0
  229. package/lib/protected-state-surfaces.js +387 -0
  230. package/lib/release-readiness.js +2089 -0
  231. package/lib/reset.js +59 -45
  232. package/lib/review-adapter.js +68 -0
  233. package/lib/rules-sync.js +260 -0
  234. package/lib/runtime-health.js +332 -23
  235. package/lib/safety-config-renderer.js +268 -0
  236. package/lib/setup-action-log.js +1 -7
  237. package/lib/setup.js +27 -65
  238. package/lib/shell-utils.js +76 -6
  239. package/lib/skills-sync.js +330 -0
  240. package/lib/smart-status/conflicts.js +205 -0
  241. package/lib/smart-status/scoring.js +191 -0
  242. package/lib/status/beads-snapshot.js +145 -0
  243. package/lib/status/presenter.js +216 -0
  244. package/lib/status/snapshot.js +186 -0
  245. package/lib/sync-backend.js +202 -0
  246. package/lib/untrusted-content.js +52 -0
  247. package/lib/upgrade-safety.js +199 -0
  248. package/lib/workflow/enforce-stage.js +298 -47
  249. package/lib/workflow/stage-transition.js +115 -0
  250. package/lib/workflow/stages.js +30 -6
  251. package/lib/workflow/state-manager.js +159 -14
  252. package/lib/workflow/state.js +23 -1
  253. package/lib/workflow-profiles.js +17 -5
  254. package/package.json +46 -36
  255. package/rules/documentation.md +19 -0
  256. package/rules/kernel-tracking.md +26 -0
  257. package/rules/security.md +22 -0
  258. package/rules/tdd.md +20 -0
  259. package/rules/workflow.md +27 -0
  260. package/scripts/auto-backing-issue.js +47 -0
  261. package/scripts/beads-context.sh +165 -22
  262. package/scripts/beads-migrate-to-dolt.sh +7 -0
  263. package/scripts/beads-upgrade-smoke.sh +284 -0
  264. package/scripts/behavioral-judge.sh +115 -11
  265. package/scripts/benchmark.js +349 -63
  266. package/scripts/bootstrap-windows-tools.sh +78 -0
  267. package/scripts/branch-protection.js +2 -3
  268. package/scripts/check-agents.js +34 -137
  269. package/scripts/commitlint.js +3 -1
  270. package/scripts/conflict-detect.sh +3 -0
  271. package/scripts/dep-guard-analyze.js +52 -17
  272. package/scripts/dep-guard-keyword-ripple.js +29 -0
  273. package/scripts/dep-guard-render-review.js +86 -0
  274. package/scripts/dep-guard.sh +64 -232
  275. package/scripts/file-index.sh +3 -0
  276. package/scripts/forge-team/lib/claim.sh +34 -18
  277. package/scripts/forge-team/lib/dashboard.sh +61 -86
  278. package/scripts/forge-team/lib/epic.sh +99 -263
  279. package/scripts/forge-team/lib/hooks.sh +26 -28
  280. package/scripts/forge-team/lib/identity.sh +4 -4
  281. package/scripts/forge-team/lib/sync-github.sh +144 -47
  282. package/scripts/forge-team/lib/verify.sh +93 -83
  283. package/scripts/forge-team/lib/workload.sh +41 -65
  284. package/scripts/forge-team/tests/claim.test.sh +25 -19
  285. package/scripts/forge-team/tests/dashboard.test.sh +31 -46
  286. package/scripts/forge-team/tests/epic.test.sh +52 -71
  287. package/scripts/forge-team/tests/hooks.test.sh +38 -50
  288. package/scripts/forge-team/tests/identity.test.sh +3 -3
  289. package/scripts/forge-team/tests/integration.test.sh +44 -66
  290. package/scripts/forge-team/tests/sync-github.test.sh +183 -79
  291. package/scripts/forge-team/tests/verify.test.sh +37 -46
  292. package/scripts/forge-team/tests/workflow-integration.test.sh +4 -4
  293. package/scripts/forge-team/tests/workload.test.sh +32 -66
  294. package/scripts/gen-command-manifest.js +153 -0
  295. package/scripts/gen-embedded-assets.mjs +129 -0
  296. package/scripts/install.ps1 +139 -0
  297. package/scripts/install.sh +268 -0
  298. package/scripts/lib/beads-migrate-to-dolt.mjs +503 -0
  299. package/scripts/lib/release-asset.mjs +84 -0
  300. package/scripts/parity-check.mjs +145 -0
  301. package/scripts/parity-check.test.mjs +58 -0
  302. package/scripts/pin-agentic-workflow-images.js +112 -0
  303. package/scripts/pr-coordinator.sh +3 -0
  304. package/scripts/preflight-sonar.eslint.config.mjs +44 -0
  305. package/scripts/preflight.sh +108 -0
  306. package/scripts/protected-state-check.js +104 -0
  307. package/scripts/smart-status-score.js +31 -0
  308. package/scripts/smart-status-sessions.js +51 -0
  309. package/scripts/smart-status.sh +117 -369
  310. package/scripts/spikes/config-race-bench.js +111 -0
  311. package/scripts/spikes/harness-capability-matrix.js +13 -0
  312. package/scripts/spikes/patch-anchor-stability-bench.js +125 -0
  313. package/scripts/spikes/protected-path-manifest.js +20 -0
  314. package/scripts/spikes/skill-auto-invoke-parity.js +292 -0
  315. package/scripts/sync-agent-skills.js +62 -0
  316. package/scripts/sync-agentic-workflow.js +48 -0
  317. package/scripts/sync-utils.sh +3 -0
  318. package/scripts/test-ci-shard.js +251 -0
  319. package/scripts/test-dashboard.js +188 -52
  320. package/scripts/test-full-suite.js +186 -0
  321. package/scripts/test-profile.js +278 -0
  322. package/scripts/test.js +302 -28
  323. package/scripts/validate.js +143 -0
  324. package/scripts/validate.sh +18 -1
  325. package/skills/claim-safety/SKILL.md +102 -0
  326. package/skills/claim-safety/evals/evals.json +46 -0
  327. package/{.github/prompts/dev.prompt.md → skills/dev/SKILL.md} +46 -52
  328. package/skills/dev/evals/evals.json +50 -0
  329. package/skills/hermes-forge/SKILL.md +185 -0
  330. package/skills/hermes-forge/evals/evals.json +46 -0
  331. package/skills/issue-basics/SKILL.md +111 -0
  332. package/skills/issue-basics/evals/evals.json +46 -0
  333. package/skills/kernel/SKILL.md +166 -0
  334. package/skills/kernel/evals/evals.json +50 -0
  335. package/skills/memory/SKILL.md +102 -0
  336. package/skills/parallel-deep-research/SKILL.md +14 -11
  337. package/skills/parallel-deep-research/evals/evals.json +11 -27
  338. package/{.github/prompts/plan.prompt.md → skills/plan/SKILL.md} +134 -159
  339. package/skills/plan/evals/evals.json +42 -0
  340. package/skills/research/SKILL.md +195 -0
  341. package/skills/research/evals/evals.json +42 -0
  342. package/{.github/prompts/review.prompt.md → skills/review/SKILL.md} +98 -62
  343. package/skills/review/evals/evals.json +42 -0
  344. package/skills/rollback/SKILL.md +110 -0
  345. package/skills/rollback/evals/evals.json +46 -0
  346. package/skills/rollback/references/methods.md +204 -0
  347. package/{.cursor/commands/rollback.md → skills/rollback/references/workflow-integration.md} +10 -284
  348. package/skills/shepherd/SKILL.md +66 -0
  349. package/skills/shepherd/evals/evals.json +42 -0
  350. package/skills/ship/SKILL.md +251 -0
  351. package/skills/ship/evals/evals.json +42 -0
  352. package/skills/smith/SKILL.md +142 -0
  353. package/skills/smith/evals/evals.json +46 -0
  354. package/skills/smith/references/autonomy-and-gates.md +94 -0
  355. package/{.github/prompts/sonarcloud.prompt.md → skills/sonarcloud/SKILL.md} +14 -3
  356. package/skills/sonarcloud/evals/evals.json +46 -0
  357. package/skills/sonarcloud-analysis/SKILL.md +18 -13
  358. package/skills/sonarcloud-analysis/evals/evals.json +11 -15
  359. package/skills/status/SKILL.md +102 -0
  360. package/skills/status/evals/evals.json +50 -0
  361. package/skills/triage-ready/SKILL.md +121 -0
  362. package/skills/triage-ready/evals/evals.json +42 -0
  363. package/{.github/prompts/validate.prompt.md → skills/validate/SKILL.md} +52 -29
  364. package/skills/validate/evals/evals.json +42 -0
  365. package/skills/verify/SKILL.md +299 -0
  366. package/skills/verify/evals/evals.json +50 -0
  367. package/.claude/commands/dev.md +0 -345
  368. package/.claude/commands/plan.md +0 -566
  369. package/.claude/commands/premerge.md +0 -186
  370. package/.claude/commands/research.md +0 -42
  371. package/.claude/commands/review.md +0 -451
  372. package/.claude/commands/rollback.md +0 -721
  373. package/.claude/commands/ship.md +0 -213
  374. package/.claude/commands/sonarcloud.md +0 -152
  375. package/.claude/commands/status.md +0 -90
  376. package/.claude/commands/validate.md +0 -288
  377. package/.claude/commands/verify.md +0 -269
  378. package/.claude/rules/workflow.md +0 -121
  379. package/.cline/workflows/dev.md +0 -342
  380. package/.cline/workflows/plan.md +0 -563
  381. package/.cline/workflows/premerge.md +0 -183
  382. package/.cline/workflows/research.md +0 -39
  383. package/.cline/workflows/review.md +0 -448
  384. package/.cline/workflows/rollback.md +0 -718
  385. package/.cline/workflows/ship.md +0 -210
  386. package/.cline/workflows/sonarcloud.md +0 -146
  387. package/.cline/workflows/status.md +0 -87
  388. package/.cline/workflows/validate.md +0 -285
  389. package/.cline/workflows/verify.md +0 -266
  390. package/.codex/config.toml +0 -11
  391. package/.codex/skills/dev/SKILL.md +0 -345
  392. package/.codex/skills/plan/SKILL.md +0 -566
  393. package/.codex/skills/premerge/SKILL.md +0 -186
  394. package/.codex/skills/research/SKILL.md +0 -42
  395. package/.codex/skills/review/SKILL.md +0 -451
  396. package/.codex/skills/rollback/SKILL.md +0 -721
  397. package/.codex/skills/ship/SKILL.md +0 -213
  398. package/.codex/skills/sonarcloud/SKILL.md +0 -149
  399. package/.codex/skills/status/SKILL.md +0 -90
  400. package/.codex/skills/validate/SKILL.md +0 -288
  401. package/.codex/skills/verify/SKILL.md +0 -269
  402. package/.cursor/commands/dev.md +0 -342
  403. package/.cursor/commands/plan.md +0 -563
  404. package/.cursor/commands/premerge.md +0 -183
  405. package/.cursor/commands/research.md +0 -39
  406. package/.cursor/commands/review.md +0 -448
  407. package/.cursor/commands/ship.md +0 -210
  408. package/.cursor/commands/sonarcloud.md +0 -146
  409. package/.cursor/commands/status.md +0 -87
  410. package/.cursor/commands/validate.md +0 -285
  411. package/.cursor/commands/verify.md +0 -266
  412. package/.cursorrules +0 -149
  413. package/.github/prompts/premerge.prompt.md +0 -188
  414. package/.github/prompts/research.prompt.md +0 -44
  415. package/.github/prompts/rollback.prompt.md +0 -723
  416. package/.github/prompts/ship.prompt.md +0 -215
  417. package/.github/prompts/status.prompt.md +0 -92
  418. package/.github/prompts/verify.prompt.md +0 -271
  419. package/.github/workflows/beads-to-github.yml +0 -56
  420. package/.github/workflows/github-to-beads.yml +0 -97
  421. package/.kilocode/workflows/dev.md +0 -346
  422. package/.kilocode/workflows/plan.md +0 -567
  423. package/.kilocode/workflows/premerge.md +0 -187
  424. package/.kilocode/workflows/research.md +0 -43
  425. package/.kilocode/workflows/review.md +0 -452
  426. package/.kilocode/workflows/rollback.md +0 -722
  427. package/.kilocode/workflows/ship.md +0 -214
  428. package/.kilocode/workflows/sonarcloud.md +0 -150
  429. package/.kilocode/workflows/status.md +0 -91
  430. package/.kilocode/workflows/validate.md +0 -289
  431. package/.kilocode/workflows/verify.md +0 -270
  432. package/.opencode/commands/dev.md +0 -345
  433. package/.opencode/commands/plan.md +0 -566
  434. package/.opencode/commands/premerge.md +0 -186
  435. package/.opencode/commands/research.md +0 -42
  436. package/.opencode/commands/review.md +0 -451
  437. package/.opencode/commands/rollback.md +0 -721
  438. package/.opencode/commands/ship.md +0 -213
  439. package/.opencode/commands/sonarcloud.md +0 -149
  440. package/.opencode/commands/status.md +0 -90
  441. package/.opencode/commands/validate.md +0 -288
  442. package/.opencode/commands/verify.md +0 -269
  443. package/.roo/commands/dev.md +0 -346
  444. package/.roo/commands/plan.md +0 -567
  445. package/.roo/commands/premerge.md +0 -187
  446. package/.roo/commands/research.md +0 -43
  447. package/.roo/commands/review.md +0 -452
  448. package/.roo/commands/rollback.md +0 -722
  449. package/.roo/commands/ship.md +0 -214
  450. package/.roo/commands/sonarcloud.md +0 -150
  451. package/.roo/commands/status.md +0 -91
  452. package/.roo/commands/validate.md +0 -289
  453. package/.roo/commands/verify.md +0 -270
  454. package/docs/BEADS_GITHUB_SYNC.md +0 -255
  455. package/docs/GREPTILE_SETUP.md +0 -400
  456. package/docs/MANUAL_REVIEW_GUIDE.md +0 -106
  457. package/docs/SETUP.md +0 -663
  458. package/docs/VALIDATION.md +0 -363
  459. package/lib/agents/cline.plugin.json +0 -29
  460. package/lib/agents/copilot.plugin.json +0 -24
  461. package/lib/agents/kilocode.plugin.json +0 -22
  462. package/lib/agents/opencode.plugin.json +0 -23
  463. package/lib/agents/roo.plugin.json +0 -30
  464. package/lib/beads-health-check.js +0 -143
  465. package/lib/commands/commands-reset.js +0 -147
  466. package/opencode.json +0 -67
  467. package/scripts/beads-context.test.js +0 -567
  468. package/scripts/github-beads-sync/comment.mjs +0 -64
  469. package/scripts/github-beads-sync/config.mjs +0 -148
  470. package/scripts/github-beads-sync/github-api.mjs +0 -131
  471. package/scripts/github-beads-sync/index.mjs +0 -332
  472. package/scripts/github-beads-sync/label-mapper.mjs +0 -54
  473. package/scripts/github-beads-sync/mapping.mjs +0 -78
  474. package/scripts/github-beads-sync/reverse-sync-cli.mjs +0 -31
  475. package/scripts/github-beads-sync/reverse-sync.mjs +0 -138
  476. package/scripts/github-beads-sync/run-bd.mjs +0 -161
  477. package/scripts/github-beads-sync/sanitize.mjs +0 -121
  478. package/scripts/github-beads-sync.config.json +0 -26
  479. package/scripts/sync-commands.js +0 -600
@@ -0,0 +1,191 @@
1
+ 'use strict';
2
+
3
+ function roundToTwo(value) {
4
+ return Math.round(value * 100) / 100;
5
+ }
6
+
7
+ function normalizePriorityNumber(priority) {
8
+ if (priority === undefined || priority === null) {
9
+ return 2;
10
+ }
11
+
12
+ if (typeof priority === 'string') {
13
+ switch (priority) {
14
+ case 'P0':
15
+ return 0;
16
+ case 'P1':
17
+ return 1;
18
+ case 'P2':
19
+ return 2;
20
+ case 'P3':
21
+ return 3;
22
+ case 'P4':
23
+ return 4;
24
+ default:
25
+ return 5;
26
+ }
27
+ }
28
+
29
+ return priority;
30
+ }
31
+
32
+ function getPriorityWeight(priority) {
33
+ switch (normalizePriorityNumber(priority)) {
34
+ case 0:
35
+ return 5;
36
+ case 1:
37
+ return 4;
38
+ case 2:
39
+ return 3;
40
+ case 3:
41
+ return 2;
42
+ case 4:
43
+ return 1;
44
+ default:
45
+ return 1;
46
+ }
47
+ }
48
+
49
+ function getTypeWeight(type = 'task') {
50
+ const normalizedType = type ?? 'task';
51
+ if (normalizedType === 'bug') {
52
+ return 1.2;
53
+ }
54
+ if (normalizedType === 'feature') {
55
+ return 1;
56
+ }
57
+ if (normalizedType === 'task') {
58
+ return 0.8;
59
+ }
60
+ return 1;
61
+ }
62
+
63
+ function getStatusBoost(status) {
64
+ if (status === 'in_progress') {
65
+ return 1.5;
66
+ }
67
+ if (status === 'open') {
68
+ return 1;
69
+ }
70
+ return 1;
71
+ }
72
+
73
+ function parseUpdatedAtLikeShell(updatedAt) {
74
+ if (!updatedAt) {
75
+ return null;
76
+ }
77
+
78
+ const normalized = `${String(updatedAt).slice(0, 19)}Z`;
79
+ const timestamp = Date.parse(normalized);
80
+ return Number.isFinite(timestamp) ? timestamp : null;
81
+ }
82
+
83
+ function getStalenessBoost(updatedAt, now = Date.now()) {
84
+ const timestamp = parseUpdatedAtLikeShell(updatedAt);
85
+ if (timestamp === null) {
86
+ return 1;
87
+ }
88
+
89
+ const days = (now - timestamp) / 86400000;
90
+ if (days >= 30) {
91
+ return 1.5;
92
+ }
93
+ if (days >= 14) {
94
+ return 1.2;
95
+ }
96
+ if (days >= 7) {
97
+ return 1.1;
98
+ }
99
+ return 1;
100
+ }
101
+
102
+ function buildDependentsMap(issues) {
103
+ const dependentsMap = new Map();
104
+
105
+ for (const issue of issues) {
106
+ for (const dependency of issue.dependencies ?? []) {
107
+ // The Kernel emits `dependencies` as bare id strings; the legacy shape
108
+ // used `{ depends_on_id }` objects. Accept both so the reverse-graph is
109
+ // reconstructable even when an issue arrives without a `dependents` array.
110
+ const dependencyId = typeof dependency === 'string'
111
+ ? dependency
112
+ : dependency?.depends_on_id;
113
+ if (!dependencyId) {
114
+ continue;
115
+ }
116
+ if (!dependentsMap.has(dependencyId)) {
117
+ dependentsMap.set(dependencyId, []);
118
+ }
119
+ dependentsMap.get(dependencyId).push(issue.id);
120
+ }
121
+ }
122
+
123
+ return dependentsMap;
124
+ }
125
+
126
+ function getEpicProximity(issue, epicStats) {
127
+ if (!issue.parent_id || !epicStats?.[issue.parent_id]) {
128
+ return 1;
129
+ }
130
+
131
+ const stats = epicStats[issue.parent_id];
132
+ if (stats.total <= 0) {
133
+ return 1;
134
+ }
135
+
136
+ return 1 + ((stats.closed / stats.total) * 0.5);
137
+ }
138
+
139
+ function scoreIssues(issues, options = {}) {
140
+ const epicStats = options.epicStats ?? {};
141
+ const now = options.now ?? Date.now();
142
+ const dependentsMap = buildDependentsMap(issues);
143
+
144
+ return [...issues]
145
+ .map((issue) => {
146
+ const priorityWeight = getPriorityWeight(issue.priority);
147
+ // Prefer an explicit count, then the Kernel's authoritative `dependents`
148
+ // reverse-graph array, then the locally-reconstructed map (legacy shape).
149
+ const directDependents = issue.dependent_count
150
+ ?? (Array.isArray(issue.dependents) ? issue.dependents.length : undefined)
151
+ ?? dependentsMap.get(issue.id)?.length
152
+ ?? 0;
153
+ const unblockChain = Math.max(directDependents + 1, 1);
154
+ const typeWeight = getTypeWeight(issue.type);
155
+ const statusBoost = getStatusBoost(issue.status);
156
+ const epicProximity = getEpicProximity(issue, epicStats);
157
+ const stalenessBoost = getStalenessBoost(issue.updated_at, now);
158
+ // The Kernel supplies `dependents` directly (reverse graph); fall back to
159
+ // the reconstructed map only for the legacy { depends_on_id } shape.
160
+ const dependents = Array.isArray(issue.dependents)
161
+ ? issue.dependents
162
+ : (dependentsMap.get(issue.id) ?? []);
163
+ const score = priorityWeight
164
+ * unblockChain
165
+ * typeWeight
166
+ * statusBoost
167
+ * epicProximity
168
+ * stalenessBoost;
169
+
170
+ return {
171
+ ...issue,
172
+ score: roundToTwo(score),
173
+ priority_weight: priorityWeight,
174
+ unblock_chain: unblockChain,
175
+ type_weight: typeWeight,
176
+ status_boost: statusBoost,
177
+ epic_proximity: roundToTwo(epicProximity),
178
+ staleness_boost: stalenessBoost,
179
+ dependents,
180
+ };
181
+ })
182
+ .sort((left, right) => right.score - left.score);
183
+ }
184
+
185
+ module.exports = {
186
+ getPriorityWeight,
187
+ getStalenessBoost,
188
+ getStatusBoost,
189
+ getTypeWeight,
190
+ scoreIssues,
191
+ };
@@ -0,0 +1,145 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const { secureExecFileSync } = require('../shell-utils.js');
6
+
7
+ function getGitConfig(projectRoot, key) {
8
+ try {
9
+ return secureExecFileSync('git', ['config', key], {
10
+ encoding: 'utf8',
11
+ cwd: projectRoot,
12
+ stdio: ['pipe', 'pipe', 'pipe'],
13
+ }).trim();
14
+ } catch (_error) {
15
+ return '';
16
+ }
17
+ }
18
+
19
+ function getDeveloperIdentity(projectRoot) {
20
+ return {
21
+ email: getGitConfig(projectRoot, 'user.email'),
22
+ name: getGitConfig(projectRoot, 'user.name'),
23
+ };
24
+ }
25
+
26
+ function normalizeEmail(value) {
27
+ return typeof value === 'string' ? value.trim().toLowerCase() : '';
28
+ }
29
+
30
+ function readIssues(projectRoot) {
31
+ const issuesPath = path.join(projectRoot, '.beads', 'issues.jsonl');
32
+ if (!fs.existsSync(issuesPath)) {
33
+ return [];
34
+ }
35
+
36
+ const raw = fs.readFileSync(issuesPath, 'utf8');
37
+ const latestById = new Map();
38
+
39
+ for (const line of raw.split(/\r?\n/)) {
40
+ if (!line.trim()) {
41
+ continue;
42
+ }
43
+
44
+ try {
45
+ const issue = JSON.parse(line);
46
+ if (issue && issue.id) {
47
+ latestById.set(issue.id, issue);
48
+ }
49
+ } catch (_error) {
50
+ // Ignore malformed rows so one bad append does not break status.
51
+ }
52
+ }
53
+
54
+ return Array.from(latestById.values());
55
+ }
56
+
57
+ function isAssignedToDeveloper(issue, developer) {
58
+ if (!issue || !developer) {
59
+ return false;
60
+ }
61
+
62
+ if (issue.owner) {
63
+ const developerEmail = normalizeEmail(developer.email);
64
+ return developerEmail !== '' && normalizeEmail(issue.owner) === developerEmail;
65
+ }
66
+
67
+ return developer.name !== '' && issue.created_by === developer.name;
68
+ }
69
+
70
+ const DEFAULT_STALE_AFTER_DAYS = 14;
71
+
72
+ function parseTimestampOrZero(value) {
73
+ if (!value) {
74
+ return 0;
75
+ }
76
+
77
+ const parsed = Date.parse(value);
78
+ return Number.isNaN(parsed) ? 0 : parsed;
79
+ }
80
+
81
+ function sortByUpdatedAtDesc(left, right) {
82
+ const leftTime = parseTimestampOrZero(left.updated_at);
83
+ const rightTime = parseTimestampOrZero(right.updated_at);
84
+ return rightTime - leftTime;
85
+ }
86
+
87
+ function hasUnresolvedDependencies(issue) {
88
+ return Number(issue.dependency_count || 0) > 0;
89
+ }
90
+
91
+ function isOpenIssue(issue) {
92
+ return issue.status === 'open' || issue.status === 'in_progress';
93
+ }
94
+
95
+ function isStale(issue, now, staleAfterDays) {
96
+ if (!isOpenIssue(issue)) {
97
+ return false;
98
+ }
99
+
100
+ const updatedAt = parseTimestampOrZero(issue.updated_at);
101
+ if (updatedAt === 0) {
102
+ return false;
103
+ }
104
+
105
+ const staleMs = staleAfterDays * 24 * 60 * 60 * 1000;
106
+ return now.getTime() - updatedAt >= staleMs;
107
+ }
108
+
109
+ function readBeadsSnapshot(projectRoot, options = {}) {
110
+ const developer = getDeveloperIdentity(projectRoot);
111
+ const issues = readIssues(projectRoot);
112
+ const parsedNow = options.now instanceof Date
113
+ ? options.now
114
+ : (typeof options.now === 'string' ? new Date(options.now) : null);
115
+ const now = parsedNow instanceof Date && !Number.isNaN(parsedNow.getTime())
116
+ ? parsedNow
117
+ : new Date();
118
+ const parsedStaleAfterDays = Number(options.staleAfterDays);
119
+ const staleAfterDays = Number.isFinite(parsedStaleAfterDays)
120
+ ? parsedStaleAfterDays
121
+ : DEFAULT_STALE_AFTER_DAYS;
122
+
123
+ return {
124
+ developer,
125
+ issues,
126
+ active: issues.filter(issue => issue.status === 'in_progress').sort(sortByUpdatedAtDesc),
127
+ activeAssigned: issues.filter(issue => issue.status === 'in_progress' && isAssignedToDeveloper(issue, developer)),
128
+ ready: issues.filter(issue => issue.status === 'open' && !hasUnresolvedDependencies(issue)),
129
+ blocked: issues.filter(issue => isOpenIssue(issue) && hasUnresolvedDependencies(issue)).sort(sortByUpdatedAtDesc),
130
+ stale: issues.filter(issue => isStale(issue, now, staleAfterDays)).sort(sortByUpdatedAtDesc),
131
+ recentCompleted: issues.filter(issue => issue.status === 'closed').sort(sortByUpdatedAtDesc),
132
+ limits: [
133
+ 'Uses local Beads issues.jsonl only.',
134
+ 'Does not read GitHub review, CI, project, or sync freshness state.',
135
+ ],
136
+ };
137
+ }
138
+
139
+ module.exports = {
140
+ getDeveloperIdentity,
141
+ isAssignedToDeveloper,
142
+ readBeadsSnapshot,
143
+ hasUnresolvedDependencies,
144
+ isStale,
145
+ };
@@ -0,0 +1,216 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ STAGE_LABELS,
5
+ getStageWorkflow,
6
+ getWorkflowPath,
7
+ } = require('../workflow/stages');
8
+
9
+ const DEFAULT_SECTION_LIMIT = 5;
10
+
11
+ // One-line "why you are at this stage", keyed by the LAST completed stage. Lets the
12
+ // one-glance view answer "why here?" without the agent re-deriving it from raw state.
13
+ const WHY_BY_LAST_COMPLETED = Object.freeze({
14
+ plan: 'planning is done; implementation not started.',
15
+ dev: 'implementation landed; not yet validated.',
16
+ validate: 'validation passed; PR not yet created.',
17
+ ship: 'PR is open; review not yet complete.',
18
+ review: 'review addressed; awaiting merge/verify.',
19
+ verify: 'post-merge verification complete.',
20
+ });
21
+
22
+ function buildSection(title, items, options = {}) {
23
+ const lines = ['', title];
24
+ if (!items || items.length === 0) {
25
+ lines.push(' none', '');
26
+ return lines;
27
+ }
28
+
29
+ const limit = options.limit ?? null;
30
+ const visibleItems = limit ? items.slice(0, limit) : items;
31
+ lines.push(...visibleItems.map(item => ` ${item}`));
32
+
33
+ if (limit && items.length > limit) {
34
+ lines.push(` ...and ${items.length - limit} more`);
35
+ }
36
+
37
+ lines.push('');
38
+ return lines;
39
+ }
40
+
41
+ function toIssueSummary(issue) {
42
+ return {
43
+ id: issue.id,
44
+ title: issue.title || '(untitled)',
45
+ status: issue.status || null,
46
+ owner: issue.owner || null,
47
+ dependency_count: Number(issue.dependency_count || 0),
48
+ updated_at: issue.updated_at || null,
49
+ };
50
+ }
51
+
52
+ function formatIssue(issue, options = {}) {
53
+ const status = options.includeStatus && issue.status ? ` [${issue.status}]` : '';
54
+ return `${issue.id} ${issue.title || '(untitled)'}${status}`;
55
+ }
56
+
57
+ // Shared Run-now / Next-after-this lines. Owned here so BOTH the one-glance
58
+ // "You are here" block and status.js's authoritative stage format render them
59
+ // identically. `noneWhenMissing` prints an explicit "none" for terminal stages
60
+ // (the one-glance view wants it; the authoritative format omits it, as before).
61
+ function formatRunNextLines(workflowResult, { noneWhenMissing = false } = {}) {
62
+ const lines = [`Run now: /${workflowResult.runCommand}`];
63
+ if (workflowResult.nextCommand) {
64
+ lines.push(`Next after this: /${workflowResult.nextCommand}`);
65
+ } else if (noneWhenMissing) {
66
+ lines.push('Next after this: none');
67
+ }
68
+ return lines;
69
+ }
70
+
71
+ // Canonical "Stage N of M — Label (classification workflow)" heading. N/M come from
72
+ // the per-classification path in lib/workflow/stages.js, so non-stages (Research,
73
+ // Merge, pre-merge, "Fresh Start") never get a number.
74
+ function formatStageHeading(workflowResult) {
75
+ const classification = workflowResult.workflowState?.workflowDecisions?.classification || null;
76
+ const stageId = workflowResult.stageId;
77
+ const label = STAGE_LABELS[stageId] || workflowResult.stageName || stageId;
78
+ const workflow = getStageWorkflow(stageId, classification);
79
+ const path = getWorkflowPath(classification);
80
+
81
+ if (workflow && path.length > 0) {
82
+ return `Stage ${workflow.order} of ${path.length} — ${label} (${classification} workflow)`;
83
+ }
84
+ return `Stage — ${label}${classification ? ` (${classification} workflow)` : ''}`;
85
+ }
86
+
87
+ function deriveWhy(workflowResult) {
88
+ const completed = workflowResult.workflowState?.completedStages || [];
89
+ const last = completed.length > 0 ? completed[completed.length - 1] : null;
90
+ return (last && WHY_BY_LAST_COMPLETED[last]) || 'just getting started.';
91
+ }
92
+
93
+ // The "You are here" block: the first thing a user or agent reads. When there is no
94
+ // active workflow, fall back to a STATE-AWARE next step rather than a dead end.
95
+ function buildYouAreHere(workflowResult, snapshot) {
96
+ const lines = ['You are here'];
97
+
98
+ if (!workflowResult) {
99
+ const topReady = (snapshot.ready || [])[0];
100
+ if (topReady) {
101
+ lines.push(` No active workflow. Next: forge claim ${topReady.id}, then /plan (or /dev for a small fix).`);
102
+ } else {
103
+ lines.push(' No active workflow and no ready issues. Next: /plan "<describe the feature>" to start one.');
104
+ }
105
+ return lines;
106
+ }
107
+
108
+ lines.push(` ${formatStageHeading(workflowResult)}`);
109
+ for (const line of formatRunNextLines(workflowResult, { noneWhenMissing: true })) {
110
+ lines.push(` ${line}`);
111
+ }
112
+ lines.push(` Why: ${deriveWhy(workflowResult)}`);
113
+ return lines;
114
+ }
115
+
116
+ // Zero-arg `forge status`: a top-down one-glance view. Order matters — orientation
117
+ // first (You are here), then Context, then your work. Blocked/Stale/Recent
118
+ // completions are detail, shown only with `--full`.
119
+ function formatZeroArgStatus({ context, snapshot, workflowResult = null, full = false }) {
120
+ const worktree = context.inWorktree ? 'worktree' : 'main';
121
+ const contextLine = `${context.branch} — ${worktree}, ${context.workingTree.summary}`;
122
+
123
+ const activeIssues = snapshot.activeAssigned || [];
124
+ const readyCount = (snapshot.ready || []).length;
125
+ const workLines = [];
126
+ if (activeIssues.length > 0) {
127
+ for (const issue of activeIssues) {
128
+ workLines.push(`Active: ${formatIssue(issue, { includeStatus: true })}`);
129
+ }
130
+ } else {
131
+ workLines.push('Active: none');
132
+ }
133
+ workLines.push(readyCount > 0 ? `Ready: ${readyCount} more (forge issue ready)` : 'Ready: none');
134
+
135
+ const blocks = [
136
+ buildYouAreHere(workflowResult, snapshot).join('\n'),
137
+ ['Context', ` ${contextLine}`].join('\n'),
138
+ ['Your work', ...workLines.map(line => ` ${line}`)].join('\n'),
139
+ 'New here? forge docs setup | forge --help',
140
+ ];
141
+
142
+ if (full) {
143
+ blocks.push(
144
+ buildSection('Blocked', (snapshot.blocked || []).map(issue => formatIssue(issue, { includeStatus: true })), { limit: DEFAULT_SECTION_LIMIT }).join('\n').trim(),
145
+ buildSection('Stale', (snapshot.stale || []).map(issue => formatIssue(issue, { includeStatus: true })), { limit: DEFAULT_SECTION_LIMIT }).join('\n').trim(),
146
+ buildSection('Parked', (snapshot.parked || []).map(issue => formatIssue(issue, { includeStatus: true })), { limit: DEFAULT_SECTION_LIMIT }).join('\n').trim(),
147
+ buildSection('Recent Completions', (snapshot.recentCompleted || []).map(issue => formatIssue(issue)), { limit: DEFAULT_SECTION_LIMIT }).join('\n').trim(),
148
+ );
149
+ }
150
+
151
+ return blocks.join('\n\n');
152
+ }
153
+
154
+ function buildPersonalStatusJson({ context, snapshot, workflowResult = null }) {
155
+ return {
156
+ context,
157
+ personal: {
158
+ activeAssigned: (snapshot.activeAssigned || []).map(toIssueSummary),
159
+ ready: (snapshot.ready || []).map(toIssueSummary),
160
+ blocked: (snapshot.blocked || []).map(toIssueSummary),
161
+ stale: (snapshot.stale || []).map(toIssueSummary),
162
+ parked: (snapshot.parked || []).map(toIssueSummary),
163
+ recentCompleted: (snapshot.recentCompleted || []).map(toIssueSummary),
164
+ },
165
+ workflow: workflowResult ? {
166
+ stageId: workflowResult.stageId,
167
+ stageName: workflowResult.stageName,
168
+ runCommand: workflowResult.runCommand,
169
+ nextCommand: workflowResult.nextCommand,
170
+ nextStages: workflowResult.nextStages,
171
+ } : null,
172
+ limits: snapshot.limits || [],
173
+ };
174
+ }
175
+
176
+ function formatBoard({ context, snapshot }) {
177
+ return [
178
+ '',
179
+ 'Team Runtime Board',
180
+ `Source: local Beads runtime state`,
181
+ `Branch: ${context.branch}`,
182
+ `Working tree: ${context.workingTree.summary}`,
183
+ '',
184
+ ...buildSection('Active', (snapshot.active || []).map(issue => formatIssue(issue, { includeStatus: true })), { limit: DEFAULT_SECTION_LIMIT }),
185
+ ...buildSection('Ready', (snapshot.ready || []).map(issue => formatIssue(issue)), { limit: DEFAULT_SECTION_LIMIT }),
186
+ ...buildSection('Blocked', (snapshot.blocked || []).map(issue => formatIssue(issue, { includeStatus: true })), { limit: DEFAULT_SECTION_LIMIT }),
187
+ ...buildSection('Stale', (snapshot.stale || []).map(issue => formatIssue(issue, { includeStatus: true })), { limit: DEFAULT_SECTION_LIMIT }),
188
+ ...buildSection('Parked', (snapshot.parked || []).map(issue => formatIssue(issue, { includeStatus: true })), { limit: DEFAULT_SECTION_LIMIT }),
189
+ ...buildSection('Recent Completions', (snapshot.recentCompleted || []).map(issue => formatIssue(issue)), { limit: DEFAULT_SECTION_LIMIT }),
190
+ ...buildSection('Limits', snapshot.limits || []),
191
+ ].join('\n');
192
+ }
193
+
194
+ function buildBoardJson({ context, snapshot }) {
195
+ return {
196
+ context,
197
+ board: {
198
+ active: (snapshot.active || []).map(toIssueSummary),
199
+ ready: (snapshot.ready || []).map(toIssueSummary),
200
+ blocked: (snapshot.blocked || []).map(toIssueSummary),
201
+ stale: (snapshot.stale || []).map(toIssueSummary),
202
+ parked: (snapshot.parked || []).map(toIssueSummary),
203
+ recentCompleted: (snapshot.recentCompleted || []).map(toIssueSummary),
204
+ },
205
+ limits: snapshot.limits || [],
206
+ };
207
+ }
208
+
209
+ module.exports = {
210
+ buildBoardJson,
211
+ buildPersonalStatusJson,
212
+ formatBoard,
213
+ formatRunNextLines,
214
+ formatZeroArgStatus,
215
+ toIssueSummary,
216
+ };