forge-workflow 0.0.10 → 0.1.0-beta.3

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 (468) 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 +82 -5
  5. package/.forge/hooks/forge-native-hook.js +431 -0
  6. package/.forge/protected-paths.yaml +157 -0
  7. package/AGENTS.md +151 -61
  8. package/CHANGELOG.md +709 -0
  9. package/CLAUDE.md +9 -118
  10. package/QUICKSTART.md +175 -0
  11. package/README.md +275 -365
  12. package/bin/forge-cmd.js +120 -9
  13. package/bin/forge-preflight.js +26 -5
  14. package/bin/forge.js +532 -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/forge/TOOLCHAIN.md +670 -0
  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 +121 -0
  29. package/docs/guides/SUPPORT.md +190 -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 +214 -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/{TOOLCHAIN.md → reference/TOOLCHAIN.md} +62 -47
  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 +155 -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/activation/ensure-forge-home.js +135 -0
  67. package/lib/adapter-cli.js +307 -0
  68. package/lib/adapters/beads-issue-adapter.js +127 -0
  69. package/lib/adapters/beads-kernel-compat.js +1109 -0
  70. package/lib/adapters/greptile-review-adapter.js +141 -0
  71. package/lib/adapters/kernel-issue-adapter.js +101 -0
  72. package/lib/adapters/pr-state-adapter.js +484 -0
  73. package/lib/adoption-profiles.js +139 -0
  74. package/lib/agents/README.md +2 -6
  75. package/lib/agents/claude.plugin.json +3 -8
  76. package/lib/agents/codex.plugin.json +9 -1
  77. package/lib/agents/cursor.plugin.json +2 -6
  78. package/lib/agents/hermes.plugin.json +22 -0
  79. package/lib/agents-config.js +39 -1236
  80. package/lib/audit-evidence.js +282 -0
  81. package/lib/beads-detect.js +60 -0
  82. package/lib/beads-nudge.js +91 -0
  83. package/lib/beads-setup.js +121 -0
  84. package/lib/beads-sync-scaffold.js +25 -101
  85. package/lib/codex-skills.js +51 -1
  86. package/lib/commands/_aliases.js +248 -0
  87. package/lib/commands/_issue.js +780 -77
  88. package/lib/commands/_manifest.js +93 -0
  89. package/lib/commands/_registry.js +99 -34
  90. package/lib/commands/_resolve-command-opts.js +230 -0
  91. package/lib/commands/_serve-security.js +270 -0
  92. package/lib/commands/adapter.js +12 -0
  93. package/lib/commands/add.js +118 -0
  94. package/lib/commands/audit.js +70 -0
  95. package/lib/commands/blocked.js +5 -0
  96. package/lib/commands/board.js +64 -0
  97. package/lib/commands/claim.js +21 -2
  98. package/lib/commands/claims.js +7 -0
  99. package/lib/commands/clean.js +485 -75
  100. package/lib/commands/close.js +2 -2
  101. package/lib/commands/comment.js +5 -0
  102. package/lib/commands/control.js +148 -0
  103. package/lib/commands/create.js +2 -2
  104. package/lib/commands/dev.js +185 -7
  105. package/lib/commands/doc-gate.js +336 -0
  106. package/lib/commands/doctor.js +156 -0
  107. package/lib/commands/explain.js +15 -0
  108. package/lib/commands/export.js +237 -0
  109. package/lib/commands/gate.js +209 -0
  110. package/lib/commands/hooks.js +377 -0
  111. package/lib/commands/inbox.js +118 -0
  112. package/lib/commands/init.js +604 -0
  113. package/lib/commands/insights.js +79 -0
  114. package/lib/commands/issue.js +12 -1
  115. package/lib/commands/issues.js +17 -0
  116. package/lib/commands/lint.js +5 -0
  117. package/lib/commands/list.js +2 -2
  118. package/lib/commands/memory.js +81 -0
  119. package/lib/commands/merge.js +312 -0
  120. package/lib/commands/migrate.js +362 -0
  121. package/lib/commands/new.js +12 -0
  122. package/lib/commands/options.js +241 -0
  123. package/lib/commands/orient.js +13 -0
  124. package/lib/commands/orphans.js +5 -0
  125. package/lib/commands/patch.js +67 -0
  126. package/lib/commands/plan.js +481 -29
  127. package/lib/commands/pr.js +88 -0
  128. package/lib/commands/preflight.js +211 -0
  129. package/lib/commands/prime.js +13 -0
  130. package/lib/commands/push.js +135 -2
  131. package/lib/commands/ready.js +2 -2
  132. package/lib/commands/recall.js +171 -0
  133. package/lib/commands/recap.js +75 -0
  134. package/lib/commands/recommend.js +0 -1
  135. package/lib/commands/release.js +104 -0
  136. package/lib/commands/remember.js +140 -0
  137. package/lib/commands/role.js +99 -0
  138. package/lib/commands/serve.js +581 -0
  139. package/lib/commands/setup.js +900 -971
  140. package/lib/commands/shepherd.js +501 -0
  141. package/lib/commands/ship.js +59 -1
  142. package/lib/commands/show.js +2 -2
  143. package/lib/commands/stage.js +192 -0
  144. package/lib/commands/stale.js +5 -0
  145. package/lib/commands/status.js +158 -21
  146. package/lib/commands/sync.js +34 -46
  147. package/lib/commands/team.js +4 -1
  148. package/lib/commands/test.js +43 -27
  149. package/lib/commands/update.js +2 -2
  150. package/lib/commands/upgrade.js +47 -0
  151. package/lib/commands/validate.js +43 -18
  152. package/lib/commands/worktree.js +362 -99
  153. package/lib/config-writer.js +202 -0
  154. package/lib/control-plane.js +236 -0
  155. package/lib/core/runtime-graph.js +977 -0
  156. package/lib/dep-guard/keyword-ripple.js +2 -2
  157. package/lib/deprecated-sync-cleanup.js +362 -0
  158. package/lib/detect-agent.js +2 -28
  159. package/lib/detect-worktree.js +35 -9
  160. package/lib/doc-gate/declaration.js +177 -0
  161. package/lib/doc-gate/detect.js +289 -0
  162. package/lib/doc-gate/gate.js +375 -0
  163. package/lib/doc-gate/okf-config.js +128 -0
  164. package/lib/doc-gate/okf.js +429 -0
  165. package/lib/docs-command.js +1161 -6
  166. package/lib/forge-issues.js +382 -11
  167. package/lib/forge-lock.js +262 -0
  168. package/lib/gate-events.js +192 -0
  169. package/lib/global-flags.js +104 -0
  170. package/lib/greptile-match.js +7 -63
  171. package/lib/grounding/context-events.js +230 -0
  172. package/lib/grounding/read-first.js +112 -0
  173. package/lib/harness-capability-matrix.js +380 -0
  174. package/lib/hook-global-installer.js +347 -0
  175. package/lib/hook-renderer.js +541 -0
  176. package/lib/inbox.js +391 -0
  177. package/lib/insights.js +397 -0
  178. package/lib/issue-adapter.js +156 -0
  179. package/lib/issue-backend.js +145 -0
  180. package/lib/issue-render.js +220 -0
  181. package/lib/kernel/backing-issue.js +311 -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/owned-kernel.js +43 -0
  192. package/lib/kernel/planning-buckets-schema.js +109 -0
  193. package/lib/kernel/projection-jsonl-writer.js +450 -0
  194. package/lib/kernel/readiness-model.js +329 -0
  195. package/lib/kernel/schema.js +356 -0
  196. package/lib/kernel/sqlite-driver.js +2540 -0
  197. package/lib/kernel/taxonomy-validator.js +394 -0
  198. package/lib/lefthook-check.js +3 -2
  199. package/lib/lefthook-wiring.js +413 -0
  200. package/lib/mcp-config-renderer.js +288 -0
  201. package/lib/memory/graphiti-mcp.js +106 -0
  202. package/lib/memory/router.js +387 -0
  203. package/lib/memory/typed-api.js +102 -0
  204. package/lib/memory-digest.js +195 -0
  205. package/lib/merge-rules.js +395 -0
  206. package/lib/migrate-dry-run.js +466 -0
  207. package/lib/orientation.js +863 -0
  208. package/lib/package-manager-remediation.js +103 -0
  209. package/lib/package-root.js +381 -0
  210. package/lib/patch-intent.js +890 -0
  211. package/lib/plugin-catalog.js +3 -4
  212. package/lib/plugin-manager.js +0 -5
  213. package/lib/pr-bundle.js +186 -0
  214. package/lib/pr-monitor/auto-actions.js +175 -0
  215. package/lib/pr-monitor/differ.js +195 -0
  216. package/lib/pr-monitor/digest.js +206 -0
  217. package/lib/pr-monitor/events.js +0 -0
  218. package/lib/pr-monitor/gather.js +124 -0
  219. package/lib/pr-monitor/journal.js +299 -0
  220. package/lib/pr-monitor/monitor.js +146 -0
  221. package/lib/pr-monitor/render-sticky.js +192 -0
  222. package/lib/pr-monitor/upsert-sticky.js +169 -0
  223. package/lib/pr-monitor/watch-lifecycle.js +95 -0
  224. package/lib/pr-monitor/watch.js +247 -0
  225. package/lib/pr-pull.js +1314 -0
  226. package/lib/pr-shepherd.js +494 -0
  227. package/lib/pr-state-validator.js +59 -0
  228. package/lib/preflight/gates.js +237 -0
  229. package/lib/preflight/runner.js +116 -0
  230. package/lib/project-discovery.js +0 -53
  231. package/lib/project-memory.js +99 -497
  232. package/lib/protected-path-manifest.js +281 -0
  233. package/lib/protected-state-surfaces.js +387 -0
  234. package/lib/release-readiness.js +2105 -0
  235. package/lib/reset.js +59 -45
  236. package/lib/review-adapter.js +68 -0
  237. package/lib/rules-sync.js +260 -0
  238. package/lib/runtime-health.js +241 -20
  239. package/lib/safety-config-renderer.js +268 -0
  240. package/lib/setup-action-log.js +1 -7
  241. package/lib/setup.js +27 -65
  242. package/lib/shell-utils.js +76 -6
  243. package/lib/skills-sync.js +330 -0
  244. package/lib/smart-status/scoring.js +17 -3
  245. package/lib/status/beads-snapshot.js +45 -2
  246. package/lib/status/presenter.js +169 -18
  247. package/lib/status/snapshot.js +186 -0
  248. package/lib/sync-backend.js +202 -0
  249. package/lib/untrusted-content.js +52 -0
  250. package/lib/upgrade-safety.js +251 -0
  251. package/lib/workflow/enforce-stage.js +351 -45
  252. package/lib/workflow/stage-transition.js +115 -0
  253. package/lib/workflow/stages.js +30 -6
  254. package/lib/workflow/state-manager.js +11 -22
  255. package/lib/workflow/state.js +23 -1
  256. package/lib/workflow-profiles.js +17 -5
  257. package/package.json +37 -35
  258. package/rules/documentation.md +19 -0
  259. package/rules/kernel-tracking.md +26 -0
  260. package/rules/security.md +22 -0
  261. package/rules/tdd.md +20 -0
  262. package/rules/workflow.md +27 -0
  263. package/scripts/auto-backing-issue.js +47 -0
  264. package/scripts/beads-context.sh +81 -57
  265. package/scripts/beads-upgrade-smoke.sh +24 -3
  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.sh +22 -3
  272. package/scripts/file-index.sh +3 -0
  273. package/scripts/forge-team/lib/claim.sh +34 -18
  274. package/scripts/forge-team/lib/dashboard.sh +61 -86
  275. package/scripts/forge-team/lib/epic.sh +99 -263
  276. package/scripts/forge-team/lib/hooks.sh +26 -28
  277. package/scripts/forge-team/lib/identity.sh +4 -4
  278. package/scripts/forge-team/lib/sync-github.sh +49 -84
  279. package/scripts/forge-team/lib/verify.sh +93 -83
  280. package/scripts/forge-team/lib/workload.sh +41 -65
  281. package/scripts/forge-team/tests/claim.test.sh +25 -19
  282. package/scripts/forge-team/tests/dashboard.test.sh +31 -46
  283. package/scripts/forge-team/tests/epic.test.sh +52 -71
  284. package/scripts/forge-team/tests/hooks.test.sh +38 -50
  285. package/scripts/forge-team/tests/identity.test.sh +3 -3
  286. package/scripts/forge-team/tests/integration.test.sh +44 -66
  287. package/scripts/forge-team/tests/sync-github.test.sh +50 -83
  288. package/scripts/forge-team/tests/verify.test.sh +37 -46
  289. package/scripts/forge-team/tests/workflow-integration.test.sh +4 -4
  290. package/scripts/forge-team/tests/workload.test.sh +32 -66
  291. package/scripts/gen-command-manifest.js +153 -0
  292. package/scripts/gen-embedded-assets.mjs +129 -0
  293. package/scripts/install.ps1 +139 -0
  294. package/scripts/install.sh +268 -0
  295. package/scripts/lib/release-asset.mjs +84 -0
  296. package/scripts/parity-check.mjs +145 -0
  297. package/scripts/parity-check.test.mjs +58 -0
  298. package/scripts/pin-agentic-workflow-images.js +112 -0
  299. package/scripts/pr-auto-actions.js +93 -0
  300. package/scripts/pr-coordinator.sh +3 -0
  301. package/scripts/pr-verdict-label.js +50 -0
  302. package/scripts/preflight-sonar.eslint.config.mjs +44 -0
  303. package/scripts/preflight.sh +21 -94
  304. package/scripts/protected-state-check.js +104 -0
  305. package/scripts/smart-status.sh +60 -57
  306. package/scripts/spikes/config-race-bench.js +111 -0
  307. package/scripts/spikes/harness-capability-matrix.js +13 -0
  308. package/scripts/spikes/patch-anchor-stability-bench.js +125 -0
  309. package/scripts/spikes/protected-path-manifest.js +20 -0
  310. package/scripts/spikes/skill-auto-invoke-parity.js +292 -0
  311. package/scripts/sync-agent-skills.js +62 -0
  312. package/scripts/sync-utils.sh +3 -0
  313. package/scripts/test-ci-shard.js +13 -6
  314. package/scripts/test.js +95 -12
  315. package/skills/claim-safety/SKILL.md +102 -0
  316. package/skills/claim-safety/evals/evals.json +46 -0
  317. package/{.github/prompts/dev.prompt.md → skills/dev/SKILL.md} +44 -50
  318. package/skills/dev/evals/evals.json +50 -0
  319. package/skills/hermes-forge/SKILL.md +185 -0
  320. package/skills/hermes-forge/evals/evals.json +46 -0
  321. package/skills/issue-basics/SKILL.md +111 -0
  322. package/skills/issue-basics/evals/evals.json +46 -0
  323. package/skills/kernel/SKILL.md +166 -0
  324. package/skills/kernel/evals/evals.json +50 -0
  325. package/skills/memory/SKILL.md +102 -0
  326. package/skills/parallel-deep-research/SKILL.md +14 -11
  327. package/skills/parallel-deep-research/evals/evals.json +11 -27
  328. package/{.github/prompts/plan.prompt.md → skills/plan/SKILL.md} +132 -157
  329. package/skills/plan/evals/evals.json +42 -0
  330. package/skills/research/SKILL.md +195 -0
  331. package/skills/research/evals/evals.json +42 -0
  332. package/{.github/prompts/review.prompt.md → skills/review/SKILL.md} +98 -62
  333. package/skills/review/evals/evals.json +42 -0
  334. package/skills/rollback/SKILL.md +110 -0
  335. package/skills/rollback/evals/evals.json +46 -0
  336. package/skills/rollback/references/methods.md +204 -0
  337. package/{.cursor/commands/rollback.md → skills/rollback/references/workflow-integration.md} +10 -284
  338. package/skills/shepherd/SKILL.md +66 -0
  339. package/skills/shepherd/evals/evals.json +42 -0
  340. package/{.github/prompts/ship.prompt.md → skills/ship/SKILL.md} +81 -45
  341. package/skills/ship/evals/evals.json +42 -0
  342. package/skills/smith/SKILL.md +142 -0
  343. package/skills/smith/evals/evals.json +46 -0
  344. package/skills/smith/references/autonomy-and-gates.md +94 -0
  345. package/{.github/prompts/sonarcloud.prompt.md → skills/sonarcloud/SKILL.md} +14 -3
  346. package/skills/sonarcloud/evals/evals.json +46 -0
  347. package/skills/sonarcloud-analysis/SKILL.md +18 -13
  348. package/skills/sonarcloud-analysis/evals/evals.json +11 -15
  349. package/{.github/prompts/status.prompt.md → skills/status/SKILL.md} +20 -10
  350. package/skills/status/evals/evals.json +50 -0
  351. package/skills/triage-ready/SKILL.md +121 -0
  352. package/skills/triage-ready/evals/evals.json +42 -0
  353. package/{.github/prompts/validate.prompt.md → skills/validate/SKILL.md} +52 -29
  354. package/skills/validate/evals/evals.json +42 -0
  355. package/skills/verify/SKILL.md +299 -0
  356. package/skills/verify/evals/evals.json +50 -0
  357. package/.claude/commands/dev.md +0 -345
  358. package/.claude/commands/plan.md +0 -566
  359. package/.claude/commands/premerge.md +0 -186
  360. package/.claude/commands/research.md +0 -42
  361. package/.claude/commands/review.md +0 -451
  362. package/.claude/commands/rollback.md +0 -721
  363. package/.claude/commands/ship.md +0 -213
  364. package/.claude/commands/sonarcloud.md +0 -152
  365. package/.claude/commands/status.md +0 -90
  366. package/.claude/commands/validate.md +0 -288
  367. package/.claude/commands/verify.md +0 -269
  368. package/.claude/rules/workflow.md +0 -121
  369. package/.cline/workflows/dev.md +0 -342
  370. package/.cline/workflows/plan.md +0 -563
  371. package/.cline/workflows/premerge.md +0 -183
  372. package/.cline/workflows/research.md +0 -39
  373. package/.cline/workflows/review.md +0 -448
  374. package/.cline/workflows/rollback.md +0 -718
  375. package/.cline/workflows/ship.md +0 -210
  376. package/.cline/workflows/sonarcloud.md +0 -146
  377. package/.cline/workflows/status.md +0 -87
  378. package/.cline/workflows/validate.md +0 -285
  379. package/.cline/workflows/verify.md +0 -266
  380. package/.codex/config.toml +0 -11
  381. package/.codex/skills/dev/SKILL.md +0 -345
  382. package/.codex/skills/plan/SKILL.md +0 -566
  383. package/.codex/skills/premerge/SKILL.md +0 -186
  384. package/.codex/skills/research/SKILL.md +0 -42
  385. package/.codex/skills/review/SKILL.md +0 -451
  386. package/.codex/skills/rollback/SKILL.md +0 -721
  387. package/.codex/skills/ship/SKILL.md +0 -213
  388. package/.codex/skills/sonarcloud/SKILL.md +0 -149
  389. package/.codex/skills/status/SKILL.md +0 -90
  390. package/.codex/skills/validate/SKILL.md +0 -288
  391. package/.codex/skills/verify/SKILL.md +0 -269
  392. package/.cursor/commands/dev.md +0 -342
  393. package/.cursor/commands/plan.md +0 -563
  394. package/.cursor/commands/premerge.md +0 -183
  395. package/.cursor/commands/research.md +0 -39
  396. package/.cursor/commands/review.md +0 -448
  397. package/.cursor/commands/ship.md +0 -210
  398. package/.cursor/commands/sonarcloud.md +0 -146
  399. package/.cursor/commands/status.md +0 -87
  400. package/.cursor/commands/validate.md +0 -285
  401. package/.cursor/commands/verify.md +0 -266
  402. package/.cursorrules +0 -149
  403. package/.github/prompts/premerge.prompt.md +0 -188
  404. package/.github/prompts/research.prompt.md +0 -44
  405. package/.github/prompts/rollback.prompt.md +0 -723
  406. package/.github/prompts/verify.prompt.md +0 -271
  407. package/.github/workflows/beads-to-github.yml +0 -89
  408. package/.github/workflows/github-to-beads.yml +0 -100
  409. package/.kilocode/workflows/dev.md +0 -346
  410. package/.kilocode/workflows/plan.md +0 -567
  411. package/.kilocode/workflows/premerge.md +0 -187
  412. package/.kilocode/workflows/research.md +0 -43
  413. package/.kilocode/workflows/review.md +0 -452
  414. package/.kilocode/workflows/rollback.md +0 -722
  415. package/.kilocode/workflows/ship.md +0 -214
  416. package/.kilocode/workflows/sonarcloud.md +0 -150
  417. package/.kilocode/workflows/status.md +0 -91
  418. package/.kilocode/workflows/validate.md +0 -289
  419. package/.kilocode/workflows/verify.md +0 -270
  420. package/.opencode/commands/dev.md +0 -345
  421. package/.opencode/commands/plan.md +0 -566
  422. package/.opencode/commands/premerge.md +0 -186
  423. package/.opencode/commands/research.md +0 -42
  424. package/.opencode/commands/review.md +0 -451
  425. package/.opencode/commands/rollback.md +0 -721
  426. package/.opencode/commands/ship.md +0 -213
  427. package/.opencode/commands/sonarcloud.md +0 -149
  428. package/.opencode/commands/status.md +0 -90
  429. package/.opencode/commands/validate.md +0 -288
  430. package/.opencode/commands/verify.md +0 -269
  431. package/.roo/commands/dev.md +0 -346
  432. package/.roo/commands/plan.md +0 -567
  433. package/.roo/commands/premerge.md +0 -187
  434. package/.roo/commands/research.md +0 -43
  435. package/.roo/commands/review.md +0 -452
  436. package/.roo/commands/rollback.md +0 -722
  437. package/.roo/commands/ship.md +0 -214
  438. package/.roo/commands/sonarcloud.md +0 -150
  439. package/.roo/commands/status.md +0 -91
  440. package/.roo/commands/validate.md +0 -289
  441. package/.roo/commands/verify.md +0 -270
  442. package/docs/BEADS_GITHUB_SYNC.md +0 -281
  443. package/docs/GREPTILE_SETUP.md +0 -400
  444. package/docs/MANUAL_REVIEW_GUIDE.md +0 -106
  445. package/docs/SETUP.md +0 -663
  446. package/docs/VALIDATION.md +0 -363
  447. package/lib/agents/cline.plugin.json +0 -29
  448. package/lib/agents/copilot.plugin.json +0 -24
  449. package/lib/agents/kilocode.plugin.json +0 -22
  450. package/lib/agents/opencode.plugin.json +0 -23
  451. package/lib/agents/roo.plugin.json +0 -30
  452. package/lib/beads-bootstrap.js +0 -225
  453. package/lib/beads-health-check.js +0 -188
  454. package/lib/commands/commands-reset.js +0 -147
  455. package/opencode.json +0 -67
  456. package/scripts/beads-context.test.js +0 -584
  457. package/scripts/github-beads-sync/comment.mjs +0 -64
  458. package/scripts/github-beads-sync/config.mjs +0 -148
  459. package/scripts/github-beads-sync/github-api.mjs +0 -131
  460. package/scripts/github-beads-sync/index.mjs +0 -356
  461. package/scripts/github-beads-sync/label-mapper.mjs +0 -54
  462. package/scripts/github-beads-sync/mapping.mjs +0 -132
  463. package/scripts/github-beads-sync/reverse-sync-cli.mjs +0 -31
  464. package/scripts/github-beads-sync/reverse-sync.mjs +0 -162
  465. package/scripts/github-beads-sync/run-bd.mjs +0 -161
  466. package/scripts/github-beads-sync/sanitize.mjs +0 -121
  467. package/scripts/github-beads-sync.config.json +0 -26
  468. package/scripts/sync-commands.js +0 -600
