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
@@ -3,16 +3,17 @@ set -euo pipefail
3
3
 
4
4
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
5
 
6
- # ── Setup temp dir for test isolation ────────────────────────────────────
7
6
  TEST_TMP="$(mktemp -d)"
8
7
  trap 'rm -rf "$TEST_TMP" "$mock_dir"' EXIT
9
8
 
10
- # ── Create mock dir and log file ─────────────────────────────────────────
11
- mock_dir="$(mktemp -d /c/tmp/forge-sync-test.XXXXXX)"
9
+ mock_dir="$(mktemp -d)"
10
+ portable_bin="$(mktemp -d)"
12
11
  log_file="$mock_dir/calls.log"
13
12
  touch "$log_file"
13
+ REAL_GREP="$(command -v grep)"
14
+ ORIGINAL_PATH="$PATH"
15
+ export REAL_GREP
14
16
 
15
- # ── Mock gh ──────────────────────────────────────────────────────────────
16
17
  cat > "$mock_dir/gh" << 'MOCK'
17
18
  #!/usr/bin/env bash
18
19
  echo "$*" >> "$LOG_FILE"
@@ -23,45 +24,57 @@ case "$1 $2" in
23
24
  "issue comment") echo ""; exit 0 ;;
24
25
  "api user") echo "testuser"; exit 0 ;;
25
26
  esac
26
- echo "unknown gh command: $*" >&2; exit 1
27
+ echo "unknown gh command: $*" >&2
28
+ exit 1
27
29
  MOCK
28
30
  chmod +x "$mock_dir/gh"
29
31
 
30
- # ── Mock bd ──────────────────────────────────────────────────────────────
31
- cat > "$mock_dir/bd" << 'MOCK'
32
+ # Mock forge: `issue show --json` carries the github_issue:<n> association as a
33
+ # label; `issue update --label` records it. Args are logged for assertions.
34
+ cat > "$mock_dir/forge" << 'MOCK'
32
35
  #!/usr/bin/env bash
33
36
  echo "$*" >> "$LOG_FILE"
34
- case "$1" in
35
- show)
36
- echo "○ $2 · Test Issue [github_issue:42]"
37
- echo "Title: Test Issue"
37
+ case "$1 $2" in
38
+ "issue show")
39
+ printf '{"data":{"issue":{"id":"beads-001","title":"Test Issue","labels":["github_issue:42"]}}}\n'
38
40
  ;;
39
- set-state) echo "State set" ;;
41
+ "issue update") echo "Updated" ;;
40
42
  esac
41
43
  MOCK
42
- chmod +x "$mock_dir/bd"
44
+ chmod +x "$mock_dir/forge"
43
45
 
44
- # ── Mock bd that returns NO github_issue ─────────────────────────────────
45
- cat > "$mock_dir/bd-no-gh" << 'MOCK'
46
+ cat > "$mock_dir/forge-no-gh" << 'MOCK'
46
47
  #!/usr/bin/env bash
47
48
  echo "$*" >> "$LOG_FILE"
48
- case "$1" in
49
- show)
50
- echo "○ $2 · Test Issue"
51
- echo "Title: Test Issue"
49
+ case "$1 $2" in
50
+ "issue show")
51
+ printf '{"data":{"issue":{"id":"beads-999","title":"Test Issue","labels":[]}}}\n'
52
52
  ;;
53
- set-state) echo "State set" ;;
53
+ "issue update") echo "Updated" ;;
54
54
  esac
55
55
  MOCK
56
- chmod +x "$mock_dir/bd-no-gh"
56
+ chmod +x "$mock_dir/forge-no-gh"
57
+
58
+ cat > "$portable_bin/grep" << 'MOCK'
59
+ #!/usr/bin/env bash
60
+ for arg in "$@"; do
61
+ case "$arg" in
62
+ -P|--perl-regexp|-*P*)
63
+ echo "grep: PCRE support disabled for test" >&2
64
+ exit 2
65
+ ;;
66
+ esac
67
+ done
68
+ exec "$REAL_GREP" "$@"
69
+ MOCK
70
+ chmod +x "$portable_bin/grep"
57
71
 
