@mknightzzz/stw 0.1.0

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 (250) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +277 -0
  3. package/dist/agentic-fallback.d.ts +3 -0
  4. package/dist/agentic-fallback.js +32 -0
  5. package/dist/agentic-fallback.js.map +1 -0
  6. package/dist/agentic-prompt.d.ts +2 -0
  7. package/dist/agentic-prompt.js +68 -0
  8. package/dist/agentic-prompt.js.map +1 -0
  9. package/dist/agentic-runtime.d.ts +48 -0
  10. package/dist/agentic-runtime.js +149 -0
  11. package/dist/agentic-runtime.js.map +1 -0
  12. package/dist/agentic-types.d.ts +37 -0
  13. package/dist/agentic-types.js +2 -0
  14. package/dist/agentic-types.js.map +1 -0
  15. package/dist/agents.d.ts +7 -0
  16. package/dist/agents.js +2 -0
  17. package/dist/agents.js.map +1 -0
  18. package/dist/assignments.d.ts +7 -0
  19. package/dist/assignments.js +125 -0
  20. package/dist/assignments.js.map +1 -0
  21. package/dist/checkpoint.d.ts +35 -0
  22. package/dist/checkpoint.js +78 -0
  23. package/dist/checkpoint.js.map +1 -0
  24. package/dist/circuit-breaker.d.ts +17 -0
  25. package/dist/circuit-breaker.js +65 -0
  26. package/dist/circuit-breaker.js.map +1 -0
  27. package/dist/claim.d.ts +6 -0
  28. package/dist/claim.js +135 -0
  29. package/dist/claim.js.map +1 -0
  30. package/dist/clarity-gate.d.ts +12 -0
  31. package/dist/clarity-gate.js +83 -0
  32. package/dist/clarity-gate.js.map +1 -0
  33. package/dist/cli.d.ts +2 -0
  34. package/dist/cli.js +38 -0
  35. package/dist/cli.js.map +1 -0
  36. package/dist/command-dispatch.d.ts +45 -0
  37. package/dist/command-dispatch.js +206 -0
  38. package/dist/command-dispatch.js.map +1 -0
  39. package/dist/command-parser.d.ts +11 -0
  40. package/dist/command-parser.js +101 -0
  41. package/dist/command-parser.js.map +1 -0
  42. package/dist/commands/clean.d.ts +10 -0
  43. package/dist/commands/clean.js +133 -0
  44. package/dist/commands/clean.js.map +1 -0
  45. package/dist/commands/execution.d.ts +2 -0
  46. package/dist/commands/execution.js +327 -0
  47. package/dist/commands/execution.js.map +1 -0
  48. package/dist/commands/go.d.ts +2 -0
  49. package/dist/commands/go.js +197 -0
  50. package/dist/commands/go.js.map +1 -0
  51. package/dist/commands/helpers.d.ts +44 -0
  52. package/dist/commands/helpers.js +231 -0
  53. package/dist/commands/helpers.js.map +1 -0
  54. package/dist/commands/idea.d.ts +2 -0
  55. package/dist/commands/idea.js +89 -0
  56. package/dist/commands/idea.js.map +1 -0
  57. package/dist/commands/init.d.ts +2 -0
  58. package/dist/commands/init.js +94 -0
  59. package/dist/commands/init.js.map +1 -0
  60. package/dist/commands/integration.d.ts +7 -0
  61. package/dist/commands/integration.js +139 -0
  62. package/dist/commands/integration.js.map +1 -0
  63. package/dist/commands/maintenance.d.ts +2 -0
  64. package/dist/commands/maintenance.js +301 -0
  65. package/dist/commands/maintenance.js.map +1 -0
  66. package/dist/commands/run.d.ts +2 -0
  67. package/dist/commands/run.js +356 -0
  68. package/dist/commands/run.js.map +1 -0
  69. package/dist/commands/setup.d.ts +2 -0
  70. package/dist/commands/setup.js +198 -0
  71. package/dist/commands/setup.js.map +1 -0
  72. package/dist/commands/spec.d.ts +2 -0
  73. package/dist/commands/spec.js +35 -0
  74. package/dist/commands/spec.js.map +1 -0
  75. package/dist/commands/stats.d.ts +2 -0
  76. package/dist/commands/stats.js +80 -0
  77. package/dist/commands/stats.js.map +1 -0
  78. package/dist/commands/task-ops.d.ts +2 -0
  79. package/dist/commands/task-ops.js +406 -0
  80. package/dist/commands/task-ops.js.map +1 -0
  81. package/dist/config.d.ts +18 -0
  82. package/dist/config.js +338 -0
  83. package/dist/config.js.map +1 -0
  84. package/dist/cost.d.ts +30 -0
  85. package/dist/cost.js +167 -0
  86. package/dist/cost.js.map +1 -0
  87. package/dist/crash-recovery.d.ts +9 -0
  88. package/dist/crash-recovery.js +42 -0
  89. package/dist/crash-recovery.js.map +1 -0
  90. package/dist/diagnostic.d.ts +48 -0
  91. package/dist/diagnostic.js +328 -0
  92. package/dist/diagnostic.js.map +1 -0
  93. package/dist/doctor.d.ts +31 -0
  94. package/dist/doctor.js +225 -0
  95. package/dist/doctor.js.map +1 -0
  96. package/dist/drift.d.ts +11 -0
  97. package/dist/drift.js +57 -0
  98. package/dist/drift.js.map +1 -0
  99. package/dist/git-utils.d.ts +20 -0
  100. package/dist/git-utils.js +206 -0
  101. package/dist/git-utils.js.map +1 -0
  102. package/dist/gitlab.d.ts +54 -0
  103. package/dist/gitlab.js +101 -0
  104. package/dist/gitlab.js.map +1 -0
  105. package/dist/idea.d.ts +35 -0
  106. package/dist/idea.js +251 -0
  107. package/dist/idea.js.map +1 -0
  108. package/dist/import-resolution.d.ts +13 -0
  109. package/dist/import-resolution.js +111 -0
  110. package/dist/import-resolution.js.map +1 -0
  111. package/dist/inbox-renderer.d.ts +2 -0
  112. package/dist/inbox-renderer.js +67 -0
  113. package/dist/inbox-renderer.js.map +1 -0
  114. package/dist/init.d.ts +105 -0
  115. package/dist/init.js +235 -0
  116. package/dist/init.js.map +1 -0
  117. package/dist/llm-reviewer.d.ts +14 -0
  118. package/dist/llm-reviewer.js +109 -0
  119. package/dist/llm-reviewer.js.map +1 -0
  120. package/dist/lock.d.ts +26 -0
  121. package/dist/lock.js +76 -0
  122. package/dist/lock.js.map +1 -0
  123. package/dist/logger.d.ts +24 -0
  124. package/dist/logger.js +40 -0
  125. package/dist/logger.js.map +1 -0
  126. package/dist/math-utils.d.ts +2 -0
  127. package/dist/math-utils.js +7 -0
  128. package/dist/math-utils.js.map +1 -0
  129. package/dist/mechanical-review.d.ts +30 -0
  130. package/dist/mechanical-review.js +76 -0
  131. package/dist/mechanical-review.js.map +1 -0
  132. package/dist/merge.d.ts +83 -0
  133. package/dist/merge.js +363 -0
  134. package/dist/merge.js.map +1 -0
  135. package/dist/parallel.d.ts +35 -0
  136. package/dist/parallel.js +214 -0
  137. package/dist/parallel.js.map +1 -0
  138. package/dist/plan-validation.d.ts +19 -0
  139. package/dist/plan-validation.js +253 -0
  140. package/dist/plan-validation.js.map +1 -0
  141. package/dist/planner-prompt.d.ts +33 -0
  142. package/dist/planner-prompt.js +244 -0
  143. package/dist/planner-prompt.js.map +1 -0
  144. package/dist/planner.d.ts +29 -0
  145. package/dist/planner.js +511 -0
  146. package/dist/planner.js.map +1 -0
  147. package/dist/poller.d.ts +34 -0
  148. package/dist/poller.js +91 -0
  149. package/dist/poller.js.map +1 -0
  150. package/dist/progress.d.ts +34 -0
  151. package/dist/progress.js +122 -0
  152. package/dist/progress.js.map +1 -0
  153. package/dist/prompt-builder.d.ts +51 -0
  154. package/dist/prompt-builder.js +481 -0
  155. package/dist/prompt-builder.js.map +1 -0
  156. package/dist/provider.d.ts +14 -0
  157. package/dist/provider.js +278 -0
  158. package/dist/provider.js.map +1 -0
  159. package/dist/question-handler.d.ts +18 -0
  160. package/dist/question-handler.js +154 -0
  161. package/dist/question-handler.js.map +1 -0
  162. package/dist/question-triage.d.ts +31 -0
  163. package/dist/question-triage.js +175 -0
  164. package/dist/question-triage.js.map +1 -0
  165. package/dist/repo-detection.d.ts +8 -0
  166. package/dist/repo-detection.js +18 -0
  167. package/dist/repo-detection.js.map +1 -0
  168. package/dist/retry-context.d.ts +2 -0
  169. package/dist/retry-context.js +196 -0
  170. package/dist/retry-context.js.map +1 -0
  171. package/dist/router.d.ts +18 -0
  172. package/dist/router.js +137 -0
  173. package/dist/router.js.map +1 -0
  174. package/dist/run-artifact-types.d.ts +43 -0
  175. package/dist/run-artifact-types.js +2 -0
  176. package/dist/run-artifact-types.js.map +1 -0
  177. package/dist/run-summary.d.ts +14 -0
  178. package/dist/run-summary.js +347 -0
  179. package/dist/run-summary.js.map +1 -0
  180. package/dist/run-sync.d.ts +11 -0
  181. package/dist/run-sync.js +110 -0
  182. package/dist/run-sync.js.map +1 -0
  183. package/dist/run.d.ts +26 -0
  184. package/dist/run.js +150 -0
  185. package/dist/run.js.map +1 -0
  186. package/dist/scope-expansion.d.ts +10 -0
  187. package/dist/scope-expansion.js +117 -0
  188. package/dist/scope-expansion.js.map +1 -0
  189. package/dist/scope.d.ts +4 -0
  190. package/dist/scope.js +37 -0
  191. package/dist/scope.js.map +1 -0
  192. package/dist/scorecard.d.ts +18 -0
  193. package/dist/scorecard.js +128 -0
  194. package/dist/scorecard.js.map +1 -0
  195. package/dist/spec-templates.d.ts +2 -0
  196. package/dist/spec-templates.js +285 -0
  197. package/dist/spec-templates.js.map +1 -0
  198. package/dist/spec-validator.d.ts +8 -0
  199. package/dist/spec-validator.js +144 -0
  200. package/dist/spec-validator.js.map +1 -0
  201. package/dist/status.d.ts +68 -0
  202. package/dist/status.js +261 -0
  203. package/dist/status.js.map +1 -0
  204. package/dist/storage.d.ts +9 -0
  205. package/dist/storage.js +35 -0
  206. package/dist/storage.js.map +1 -0
  207. package/dist/task-executor-completion.d.ts +12 -0
  208. package/dist/task-executor-completion.js +67 -0
  209. package/dist/task-executor-completion.js.map +1 -0
  210. package/dist/task-executor-fallback.d.ts +20 -0
  211. package/dist/task-executor-fallback.js +12 -0
  212. package/dist/task-executor-fallback.js.map +1 -0
  213. package/dist/task-executor.d.ts +34 -0
  214. package/dist/task-executor.js +521 -0
  215. package/dist/task-executor.js.map +1 -0
  216. package/dist/task-graph.d.ts +11 -0
  217. package/dist/task-graph.js +226 -0
  218. package/dist/task-graph.js.map +1 -0
  219. package/dist/task-pipeline-helpers.d.ts +45 -0
  220. package/dist/task-pipeline-helpers.js +160 -0
  221. package/dist/task-pipeline-helpers.js.map +1 -0
  222. package/dist/task-review.d.ts +51 -0
  223. package/dist/task-review.js +410 -0
  224. package/dist/task-review.js.map +1 -0
  225. package/dist/transitions.d.ts +13 -0
  226. package/dist/transitions.js +104 -0
  227. package/dist/transitions.js.map +1 -0
  228. package/dist/types.d.ts +405 -0
  229. package/dist/types.js +101 -0
  230. package/dist/types.js.map +1 -0
  231. package/dist/utils.d.ts +1 -0
  232. package/dist/utils.js +23 -0
  233. package/dist/utils.js.map +1 -0
  234. package/dist/validation.d.ts +19 -0
  235. package/dist/validation.js +73 -0
  236. package/dist/validation.js.map +1 -0
  237. package/dist/worker-response.d.ts +12 -0
  238. package/dist/worker-response.js +60 -0
  239. package/dist/worker-response.js.map +1 -0
  240. package/dist/worker-runner.d.ts +19 -0
  241. package/dist/worker-runner.js +347 -0
  242. package/dist/worker-runner.js.map +1 -0
  243. package/dist/worktree-cleanup.d.ts +44 -0
  244. package/dist/worktree-cleanup.js +325 -0
  245. package/dist/worktree-cleanup.js.map +1 -0
  246. package/dist/worktree.d.ts +22 -0
  247. package/dist/worktree.js +213 -0
  248. package/dist/worktree.js.map +1 -0
  249. package/examples/spec.md +58 -0
  250. package/package.json +66 -0
