specweave 1.0.235 → 1.0.239

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 (196) hide show
  1. package/README.md +89 -193
  2. package/dist/plugins/specweave-github/lib/github-ac-comment-poster.d.ts +37 -0
  3. package/dist/plugins/specweave-github/lib/github-ac-comment-poster.d.ts.map +1 -0
  4. package/dist/plugins/specweave-github/lib/github-ac-comment-poster.js +176 -0
  5. package/dist/plugins/specweave-github/lib/github-ac-comment-poster.js.map +1 -0
  6. package/dist/plugins/specweave-github/lib/github-batch-sync.d.ts +36 -0
  7. package/dist/plugins/specweave-github/lib/github-batch-sync.d.ts.map +1 -0
  8. package/dist/plugins/specweave-github/lib/github-batch-sync.js +115 -0
  9. package/dist/plugins/specweave-github/lib/github-batch-sync.js.map +1 -0
  10. package/dist/plugins/specweave-github/lib/github-board-resolver-v2.d.ts +37 -0
  11. package/dist/plugins/specweave-github/lib/github-board-resolver-v2.d.ts.map +1 -0
  12. package/dist/plugins/specweave-github/lib/github-board-resolver-v2.js +56 -0
  13. package/dist/plugins/specweave-github/lib/github-board-resolver-v2.js.map +1 -0
  14. package/dist/plugins/specweave-github/lib/github-conflict-resolver.d.ts +68 -0
  15. package/dist/plugins/specweave-github/lib/github-conflict-resolver.d.ts.map +1 -0
  16. package/dist/plugins/specweave-github/lib/github-conflict-resolver.js +102 -0
  17. package/dist/plugins/specweave-github/lib/github-conflict-resolver.js.map +1 -0
  18. package/dist/plugins/specweave-github/lib/github-cross-repo-sync.d.ts +64 -0
  19. package/dist/plugins/specweave-github/lib/github-cross-repo-sync.d.ts.map +1 -0
  20. package/dist/plugins/specweave-github/lib/github-cross-repo-sync.js +162 -0
  21. package/dist/plugins/specweave-github/lib/github-cross-repo-sync.js.map +1 -0
  22. package/dist/plugins/specweave-github/lib/github-field-sync.d.ts +50 -0
  23. package/dist/plugins/specweave-github/lib/github-field-sync.d.ts.map +1 -0
  24. package/dist/plugins/specweave-github/lib/github-field-sync.js +107 -0
  25. package/dist/plugins/specweave-github/lib/github-field-sync.js.map +1 -0
  26. package/dist/plugins/specweave-github/lib/github-graphql-client.d.ts +53 -0
  27. package/dist/plugins/specweave-github/lib/github-graphql-client.d.ts.map +1 -0
  28. package/dist/plugins/specweave-github/lib/github-graphql-client.js +138 -0
  29. package/dist/plugins/specweave-github/lib/github-graphql-client.js.map +1 -0
  30. package/dist/plugins/specweave-github/lib/github-issue-body-generator.d.ts +40 -0
  31. package/dist/plugins/specweave-github/lib/github-issue-body-generator.d.ts.map +1 -0
  32. package/dist/plugins/specweave-github/lib/github-issue-body-generator.js +50 -0
  33. package/dist/plugins/specweave-github/lib/github-issue-body-generator.js.map +1 -0
  34. package/dist/plugins/specweave-github/lib/github-issue-body-parser.d.ts +30 -0
  35. package/dist/plugins/specweave-github/lib/github-issue-body-parser.d.ts.map +1 -0
  36. package/dist/plugins/specweave-github/lib/github-issue-body-parser.js +75 -0
  37. package/dist/plugins/specweave-github/lib/github-issue-body-parser.js.map +1 -0
  38. package/dist/plugins/specweave-github/lib/github-pull-sync.d.ts +94 -0
  39. package/dist/plugins/specweave-github/lib/github-pull-sync.d.ts.map +1 -0
  40. package/dist/plugins/specweave-github/lib/github-pull-sync.js +232 -0
  41. package/dist/plugins/specweave-github/lib/github-pull-sync.js.map +1 -0
  42. package/dist/plugins/specweave-github/lib/github-push-sync.d.ts +50 -0
  43. package/dist/plugins/specweave-github/lib/github-push-sync.d.ts.map +1 -0
  44. package/dist/plugins/specweave-github/lib/github-push-sync.js +114 -0
  45. package/dist/plugins/specweave-github/lib/github-push-sync.js.map +1 -0
  46. package/dist/plugins/specweave-github/lib/github-rate-limiter.d.ts +53 -0
  47. package/dist/plugins/specweave-github/lib/github-rate-limiter.d.ts.map +1 -0
  48. package/dist/plugins/specweave-github/lib/github-rate-limiter.js +109 -0
  49. package/dist/plugins/specweave-github/lib/github-rate-limiter.js.map +1 -0
  50. package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.d.ts +21 -0
  51. package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.d.ts.map +1 -0
  52. package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.js +161 -0
  53. package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.js.map +1 -0
  54. package/dist/plugins/specweave-github/lib/github-sync-orchestrator.d.ts +46 -0
  55. package/dist/plugins/specweave-github/lib/github-sync-orchestrator.d.ts.map +1 -0
  56. package/dist/plugins/specweave-github/lib/github-sync-orchestrator.js +99 -0
  57. package/dist/plugins/specweave-github/lib/github-sync-orchestrator.js.map +1 -0
  58. package/dist/plugins/specweave-github/lib/github-us-auto-closer.d.ts +43 -0
  59. package/dist/plugins/specweave-github/lib/github-us-auto-closer.d.ts.map +1 -0
  60. package/dist/plugins/specweave-github/lib/github-us-auto-closer.js +153 -0
  61. package/dist/plugins/specweave-github/lib/github-us-auto-closer.js.map +1 -0
  62. package/dist/plugins/specweave-github/lib/index.d.ts +1 -4
  63. package/dist/plugins/specweave-github/lib/index.d.ts.map +1 -1
  64. package/dist/plugins/specweave-github/lib/index.js +1 -4
  65. package/dist/plugins/specweave-github/lib/index.js.map +1 -1
  66. package/dist/plugins/specweave-testing/lib/playwright-ci-defaults.d.ts +7 -0
  67. package/dist/plugins/specweave-testing/lib/playwright-ci-defaults.d.ts.map +1 -0
  68. package/dist/plugins/specweave-testing/lib/playwright-ci-defaults.js +15 -0
  69. package/dist/plugins/specweave-testing/lib/playwright-ci-defaults.js.map +1 -0
  70. package/dist/plugins/specweave-testing/lib/playwright-cli-detector.d.ts +10 -0
  71. package/dist/plugins/specweave-testing/lib/playwright-cli-detector.d.ts.map +1 -0
  72. package/dist/plugins/specweave-testing/lib/playwright-cli-detector.js +36 -0
  73. package/dist/plugins/specweave-testing/lib/playwright-cli-detector.js.map +1 -0
  74. package/dist/plugins/specweave-testing/lib/playwright-cli-runner.d.ts +25 -0
  75. package/dist/plugins/specweave-testing/lib/playwright-cli-runner.d.ts.map +1 -0
  76. package/dist/plugins/specweave-testing/lib/playwright-cli-runner.js +57 -0
  77. package/dist/plugins/specweave-testing/lib/playwright-cli-runner.js.map +1 -0
  78. package/dist/plugins/specweave-testing/lib/playwright-routing.d.ts +7 -0
  79. package/dist/plugins/specweave-testing/lib/playwright-routing.d.ts.map +1 -0
  80. package/dist/plugins/specweave-testing/lib/playwright-routing.js +17 -0
  81. package/dist/plugins/specweave-testing/lib/playwright-routing.js.map +1 -0
  82. package/dist/src/cli/commands/auto.d.ts.map +1 -1
  83. package/dist/src/cli/commands/auto.js +1 -2
  84. package/dist/src/cli/commands/auto.js.map +1 -1
  85. package/dist/src/cli/commands/cancel-auto.js +1 -2
  86. package/dist/src/cli/commands/cancel-auto.js.map +1 -1
  87. package/dist/src/cli/commands/living-docs.js +2 -2
  88. package/dist/src/cli/commands/living-docs.js.map +1 -1
  89. package/dist/src/cli/commands/update.d.ts.map +1 -1
  90. package/dist/src/cli/commands/update.js +1 -2
  91. package/dist/src/cli/commands/update.js.map +1 -1
  92. package/dist/src/core/config/types.d.ts +8 -0
  93. package/dist/src/core/config/types.d.ts.map +1 -1
  94. package/dist/src/core/config/types.js +3 -0
  95. package/dist/src/core/config/types.js.map +1 -1
  96. package/dist/src/core/types/sync-profile.d.ts +72 -0
  97. package/dist/src/core/types/sync-profile.d.ts.map +1 -1
  98. package/dist/src/core/types/sync-profile.js +6 -0
  99. package/dist/src/core/types/sync-profile.js.map +1 -1
  100. package/package.json +2 -2
  101. package/plugins/specweave/hooks/hooks.json +2 -2
  102. package/plugins/specweave/hooks/startup-health-check.sh +1 -1
  103. package/plugins/specweave/hooks/stop-auto-v5.sh +166 -0
  104. package/plugins/specweave/hooks/user-prompt-submit.sh +10 -0
  105. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +21 -1
  106. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +1 -1
  107. package/plugins/specweave/skills/auto/SKILL.md +71 -251
  108. package/plugins/specweave/skills/team-build/SKILL.md +370 -0
  109. package/plugins/specweave/skills/team-merge/SKILL.md +123 -0
  110. package/plugins/specweave/skills/team-orchestrate/SKILL.md +800 -0
  111. package/plugins/specweave/skills/team-status/SKILL.md +89 -0
  112. package/plugins/specweave-github/MULTI-PROJECT-SYNC-ARCHITECTURE.md +94 -8
  113. package/plugins/specweave-github/commands/sync.md +17 -3
  114. package/plugins/specweave-github/hooks/github-ac-sync-handler.sh +255 -0
  115. package/plugins/specweave-github/hooks/github-auto-create-handler.sh +455 -0
  116. package/plugins/specweave-github/lib/github-ac-comment-poster.js +150 -0
  117. package/plugins/specweave-github/lib/github-ac-comment-poster.ts +245 -0
  118. package/plugins/specweave-github/lib/github-batch-sync.js +93 -0
  119. package/plugins/specweave-github/lib/github-batch-sync.ts +152 -0
  120. package/plugins/specweave-github/lib/github-board-resolver-v2.js +47 -0
  121. package/plugins/specweave-github/lib/github-board-resolver-v2.ts +73 -0
  122. package/plugins/specweave-github/lib/github-conflict-resolver.js +90 -0
  123. package/plugins/specweave-github/lib/github-conflict-resolver.ts +154 -0
  124. package/plugins/specweave-github/lib/github-cross-repo-sync.js +168 -0
  125. package/plugins/specweave-github/lib/github-cross-repo-sync.ts +252 -0
  126. package/plugins/specweave-github/lib/github-field-sync.js +116 -0
  127. package/plugins/specweave-github/lib/github-field-sync.ts +165 -0
  128. package/plugins/specweave-github/lib/github-graphql-client.js +129 -0
  129. package/plugins/specweave-github/lib/github-graphql-client.ts +181 -0
  130. package/plugins/specweave-github/lib/github-issue-body-generator.js +30 -0
  131. package/plugins/specweave-github/lib/github-issue-body-generator.ts +76 -0
  132. package/plugins/specweave-github/lib/github-issue-body-parser.js +55 -0
  133. package/plugins/specweave-github/lib/github-issue-body-parser.ts +92 -0
  134. package/plugins/specweave-github/lib/github-pull-sync.js +185 -0
  135. package/plugins/specweave-github/lib/github-pull-sync.ts +343 -0
  136. package/plugins/specweave-github/lib/github-push-sync.js +119 -0
  137. package/plugins/specweave-github/lib/github-push-sync.ts +174 -0
  138. package/plugins/specweave-github/lib/github-rate-limiter.js +96 -0
  139. package/plugins/specweave-github/lib/github-rate-limiter.ts +143 -0
  140. package/plugins/specweave-github/lib/github-spec-frontmatter-updater.js +117 -0
  141. package/plugins/specweave-github/lib/github-spec-frontmatter-updater.ts +180 -0
  142. package/plugins/specweave-github/lib/github-sync-orchestrator.js +84 -0
  143. package/plugins/specweave-github/lib/github-sync-orchestrator.ts +156 -0
  144. package/plugins/specweave-github/lib/github-us-auto-closer.js +134 -0
  145. package/plugins/specweave-github/lib/github-us-auto-closer.ts +226 -0
  146. package/plugins/specweave-github/lib/index.js +1 -7
  147. package/plugins/specweave-github/lib/index.ts +1 -4
  148. package/plugins/specweave-github/skills/github-sync/SKILL.md +76 -4
  149. package/plugins/specweave-testing/commands/e2e-setup.md +18 -0
  150. package/plugins/specweave-testing/commands/ui-automate.md +2 -0
  151. package/plugins/specweave-testing/commands/ui-inspect.md +8 -0
  152. package/plugins/specweave-testing/lib/playwright-ci-defaults.d.ts +6 -0
  153. package/plugins/specweave-testing/lib/playwright-ci-defaults.js +14 -0
  154. package/plugins/specweave-testing/lib/playwright-ci-defaults.ts +24 -0
  155. package/plugins/specweave-testing/lib/playwright-cli-detector.js +33 -0
  156. package/plugins/specweave-testing/lib/playwright-cli-detector.ts +48 -0
  157. package/plugins/specweave-testing/lib/playwright-cli-runner.js +58 -0
  158. package/plugins/specweave-testing/lib/playwright-cli-runner.ts +80 -0
  159. package/plugins/specweave-testing/lib/playwright-routing.js +16 -0
  160. package/plugins/specweave-testing/lib/playwright-routing.ts +38 -0
  161. package/plugins/specweave-testing/skills/e2e-testing/SKILL.md +38 -0
  162. package/src/templates/CLAUDE.md.template +7 -0
  163. package/src/templates/config.json.template +9 -1
  164. package/dist/plugins/specweave-github/lib/subtask-sync.d.ts +0 -51
  165. package/dist/plugins/specweave-github/lib/subtask-sync.d.ts.map +0 -1
  166. package/dist/plugins/specweave-github/lib/subtask-sync.js +0 -147
  167. package/dist/plugins/specweave-github/lib/subtask-sync.js.map +0 -1
  168. package/dist/plugins/specweave-github/lib/task-parser.d.ts +0 -37
  169. package/dist/plugins/specweave-github/lib/task-parser.d.ts.map +0 -1
  170. package/dist/plugins/specweave-github/lib/task-parser.js +0 -211
  171. package/dist/plugins/specweave-github/lib/task-parser.js.map +0 -1
  172. package/dist/plugins/specweave-github/lib/task-sync.d.ts +0 -56
  173. package/dist/plugins/specweave-github/lib/task-sync.d.ts.map +0 -1
  174. package/dist/plugins/specweave-github/lib/task-sync.js +0 -375
  175. package/dist/plugins/specweave-github/lib/task-sync.js.map +0 -1
  176. package/plugins/specweave/hooks/validate-completion-conditions.sh +0 -474
  177. package/plugins/specweave-github/lib/subtask-sync.d.ts +0 -51
  178. package/plugins/specweave-github/lib/subtask-sync.d.ts.map +0 -1
  179. package/plugins/specweave-github/lib/subtask-sync.js +0 -154
  180. package/plugins/specweave-github/lib/subtask-sync.js.map +0 -1
  181. package/plugins/specweave-github/lib/subtask-sync.ts +0 -225
  182. package/plugins/specweave-github/lib/task-parser.d.js +0 -0
  183. package/plugins/specweave-github/lib/task-parser.d.ts +0 -37
  184. package/plugins/specweave-github/lib/task-parser.d.ts.map +0 -1
  185. package/plugins/specweave-github/lib/task-parser.js +0 -195
  186. package/plugins/specweave-github/lib/task-parser.js.map +0 -1
  187. package/plugins/specweave-github/lib/task-parser.ts +0 -246
  188. package/plugins/specweave-github/lib/task-sync.d.js +0 -0
  189. package/plugins/specweave-github/lib/task-sync.d.ts +0 -51
  190. package/plugins/specweave-github/lib/task-sync.d.ts.map +0 -1
  191. package/plugins/specweave-github/lib/task-sync.js +0 -415
  192. package/plugins/specweave-github/lib/task-sync.js.map +0 -1
  193. package/plugins/specweave-github/lib/task-sync.ts +0 -451
  194. package/plugins/specweave-github/skills/github-issue-tracker/SKILL.md +0 -496
  195. /package/plugins/specweave/hooks/{stop-auto.sh → _archive/stop-auto-v4-legacy.sh} +0 -0
  196. /package/plugins/{specweave-github/lib/subtask-sync.d.js → specweave-testing/lib/playwright-ci-defaults.d.js} +0 -0