58
- # Export env for mocks
59
72
  export LOG_FILE="$log_file"
60
73
  export GH_CMD="$mock_dir/gh"
61
- export BD_CMD="$mock_dir/bd"
74
+ export FORGE_CMD="$mock_dir/forge"
62
75
  export TEAM_MAP_ROOT="$TEST_TMP"
76
+ mapping_file="$TEAM_MAP_ROOT/.github/beads-mapping.json"
63
77
 
64
- # Source the library under test
65
78
  source "$SCRIPT_DIR/lib/sync-github.sh"
66
79
 
67
80
  PASS=0
@@ -70,140 +83,231 @@ FAIL=0
70
83
  assert_eq() {
71
84
  local label="$1" expected="$2" actual="$3"
72
85
  if [[ "$actual" == "$expected" ]]; then
73
- PASS=$((PASS + 1)); echo " PASS: $label"
86
+ PASS=$((PASS + 1))
87
+ echo " PASS: $label"
74
88
  else
75
- FAIL=$((FAIL + 1)); echo " FAIL: $label (expected '$expected', got '$actual')"
89
+ FAIL=$((FAIL + 1))
90
+ echo " FAIL: $label (expected '$expected', got '$actual')"
76
91
  fi
77
92
  }
78
93
 
79
94
  assert_contains() {
80
95
  local label="$1" expected="$2" actual="$3"
81
96
  if [[ "$actual" == *"$expected"* ]]; then
82
- PASS=$((PASS + 1)); echo " PASS: $label"
97
+ PASS=$((PASS + 1))
98
+ echo " PASS: $label"
83
99
  else
84
- FAIL=$((FAIL + 1)); echo " FAIL: $label (expected to contain '$expected', got '$actual')"
100
+ FAIL=$((FAIL + 1))
101
+ echo " FAIL: $label (expected to contain '$expected', got '$actual')"
102
+ fi
103
+ }
104
+
105
+ assert_not_contains() {
106
+ local label="$1" unexpected="$2" actual="$3"
107
+ if [[ "$actual" == *"$unexpected"* ]]; then
108
+ FAIL=$((FAIL + 1))
109
+ echo " FAIL: $label (did not expect '$unexpected', got '$actual')"
110
+ else
111
+ PASS=$((PASS + 1))
112
+ echo " PASS: $label"
85
113
  fi
86
114
  }
87
115
 
88
116
  assert_exit() {
89
117
  local label="$1" expected="$2" actual="$3"
90
118
  if [[ "$actual" -eq "$expected" ]]; then
91
- PASS=$((PASS + 1)); echo " PASS: $label"
119
+ PASS=$((PASS + 1))
120
+ echo " PASS: $label"
92
121
  else
93
- FAIL=$((FAIL + 1)); echo " FAIL: $label (expected exit $expected, got $actual)"
122
+ FAIL=$((FAIL + 1))
123
+ echo " FAIL: $label (expected exit $expected, got $actual)"
94
124
  fi
95
125
  }
96
126
 
97
- # ── Test 1: sync_issue_create — creates GitHub issue, calls bd set-state ─
98
- echo "── Test 1: sync_issue_create ──"
99
- > "$log_file" # clear log
127
+ echo "== Test 1: sync_issue_create =="
128
+ > "$log_file"
100
129
  rc=0
101
130
  sync_issue_create "beads-001" || rc=$?
102
131
  assert_exit "exit code 0" 0 "$rc"
103
- # Check gh was called with issue create
104
132
  log_contents="$(cat "$log_file")"
105
133
  assert_contains "gh issue create called" "issue create" "$log_contents"
106
134
  assert_contains "title includes Test Issue" "Test Issue" "$log_contents"
107
135
  assert_contains "body includes beads-001" "beads-001" "$log_contents"
108
- # Check bd set-state was called with github_issue=42
109
- assert_contains "bd set-state called" "set-state" "$log_contents"
110
- assert_contains "github_issue=42 set" "github_issue=42" "$log_contents"
136
+ assert_contains "sync create writes github_issue label" "github_issue:42" "$log_contents"
137
+ assert_contains "sync create calls issue update for the label" "issue update" "$log_contents"
138
+ assert_contains "sync create persists mapping entry" '"42": "beads-001"' "$(cat "$mapping_file")"
111
139
 
