forge-workflow 0.0.1 → 0.0.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 (150) hide show
  1. package/.claude/commands/plan.md +93 -4
  2. package/.cline/workflows/dev.md +311 -0
  3. package/.cline/workflows/plan.md +475 -0
  4. package/.cline/workflows/premerge.md +176 -0
  5. package/.cline/workflows/research.md +39 -0
  6. package/.cline/workflows/review.md +439 -0
  7. package/.cline/workflows/rollback.md +718 -0
  8. package/.cline/workflows/ship.md +131 -0
  9. package/.cline/workflows/sonarcloud.md +146 -0
  10. package/.cline/workflows/status.md +74 -0
  11. package/.cline/workflows/validate.md +234 -0
  12. package/.cline/workflows/verify.md +218 -0
  13. package/.codex/config.toml +11 -0
  14. package/.codex/skills/dev/SKILL.md +314 -0
  15. package/.codex/skills/plan/SKILL.md +478 -0
  16. package/.codex/skills/premerge/SKILL.md +179 -0
  17. package/.codex/skills/research/SKILL.md +42 -0
  18. package/.codex/skills/review/SKILL.md +442 -0
  19. package/.codex/skills/rollback/SKILL.md +721 -0
  20. package/.codex/skills/ship/SKILL.md +134 -0
  21. package/.codex/skills/sonarcloud/SKILL.md +149 -0
  22. package/.codex/skills/status/SKILL.md +77 -0
  23. package/.codex/skills/validate/SKILL.md +237 -0
  24. package/.codex/skills/verify/SKILL.md +221 -0
  25. package/.cursor/commands/dev.md +311 -0
  26. package/.cursor/commands/plan.md +475 -0
  27. package/.cursor/commands/premerge.md +176 -0
  28. package/.cursor/commands/research.md +39 -0
  29. package/.cursor/commands/review.md +439 -0
  30. package/.cursor/commands/rollback.md +718 -0
  31. package/.cursor/commands/ship.md +131 -0
  32. package/.cursor/commands/sonarcloud.md +146 -0
  33. package/.cursor/commands/status.md +74 -0
  34. package/.cursor/commands/validate.md +234 -0
  35. package/.cursor/commands/verify.md +218 -0
  36. package/.cursor/rules/permissions-guidance.mdc +37 -0
  37. package/.github/prompts/dev.prompt.md +316 -0
  38. package/.github/prompts/plan.prompt.md +480 -0
  39. package/.github/prompts/premerge.prompt.md +181 -0
  40. package/.github/prompts/research.prompt.md +44 -0
  41. package/.github/prompts/review.prompt.md +444 -0
  42. package/.github/prompts/rollback.prompt.md +723 -0
  43. package/.github/prompts/ship.prompt.md +136 -0
  44. package/.github/prompts/sonarcloud.prompt.md +151 -0
  45. package/.github/prompts/status.prompt.md +79 -0
  46. package/.github/prompts/validate.prompt.md +239 -0
  47. package/.github/prompts/verify.prompt.md +223 -0
  48. package/.kilocode/workflows/dev.md +315 -0
  49. package/.kilocode/workflows/plan.md +479 -0
  50. package/.kilocode/workflows/premerge.md +180 -0
  51. package/.kilocode/workflows/research.md +43 -0
  52. package/.kilocode/workflows/review.md +443 -0
  53. package/.kilocode/workflows/rollback.md +722 -0
  54. package/.kilocode/workflows/ship.md +135 -0
  55. package/.kilocode/workflows/sonarcloud.md +150 -0
  56. package/.kilocode/workflows/status.md +78 -0
  57. package/.kilocode/workflows/validate.md +238 -0
  58. package/.kilocode/workflows/verify.md +222 -0
  59. package/.opencode/commands/dev.md +314 -0
  60. package/.opencode/commands/plan.md +478 -0
  61. package/.opencode/commands/premerge.md +179 -0
  62. package/.opencode/commands/research.md +42 -0
  63. package/.opencode/commands/review.md +442 -0
  64. package/.opencode/commands/rollback.md +721 -0
  65. package/.opencode/commands/ship.md +134 -0
  66. package/.opencode/commands/sonarcloud.md +149 -0
  67. package/.opencode/commands/status.md +77 -0
  68. package/.opencode/commands/validate.md +237 -0
  69. package/.opencode/commands/verify.md +221 -0
  70. package/.roo/commands/dev.md +315 -0
  71. package/.roo/commands/plan.md +479 -0
  72. package/.roo/commands/premerge.md +180 -0
  73. package/.roo/commands/research.md +43 -0
  74. package/.roo/commands/review.md +443 -0
  75. package/.roo/commands/rollback.md +722 -0
  76. package/.roo/commands/ship.md +135 -0
  77. package/.roo/commands/sonarcloud.md +150 -0
  78. package/.roo/commands/status.md +78 -0
  79. package/.roo/commands/validate.md +238 -0
  80. package/.roo/commands/verify.md +222 -0
  81. package/LICENSE +21 -21
  82. package/bin/forge.js +8 -4
  83. package/docs/ENHANCED_ONBOARDING.md +2 -2
  84. package/docs/TOOLCHAIN.md +15 -234
  85. package/install.sh +35 -39
  86. package/lib/agents/cline.plugin.json +1 -1
  87. package/lib/agents/roo.plugin.json +1 -1
  88. package/lib/commands/plan.js +11 -15
  89. package/lib/commands/recommend.js +2 -2
  90. package/lib/dep-guard/analyzer.js +294 -0
  91. package/lib/dep-guard/behavior-detector.js +98 -0
  92. package/lib/dep-guard/contract-detector.js +162 -0
  93. package/lib/dep-guard/import-detector.js +498 -0
  94. package/lib/dep-guard/path-utils.js +13 -0
  95. package/lib/dep-guard/rubric.js +120 -0
  96. package/lib/dep-guard/task-parser.js +318 -0
  97. package/lib/plugin-catalog.js +18 -28
  98. package/lib/workflow-profiles.js +5 -11
  99. package/package.json +18 -4
  100. package/skills/parallel-deep-research/SKILL.md +108 -0
  101. package/skills/parallel-deep-research/evals/README.md +27 -0
  102. package/skills/parallel-deep-research/evals/evals.json +62 -0
  103. package/skills/sonarcloud-analysis/SKILL.md +171 -0
  104. package/skills/sonarcloud-analysis/evals/README.md +27 -0
  105. package/skills/sonarcloud-analysis/evals/evals.json +50 -0
  106. package/skills/sonarcloud-analysis/references/api-reference.md +466 -0
  107. package/docs/planning/PROGRESS.md +0 -396
  108. package/docs/plans/.gitkeep +0 -0
  109. package/docs/plans/2026-02-27-forge-test-suite-v2-decisions.md +0 -21
  110. package/docs/plans/2026-02-27-forge-test-suite-v2-design.md +0 -362
  111. package/docs/plans/2026-02-27-forge-test-suite-v2-tasks.md +0 -343
  112. package/docs/plans/2026-03-02-superpowers-gaps-decisions.md +0 -26
  113. package/docs/plans/2026-03-02-superpowers-gaps-design.md +0 -239
  114. package/docs/plans/2026-03-02-superpowers-gaps-tasks.md +0 -260
  115. package/docs/plans/2026-03-04-agent-command-parity-design.md +0 -163
  116. package/docs/plans/2026-03-04-verify-worktree-cleanup-decisions.md +0 -7
  117. package/docs/plans/2026-03-04-verify-worktree-cleanup-design.md +0 -165
  118. package/docs/plans/2026-03-05-forge-uto-decisions.md +0 -6
  119. package/docs/plans/2026-03-05-forge-uto-design.md +0 -116
  120. package/docs/plans/2026-03-05-forge-uto-tasks.md +0 -244
  121. package/docs/plans/2026-03-10-command-creator-and-eval-decisions.md +0 -52
  122. package/docs/plans/2026-03-10-command-creator-and-eval-design.md +0 -350
  123. package/docs/plans/2026-03-10-command-creator-and-eval-tasks.md +0 -426
  124. package/docs/plans/2026-03-10-stale-workflow-refs-decisions.md +0 -8
  125. package/docs/plans/2026-03-10-stale-workflow-refs-design.md +0 -80
  126. package/docs/plans/2026-03-10-stale-workflow-refs-tasks.md +0 -90
  127. package/docs/plans/2026-03-14-beads-plan-context-decisions.md +0 -9
  128. package/docs/plans/2026-03-14-beads-plan-context-design.md +0 -171
  129. package/docs/plans/2026-03-14-beads-plan-context-tasks.md +0 -160
  130. package/docs/plans/2026-03-14-skill-eval-loop-decisions.md +0 -33
  131. package/docs/plans/2026-03-14-skill-eval-loop-design.md +0 -118
  132. package/docs/plans/2026-03-14-skill-eval-loop-results.md +0 -78
  133. package/docs/plans/2026-03-14-skill-eval-loop-tasks.md +0 -160
  134. package/docs/plans/2026-03-15-agent-command-parity-v2-decisions.md +0 -11
  135. package/docs/plans/2026-03-15-agent-command-parity-v2-design.md +0 -145
  136. package/docs/plans/2026-03-15-agent-command-parity-v2-tasks.md +0 -211
  137. package/docs/research/TEMPLATE.md +0 -292
  138. package/docs/research/advanced-testing.md +0 -297
  139. package/docs/research/agent-permissions.md +0 -167
  140. package/docs/research/dependency-chain.md +0 -328
  141. package/docs/research/forge-workflow-v2.md +0 -550
  142. package/docs/research/plugin-architecture.md +0 -772
  143. package/docs/research/pr4-cli-automation.md +0 -326
  144. package/docs/research/premerge-verify-restructure.md +0 -205
  145. package/docs/research/skills-restructure.md +0 -508
  146. package/docs/research/sonarcloud-perfection-plan.md +0 -166
  147. package/docs/research/sonarcloud-quality-gate.md +0 -184
  148. package/docs/research/superpowers-integration.md +0 -403
  149. package/docs/research/superpowers.md +0 -319
  150. package/docs/research/test-environment.md +0 -519