@@ -2,12 +2,15 @@
2
2
  # scripts/forge-team/lib/epic.sh — Epic rollup view
3
3
  #
4
4
  # Shows epic progress with per-developer breakdown and blocked issue tracking.
5
+ # All data comes from a SINGLE `forge issue children <id> --json` call: the kernel
6
+ # computes the rollup (done-only percentage, per-status counts) and emits each child
7
+ # with its assignee + blocked_by, so this layer only renders.
5
8
  #
6
9
  # Functions:
7
10
  # cmd_epic — Top-level dispatcher entry point
8
11
  #
9
12
  # Env overrides (for testing):
10
- # BD_CMD — Path to bd binary
13
+ # FORGE_CMD — Path to forge binary (default: forge)
11
14
  #
12
15
  # This file does NOT set errexit/pipefail — callers manage their own shell options.
13
16
 
@@ -19,85 +22,10 @@ _EPIC_LIB_LOADED=1
19
22
 
20
23
  # ── Internal helpers ─────────────────────────────────────────────────────
21
24
 
22
- # _epic_get_bd Returns the bd command path
23
- _epic_get_bd() {
24
- printf '%s' "${BD_CMD:-bd}"
25
- }
26
-
27
- # _epic_parse_blocks <bd-show-output>
28
- # Extracts child issue IDs from the BLOCKS section.
29
- # Each line in BLOCKS looks like: ← ✓ forge-child1: Child 1 (closed)
30
- # Returns one ID per line.
31
- _epic_parse_blocks() {
32
- local bd_output="$1"
33
- local in_blocks=0
34
-
35
- while IFS= read -r line; do
36
- if [[ "$line" == "BLOCKS" ]]; then
37
- in_blocks=1
38
- continue
39
- fi
40
- # Stop at next section header (non-indented, non-empty line after BLOCKS)
41
- if [[ $in_blocks -eq 1 ]]; then
42
- if [[ -z "$line" ]]; then
43
- continue
44
- fi
45
- if [[ "$line" =~ ^[A-Z] ]]; then
46
- break
47
- fi
48
- # Extract issue ID: matches forge-XXXX pattern after the arrow+status marker
49
- local child_id
50
- child_id="$(printf '%s' "$line" | sed -n 's/.*← [^ ]* \([a-z0-9-]*\):.*/\1/p')"
51
- if [[ -n "$child_id" ]]; then
52
- printf '%s\n' "$child_id"
53
- fi
54
- fi
55
- done <<< "$bd_output"
56
- }
57
-
58
- # _epic_get_child_info <child-id>
59
- # Returns: id|status|owner|title|blocked_by
60
- _epic_get_child_info() {
61
- local child_id="$1"
62
- local bd_cmd
63
- bd_cmd="$(_epic_get_bd)"
64
-
65
- local child_output
66
- child_output="$("$bd_cmd" show "$child_id" 2>/dev/null)" || return 1
67
-
68
- local first_line
69
- first_line="$(printf '%s' "$child_output" | head -1)"
70
-
71
- # Parse status from the first character/marker
72
- local status="open"
73
- if [[ "$first_line" == *"CLOSED"* ]] || [[ "$first_line" == *"✓"* ]]; then
74
- status="closed"
75
- elif [[ "$first_line" == *"IN_PROGRESS"* ]] || [[ "$first_line" == *"◐"* ]]; then
76
- status="in_progress"
77
- fi
78
-
79
- # Parse title — between · and [
80
- local title
81
- title="$(printf '%s' "$first_line" | sed -n 's/^[^ ]* [^ ]* · \(.*\) \[.*/\1/p')"
82
- if [[ -z "$title" ]]; then
83
- title="$child_id"
84
- fi
85
-
86
- # Parse owner from "Owner: xxx" line
87
- local owner=""
88
- owner="$(printf '%s' "$child_output" | sed -n 's/^Owner: *//p' | head -1)"
89
-
90
- # Check for BLOCKED_BY section
91
- local blocked_by=""
92
- blocked_by="$(printf '%s' "$child_output" | sed -n '/^BLOCKED_BY$/,/^[A-Z]/{ /^ /{ s/.*→ \([a-z0-9-]*\):.*/\1/p; }; }')"
93
-
94
- printf '%s|%s|%s|%s|%s' "$child_id" "$status" "$owner" "$title" "$blocked_by"
95
- }
96
-
97
- # _epic_status_icon <status>
25
+ # _epic_status_icon <status> (kernel status vocabulary: open|in_progress|review|done|cancelled)
98
26
  _epic_status_icon() {
99
27
  case "$1" in
100
- closed) printf '%s' "✓" ;;
28
+ done) printf '%s' "✓" ;;
101
29
  in_progress) printf '%s' "◐" ;;
