forge-workflow 0.0.3 → 0.0.5

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 (209) hide show
  1. package/.claude/commands/dev.md +340 -314
  2. package/.claude/commands/plan.md +521 -478
  3. package/.claude/commands/premerge.md +176 -179
  4. package/.claude/commands/research.md +42 -42
  5. package/.claude/commands/review.md +442 -442
  6. package/.claude/commands/rollback.md +721 -721
  7. package/.claude/commands/ship.md +164 -134
  8. package/.claude/commands/sonarcloud.md +152 -152
  9. package/.claude/commands/status.md +48 -77
  10. package/.claude/commands/validate.md +282 -237
  11. package/.claude/commands/verify.md +221 -221
  12. package/.claude/rules/greptile-review-process.md +285 -285
  13. package/.claude/rules/workflow.md +105 -105
  14. package/.claude/scripts/greptile-resolve.sh +526 -526
  15. package/.claude/scripts/load-env.sh +32 -32
  16. package/.cline/workflows/dev.md +337 -311
  17. package/.cline/workflows/plan.md +518 -475
  18. package/.cline/workflows/premerge.md +173 -176
  19. package/.cline/workflows/research.md +39 -39
  20. package/.cline/workflows/review.md +439 -439
  21. package/.cline/workflows/rollback.md +718 -718
  22. package/.cline/workflows/ship.md +161 -131
  23. package/.cline/workflows/sonarcloud.md +146 -146
  24. package/.cline/workflows/status.md +45 -74
  25. package/.cline/workflows/validate.md +279 -234
  26. package/.cline/workflows/verify.md +218 -218
  27. package/.codex/config.toml +11 -11
  28. package/.codex/skills/dev/SKILL.md +340 -314
  29. package/.codex/skills/plan/SKILL.md +521 -478
  30. package/.codex/skills/premerge/SKILL.md +176 -179
  31. package/.codex/skills/research/SKILL.md +42 -42
  32. package/.codex/skills/review/SKILL.md +442 -442
  33. package/.codex/skills/rollback/SKILL.md +721 -721
  34. package/.codex/skills/ship/SKILL.md +164 -134
  35. package/.codex/skills/sonarcloud/SKILL.md +149 -149
  36. package/.codex/skills/status/SKILL.md +48 -77
  37. package/.codex/skills/validate/SKILL.md +282 -237
  38. package/.codex/skills/verify/SKILL.md +221 -221
  39. package/.cursor/commands/dev.md +337 -311
  40. package/.cursor/commands/plan.md +518 -475
  41. package/.cursor/commands/premerge.md +173 -176
  42. package/.cursor/commands/research.md +39 -39
  43. package/.cursor/commands/review.md +439 -439
  44. package/.cursor/commands/rollback.md +718 -718
  45. package/.cursor/commands/ship.md +161 -131
  46. package/.cursor/commands/sonarcloud.md +146 -146
  47. package/.cursor/commands/status.md +45 -74
  48. package/.cursor/commands/validate.md +279 -234
  49. package/.cursor/commands/verify.md +218 -218
  50. package/.cursor/rules/permissions-guidance.mdc +37 -37
  51. package/.forge/hooks/check-tdd.js +240 -240
  52. package/.github/PLUGIN_TEMPLATE.json +32 -32
  53. package/.github/prompts/dev.prompt.md +342 -316
  54. package/.github/prompts/plan.prompt.md +523 -480
  55. package/.github/prompts/premerge.prompt.md +178 -181
  56. package/.github/prompts/research.prompt.md +44 -44
  57. package/.github/prompts/review.prompt.md +444 -444
  58. package/.github/prompts/rollback.prompt.md +723 -723
  59. package/.github/prompts/ship.prompt.md +166 -136
  60. package/.github/prompts/sonarcloud.prompt.md +151 -151
  61. package/.github/prompts/status.prompt.md +50 -79
  62. package/.github/prompts/validate.prompt.md +284 -239
  63. package/.github/prompts/verify.prompt.md +223 -223
  64. package/.github/workflows/beads-to-github.yml +56 -0
  65. package/.github/workflows/github-to-beads.yml +97 -0
  66. package/.kilocode/workflows/dev.md +341 -315
  67. package/.kilocode/workflows/plan.md +522 -479
  68. package/.kilocode/workflows/premerge.md +177 -180
  69. package/.kilocode/workflows/research.md +43 -43
  70. package/.kilocode/workflows/review.md +443 -443
  71. package/.kilocode/workflows/rollback.md +722 -722
  72. package/.kilocode/workflows/ship.md +165 -135
  73. package/.kilocode/workflows/sonarcloud.md +150 -150
  74. package/.kilocode/workflows/status.md +49 -78
  75. package/.kilocode/workflows/validate.md +283 -238
  76. package/.kilocode/workflows/verify.md +222 -222
  77. package/.mcp.json.example +12 -12
  78. package/.opencode/commands/dev.md +340 -314
  79. package/.opencode/commands/plan.md +521 -478
  80. package/.opencode/commands/premerge.md +176 -179
  81. package/.opencode/commands/research.md +42 -42
  82. package/.opencode/commands/review.md +442 -442
  83. package/.opencode/commands/rollback.md +721 -721
  84. package/.opencode/commands/ship.md +164 -134
  85. package/.opencode/commands/sonarcloud.md +149 -149
  86. package/.opencode/commands/status.md +48 -77
  87. package/.opencode/commands/validate.md +282 -237
  88. package/.opencode/commands/verify.md +221 -221
  89. package/.roo/commands/dev.md +341 -315
  90. package/.roo/commands/plan.md +522 -479
  91. package/.roo/commands/premerge.md +177 -180
  92. package/.roo/commands/research.md +43 -43
  93. package/.roo/commands/review.md +443 -443
  94. package/.roo/commands/rollback.md +722 -722
  95. package/.roo/commands/ship.md +165 -135
  96. package/.roo/commands/sonarcloud.md +150 -150
  97. package/.roo/commands/status.md +49 -78
  98. package/.roo/commands/validate.md +283 -238
  99. package/.roo/commands/verify.md +222 -222
  100. package/AGENTS.md +175 -169
  101. package/CLAUDE.md +100 -99
  102. package/LICENSE +21 -21
  103. package/README.md +429 -414
  104. package/bin/forge-cmd.js +313 -313
  105. package/bin/{forge-validate.js → forge-preflight.js} +309 -303
  106. package/bin/forge.js +4596 -4232
  107. package/docs/AGENT_INSTALL_PROMPT.md +342 -342
  108. package/docs/BEADS_GITHUB_SYNC.md +251 -0
  109. package/docs/ENHANCED_ONBOARDING.md +602 -602
  110. package/docs/EXAMPLES.md +482 -482
  111. package/docs/GREPTILE_SETUP.md +400 -400
  112. package/docs/MANUAL_REVIEW_GUIDE.md +106 -106
  113. package/docs/ROADMAP.md +359 -359
  114. package/docs/SETUP.md +663 -632
  115. package/docs/TOOLCHAIN.md +630 -630
  116. package/docs/VALIDATION.md +363 -363
  117. package/install.sh +40 -1058
  118. package/lefthook.yml +39 -39
  119. package/lib/agents/README.md +198 -198
  120. package/lib/agents/claude.plugin.json +28 -28
  121. package/lib/agents/cline.plugin.json +22 -22
  122. package/lib/agents/codex.plugin.json +19 -19
  123. package/lib/agents/copilot.plugin.json +24 -24
  124. package/lib/agents/cursor.plugin.json +25 -25
  125. package/lib/agents/kilocode.plugin.json +22 -22
  126. package/lib/agents/opencode.plugin.json +20 -20
  127. package/lib/agents/roo.plugin.json +23 -23
  128. package/lib/agents-config.js +2112 -2112
  129. package/lib/beads-health-check.js +143 -0
  130. package/lib/beads-setup.js +341 -0
  131. package/lib/beads-sync-scaffold.js +260 -0
  132. package/lib/commands/dev.js +513 -513
  133. package/lib/commands/plan.js +692 -692
  134. package/lib/commands/recommend.js +119 -119
  135. package/lib/commands/ship.js +377 -377
  136. package/lib/commands/status.js +378 -378
  137. package/lib/commands/validate.js +602 -602
  138. package/lib/context-merge.js +359 -359
  139. package/lib/dep-guard/analyzer.js +294 -294
  140. package/lib/dep-guard/behavior-detector.js +98 -98
  141. package/lib/dep-guard/contract-detector.js +162 -162
  142. package/lib/dep-guard/import-detector.js +498 -498
  143. package/lib/dep-guard/path-utils.js +13 -13
  144. package/lib/dep-guard/rubric.js +120 -120
  145. package/lib/dep-guard/task-parser.js +318 -318
  146. package/lib/detect-agent.js +191 -0
  147. package/lib/detect-worktree.js +47 -0
  148. package/lib/file-hash.js +26 -0
  149. package/lib/husky-migration.js +450 -0
  150. package/lib/lefthook-check.js +65 -0
  151. package/lib/pat-setup.js +207 -0
  152. package/lib/plugin-catalog.js +350 -350
  153. package/lib/plugin-manager.js +166 -166
  154. package/lib/plugin-recommender.js +141 -141
  155. package/lib/project-discovery.js +491 -491
  156. package/lib/setup-action-log.js +139 -0
  157. package/lib/setup-summary-renderer.js +106 -0
  158. package/lib/setup-utils.js +96 -0
  159. package/lib/setup.js +192 -118
  160. package/lib/smart-merge.js +64 -0
  161. package/lib/symlink-utils.js +81 -0
  162. package/lib/workflow-profiles.js +197 -197
  163. package/package.json +131 -129
  164. package/scripts/beads-context.sh +291 -0
  165. package/scripts/beads-context.test.js +563 -0
  166. package/scripts/behavioral-judge.sh +378 -0
  167. package/scripts/benchmark.js +85 -0
  168. package/scripts/branch-protection.js +183 -0
  169. package/scripts/check-agents.js +172 -0
  170. package/scripts/commitlint.js +42 -0
  171. package/scripts/conflict-detect.sh +323 -0
  172. package/scripts/dep-guard-analyze.js +71 -0
  173. package/scripts/dep-guard.sh +811 -0
  174. package/scripts/eval_win.py +249 -0
  175. package/scripts/file-index.sh +399 -0
  176. package/scripts/github-beads-sync/comment.mjs +64 -0
  177. package/scripts/github-beads-sync/config.mjs +148 -0
  178. package/scripts/github-beads-sync/github-api.mjs +131 -0
  179. package/scripts/github-beads-sync/index.mjs +332 -0
  180. package/scripts/github-beads-sync/label-mapper.mjs +54 -0
  181. package/scripts/github-beads-sync/mapping.mjs +78 -0
  182. package/scripts/github-beads-sync/reverse-sync-cli.mjs +31 -0
  183. package/scripts/github-beads-sync/reverse-sync.mjs +138 -0
  184. package/scripts/github-beads-sync/run-bd.mjs +159 -0
  185. package/scripts/github-beads-sync/sanitize.mjs +121 -0
  186. package/scripts/github-beads-sync.config.json +26 -0
  187. package/scripts/improve-command.js +375 -0
  188. package/scripts/lib/eval-runner.js +229 -0
  189. package/scripts/lib/eval-schema.js +135 -0
  190. package/scripts/lib/eval-storage.js +78 -0
  191. package/scripts/lib/grading.js +203 -0
  192. package/scripts/lib/transcript-parser.js +63 -0
  193. package/scripts/lint.js +47 -0
  194. package/scripts/migrate-to-bun-test.js +412 -0
  195. package/scripts/run-command-eval.js +236 -0
  196. package/scripts/smart-status.sh +782 -0
  197. package/scripts/sync-commands.js +571 -0
  198. package/scripts/sync-utils.sh +460 -0
  199. package/scripts/test-dashboard.js +123 -0
  200. package/scripts/test.js +44 -0
  201. package/scripts/validate.sh +94 -0
  202. package/skills/parallel-deep-research/SKILL.md +108 -108
  203. package/skills/parallel-deep-research/evals/README.md +27 -27
  204. package/skills/parallel-deep-research/evals/evals.json +62 -62
  205. package/skills/sonarcloud-analysis/SKILL.md +171 -171
  206. package/skills/sonarcloud-analysis/evals/README.md +27 -27
  207. package/skills/sonarcloud-analysis/evals/evals.json +50 -50
  208. package/skills/sonarcloud-analysis/references/api-reference.md +466 -466
  209. package/docs/WORKFLOW.md +0 -400
