ai-spec-dev 0.1.0 → 0.17.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 (60) hide show
  1. package/.claude/settings.local.json +18 -0
  2. package/README.md +1215 -146
  3. package/RELEASE_LOG.md +1489 -0
  4. package/cli/index.ts +1981 -0
  5. package/cli/welcome.ts +151 -0
  6. package/core/code-generator.ts +757 -0
  7. package/core/combined-generator.ts +63 -0
  8. package/core/constitution-consolidator.ts +141 -0
  9. package/core/constitution-generator.ts +89 -0
  10. package/core/context-loader.ts +453 -0
  11. package/core/contract-bridge.ts +217 -0
  12. package/core/dsl-extractor.ts +337 -0
  13. package/core/dsl-types.ts +166 -0
  14. package/core/dsl-validator.ts +450 -0
  15. package/core/error-feedback.ts +354 -0
  16. package/core/frontend-context-loader.ts +602 -0
  17. package/core/global-constitution.ts +88 -0
  18. package/core/key-store.ts +49 -0
  19. package/core/knowledge-memory.ts +171 -0
  20. package/core/mock-server-generator.ts +571 -0
  21. package/core/openapi-exporter.ts +361 -0
  22. package/core/requirement-decomposer.ts +198 -0
  23. package/core/reviewer.ts +259 -0
  24. package/core/spec-assessor.ts +99 -0
  25. package/core/spec-generator.ts +428 -0
  26. package/core/spec-refiner.ts +89 -0
  27. package/core/spec-updater.ts +227 -0
  28. package/core/spec-versioning.ts +213 -0
  29. package/core/task-generator.ts +174 -0
  30. package/core/test-generator.ts +273 -0
  31. package/core/workspace-loader.ts +256 -0
  32. package/dist/cli/index.js +6717 -672
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/index.mjs +6717 -670
  35. package/dist/cli/index.mjs.map +1 -1
  36. package/dist/index.d.mts +147 -27
  37. package/dist/index.d.ts +147 -27
  38. package/dist/index.js +2337 -286
  39. package/dist/index.js.map +1 -1
  40. package/dist/index.mjs +2329 -285
  41. package/dist/index.mjs.map +1 -1
  42. package/git/worktree.ts +109 -0
  43. package/index.ts +9 -0
  44. package/package.json +4 -28
  45. package/prompts/codegen.prompt.ts +259 -0
  46. package/prompts/consolidate.prompt.ts +73 -0
  47. package/prompts/constitution.prompt.ts +63 -0
  48. package/prompts/decompose.prompt.ts +168 -0
  49. package/prompts/dsl.prompt.ts +203 -0
  50. package/prompts/frontend-spec.prompt.ts +191 -0
  51. package/prompts/global-constitution.prompt.ts +61 -0
  52. package/prompts/spec-assess.prompt.ts +53 -0
  53. package/prompts/spec.prompt.ts +102 -0
  54. package/prompts/tasks.prompt.ts +35 -0
  55. package/prompts/testgen.prompt.ts +84 -0
  56. package/prompts/update.prompt.ts +131 -0
  57. package/purpose.docx +0 -0
  58. package/purpose.md +444 -0
  59. package/tsconfig.json +14 -0
  60. package/tsup.config.ts +10 -0
package/dist/index.d.mts CHANGED
@@ -1,5 +1,13 @@
1
1
  import OpenAI from 'openai';
2
2
 