102
30
  *) printf '%s' "○" ;;
103
31
  esac
@@ -115,35 +43,43 @@ cmd_epic() {
115
43
  return 1
116
44
  fi
117
45
 
118
- local bd_cmd
119
- bd_cmd="$(_epic_get_bd)"
46
+ local forge_cmd
47
+ forge_cmd="${FORGE_CMD:-forge}"
120
48
 
121
- # 1. Get epic details
122
- local epic_output
123
- epic_output="$("$bd_cmd" show "$issue_id" 2>/dev/null)" || {
49
+ # 1. Single query: epic header + direct children + kernel-computed rollup. A missing
50
+ # or invalid id makes `forge issue children` fail (empty stdout) — treat as not found.
51
+ local response
52
+ response="$("$forge_cmd" issue children "$issue_id" --json 2>/dev/null)" || {
124
53
  echo "ERROR: Could not fetch epic $issue_id" >&2
125
54
  return 1
126
55
  }
127
-
128
- # Parse epic title from first line
129
- local epic_first_line
130
- epic_first_line="$(printf '%s' "$epic_output" | head -1)"
131
- local epic_title
132
- epic_title="$(printf '%s' "$epic_first_line" | sed -n 's/^[^ ]* [^ ]* · \(.*\) \[.*/\1/p')"
133
- if [[ -z "$epic_title" ]]; then
134
- epic_title="$issue_id"
56
+ if [[ -z "$response" ]]; then
57
+ echo "ERROR: Could not fetch epic $issue_id" >&2
58
+ return 1
135
59
  fi
136
60
 
137
- # 2. Parse BLOCKS section to find child issues
138
- local children_ids
139
- children_ids="$(_epic_parse_blocks "$epic_output")"
140
-
141
- # Handle empty epic
142
- if [[ -z "$children_ids" ]]; then
61
+ # 2. Epic title (fall back to the id when the header carries no title).
62
+ local epic_title
63
+ epic_title="$(printf '%s' "$response" | jq -r '.data.epic.title // empty' | tr -d '\r')"
64
+ [[ -z "$epic_title" ]] && epic_title="$issue_id"
65
+
66
+ # 3. Rollup counts (kernel-computed). open_count keeps the historical invariant
67
+ # total = done + in_progress + open_count (the catch-all bucket also absorbs the
68
+ # kernel review/cancelled statuses), so downstream consumers see a stable shape.
69
+ local total done_count in_progress_count open_count percentage
70
+ total="$(printf '%s' "$response" | jq -r '.data.rollup.total // 0' | tr -d '\r')"
71
+ done_count="$(printf '%s' "$response" | jq -r '.data.rollup.done // 0' | tr -d '\r')"
72
+ in_progress_count="$(printf '%s' "$response" | jq -r '.data.rollup.in_progress // 0' | tr -d '\r')"
73
+ percentage="$(printf '%s' "$response" | jq -r '.data.rollup.percentage // 0' | tr -d '\r')"
74
+ open_count=$((total - done_count - in_progress_count))
75
+
76
+ # 4. Empty epic → no children.
77
+ if [[ "$total" -eq 0 ]]; then
143
78
  if [[ "$format_flag" == "--format=json" ]]; then
144
- cat <<ENDJSON
145
- {"epic_id":"$issue_id","title":"$epic_title","total":0,"done":0,"in_progress":0,"open_count":0,"percentage":0,"children":[],"by_developer":{},"blocked":[]}
146
- ENDJSON
79
+ # Build via jq --arg so a title containing quotes/backslashes stays valid
80
+ # JSON (parity with the non-empty path below).
81
+ jq -cn --arg epic_id "$issue_id" --arg title "$epic_title" \
82
+ '{epic_id:$epic_id,title:$title,total:0,done:0,in_progress:0,open_count:0,percentage:0,children:[],by_developer:{},blocked:[]}'
147
83
  return 0
148
84
  fi
149
85
  echo "Epic: $issue_id — $epic_title"
@@ -151,181 +87,81 @@ ENDJSON
151
87
  return 0
152
88
  fi
153
89
 
154
- # 3. For each child: get status, assignee
155
- local total=0
156
- local done_count=0
157
- local in_progress_count=0
158
- local open_count=0
159
- local blocked_list=""
160
-
161
- # Arrays for child data (using indexed approach for bash 3 compat)
162
- local child_lines=""
163
- # Developer tracking: accumulate "dev:status" pairs
164
- local dev_entries=""
165
-
166
- while IFS= read -r child_id; do
167
- [[ -z "$child_id" ]] && continue
168
-
169
- local info
170
- info="$(_epic_get_child_info "$child_id")" || continue
171
-
172
- local c_id c_status c_owner c_title c_blocked
173
- IFS='|' read -r c_id c_status c_owner c_title c_blocked <<< "$info"
174
-
175
- total=$((total + 1))
176
-
177
- case "$c_status" in
178
- closed) done_count=$((done_count + 1)) ;;
179
- in_progress) in_progress_count=$((in_progress_count + 1)) ;;
180
- *) open_count=$((open_count + 1)) ;;
181
- esac
182
-
183
- # Track blocked children
184
- if [[ -n "$c_blocked" ]]; then
185
- if [[ -n "$blocked_list" ]]; then
186
- blocked_list="$blocked_list"$'\n'"$c_id blocked by $c_blocked"
187
- else
188
- blocked_list="$c_id blocked by $c_blocked"
189
- fi
190
- fi
191
-
192
- # Build child line for display
193
- local icon
194
- icon="$(_epic_status_icon "$c_status")"
195
- local display_owner="${c_owner:-unassigned}"
196
- child_lines="${child_lines} $icon $c_id [$display_owner] $c_title ($c_status)"$'\n'
197
-
198
- # Track developer entries
199
- if [[ -n "$c_owner" ]]; then
200
- dev_entries="${dev_entries}${c_owner}:${c_status}"$'\n'
201
- fi
202
- done <<< "$children_ids"
203
-
204
- # 4. Calculate completion percentage
205
- local percentage=0
206
- if [[ $total -gt 0 ]]; then
207
- percentage=$(( (done_count * 100) / total ))
208
- fi
209
-
210
- # 5. Build per-developer breakdown
211
- # Collect unique developers
212
- local devs=""
213
- while IFS= read -r entry; do
214
- [[ -z "$entry" ]] && continue
215
- local dev="${entry%%:*}"
216
- if [[ -z "$devs" ]] || ! printf '%s' "$devs" | grep -qxF "$dev"; then
217
- if [[ -n "$devs" ]]; then
218
- devs="$devs"$'\n'"$dev"
219
- else
220
- devs="$dev"
221
- fi
222
- fi
223
- done <<< "$dev_entries"
224
-
225
- # JSON output
90
+ # 5. JSON output one jq transform from the kernel response. Preserves the historical
91
+ # cmd_epic shape (epic_id,title,total,done,in_progress,open_count,percentage,
92
+ # children,by_developer,blocked). Unassigned children are excluded from by_developer
93
+ # (matches the prior behavior), and per-dev open is the same total-done-in_progress
94
+ # catch-all.
226
95
  if [[ "$format_flag" == "--format=json" ]]; then