112
- # ── Test 2: sync_issue_claim — updates GitHub assignee ───────────────────
113
- echo ""
114
- echo "── Test 2: sync_issue_claim ──"
140
+ echo
141
+ echo "== Test 2: sync_issue_claim =="
115
142
  > "$log_file"
116
143
  unset _GITHUB_USER_CACHE
117
144
  rc=0
118
145
  sync_issue_claim "beads-001" || rc=$?
119
146
  assert_exit "exit code 0" 0 "$rc"
120
147
  log_contents="$(cat "$log_file")"
148
+ assert_contains "canonical lookup uses --json" "--json" "$log_contents"
121
149
  assert_contains "gh issue edit called" "issue edit" "$log_contents"
122
150
  assert_contains "add-assignee used" "--add-assignee" "$log_contents"
123
151
  assert_contains "assignee is testuser" "testuser" "$log_contents"
124
152
 
125
- # ── Test 3: sync_issue_status — removes old labels, adds new one ─────────
126
- echo ""
127
- echo "── Test 3: sync_issue_status ──"
153
+ echo
154
+ echo "== Test 3: sync_issue_status =="
128
155
  > "$log_file"
129
156
  rc=0
130
157
  sync_issue_status "beads-001" "in_progress" || rc=$?
131
158
  assert_exit "exit code 0" 0 "$rc"
132
159
  log_contents="$(cat "$log_file")"
160
+ assert_contains "canonical lookup uses --json" "--json" "$log_contents"
133
161
  assert_contains "gh issue edit called" "issue edit" "$log_contents"
134
162
  assert_contains "removes status/open" "--remove-label status/open" "$log_contents"
135
163
  assert_contains "adds status/in-progress" "--add-label status/in-progress" "$log_contents"
136
164
 
137
- # ── Test 4: sync_issue_close — closes GitHub issue ───────────────────────
138
- echo ""
139
- echo "── Test 4: sync_issue_close ──"
165
+ echo
166
+ echo "== Test 4: sync_issue_close =="
140
167
  > "$log_file"
141
168
  rc=0
142
169
  sync_issue_close "beads-001" || rc=$?
143
170
  assert_exit "exit code 0" 0 "$rc"
144
171
  log_contents="$(cat "$log_file")"
172
+ assert_contains "canonical lookup uses --json" "--json" "$log_contents"
145
173
  assert_contains "gh issue close called" "issue close" "$log_contents"
146
174
  assert_contains "closes issue 42" " 42" "$log_contents"
147
175
 
148
- # ── Test 5: sync_issue_deps — adds comment on GitHub issue ───────────────
149
- echo ""
150
- echo "── Test 5: sync_issue_deps ──"
176
+ echo
177
+ echo "== Test 5: sync_issue_deps =="
151
178
  > "$log_file"
152
179
  rc=0
153
180
  sync_issue_deps "beads-001" "beads-002" || rc=$?
154
181
  assert_exit "exit code 0" 0 "$rc"
155
182
  log_contents="$(cat "$log_file")"
183
+ assert_contains "canonical lookup uses --json" "--json" "$log_contents"
156
184
  assert_contains "gh issue comment called" "issue comment" "$log_contents"
157
185
  assert_contains "Blocked by referenced" "Blocked by #42" "$log_contents"
158
186
 
159
- # ── Test 6: _get_github_issue_number — extracts number from bd show ──────
160
- echo ""
161
- echo "── Test 6: _get_github_issue_number ──"
187
+ echo
188
+ echo "== Test 6: _get_github_issue_number =="
162
189
  result="$(_get_github_issue_number "beads-001")"
163
190
  assert_eq "extracts issue number 42" "42" "$result"
