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
@@ -0,0 +1,202 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @module config-writer
5
+ *
6
+ * Sparse read-modify-write for the ONE schema-validated config surface,
7
+ * `.forge/config.yaml` (the file `lib/core/runtime-graph.js` reads via
8
+ * `loadRuntimeGraphConfig`). This is the single missing primitive behind the
9
+ * `forge gate` / `forge role` verbs: create-or-update the file, set/remove one
10
+ * nested key, and preserve every other key untouched.
11
+ *
12
+ * Design: docs/work/2026-07-04-kernel-native-skills/extensibility-architecture.md
13
+ * (§9 "the sparse writer"). This is NOT a generalization of the legacy
14
+ * `.forge/adapters.json` review writer — that path stays where it is.
15
+ *
16
+ * Key paths are ARRAYS of segments, not dotted strings, because real keys
17
+ * contain dots (e.g. the gate id `gate.plan-exit`). Splitting on `.` would
18
+ * corrupt them, so callers pass `['workflow', 'gates', 'gate.plan-exit',
19
+ * 'enabled']`.
20
+ */
21
+
22
+ const fs = require('node:fs');
23
+ const path = require('node:path');
24
+ const YAML = require('yaml');
25
+ const { getPackageRoot } = require('./package-root');
26
+
27
+ /** Root of the installed Forge package (ships the canonical `skills/` dir). */
28
+ const PACKAGE_ROOT = path.join(__dirname, '..');
29
+
30
+ const CONFIG_RELATIVE = path.join('.forge', 'config.yaml');
31
+
32
+ function getConfigPath(projectRoot = process.cwd()) {
33
+ return path.join(projectRoot, '.forge', 'config.yaml');
34
+ }
35
+
36
+ function assertKeyPath(keyPath) {
37
+ if (!Array.isArray(keyPath) || keyPath.length === 0
38
+ || keyPath.some(seg => typeof seg !== 'string' || seg === '')) {
39
+ throw new Error('config-writer: keyPath must be a non-empty array of non-empty string segments.');
40
+ }
41
+ }
42
+
43
+ /** Load the raw config object (or `{}` if the file is absent/empty). */
44
+ function loadRawConfig(projectRoot = process.cwd()) {
45
+ const configPath = getConfigPath(projectRoot);
46
+ if (!fs.existsSync(configPath)) return {};
47
+ const raw = fs.readFileSync(configPath, 'utf8');
48
+ if (raw.trim() === '') return {};
49
+ const parsed = YAML.parse(raw);
50
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
51
+ throw new Error(`${CONFIG_RELATIVE} root must be an object.`);
52
+ }
53
+ return parsed;
54
+ }
55
+
56
+ function writeRawConfig(projectRoot, config) {
57
+ const configPath = getConfigPath(projectRoot);
58
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
59
+ fs.writeFileSync(configPath, YAML.stringify(config));
60
+ return configPath;
61
+ }
62
+
63
+ /**
64
+ * Set a nested key to `value`, creating intermediate objects as needed and
65
+ * preserving all sibling keys. Creates `.forge/config.yaml` if absent.
66
+ *
67
+ * @param {string} projectRoot
68
+ * @param {string[]} keyPath - Segments, e.g. ['roles', 'plan', 'skill'].
69
+ * @param {*} value
70
+ * @returns {{config: object, configPath: string}}
71
+ */
72
+ function setConfigOverride(projectRoot, keyPath, value) {
73
+ assertKeyPath(keyPath);
74
+ const config = loadRawConfig(projectRoot);
75
+ let node = config;
76
+ for (let i = 0; i < keyPath.length - 1; i += 1) {
77
+ const key = keyPath[i];
78
+ if (!node[key] || typeof node[key] !== 'object' || Array.isArray(node[key])) {
79
+ node[key] = {};
80
+ }
81
+ node = node[key];
82
+ }
83
+ node[keyPath[keyPath.length - 1]] = value;
84
+ return { config, configPath: writeRawConfig(projectRoot, config) };
85
+ }
86
+
87
+ /**
88
+ * Remove a nested key (a "reset" to the profile/default). Prunes ancestor
89
+ * objects that become empty so the surface stays sparse. No-op if the key is
90
+ * absent or the file does not exist.
91
+ *
92
+ * @param {string} projectRoot
93
+ * @param {string[]} keyPath
94
+ * @returns {{config: object, configPath: string, removed: boolean}}
95
+ */
96
+ function removeConfigOverride(projectRoot, keyPath) {
97
+ assertKeyPath(keyPath);
98
+ const configPath = getConfigPath(projectRoot);
99
+ if (!fs.existsSync(configPath)) {
100
+ return { config: {}, configPath, removed: false };
101
+ }
102
+ const config = loadRawConfig(projectRoot);
103
+ const chain = [config];
104
+ let node = config;
105
+ for (let i = 0; i < keyPath.length - 1; i += 1) {
106
+ const key = keyPath[i];
107
+ if (!node[key] || typeof node[key] !== 'object' || Array.isArray(node[key])) {
108
+ return { config, configPath, removed: false };
109
+ }
110
+ node = node[key];
111
+ chain.push(node);
112
+ }
113
+ const leaf = keyPath[keyPath.length - 1];
114
+ if (!Object.hasOwn(node, leaf)) {
115
+ return { config, configPath, removed: false };
116
+ }
117
+ delete node[leaf];
118
+ // Prune now-empty ancestor objects, deepest first.
119
+ for (let i = chain.length - 1; i > 0; i -= 1) {
120
+ if (Object.keys(chain[i]).length === 0) {
121
+ delete chain[i - 1][keyPath[i - 1]];
122
+ } else {
123
+ break;
124
+ }
125
+ }
126
+ return { config, configPath: writeRawConfig(projectRoot, config), removed: true };
127
+ }
128
+
129
+ /** Project-local skill dirs (highest precedence), independent of any extraction. */
130
+ function localSkillSearchDirs(projectRoot = process.cwd()) {
131
+ return [path.join(projectRoot, '.skills'), path.join(projectRoot, 'skills')];
132
+ }
133
+
134
+ /**
135
+ * The packaged (shipped-default) skills dir — resolved LAZILY and NON-throwing.
136
+ * In a compiled binary this triggers asset extraction, so it must only run after
137
+ * the project-local dirs miss (and must never abort skill resolution if assets
138
+ * cannot be resolved). Returns null if unavailable.
139
+ */
140
+ function packagedSkillsDir() {
141
+ try {
142
+ return path.join(getPackageRoot(PACKAGE_ROOT), 'skills');
143
+ } catch {
144
+ return null;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Directories searched (in precedence order) when resolving a skill name.
150
+ * Mirrors the skills-sync precedence: `.skills/` shadow wins over canonical
151
+ * `skills/`, then the installed package's shipped defaults (resolved lazily).
152
+ */
153
+ function skillSearchDirs(projectRoot = process.cwd()) {
154
+ const dirs = localSkillSearchDirs(projectRoot);
155
+ const packaged = packagedSkillsDir();
156
+ if (packaged) dirs.push(packaged);
157
+ return dirs;
158
+ }
159
+
160
+ /**
161
+ * Resolve a skill NAME to a real `SKILL.md` via `.skills/ > skills/`
162
+ * precedence. Returns null if no such skill exists — the `forge role` verb
163
+ * uses this for write-time validation so an unresolvable skill errors before
164
+ * anything is written (never mid-run).
165
+ *
166
+ * @param {string} projectRoot
167
+ * @param {string} name
168
+ * @returns {{name: string, dir: string, path: string}|null}
169
+ */
170
+ function resolveSkill(projectRoot, name) {
171
+ if (typeof name !== 'string' || name === ''
172
+ || name.includes('/') || name.includes('\\') || name.includes('\0')
173
+ || name === '.' || name === '..') {
174
+ return null;
175
+ }
176
+ // Check project-local dirs FIRST — these never trigger extraction, so a
177
+ // project-local skill resolves without touching the packaged fallback.
178
+ for (const dir of localSkillSearchDirs(projectRoot)) {
179
+ const skillMd = path.join(dir, name, 'SKILL.md');
180
+ if (fs.existsSync(skillMd)) {
181
+ return { name, dir, path: skillMd };
182
+ }
183
+ }
184
+ // Only now resolve the packaged fallback (lazy, non-throwing).
185
+ const packaged = packagedSkillsDir();
186
+ if (packaged) {
187
+ const skillMd = path.join(packaged, name, 'SKILL.md');
188
+ if (fs.existsSync(skillMd)) {
189
+ return { name, dir: packaged, path: skillMd };
190
+ }
191
+ }
192
+ return null;
193
+ }
194
+
195
+ module.exports = {
196
+ getConfigPath,
197
+ loadRawConfig,
198
+ setConfigOverride,
199
+ removeConfigOverride,
200
+ resolveSkill,
201
+ skillSearchDirs,
202
+ };
@@ -0,0 +1,236 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @module control-plane
5
+ *
6
+ * The single source of truth for the **control-plane guarantee matrix**
7
+ * (docs/reference/control-plane-guarantees.md): it classifies each control
8
+ * surface, names its enforcement-locus, derives the tri-state label, renders the
9
+ * honest read badge, and resolves a `forge control` write-intent into the ONE
10
+ * resolver-enforced field — `workflow.gates.<id>.enabled`.
11
+ *
12
+ * Why this module exists: the cockpit uses a tri-state vocabulary
13
+ * (`mandatory` / `optional` / `permission`), but that vocabulary is only
14
+ * meaningful where Forge can actually DENY at run time — on gates and rails. On
15
+ * MCP servers, rules, and skills there is no run-time deny; "mandatory" there
16
+ * would mean nothing more than *the file is present*. This module draws that
17
+ * line so the UI and the `forge control` command never sell enforcement Forge
18
+ * cannot deliver. Pure + dependency-free so it is trivially testable and shared
19
+ * by the command, `forge options`, and any dashboard snapshot.
20
+ */
21
+
22
+ /** The closed set of human gates — satisfied by a `gate.approved` kernel EVENT. */
23
+ const HUMAN_GATE_IDS = new Set(['gate.intent', 'gate.plan-approval', 'gate.merge']);
24
+
25
+ const CONTROLLABLE_SURFACES = new Set(['gate', 'human-gate', 'rail']);
26
+
27
+ const GUARANTEE_DOC = 'docs/reference/control-plane-guarantees.md';
28
+
29
+ const VALID_STATES = new Set(['mandatory', 'optional', 'permission']);
30
+
31
+ /**
32
+ * Classify a control id into its surface. The id namespaces are disjoint, so a
33
+ * prefix match is unambiguous; the three human gates are singled out because
34
+ * their enforcement-locus (a human approval event) differs from ordinary gates.
35
+ *
36
+ * @param {string} id
37
+ * @returns {'gate'|'human-gate'|'rail'|'mcp'|'rule'|'skill'|'unknown'}
38
+ */
39
+ function classifySurface(id) {
40
+ if (typeof id !== 'string') return 'unknown';
41
+ if (HUMAN_GATE_IDS.has(id)) return 'human-gate';
42
+ if (id.startsWith('gate.')) return 'gate';
43
+ if (id.startsWith('rail.')) return 'rail';
44
+ if (id.startsWith('mcp.')) return 'mcp';
45
+ if (id.startsWith('rule.')) return 'rule';
46
+ if (id.startsWith('skill.')) return 'skill';
47
+ return 'unknown';
48
+ }
49
+
50
+ /**
51
+ * True only for surfaces `forge control` can CONFIGURE (gates + rails).
52
+ *
53
+ * NOTE: "controllable" means CLI-configurable, NOT runtime-enforced — the two are
54
+ * deliberately separate. Configuring one of these writes a declared flag; whether
55
+ * anything actually denies on it is a distinct question answered by
56
+ * `enforcementLocus` (today: nothing does). See docs/reference/control-plane-guarantees.md.
57
+ */
58
+ function isControllable(id) {
59
+ return CONTROLLABLE_SURFACES.has(classifySurface(id));
60
+ }
61
+
62
+ /**
63
+ * The honest enforcement-locus — WHERE and WHETHER Forge actually consumes this
64
+ * flag TODAY (as of 2026-07-15). This deliberately does NOT claim `run-time-deny`
65
+ * for the configurable gates/rails, because an adversarial grep of every consumer
66
+ * of the resolved graph found NONE that denies on `workflow.gates.<id>.enabled`:
67
+ *
68
+ * - stage-exit gates + rails: no runtime consumer reads their `.enabled` to
69
+ * refuse. `enforce-stage.js` enforces stage ORDER + kernel COMPLETION, which
70
+ * is independent of these flags. → "registry — declared, not yet enforced".
71
+ * - `gate.issue_verify`: consumed by lib/commands/_issue.js, but WARN-ONLY —
72
+ * a mismatch prints a warning and never overturns the write's `ok`.
73
+ * - human gates: the `forge gate approve`/`check` primitives are real and
74
+ * deny-CAPABLE, but no chokepoint auto-invokes `forge gate check`, so nothing
75
+ * denies on them yet. → "deny-on-check (no chokepoint yet)".
76
+ *
77
+ * Real enforcement today lives elsewhere and is independent of these flags: the
78
+ * B3 lefthook TDD pre-commit hook, B2 fail-closed `validate`/`preflight`, and
79
+ * `enforce-stage` order+completion. See docs/reference/control-plane-guarantees.md.
80
+ *
81
+ * @param {string} id
82
+ */
83
+ function enforcementLocus(id) {
84
+ const surface = classifySurface(id);
85
+ if (surface === 'human-gate') {
86
+ return 'deny-on-check (deny-capable via forge gate check; no chokepoint invokes it yet)';
87
+ }
88
+ if (id === 'gate.issue_verify') {
89
+ return 'run-time verify (warn-only, never denies)';
90
+ }
91
+ if (surface === 'gate' || surface === 'rail') {
92
+ return 'registry — declared, not yet enforced';
93
+ }
94
+ // mcp / rule / skill / unknown — presence written into harness config only.
95
+ return 'render-time presence-only';
96
+ }
97
+
98
+ /**
99
+ * Derive the tri-state label from the resolver-enforced fields, so state is
100
+ * never stored twice (single source of truth = `enabled`).
101
+ *
102
+ * @param {{id: string, enabled?: boolean}} primitive
103
+ * @returns {'mandatory'|'optional'|'permission'|null} null for advisory surfaces.
104
+ */
105
+ function deriveState(primitive) {
106
+ const surface = classifySurface(primitive.id);
107
+ if (!CONTROLLABLE_SURFACES.has(surface)) return null;
108
+ const enabled = primitive.enabled !== false;
109
+ if (surface === 'human-gate') return enabled ? 'permission' : 'optional';
110
+ return enabled ? 'mandatory' : 'optional';
111
+ }
112
+
113
+ /**
114
+ * The read-view badge: reflects the HONEST wiring status TODAY, never the
115
+ * author's intent, so the UI can never imply enforcement a surface lacks.
116
+ * `ENFORCED` is reserved strictly for a wired runtime deny — a set that is
117
+ * EMPTY today for these configurable flags, so this function never returns it.
118
+ * A `locked` primitive appends a `LOCKED` marker (it cannot be lowered).
119
+ *
120
+ * @param {{id: string, enabled?: boolean, locked?: boolean}} primitive
121
+ * @returns {string}
122
+ */
123
+ function badgeFor(primitive) {
124
+ const surface = classifySurface(primitive.id);
125
+ if (!CONTROLLABLE_SURFACES.has(surface)) return 'PRESENT (advisory)';
126
+
127
+ const enabled = primitive.enabled !== false;
128
+ let badge;
129
+ if (!enabled) {
130
+ badge = 'OFF (optional)';
131
+ } else if (surface === 'human-gate') {
132
+ // Deny-capable via `forge gate check`, but no chokepoint invokes it yet.
133
+ badge = 'DENY-ON-CHECK';
134
+ } else if (primitive.id === 'gate.issue_verify') {
135
+ // Consumed by _issue.js, but warn-only — never overturns a write.
136
+ badge = 'VERIFY (warn-only)';
137
+ } else {
138
+ // stage-exit gates + rails: declared in the registry, no runtime consumer.
139
+ badge = 'DECLARED (no runtime consumer yet)';
140
+ }
141
+ return primitive.locked === true ? `${badge} · LOCKED` : badge;
142
+ }
143
+
144
+ /**
145
+ * The full read record for a primitive — everything a read view / badge needs.
146
+ *
147
+ * @param {{id: string, enabled?: boolean, locked?: boolean}} primitive
148
+ */
149
+ function describeControl(primitive) {
150
+ const surface = classifySurface(primitive.id);
151
+ return {
152
+ id: primitive.id,
153
+ surface,
154
+ controllable: CONTROLLABLE_SURFACES.has(surface),
155
+ state: deriveState(primitive),
156
+ locus: enforcementLocus(primitive.id),
157
+ badge: badgeFor(primitive),
158
+ locked: primitive.locked === true,
159
+ };
160
+ }
161
+
162
+ /**
163
+ * Resolve a `forge control <id> <state>` write-intent into the enabled boolean
164
+ * for `workflow.gates.<id>.enabled` — or an honest refusal. This is the guard
165
+ * that keeps the tri-state vocabulary from over-promising:
166
+ *
167
+ * - advisory surfaces (mcp/rule/skill/unknown) → refused (presence-only).
168
+ * - `permission` is valid ONLY for human gates; elsewhere it has no path.
169
+ * - `mandatory` on a human gate → refused, directed to `permission`.
170
+ * - `optional` on a `locked` primitive → refused (cannot be lowered).
171
+ *
172
+ * @param {{id: string, locked?: boolean}} primitive
173
+ * @param {string} state - requested tri-state
174
+ * @returns {{ok: true, enabled: boolean}|{ok: false, error: string}}
175
+ */
176
+ function planControl(primitive, state) {
177
+ const surface = classifySurface(primitive.id);
178
+
179
+ if (!CONTROLLABLE_SURFACES.has(surface)) {
180
+ return {
181
+ ok: false,
182
+ error: `${primitive.id} is presence-only, not enforceable — Forge has no `
183
+ + `run-time deny for this surface. It stays read-only in the cockpit `
184
+ + `(badge PRESENT (advisory)). See ${GUARANTEE_DOC}.`,
185
+ };
186
+ }
187
+
188
+ if (!VALID_STATES.has(state)) {
189
+ return {
190
+ ok: false,
191
+ error: `Unknown state '${state}'. Use one of: mandatory, optional, permission.`,
192
+ };
193
+ }
194
+
195
+ const isHuman = surface === 'human-gate';
196
+
197
+ if (state === 'permission' && !isHuman) {
198
+ return {
199
+ ok: false,
200
+ error: `'permission' applies only to a human gate `
201
+ + `(${[...HUMAN_GATE_IDS].join(', ')}); ${primitive.id} enforces evidence, `
202
+ + `not approval. Use 'mandatory' or 'optional'. See ${GUARANTEE_DOC}.`,
203
+ };
204
+ }
205
+
206
+ if (state === 'mandatory' && isHuman) {
207
+ return {
208
+ ok: false,
209
+ error: `${primitive.id} is a human gate — it blocks until a human approval `
210
+ + `event, so use 'permission' (not 'mandatory'). See ${GUARANTEE_DOC}.`,
211
+ };
212
+ }
213
+
214
+ if (state === 'optional' && primitive.locked === true) {
215
+ return {
216
+ ok: false,
217
+ error: `Cannot lower locked ${surface} '${primitive.id}' to optional.`,
218
+ };
219
+ }
220
+
221
+ // mandatory / permission → enabled; optional → disabled. Written to the ONE
222
+ // field the resolver honors, so enforcement is genuine.
223
+ return { ok: true, enabled: state !== 'optional' };
224
+ }
225
+
226
+ module.exports = {
227
+ HUMAN_GATE_IDS,
228
+ GUARANTEE_DOC,
229
+ classifySurface,
230
+ isControllable,
231
+ enforcementLocus,
232
+ deriveState,
233
+ badgeFor,
234
+ describeControl,
235
+ planControl,
236
+ };