@@ -0,0 +1,260 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const { execFileSync } = require('node:child_process');
6
+
7
+ /**
8
+ * Detect the default branch of the repository.
9
+ *
10
+ * Strategy (in order):
11
+ * 1. `git symbolic-ref refs/remotes/origin/HEAD` -> parse branch name
12
+ * 2. `git remote show origin` -> parse "HEAD branch:" line
13
+ * 3. Fall back to `'main'`
14
+ *
15
+ * @param {string} projectRoot - Absolute path to the project root.
16
+ * @param {object} [options] - Options object.
17
+ * @param {Function} [options._exec] - Injected execFileSync for testing.
18
+ * @returns {string} The default branch name.
19
+ */
20
+ function detectDefaultBranch(projectRoot, options = {}) {
21
+ const exec = options._exec || execFileSync;
22
+
23
+ // Strategy 1: symbolic-ref
24
+ try {
25
+ const out = exec('git', ['symbolic-ref', 'refs/remotes/origin/HEAD'], {
26
+ cwd: projectRoot,
27
+ stdio: ['pipe', 'pipe', 'pipe'],
28
+ });
29
+ const ref = out.toString().trim();
30
+ // refs/remotes/origin/main -> main
31
+ const parts = ref.split('/');
32
+ if (parts.length > 0) {
33
+ return parts[parts.length - 1];
34
+ }
35
+ } catch (_e) {
36
+ // Expected: symbolic-ref fails when origin/HEAD is not set — fall through to strategy 2
37
+ }
38
+
39
+ // Strategy 2: remote show origin
40
+ try {
41
+ const out = exec('git', ['remote', 'show', 'origin'], {
42
+ cwd: projectRoot,
43
+ stdio: ['pipe', 'pipe', 'pipe'],
44
+ });
45
+ const text = out.toString();
46
+ const match = text.match(/HEAD branch:\s*(.+)/);
47
+ if (match) {
48
+ return match[1].trim();
49
+ }
50
+ } catch (_e) {
51
+ // Expected: 'git remote show origin' fails when no remote is configured — fall through to fallback
52
+ }
53
+
54
+ // Strategy 3: fallback
55
+ return 'main';
56
+ }
57
+
58
+ /**
59
+ * Detect the installed Beads version.
60
+ *
61
+ * Strategy (in order):
62
+ * 1. `bd --version` -> parse version string (e.g. "beads version 0.52.0" -> "0.52.0")
63
+ * 2. Fall back to known-good default `'0.49.1'`
64
+ *
65
+ * @param {object} [options] - Options object.
66
+ * @param {Function} [options._exec] - Injected execFileSync for testing.
67
+ * @returns {string} The Beads version string.
68
+ */
69
+ function detectBeadsVersion(options = {}) {
70
+ const exec = options._exec || execFileSync;
71
+
72
+ try {
73
+ const out = exec('bd', ['--version'], {
74
+ stdio: ['pipe', 'pipe', 'pipe'],
75
+ });
76
+ const text = out.toString().trim();
77
+ // "beads version 0.52.0" -> "0.52.0"
78
+ const match = text.match(/(\d{1,4}\.\d{1,4}\.\d{1,4})/);
79
+ if (match) {
80
+ return match[1];
81
+ }
82
+ } catch (_e) {
83
+ // Expected: 'bd --version' fails when bd CLI is not installed — fall through to default version
84
+ }
85
+
86
+ return '0.49.1';
87
+ }
88
+
89
+ /**
90
+ * Template workflow YAML files by replacing the default branch and Beads version.
91
+ *
92
+ * Templates only forge-created workflow files by replacing the default branch
93
+ * and Beads version. Skips user-owned workflows to avoid overwriting legitimate
94
+ * branch targets.
95
+ *
96
+ * @param {string} workflowDir - Absolute path to the directory containing YAML files.
97
+ * @param {string} branch - The default branch name to substitute.
98
+ * @param {string} beadsVersion - The Beads version to substitute.
99
+ * @param {string[]} [createdFiles=[]] - List of file paths created by scaffoldBeadsSync. Only these are templated.
100
+ */
101
+ function templateWorkflows(workflowDir, branch, beadsVersion, createdFiles = []) {
102
+ if (!fs.existsSync(workflowDir)) return;
103
+
104
+ const targetNames = new Set(createdFiles.map(f => path.basename(f)));
105
+
106
+ const entries = fs.readdirSync(workflowDir);
107
+
108
+ for (const entry of entries) {
109
+ // Only template forge-created files; skip user-owned workflows
110
+ if (targetNames.size > 0 && !targetNames.has(entry)) continue;
111
+
112
+ const ext = path.extname(entry).toLowerCase();
113
+ if (ext !== '.yml' && ext !== '.yaml') {
114
+ continue;
115
+ }
116
+
117
+ const filePath = path.join(workflowDir, entry);
118
+ const stat = fs.statSync(filePath);
119
+ if (!stat.isFile()) {
120
+ continue;
121
+ }
122
+
123
+ const original = fs.readFileSync(filePath, 'utf8');
124
+ let content = original;
125
+ content = content.replaceAll(
126
+ /branches:\s*\[master\]/g,
127
+ `branches: [${branch}]`
128
+ );
129
+ content = content.replaceAll(
130
+ /BD_VERSION="0\.49\.1"/g,
131
+ `BD_VERSION="${beadsVersion}"`
132
+ );
133
+ // Only write if content actually changed
134
+ if (content !== original) {
135
+ fs.writeFileSync(filePath, content);
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * @typedef {Object} ScaffoldResult
142
+ * @property {string[]} filesCreated - Relative paths of files written (new or overwritten)
143
+ * @property {string[]} filesSkipped - Relative paths of files that already existed and were preserved
144
+ */
145
+
146
+ /**
147
+ * Copy a single file from src to dest, creating parent directories as needed.
148
+ *
149
+ * @param {string} src - Absolute source path
150
+ * @param {string} dest - Absolute destination path
151
+ * @returns {void}
152
+ */
153
+ function copyFileWithDirs(src, dest) {
154
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
155
+ fs.copyFileSync(src, dest);
156
+ }
157
+
158
+ /**
159
+ * Scaffold Beads sync workflows and scripts to the user's project.
160
+ *
161
+ * Copies workflow templates, sync modules, config, and mapping stub into
162
+ * the project's `.github/` tree from the forge package source.
163
+ *
164
+ * @param {string} projectRoot - Absolute path to the user's project root
165
+ * @param {string} packageDir - Absolute path to the forge package install location
166
+ * @param {Object} [_options={}] - Reserved for future options
167
+ * @returns {ScaffoldResult}
168
+ */
169
+ function scaffoldBeadsSync(projectRoot, packageDir, _options = {}) {
170
+ /** @type {string[]} */
171
+ const filesCreated = [];
172
+ /** @type {string[]} */
173
+ const filesSkipped = [];
174
+
175
+ const githubDir = path.join(projectRoot, '.github');
176
+
177
+ // --- Step a: Copy workflow templates ---
178
+ const workflowNames = ['github-to-beads.yml', 'beads-to-github.yml'];
179
+ const srcWorkflowsDir = path.join(packageDir, '.github', 'workflows');
180
+
181
+ for (const name of workflowNames) {
182
+ const src = path.join(srcWorkflowsDir, name);
183
+ const relPath = `.github/workflows/${name}`;
184
+ const dest = path.join(projectRoot, '.github', 'workflows', name);
185
+
186
+ if (!fs.existsSync(src)) continue;
187
+ if (fs.existsSync(dest)) {
188
+ filesSkipped.push(relPath);
189
+ } else {
190
+ copyFileWithDirs(src, dest);
191
+ filesCreated.push(relPath);
192
+ }
193
+ }
194
+
195
+ // --- Step b: Copy sync modules ---
196
+ const srcSyncDir = path.join(packageDir, 'scripts', 'github-beads-sync');
197
+ const destSyncDir = path.join(githubDir, 'scripts', 'beads-sync');
198
+
199
+ if (fs.existsSync(srcSyncDir)) {
200
+ const entries = fs.readdirSync(srcSyncDir);
201
+ for (const entry of entries) {
202
+ const srcFile = path.join(srcSyncDir, entry);
203
+ const stat = fs.statSync(srcFile);
204
+ if (stat.isFile()) {
205
+ const relPath = `.github/scripts/beads-sync/${entry}`;
206
+ const dest = path.join(destSyncDir, entry);
207
+ if (fs.existsSync(dest)) {
208
+ filesSkipped.push(relPath);
209
+ } else {
210
+ copyFileWithDirs(srcFile, dest);
211
+ filesCreated.push(relPath);
212
+ }
213
+ }
214
+ }
215
+ }
216
+
217
+ // --- Step c: Create beads-sync-config.json ---
218
+ const configRelPath = '.github/beads-sync-config.json';
219
+ const configDest = path.join(githubDir, 'beads-sync-config.json');
220
+ const srcConfig = path.join(packageDir, 'scripts', 'github-beads-sync.config.json');
221
+
222
+ if (fs.existsSync(configDest)) {
223
+ filesSkipped.push(configRelPath);
224
+ } else if (fs.existsSync(srcConfig)) {
225
+ copyFileWithDirs(srcConfig, configDest);
226
+ filesCreated.push(configRelPath);
227
+ } else {
228
+ // Create a sensible default config
229
+ const defaultConfig = {
230
+ defaultType: 'task',
231
+ defaultPriority: 2,
232
+ mapAssignee: true,
233
+ publicRepoGate: 'none'
234
+ };
235
+ fs.mkdirSync(path.dirname(configDest), { recursive: true });
236
+ fs.writeFileSync(configDest, JSON.stringify(defaultConfig, null, 2) + '\n');
237
+ filesCreated.push(configRelPath);
238
+ }
239
+
240
+ // --- Step d: Create beads-mapping.json if not exists ---
241
+ const mappingRelPath = '.github/beads-mapping.json';
242
+ const mappingDest = path.join(githubDir, 'beads-mapping.json');
243
+
244
+ if (fs.existsSync(mappingDest)) {
245
+ filesSkipped.push(mappingRelPath);
246
+ } else {
247
+ fs.mkdirSync(path.dirname(mappingDest), { recursive: true });
248
+ fs.writeFileSync(mappingDest, '{}');
249
+ filesCreated.push(mappingRelPath);
250
+ }
251
+
252
+ return { filesCreated, filesSkipped };
253
+ }
254
+
255
+ module.exports = {
256
+ detectDefaultBranch,
257
+ detectBeadsVersion,
258
+ templateWorkflows,
259
+ scaffoldBeadsSync,
260
+ };