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.
- package/.claude/settings.local.json +18 -0
- package/README.md +1215 -146
- package/RELEASE_LOG.md +1489 -0
- package/cli/index.ts +1981 -0
- package/cli/welcome.ts +151 -0
- package/core/code-generator.ts +757 -0
- package/core/combined-generator.ts +63 -0
- package/core/constitution-consolidator.ts +141 -0
- package/core/constitution-generator.ts +89 -0
- package/core/context-loader.ts +453 -0
- package/core/contract-bridge.ts +217 -0
- package/core/dsl-extractor.ts +337 -0
- package/core/dsl-types.ts +166 -0
- package/core/dsl-validator.ts +450 -0
- package/core/error-feedback.ts +354 -0
- package/core/frontend-context-loader.ts +602 -0
- package/core/global-constitution.ts +88 -0
- package/core/key-store.ts +49 -0
- package/core/knowledge-memory.ts +171 -0
- package/core/mock-server-generator.ts +571 -0
- package/core/openapi-exporter.ts +361 -0
- package/core/requirement-decomposer.ts +198 -0
- package/core/reviewer.ts +259 -0
- package/core/spec-assessor.ts +99 -0
- package/core/spec-generator.ts +428 -0
- package/core/spec-refiner.ts +89 -0
- package/core/spec-updater.ts +227 -0
- package/core/spec-versioning.ts +213 -0
- package/core/task-generator.ts +174 -0
- package/core/test-generator.ts +273 -0
- package/core/workspace-loader.ts +256 -0
- package/dist/cli/index.js +6717 -672
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +6717 -670
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +147 -27
- package/dist/index.d.ts +147 -27
- package/dist/index.js +2337 -286
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2329 -285
- package/dist/index.mjs.map +1 -1
- package/git/worktree.ts +109 -0
- package/index.ts +9 -0
- package/package.json +4 -28
- package/prompts/codegen.prompt.ts +259 -0
- package/prompts/consolidate.prompt.ts +73 -0
- package/prompts/constitution.prompt.ts +63 -0
- package/prompts/decompose.prompt.ts +168 -0
- package/prompts/dsl.prompt.ts +203 -0
- package/prompts/frontend-spec.prompt.ts +191 -0
- package/prompts/global-constitution.prompt.ts +61 -0
- package/prompts/spec-assess.prompt.ts +53 -0
- package/prompts/spec.prompt.ts +102 -0
- package/prompts/tasks.prompt.ts +35 -0
- package/prompts/testgen.prompt.ts +84 -0
- package/prompts/update.prompt.ts +131 -0
- package/purpose.docx +0 -0
- package/purpose.md +444 -0
- package/tsconfig.json +14 -0
- 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
|
-
/**
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
211
|
+
private projectRoot;
|
|
212
|
+
constructor(provider: AIProvider, projectRoot?: string);
|
|
106
213
|
private getGitDiff;
|
|
107
214
|
private getDiffStats;
|
|
108
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
211
|
+
private projectRoot;
|
|
212
|
+
constructor(provider: AIProvider, projectRoot?: string);
|
|
106
213
|
private getGitDiff;
|
|
107
214
|
private getDiffStats;
|
|
108
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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 };
|