@@ -0,0 +1,98 @@
1
+ const STOP_WORDS = new Set([
2
+ 'the', 'a', 'an', 'and', 'or', 'is', 'in', 'to', 'for', 'of', 'with', 'on',
3
+ 'at', 'by', 'from', 'add', 'fix', 'update', 'implement', 'create', 'remove',
4
+ 'delete', 'make', 'use', 'get', 'set', 'run', 'test', 'check', 'this', 'that',
5
+ 'it', 'be', 'as', 'not', 'no', 'but', 'if', 'do', 'we', 'they', 'are', 'was',
6
+ 'were', 'been', 'have', 'has', 'had', 'will', 'would', 'could', 'should',
7
+ 'may', 'can', 'each', 'every', 'both', 'also', 'into', 'than', 'then', 'when',
8
+ 'where', 'which', 'what', 'how', 'why', 'who', 'its', 'new', 'first', 'last',
9
+ 'same', 'other',
10
+ ]);
11
+
12
+ const BEHAVIOR_TERMS = new Set([
13
+ 'approval', 'behavior', 'confidence', 'default', 'manual', 'ordering',
14
+ 'output', 'policy', 'review', 'rules', 'rule', 'threshold', 'validation',
15
+ 'workflow', 'state',
16
+ ]);
17
+ const STRONG_SIGNAL_TERMS = new Set([
18
+ 'approval',
19
+ 'confidence',
20
+ 'manual',
21
+ 'policy',
22
+ 'review',
23
+ 'rule',
24
+ 'rules',
25
+ 'threshold',
26
+ ]);
27
+
28
+ function tokenize(text) {
29
+ return Array.from(new Set(
30
+ text
31
+ .toLowerCase()
32
+ .split(/[^a-z0-9]+/)
33
+ .filter((term) => term.length >= 3 && !STOP_WORDS.has(term)),
34
+ ));
35
+ }
36
+
37
+ function scoreBehavioralDependencies(normalizedInput) {
38
+ const taskText = normalizedInput.taskContext.tasks
39
+ .map((task) => task.whatToImplement)
40
+ .join(' ');
41
+ const taskTerms = tokenize(taskText).filter((term) => BEHAVIOR_TERMS.has(term));
42
+
43
+ if (taskTerms.length === 0) {
44
+ return {
45
+ score: 0,
46
+ findings: [],
47
+ evidence: [],
48
+ uncertain: false,
49
+ };
50
+ }
51
+
52
+ const findings = [];
53
+ const evidence = [];
54
+
55
+ for (const issue of normalizedInput.openIssues) {
56
+ const issueText = [issue.title, issue.description, issue.notes].filter(Boolean).join(' ');
57
+ const issueTerms = new Set(tokenize(issueText));
58
+ const sharedTerms = taskTerms.filter((term) => issueTerms.has(term));
59
+
60
+ if (sharedTerms.length < 2) {
61
+ continue;
62
+ }
63
+
64
+ const strongSignalCount = sharedTerms.filter((term) => STRONG_SIGNAL_TERMS.has(term)).length;
65
+ const isUncertain = strongSignalCount < 2 || sharedTerms.length < 3;
66
+ const signal = sharedTerms.some((term) => ['rule', 'rules', 'policy', 'approval'].includes(term))
67
+ ? 'rule-change-overlap'
68
+ : 'behavior-change-overlap';
69
+ const issueEvidence = sharedTerms.map((term) => ({
70
+ type: 'behavior',
71
+ targetIssueId: issue.id,
72
+ sharedTerms: sharedTerms,
73
+ term,
74
+ scoreContribution: 1,
75
+ }));
76
+
77
+ findings.push({
78
+ sourceIssueId: normalizedInput.currentIssue.id,
79
+ targetIssueId: issue.id,
80
+ score: sharedTerms.length,
81
+ behavioralSignal: signal,
82
+ uncertain: isUncertain,
83
+ evidence: issueEvidence,
84
+ });
85
+ evidence.push(...issueEvidence);
86
+ }
87
+
88
+ return {
89
+ score: findings.reduce((total, finding) => total + finding.score, 0),
90
+ findings,
91
+ evidence,
92
+ uncertain: findings.some((finding) => finding.uncertain),
93
+ };
94
+ }
95
+
96
+ module.exports = {
97
+ scoreBehavioralDependencies,
98
+ };
@@ -0,0 +1,162 @@
1
+ const { detectContractType, extractTaskContracts } = require('./task-parser.js');
2
+ const { normalizeRepoPath } = require('./path-utils.js');
3
+
4
+ function isIdentifier(name) {
5
+ return typeof name === 'string' && /^[A-Za-z_]\w*$/.test(name);
6
+ }
7
+
8
+ function isCommandContractName(name) {
9
+ return typeof name === 'string' && /^[A-Za-z_][\w-]*$/.test(name);
10
+ }
11
+
12
+ function parseContractToken(token) {
13
+ if (typeof token !== 'string') {
14
+ return null;
15
+ }
16
+
17
+ const trimmed = token.trim();
18
+ if (!trimmed) {
19
+ return null;
20
+ }
21
+
22
+ let annotation = '';
23
+ let contractTarget = trimmed;
24
+ const openParenIndex = trimmed.lastIndexOf('(');
25
+ if (openParenIndex !== -1 && trimmed.endsWith(')')) {
26
+ annotation = trimmed.slice(openParenIndex + 1, -1);
27
+ contractTarget = trimmed.slice(0, openParenIndex);
28
+ }
29
+
30
+ const separatorIndex = contractTarget.lastIndexOf(':');
31
+ if (separatorIndex <= 0 || separatorIndex === contractTarget.length - 1) {
32
+ return null;
33
+ }
34
+
35
+ const file = normalizeRepoPath(contractTarget.slice(0, separatorIndex));
36
+ const symbol = contractTarget.slice(separatorIndex + 1);
37
+ const contractType = detectContractType(symbol, annotation);
38
+
39
+ const validSymbol = contractType === 'command-contract'
40
+ ? isCommandContractName(symbol)
41
+ : isIdentifier(symbol);
42
+ if (!validSymbol) {
43
+ return null;
44
+ }
45
+
46
+ return {
47
+ contract: `${file}:${symbol}(${contractType})`,
48
+ file,
49
+ symbol,
50
+ contractType,
51
+ };
52
+ }
53
+
54
+ function parseStoredContractsFromNotes(notes = '') {
55
+ if (!notes || typeof notes !== 'string') {
56
+ return [];
57
+ }
58
+
59
+ const contractLines = notes
60
+ .split(/\r?\n/)
61
+ .filter((line) => line.startsWith('contracts@') && line.includes(': '));
62
+ if (contractLines.length === 0) {
63
+ return [];
64
+ }
65
+
66
+ contractLines.sort((left, right) => left.localeCompare(right));
67
+ const latestLine = contractLines.at(-1);
68
+ const latestPayload = latestLine.slice(latestLine.indexOf(': ') + 2);
69
+
70
+ return latestPayload
71
+ .split(/\s+/)
72
+ .map((token) => token.trim())
73
+ .filter(Boolean);
74
+ }
75
+
76
+ function mergeEvidence(evidence) {
77
+ const seen = new Set();
78
+ return evidence.filter((item) => {
79
+ const key = `${item.contract}:${item.storedContract}:${item.targetIssueId}`;
80
+ if (seen.has(key)) {
81
+ return false;
82
+ }
83
+ seen.add(key);
84
+ return true;
85
+ });
86
+ }
87
+
88
+ function scoreContractDependencies(normalizedInput) {
89
+ const currentContracts = extractTaskContracts(normalizedInput.taskContext, {
90
+ repositoryRoot: normalizedInput.repositoryRoot,
91
+ })
92
+ .map(parseContractToken)
93
+ .filter(Boolean);
94
+
95
+ if (currentContracts.length === 0) {
96
+ return {
97
+ score: 0,
98
+ findings: [],
99
+ evidence: [],
100
+ };
101
+ }
102
+
103
+ const findings = [];
104
+ const evidence = [];
105
+
106
+ for (const issue of normalizedInput.openIssues) {
107
+ const issueContracts = Array.from(new Set([
108
+ ...issue.contracts,
109
+ ...parseStoredContractsFromNotes(issue.notes),
110
+ ]))
111
+ .map(parseContractToken)
112
+ .filter(Boolean);
113
+
114
+ const issueEvidence = [];
115
+ for (const currentContract of currentContracts) {
116
+ for (const storedContract of issueContracts) {
117
+ if (
118
+ currentContract.file !== storedContract.file
119
+ || currentContract.symbol !== storedContract.symbol
120
+ || currentContract.contractType !== storedContract.contractType
121
+ ) {
122
+ continue;
123
+ }
124
+
125
+ issueEvidence.push({
126
+ type: 'contract',
127
+ sourceIssueId: normalizedInput.currentIssue.id,
128
+ targetIssueId: issue.id,
129
+ contract: currentContract.contract,
130
+ storedContract: storedContract.contract,
131
+ symbol: currentContract.symbol,
132
+ contractType: currentContract.contractType,
133
+ scoreContribution: 1,
134
+ });
135
+ }
136
+ }
137
+
138
+ if (issueEvidence.length === 0) {
139
+ continue;
140
+ }
141
+
142
+ const mergedEvidence = mergeEvidence(issueEvidence);
143
+ findings.push({
144
+ sourceIssueId: normalizedInput.currentIssue.id,
145
+ targetIssueId: issue.id,
146
+ score: mergedEvidence.length,
147
+ evidence: mergedEvidence,
148
+ });
149
+ evidence.push(...mergedEvidence);
150
+ }
151
+
152
+ return {
153
+ score: findings.reduce((total, finding) => total + finding.score, 0),
154
+ findings,
155
+ evidence: mergeEvidence(evidence),
156
+ };
157
+ }
158
+
159
+ module.exports = {
160
+ parseStoredContractsFromNotes,
161
+ scoreContractDependencies,
162
+ };