227
- local children_json="["
228
- local first_child=1
229
- while IFS= read -r child_id; do
230
- [[ -z "$child_id" ]] && continue
231
- local info
232
- info="$(_epic_get_child_info "$child_id")" || continue
233
- local c_id c_status c_owner c_title c_blocked
234
- IFS='|' read -r c_id c_status c_owner c_title c_blocked <<< "$info"
235
-
236
- if [[ $first_child -eq 0 ]]; then
237
- children_json="$children_json,"
238
- fi
239
- first_child=0
240
- children_json="$children_json{\"id\":\"$c_id\",\"status\":\"$c_status\",\"owner\":\"$c_owner\",\"title\":\"$c_title\",\"blocked_by\":\"$c_blocked\"}"
241
- done <<< "$children_ids"
242
- children_json="$children_json]"
243
-
244
- local dev_json="{"
245
- local first_dev=1
246
- while IFS= read -r dev; do
247
- [[ -z "$dev" ]] && continue
248
- local d_done=0 d_in_progress=0 d_open=0 d_total=0
249
- while IFS= read -r entry; do
250
- [[ -z "$entry" ]] && continue
251
- local e_dev="${entry%%:*}"
252
- local e_status="${entry#*:}"
253
- if [[ "$e_dev" == "$dev" ]]; then
254
- d_total=$((d_total + 1))
255
- case "$e_status" in
256
- closed) d_done=$((d_done + 1)) ;;
257
- in_progress) d_in_progress=$((d_in_progress + 1)) ;;
258
- *) d_open=$((d_open + 1)) ;;
259
- esac
260
- fi
261
- done <<< "$dev_entries"
262
-
263
- if [[ $first_dev -eq 0 ]]; then
264
- dev_json="$dev_json,"
265
- fi
266
- first_dev=0
267
- dev_json="$dev_json\"$dev\":{\"total\":$d_total,\"done\":$d_done,\"in_progress\":$d_in_progress,\"open\":$d_open}"
268
- done <<< "$devs"
269
- dev_json="$dev_json}"
270
-
271
- local blocked_json="["
272
- if [[ -n "$blocked_list" ]]; then
273
- local first_blocked=1
274
- while IFS= read -r bline; do
275
- [[ -z "$bline" ]] && continue
276
- if [[ $first_blocked -eq 0 ]]; then
277
- blocked_json="$blocked_json,"
278
- fi
279
- first_blocked=0
280
- blocked_json="$blocked_json\"$bline\""
281
- done <<< "$blocked_list"
282
- fi
283
- blocked_json="$blocked_json]"
284
-
285
- printf '{"epic_id":"%s","title":"%s","total":%d,"done":%d,"in_progress":%d,"open_count":%d,"percentage":%d,"children":%s,"by_developer":%s,"blocked":%s}\n' \
286
- "$issue_id" "$epic_title" "$total" "$done_count" "$in_progress_count" "$open_count" "$percentage" \
287
- "$children_json" "$dev_json" "$blocked_json"
96
+ printf '%s' "$response" | jq -c \
97
+ --arg epic_id "$issue_id" \
98
+ --arg title "$epic_title" '
99
+ (.data.children // []) as $children
100
+ | {
101
+ epic_id: $epic_id,
102
+ title: $title,
103
+ total: (.data.rollup.total // 0),
104
+ done: (.data.rollup.done // 0),
105
+ in_progress: (.data.rollup.in_progress // 0),
106
+ open_count: ((.data.rollup.total // 0) - (.data.rollup.done // 0) - (.data.rollup.in_progress // 0)),
107
+ percentage: (.data.rollup.percentage // 0),
108
+ children: [ $children[] | {
109
+ id: .id,
110
+ status: .status,
111
+ owner: (.assignee // ""),
112
+ title: (.title // .id),
113
+ blocked_by: ((.blocked_by // []) | join(","))
114
+ } ],
115
+ by_developer: (
116
+ [ $children[] | select((.assignee // "") != "") ]
117
+ | group_by(.assignee)
118
+ | map(
119
+ (.[0].assignee) as $dev
120
+ | length as $t
121
+ | ([.[] | select(.status == "done")] | length) as $d
122
+ | ([.[] | select(.status == "in_progress")] | length) as $ip
123
+ | { key: $dev, value: { total: $t, done: $d, in_progress: $ip, open: ($t - $d - $ip) } }
124
+ )
125
+ | from_entries
126
+ ),
127
+ blocked: [ $children[] | select(.blocked == true) | "\(.id) blocked by \((.blocked_by // []) | join(","))" ]
128
+ }' | tr -d '\r'
288
129
  return 0
289
130
  fi
290
131
 
291
- # Text output
132
+ # 6. Text output.
292
133
  echo "Epic: $issue_id — $epic_title"
293
134
  echo "Progress: $done_count/$total ($percentage%)"
294
- printf '%s' "$child_lines"
135
+ while IFS=$'\t' read -r c_id c_status c_owner c_title; do
136
+ [[ -z "$c_id" ]] && continue
137
+ local icon
138
+ icon="$(_epic_status_icon "$c_status")"
139
+ echo " $icon $c_id [${c_owner:-unassigned}] $c_title ($c_status)"
140
+ done < <(printf '%s' "$response" | jq -r '.data.children[] | [.id, .status, (.assignee // ""), (.title // .id)] | @tsv' | tr -d '\r')
295
141
 
296
142
  echo ""
297
143
  echo "By developer:"
298
- while IFS= read -r dev; do
299
- [[ -z "$dev" ]] && continue
300
- local d_done=0 d_in_progress=0 d_open=0 d_total=0
301
- while IFS= read -r entry; do
302
- [[ -z "$entry" ]] && continue
303
- local e_dev="${entry%%:*}"
304
- local e_status="${entry#*:}"
305
- if [[ "$e_dev" == "$dev" ]]; then
306
- d_total=$((d_total + 1))
307
- case "$e_status" in
308
- closed) d_done=$((d_done + 1)) ;;
309
- in_progress) d_in_progress=$((d_in_progress + 1)) ;;
310
- *) d_open=$((d_open + 1)) ;;
311
- esac
312
- fi
313
- done <<< "$dev_entries"
314
-
315
- local dev_parts=""
316
- dev_parts="$d_done/$d_total done"
317
- [[ $d_in_progress -gt 0 ]] && dev_parts="$dev_parts, $d_in_progress in progress"
318
- [[ $d_open -gt 0 ]] && dev_parts="$dev_parts, $d_open open"
319
- echo " $dev: $dev_parts"
320
- done <<< "$devs"
144
+ printf '%s' "$response" | jq -r '
145
+ [ (.data.children // [])[] | select((.assignee // "") != "") ]
146
+ | group_by(.assignee)
147
+ | map(
148
+ (.[0].assignee) as $dev
149
+ | length as $t
150
+ | ([.[] | select(.status == "done")] | length) as $d
151
+ | ([.[] | select(.status == "in_progress")] | length) as $ip
152
+ | ($t - $d - $ip) as $op
153
+ | " \($dev): \($d)/\($t) done"
154
+ + (if $ip > 0 then ", \($ip) in progress" else "" end)
155
+ + (if $op > 0 then ", \($op) open" else "" end)
156
+ )
157
+ | .[]' | tr -d '\r'
321
158
 
322
159
  echo ""
323
- if [[ -n "$blocked_list" ]]; then
160
+ local blocked_lines
161
+ blocked_lines="$(printf '%s' "$response" | jq -r '.data.children[] | select(.blocked == true) | " \(.id) blocked by \((.blocked_by // []) | join(","))"' | tr -d '\r')"
162
+ if [[ -n "$blocked_lines" ]]; then
324
163
  echo "Blocked:"
325
- while IFS= read -r bline; do
326
- [[ -z "$bline" ]] && continue
327
- echo " $bline"
328
- done <<< "$blocked_list"
164
+ printf '%s\n' "$blocked_lines"
329
165
  else
330
166
  echo "Blocked: none"
331
167
  fi
@@ -8,8 +8,8 @@
8
8
  #
9
9
  # Env overrides (for testing):
10
10
  # GH_CMD — Path to gh binary (default: gh)
11
- # BD_CMD — Path to bd binary (default: bd)
12
- # BEADS_ROOT — Path to .beads/ parent directory (default: .)
11
+ # FORGE_CMD — Path to forge binary (default: forge)
12
+ # FORGE_ROOT — Path to .forge/ parent directory (default: .)
13
13
  #
14
14
  # This file does NOT set errexit/pipefail — callers manage their own shell options.
15
15
 
@@ -56,11 +56,11 @@ _hooks_warn() {
56
56
  }
57
57
 
58
58
  # ── _check_auto_sync_enabled ─────────────────────────────────────────────
59
- # Reads .beads/config.yaml for team.auto-sync setting.
59
+ # Reads .forge/config.yaml for the team.auto-sync setting.
60
60
  # Returns 0 if enabled (default), 1 if disabled.
61
61
  _check_auto_sync_enabled() {
62
- local beads_root="${BEADS_ROOT:-.}"
63
- local config_file="$beads_root/.beads/config.yaml"
62
+ local forge_root="${FORGE_ROOT:-.}"
63
+ local config_file="$forge_root/.forge/config.yaml"
64
64
 
65
65
  if [[ ! -f "$config_file" ]]; then
66
66
  # Default: enabled
@@ -108,7 +108,7 @@ forge_team_sync() {
108
108
  done
109
109
 
110
110
  local gh_cmd="${GH_CMD:-gh}"
111
- local bd_cmd="${BD_CMD:-bd}"
111
+ local forge_cmd="${FORGE_CMD:-forge}"
112
112
 
113
113
  # 1. Check gh auth status
114
114
  if ! "$gh_cmd" auth status >/dev/null 2>&1; then
@@ -122,44 +122,42 @@ forge_team_sync() {
122
122
  return 0
123
123
  fi
124
124
 
125
- # 3. Get all in_progress issues
126
- local list_output
127
- list_output="$("$bd_cmd" list --status=in_progress 2>/dev/null)" || {
125
+ # 3. Get all in_progress issues as JSON
126
+ local list_json
127
+ list_json="$("$forge_cmd" issue list --status=in_progress --json 2>/dev/null)" || {
128
128
  if [[ "$quiet" == "false" ]]; then
129
129
  _hooks_warn "Failed to list issues, sync skipped"
130
130
  fi
131
131
  return 0
132
132
  }
133
133
 
134
- # Filter empty lines
135
- if [[ -z "$list_output" ]] || [[ -z "$(echo "$list_output" | tr -d '[:space:]')" ]]; then
134
+ # Build "id<TAB>has_github" lines (has_github is true when a github_issue:<n>
135
+ # label is present on the issue).
136
+ local issue_lines
137
+ issue_lines="$(printf '%s' "$list_json" | jq -r '
138
+ (.data.issues // [])[]
139
+ | [ .id, (((.labels // []) | any(test("^github_issue:"))) | tostring) ]
140
+ | join("\t")' 2>/dev/null | tr -d '\r')"
141
+
142
+ if [[ -z "$issue_lines" ]] || [[ -z "$(printf '%s' "$issue_lines" | tr -d '[:space:]')" ]]; then
136
143
  if [[ "$quiet" == "false" ]]; then
137
144
  _hooks_info "Nothing to sync"
138
145
  fi
139
146
  return 0
140
147
  fi
141
148
 
142
- # 4. For each issue, check for github_issue state and sync
149
+ # 4. For each issue with a github_issue label, sync its status to GitHub
143
150
  local synced=0
144
151
  local warnings=0
145
152
 
146
- while IFS= read -r line; do
147
- [[ -z "$line" ]] && continue
148
-
149
- # Extract issue id
150
- local issue_id
151
- issue_id="$(echo "$line" | grep -oE 'forge-[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*' | head -1)"
153
+ while IFS=$'\t' read -r issue_id has_github; do
152
154
  [[ -z "$issue_id" ]] && continue
153
155
 
154
- # Get details to check for github_issue state
155
- local show_output
156
- show_output="$("$bd_cmd" show "$issue_id" 2>/dev/null)" || continue
157
-
158
- # Check if it has github_issue:N state
159
- local gh_issue_num
160
- gh_issue_num="$(printf '%s' "$show_output" | grep -oP 'github_issue:\K[0-9]+' | head -1 || true)"
161
-
162
- if [[ -z "$gh_issue_num" ]]; then
156
+ # Skip only when there is neither a github_issue:<n> label nor a legacy
157
+ # mapping-file association. _get_github_issue_number (from sync-github.sh)
158
+ # checks the label first, then the mapping-file fallback, so mapping-only
159
+ # linked issues are still synced instead of being skipped here.
160
+ if [[ "$has_github" != "true" ]] && ! _get_github_issue_number "$issue_id" >/dev/null 2>&1; then
163
161
  # No GitHub issue linked, skip but warn
164
162
  warnings=$((warnings + 1))
165
163
  if [[ "$quiet" == "false" ]]; then
@@ -177,7 +175,7 @@ forge_team_sync() {
177
175
  _hooks_warn "Failed to sync $issue_id to GitHub"
178
176
  fi
179
177
  fi
180
- done <<< "$list_output"
178
+ done <<< "$issue_lines"
181
179
 
182
180
  # 5. Report
183
181
  if [[ "$quiet" == "false" ]]; then
@@ -2,7 +2,7 @@
2
2
  # scripts/forge-team/lib/identity.sh — GitHub-username-only identity mapping
3
3
  #
4
4
  # Auto-detects developer via `gh api user`. Stores identity in
5
- # .beads/team-map.jsonl (append-only, LWW per GitHub username).
5
+ # .forge/team-map.jsonl (append-only, LWW per GitHub username).
6
6
  #
7
7
  # Functions:
8
8
  # get_github_user — Current dev's GitHub username (cached)
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # Env overrides:
16
16
  # GH_CMD — Path to gh binary (for testing)
17
- # TEAM_MAP_ROOT — Root dir for .beads/team-map.jsonl (default: .)
17
+ # TEAM_MAP_ROOT — Root dir for .forge/team-map.jsonl (default: .)
18
18
  #
19
19
  # This file does NOT set errexit/pipefail — callers manage their own shell options.
20
20
 
@@ -69,7 +69,7 @@ _identity_prompt() {
69
69
  # _team_map_file — Returns the path to team-map.jsonl
70
70
  _team_map_file() {
71
71
  local root="${TEAM_MAP_ROOT:-.}"
72
- printf '%s' "$root/.beads/team-map.jsonl"
72
+ printf '%s' "$root/.forge/team-map.jsonl"
73
73
  }
74
74
 
75
75
  # _validate_github_username <username>
@@ -124,7 +124,7 @@ get_github_user() {
124
124
  }
125
125
 
126
126
  # team_map_add <github-user> [display-name]
127
- # Adds/updates entry in .beads/team-map.jsonl.
127
+ # Adds/updates entry in .forge/team-map.jsonl.
128
128
  # Schema: {"github":"<user>","display_name":"<name>","updated_at":"<ts>","is_bot":false}
129
129
  team_map_add() {
130
130
  local github_user="${1:-}"