goalforge-claude 1.0.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 (54) hide show
  1. package/README.md +343 -0
  2. package/dist/components/claude-cli.d.ts +14 -0
  3. package/dist/components/claude-cli.d.ts.map +1 -0
  4. package/dist/components/claude-cli.js +50 -0
  5. package/dist/components/claude-cli.js.map +1 -0
  6. package/dist/components/cost-optimizer.d.ts +43 -0
  7. package/dist/components/cost-optimizer.d.ts.map +1 -0
  8. package/dist/components/cost-optimizer.js +140 -0
  9. package/dist/components/cost-optimizer.js.map +1 -0
  10. package/dist/components/executor.d.ts +18 -0
  11. package/dist/components/executor.d.ts.map +1 -0
  12. package/dist/components/executor.js +154 -0
  13. package/dist/components/executor.js.map +1 -0
  14. package/dist/components/memory-store.d.ts +47 -0
  15. package/dist/components/memory-store.d.ts.map +1 -0
  16. package/dist/components/memory-store.js +168 -0
  17. package/dist/components/memory-store.js.map +1 -0
  18. package/dist/components/planner.d.ts +22 -0
  19. package/dist/components/planner.d.ts.map +1 -0
  20. package/dist/components/planner.js +164 -0
  21. package/dist/components/planner.js.map +1 -0
  22. package/dist/components/reviewer.d.ts +19 -0
  23. package/dist/components/reviewer.d.ts.map +1 -0
  24. package/dist/components/reviewer.js +162 -0
  25. package/dist/components/reviewer.js.map +1 -0
  26. package/dist/components/task-queue.d.ts +36 -0
  27. package/dist/components/task-queue.d.ts.map +1 -0
  28. package/dist/components/task-queue.js +156 -0
  29. package/dist/components/task-queue.js.map +1 -0
  30. package/dist/components/test-runner.d.ts +20 -0
  31. package/dist/components/test-runner.d.ts.map +1 -0
  32. package/dist/components/test-runner.js +201 -0
  33. package/dist/components/test-runner.js.map +1 -0
  34. package/dist/core/config.d.ts +5 -0
  35. package/dist/core/config.d.ts.map +1 -0
  36. package/dist/core/config.js +38 -0
  37. package/dist/core/config.js.map +1 -0
  38. package/dist/core/logger.d.ts +16 -0
  39. package/dist/core/logger.d.ts.map +1 -0
  40. package/dist/core/logger.js +78 -0
  41. package/dist/core/logger.js.map +1 -0
  42. package/dist/core/types.d.ts +122 -0
  43. package/dist/core/types.d.ts.map +1 -0
  44. package/dist/core/types.js +4 -0
  45. package/dist/core/types.js.map +1 -0
  46. package/dist/index.d.ts +3 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +137 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/loop-controller.d.ts +39 -0
  51. package/dist/loop-controller.d.ts.map +1 -0
  52. package/dist/loop-controller.js +272 -0
  53. package/dist/loop-controller.js.map +1 -0
  54. package/package.json +50 -0
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Executor = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const logger_1 = require("../core/logger");
8
+ const claude_cli_1 = require("./claude-cli");
9
+ const SYSTEM_PROMPT = `You are a senior software engineer implementing a task as part of an autonomous development loop.
10
+ Your output MUST be valid JSON matching this schema (no markdown wrapping):
11
+ {
12
+ "explanation": "string — brief rationale for your approach",
13
+ "files": [
14
+ {
15
+ "path": "string — relative to workspace root",
16
+ "content": "string — full file content"
17
+ }
18
+ ],
19
+ "commands": [
20
+ "string — shell commands to run after files are written (e.g. npm install)"
21
+ ],
22
+ "summary": "string — one sentence describing what was done"
23
+ }
24
+
25
+ Rules:
26
+ - Produce real, working code — no stubs or TODOs unless the task explicitly says so.
27
+ - File paths must be relative to the workspace root (no leading slash).
28
+ - Keep commands minimal and safe (no destructive operations).
29
+ - If no commands are needed, return an empty array.`;
30
+ class Executor {
31
+ constructor(workspaceDir, optimizer, memory, dryRun = false) {
32
+ this.workspaceDir = workspaceDir;
33
+ this.optimizer = optimizer;
34
+ this.memory = memory;
35
+ this.dryRun = dryRun;
36
+ this.log = (0, logger_1.createLogger)('Executor');
37
+ (0, fs_1.mkdirSync)(workspaceDir, { recursive: true });
38
+ }
39
+ async execute(task) {
40
+ this.log.info('Executing task', { taskId: task.id, objective: task.objective });
41
+ const context = this.buildContext(task);
42
+ const cacheKey = this.optimizer.buildCacheKey(task.objective, context);
43
+ const estimate = this.optimizer.estimate(task.objective + context, 4000, cacheKey);
44
+ if (estimate.recommendedAction === 'skip') {
45
+ throw new Error('Budget exhausted — cannot execute task');
46
+ }
47
+ let raw;
48
+ const cached = this.optimizer.getCachedResponse(cacheKey);
49
+ if (cached) {
50
+ raw = cached;
51
+ this.log.debug('Using cached executor response', { taskId: task.id });
52
+ }
53
+ else if (this.dryRun) {
54
+ raw = this.dryRunResponse(task);
55
+ }
56
+ else {
57
+ raw = await this.callApi(task.objective, context);
58
+ this.optimizer.putCachedResponse(cacheKey, raw);
59
+ }
60
+ const parsed = this.parse(raw);
61
+ const result = await this.apply(task, parsed);
62
+ this.memory.updateTaskResult(task.id, result);
63
+ this.log.info('Task executed', {
64
+ taskId: task.id,
65
+ filesCreated: result.filesCreated.length,
66
+ commandsRun: result.commandsRun.length,
67
+ });
68
+ return result;
69
+ }
70
+ // ── Private ────────────────────────────────────────────────────────────────
71
+ buildContext(task) {
72
+ const decisions = this.memory
73
+ .loadAllDecisions()
74
+ .map((d) => `• ${d.title}: ${d.decision}`)
75
+ .join('\n');
76
+ const completedTasks = this.memory
77
+ .loadAllTasks()
78
+ .filter((t) => t.status === 'COMPLETE' && t.result)
79
+ .slice(-5) // last 5 for brevity
80
+ .map((t) => `• ${t.objective}: ${t.result.output.slice(0, 200)}`)
81
+ .join('\n');
82
+ return [
83
+ `Task objective: ${task.objective}`,
84
+ `Effort: ${task.estimatedEffort}`,
85
+ decisions ? `\nArchitecture decisions:\n${decisions}` : '',
86
+ completedTasks ? `\nRecent completed work:\n${completedTasks}` : '',
87
+ ]
88
+ .filter(Boolean)
89
+ .join('\n');
90
+ }
91
+ async callApi(objective, context) {
92
+ const { text, costUsd } = await (0, claude_cli_1.callClaude)(SYSTEM_PROMPT, `TASK: ${objective}\n\nCONTEXT:\n${context}`);
93
+ this.optimizer.recordCost(costUsd);
94
+ return text;
95
+ }
96
+ parse(raw) {
97
+ const json = raw.replace(/^```json?\n?/m, '').replace(/```$/m, '').trim();
98
+ return JSON.parse(json);
99
+ }
100
+ async apply(task, parsed) {
101
+ const filesCreated = [];
102
+ const commandsRun = [];
103
+ // Write files
104
+ for (const file of parsed.files) {
105
+ const absPath = (0, path_1.join)(this.workspaceDir, file.path);
106
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(absPath), { recursive: true });
107
+ (0, fs_1.writeFileSync)(absPath, file.content, 'utf-8');
108
+ filesCreated.push(absPath);
109
+ this.memory.recordGeneratedFile(absPath, task.id, file.content);
110
+ this.log.debug('File written', { path: absPath });
111
+ }
112
+ // Run commands
113
+ for (const cmd of parsed.commands) {
114
+ try {
115
+ this.log.info('Running command', { cmd });
116
+ if (!this.dryRun) {
117
+ (0, child_process_1.execSync)(cmd, { cwd: this.workspaceDir, stdio: 'pipe' });
118
+ }
119
+ commandsRun.push(cmd);
120
+ }
121
+ catch (err) {
122
+ this.log.warn('Command failed (non-fatal)', { cmd, err: String(err) });
123
+ commandsRun.push(`FAILED: ${cmd}`);
124
+ }
125
+ }
126
+ return {
127
+ output: parsed.summary,
128
+ filesCreated,
129
+ filesModified: [],
130
+ commandsRun,
131
+ tokenUsage: {
132
+ inputTokens: 0,
133
+ outputTokens: 0,
134
+ estimatedCostUsd: this.optimizer.getStats().totalSpendUsd,
135
+ },
136
+ executedAt: new Date().toISOString(),
137
+ };
138
+ }
139
+ dryRunResponse(task) {
140
+ return JSON.stringify({
141
+ explanation: 'Dry-run — no API call made',
142
+ files: [
143
+ {
144
+ path: `dry-run/${task.id}.txt`,
145
+ content: `Dry-run output for task: ${task.objective}\n`,
146
+ },
147
+ ],
148
+ commands: [],
149
+ summary: `[DRY-RUN] Completed: ${task.objective}`,
150
+ });
151
+ }
152
+ }
153
+ exports.Executor = Executor;
154
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/components/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { ArchitectureDecision, Critique, ProjectState, Task, TaskResult } from '../core/types';
2
+ /**
3
+ * File-system backed memory store. No external services, no MCP.
4
+ *
5
+ * Layout:
6
+ * memory/
7
+ * state/project.json ← single project state document
8
+ * tasks/<id>.json ← one file per task
9
+ * critiques/<id>.json ← one file per critique
10
+ * decisions/<id>.json ← one file per ADR
11
+ * files/<path-hash>.json ← metadata for generated files
12
+ * cache/<hash>.json ← cost-optimizer response cache
13
+ */
14
+ export declare class MemoryStore {
15
+ private readonly dirs;
16
+ private readonly log;
17
+ constructor(memoryDir: string);
18
+ saveState(state: ProjectState): void;
19
+ loadState(projectId: string): ProjectState | null;
20
+ saveTask(task: Task): void;
21
+ loadTask(taskId: string): Task | null;
22
+ loadAllTasks(): Task[];
23
+ updateTaskResult(taskId: string, result: TaskResult): void;
24
+ saveCritique(critique: Critique): void;
25
+ loadCritiquesForTask(taskId: string): Critique[];
26
+ loadAllCritiques(): Critique[];
27
+ saveDecision(decision: ArchitectureDecision): void;
28
+ loadAllDecisions(): ArchitectureDecision[];
29
+ recordGeneratedFile(filePath: string, taskId: string, content?: string): void;
30
+ loadGeneratedFilePaths(): string[];
31
+ getCached(cacheKey: string): string | null;
32
+ putCache(cacheKey: string, response: string): void;
33
+ getCacheSize(): number;
34
+ getSummary(): {
35
+ taskCount: number;
36
+ completedCount: number;
37
+ critiqueCount: number;
38
+ decisionCount: number;
39
+ generatedFileCount: number;
40
+ cacheEntries: number;
41
+ };
42
+ private write;
43
+ private read;
44
+ private readDir;
45
+ private pathKey;
46
+ }
47
+ //# sourceMappingURL=memory-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../../src/components/memory-store.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,oBAAoB,EACpB,QAAQ,EACR,YAAY,EACZ,IAAI,EACJ,UAAU,EACX,MAAM,eAAe,CAAC;AAGvB;;;;;;;;;;;GAWG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAC9C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA+B;gBAEvC,SAAS,EAAE,MAAM;IAkB7B,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAMpC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IASjD,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAM1B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKrC,YAAY,IAAI,IAAI,EAAE;IAItB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAc1D,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAKtC,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE;IAMhD,gBAAgB,IAAI,QAAQ,EAAE;IAM9B,YAAY,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI;IAMlD,gBAAgB,IAAI,oBAAoB,EAAE;IAM1C,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAW7E,sBAAsB,IAAI,MAAM,EAAE;IAQlC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlD,YAAY,IAAI,MAAM;IAMtB,UAAU,IAAI;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,YAAY,EAAE,MAAM,CAAC;KACtB;IAcD,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,OAAO;CAOhB"}
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryStore = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const logger_1 = require("../core/logger");
7
+ /**
8
+ * File-system backed memory store. No external services, no MCP.
9
+ *
10
+ * Layout:
11
+ * memory/
12
+ * state/project.json ← single project state document
13
+ * tasks/<id>.json ← one file per task
14
+ * critiques/<id>.json ← one file per critique
15
+ * decisions/<id>.json ← one file per ADR
16
+ * files/<path-hash>.json ← metadata for generated files
17
+ * cache/<hash>.json ← cost-optimizer response cache
18
+ */
19
+ class MemoryStore {
20
+ constructor(memoryDir) {
21
+ this.log = (0, logger_1.createLogger)('MemoryStore');
22
+ this.dirs = {
23
+ root: memoryDir,
24
+ state: (0, path_1.join)(memoryDir, 'state'),
25
+ tasks: (0, path_1.join)(memoryDir, 'tasks'),
26
+ critiques: (0, path_1.join)(memoryDir, 'critiques'),
27
+ decisions: (0, path_1.join)(memoryDir, 'decisions'),
28
+ files: (0, path_1.join)(memoryDir, 'files'),
29
+ cache: (0, path_1.join)(memoryDir, 'cache'),
30
+ };
31
+ for (const dir of Object.values(this.dirs)) {
32
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
33
+ }
34
+ }
35
+ // ── Project State ──────────────────────────────────────────────────────────
36
+ saveState(state) {
37
+ const path = (0, path_1.join)(this.dirs.state, 'project.json');
38
+ this.write(path, state);
39
+ this.log.debug('Project state saved', { projectId: state.projectId });
40
+ }
41
+ loadState(projectId) {
42
+ const path = (0, path_1.join)(this.dirs.state, 'project.json');
43
+ const state = this.read(path);
44
+ if (state && state.projectId === projectId)
45
+ return state;
46
+ return null;
47
+ }
48
+ // ── Tasks ──────────────────────────────────────────────────────────────────
49
+ saveTask(task) {
50
+ const path = (0, path_1.join)(this.dirs.tasks, `${task.id}.json`);
51
+ this.write(path, task);
52
+ this.log.debug('Task saved', { taskId: task.id, status: task.status });
53
+ }
54
+ loadTask(taskId) {
55
+ const path = (0, path_1.join)(this.dirs.tasks, `${taskId}.json`);
56
+ return this.read(path);
57
+ }
58
+ loadAllTasks() {
59
+ return this.readDir(this.dirs.tasks);
60
+ }
61
+ updateTaskResult(taskId, result) {
62
+ const task = this.loadTask(taskId);
63
+ if (!task) {
64
+ this.log.warn('Cannot update result — task not found', { taskId });
65
+ return;
66
+ }
67
+ task.result = result;
68
+ task.status = 'COMPLETE';
69
+ task.updatedAt = new Date().toISOString();
70
+ this.saveTask(task);
71
+ }
72
+ // ── Critiques ──────────────────────────────────────────────────────────────
73
+ saveCritique(critique) {
74
+ const path = (0, path_1.join)(this.dirs.critiques, `${critique.id}.json`);
75
+ this.write(path, critique);
76
+ }
77
+ loadCritiquesForTask(taskId) {
78
+ return this.readDir(this.dirs.critiques).filter((c) => c.taskId === taskId);
79
+ }
80
+ loadAllCritiques() {
81
+ return this.readDir(this.dirs.critiques);
82
+ }
83
+ // ── Architecture Decisions ─────────────────────────────────────────────────
84
+ saveDecision(decision) {
85
+ const path = (0, path_1.join)(this.dirs.decisions, `${decision.id}.json`);
86
+ this.write(path, decision);
87
+ this.log.info('Architecture decision recorded', { title: decision.title });
88
+ }
89
+ loadAllDecisions() {
90
+ return this.readDir(this.dirs.decisions);
91
+ }
92
+ // ── Generated File Metadata ────────────────────────────────────────────────
93
+ recordGeneratedFile(filePath, taskId, content) {
94
+ const key = this.pathKey(filePath);
95
+ const path = (0, path_1.join)(this.dirs.files, `${key}.json`);
96
+ this.write(path, {
97
+ filePath,
98
+ taskId,
99
+ recordedAt: new Date().toISOString(),
100
+ contentLength: content?.length ?? 0,
101
+ });
102
+ }
103
+ loadGeneratedFilePaths() {
104
+ return this.readDir(this.dirs.files).map((f) => f.filePath);
105
+ }
106
+ // ── Response Cache ─────────────────────────────────────────────────────────
107
+ getCached(cacheKey) {
108
+ const path = (0, path_1.join)(this.dirs.cache, `${cacheKey}.json`);
109
+ if (!(0, fs_1.existsSync)(path))
110
+ return null;
111
+ const entry = this.read(path);
112
+ return entry?.response ?? null;
113
+ }
114
+ putCache(cacheKey, response) {
115
+ const path = (0, path_1.join)(this.dirs.cache, `${cacheKey}.json`);
116
+ this.write(path, { response, cachedAt: new Date().toISOString() });
117
+ }
118
+ getCacheSize() {
119
+ return (0, fs_1.readdirSync)(this.dirs.cache).filter((f) => f.endsWith('.json')).length;
120
+ }
121
+ // ── Summary ────────────────────────────────────────────────────────────────
122
+ getSummary() {
123
+ const tasks = this.loadAllTasks();
124
+ return {
125
+ taskCount: tasks.length,
126
+ completedCount: tasks.filter((t) => t.status === 'COMPLETE').length,
127
+ critiqueCount: this.readDir(this.dirs.critiques).length,
128
+ decisionCount: this.readDir(this.dirs.decisions).length,
129
+ generatedFileCount: this.readDir(this.dirs.files).length,
130
+ cacheEntries: this.getCacheSize(),
131
+ };
132
+ }
133
+ // ── Internal helpers ───────────────────────────────────────────────────────
134
+ write(path, data) {
135
+ (0, fs_1.writeFileSync)(path, JSON.stringify(data, null, 2), 'utf-8');
136
+ }
137
+ read(path) {
138
+ try {
139
+ if (!(0, fs_1.existsSync)(path))
140
+ return null;
141
+ return JSON.parse((0, fs_1.readFileSync)(path, 'utf-8'));
142
+ }
143
+ catch (err) {
144
+ this.log.warn('Failed to read file', { path, err: String(err) });
145
+ return null;
146
+ }
147
+ }
148
+ readDir(dir) {
149
+ try {
150
+ return (0, fs_1.readdirSync)(dir)
151
+ .filter((f) => f.endsWith('.json'))
152
+ .map((f) => this.read((0, path_1.join)(dir, f)))
153
+ .filter((x) => x !== null);
154
+ }
155
+ catch {
156
+ return [];
157
+ }
158
+ }
159
+ pathKey(filePath) {
160
+ // deterministic safe filename from arbitrary path
161
+ return filePath
162
+ .replace(/[^a-zA-Z0-9]/g, '_')
163
+ .replace(/_+/g, '_')
164
+ .slice(0, 120);
165
+ }
166
+ }
167
+ exports.MemoryStore = MemoryStore;
168
+ //# sourceMappingURL=memory-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-store.js","sourceRoot":"","sources":["../../src/components/memory-store.ts"],"names":[],"mappings":";;;AAAA,2BAAqF;AACrF,+BAA4B;AAQ5B,2CAA8C;AAE9C;;;;;;;;;;;GAWG;AACH,MAAa,WAAW;IAItB,YAAY,SAAiB;QAFZ,QAAG,GAAG,IAAA,qBAAY,EAAC,aAAa,CAAC,CAAC;QAGjD,IAAI,CAAC,IAAI,GAAG;YACV,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,OAAO,CAAC;YAC/B,KAAK,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,OAAO,CAAC;YAC/B,SAAS,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,WAAW,CAAC;YACvC,SAAS,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,WAAW,CAAC;YACvC,KAAK,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,OAAO,CAAC;YAC/B,KAAK,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,OAAO,CAAC;SAChC,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,IAAA,cAAS,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,8EAA8E;IAE9E,SAAS,CAAC,KAAmB;QAC3B,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,SAAS,CAAC,SAAiB;QACzB,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAe,IAAI,CAAC,CAAC;QAC5C,IAAI,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8EAA8E;IAE9E,QAAQ,CAAC,IAAU;QACjB,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,QAAQ,CAAC,MAAc;QACrB,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,IAAI,CAAO,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,OAAO,CAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IAED,gBAAgB,CAAC,MAAc,EAAE,MAAkB;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uCAAuC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,8EAA8E;IAE9E,YAAY,CAAC,QAAkB;QAC7B,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,oBAAoB,CAAC,MAAc;QACjC,OAAO,IAAI,CAAC,OAAO,CAAW,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CACvD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAC3B,CAAC;IACJ,CAAC;IAED,gBAAgB;QACd,OAAO,IAAI,CAAC,OAAO,CAAW,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrD,CAAC;IAED,8EAA8E;IAE9E,YAAY,CAAC,QAA8B;QACzC,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,gBAAgB;QACd,OAAO,IAAI,CAAC,OAAO,CAAuB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACjE,CAAC;IAED,8EAA8E;IAE9E,mBAAmB,CAAC,QAAgB,EAAE,MAAc,EAAE,OAAgB;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YACf,QAAQ;YACR,MAAM;YACN,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,aAAa,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;SACpC,CAAC,CAAC;IACL,CAAC;IAED,sBAAsB;QACpB,OAAO,IAAI,CAAC,OAAO,CAAuB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAC5D,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAClB,CAAC;IACJ,CAAC;IAED,8EAA8E;IAE9E,SAAS,CAAC,QAAgB;QACxB,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;QACvD,IAAI,CAAC,IAAA,eAAU,EAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAyC,IAAI,CAAC,CAAC;QACtE,OAAO,KAAK,EAAE,QAAQ,IAAI,IAAI,CAAC;IACjC,CAAC;IAED,QAAQ,CAAC,QAAgB,EAAE,QAAgB;QACzC,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,YAAY;QACV,OAAO,IAAA,gBAAW,EAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAChF,CAAC;IAED,8EAA8E;IAE9E,UAAU;QAQR,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAClC,OAAO;YACL,SAAS,EAAE,KAAK,CAAC,MAAM;YACvB,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,MAAM;YACnE,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM;YACvD,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM;YACvD,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM;YACxD,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE;SAClC,CAAC;IACJ,CAAC;IAED,8EAA8E;IAEtE,KAAK,CAAC,IAAY,EAAE,IAAa;QACvC,IAAA,kBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAEO,IAAI,CAAI,IAAY;QAC1B,IAAI,CAAC;YACH,IAAI,CAAC,IAAA,eAAU,EAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YACnC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,IAAI,EAAE,OAAO,CAAC,CAAM,CAAC;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,OAAO,CAAI,GAAW;QAC5B,IAAI,CAAC;YACH,OAAO,IAAA,gBAAW,EAAC,GAAG,CAAC;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;iBAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAI,IAAA,WAAI,EAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;iBACtC,MAAM,CAAC,CAAC,CAAC,EAAU,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,QAAgB;QAC9B,kDAAkD;QAClD,OAAO,QAAQ;aACZ,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;aAC7B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACnB,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnB,CAAC;CACF;AAzLD,kCAyLC"}
@@ -0,0 +1,22 @@
1
+ import { PlannerOutput, ProjectState } from '../core/types';
2
+ import { CostOptimizer } from './cost-optimizer';
3
+ import { MemoryStore } from './memory-store';
4
+ export declare class Planner {
5
+ private readonly optimizer;
6
+ private readonly memory;
7
+ private readonly dryRun;
8
+ private readonly log;
9
+ constructor(optimizer: CostOptimizer, memory: MemoryStore, dryRun?: boolean);
10
+ /**
11
+ * Produce an ordered task list for the given goal.
12
+ * Includes prior project state as context so the planner doesn't re-generate
13
+ * already-completed work.
14
+ */
15
+ plan(goal: string, state: ProjectState): Promise<PlannerOutput[]>;
16
+ private buildContext;
17
+ private buildPrompt;
18
+ private callApi;
19
+ private parse;
20
+ private dryRunResponse;
21
+ }
22
+ //# sourceMappingURL=planner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../src/components/planner.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA8C7C,qBAAa,OAAO;IAIhB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA2B;gBAG5B,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,WAAW,EACnB,MAAM,UAAQ;IAGjC;;;;OAIG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAiCvE,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,WAAW;YASL,OAAO;IAMrB,OAAO,CAAC,KAAK;IAoCb,OAAO,CAAC,cAAc;CA4BvB"}
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Planner = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const logger_1 = require("../core/logger");
6
+ const claude_cli_1 = require("./claude-cli");
7
+ const SYSTEM_PROMPT = `You are a senior software architect acting as a project planner.
8
+ Your job is to decompose a high-level project goal into a prioritised list of concrete,
9
+ independently-executable tasks. Each task must be atomic — a single engineer should be
10
+ able to complete it in one sitting.
11
+
12
+ Return ONLY valid JSON matching this schema (no markdown, no prose):
13
+ {
14
+ "tasks": [
15
+ {
16
+ "objective": "string — what exactly must be done",
17
+ "priority": 1, // integer, 1 = highest
18
+ "dependencies": [], // array of objective strings from THIS response
19
+ "estimatedEffort": "low|medium|high",
20
+ "rationale": "string — why this task exists"
21
+ }
22
+ ],
23
+ "decisions": [
24
+ {
25
+ "title": "string",
26
+ "context": "string",
27
+ "decision": "string",
28
+ "consequences": "string"
29
+ }
30
+ ]
31
+ }`;
32
+ class Planner {
33
+ constructor(optimizer, memory, dryRun = false) {
34
+ this.optimizer = optimizer;
35
+ this.memory = memory;
36
+ this.dryRun = dryRun;
37
+ this.log = (0, logger_1.createLogger)('Planner');
38
+ }
39
+ /**
40
+ * Produce an ordered task list for the given goal.
41
+ * Includes prior project state as context so the planner doesn't re-generate
42
+ * already-completed work.
43
+ */
44
+ async plan(goal, state) {
45
+ const contextSummary = this.buildContext(state);
46
+ const prompt = this.buildPrompt(goal, contextSummary);
47
+ const cacheKey = this.optimizer.buildCacheKey(prompt);
48
+ const estimate = this.optimizer.estimate(prompt, 2000, cacheKey);
49
+ this.log.info('Planning tasks', {
50
+ goal: goal.slice(0, 80),
51
+ action: estimate.recommendedAction,
52
+ });
53
+ if (estimate.recommendedAction === 'skip') {
54
+ this.log.warn('Skipping planning — budget exhausted');
55
+ return [];
56
+ }
57
+ let raw;
58
+ const cached = this.optimizer.getCachedResponse(cacheKey);
59
+ if (cached) {
60
+ raw = cached;
61
+ }
62
+ else if (this.dryRun) {
63
+ raw = this.dryRunResponse(goal);
64
+ }
65
+ else {
66
+ raw = await this.callApi(prompt);
67
+ this.optimizer.putCachedResponse(cacheKey, raw);
68
+ }
69
+ return this.parse(raw);
70
+ }
71
+ // ── Private ────────────────────────────────────────────────────────────────
72
+ buildContext(state) {
73
+ const completed = state.completedTaskIds.length;
74
+ const decisions = this.memory.loadAllDecisions();
75
+ const decisionSummary = decisions
76
+ .map((d) => `• ${d.title}: ${d.decision}`)
77
+ .join('\n');
78
+ return [
79
+ `Phase: ${state.currentPhase}`,
80
+ `Iteration: ${state.iterationCount}`,
81
+ `Completed tasks: ${completed}`,
82
+ `Coverage: ${state.coveragePercent}%`,
83
+ decisions.length > 0 ? `\nArchitecture decisions:\n${decisionSummary}` : '',
84
+ ]
85
+ .filter(Boolean)
86
+ .join('\n');
87
+ }
88
+ buildPrompt(goal, context) {
89
+ return [
90
+ `PROJECT GOAL:\n${goal}`,
91
+ `\nCURRENT STATE:\n${context}`,
92
+ '\nGenerate a prioritised task breakdown. Focus only on tasks NOT yet completed.',
93
+ 'Be specific and avoid redundancy with already-made architecture decisions.',
94
+ ].join('\n');
95
+ }
96
+ async callApi(prompt) {
97
+ const { text, costUsd } = await (0, claude_cli_1.callClaude)(SYSTEM_PROMPT, prompt);
98
+ this.optimizer.recordCost(costUsd);
99
+ return text;
100
+ }
101
+ parse(raw) {
102
+ let parsed;
103
+ try {
104
+ // strip markdown fences if present
105
+ const json = raw.replace(/^```json?\n?/m, '').replace(/```$/m, '').trim();
106
+ parsed = JSON.parse(json);
107
+ }
108
+ catch (err) {
109
+ this.log.error('Failed to parse planner response', { err: String(err), raw });
110
+ return [];
111
+ }
112
+ // Persist architecture decisions
113
+ for (const d of parsed.decisions ?? []) {
114
+ const decision = {
115
+ id: (0, crypto_1.randomUUID)(),
116
+ ...d,
117
+ madeAt: new Date().toISOString(),
118
+ };
119
+ this.memory.saveDecision(decision);
120
+ }
121
+ // Resolve dependency strings → task objectives (same-batch cross-referencing)
122
+ const tasks = parsed.tasks ?? [];
123
+ const objectiveToIndex = new Map(tasks.map((t, i) => [t.objective, String(i)]));
124
+ return tasks.map((t) => ({
125
+ objective: t.objective,
126
+ priority: t.priority,
127
+ estimatedEffort: t.estimatedEffort,
128
+ rationale: t.rationale,
129
+ dependencies: t.dependencies
130
+ .map((dep) => objectiveToIndex.get(dep))
131
+ .filter((id) => id !== undefined),
132
+ }));
133
+ }
134
+ dryRunResponse(goal) {
135
+ return JSON.stringify({
136
+ tasks: [
137
+ {
138
+ objective: `[DRY-RUN] Scaffold project structure for: ${goal}`,
139
+ priority: 1,
140
+ dependencies: [],
141
+ estimatedEffort: 'low',
142
+ rationale: 'Dry-run placeholder task',
143
+ },
144
+ {
145
+ objective: `[DRY-RUN] Implement core logic for: ${goal}`,
146
+ priority: 2,
147
+ dependencies: [`[DRY-RUN] Scaffold project structure for: ${goal}`],
148
+ estimatedEffort: 'medium',
149
+ rationale: 'Dry-run placeholder task',
150
+ },
151
+ ],
152
+ decisions: [
153
+ {
154
+ title: 'DRY-RUN mode',
155
+ context: 'Planner invoked with dryRun=true',
156
+ decision: 'Return stubbed tasks without API calls',
157
+ consequences: 'No real planning occurs',
158
+ },
159
+ ],
160
+ });
161
+ }
162
+ }
163
+ exports.Planner = Planner;
164
+ //# sourceMappingURL=planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../src/components/planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { ReviewResult, Task } from '../core/types';
2
+ import { CostOptimizer } from './cost-optimizer';
3
+ import { MemoryStore } from './memory-store';
4
+ export declare class Reviewer {
5
+ private readonly optimizer;
6
+ private readonly memory;
7
+ private readonly dryRun;
8
+ private readonly log;
9
+ constructor(optimizer: CostOptimizer, memory: MemoryStore, dryRun?: boolean);
10
+ review(task: Task): Promise<ReviewResult>;
11
+ /** Count critical issues across all stored critiques. */
12
+ countCriticalIssues(): number;
13
+ private buildPrompt;
14
+ private callApi;
15
+ private parse;
16
+ private emptyReview;
17
+ private dryRunResponse;
18
+ }
19
+ //# sourceMappingURL=reviewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewer.d.ts","sourceRoot":"","sources":["../../src/components/reviewer.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,YAAY,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA4C7C,qBAAa,QAAQ;IAIjB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA4B;gBAG7B,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,WAAW,EACnB,MAAM,UAAQ;IAG3B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;IA6C/C,yDAAyD;IACzD,mBAAmB,IAAI,MAAM;IAQ7B,OAAO,CAAC,WAAW;YAqBL,OAAO;IAMrB,OAAO,CAAC,KAAK;IA8Bb,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,cAAc;CAevB"}