191
+ log_contents="$(cat "$log_file")"
192
+ assert_contains "_get_github_issue_number uses JSON" "--json" "$log_contents"
193
+
194
+ echo
195
+ echo "== Test 7: Mapping fallback when canonical GitHub number missing =="
196
+ mkdir -p "$(dirname "$mapping_file")"
197
+ cat > "$mapping_file" << 'JSON'
198
+ {
199
+ "77": "beads-999"
200
+ }
201
+ JSON
202
+ export FORGE_CMD="$mock_dir/forge-no-gh"
203
+ result="$(_get_github_issue_number "beads-999")"
204
+ assert_eq "mapping fallback returns issue number 77" "77" "$result"
205
+ export FORGE_CMD="$mock_dir/forge"
206
+
207
+ echo
208
+ echo "== Test 8: Mapping fallback returns newest issue number =="
209
+ cat > "$mapping_file" << 'JSON'
210
+ {
211
+ "77": "beads-999",
212
+ "91": "beads-999",
213
+ "88": "beads-other"
214
+ }
215
+ JSON
216
+ export FORGE_CMD="$mock_dir/forge-no-gh"
217
+ result="$(_get_github_issue_number "beads-999")"
218
+ assert_eq "mapping fallback returns newest matching issue number" "91" "$result"
219
+ export FORGE_CMD="$mock_dir/forge"
164
220
 
165
- # ── Test 7: Missing GitHub issue number → returns error ──────────────────
166
- echo ""
167
- echo "── Test 7: Missing GitHub issue number ──"
168
- export BD_CMD="$mock_dir/bd-no-gh"
221
+ echo
222
+ echo "== Test 9: Missing canonical GitHub number =="
223
+ rm -f "$mapping_file"
224
+ export FORGE_CMD="$mock_dir/forge-no-gh"
169
225
  rc=0
170
226
  result="$(_get_github_issue_number "beads-999" 2>/dev/null)" || rc=$?
171
- assert_exit "returns error when no github_issue" 1 "$rc"
172
- # Restore normal bd mock
173
- export BD_CMD="$mock_dir/bd"
174
-
175
- # ── Test 8: Injection in issue title → sanitized before gh call ──────────
176
- echo ""
177
- echo "── Test 8: Injection in title sanitized ──"
178
- # Create a bd mock that returns injection-laden title
179
- cat > "$mock_dir/bd-inject" << 'MOCK'
227
+ assert_exit "returns error when no canonical github number" 1 "$rc"
228
+ export FORGE_CMD="$mock_dir/forge"
229
+
230
+ echo
231
+ echo "== Test 10: github_issue label lookup =="
232
+ cat > "$mock_dir/forge-legacy" << 'MOCK'
233
+ #!/usr/bin/env bash
234
+ echo "$*" >> "$LOG_FILE"
235
+ case "$1 $2" in
236
+ "issue show")
237
+ printf '{"data":{"issue":{"id":"beads-legacy","title":"Legacy Issue","labels":["github_issue:43"]}}}\n'
238
+ ;;
239
+ "issue update") echo "Updated" ;;
240
+ esac
241
+ MOCK
242
+ chmod +x "$mock_dir/forge-legacy"
243
+ export FORGE_CMD="$mock_dir/forge-legacy"
244
+ rc=0
245
+ result="$(_get_github_issue_number "beads-legacy" 2>/dev/null)" || rc=$?
246
+ assert_exit "legacy github_issue exits successfully" 0 "$rc"
247
+ assert_eq "legacy github_issue returns number" "43" "$result"
248
+ export FORGE_CMD="$mock_dir/forge"
249
+
250
+ echo
251
+ echo "== Test 11: Injection in title sanitized =="
252
+ cat > "$mock_dir/forge-inject" << 'MOCK'
180
253
  #!/usr/bin/env bash
181
254
  echo "$*" >> "$LOG_FILE"
182
- case "$1" in
183
- show)
184
- echo 'beads-inject · Evil $(rm -rf /) Issue [github_issue:99]'
185
- echo 'Title: Evil $(rm -rf /) Issue'
255
+ case "$1 $2" in
256
+ "issue show")
257
+ printf '{"data":{"issue":{"id":"beads-inject","title":"Evil $(rm -rf /) Issue","labels":["github_issue:99"]}}}\n'
186
258
  ;;
187
- set-state) echo "State set" ;;
259
+ "issue update") echo "Updated" ;;
188
260
  esac
