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,66 @@
1
+ 'use strict';
2
+
3
+ const { runIssueOperation } = require('../forge-issues');
4
+ const { SUBCOMMANDS } = require('./_issue');
5
+
6
+ const SUPPORTED_SUBCOMMANDS = ['create', 'list', 'show', 'close', 'update'];
7
+
8
+ function normalizeArgs(args = []) {
9
+ return args.filter(arg => arg !== '--');
10
+ }
11
+
12
+ function formatHelp() {
13
+ return [
14
+ 'Usage: forge issues <subcommand> [...]',
15
+ '',
16
+ 'Supported subcommands:',
17
+ ' create Create an issue through Forge',
18
+ ' list List issues through Forge',
19
+ ' show Show a single issue through Forge',
20
+ ' close Close an issue through Forge',
21
+ ' update Update an issue through Forge',
22
+ ].join('\n');
23
+ }
24
+
25
+ module.exports = {
26
+ name: 'issues',
27
+ description: 'Manage issues through the Forge authority layer',
28
+ usage: 'forge issues <subcommand> [...]',
29
+ // Undocumented back-compat alias for the canonical `forge issue` surface. It stays
30
+ // registered and executable, but `hidden: true` omits it from `forge --help` so the
31
+ // singular `issue` reads as the one canonical issue surface (kernel issue 450c6e34).
32
+ hidden: true,
33
+ flags: {},
34
+ handler: async (args, _flags, projectRoot, opts = {}) => {
35
+ const [subcommand, ...rest] = normalizeArgs(args);
36
+
37
+ if (!subcommand || subcommand === '--help' || subcommand === '-h') {
38
+ return {
39
+ success: true,
40
+ output: formatHelp(),
41
+ };
42
+ }
43
+
44
+ if (!SUPPORTED_SUBCOMMANDS.includes(subcommand)) {
45
+ return {
46
+ success: false,
47
+ error: `Unknown issue subcommand '${subcommand}'.\n\n${formatHelp()}`,
48
+ };
49
+ }
50
+
51
+ // --help for a specific subcommand: print its usage and return BEFORE dispatching
52
+ // to any backend. Otherwise --help is forwarded as an operation arg, which is
53
+ // absorbed by Beads but fails with a bare "Command failed" on the Kernel default
54
+ // (mirrors the short-circuit in lib/commands/_issue.js runIssueSubcommand).
55
+ if (rest.some(arg => arg === '--help' || arg === '-h')) {
56
+ const spec = SUBCOMMANDS[subcommand];
57
+ return {
58
+ success: true,
59
+ output: spec ? `${spec.usage}\n\n${spec.description}` : formatHelp(),
60
+ };
61
+ }
62
+
63
+ const runner = opts.runIssueOperation || runIssueOperation;
64
+ return runner(subcommand, rest, projectRoot, opts);
65
+ },
66
+ };
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ const { createIssueSubcommand } = require('./_issue');
4
+
5
+ module.exports = createIssueSubcommand('lint');
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const { makeAliasCommand } = require('./_issue');
3
+ const { createIssueSubcommand } = require('./_issue');
4
4
 