@@ -0,0 +1,214 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { join } from 'node:path';
3
+ import { readTaskStatus } from './status.js';
4
+ import { runGit, applyPatchToBranch } from './git-utils.js';
5
+ import { cleanupWorktree } from './worktree.js';
6
+ import { fileExists } from './storage.js';
7
+ import { executeTask } from './task-executor.js';
8
+ export function findReadyTasks(graph, stwRoot, runId) {
9
+ const ready = [];
10
+ for (let i = 0; i < graph.tasks.length; i++) {
11
+ const task = graph.tasks[i];
12
+ const status = readTaskStatus(stwRoot, runId, task.id);
13
+ if (status)
14
+ continue;
15
+ const depsDone = task.dependencies.every((dep) => {
16
+ const depStatus = readTaskStatus(stwRoot, runId, dep);
17
+ return depStatus?.status === 'complete';
18
+ });
19
+ if (!depsDone)
20
+ continue;
21
+ ready.push({ task, index: i });
22
+ }
23
+ return ready;
24
+ }
25
+ export function mergeBackSequentially(input) {
26
+ const { completedResults, repoRoot, runBranch, logger } = input;
27
+ const results = [];
28
+ for (const batch of completedResults) {
29
+ const { task, result, worktreePath, taskBranch, taskDir } = batch;
30
+ if (result.finalState !== 'complete' || !worktreePath || !taskBranch) {
31
+ results.push({ taskId: task.id, merged: false, needsRetry: false });
32
+ continue;
33
+ }
34
+ // Commit any uncommitted changes in the worktree
35
+ const gitOpts = { cwd: worktreePath, encoding: 'utf-8', stdio: 'pipe' };
36
+ try {
37
+ runGit(worktreePath, ['add', '-A']);
38
+ execFileSync('git', ['commit', '--allow-empty', '-m', `feat(${task.id}): ${task.description}`], gitOpts);
39
+ }
40
+ catch {
41
+ // May already be committed by the agentic backend
42
+ }
43
+ // Try fast-forward first
44
+ let merged = false;
45
+ try {
46
+ execFileSync('git', ['fetch', '.', `${taskBranch}:${runBranch}`], {
47
+ cwd: repoRoot,
48
+ encoding: 'utf-8',
49
+ stdio: 'pipe',
50
+ });
51
+ merged = true;
52
+ logger?.info('Fast-forward merge succeeded', { task_id: task.id });
53
+ }
54
+ catch {
55
+ // Fast-forward failed — run branch has moved. Try rebase.
56
+ logger?.info('Fast-forward failed, attempting rebase', { task_id: task.id });
57
+ try {
58
+ execFileSync('git', ['rebase', runBranch], {
59
+ cwd: worktreePath,
60
+ encoding: 'utf-8',
61
+ stdio: 'pipe',
62
+ });
63
+ // Rebase succeeded — now fast-forward
64
+ execFileSync('git', ['fetch', '.', `${taskBranch}:${runBranch}`], {
65
+ cwd: repoRoot,
66
+ encoding: 'utf-8',
67
+ stdio: 'pipe',
68
+ });
69
+ merged = true;
70
+ logger?.info('Rebase + fast-forward succeeded', { task_id: task.id });
71
+ }
72
+ catch {
73
+ // Rebase failed — abort it and try patch-based fallback
74
+ try {
75
+ execFileSync('git', ['rebase', '--abort'], {
76
+ cwd: worktreePath,
77
+ encoding: 'utf-8',
78
+ stdio: 'pipe',
79
+ });
80
+ }
81
+ catch {
82
+ // rebase --abort may fail if not in rebase state
83
+ }
84
+ logger?.info('Rebase failed, trying patch fallback', { task_id: task.id });
85
+ // Try applying the diff patch directly
86
+ const patchPath = join(taskDir, 'diff.patch');
87
+ if (fileExists(patchPath)) {
88
+ const applyResult = applyPatchToBranch({
89
+ repoRoot,
90
+ branch: runBranch,
91
+ patchPath,
92
+ commitMessage: `stw(${task.id}): apply task changes`,
93
+ });
94
+ if (applyResult.success) {
95
+ merged = true;
96
+ logger?.info('Patch fallback succeeded', { task_id: task.id });
97
+ }
98
+ }
99
+ }
100
+ }
101
+ if (merged) {
102
+ // Clean up worktree and branch
103
+ try {
104
+ cleanupWorktree(worktreePath, repoRoot);
105
+ }
106
+ catch {
107
+ // Best effort
108
+ }
109
+ try {
110
+ execFileSync('git', ['branch', '-D', taskBranch], {
111
+ cwd: repoRoot,
112
+ encoding: 'utf-8',
113
+ stdio: 'pipe',
114
+ });
115
+ }
116
+ catch {
117
+ // Branch already gone
118
+ }
119
+ results.push({ taskId: task.id, merged: true, needsRetry: false });
120
+ }
121
+ else {
122
+ // All merge strategies failed — signal retry
123
+ logger?.warn('All merge strategies failed, task needs retry', { task_id: task.id });
124
+ try {
125
+ cleanupWorktree(worktreePath, repoRoot);
126
+ }
127
+ catch {
128
+ // Best effort
129
+ }
130
+ try {
131
+ execFileSync('git', ['branch', '-D', taskBranch], {
132
+ cwd: repoRoot,
133
+ encoding: 'utf-8',
134
+ stdio: 'pipe',
135
+ });
136
+ }
137
+ catch {
138
+ // Best effort
139
+ }
140
+ results.push({
141
+ taskId: task.id,
142
+ merged: false,
143
+ needsRetry: true,
144
+ error: 'Fast-forward, rebase, and patch apply all failed',
145
+ });
146
+ }
147
+ }
148
+ return results;
149
+ }
150
+ export async function executeBatch(options) {
151
+ const { tasks, config, baseOptions, taskDirFn, logger } = options;
152
+ const promises = tasks.map(async (task) => {
153
+ console.log(` Starting task: ${task.id}`);
154
+ const td = taskDirFn(task.id);
155
+ const result = await executeTask(task, config, {
156
+ ...baseOptions,
157
+ taskDir: td,
158
+ deferMerge: true,
159
+ });
160
+ return {
161
+ task,
162
+ result,
163
+ worktreePath: result.worktreePath,
164
+ taskBranch: result.taskBranch,
165
+ taskDir: td,
166
+ };
167
+ });
168
+ const settled = await Promise.allSettled(promises);
169
+ const results = [];
170
+ for (const [i, outcome] of settled.entries()) {
171
+ const task = tasks[i];
172
+ if (outcome.status === 'fulfilled') {
173
+ results.push(outcome.value);
174
+ }
175
+ else {
176
+ logger?.warn('Parallel task execution failed', {
177
+ task_id: task.id,
178
+ error: outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason),
179
+ });
180
+ results.push({
181
+ task,
182
+ result: {
183
+ finalState: 'escalated',
184
+ attempts: 0,
185
+ totalTokens: { input_tokens: 0, output_tokens: 0 },
186
+ },
187
+ taskDir: taskDirFn(task.id),
188
+ });
189
+ }
190
+ }
191
+ // Sequential merge-back for completed tasks
192
+ const completedForMerge = results.filter((br) => br.result.finalState === 'complete');
193
+ if (completedForMerge.length > 0) {
194
+ console.log(`Merging ${completedForMerge.length} completed task(s) to run branch...`);
195
+ const mergeResults = mergeBackSequentially({
196
+ completedResults: completedForMerge,
197
+ repoRoot: baseOptions.repoRoot,
198
+ runBranch: baseOptions.runBranch,
199
+ logger,
200
+ });
201
+ for (const mr of mergeResults) {
202
+ if (mr.needsRetry) {
203
+ console.log(`Task ${mr.taskId} needs retry due to merge conflict`);
204
+ const br = results.find((b) => b.task.id === mr.taskId);
205
+ if (br) {
206
+ br.result.finalState = 'rejected';
207
+ br.result.failureClass = 'merge_conflict_needs_retry';
208
+ }
209
+ }
210
+ }
211
+ }
212
+ return results;
213
+ }
214
+ //# sourceMappingURL=parallel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Task, TaskGraph } from './types.js';
2
+ export interface PlanScopeValidationResult {
3
+ warnings: string[];
4
+ errors: string[];
5
+ valid: boolean;
6
+ }
7
+ export interface AcceptanceCheckValidationResult {
8
+ warnings: string[];
9
+ fixedChecks: Map<string, string[]>;
10
+ }
11
+ export declare function validatePlanScope(graph: TaskGraph, repoRoot?: string, config?: {
12
+ max_scope_files_per_task?: number;
13
+ max_tasks_per_spec?: number;
14
+ }): PlanScopeValidationResult;
15
+ export declare function isSerialized(leftTaskId: string, rightTaskId: string, taskById: Map<string, Task>, dependencyCache: Map<string, Set<string>>): boolean;
16
+ export declare function intersectFiles(leftFiles: string[], rightFiles: string[]): string[];
17
+ export declare function validatePlannerOutput(graph: TaskGraph, repoRoot?: string): AcceptanceCheckValidationResult;
18
+ export { expandScopesFromImportGraph } from './scope-expansion.js';
19
+ export type { ScopeExpansionResult } from './scope-expansion.js';
@@ -0,0 +1,253 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join, normalize } from 'node:path';
3
+ import { fileExists } from './storage.js';
4
+ const TEST_FILE_PATTERNS = [
5
+ /^tests\/.*\.test\.ts$/,
6
+ /^tests\/.*\.test\.js$/,
7
+ /^tests\/.*\.spec\.ts$/,
8
+ /^tests\/.*\.spec\.js$/,
9
+ /^__tests__\/.*\.ts$/,
10
+ /^__tests__\/.*\.js$/,
11
+ /^.*\.test\.ts$/,
12
+ /^.*\.test\.js$/,
13
+ /^.*\.spec\.ts$/,
14
+ /^.*\.spec\.js$/,
15
+ /^test\/.*\.ts$/,
16
+ /^test\/.*\.js$/,
17
+ ];
18
+ const TEST_RUNNER_PATTERNS = [
19
+ { pattern: /npx\s+vitest\s+run\s+(\S+)/, runner: 'vitest', replaceWith: 'npx vitest run' },
20
+ { pattern: /npx\s+vitest\s+(\S+)/, runner: 'vitest', replaceWith: 'npx vitest' },
21
+ { pattern: /npx\s+jest\s+(.+)/, runner: 'jest', replaceWith: 'npx jest' },
22
+ { pattern: /npx\s+pytest\s+(.+)/, runner: 'pytest', replaceWith: 'npx pytest' },
23
+ { pattern: /yarn\s+vitest\s+run\s+(\S+)/, runner: 'vitest', replaceWith: 'yarn vitest run' },
24
+ { pattern: /yarn\s+jest\s+(.+)/, runner: 'jest', replaceWith: 'yarn jest' },
25
+ { pattern: /npm\s+test\s+--\s+(.+)/, runner: 'npm', replaceWith: 'npm test' },
26
+ ];
27
+ function isTestFilePath(path) {
28
+ return TEST_FILE_PATTERNS.some((pattern) => pattern.test(path));
29
+ }
30
+ function extractFilePathsFromCheck(check) {
31
+ const filePaths = [];
32
+ const pathPattern = /(?<!\S)(?:\.{0,2}\/)?[\w\-\.]+\/[\w\-\.\/]+\.\w+(?!\S)/g;
33
+ const matches = check.match(pathPattern);
34
+ if (matches) {
35
+ for (const match of matches) {
36
+ const cleanedPath = match.replace(/^\.\//, '');
37
+ if (isTestFilePath(cleanedPath)) {
38
+ filePaths.push(cleanedPath);
39
+ }
40
+ }
41
+ }
42
+ return filePaths;
43
+ }
44
+ function getAutoFixForCommand(check) {
45
+ for (const { pattern, replaceWith } of TEST_RUNNER_PATTERNS) {
46
+ if (pattern.test(check)) {
47
+ return check.replace(pattern, replaceWith);
48
+ }
49
+ }
50
+ return null;
51
+ }
52
+ export function validatePlanScope(graph, repoRoot, config) {
53
+ const warnings = [];
54
+ const errors = [];
55
+ const taskById = new Map(graph.tasks.map((task) => [task.id, task]));
56
+ const dependencyCache = new Map();
57
+ const maxScopeFiles = config?.max_scope_files_per_task ?? 8;
58
+ const maxTasks = config?.max_tasks_per_spec ?? 15;
59
+ if (graph.tasks.length > maxTasks) {
60
+ errors.push(`Task count ${graph.tasks.length} exceeds maximum ${maxTasks} per spec`);
61
+ }
62
+ for (const task of graph.tasks) {
63
+ if (task.scope.files.length === 0) {
64
+ warnings.push(`${task.id}: task has zero scope files`);
65
+ }
66
+ if (task.scope.files.length > maxScopeFiles) {
67
+ errors.push(`${task.id}: task has ${task.scope.files.length} scope files, exceeds maximum ${maxScopeFiles}`);
68
+ }
69
+ if (task.scope.files.length > 5) {
70
+ warnings.push(`${task.id}: task has ${task.scope.files.length} scope files (>5), consider splitting`);
71
+ }
72
+ if (repoRoot) {
73
+ const newFiles = new Set((task.scope.new_files ?? []).map((f) => normalize(f).replace(/^\.\//, '')));
74
+ const upstreamNewFiles = getUpstreamNewFiles(task.id, taskById, dependencyCache);
75
+ for (const file of task.scope.files) {
76
+ const normalizedFile = normalize(file).replace(/^\.\//, '');
77
+ const absolutePath = join(repoRoot, file);
78
+ if (!fileExists(absolutePath)) {
79
+ if (newFiles.has(normalizedFile)) {
80
+ warnings.push(`${task.id}: scope file ${file} does not exist yet (declared as new_files, will be created)`);
81
+ }
82
+ else if (upstreamNewFiles.has(normalizedFile)) {
83
+ const creators = [];
84
+ for (const depId of getReachableDependencies(task.id, taskById, dependencyCache)) {
85
+ const depTask = taskById.get(depId);
86
+ if (depTask?.scope.new_files?.some((f) => normalize(f).replace(/^\.\//, '') === normalizedFile)) {
87
+ creators.push(depId);
88
+ }
89
+ }
90
+ warnings.push(`${task.id}: scope file ${file} does not exist yet (will be created by upstream task${creators.length > 1 ? 's' : ''} ${creators.join(', ')})`);
91
+ }
92
+ else {
93
+ errors.push(`${task.id}: scope file does not exist: ${file} (add to scope.new_files if the task creates it)`);
94
+ }
95
+ }
96
+ else {
97
+ try {
98
+ const content = readFileSync(absolutePath, 'utf-8');
99
+ const lines = content.split('\n').length;
100
+ if (lines > 500) {
101
+ warnings.push(`${task.id}: scope file ${file} is ${lines} lines (>500), consider narrowing task description to specific sections`);
102
+ }
103
+ }
104
+ catch {
105
+ warnings.push(`${task.id}: could not read scope file ${file} for line count`);
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ for (let index = 0; index < graph.tasks.length; index += 1) {
112
+ for (let otherIndex = index + 1; otherIndex < graph.tasks.length; otherIndex += 1) {
113
+ const left = graph.tasks[index];
114
+ const right = graph.tasks[otherIndex];
115
+ if (!left || !right) {
116
+ continue;
117
+ }
118
+ if (isSerialized(left.id, right.id, taskById, dependencyCache)) {
119
+ continue;
120
+ }
121
+ const overlap = intersectFiles(left.scope.files, right.scope.files);
122
+ if (overlap.length === 0) {
123
+ continue;
124
+ }
125
+ if (left.scope.allow_shared_files && right.scope.allow_shared_files) {
126
+ warnings.push(`Scope overlap between ${left.id} and ${right.id}: ${overlap.join(', ')}`);
127
+ warnings.push(`Consider consolidating or serializing ${left.id} and ${right.id} for shared files: ${overlap.join(', ')}`);
128
+ continue;
129
+ }
130
+ errors.push(`Scope overlap between ${left.id} and ${right.id}: ${overlap.join(', ')} — set allow_shared_files: true on both tasks or add a dependency to serialize them`);
131
+ }
132
+ }
133
+ // Boundary-crossing detection: warn if a task's description references other task IDs
134
+ const allTaskIds = new Set(graph.tasks.map((t) => t.id));
135
+ for (const task of graph.tasks) {
136
+ const text = task.description;
137
+ for (const otherId of allTaskIds) {
138
+ if (otherId === task.id)
139
+ continue;
140
+ // Match "T3" as a word boundary (not inside "T31")
141
+ const pattern = new RegExp(`\\b${otherId}\\b`);
142
+ if (pattern.test(text)) {
143
+ warnings.push(`${task.id}: description references ${otherId} — may indicate cross-task scope bleed`);
144
+ }
145
+ }
146
+ }
147
+ return {
148
+ warnings,
149
+ errors,
150
+ valid: errors.length === 0,
151
+ };
152
+ }
153
+ function getUpstreamNewFiles(taskId, taskById, dependencyCache) {
154
+ const upstreamNewFiles = new Set();
155
+ const upstreamTaskIds = getReachableDependencies(taskId, taskById, dependencyCache);
156
+ for (const upstreamId of upstreamTaskIds) {
157
+ const upstreamTask = taskById.get(upstreamId);
158
+ if (upstreamTask?.scope.new_files) {
159
+ for (const file of upstreamTask.scope.new_files) {
160
+ upstreamNewFiles.add(normalize(file).replace(/^\.\//, ''));
161
+ }
162
+ }
163
+ }
164
+ return upstreamNewFiles;
165
+ }
166
+ export function isSerialized(leftTaskId, rightTaskId, taskById, dependencyCache) {
167
+ return (hasDependencyPath(leftTaskId, rightTaskId, taskById, dependencyCache) ||
168
+ hasDependencyPath(rightTaskId, leftTaskId, taskById, dependencyCache));
169
+ }
170
+ function hasDependencyPath(fromTaskId, toTaskId, taskById, dependencyCache) {
171
+ return getReachableDependencies(fromTaskId, taskById, dependencyCache).has(toTaskId);
172
+ }
173
+ function getReachableDependencies(taskId, taskById, dependencyCache, visiting) {
174
+ const cached = dependencyCache.get(taskId);
175
+ if (cached) {
176
+ return cached;
177
+ }
178
+ const currentVisiting = visiting ?? new Set();
179
+ if (currentVisiting.has(taskId)) {
180
+ // Cycle detected — return empty set to avoid infinite recursion
181
+ return new Set();
182
+ }
183
+ currentVisiting.add(taskId);
184
+ const task = taskById.get(taskId);
185
+ const reachable = new Set();
186
+ if (task) {
187
+ for (const dependencyId of task.dependencies) {
188
+ reachable.add(dependencyId);
189
+ for (const nestedDependencyId of getReachableDependencies(dependencyId, taskById, dependencyCache, currentVisiting)) {
190
+ reachable.add(nestedDependencyId);
191
+ }
192
+ }
193
+ }
194
+ dependencyCache.set(taskId, reachable);
195
+ return reachable;
196
+ }
197
+ export function intersectFiles(leftFiles, rightFiles) {
198
+ const rightSet = new Set(rightFiles);
199
+ const seen = new Set();
200
+ const overlap = [];
201
+ for (const file of leftFiles) {
202
+ if (rightSet.has(file) && !seen.has(file)) {
203
+ seen.add(file);
204
+ overlap.push(file);
205
+ }
206
+ }
207
+ return overlap.sort();
208
+ }
209
+ export function validatePlannerOutput(graph, repoRoot) {
210
+ const warnings = [];
211
+ const fixedChecks = new Map();
212
+ const taskById = new Map(graph.tasks.map((task) => [task.id, task]));
213
+ const dependencyCache = new Map();
214
+ for (const task of graph.tasks) {
215
+ const newFiles = new Set((task.scope.new_files ?? []).map((f) => normalize(f).replace(/^\.\//, '')));
216
+ const upstreamNewFiles = getUpstreamNewFiles(task.id, taskById, dependencyCache);
217
+ for (const check of task.acceptance_checks) {
218
+ const testFilePaths = extractFilePathsFromCheck(check);
219
+ for (const filePath of testFilePaths) {
220
+ const normalizedPath = normalize(filePath).replace(/^\.\//, '');
221
+ let pathExists = false;
222
+ if (repoRoot) {
223
+ const absolutePath = join(repoRoot, filePath);
224
+ if (fileExists(absolutePath)) {
225
+ pathExists = true;
226
+ }
227
+ }
228
+ if (!pathExists && newFiles.has(normalizedPath)) {
229
+ pathExists = true;
230
+ }
231
+ if (!pathExists && upstreamNewFiles.has(normalizedPath)) {
232
+ pathExists = true;
233
+ }
234
+ if (!pathExists) {
235
+ const autoFixed = getAutoFixForCommand(check);
236
+ if (autoFixed && autoFixed !== check) {
237
+ const existingFixed = fixedChecks.get(task.id) ?? [];
238
+ existingFixed.push(check);
239
+ fixedChecks.set(task.id, existingFixed);
240
+ warnings.push(`${task.id}: acceptance check references missing test file ${filePath}, auto-fixing to: ${autoFixed}`);
241
+ }
242
+ else {
243
+ warnings.push(`${task.id}: acceptance check references missing test file ${filePath} (not on disk, not in scope.new_files, not in upstream new_files)`);
244
+ }
245
+ }
246
+ }
247
+ }
248
+ }
249
+ return { warnings, fixedChecks };
250
+ }
251
+ // Re-export scope expansion from its own module
252
+ export { expandScopesFromImportGraph } from './scope-expansion.js';
253
+ //# sourceMappingURL=plan-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-validation.js","sourceRoot":"","sources":["../src/plan-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { CompletedTaskContext, OversizedTask } from './types.js';
2
+ export interface ImportGraphEdge {
3
+ importer: string;
4
+ specifier: string;
5
+ resolved: string | null;
6
+ }
7
+ export interface ImportGraph {
8
+ resolvedEdges: ImportGraphEdge[];
9
+ unresolvedEdges: ImportGraphEdge[];
10
+ }
11
+ export declare function buildPlannerPrompt(input: {
12
+ spec: string;
13
+ repoFiles: string[];
14
+ repoRoot?: string;
15
+ completedTasks?: CompletedTaskContext[];
16
+ extraConstraints?: string;
17
+ importGraph?: ImportGraph;
18
+ }): string;
19
+ export declare function buildReplanPrompt(input: {
20
+ spec: string;
21
+ repoFiles: string[];
22
+ repoRoot?: string;
23
+ completedTasks?: CompletedTaskContext[];
24
+ oversizedTasks: OversizedTask[];
25
+ attemptNumber: number;
26
+ importGraph?: ImportGraph;
27
+ }): string;
28
+ export declare function buildImportGraph(repoRoot: string, repoFiles: string[]): ImportGraph;
29
+ export declare function selectImportGraphEdgesForPrompt(importGraph: ImportGraph): ImportGraph;
30
+ export { validatePlanScope } from './plan-validation.js';
31
+ export type { PlanScopeValidationResult } from './plan-validation.js';
32
+ export declare const TEST_FILE_PATTERN: RegExp;
33
+ export declare function isTestFile(filePath: string): boolean;