189
261
  MOCK
190
- chmod +x "$mock_dir/bd-inject"
191
- export BD_CMD="$mock_dir/bd-inject"
262
+ chmod +x "$mock_dir/forge-inject"
263
+ export FORGE_CMD="$mock_dir/forge-inject"
192
264
  > "$log_file"
193
265
  rc=0
194
266
  sync_issue_create "beads-inject" || rc=$?
195
267
  assert_exit "exit code 0 with injection" 0 "$rc"
196
268
  log_contents="$(cat "$log_file")"
197
- # The $(...) pattern must NOT appear in the gh call
198
269
  if [[ "$log_contents" == *'$(rm'* ]]; then
199
- FAIL=$((FAIL + 1)); echo " FAIL: injection NOT sanitized — \$(rm found in gh call"
270
+ FAIL=$((FAIL + 1))
271
+ echo " FAIL: injection NOT sanitized - \$\(rm found in gh call"
200
272
  else
201
- PASS=$((PASS + 1)); echo " PASS: injection sanitized — no \$(rm in gh call"
273
+ PASS=$((PASS + 1))
274
+ echo " PASS: injection sanitized - no \$\(rm in gh call"
202
275
  fi
203
- # Restore normal bd mock
204
- export BD_CMD="$mock_dir/bd"
276
+ export FORGE_CMD="$mock_dir/forge"
277
+
278
+ echo
279
+ echo "== Test 11: sync_issue_create without grep -P =="
280
+ export PATH="$portable_bin:$ORIGINAL_PATH"
281
+ > "$log_file"
282
+ rc=0
283
+ sync_issue_create "beads-001" || rc=$?
284
+ assert_exit "sync_issue_create works when grep -P is unavailable" 0 "$rc"
285
+ log_contents="$(cat "$log_file")"
286
+ assert_contains "gh issue create called without PCRE grep" "issue create" "$log_contents"
287
+ export PATH="$ORIGINAL_PATH"
288
+
289
+ echo
290
+ echo "== Test 12: sync_issue_create reads title from issue show JSON =="
291
+ cat > "$mock_dir/forge-summary-only" << 'MOCK'
292
+ #!/usr/bin/env bash
293
+ echo "$*" >> "$LOG_FILE"
294
+ case "$1 $2" in
295
+ "issue show")
296
+ printf '{"data":{"issue":{"id":"beads-summary","title":"Summary Only Title","labels":["github_issue:77"]}}}\n'
297
+ ;;
298
+ "issue update") echo "Updated" ;;
299
+ esac
300
+ MOCK
301
+ chmod +x "$mock_dir/forge-summary-only"
302
+ export FORGE_CMD="$mock_dir/forge-summary-only"
303
+ > "$log_file"
304
+ rc=0
305
+ sync_issue_create "beads-summary" || rc=$?
306
+ assert_exit "sync_issue_create works with title from issue show JSON" 0 "$rc"
307
+ log_contents="$(cat "$log_file")"
308
+ assert_contains "summary-only title is passed to gh issue create" "Summary Only Title" "$log_contents"
309
+ export FORGE_CMD="$mock_dir/forge"
205
310
 
206
- # ── Results ──────────────────────────────────────────────────────────────
207
- echo ""
311
+ echo
208
312
  echo "Results: $PASS passed, $FAIL failed"
209
313
  [[ $FAIL -eq 0 ]] && exit 0 || exit 1
@@ -7,7 +7,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
7
7
  TEST_TMP="$(mktemp -d)"
8
8
  trap 'rm -rf "$TEST_TMP"' EXIT
9
9
 
10
- # Override TEAM_MAP_ROOT so tests don't touch real .beads/
10
+ # Override TEAM_MAP_ROOT so tests don't touch real .forge/
11
11
  export TEAM_MAP_ROOT="$TEST_TMP"
12
12
 
13
13
  # ── Create mock directories ────────────────────────────────────────────
@@ -66,47 +66,34 @@ exit 1
66
66
  MOCK
67
67
  chmod +x "$mock_dir/gh-noauth"
68
68
 