5
- module.exports = makeAliasCommand('list');
5
+ module.exports = createIssueSubcommand('list');
@@ -0,0 +1,312 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * merge command — opt-in conditional auto-merge.
5
+ *
6
+ * `forge merge --auto <pr>` is the ONLY path by which Forge will merge a PR on
7
+ * its own, and it stays OFF unless the user has explicitly opted in. It reads
8
+ * the `merge.auto` section of `.forge/config.yaml`:
9
+ *
10
+ * merge:
11
+ * auto:
12
+ * enabled: true # default false / absent → strict NO-OP
13
+ * rules: # ALL must pass (see lib/merge-rules.js)
14
+ * - checks_green # or scope it, e.g. for a docs-only task that
15
+ * # may take a coverage dip:
16
+ * # - checks_green: { ignore: ["Coverage"] }
17
+ * - threads_resolved
18
+ * - no_conflicts # recommended: never merge a conflicting branch
19
+ * - not_behind
20
+ * - settle_min: 10
21
+ *
22
+ * Flow: with no config (or `enabled` not true) the command is a strict NO-OP —
23
+ * it prints why and merges nothing, preserving the test-enforced
24
+ * never-auto-merge-by-default invariant. When enabled, it fetches the PR
25
+ * context via `gh`, evaluates the rules with the pure `evaluateMergeRules`, and
26
+ * merges ONLY when every rule passes. Two extra safety layers wrap that decision:
27
+ * a pre-flight guard that no-ops on an already merged/closed PR (idempotent
28
+ * re-runs), and a TOCTOU live re-check that re-fetches and re-evaluates right
29
+ * before merging so a stale snapshot can never merge a since-changed PR. The
30
+ * gh-fetch and the merge action are isolated behind injectable `fetchPrContext`
31
+ * / `mergePr` seams so the decision path is unit-testable without the network.
32
+ *
33
+ * A bring-your-own custom-predicate seam (registered via `forge add`) is a
34
+ * documented follow-up and intentionally NOT wired here. Further follow-ups
35
+ * documented in lib/merge-rules.js: opt-in `auto_update`, required-checks
36
+ * scoping for `checks_green`, a configurable merge `method`, and post-merge
37
+ * branch deletion.
38
+ *
39
+ * @module commands/merge
40
+ */
41
+
42
+ const { execFileSync } = require('node:child_process');
43
+
44
+ const { loadRawConfig } = require('../config-writer');
45
+ const { evaluateMergeRules } = require('../merge-rules');
46
+
47
+ /** Default `gh` runner. Only reached by the default fetch/merge seams (never in unit tests). */
48
+ function defaultGh(args, options = {}) {
49
+ return execFileSync('gh', args, { encoding: 'utf8', ...options }); // NOSONAR S4036 - hardcoded CLI (gh), args array (no shell), developer-tool context
50
+ }
51
+
52
+ /** Parse `gh ... --json` output, returning `null` on any failure (callers fail closed). */
53
+ function ghJson(gh, args) {
54
+ try {
55
+ return JSON.parse(gh(args) || '{}');
56
+ } catch (_err) {
57
+ return null;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Read the unresolved review-thread count via the GraphQL API. `reviewThreads`
63
+ * is not a valid `gh pr view --json` field, so this needs a dedicated query.
64
+ * Returns `undefined` on any failure so `threads_resolved` fails closed.
65
+ */
66
+ function fetchUnresolvedThreadCount(gh, pr) {
67
+ try {
68
+ const repo = ghJson(gh, ['repo', 'view', '--json', 'owner,name']);
69
+ const owner = repo && repo.owner && repo.owner.login;
70
+ const name = repo && repo.name;
71
+ if (!owner || !name) return undefined;
72
+ // Paginate through ALL review threads — a PR can have >100, and the ones on
73
+ // later pages could be the unresolved/newest ones. Stopping at page 1 would
74
+ // both miss them and make a large PR un-mergeable. Loop on the GraphQL cursor
75
+ // until hasNextPage is false; any unreadable page → undefined (fail closed).
76
+ const query = 'query($o:String!,$n:String!,$pr:Int!,$after:String){repository(owner:$o,name:$n)'
77
+ + '{pullRequest(number:$pr){reviewThreads(first:100,after:$after){pageInfo{hasNextPage endCursor}nodes{isResolved isOutdated}}}}}';
78
+ let after = '';
79
+ let count = 0;
80
+ for (let page = 0; page < 100; page += 1) { // 100-page cap = 10k threads backstop
81
+ const args = ['api', 'graphql', '-f', `query=${query}`,
82
+ '-F', `o=${owner}`, '-F', `n=${name}`, '-F', `pr=${Number(pr)}`];
83
+ if (after) args.push('-F', `after=${after}`);
84
+ const data = JSON.parse(gh(args) || '{}');
85
+ const threads = (((data.data || {}).repository || {}).pullRequest || {}).reviewThreads;
86
+ if (!threads) return undefined; // unreadable page → fail closed
87
+ count += (threads.nodes || []).filter((t) => t && t.isResolved === false && t.isOutdated === false).length;
88
+ if (!threads.pageInfo || !threads.pageInfo.hasNextPage) return count;
89
+ after = threads.pageInfo.endCursor;
90
+ if (!after) return undefined; // hasNextPage but no cursor → fail closed
91
+ }
92
+ return undefined; // exceeded the page cap → fail closed rather than undercount
93
+ } catch (_err) {
94
+ return undefined;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Default PR-context fetcher (the network seam). Assembles the shape consumed
100
+ * by `evaluateMergeRules` from `gh`. Anything it cannot read is left absent so
101
+ * the dependent rule fails closed rather than guessing. Fully replaced by
102
+ * `deps.fetchPrContext` in tests.
103
+ *
104
+ * @returns {object} prContext
105
+ */
106
+ function defaultFetchPrContext({ pr, gh = defaultGh, now = Date.now() }) {
107
+ const view = ghJson(gh, ['pr', 'view', String(pr), '--json',
108
+ 'number,state,isDraft,mergeable,mergeStateStatus,statusCheckRollup,reviews,comments,updatedAt']) || {};
109
+
110
+ const rollup = Array.isArray(view.statusCheckRollup) ? view.statusCheckRollup : null;
111
+ const checks = (rollup || []).map((c) => ({
112
+ name: c.name || c.context || '?',
113
+ conclusion: String(c.conclusion || c.state || c.status || ''),
114
+ }));
115
+
116
+ const comments = Array.isArray(view.comments)
117
+ ? view.comments.map((c) => ({
118
+ author: (c.author && c.author.login) || '',
119
+ at: c.createdAt || c.submittedAt || '',
120
+ }))
121
+ : [];
122
+
123
+ const reviews = Array.isArray(view.reviews) ? view.reviews : [];
124
+ const approvals = reviews
125
+ .filter((r) => String(r.state).toUpperCase() === 'APPROVED')
126
+ .map((r) => ({ author: (r.author && r.author.login) || '' }));
127
+
128
+ // Derive from GitHub's mergeStateStatus / mergeable. Only a known set maps to
129
+ // a definite answer; anything else stays undefined so the dependent rule fails
130
+ // closed rather than guessing.
131
+ const mergeStateStatus = String(view.mergeStateStatus || '').toUpperCase();
132
+ const mergeable = String(view.mergeable || '').toUpperCase();
133
+
134
+ let behindBase;
135
+ if (mergeStateStatus === 'BEHIND') behindBase = true;
136
+ else if (['CLEAN', 'UNSTABLE', 'HAS_HOOKS', 'BLOCKED', 'DIRTY'].includes(mergeStateStatus)) behindBase = false;
137
+
138
+ // Conflict status: DIRTY (or mergeable=CONFLICTING) → conflicting; a clean set
139
+ // of states → not conflicting; UNKNOWN / missing / still-computing → undefined.
140
+ let conflicting;
141
+ if (mergeStateStatus === 'DIRTY' || mergeable === 'CONFLICTING') conflicting = true;
142
+ else if (['CLEAN', 'UNSTABLE', 'HAS_HOOKS', 'BLOCKED'].includes(mergeStateStatus)) conflicting = false;
143
+
144
+ const isDraft = typeof view.isDraft === 'boolean' ? view.isDraft : undefined;
145
+ const state = view.state ? String(view.state).toUpperCase() : undefined;
146
+
147
+ const stamps = [
148
+ ...comments.map((c) => c.at),
149
+ ...reviews.map((r) => r.submittedAt || r.createdAt || ''),
150
+ view.updatedAt || '',
151
+ ].map((s) => Date.parse(s)).filter((n) => !Number.isNaN(n));
152
+ const lastActivityAt = stamps.length ? Math.max(...stamps) : undefined;
153
+
154
+ return {
155
+ checks,
156
+ requiredChecksKnown: rollup !== null,
157
+ unresolvedThreads: fetchUnresolvedThreadCount(gh, pr),
158
+ behindBase,
159
+ conflicting,
160
+ isDraft,
161
+ state,
162
+ approvals,
163
+ comments,
164
+ lastActivityAt,
165
+ now,
166
+ };
167
+ }
168
+
169
+ /** Default merge action (squash). Fully replaced by `deps.mergePr` in tests. */
170
+ function defaultMergePr({ pr, gh = defaultGh }) {
171
+ gh(['pr', 'merge', String(pr), '--squash']);
172
+ return { merged: true, method: 'squash' };
173
+ }
174
+
175
+ /**
176
+ * Command handler.
177
+ *
178
+ * @param {string[]} args - Positional + flag args (first positional is the PR).
179
+ * @param {object} _flags - Parsed flags (unused; flags are read from args).
180
+ * @param {string} projectRoot - Project root.
181
+ * @param {object} [deps] - Injected seams for testing: loadConfig, fetchPrContext, mergePr, gh, now.
182
+ * @returns {Promise<object>} result envelope.
183
+ */
184
+ async function handler(args, _flags, projectRoot, deps = {}) {
185
+ const argv = Array.isArray(args) ? args : [];
186
+ const positional = argv.filter((a) => !String(a).startsWith('--'));
187
+ const flags = new Set(argv.filter((a) => String(a).startsWith('--')));
188
+ const pr = positional[0];
189
+ const root = projectRoot || process.cwd();
190
+
191
+ if (!flags.has('--auto')) {
192
+ return { success: false, error: 'Usage: forge merge --auto <pr> (opt-in conditional auto-merge; OFF by default)' };
193
+ }
194
+ if (!pr) {
195
+ return { success: false, error: 'Usage: forge merge --auto <pr>' };
196
+ }
197
+
198
+ const loadConfig = deps.loadConfig || loadRawConfig;
199
+ let config;
200
+ try {
201
+ config = loadConfig(root) || {};
202
+ } catch (err) {
203
+ // A malformed .forge/config.yaml must NOT crash the command — fail closed:
204
+ // refuse to auto-merge and report, rather than throwing past the contract.
205
+ const reason = `Could not read merge config (${err.message}) — refusing to auto-merge (fail-closed).`;
206
+ process.stdout.write(`${reason}\n`);
207
+ return { success: false, merged: false, error: reason };
208
+ }
209
+ const auto = (config.merge && config.merge.auto) || {};
210
+ const enabled = auto.enabled === true;
211
+ const rules = Array.isArray(auto.rules) ? auto.rules : [];
212
+
213
+ // Invariant: absent config or `enabled` not true → strict NO-OP. Forge never
214
+ // auto-merges unless the user has explicitly opted in via .forge/config.yaml.
215
+ if (!enabled) {
216
+ const reason = 'Auto-merge is OPT-IN and OFF by default (merge.auto.enabled is not true in .forge/config.yaml). No action taken.';
217
+ process.stdout.write(`${reason}\n`);
218
+ return { success: true, merged: false, enabled: false, reason };
219
+ }
220
+
221
+ // Opted in but no rules → refuse (fail-closed): an empty ruleset is vacuously
222
+ // "allowed", which would merge unconditionally. Treat that as misconfiguration.
223
+ if (rules.length === 0) {
224
+ const reason = 'merge.auto.enabled is true but no rules are configured — refusing to auto-merge (fail-closed). Add rules under merge.auto.rules.';
225
+ process.stdout.write(`${reason}\n`);
226
+ return { success: false, merged: false, enabled: true, reason };
227
+ }
228
+
229
+ const fetchPrContext = deps.fetchPrContext || defaultFetchPrContext;
230
+ const mergePr = deps.mergePr || defaultMergePr;
231
+ const gh = deps.gh || defaultGh;
232
+
233
+ let prContext;
234
+ try {
235
+ prContext = await fetchPrContext({ pr, projectRoot: root, gh, now: deps.now || Date.now() });
236
+ } catch (err) {
237
+ return { success: false, merged: false, error: `Failed to fetch PR context: ${err.message}` };
238
+ }
239
+
240
+ // Pre-flight: a PR that is already merged or closed is terminal. Re-running the
241
+ // command must be an idempotent NO-OP — never an error and never a second merge
242
+ // attempt. (An absent/unknown state falls through to the fail-closed rules.)
243
+ const prState = prContext && prContext.state ? String(prContext.state).toUpperCase() : '';
244
+ if (prState && prState !== 'OPEN') {
245
+ const reason = `PR #${pr} is ${prState} (not OPEN) — nothing to merge. No action taken.`;
246
+ process.stdout.write(`${reason}\n`);
247
+ return { success: true, merged: false, enabled: true, state: prState, reason };
248
+ }
249
+
250
+ const { allowed, unmet } = evaluateMergeRules(prContext, rules);
251
+
252
+ if (!allowed) {
253
+ process.stdout.write(`Auto-merge conditions NOT met for PR #${pr} — ${unmet.length} unmet rule(s):\n`);
254
+ for (const item of unmet) {
255
+ process.stdout.write(` x ${item.rule} — ${item.reason}\n`);
256
+ }
257
+ return { success: true, merged: false, enabled: true, allowed: false, unmet, reason: 'auto-merge conditions not met' };
258
+ }
259
+
260
+ // TOCTOU guard: PR state can change between the first fetch and the merge — a
261
+ // new comment resets settle_min, a required check regresses, a thread opens.
262
+ // Re-pull LIVE data and re-evaluate immediately before merging so our custom
263
+ // rules (which GitHub's server-side branch protection does NOT enforce) are
264
+ // honored against the freshest possible state, never a stale snapshot.
265
+ let freshContext;
266
+ try {
267
+ freshContext = await fetchPrContext({ pr, projectRoot: root, gh, now: deps.now || Date.now() });
268
+ } catch (err) {
269
+ return { success: false, merged: false, error: `Failed to re-fetch PR context before merge: ${err.message}` };
270
+ }
271
+ // Re-apply the terminal-state guard on the FRESH context: the PR may have been
272
+ // merged or closed between the first fetch and now. Never merge a terminal PR.
273
+ const freshState = freshContext && freshContext.state ? String(freshContext.state).toUpperCase() : '';
274
+ if (freshState && freshState !== 'OPEN') {
275
+ const reason = `PR #${pr} became ${freshState} (not OPEN) before merge — nothing to merge. No action taken.`;
276
+ process.stdout.write(`${reason}\n`);
277
+ return { success: true, merged: false, enabled: true, state: freshState, reason };
278
+ }
279
+ const recheck = evaluateMergeRules(freshContext, rules);
280
+ if (!recheck.allowed) {
281
+ process.stdout.write(`Auto-merge ABORTED for PR #${pr} — state changed since first check; ${recheck.unmet.length} rule(s) now unmet:\n`);
282
+ for (const item of recheck.unmet) {
283
+ process.stdout.write(` x ${item.rule} — ${item.reason}\n`);
284
+ }
285
+ return { success: true, merged: false, enabled: true, allowed: false, unmet: recheck.unmet, reason: 'PR state changed before merge (live re-check failed)' };
286
+ }
287
+
288
+ try {
289
+ const mergeResult = await mergePr({ pr, projectRoot: root, gh });
290
+ process.stdout.write(`All ${rules.length} merge rule(s) passed — merged PR #${pr}.\n`);
291
+ return {
292
+ success: true,
293
+ merged: true,
294
+ enabled: true,
295
+ allowed: true,
296
+ reason: 'all merge rules passed',
297
+ ...(mergeResult && typeof mergeResult === 'object' ? mergeResult : {}),
298
+ };
299
+ } catch (err) {
300
+ return { success: false, merged: false, error: `Merge failed: ${err.message}` };
301
+ }
302
+ }
303
+
304
+ module.exports = {
305
+ name: 'merge',
306
+ description: 'Opt-in conditional auto-merge: merge a PR only when all user-configured rules pass (OFF by default)',
307
+ usage: 'Usage: forge merge --auto <pr>',
308
+ handler,
309
+ // Exported seams for testing / reuse.
310
+ defaultFetchPrContext,
311
+ defaultMergePr,
312
+ };