3
+ interface SharedConfigFile {
4
+ /** Relative path from project root */
5
+ path: string;
6
+ /** First 80 lines of the file */
7
+ preview: string;
8
+ /** Inferred category */
9
+ category: "i18n" | "constants" | "enums" | "config" | "route-index" | "store-index" | "other";
10
+ }
3
11
  interface ProjectContext {
4
12
  techStack: string[];
5
13
  fileStructure: string[];
@@ -7,20 +15,55 @@ interface ProjectContext {
7
15
  apiStructure: string[];
8
16
  schema?: string;
9
17
  routeSummary?: string;
10
- /** Contents of .ai-spec-constitution.md if present */
18
+ /**
19
+ * Effective constitution injected into prompts.
20
+ * If a global constitution was found it is merged in here (global first, project overrides).
21
+ */
11
22
  constitution?: string;
12
23
  /** Extracted error handling patterns from source */
13
24
  errorPatterns?: string;
25
+ /**
26
+ * Singleton/append-only config files that MUST be modified in-place,
27
+ * never recreated as a new parallel file (i18n, constants, enums, config indices, etc.)
28
+ */
29
+ sharedConfigFiles?: SharedConfigFile[];
14
30
  }
31
+ /**
32
+ * Single source of truth for what counts as a "frontend" project.
33
+ * Import this constant (and isFrontendDeps) everywhere instead of
34
+ * repeating the inline array — one place to add Svelte, Solid, Qwik, etc.
35
+ */
36
+ declare const FRONTEND_FRAMEWORKS: readonly ["react", "vue", "next", "nuxt", "react-native", "expo", "svelte", "solid-js", "qwik"];
37
+ /**
38
+ * Returns true if any of the given dependency keys is a recognised frontend framework.
39
+ * Works on the raw key list from package.json / context.dependencies.
40
+ */
41
+ declare function isFrontendDeps(deps: string[]): boolean;
15
42
  declare class ContextLoader {
16
43
  private projectRoot;
17
44
  constructor(projectRoot: string);
18
45
  loadProjectContext(): Promise<ProjectContext>;
46
+ /** Load PHP project context from composer.json */
47
+ private loadComposerJson;
48
+ /**
49
+ * Load PHP route files (routes/api.php, routes/web.php) as routeSummary.
50
+ * Lumen uses these files to register API endpoints.
51
+ */
52
+ private loadPhpRoutes;
53
+ /** Load Java project context from pom.xml or build.gradle */
54
+ private loadMavenOrGradle;
55
+ /** Scan Java controller files for API structure */
56
+ private loadJavaApiStructure;
19
57
  private loadPackageJson;
20
58
  private loadPrismaSchema;
21
59
  private loadFileStructure;
22
60
  private loadConstitution;
23
61
  private loadErrorPatterns;
62
+ /**
63
+ * Scan for "singleton" config files that should never be duplicated.
64
+ * These are append-only files: i18n bundles, constants, enums, config indices.
65
+ */
66
+ private loadSharedConfigFiles;
24
67
  private loadApiStructure;
25
68
  }
26
69
 
@@ -43,6 +86,17 @@ interface ProviderMeta {
43
86
  * Undefined means the provider has its own SDK (Gemini / Claude).
44
87
  */
45
88
  baseURL?: string;
89
+ /**
90
+ * Role to use for system instructions.
91
+ * OpenAI o1/o3 use "developer" instead of "system".
92
+ * Default: "system"
93
+ */
94
+ systemRole?: "system" | "developer";
95
+ /**
96
+ * Extra body params injected into every chat completion request.
97
+ * e.g. Qwen3 needs { enable_thinking: false } to suppress CoT noise.
98
+ */
99
+ extraBody?: Record<string, unknown>;
46
100
  }
47
101
  declare const PROVIDER_CATALOG: Record<string, ProviderMeta>;
48
102
  declare const SUPPORTED_PROVIDERS: string[];
@@ -66,7 +120,17 @@ declare class OpenAICompatibleProvider implements AIProvider {
66
120
  protected client: OpenAI;
67
121
  readonly providerName: string;
68
122
  readonly modelName: string;
69
- constructor(providerName: string, apiKey: string, modelName: string, baseURL?: string);
123
+ private systemRole;
124
+ private extraBody?;
125
+ constructor(providerName: string, apiKey: string, modelName: string, baseURL?: string, systemRole?: "system" | "developer", extraBody?: Record<string, unknown>);
126
+ generate(prompt: string, systemInstruction?: string): Promise<string>;
127
+ }
128
+ declare class MiMoProvider implements AIProvider {
129
+ readonly providerName = "mimo";
130
+ readonly modelName: string;
131
+ private apiKey;
132
+ private readonly baseUrl;
133
+ constructor(apiKey: string, modelName?: string);
70
134
  generate(prompt: string, systemInstruction?: string): Promise<string>;
71
135
  }
72
136
  declare function createProvider(providerName: string, apiKey: string, modelName?: string): AIProvider;
@@ -82,30 +146,88 @@ declare class SpecRefiner {
82
146
  refineLoop(initialSpec: string): Promise<string>;
83
147
  }
84
148
 
149
+ declare function buildTaskPrompt(spec: string, context?: ProjectContext): string;
150
+ type TaskLayer = "data" | "infra" | "service" | "api" | "test";
151
+ type TaskPriority = "high" | "medium" | "low";
152
+ type TaskStatus = "pending" | "done" | "failed";
153
+ interface SpecTask {
154
+ id: string;
155
+ title: string;
156
+ description: string;
157
+ layer: TaskLayer;
158
+ filesToTouch: string[];
159
+ acceptanceCriteria: string[];
160
+ dependencies: string[];
161
+ priority: TaskPriority;
162
+ /** Runtime checkpoint — set by code generator, persisted to tasks file */
163
+ status?: TaskStatus;
164
+ }
165
+ declare class TaskGenerator {
166
+ private provider;
167
+ constructor(provider: AIProvider);
168
+ generateTasks(spec: string, context?: ProjectContext): Promise<SpecTask[]>;
169
+ saveTasks(tasks: SpecTask[], specFilePath: string): Promise<string>;
170
+ sortByLayer(tasks: SpecTask[]): SpecTask[];
171
+ }
172
+ declare function printTasks(tasks: SpecTask[]): void;
173
+ declare function loadTasksForSpec(specFilePath: string): Promise<SpecTask[] | null>;
174
+ /** Persist a single task's status to the tasks JSON file (checkpoint). */
175
+ declare function updateTaskStatus(specFilePath: string, taskId: string, status: TaskStatus): Promise<void>;
176
+
85
177
  type CodeGenMode = "claude-code" | "api" | "plan";
86
178
  interface CodeGenOptions {
87
179
  /** Run claude non-interactively via -p flag (saves tokens, good for automation) */
88
180
  auto?: boolean;
181
+ /** Resume from last checkpoint — skip tasks already marked as done */
182
+ resume?: boolean;
183
+ /** Path to the DSL JSON file — if provided, structured context is injected into prompts */
184
+ dslFilePath?: string;
185
+ /** Repo language type — selects the appropriate codegen system prompt */
186
+ repoType?: string;
89
187
  }
90
188
  declare class CodeGenerator {
91
189
  private provider;
92
190
  private mode;
93
191
  constructor(provider: AIProvider, mode?: CodeGenMode);
94
- generateCode(specFilePath: string, workingDir: string, context?: ProjectContext, options?: CodeGenOptions): Promise<void>;
192
+ /** Returns the list of file paths written to disk (useful for api-mode review). */
193
+ generateCode(specFilePath: string, workingDir: string, context?: ProjectContext, options?: CodeGenOptions): Promise<string[]>;
95
194
  private isClaudeCLIAvailable;
96
195
  private runClaudeCode;
196
+ /**
197
+ * Incremental claude-code execution: one `claude -p` call per task.
198
+ * Tasks marked as "done" are skipped (resume support).
199
+ * Progress is shown as a percentage bar.
200
+ */
201
+ private runClaudeCodeIncremental;
97
202
  private runApiMode;
98
203
  private runApiModeWithTasks;
99
204
  private generateFiles;
100
205
  private runPlanMode;
101
206
  }
207
+ declare function printTaskProgress(completed: number, total: number, task: SpecTask, mode: "run" | "skip"): void;
102
208
 
103
209
  declare class CodeReviewer {
104
210
  private provider;
105
- constructor(provider: AIProvider);
211
+ private projectRoot;
212
+ constructor(provider: AIProvider, projectRoot?: string);
106
213
  private getGitDiff;
107
214
  private getDiffStats;
108
- reviewCode(specContent: string): Promise<string>;
215
+ /**
216
+ * Two-pass review:
217
+ * Pass 1 — architecture (spec compliance, layer separation, auth)
218
+ * Pass 2 — implementation details (validation, error handling, edge cases)
219
+ * + historical issue recurrence check
220
+ *
221
+ * Falls back to single-pass if the two-pass flag is not set.
222
+ */
223
+ private runTwoPassReview;
224
+ reviewCode(specContent: string, specFile?: string): Promise<string>;
225
+ /**
226
+ * Review directly from generated file contents (for api mode where git diff is empty).
227
+ */
228
+ reviewFiles(specContent: string, filePaths: string[], workingDir: string, specFile?: string): Promise<string>;
229
+ /** Print score trend from history (last N reviews) */
230
+ printScoreTrend(limit?: number): Promise<void>;
109
231
  }
110
232
 
111
233
  declare const CONSTITUTION_FILE = ".ai-spec-constitution.md";
@@ -118,34 +240,32 @@ declare class ConstitutionGenerator {
118
240
  declare function loadConstitution(projectRoot: string): Promise<string | undefined>;
119
241
  declare function printConstitutionHint(exists: boolean): void;
120
242
 
121
- type TaskLayer = "data" | "infra" | "service" | "api" | "test";
122
- type TaskPriority = "high" | "medium" | "low";
123
- interface SpecTask {
124
- id: string;
125
- title: string;
126
- description: string;
127
- layer: TaskLayer;
128
- filesToTouch: string[];
129
- acceptanceCriteria: string[];
130
- dependencies: string[];
131
- priority: TaskPriority;
132
- }
133
- declare class TaskGenerator {
134
- private provider;
135
- constructor(provider: AIProvider);
136
- generateTasks(spec: string, context?: ProjectContext): Promise<SpecTask[]>;
137
- saveTasks(tasks: SpecTask[], specFilePath: string): Promise<string>;
138
- sortByLayer(tasks: SpecTask[]): SpecTask[];
139
- }
140
- declare function printTasks(tasks: SpecTask[]): void;
141
- declare function loadTasksForSpec(specFilePath: string): Promise<SpecTask[] | null>;
243
+ /**
244
+ * combined-generator.ts
245
+ *
246
+ * Generates Spec + Tasks in a single AI call instead of two sequential calls.
247
+ * Avoids the circular-dependency that would arise if spec-generator.ts imported
248
+ * from task-generator.ts (which already imports AIProvider from spec-generator).
249
+ */
250
+
251
+ declare function generateSpecWithTasks(provider: AIProvider, idea: string, context?: ProjectContext): Promise<{
252
+ spec: string;
253
+ tasks: SpecTask[];
254
+ }>;
142
255
 
143
256
  declare class GitWorktreeManager {
144
257
  private baseDir;
145
258
  constructor(baseDir: string);
146
259
  private isGitRepo;
147
260
  private sanitizeFeatureName;
261
+ /**
262
+ * Symlink dependency directories from the base repo into the worktree so that
263
+ * tools like `vite`, `tsc`, etc. are available without re-installing.
264
+ *
265
+ * Handles: node_modules (npm/yarn/pnpm), vendor (PHP Composer)
266
+ */
267
+ private linkDependencies;
148
268
  createWorktree(idea: string): Promise<string | null>;
149
269
  }
150
270
 
151
- export { type AIProvider, CONSTITUTION_FILE, ClaudeProvider, type CodeGenMode, type CodeGenOptions, CodeGenerator, CodeReviewer, ConstitutionGenerator, ContextLoader, DEFAULT_MODELS, ENV_KEY_MAP, GeminiProvider, GitWorktreeManager, OpenAICompatibleProvider, PROVIDER_CATALOG, type ProjectContext, type ProviderMeta, SUPPORTED_PROVIDERS, SpecGenerator, SpecRefiner, type SpecTask, TaskGenerator, type TaskLayer, type TaskPriority, createProvider, loadConstitution, loadTasksForSpec, printConstitutionHint, printTasks };
271
+ export { type AIProvider, CONSTITUTION_FILE, ClaudeProvider, type CodeGenMode, type CodeGenOptions, CodeGenerator, CodeReviewer, ConstitutionGenerator, ContextLoader, DEFAULT_MODELS, ENV_KEY_MAP, FRONTEND_FRAMEWORKS, GeminiProvider, GitWorktreeManager, MiMoProvider, OpenAICompatibleProvider, PROVIDER_CATALOG, type ProjectContext, type ProviderMeta, SUPPORTED_PROVIDERS, type SharedConfigFile, SpecGenerator, SpecRefiner, type SpecTask, TaskGenerator, type TaskLayer, type TaskPriority, type TaskStatus, buildTaskPrompt, createProvider, generateSpecWithTasks, isFrontendDeps, loadConstitution, loadTasksForSpec, printConstitutionHint, printTaskProgress, printTasks, updateTaskStatus };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,13 @@
1
1
  import OpenAI from 'openai';
2
2
 
3
+ interface SharedConfigFile {
4
+ /** Relative path from project root */
5
+ path: string;
6
+ /** First 80 lines of the file */
7
+ preview: string;
8
+ /** Inferred category */
9
+ category: "i18n" | "constants" | "enums" | "config" | "route-index" | "store-index" | "other";
10
+ }
3
11
  interface ProjectContext {
4
12
  techStack: string[];
5
13
  fileStructure: string[];
@@ -7,20 +15,55 @@ interface ProjectContext {
7
15
  apiStructure: string[];
8
16
  schema?: string;
9
17
  routeSummary?: string;
10
- /** Contents of .ai-spec-constitution.md if present */
18
+ /**
19
+ * Effective constitution injected into prompts.
20
+ * If a global constitution was found it is merged in here (global first, project overrides).
21
+ */
11
22
  constitution?: string;
12
23
  /** Extracted error handling patterns from source */
13
24
  errorPatterns?: string;
25
+ /**
26
+ * Singleton/append-only config files that MUST be modified in-place,
27
+ * never recreated as a new parallel file (i18n, constants, enums, config indices, etc.)
28
+ */
29
+ sharedConfigFiles?: SharedConfigFile[];
14
30
  }
31
+ /**
32
+ * Single source of truth for what counts as a "frontend" project.
33
+ * Import this constant (and isFrontendDeps) everywhere instead of
34
+ * repeating the inline array — one place to add Svelte, Solid, Qwik, etc.
35
+ */
36
+ declare const FRONTEND_FRAMEWORKS: readonly ["react", "vue", "next", "nuxt", "react-native", "expo", "svelte", "solid-js", "qwik"];
37
+ /**
38
+ * Returns true if any of the given dependency keys is a recognised frontend framework.
39
+ * Works on the raw key list from package.json / context.dependencies.
40
+ */
41
+ declare function isFrontendDeps(deps: string[]): boolean;
15
42
  declare class ContextLoader {
16
43
  private projectRoot;
17
44
  constructor(projectRoot: string);
18
45
  loadProjectContext(): Promise<ProjectContext>;
46
+ /** Load PHP project context from composer.json */
47
+ private loadComposerJson;
48
+ /**
49
+ * Load PHP route files (routes/api.php, routes/web.php) as routeSummary.
50
+ * Lumen uses these files to register API endpoints.
51
+ */
52
+ private loadPhpRoutes;
53
+ /** Load Java project context from pom.xml or build.gradle */
54
+ private loadMavenOrGradle;
55
+ /** Scan Java controller files for API structure */
56
+ private loadJavaApiStructure;
19
57
  private loadPackageJson;
20
58
  private loadPrismaSchema;
21
59
  private loadFileStructure;
22
60
  private loadConstitution;
23
61
  private loadErrorPatterns;
62
+ /**
63
+ * Scan for "singleton" config files that should never be duplicated.
64
+ * These are append-only files: i18n bundles, constants, enums, config indices.
65
+ */
66
+ private loadSharedConfigFiles;
24
67
  private loadApiStructure;
25
68
  }
26
69
 
@@ -43,6 +86,17 @@ interface ProviderMeta {
43
86
  * Undefined means the provider has its own SDK (Gemini / Claude).
44
87
  */
45
88
  baseURL?: string;
89
+ /**
90
+ * Role to use for system instructions.
91
+ * OpenAI o1/o3 use "developer" instead of "system".
92
+ * Default: "system"
93
+ */
94
+ systemRole?: "system" | "developer";
95
+ /**
96
+ * Extra body params injected into every chat completion request.
97
+ * e.g. Qwen3 needs { enable_thinking: false } to suppress CoT noise.
98
+ */
99
+ extraBody?: Record<string, unknown>;
46
100
  }
47
101
  declare const PROVIDER_CATALOG: Record<string, ProviderMeta>;
48
102
  declare const SUPPORTED_PROVIDERS: string[];
@@ -66,7 +120,17 @@ declare class OpenAICompatibleProvider implements AIProvider {
66
120
  protected client: OpenAI;
67
121
  readonly providerName: string;
68
122
  readonly modelName: string;
69
- constructor(providerName: string, apiKey: string, modelName: string, baseURL?: string);
123
+ private systemRole;
124
+ private extraBody?;
125
+ constructor(providerName: string, apiKey: string, modelName: string, baseURL?: string, systemRole?: "system" | "developer", extraBody?: Record<string, unknown>);
126
+ generate(prompt: string, systemInstruction?: string): Promise<string>;
127
+ }
128
+ declare class MiMoProvider implements AIProvider {
129
+ readonly providerName = "mimo";
130
+ readonly modelName: string;
131
+ private apiKey;
132
+ private readonly baseUrl;
133
+ constructor(apiKey: string, modelName?: string);
70
134
  generate(prompt: string, systemInstruction?: string): Promise<string>;
71
135
  }
72
136
  declare function createProvider(providerName: string, apiKey: string, modelName?: string): AIProvider;
@@ -82,30 +146,88 @@ declare class SpecRefiner {
82
146
  refineLoop(initialSpec: string): Promise<string>;
83
147
  }
84
148
 
149
+ declare function buildTaskPrompt(spec: string, context?: ProjectContext): string;
150
+ type TaskLayer = "data" | "infra" | "service" | "api" | "test";
151
+ type TaskPriority = "high" | "medium" | "low";
152
+ type TaskStatus = "pending" | "done" | "failed";
153
+ interface SpecTask {
154
+ id: string;
155
+ title: string;
156
+ description: string;
157
+ layer: TaskLayer;
158
+ filesToTouch: string[];
159
+ acceptanceCriteria: string[];
160
+ dependencies: string[];
161
+ priority: TaskPriority;
162
+ /** Runtime checkpoint — set by code generator, persisted to tasks file */
163
+ status?: TaskStatus;
164
+ }
165
+ declare class TaskGenerator {
166
+ private provider;
167
+ constructor(provider: AIProvider);
168
+ generateTasks(spec: string, context?: ProjectContext): Promise<SpecTask[]>;
169
+ saveTasks(tasks: SpecTask[], specFilePath: string): Promise<string>;
170
+ sortByLayer(tasks: SpecTask[]): SpecTask[];
171
+ }
172
+ declare function printTasks(tasks: SpecTask[]): void;
173
+ declare function loadTasksForSpec(specFilePath: string): Promise<SpecTask[] | null>;
174
+ /** Persist a single task's status to the tasks JSON file (checkpoint). */
175
+ declare function updateTaskStatus(specFilePath: string, taskId: string, status: TaskStatus): Promise<void>;
176
+
85
177
  type CodeGenMode = "claude-code" | "api" | "plan";
86
178
  interface CodeGenOptions {
87
179
  /** Run claude non-interactively via -p flag (saves tokens, good for automation) */
88
180
  auto?: boolean;
181
+ /** Resume from last checkpoint — skip tasks already marked as done */
182
+ resume?: boolean;
183
+ /** Path to the DSL JSON file — if provided, structured context is injected into prompts */
184
+ dslFilePath?: string;
185
+ /** Repo language type — selects the appropriate codegen system prompt */
186
+ repoType?: string;
89
187
  }
90
188
  declare class CodeGenerator {
91
189
  private provider;
92
190
  private mode;
93
191
  constructor(provider: AIProvider, mode?: CodeGenMode);
94
- generateCode(specFilePath: string, workingDir: string, context?: ProjectContext, options?: CodeGenOptions): Promise<void>;
192
+ /** Returns the list of file paths written to disk (useful for api-mode review). */
193
+ generateCode(specFilePath: string, workingDir: string, context?: ProjectContext, options?: CodeGenOptions): Promise<string[]>;
95
194
  private isClaudeCLIAvailable;
96
195
  private runClaudeCode;
196
+ /**
197
+ * Incremental claude-code execution: one `claude -p` call per task.
198
+ * Tasks marked as "done" are skipped (resume support).
199
+ * Progress is shown as a percentage bar.
200
+ */
201
+ private runClaudeCodeIncremental;
97
202
  private runApiMode;
98
203
  private runApiModeWithTasks;
99
204
  private generateFiles;
100
205
  private runPlanMode;
101
206
  }
207
+ declare function printTaskProgress(completed: number, total: number, task: SpecTask, mode: "run" | "skip"): void;
102
208
 
103
209
  declare class CodeReviewer {
104
210
  private provider;
105
- constructor(provider: AIProvider);
211
+ private projectRoot;
212
+ constructor(provider: AIProvider, projectRoot?: string);
106
213
  private getGitDiff;
107
214
  private getDiffStats;
108
- reviewCode(specContent: string): Promise<string>;
215
+ /**
216
+ * Two-pass review:
217
+ * Pass 1 — architecture (spec compliance, layer separation, auth)
218
+ * Pass 2 — implementation details (validation, error handling, edge cases)
219
+ * + historical issue recurrence check
220
+ *
221
+ * Falls back to single-pass if the two-pass flag is not set.
222
+ */
223
+ private runTwoPassReview;
224
+ reviewCode(specContent: string, specFile?: string): Promise<string>;
225
+ /**
226
+ * Review directly from generated file contents (for api mode where git diff is empty).
227
+ */
228
+ reviewFiles(specContent: string, filePaths: string[], workingDir: string, specFile?: string): Promise<string>;
229
+ /** Print score trend from history (last N reviews) */
230
+ printScoreTrend(limit?: number): Promise<void>;
109
231
  }
110
232
 
111
233
  declare const CONSTITUTION_FILE = ".ai-spec-constitution.md";
@@ -118,34 +240,32 @@ declare class ConstitutionGenerator {
118
240
  declare function loadConstitution(projectRoot: string): Promise<string | undefined>;
119
241
  declare function printConstitutionHint(exists: boolean): void;
120
242
 
121
- type TaskLayer = "data" | "infra" | "service" | "api" | "test";
122
- type TaskPriority = "high" | "medium" | "low";
123
- interface SpecTask {
124
- id: string;
125
- title: string;
126
- description: string;
127
- layer: TaskLayer;
128
- filesToTouch: string[];
129
- acceptanceCriteria: string[];
130
- dependencies: string[];
131
- priority: TaskPriority;
132
- }
133
- declare class TaskGenerator {
134
- private provider;
135
- constructor(provider: AIProvider);
136
- generateTasks(spec: string, context?: ProjectContext): Promise<SpecTask[]>;
137
- saveTasks(tasks: SpecTask[], specFilePath: string): Promise<string>;
138
- sortByLayer(tasks: SpecTask[]): SpecTask[];
139
- }
140
- declare function printTasks(tasks: SpecTask[]): void;
141
- declare function loadTasksForSpec(specFilePath: string): Promise<SpecTask[] | null>;
243
+ /**
244
+ * combined-generator.ts
245
+ *
246
+ * Generates Spec + Tasks in a single AI call instead of two sequential calls.
247
+ * Avoids the circular-dependency that would arise if spec-generator.ts imported
248
+ * from task-generator.ts (which already imports AIProvider from spec-generator).
249
+ */
250
+
251
+ declare function generateSpecWithTasks(provider: AIProvider, idea: string, context?: ProjectContext): Promise<{
252
+ spec: string;
253
+ tasks: SpecTask[];
254
+ }>;
142
255
 
143
256
  declare class GitWorktreeManager {
144
257
  private baseDir;
145
258
  constructor(baseDir: string);
146
259
  private isGitRepo;
147
260
  private sanitizeFeatureName;
261
+ /**
262
+ * Symlink dependency directories from the base repo into the worktree so that
263
+ * tools like `vite`, `tsc`, etc. are available without re-installing.
264
+ *
265
+ * Handles: node_modules (npm/yarn/pnpm), vendor (PHP Composer)
266
+ */
267
+ private linkDependencies;
148
268
  createWorktree(idea: string): Promise<string | null>;
149
269
  }
150
270
 
151
- export { type AIProvider, CONSTITUTION_FILE, ClaudeProvider, type CodeGenMode, type CodeGenOptions, CodeGenerator, CodeReviewer, ConstitutionGenerator, ContextLoader, DEFAULT_MODELS, ENV_KEY_MAP, GeminiProvider, GitWorktreeManager, OpenAICompatibleProvider, PROVIDER_CATALOG, type ProjectContext, type ProviderMeta, SUPPORTED_PROVIDERS, SpecGenerator, SpecRefiner, type SpecTask, TaskGenerator, type TaskLayer, type TaskPriority, createProvider, loadConstitution, loadTasksForSpec, printConstitutionHint, printTasks };
271
+ export { type AIProvider, CONSTITUTION_FILE, ClaudeProvider, type CodeGenMode, type CodeGenOptions, CodeGenerator, CodeReviewer, ConstitutionGenerator, ContextLoader, DEFAULT_MODELS, ENV_KEY_MAP, FRONTEND_FRAMEWORKS, GeminiProvider, GitWorktreeManager, MiMoProvider, OpenAICompatibleProvider, PROVIDER_CATALOG, type ProjectContext, type ProviderMeta, SUPPORTED_PROVIDERS, type SharedConfigFile, SpecGenerator, SpecRefiner, type SpecTask, TaskGenerator, type TaskLayer, type TaskPriority, type TaskStatus, buildTaskPrompt, createProvider, generateSpecWithTasks, isFrontendDeps, loadConstitution, loadTasksForSpec, printConstitutionHint, printTaskProgress, printTasks, updateTaskStatus };