@@ -1,451 +0,0 @@
1
- /**
2
- * Task-level GitHub synchronization
3
- * Orchestrates syncing tasks.md to GitHub issues
4
- */
5
-
6
- import * as fs from 'fs';
7
- import * as path from 'path';
8
- import * as yaml from 'js-yaml';
9
- import { GitHubClient } from './github-client';
10
- import { TaskParser } from './task-parser';
11
- import { Task, IncrementMetadata, SyncResult, GitHubSyncOptions } from './types';
12
-
13
- export class TaskSync {
14
- private client: GitHubClient;
15
- private incrementPath: string;
16
-
17
- constructor(incrementPath: string, repo?: string) {
18
- this.incrementPath = incrementPath;
19
- this.client = new GitHubClient(repo);
20
- }
21
-
22
- /**
23
- * Sync all tasks to GitHub (main entry point)
24
- */
25
- async syncTasks(options: GitHubSyncOptions = {}): Promise<SyncResult> {
26
- const {
27
- force = false,
28
- dryRun = false,
29
- batchDelay = 6000,
30
- batchSize = 10,
31
- milestoneDays = 2, // SpecWeave default: 2 days (AI velocity)
32
- projectName,
33
- fastMode = false
34
- } = options;
35
-
36
- console.log(`\nšŸ”„ Syncing increment to GitHub...`);
37
-
38
- // 1. Check prerequisites
39
- const ghCheck = GitHubClient.checkGitHubCLI();
40
- if (!ghCheck.installed || !ghCheck.authenticated) {
41
- throw new Error(ghCheck.error || 'GitHub CLI check failed');
42
- }
43
-
44
- // 2. Load increment metadata
45
- const metadata = this.loadIncrementMetadata();
46
- console.log(`šŸ“¦ Increment: ${metadata.id} - ${metadata.title}`);
47
-
48
- // 3. Parse tasks
49
- const tasks = TaskParser.parseTasksFile(this.incrementPath);
50
- console.log(`šŸ“‹ Found ${tasks.length} tasks`);
51
-
52
- if (dryRun) {
53
- console.log(`\nšŸ” DRY RUN MODE - No changes will be made`);
54
- this.printDryRunSummary(tasks, metadata);
55
- return {
56
- epic: {} as any,
57
- tasks: [],
58
- errors: []
59
- };
60
- }
61
-
62
- // 4. Check if already synced (and force not set)
63
- if (metadata.github?.epic_issue && !force) {
64
- console.log(`\nāš ļø Increment already synced to GitHub (epic #${metadata.github.epic_issue})`);
65
- console.log(` Use --force to re-sync (WARNING: will create duplicate issues)`);
66
- throw new Error('Already synced. Use --force to override.');
67
- }
68
-
69
- const errors: Array<{ taskId?: string; error: string }> = [];
70
-
71
- try {
72
- // 5. Create or get milestone (with SpecWeave AI velocity: 1-2 days)
73
- const milestoneTitle = this.getMilestoneTitle(metadata);
74
- console.log(`\nšŸ“ Creating milestone: ${milestoneTitle} (due in ${milestoneDays} days)`);
75
- const milestone = await this.client.createOrGetMilestone(
76
- milestoneTitle,
77
- `Milestone for increment ${metadata.id}`,
78
- milestoneDays
79
- );
80
- console.log(` āœ… Milestone #${milestone.number}: ${milestone.title}`);
81
-
82
- // 6. Create epic issue
83
- console.log(`\nšŸŽÆ Creating epic issue for increment ${metadata.id}...`);
84
-
85
- // Get issue prefix from metadata.json (with created date)
86
- const issuePrefix = this.getIssuePrefix(metadata.id);
87
-
88
- const epicBody = this.generateEpicBody(metadata, tasks);
89
- const epic = await this.client.createEpicIssue(
90
- `[${issuePrefix}] ${metadata.title}`,
91
- epicBody,
92
- milestone.title,
93
- ['increment', 'specweave', metadata.priority.toLowerCase()]
94
- );
95
- console.log(` āœ… Epic issue #${epic.number}: ${epic.html_url}`);
96
-
97
- // 7. Create task issues (with smart rate limiting)
98
- // Fast mode: Skip delays for small increments (< 10 tasks) or when explicitly requested
99
- const useFastMode = fastMode || tasks.length < 10;
100
- const effectiveDelay = useFastMode ? 0 : batchDelay;
101
-
102
- if (useFastMode) {
103
- console.log(`\nšŸ“ Creating ${tasks.length} task issues (fast mode - no rate limiting)...`);
104
- } else {
105
- console.log(`\nšŸ“ Creating ${tasks.length} task issues (batch size: ${batchSize}, delay: ${effectiveDelay}ms)...`);
106
- }
107
-
108
- const taskIssues: Array<{ taskId: string; issue: any }> = [];
109
- const issueData = tasks.map(task => ({
110
- title: `[${task.id}] ${task.title}`,
111
- body: this.generateTaskBody(task),
112
- labels: ['task', task.priority.toLowerCase(), ...(task.phase ? [this.slugify(task.phase)] : [])]
113
- }));
114
-
115
- const createdIssues = await this.client.batchCreateIssues(
116
- issueData,
117
- milestone.title,
118
- epic.number,
119
- { batchSize, delayMs: effectiveDelay }
120
- );
121
-
122
- // TODO: GitHub Projects integration (if projectName provided)
123
- // if (projectName) {
124
- // await this.addIssuesToProject(projectName, [epic, ...createdIssues]);
125
- // }
126
-
127
- // Map issues to tasks
128
- for (let i = 0; i < tasks.length; i++) {
129
- if (createdIssues[i]) {
130
- taskIssues.push({
131
- taskId: tasks[i].id,
132
- issue: createdIssues[i]
133
- });
134
- console.log(` āœ… #${createdIssues[i].number}: [${tasks[i].id}] ${tasks[i].title}`);
135
- } else {
136
- errors.push({
137
- taskId: tasks[i].id,
138
- error: 'Failed to create issue'
139
- });
140
- console.log(` āŒ [${tasks[i].id}] ${tasks[i].title} - Failed`);
141
- }
142
- }
143
-
144
- // 8. Update tasks.md with GitHub issue numbers
145
- console.log(`\nšŸ“„ Updating tasks.md with GitHub issue numbers...`);
146
- const taskIssueMap: Record<string, number> = {};
147
- taskIssues.forEach(({ taskId, issue }) => {
148
- taskIssueMap[taskId] = issue.number;
149
- });
150
- TaskParser.updateTasksWithGitHubIssues(this.incrementPath, taskIssueMap);
151
- console.log(` āœ… Updated tasks.md`);
152
-
153
- // 9. Save sync mapping
154
- console.log(`\nšŸ’¾ Saving sync mapping...`);
155
- this.saveSyncMapping({
156
- milestone: milestone.number,
157
- epic_issue: epic.number,
158
- task_issues: taskIssueMap,
159
- last_sync: new Date().toISOString()
160
- });
161
- console.log(` āœ… Saved to .github-sync.yaml`);
162
-
163
- // 10. Update increment metadata
164
- metadata.github = {
165
- milestone: milestone.number,
166
- epic_issue: epic.number,
167
- task_issues: taskIssueMap,
168
- last_sync: new Date().toISOString()
169
- };
170
- this.saveIncrementMetadata(metadata);
171
-
172
- // Success summary
173
- console.log(`\nšŸŽ‰ GitHub sync complete!`);
174
- console.log(` šŸ“ Milestone: #${milestone.number} ${milestone.title}`);
175
- console.log(` šŸŽÆ Epic: #${epic.number} ${epic.html_url}`);
176
- console.log(` šŸ“ Tasks: #${createdIssues[0]?.number}-#${createdIssues[createdIssues.length - 1]?.number} (${createdIssues.length} issues)`);
177
-
178
- return {
179
- milestone,
180
- epic,
181
- tasks: taskIssues,
182
- errors
183
- };
184
-
185
- } catch (error: any) {
186
- console.error(`\nāŒ Sync failed:`, error.message);
187
- throw error;
188
- }
189
- }
190
-
191
- /**
192
- * Generate epic issue body
193
- */
194
- private generateEpicBody(metadata: IncrementMetadata, tasks: Task[]): string {
195
- const specPath = path.join(this.incrementPath, 'spec.md');
196
- let summary = 'No summary available';
197
-
198
- if (fs.existsSync(specPath)) {
199
- const specContent = fs.readFileSync(specPath, 'utf-8');
200
- const summaryMatch = specContent.match(/## Executive Summary\s+(.+?)(?=\n##|$)/s);
201
- summary = summaryMatch?.[1]?.trim() || summary;
202
- }
203
-
204
- // Group tasks by phase
205
- const phases = new Map<string, Task[]>();
206
- tasks.forEach(task => {
207
- const phase = task.phase || 'Other';
208
- if (!phases.has(phase)) {
209
- phases.set(phase, []);
210
- }
211
- phases.get(phase)!.push(task);
212
- });
213
-
214
- let phaseChecklist = '';
215
- for (const [phase, phaseTasks] of phases.entries()) {
216
- phaseChecklist += `\n### ${phase}\n\n`;
217
- phaseTasks.forEach(task => {
218
- phaseChecklist += `- [ ] [${task.id}] ${task.title} (${task.estimate})\n`;
219
- });
220
- }
221
-
222
- // DEPRECATED: This method generates old [Increment XXX] format
223
- // It will be blocked by github-client-v2.ts validation
224
- // TODO: Remove task-sync.ts entirely - use living docs sync instead
225
- return `# [Increment ${metadata.id}] ${metadata.title}
226
-
227
- **Status**: ${metadata.status}
228
- **Priority**: ${metadata.priority}
229
- **Created**: ${new Date().toISOString().split('T')[0]}
230
-
231
- ## Summary
232
-
233
- ${summary}
234
-
235
- ## Tasks (${tasks.length} total)
236
- ${phaseChecklist}
237
-
238
- ## SpecWeave Increment
239
-
240
- āš ļø **DEPRECATED FORMAT**: This issue was created using the old increment-based sync.
241
-
242
- **Correct data flow**: Increment → Living Docs → GitHub
243
-
244
- This epic tracks SpecWeave increment \`${metadata.id}\`.
245
-
246
- - **Spec**: [\`spec.md\`](${this.getGitHubFileURL('spec.md')})
247
- - **Plan**: [\`plan.md\`](${this.getGitHubFileURL('plan.md')})
248
- - **Tasks**: [\`tasks.md\`](${this.getGitHubFileURL('tasks.md')})
249
-
250
- ---
251
-
252
- šŸ¤– Auto-synced by [SpecWeave](https://spec-weave.com)`;
253
- }
254
-
255
- /**
256
- * Generate task issue body
257
- */
258
- private generateTaskBody(task: Task): string {
259
- let body = `**Priority**: ${task.priority}
260
- **Estimate**: ${task.estimate}
261
- **Phase**: ${task.phase || 'N/A'}
262
-
263
- ## Description
264
-
265
- ${task.description}
266
- `;
267
-
268
- if (task.subtasks && task.subtasks.length > 0) {
269
- body += `\n## Subtasks\n\n`;
270
- task.subtasks.forEach(subtask => {
271
- const checked = subtask.completed ? 'x' : ' ';
272
- body += `- [${checked}] ${subtask.id}: ${subtask.description} (${subtask.estimate})\n`;
273
- });
274
- }
275
-
276
- if (task.filesToCreate && task.filesToCreate.length > 0) {
277
- body += `\n## Files to Create\n\n`;
278
- task.filesToCreate.forEach(file => {
279
- body += `- \`${file}\`\n`;
280
- });
281
- }
282
-
283
- if (task.filesToModify && task.filesToModify.length > 0) {
284
- body += `\n## Files to Modify\n\n`;
285
- task.filesToModify.forEach(file => {
286
- body += `- \`${file}\`\n`;
287
- });
288
- }
289
-
290
- if (task.implementation) {
291
- body += `\n## Implementation\n\n\`\`\`typescript\n${task.implementation}\n\`\`\`\n`;
292
- }
293
-
294
- if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
295
- body += `\n## Acceptance Criteria\n\n`;
296
- task.acceptanceCriteria.forEach(criterion => {
297
- body += `- āœ… ${criterion}\n`;
298
- });
299
- }
300
-
301
- if (task.dependencies && task.dependencies.length > 0) {
302
- body += `\n## Dependencies\n\nThis task depends on:\n`;
303
- task.dependencies.forEach(dep => {
304
- body += `- ${dep} (must complete first)\n`;
305
- });
306
- }
307
-
308
- if (task.blocks && task.blocks.length > 0) {
309
- body += `\n## Blocks\n\nThis task blocks:\n`;
310
- task.blocks.forEach(blocked => {
311
- body += `- ${blocked} (waiting on this)\n`;
312
- });
313
- }
314
-
315
- body += `\n---\n\nšŸ¤– Synced from SpecWeave increment \`${path.basename(this.incrementPath)}\`\n`;
316
- body += `- **Tasks**: [\`tasks.md\`](${this.getGitHubFileURL('tasks.md')})\n`;
317
-
318
- return body;
319
- }
320
-
321
- /**
322
- * Load increment metadata
323
- */
324
- private loadIncrementMetadata(): IncrementMetadata {
325
- const metadataPath = path.join(this.incrementPath, '.metadata.yaml');
326
-
327
- if (fs.existsSync(metadataPath)) {
328
- const content = fs.readFileSync(metadataPath, 'utf-8');
329
- return yaml.load(content) as IncrementMetadata;
330
- }
331
-
332
- // Fallback: extract from directory name and spec
333
- const incrementId = path.basename(this.incrementPath);
334
- const specPath = path.join(this.incrementPath, 'spec.md');
335
- let title = 'Unknown';
336
- let priority: 'P0' | 'P1' | 'P2' | 'P3' = 'P1';
337
-
338
- if (fs.existsSync(specPath)) {
339
- const specContent = fs.readFileSync(specPath, 'utf-8');
340
- const titleMatch = specContent.match(/\*\*Title\*\*:\s*(.+)/);
341
- const priorityMatch = specContent.match(/\*\*Priority\*\*:\s*(P[0-3])/);
342
- title = titleMatch?.[1]?.trim() || title;
343
- priority = (priorityMatch?.[1] as any) || priority;
344
- }
345
-
346
- return {
347
- id: incrementId,
348
- title,
349
- priority,
350
- status: 'planning'
351
- };
352
- }
353
-
354
- /**
355
- * Save increment metadata
356
- */
357
- private saveIncrementMetadata(metadata: IncrementMetadata): void {
358
- const metadataPath = path.join(this.incrementPath, '.metadata.yaml');
359
- fs.writeFileSync(metadataPath, yaml.dump(metadata), 'utf-8');
360
- }
361
-
362
- /**
363
- * Get issue prefix from metadata.json (with created date)
364
- * Returns FS-YY-MM-DD format or fallback to FS-UNKNOWN
365
- */
366
- private getIssuePrefix(incrementId: string): string {
367
- const metadataJsonPath = path.join(this.incrementPath, 'metadata.json');
368
-
369
- // Try to read metadata.json for created date
370
- if (fs.existsSync(metadataJsonPath)) {
371
- try {
372
- const metadataContent = fs.readFileSync(metadataJsonPath, 'utf-8');
373
- const metadata = JSON.parse(metadataContent);
374
-
375
- if (metadata.created) {
376
- // Extract YY-MM-DD from date (e.g., "2025-11-12T12:46:00Z" -> "25-11-12")
377
- const dateMatch = metadata.created.match(/^(\d{4})-(\d{2})-(\d{2})/);
378
- if (dateMatch) {
379
- const year = dateMatch[1].slice(2); // "2025" -> "25"
380
- const month = dateMatch[2]; // "11"
381
- const day = dateMatch[3]; // "12"
382
- return `FS-${year}-${month}-${day}`;
383
- }
384
- }
385
- } catch (error) {
386
- console.warn(`āš ļø Could not parse metadata.json: ${error}`);
387
- }
388
- }
389
-
390
- // Fallback: use increment number if available
391
- const incrementNumber = incrementId.match(/^(\d+)/)?.[1];
392
- if (incrementNumber) {
393
- return `FS-${incrementNumber}`;
394
- }
395
-
396
- return 'FS-UNKNOWN';
397
- }
398
-
399
- /**
400
- * Save sync mapping
401
- */
402
- private saveSyncMapping(githubData: any): void {
403
- const syncPath = path.join(this.incrementPath, '.github-sync.yaml');
404
- fs.writeFileSync(syncPath, yaml.dump(githubData), 'utf-8');
405
- }
406
-
407
- /**
408
- * Get milestone title from metadata
409
- */
410
- private getMilestoneTitle(metadata: IncrementMetadata): string {
411
- return metadata.version ? `v${metadata.version}` : `Increment ${metadata.id}`;
412
- }
413
-
414
- /**
415
- * Get GitHub file URL
416
- */
417
- private getGitHubFileURL(filename: string): string {
418
- try {
419
- const remote = this.client['detectRepo']();
420
- const incrementId = path.basename(this.incrementPath);
421
- return `https://github.com/${remote}/blob/develop/.specweave/increments/${incrementId}/${filename}`;
422
- } catch {
423
- return `#`;
424
- }
425
- }
426
-
427
- /**
428
- * Convert string to slug
429
- */
430
- private slugify(str: string): string {
431
- return str
432
- .toLowerCase()
433
- .replace(/[^a-z0-9]+/g, '-')
434
- .replace(/^-|-$/g, '');
435
- }
436
-
437
- /**
438
- * Print dry run summary
439
- */
440
- private printDryRunSummary(tasks: Task[], metadata: IncrementMetadata): void {
441
- const issuePrefix = this.getIssuePrefix(metadata.id);
442
- console.log(`\nšŸ“Š Dry Run Summary:`);
443
- console.log(` Milestone: ${this.getMilestoneTitle(metadata)}`);
444
- console.log(` Epic: [${issuePrefix}] ${metadata.title}`);
445
- console.log(` Task Issues: ${tasks.length}`);
446
- console.log(`\nšŸ“ Would create:`);
447
- tasks.forEach((task, i) => {
448
- console.log(` ${i + 1}. [${task.id}] ${task.title} (${task.estimate})`);
449
- });
450
- }
451
- }