69
- # ── Mock bd ────────────────────────────────────────────────────────────
70
- cat > "$mock_dir/bd" << 'MOCK'
69
+ # ── Mock forge (emits Kernel-shaped issue list JSON) ───────────────────
70
+ # The GitHub association lives in each issue's labels as github_issue:<n>.
71
+ # Tests drive which issues appear via FORGE_MOCK_OPEN / FORGE_MOCK_INPROGRESS
72
+ # (JSON arrays, each defaulting to []).
73
+ cat > "$mock_dir/forge" << 'MOCK'
71
74
  #!/usr/bin/env bash
72
- case "$1" in
73
- list)
74
- if [[ -n "${BD_MOCK_OUTPUT:-}" ]]; then
75
- echo "$BD_MOCK_OUTPUT"
76
- fi
77
- exit 0
78
- ;;
79
- show)
80
- case "${2:-}" in
81
- forge-aaa)
82
- echo "◐ forge-aaa · Feature A [● P2 · IN_PROGRESS]"
83
- echo "Owner: devone"
84
- if [[ -z "${BD_MOCK_NO_GITHUB_AAA:-}" ]]; then
85
- echo "State: github_issue:10"
86
- fi
87
- ;;
88
- forge-bbb)
89
- echo "○ forge-bbb · Feature B [● P2 · OPEN]"
90
- echo "Owner: devtwo"
91
- if [[ -z "${BD_MOCK_NO_GITHUB_BBB:-}" ]]; then
92
- echo "State: github_issue:20"
93
- fi
94
- ;;
95
- forge-ccc)
96
- echo "◐ forge-ccc · Feature C [● P1 · IN_PROGRESS]"
97
- echo "Owner: devone"
98
- # forge-ccc never has github_issue (for orphan tests)
99
- ;;
100
- esac
101
- exit 0
102
- ;;
103
- esac
75
+ args="$*"
76
+ if [[ "$args" == *"issue list"* ]]; then
77
+ if [[ "$args" == *"--status=open"* ]]; then
78
+ printf '{"data":{"issues":%s}}\n' "${FORGE_MOCK_OPEN:-[]}"
79
+ elif [[ "$args" == *"--status=in_progress"* ]]; then
80
+ printf '{"data":{"issues":%s}}\n' "${FORGE_MOCK_INPROGRESS:-[]}"
81
+ else
82
+ printf '{"data":{"issues":[]}}\n'
83
+ fi
84
+ exit 0
85
+ fi
104
86
  exit 0
105
87
  MOCK
106
- chmod +x "$mock_dir/bd"
88
+ chmod +x "$mock_dir/forge"
89
+
90
+ # Reusable issue fixtures (synced issues carry a github_issue:<n> label)
91
+ ccc_orphan='{"id":"forge-ccc","title":"Feature C","status":"in_progress","assignee":"devone","labels":[],"dependencies":[]}'
92
+ aaa_synced='{"id":"forge-aaa","title":"Feature A","status":"in_progress","assignee":"devone","labels":["github_issue:10"],"dependencies":[]}'
93
+ bbb_synced='{"id":"forge-bbb","title":"Feature B","status":"open","assignee":"devtwo","labels":["github_issue:20"],"dependencies":[]}'
107
94
 
108
95
  export GH_CMD="$mock_dir/gh"
109
- export BD_CMD="$mock_dir/bd"
96
+ export FORGE_CMD="$mock_dir/forge"
110
97
 
111
98
  # Source the library under test
112
99
  source "$SCRIPT_DIR/lib/agent-prompt.sh"
@@ -158,11 +145,12 @@ echo "── Test 1: All clean → exit 0 ──"
158
145
  # Setup: identity exists in team map
159
146
  unset _GITHUB_USER_CACHE
160
147
  export GH_CMD="$mock_dir/gh"
161
- export BD_CMD="$mock_dir/bd"
148
+ export FORGE_CMD="$mock_dir/forge"
162
149
  team_map_add "testuser" "Test User"
163
150
 
