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.
- package/README.md +343 -0
- package/dist/components/claude-cli.d.ts +14 -0
- package/dist/components/claude-cli.d.ts.map +1 -0
- package/dist/components/claude-cli.js +50 -0
- package/dist/components/claude-cli.js.map +1 -0
- package/dist/components/cost-optimizer.d.ts +43 -0
- package/dist/components/cost-optimizer.d.ts.map +1 -0
- package/dist/components/cost-optimizer.js +140 -0
- package/dist/components/cost-optimizer.js.map +1 -0
- package/dist/components/executor.d.ts +18 -0
- package/dist/components/executor.d.ts.map +1 -0
- package/dist/components/executor.js +154 -0
- package/dist/components/executor.js.map +1 -0
- package/dist/components/memory-store.d.ts +47 -0
- package/dist/components/memory-store.d.ts.map +1 -0
- package/dist/components/memory-store.js +168 -0
- package/dist/components/memory-store.js.map +1 -0
- package/dist/components/planner.d.ts +22 -0
- package/dist/components/planner.d.ts.map +1 -0
- package/dist/components/planner.js +164 -0
- package/dist/components/planner.js.map +1 -0
- package/dist/components/reviewer.d.ts +19 -0
- package/dist/components/reviewer.d.ts.map +1 -0
- package/dist/components/reviewer.js +162 -0
- package/dist/components/reviewer.js.map +1 -0
- package/dist/components/task-queue.d.ts +36 -0
- package/dist/components/task-queue.d.ts.map +1 -0
- package/dist/components/task-queue.js +156 -0
- package/dist/components/task-queue.js.map +1 -0
- package/dist/components/test-runner.d.ts +20 -0
- package/dist/components/test-runner.d.ts.map +1 -0
- package/dist/components/test-runner.js +201 -0
- package/dist/components/test-runner.js.map +1 -0
- package/dist/core/config.d.ts +5 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +38 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/logger.d.ts +16 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +78 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/types.d.ts +122 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +4 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +137 -0
- package/dist/index.js.map +1 -0
- package/dist/loop-controller.d.ts +39 -0
- package/dist/loop-controller.d.ts.map +1 -0
- package/dist/loop-controller.js +272 -0
- package/dist/loop-controller.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Reviewer = 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 critical code reviewer in an autonomous development loop.
|
|
8
|
+
Your job is to find real problems — not style preferences. Be specific and actionable.
|
|
9
|
+
|
|
10
|
+
Return ONLY valid JSON (no markdown):
|
|
11
|
+
{
|
|
12
|
+
"score": 0-100,
|
|
13
|
+
"passed": true|false,
|
|
14
|
+
"critiques": [
|
|
15
|
+
{
|
|
16
|
+
"severity": "low|medium|high|critical",
|
|
17
|
+
"category": "missing-feature|complexity|correctness|performance|security",
|
|
18
|
+
"description": "what is wrong",
|
|
19
|
+
"suggestion": "how to fix it specifically"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"suggestions": ["string — broader improvement ideas"]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Score guide:
|
|
26
|
+
90-100 : excellent, ship it
|
|
27
|
+
70-89 : good, minor issues
|
|
28
|
+
50-69 : mediocre, should fix before proceeding
|
|
29
|
+
0-49 : significant problems, must rework
|
|
30
|
+
|
|
31
|
+
"passed" = score >= 70 AND no "critical" severity critiques.`;
|
|
32
|
+
class Reviewer {
|
|
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)('Reviewer');
|
|
38
|
+
}
|
|
39
|
+
async review(task) {
|
|
40
|
+
this.log.info('Reviewing task', { taskId: task.id });
|
|
41
|
+
if (!task.result) {
|
|
42
|
+
this.log.warn('Task has no result to review', { taskId: task.id });
|
|
43
|
+
return this.emptyReview(task.id, 'No result to review');
|
|
44
|
+
}
|
|
45
|
+
const prompt = this.buildPrompt(task);
|
|
46
|
+
const cacheKey = this.optimizer.buildCacheKey('review', task.id, prompt);
|
|
47
|
+
const estimate = this.optimizer.estimate(prompt, 1500, cacheKey);
|
|
48
|
+
if (estimate.recommendedAction === 'skip') {
|
|
49
|
+
this.log.warn('Skipping review — budget exhausted');
|
|
50
|
+
return this.emptyReview(task.id, 'Budget exhausted');
|
|
51
|
+
}
|
|
52
|
+
let raw;
|
|
53
|
+
const cached = this.optimizer.getCachedResponse(cacheKey);
|
|
54
|
+
if (cached) {
|
|
55
|
+
raw = cached;
|
|
56
|
+
}
|
|
57
|
+
else if (this.dryRun) {
|
|
58
|
+
raw = this.dryRunResponse(task);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
raw = await this.callApi(prompt);
|
|
62
|
+
this.optimizer.putCachedResponse(cacheKey, raw);
|
|
63
|
+
}
|
|
64
|
+
const result = this.parse(task.id, raw);
|
|
65
|
+
// Persist critiques to memory
|
|
66
|
+
for (const c of result.critiques) {
|
|
67
|
+
this.memory.saveCritique(c);
|
|
68
|
+
}
|
|
69
|
+
this.log.info('Review complete', {
|
|
70
|
+
taskId: task.id,
|
|
71
|
+
score: result.score,
|
|
72
|
+
passed: result.passed,
|
|
73
|
+
criticalIssues: result.critiques.filter((c) => c.severity === 'critical').length,
|
|
74
|
+
});
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
/** Count critical issues across all stored critiques. */
|
|
78
|
+
countCriticalIssues() {
|
|
79
|
+
return this.memory
|
|
80
|
+
.loadAllCritiques()
|
|
81
|
+
.filter((c) => c.severity === 'critical').length;
|
|
82
|
+
}
|
|
83
|
+
// ── Private ────────────────────────────────────────────────────────────────
|
|
84
|
+
buildPrompt(task) {
|
|
85
|
+
const priorCritiques = this.memory
|
|
86
|
+
.loadCritiquesForTask(task.id)
|
|
87
|
+
.map((c) => `• [${c.severity}] ${c.description}`)
|
|
88
|
+
.join('\n');
|
|
89
|
+
const filesCreated = task.result.filesCreated
|
|
90
|
+
.map((f) => `• ${f}`)
|
|
91
|
+
.join('\n');
|
|
92
|
+
return [
|
|
93
|
+
`TASK: ${task.objective}`,
|
|
94
|
+
`\nOUTPUT SUMMARY:\n${task.result.output}`,
|
|
95
|
+
filesCreated ? `\nFILES CREATED:\n${filesCreated}` : '',
|
|
96
|
+
priorCritiques ? `\nPRIOR CRITIQUES (avoid duplicates):\n${priorCritiques}` : '',
|
|
97
|
+
'\nAnalyse this work. Find real problems only — not stylistic preferences.',
|
|
98
|
+
]
|
|
99
|
+
.filter(Boolean)
|
|
100
|
+
.join('\n');
|
|
101
|
+
}
|
|
102
|
+
async callApi(prompt) {
|
|
103
|
+
const { text, costUsd } = await (0, claude_cli_1.callClaude)(SYSTEM_PROMPT, prompt);
|
|
104
|
+
this.optimizer.recordCost(costUsd);
|
|
105
|
+
return text;
|
|
106
|
+
}
|
|
107
|
+
parse(taskId, raw) {
|
|
108
|
+
let parsed;
|
|
109
|
+
try {
|
|
110
|
+
const json = raw.replace(/^```json?\n?/m, '').replace(/```$/m, '').trim();
|
|
111
|
+
parsed = JSON.parse(json);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
this.log.error('Failed to parse review response', { err: String(err) });
|
|
115
|
+
return this.emptyReview(taskId, 'Parse error');
|
|
116
|
+
}
|
|
117
|
+
const critiques = (parsed.critiques ?? []).map((c) => ({
|
|
118
|
+
id: (0, crypto_1.randomUUID)(),
|
|
119
|
+
taskId,
|
|
120
|
+
severity: c.severity,
|
|
121
|
+
category: c.category,
|
|
122
|
+
description: c.description,
|
|
123
|
+
suggestion: c.suggestion,
|
|
124
|
+
createdAt: new Date().toISOString(),
|
|
125
|
+
}));
|
|
126
|
+
return {
|
|
127
|
+
taskId,
|
|
128
|
+
passed: parsed.passed ?? parsed.score >= 70,
|
|
129
|
+
score: parsed.score,
|
|
130
|
+
critiques,
|
|
131
|
+
suggestions: parsed.suggestions ?? [],
|
|
132
|
+
reviewedAt: new Date().toISOString(),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
emptyReview(taskId, reason) {
|
|
136
|
+
return {
|
|
137
|
+
taskId,
|
|
138
|
+
passed: true, // assume pass when review cannot run
|
|
139
|
+
score: 100,
|
|
140
|
+
critiques: [],
|
|
141
|
+
suggestions: [reason],
|
|
142
|
+
reviewedAt: new Date().toISOString(),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
dryRunResponse(task) {
|
|
146
|
+
return JSON.stringify({
|
|
147
|
+
score: 85,
|
|
148
|
+
passed: true,
|
|
149
|
+
critiques: [
|
|
150
|
+
{
|
|
151
|
+
severity: 'low',
|
|
152
|
+
category: 'missing-feature',
|
|
153
|
+
description: '[DRY-RUN] Placeholder critique',
|
|
154
|
+
suggestion: 'This is a dry-run — no real review performed',
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
suggestions: ['Dry-run mode active — enable real review for production use'],
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
exports.Reviewer = Reviewer;
|
|
162
|
+
//# sourceMappingURL=reviewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../../src/components/reviewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { PlannerOutput, Task, TaskStatus } from '../core/types';
|
|
2
|
+
import { MemoryStore } from './memory-store';
|
|
3
|
+
/**
|
|
4
|
+
* In-memory task queue backed by MemoryStore for persistence.
|
|
5
|
+
* Respects dependency ordering: a task is only eligible when all its
|
|
6
|
+
* dependency task IDs are in COMPLETE status.
|
|
7
|
+
*/
|
|
8
|
+
export declare class TaskQueue {
|
|
9
|
+
private readonly memory;
|
|
10
|
+
private tasks;
|
|
11
|
+
private readonly log;
|
|
12
|
+
constructor(memory: MemoryStore);
|
|
13
|
+
enqueue(plan: PlannerOutput): Task;
|
|
14
|
+
enqueueBatch(plans: PlannerOutput[]): Task[];
|
|
15
|
+
/** Move a task to RUNNING. Throws if it cannot run yet. */
|
|
16
|
+
start(taskId: string): Task;
|
|
17
|
+
complete(taskId: string): Task;
|
|
18
|
+
fail(taskId: string, reason?: string): Task;
|
|
19
|
+
block(taskId: string, reason: string): Task;
|
|
20
|
+
retry(taskId: string): Task;
|
|
21
|
+
update(taskId: string, updates: Partial<Task>): Task;
|
|
22
|
+
/** Returns the highest-priority PENDING task whose dependencies are all COMPLETE. */
|
|
23
|
+
nextEligible(): Task | null;
|
|
24
|
+
byStatus(status: TaskStatus): Task[];
|
|
25
|
+
getById(taskId: string): Task | undefined;
|
|
26
|
+
size(): number;
|
|
27
|
+
isComplete(): boolean;
|
|
28
|
+
stats(): Record<TaskStatus, number>;
|
|
29
|
+
private canRun;
|
|
30
|
+
private transition;
|
|
31
|
+
private getOrThrow;
|
|
32
|
+
private persist;
|
|
33
|
+
/** Load tasks that were persisted in a previous run. */
|
|
34
|
+
private hydrate;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=task-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-queue.d.ts","sourceRoot":"","sources":["../../src/components/task-queue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C;;;;GAIG;AACH,qBAAa,SAAS;IAIR,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA6B;gBAEpB,MAAM,EAAE,WAAW;IAMhD,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAgBlC,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE;IAI5C,2DAA2D;IAC3D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAa3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI9B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAO3C,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAO3C,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAW3B,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IASpD,qFAAqF;IACrF,YAAY,IAAI,IAAI,GAAG,IAAI;IAQ3B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE;IAIpC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIzC,IAAI,IAAI,MAAM;IAId,UAAU,IAAI,OAAO;IASrB,KAAK,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC;IAgBnC,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,OAAO;IAKf,wDAAwD;IACxD,OAAO,CAAC,OAAO;CAchB"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TaskQueue = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const logger_1 = require("../core/logger");
|
|
6
|
+
/**
|
|
7
|
+
* In-memory task queue backed by MemoryStore for persistence.
|
|
8
|
+
* Respects dependency ordering: a task is only eligible when all its
|
|
9
|
+
* dependency task IDs are in COMPLETE status.
|
|
10
|
+
*/
|
|
11
|
+
class TaskQueue {
|
|
12
|
+
constructor(memory) {
|
|
13
|
+
this.memory = memory;
|
|
14
|
+
this.tasks = new Map();
|
|
15
|
+
this.log = (0, logger_1.createLogger)('TaskQueue');
|
|
16
|
+
this.hydrate();
|
|
17
|
+
}
|
|
18
|
+
// ── Mutation ───────────────────────────────────────────────────────────────
|
|
19
|
+
enqueue(plan) {
|
|
20
|
+
const task = {
|
|
21
|
+
...plan,
|
|
22
|
+
id: (0, crypto_1.randomUUID)(),
|
|
23
|
+
status: 'PENDING',
|
|
24
|
+
retryCount: 0,
|
|
25
|
+
createdAt: new Date().toISOString(),
|
|
26
|
+
updatedAt: new Date().toISOString(),
|
|
27
|
+
};
|
|
28
|
+
this.tasks.set(task.id, task);
|
|
29
|
+
this.memory.saveTask(task);
|
|
30
|
+
this.log.info('Task enqueued', { taskId: task.id, objective: task.objective });
|
|
31
|
+
return task;
|
|
32
|
+
}
|
|
33
|
+
enqueueBatch(plans) {
|
|
34
|
+
return plans.map((p) => this.enqueue(p));
|
|
35
|
+
}
|
|
36
|
+
/** Move a task to RUNNING. Throws if it cannot run yet. */
|
|
37
|
+
start(taskId) {
|
|
38
|
+
const task = this.getOrThrow(taskId);
|
|
39
|
+
if (!this.canRun(task)) {
|
|
40
|
+
throw new Error(`Task ${taskId} has unresolved dependencies or is not PENDING`);
|
|
41
|
+
}
|
|
42
|
+
task.status = 'RUNNING';
|
|
43
|
+
task.updatedAt = new Date().toISOString();
|
|
44
|
+
this.persist(task);
|
|
45
|
+
return task;
|
|
46
|
+
}
|
|
47
|
+
complete(taskId) {
|
|
48
|
+
return this.transition(taskId, 'COMPLETE');
|
|
49
|
+
}
|
|
50
|
+
fail(taskId, reason) {
|
|
51
|
+
const task = this.transition(taskId, 'FAILED');
|
|
52
|
+
task.blockedReason = reason;
|
|
53
|
+
this.persist(task);
|
|
54
|
+
return task;
|
|
55
|
+
}
|
|
56
|
+
block(taskId, reason) {
|
|
57
|
+
const task = this.transition(taskId, 'BLOCKED');
|
|
58
|
+
task.blockedReason = reason;
|
|
59
|
+
this.persist(task);
|
|
60
|
+
return task;
|
|
61
|
+
}
|
|
62
|
+
retry(taskId) {
|
|
63
|
+
const task = this.getOrThrow(taskId);
|
|
64
|
+
task.status = 'PENDING';
|
|
65
|
+
task.retryCount += 1;
|
|
66
|
+
task.blockedReason = undefined;
|
|
67
|
+
task.updatedAt = new Date().toISOString();
|
|
68
|
+
this.persist(task);
|
|
69
|
+
this.log.info('Task queued for retry', { taskId, retryCount: task.retryCount });
|
|
70
|
+
return task;
|
|
71
|
+
}
|
|
72
|
+
update(taskId, updates) {
|
|
73
|
+
const task = this.getOrThrow(taskId);
|
|
74
|
+
Object.assign(task, updates, { updatedAt: new Date().toISOString() });
|
|
75
|
+
this.persist(task);
|
|
76
|
+
return task;
|
|
77
|
+
}
|
|
78
|
+
// ── Queries ────────────────────────────────────────────────────────────────
|
|
79
|
+
/** Returns the highest-priority PENDING task whose dependencies are all COMPLETE. */
|
|
80
|
+
nextEligible() {
|
|
81
|
+
const eligible = [...this.tasks.values()]
|
|
82
|
+
.filter((t) => t.status === 'PENDING' && this.canRun(t))
|
|
83
|
+
.sort((a, b) => a.priority - b.priority);
|
|
84
|
+
return eligible[0] ?? null;
|
|
85
|
+
}
|
|
86
|
+
byStatus(status) {
|
|
87
|
+
return [...this.tasks.values()].filter((t) => t.status === status);
|
|
88
|
+
}
|
|
89
|
+
getById(taskId) {
|
|
90
|
+
return this.tasks.get(taskId);
|
|
91
|
+
}
|
|
92
|
+
size() {
|
|
93
|
+
return this.tasks.size;
|
|
94
|
+
}
|
|
95
|
+
isComplete() {
|
|
96
|
+
return (this.tasks.size > 0 &&
|
|
97
|
+
[...this.tasks.values()].every((t) => t.status === 'COMPLETE' || t.status === 'FAILED'));
|
|
98
|
+
}
|
|
99
|
+
stats() {
|
|
100
|
+
const counts = {
|
|
101
|
+
PENDING: 0,
|
|
102
|
+
RUNNING: 0,
|
|
103
|
+
BLOCKED: 0,
|
|
104
|
+
COMPLETE: 0,
|
|
105
|
+
FAILED: 0,
|
|
106
|
+
};
|
|
107
|
+
for (const t of this.tasks.values()) {
|
|
108
|
+
counts[t.status]++;
|
|
109
|
+
}
|
|
110
|
+
return counts;
|
|
111
|
+
}
|
|
112
|
+
// ── Internals ──────────────────────────────────────────────────────────────
|
|
113
|
+
canRun(task) {
|
|
114
|
+
if (task.status !== 'PENDING')
|
|
115
|
+
return false;
|
|
116
|
+
return task.dependencies.every((depId) => {
|
|
117
|
+
const dep = this.tasks.get(depId);
|
|
118
|
+
return dep?.status === 'COMPLETE';
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
transition(taskId, status) {
|
|
122
|
+
const task = this.getOrThrow(taskId);
|
|
123
|
+
task.status = status;
|
|
124
|
+
task.updatedAt = new Date().toISOString();
|
|
125
|
+
this.persist(task);
|
|
126
|
+
this.log.debug(`Task → ${status}`, { taskId });
|
|
127
|
+
return task;
|
|
128
|
+
}
|
|
129
|
+
getOrThrow(taskId) {
|
|
130
|
+
const task = this.tasks.get(taskId);
|
|
131
|
+
if (!task)
|
|
132
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
133
|
+
return task;
|
|
134
|
+
}
|
|
135
|
+
persist(task) {
|
|
136
|
+
this.tasks.set(task.id, task);
|
|
137
|
+
this.memory.saveTask(task);
|
|
138
|
+
}
|
|
139
|
+
/** Load tasks that were persisted in a previous run. */
|
|
140
|
+
hydrate() {
|
|
141
|
+
const persisted = this.memory.loadAllTasks();
|
|
142
|
+
for (const task of persisted) {
|
|
143
|
+
// Tasks that were RUNNING when the process died become PENDING again
|
|
144
|
+
if (task.status === 'RUNNING') {
|
|
145
|
+
task.status = 'PENDING';
|
|
146
|
+
task.updatedAt = new Date().toISOString();
|
|
147
|
+
}
|
|
148
|
+
this.tasks.set(task.id, task);
|
|
149
|
+
}
|
|
150
|
+
if (persisted.length > 0) {
|
|
151
|
+
this.log.info('Hydrated task queue from disk', { count: persisted.length });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.TaskQueue = TaskQueue;
|
|
156
|
+
//# sourceMappingURL=task-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-queue.js","sourceRoot":"","sources":["../../src/components/task-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TestReport } from '../core/types';
|
|
2
|
+
export declare class TestRunner {
|
|
3
|
+
private readonly workspaceDir;
|
|
4
|
+
private readonly log;
|
|
5
|
+
constructor(workspaceDir: string);
|
|
6
|
+
/**
|
|
7
|
+
* Runs the test suite in workspaceDir and returns a structured report.
|
|
8
|
+
* Supports Jest (detected via jest.config.* or package.json scripts).
|
|
9
|
+
* Falls back to "npm test" if no Jest config is found.
|
|
10
|
+
*/
|
|
11
|
+
run(): Promise<TestReport>;
|
|
12
|
+
private detectRunner;
|
|
13
|
+
private execTests;
|
|
14
|
+
private parseOutput;
|
|
15
|
+
private parseJestJson;
|
|
16
|
+
private parseJestText;
|
|
17
|
+
private extractCoverage;
|
|
18
|
+
private emptyReport;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=test-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../../src/components/test-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,UAAU,EAAE,MAAM,eAAe,CAAC;AAKxD,qBAAa,UAAU;IAGT,OAAO,CAAC,QAAQ,CAAC,YAAY;IAFzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA8B;gBAErB,YAAY,EAAE,MAAM;IAEjD;;;;OAIG;IACG,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;IAiDhC,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,aAAa;IAwCrB,OAAO,CAAC,aAAa;IAmCrB,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,WAAW;CAYpB"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TestRunner = 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 JSON_REPORTER_SENTINEL = /^{/m;
|
|
9
|
+
class TestRunner {
|
|
10
|
+
constructor(workspaceDir) {
|
|
11
|
+
this.workspaceDir = workspaceDir;
|
|
12
|
+
this.log = (0, logger_1.createLogger)('TestRunner');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Runs the test suite in workspaceDir and returns a structured report.
|
|
16
|
+
* Supports Jest (detected via jest.config.* or package.json scripts).
|
|
17
|
+
* Falls back to "npm test" if no Jest config is found.
|
|
18
|
+
*/
|
|
19
|
+
async run() {
|
|
20
|
+
this.log.info('Running tests', { workspaceDir: this.workspaceDir });
|
|
21
|
+
if (!(0, fs_1.existsSync)(this.workspaceDir)) {
|
|
22
|
+
return this.emptyReport('Workspace directory does not exist');
|
|
23
|
+
}
|
|
24
|
+
const hasJestConfig = (0, fs_1.existsSync)((0, path_1.join)(this.workspaceDir, 'jest.config.ts')) ||
|
|
25
|
+
(0, fs_1.existsSync)((0, path_1.join)(this.workspaceDir, 'jest.config.js')) ||
|
|
26
|
+
(0, fs_1.existsSync)((0, path_1.join)(this.workspaceDir, 'jest.config.json'));
|
|
27
|
+
const hasPkgJson = (0, fs_1.existsSync)((0, path_1.join)(this.workspaceDir, 'package.json'));
|
|
28
|
+
if (!hasJestConfig && !hasPkgJson) {
|
|
29
|
+
return this.emptyReport('No test setup found in workspace');
|
|
30
|
+
}
|
|
31
|
+
const runner = this.detectRunner();
|
|
32
|
+
this.log.debug('Detected test runner', { runner });
|
|
33
|
+
try {
|
|
34
|
+
const raw = this.execTests(runner);
|
|
35
|
+
const report = this.parseOutput(raw, runner);
|
|
36
|
+
this.log.info('Tests complete', {
|
|
37
|
+
total: report.totalTests,
|
|
38
|
+
passed: report.passed,
|
|
39
|
+
failed: report.failed,
|
|
40
|
+
coverage: report.coveragePercent,
|
|
41
|
+
});
|
|
42
|
+
return report;
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
// execSync throws on non-zero exit; capture the output anyway
|
|
46
|
+
const stderr = err instanceof Error && 'stderr' in err
|
|
47
|
+
? String(err.stderr ?? '')
|
|
48
|
+
: String(err);
|
|
49
|
+
const stdout = err instanceof Error && 'stdout' in err
|
|
50
|
+
? String(err.stdout ?? '')
|
|
51
|
+
: '';
|
|
52
|
+
this.log.warn('Test command exited with non-zero code', {
|
|
53
|
+
message: (err instanceof Error ? err.message : String(err)).slice(0, 200),
|
|
54
|
+
});
|
|
55
|
+
return this.parseOutput(stdout + '\n' + stderr, runner);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ── Private ────────────────────────────────────────────────────────────────
|
|
59
|
+
detectRunner() {
|
|
60
|
+
const hasJestConfig = (0, fs_1.existsSync)((0, path_1.join)(this.workspaceDir, 'jest.config.ts')) ||
|
|
61
|
+
(0, fs_1.existsSync)((0, path_1.join)(this.workspaceDir, 'jest.config.js')) ||
|
|
62
|
+
(0, fs_1.existsSync)((0, path_1.join)(this.workspaceDir, 'jest.config.json'));
|
|
63
|
+
if (hasJestConfig)
|
|
64
|
+
return 'jest-json';
|
|
65
|
+
const pkgPath = (0, path_1.join)(this.workspaceDir, 'package.json');
|
|
66
|
+
if ((0, fs_1.existsSync)(pkgPath)) {
|
|
67
|
+
try {
|
|
68
|
+
const pkg = JSON.parse(require('fs').readFileSync(pkgPath, 'utf-8'));
|
|
69
|
+
if (pkg.devDependencies?.jest || pkg.dependencies?.jest)
|
|
70
|
+
return 'jest';
|
|
71
|
+
if (pkg.scripts?.test)
|
|
72
|
+
return 'npm-test';
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// ignore
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return 'npm-test';
|
|
79
|
+
}
|
|
80
|
+
execTests(runner) {
|
|
81
|
+
const opts = {
|
|
82
|
+
cwd: this.workspaceDir,
|
|
83
|
+
encoding: 'utf-8',
|
|
84
|
+
stdio: 'pipe',
|
|
85
|
+
timeout: 120000,
|
|
86
|
+
};
|
|
87
|
+
const cmd = runner === 'jest-json'
|
|
88
|
+
? 'npx jest --json --coverage --passWithNoTests 2>&1 || true'
|
|
89
|
+
: runner === 'jest'
|
|
90
|
+
? 'npx jest --coverage --passWithNoTests 2>&1 || true'
|
|
91
|
+
: 'npm test 2>&1 || true';
|
|
92
|
+
return (0, child_process_1.execSync)(cmd, opts);
|
|
93
|
+
}
|
|
94
|
+
parseOutput(raw, runner) {
|
|
95
|
+
if (runner === 'jest-json') {
|
|
96
|
+
return this.parseJestJson(raw);
|
|
97
|
+
}
|
|
98
|
+
return this.parseJestText(raw);
|
|
99
|
+
}
|
|
100
|
+
parseJestJson(raw) {
|
|
101
|
+
// Jest --json outputs a JSON object as the last line
|
|
102
|
+
const lines = raw.split('\n').filter(Boolean);
|
|
103
|
+
const jsonLine = lines.reverse().find((l) => JSON_REPORTER_SENTINEL.test(l));
|
|
104
|
+
if (!jsonLine)
|
|
105
|
+
return this.parseJestText(raw);
|
|
106
|
+
try {
|
|
107
|
+
const result = JSON.parse(jsonLine);
|
|
108
|
+
const failures = [];
|
|
109
|
+
for (const suite of result.testResults ?? []) {
|
|
110
|
+
for (const t of suite.testResults ?? []) {
|
|
111
|
+
if (t.status === 'failed') {
|
|
112
|
+
failures.push({
|
|
113
|
+
testName: t.fullName,
|
|
114
|
+
file: suite.testFilePath,
|
|
115
|
+
error: t.failureMessages?.[0] ?? 'Unknown failure',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const coverage = this.extractCoverage(result.coverageMap);
|
|
121
|
+
return {
|
|
122
|
+
runAt: new Date().toISOString(),
|
|
123
|
+
totalTests: result.numTotalTests ?? 0,
|
|
124
|
+
passed: result.numPassedTests ?? 0,
|
|
125
|
+
failed: result.numFailedTests ?? 0,
|
|
126
|
+
skipped: result.numPendingTests ?? 0,
|
|
127
|
+
coveragePercent: coverage,
|
|
128
|
+
failures,
|
|
129
|
+
rawOutput: raw.slice(0, 2000),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return this.parseJestText(raw);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
parseJestText(raw) {
|
|
137
|
+
// Heuristic parsing for jest text output or arbitrary test runners
|
|
138
|
+
const testMatch = raw.match(/Tests:\s+(\d+)\s+passed.*?(\d+)\s+total/);
|
|
139
|
+
const failMatch = raw.match(/(\d+)\s+failed/);
|
|
140
|
+
const covMatch = raw.match(/All files\s*\|\s*([\d.]+)/);
|
|
141
|
+
const total = testMatch ? parseInt(testMatch[2]) : 0;
|
|
142
|
+
const failed = failMatch ? parseInt(failMatch[1]) : 0;
|
|
143
|
+
const passed = total - failed;
|
|
144
|
+
const coverage = covMatch ? parseFloat(covMatch[1]) : 0;
|
|
145
|
+
// Extract failure blocks
|
|
146
|
+
const failures = [];
|
|
147
|
+
const failBlocks = raw.match(/● .+\n[\s\S]*?(?=\n●|\n\n[A-Z]|$)/g) ?? [];
|
|
148
|
+
for (const block of failBlocks.slice(0, 20)) {
|
|
149
|
+
const name = block.match(/● (.+)/)?.[1] ?? 'Unknown';
|
|
150
|
+
failures.push({
|
|
151
|
+
testName: name.trim(),
|
|
152
|
+
file: 'unknown',
|
|
153
|
+
error: block.slice(0, 500).trim(),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
runAt: new Date().toISOString(),
|
|
158
|
+
totalTests: total,
|
|
159
|
+
passed,
|
|
160
|
+
failed,
|
|
161
|
+
skipped: 0,
|
|
162
|
+
coveragePercent: coverage,
|
|
163
|
+
failures,
|
|
164
|
+
rawOutput: raw.slice(0, 2000),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
extractCoverage(coverageMap) {
|
|
168
|
+
if (!coverageMap)
|
|
169
|
+
return 0;
|
|
170
|
+
const totals = [];
|
|
171
|
+
for (const file of Object.values(coverageMap)) {
|
|
172
|
+
const f = file;
|
|
173
|
+
const statements = f?.s;
|
|
174
|
+
if (!statements)
|
|
175
|
+
continue;
|
|
176
|
+
const vals = Object.values(statements);
|
|
177
|
+
// istanbul coverage format: s = { "0": 1, "1": 0 } (1 = covered)
|
|
178
|
+
const covered = Object.values(f.s ?? {}).filter((v) => Number(v) > 0).length;
|
|
179
|
+
const total = Object.keys(f.s ?? {}).length;
|
|
180
|
+
if (total > 0)
|
|
181
|
+
totals.push((covered / total) * 100);
|
|
182
|
+
}
|
|
183
|
+
return totals.length > 0
|
|
184
|
+
? Math.round(totals.reduce((a, b) => a + b, 0) / totals.length)
|
|
185
|
+
: 0;
|
|
186
|
+
}
|
|
187
|
+
emptyReport(reason) {
|
|
188
|
+
return {
|
|
189
|
+
runAt: new Date().toISOString(),
|
|
190
|
+
totalTests: 0,
|
|
191
|
+
passed: 0,
|
|
192
|
+
failed: 0,
|
|
193
|
+
skipped: 0,
|
|
194
|
+
coveragePercent: 0,
|
|
195
|
+
failures: [],
|
|
196
|
+
rawOutput: reason,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.TestRunner = TestRunner;
|
|
201
|
+
//# sourceMappingURL=test-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner.js","sourceRoot":"","sources":["../../src/components/test-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { CostBudget, LoopConfig } from './types';
|
|
2
|
+
export declare const DEFAULT_BUDGET: CostBudget;
|
|
3
|
+
export declare function calcCost(inputTokens: number, outputTokens: number): number;
|
|
4
|
+
export declare function defaultLoopConfig(overrides?: Partial<LoopConfig>): LoopConfig;
|
|
5
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEjD,eAAO,MAAM,cAAc,EAAE,UAK5B,CAAC;AASF,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAK1E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,GAAE,OAAO,CAAC,UAAU,CAAM,GAAG,UAAU,CAejF"}
|