164
- # No beads issues, no github issues
165
- export BD_MOCK_OUTPUT=""
151
+ # No tracked issues, no github issues
152
+ export FORGE_MOCK_OPEN="[]"
153
+ export FORGE_MOCK_INPROGRESS="[]"
166
154
  export GH_MOCK_ISSUES="[]"
167
155
 
168
156
  # Create empty mapping file
@@ -194,10 +182,11 @@ echo "── Test 3: Orphan Beads issue detected ──"
194
182
 
195
183
  unset _GITHUB_USER_CACHE
196
184
  export GH_CMD="$mock_dir/gh"
197
- export BD_MOCK_OUTPUT="◐ forge-ccc · Feature C"
185
+ export FORGE_MOCK_OPEN="[]"
186
+ export FORGE_MOCK_INPROGRESS="[$ccc_orphan]"
198
187
  export GH_MOCK_ISSUES="[]"
199
188
 
200
- # forge-ccc has no github_issue state (see mock bd above)
189
+ # forge-ccc carries no github_issue label (see fixtures above)
201
190
  rc=0
202
191
  output="$(cmd_verify 2>&1)" || rc=$?
203
192
  assert_exit "orphan beads exits 1" 1 "$rc"
@@ -210,7 +199,8 @@ echo "── Test 4: Orphan GitHub issue detected ──"
210
199
 
211
200
  unset _GITHUB_USER_CACHE
212
201
  export GH_CMD="$mock_dir/gh"
213
- export BD_MOCK_OUTPUT=""
202
+ export FORGE_MOCK_OPEN="[]"
203
+ export FORGE_MOCK_INPROGRESS="[]"
214
204
  export GH_MOCK_ISSUES='[{"number":42,"title":"Some feature"},{"number":45,"title":"Another feature"}]'
215
205
 
216
206
  # Mapping file has neither #42 nor #45
@@ -231,8 +221,8 @@ unset _GITHUB_USER_CACHE
231
221
  export GH_CMD="$mock_dir/gh"
232
222
 
233
223
  # Setup: forge-aaa has github_issue:10, forge-bbb has github_issue:20
234
- export BD_MOCK_OUTPUT="◐ forge-aaa · Feature A
235
- forge-bbb · Feature B"
224
+ export FORGE_MOCK_OPEN="[$bbb_synced]"
225
+ export FORGE_MOCK_INPROGRESS="[$aaa_synced]"
236
226
 
237
227
  # Create mapping with both issues
238
228
  cat > "$TEST_TMP/.github/beads-mapping.json" << 'EOF'
@@ -300,7 +290,8 @@ echo "── Test 6: No issues at all → exit 0 ──"
300
290
 
301
291
  unset _GITHUB_USER_CACHE
302
292
  export GH_CMD="$mock_dir/gh"
303
- export BD_MOCK_OUTPUT=""
293
+ export FORGE_MOCK_OPEN="[]"
294
+ export FORGE_MOCK_INPROGRESS="[]"
304
295
  export GH_MOCK_ISSUES="[]"
305
296
  echo '{}' > "$TEST_TMP/.github/beads-mapping.json"
306
297
 
@@ -31,11 +31,11 @@ assert_contains_file "ship calls sync" "forge-team.*sync" "$SHIP"
31
31
  assert_contains_file "ship calls verify" "forge-team.*verify" "$SHIP"
32
32
 
33
33
  echo ""
34
- echo "── Sync check ──"
35
- if node "$SCRIPT_DIR/scripts/sync-commands.js" --check 2>&1 | grep -qi 'error\|drift\|mismatch'; then
36
- FAIL=$((FAIL + 1)); echo " FAIL: sync drift detected"
34
+ echo "── Skill sync check ──"
35
+ if (cd "$SCRIPT_DIR" && node -e "const r=require('./lib/skills-sync').checkSkillsSync({repoRoot:process.cwd()}); process.exit(r.inSync?0:1)"); then
36
+ PASS=$((PASS + 1)); echo " PASS: all agent skill dirs in sync"
37
37
  else
38
- PASS=$((PASS + 1)); echo " PASS: all agent dirs in sync"
38
+ FAIL=$((FAIL + 1)); echo " FAIL: skill drift detected"
39
39
  fi
40
40
 
41
41
  echo ""