agents-harness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +317 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +56 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/config.d.ts +26 -0
  6. package/dist/commands/config.js +91 -0
  7. package/dist/commands/config.js.map +1 -0
  8. package/dist/commands/init.d.ts +1 -0
  9. package/dist/commands/init.js +67 -0
  10. package/dist/commands/init.js.map +1 -0
  11. package/dist/commands/resume.d.ts +6 -0
  12. package/dist/commands/resume.js +88 -0
  13. package/dist/commands/resume.js.map +1 -0
  14. package/dist/commands/run.d.ts +8 -0
  15. package/dist/commands/run.js +106 -0
  16. package/dist/commands/run.js.map +1 -0
  17. package/dist/commands/status.d.ts +1 -0
  18. package/dist/commands/status.js +38 -0
  19. package/dist/commands/status.js.map +1 -0
  20. package/dist/core/context-manager.d.ts +19 -0
  21. package/dist/core/context-manager.js +118 -0
  22. package/dist/core/context-manager.js.map +1 -0
  23. package/dist/core/file-protocol.d.ts +14 -0
  24. package/dist/core/file-protocol.js +119 -0
  25. package/dist/core/file-protocol.js.map +1 -0
  26. package/dist/core/orchestrator.d.ts +30 -0
  27. package/dist/core/orchestrator.js +238 -0
  28. package/dist/core/orchestrator.js.map +1 -0
  29. package/dist/core/types.d.ts +136 -0
  30. package/dist/core/types.js +3 -0
  31. package/dist/core/types.js.map +1 -0
  32. package/dist/dashboard/server.d.ts +15 -0
  33. package/dist/dashboard/server.js +61 -0
  34. package/dist/dashboard/server.js.map +1 -0
  35. package/dist/dashboard/socket.d.ts +8 -0
  36. package/dist/dashboard/socket.js +22 -0
  37. package/dist/dashboard/socket.js.map +1 -0
  38. package/dist/defaults/criteria.d.ts +1 -0
  39. package/dist/defaults/criteria.js +23 -0
  40. package/dist/defaults/criteria.js.map +1 -0
  41. package/dist/defaults/prompts.d.ts +15 -0
  42. package/dist/defaults/prompts.js +123 -0
  43. package/dist/defaults/prompts.js.map +1 -0
  44. package/dist/discovery/config-loader.d.ts +12 -0
  45. package/dist/discovery/config-loader.js +64 -0
  46. package/dist/discovery/config-loader.js.map +1 -0
  47. package/dist/discovery/project-context.d.ts +12 -0
  48. package/dist/discovery/project-context.js +56 -0
  49. package/dist/discovery/project-context.js.map +1 -0
  50. package/dist/discovery/stack-detector.d.ts +15 -0
  51. package/dist/discovery/stack-detector.js +372 -0
  52. package/dist/discovery/stack-detector.js.map +1 -0
  53. package/dist/index.d.ts +12 -0
  54. package/dist/index.js +14 -0
  55. package/dist/index.js.map +1 -0
  56. package/package.json +60 -0
@@ -0,0 +1,238 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { ContextManager } from "./context-manager.js";
3
+ import { FileProtocol } from "./file-protocol.js";
4
+ import { buildProjectContext } from "../discovery/project-context.js";
5
+ export class Harness extends EventEmitter {
6
+ contextManager;
7
+ fileProtocol;
8
+ progress;
9
+ aborted = false;
10
+ options;
11
+ constructor(opts) {
12
+ super();
13
+ const projectContext = buildProjectContext(opts.root, opts.scope ?? null);
14
+ // Apply config overrides from .harness/config.yaml
15
+ const config = projectContext.config;
16
+ this.options = {
17
+ maxAttemptsPerSprint: opts.maxAttemptsPerSprint ?? config?.maxAttemptsPerSprint ?? 3,
18
+ maxBudgetPerSprintUsd: opts.maxBudgetPerSprintUsd ?? config?.maxBudgetPerSprintUsd ?? 5,
19
+ maxTotalBudgetUsd: opts.maxTotalBudgetUsd ?? config?.maxTotalBudgetUsd ?? 50,
20
+ };
21
+ this.contextManager = new ContextManager(opts.apiKey, projectContext);
22
+ this.fileProtocol = new FileProtocol(opts.root);
23
+ this.progress = this.initProgress("");
24
+ }
25
+ initProgress(runSpec) {
26
+ return {
27
+ status: "running",
28
+ runSpec,
29
+ currentSprint: 0,
30
+ totalSprints: 0,
31
+ currentAttempt: 0,
32
+ currentPhase: "plan",
33
+ startedAt: new Date().toISOString(),
34
+ costUsd: 0,
35
+ maxBudgetUsd: this.options.maxTotalBudgetUsd,
36
+ sprints: {},
37
+ };
38
+ }
39
+ emitEvent(event) {
40
+ this.emit(event.type, event.data);
41
+ this.emit("event", event);
42
+ }
43
+ updatePhase(phase, sprint = 0, attempt = 0) {
44
+ this.progress.currentPhase = phase;
45
+ this.progress.currentSprint = sprint;
46
+ this.progress.currentAttempt = attempt;
47
+ this.emitEvent({
48
+ type: "phase:start",
49
+ data: { sprint, phase, attempt },
50
+ });
51
+ }
52
+ async runAgentPhase(role, prompt, sprint) {
53
+ const result = await this.contextManager.runAgent({
54
+ role,
55
+ prompt,
56
+ onActivity: (tool, summary) => {
57
+ this.emitEvent({
58
+ type: "agent:activity",
59
+ data: { sprint, role, tool, summary, timestamp: Date.now() },
60
+ });
61
+ },
62
+ });
63
+ this.progress.costUsd += result.costUsd;
64
+ if (this.progress.sprints[sprint]) {
65
+ this.progress.sprints[sprint].costUsd += result.costUsd;
66
+ }
67
+ this.emitEvent({
68
+ type: "cost:update",
69
+ data: {
70
+ sprintCostUsd: this.progress.sprints[sprint]?.costUsd ?? 0,
71
+ totalCostUsd: this.progress.costUsd,
72
+ budgetUsd: this.options.maxTotalBudgetUsd,
73
+ },
74
+ });
75
+ this.fileProtocol.writeProgress(this.progress);
76
+ return result.response;
77
+ }
78
+ isBudgetExceeded() {
79
+ return this.progress.costUsd >= this.options.maxTotalBudgetUsd;
80
+ }
81
+ parseTotalSprints(_plannerResponse) {
82
+ // Read sprints.md to count how many sprints were planned
83
+ const sprints = this.fileProtocol.readFile("sprints.md");
84
+ if (!sprints)
85
+ return 1;
86
+ // Count sprint headers (## Sprint N or ### Sprint N)
87
+ const matches = sprints.match(/^#{2,3}\s+Sprint\s+\d+/gim);
88
+ return matches ? matches.length : 1;
89
+ }
90
+ async run(spec) {
91
+ this.fileProtocol.ensureDir();
92
+ this.fileProtocol.ensureGitignore();
93
+ this.progress = this.initProgress(spec);
94
+ this.aborted = false;
95
+ try {
96
+ // Phase 1: Plan — write spec to file, have planner create full spec
97
+ this.updatePhase("plan");
98
+ this.fileProtocol.writeFile("spec.md", spec);
99
+ await this.runAgentPhase("planner", `Read .harness/spec.md. Create a comprehensive product specification. Write the full specification back to .harness/spec.md — expand and refine the user's original request into a complete spec.`, 0);
100
+ if (this.aborted || this.isBudgetExceeded())
101
+ return this.finalize();
102
+ // Phase 2: Decompose — break spec into sprints
103
+ this.updatePhase("decompose");
104
+ await this.runAgentPhase("planner", `Read .harness/spec.md. Decompose this specification into ordered sprints. Each sprint must be independently testable. Write the sprint plan to .harness/sprints.md.`, 0);
105
+ if (this.aborted || this.isBudgetExceeded())
106
+ return this.finalize();
107
+ const totalSprints = this.parseTotalSprints("");
108
+ this.progress.totalSprints = totalSprints;
109
+ // Execute sprints
110
+ for (let s = 1; s <= totalSprints; s++) {
111
+ if (this.aborted || this.isBudgetExceeded())
112
+ break;
113
+ await this.executeSprint(s);
114
+ }
115
+ }
116
+ catch (error) {
117
+ this.progress.status = "failed";
118
+ this.fileProtocol.writeProgress(this.progress);
119
+ throw error;
120
+ }
121
+ return this.finalize();
122
+ }
123
+ async executeSprint(sprintNum) {
124
+ this.progress.sprints[sprintNum] = {
125
+ status: "in_progress",
126
+ attempts: 0,
127
+ costUsd: 0,
128
+ };
129
+ // Contract phase — have planner write a contract for this sprint
130
+ this.updatePhase("contract", sprintNum, 0);
131
+ await this.runAgentPhase("planner", `Read .harness/sprints.md. Write a sprint contract for Sprint ${sprintNum} to .harness/contract.md. Include specific, testable success criteria.`, sprintNum);
132
+ // Attempt loop
133
+ const maxAttempts = this.options.maxAttemptsPerSprint;
134
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
135
+ if (this.aborted || this.isBudgetExceeded())
136
+ break;
137
+ this.progress.sprints[sprintNum].attempts = attempt;
138
+ // Generate phase
139
+ this.updatePhase("generate", sprintNum, attempt);
140
+ await this.runAgentPhase("generator", `Implement the sprint contract. Read .harness/contract.md for requirements.${attempt > 1 ? " Read .harness/evaluation.md for feedback from your previous attempt." : ""}`, sprintNum);
141
+ if (this.aborted || this.isBudgetExceeded())
142
+ break;
143
+ // Evaluate phase
144
+ this.updatePhase("evaluate", sprintNum, attempt);
145
+ await this.runAgentPhase("evaluator", `Evaluate the implementation against the sprint contract. Read .harness/contract.md for requirements. Write your evaluation to .harness/evaluation.md.`, sprintNum);
146
+ // Parse evaluation
147
+ const evalResult = this.fileProtocol.parseEvaluation();
148
+ this.emitEvent({
149
+ type: "evaluation",
150
+ data: { sprint: sprintNum, attempt, result: evalResult },
151
+ });
152
+ if (evalResult.passed) {
153
+ this.progress.sprints[sprintNum].status = "passed";
154
+ this.emitEvent({
155
+ type: "sprint:complete",
156
+ data: {
157
+ sprint: sprintNum,
158
+ status: "passed",
159
+ attempts: attempt,
160
+ costUsd: this.progress.sprints[sprintNum].costUsd,
161
+ },
162
+ });
163
+ // Handoff phase — write context for next sprint
164
+ if (sprintNum < this.progress.totalSprints) {
165
+ this.updatePhase("handoff", sprintNum);
166
+ await this.runAgentPhase("planner", `Sprint ${sprintNum} passed. Write a handoff document to .harness/handoff.md summarizing what was done, what changed, and key context the next sprint needs.`, sprintNum);
167
+ }
168
+ return; // sprint passed, move to next
169
+ }
170
+ // If last attempt and still failing
171
+ if (attempt === maxAttempts) {
172
+ this.progress.sprints[sprintNum].status = "failed";
173
+ this.emitEvent({
174
+ type: "sprint:complete",
175
+ data: {
176
+ sprint: sprintNum,
177
+ status: "failed",
178
+ attempts: attempt,
179
+ costUsd: this.progress.sprints[sprintNum].costUsd,
180
+ },
181
+ });
182
+ }
183
+ }
184
+ }
185
+ finalize() {
186
+ if (this.aborted) {
187
+ this.progress.status = "stopped";
188
+ this.progress.stoppedAt = new Date().toISOString();
189
+ }
190
+ else {
191
+ // Check if all sprints passed
192
+ const allPassed = Object.values(this.progress.sprints).every((s) => s.status === "passed");
193
+ this.progress.status = allPassed ? "completed" : "failed";
194
+ }
195
+ this.fileProtocol.writeProgress(this.progress);
196
+ const startMs = new Date(this.progress.startedAt).getTime();
197
+ const endMs = Date.now();
198
+ this.emitEvent({
199
+ type: "run:complete",
200
+ data: {
201
+ status: this.progress.status,
202
+ totalSprints: this.progress.totalSprints,
203
+ totalCostUsd: this.progress.costUsd,
204
+ durationMs: endMs - startMs,
205
+ },
206
+ });
207
+ }
208
+ async resume() {
209
+ const saved = this.fileProtocol.readProgress();
210
+ if (!saved) {
211
+ throw new Error("No progress file found. Nothing to resume.");
212
+ }
213
+ this.progress = { ...saved, status: "running" };
214
+ this.aborted = false;
215
+ delete this.progress.stoppedAt;
216
+ // Resume from the current sprint
217
+ const startSprint = this.progress.currentSprint || 1;
218
+ for (let s = startSprint; s <= this.progress.totalSprints; s++) {
219
+ if (this.aborted || this.isBudgetExceeded())
220
+ break;
221
+ const sprintProgress = this.progress.sprints[s];
222
+ if (sprintProgress?.status === "passed")
223
+ continue; // skip completed sprints
224
+ await this.executeSprint(s);
225
+ }
226
+ return this.finalize();
227
+ }
228
+ stop() {
229
+ this.aborted = true;
230
+ this.progress.status = "stopped";
231
+ this.progress.stoppedAt = new Date().toISOString();
232
+ this.fileProtocol.writeProgress(this.progress);
233
+ }
234
+ getProgress() {
235
+ return { ...this.progress };
236
+ }
237
+ }
238
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ export interface Stack {
2
+ language: string;
3
+ framework: string | null;
4
+ testRunner: string | null;
5
+ testCommand: string;
6
+ lintCommand: string | null;
7
+ buildCommand: string | null;
8
+ devServer: string | null;
9
+ }
10
+ export interface Workspace {
11
+ path: string;
12
+ stack: Stack;
13
+ claudeMd: string | null;
14
+ }
15
+ export interface ProjectContext {
16
+ repoType: "single" | "monorepo";
17
+ workspaces: Workspace[];
18
+ rootClaudeMd: string | null;
19
+ config: HarnessConfig | null;
20
+ criteria: string | null;
21
+ scope: string[] | null;
22
+ root: string;
23
+ }
24
+ export interface AgentConfig {
25
+ model?: string;
26
+ maxTurns?: number;
27
+ systemPromptAppend?: string;
28
+ }
29
+ export interface WorkspaceConfig {
30
+ path: string;
31
+ language?: string;
32
+ framework?: string;
33
+ testCommand?: string;
34
+ lintCommand?: string;
35
+ buildCommand?: string;
36
+ devServer?: string;
37
+ }
38
+ export interface HarnessConfig {
39
+ agents?: {
40
+ planner?: AgentConfig;
41
+ generator?: AgentConfig;
42
+ evaluator?: AgentConfig;
43
+ };
44
+ workspaces?: Record<string, WorkspaceConfig>;
45
+ maxAttemptsPerSprint?: number;
46
+ maxBudgetPerSprintUsd?: number;
47
+ maxTotalBudgetUsd?: number;
48
+ }
49
+ export type SprintStatus = "pending" | "in_progress" | "passed" | "failed";
50
+ export type RunStatus = "running" | "stopped" | "completed" | "failed";
51
+ export type Phase = "plan" | "decompose" | "contract" | "generate" | "evaluate" | "handoff";
52
+ export interface SprintProgress {
53
+ status: SprintStatus;
54
+ attempts: number;
55
+ costUsd: number;
56
+ }
57
+ export interface Progress {
58
+ status: RunStatus;
59
+ runSpec: string;
60
+ currentSprint: number;
61
+ totalSprints: number;
62
+ currentAttempt: number;
63
+ currentPhase: Phase;
64
+ startedAt: string;
65
+ stoppedAt?: string;
66
+ costUsd: number;
67
+ maxBudgetUsd: number;
68
+ sprints: Record<number, SprintProgress>;
69
+ }
70
+ export interface EvalResult {
71
+ passed: boolean;
72
+ critique: string;
73
+ failedCriteria: string[];
74
+ passedCriteria: string[];
75
+ }
76
+ export type AgentRole = "planner" | "generator" | "evaluator";
77
+ export interface AgentDefinition {
78
+ role: AgentRole;
79
+ systemPrompt: string;
80
+ tools: string[];
81
+ model: string;
82
+ maxTurns: number;
83
+ }
84
+ export interface PhaseStartEvent {
85
+ sprint: number;
86
+ phase: Phase;
87
+ attempt: number;
88
+ }
89
+ export interface AgentActivityEvent {
90
+ sprint: number;
91
+ role: AgentRole;
92
+ tool: string;
93
+ summary: string;
94
+ timestamp: number;
95
+ }
96
+ export interface EvaluationEvent {
97
+ sprint: number;
98
+ attempt: number;
99
+ result: EvalResult;
100
+ }
101
+ export interface CostUpdateEvent {
102
+ sprintCostUsd: number;
103
+ totalCostUsd: number;
104
+ budgetUsd: number;
105
+ }
106
+ export interface SprintCompleteEvent {
107
+ sprint: number;
108
+ status: SprintStatus;
109
+ attempts: number;
110
+ costUsd: number;
111
+ }
112
+ export interface RunCompleteEvent {
113
+ status: RunStatus;
114
+ totalSprints: number;
115
+ totalCostUsd: number;
116
+ durationMs: number;
117
+ }
118
+ export type HarnessEvent = {
119
+ type: "phase:start";
120
+ data: PhaseStartEvent;
121
+ } | {
122
+ type: "agent:activity";
123
+ data: AgentActivityEvent;
124
+ } | {
125
+ type: "evaluation";
126
+ data: EvaluationEvent;
127
+ } | {
128
+ type: "cost:update";
129
+ data: CostUpdateEvent;
130
+ } | {
131
+ type: "sprint:complete";
132
+ data: SprintCompleteEvent;
133
+ } | {
134
+ type: "run:complete";
135
+ data: RunCompleteEvent;
136
+ };
@@ -0,0 +1,3 @@
1
+ // --- Project Discovery Types ---
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,kCAAkC"}
@@ -0,0 +1,15 @@
1
+ import type { HarnessEvent } from "../core/types.js";
2
+ export declare class DashboardServer {
3
+ private server;
4
+ private broadcaster;
5
+ private port;
6
+ private running;
7
+ constructor(port?: number);
8
+ private handleRequest;
9
+ start(): Promise<void>;
10
+ stop(): Promise<void>;
11
+ isRunning(): boolean;
12
+ getUrl(): string;
13
+ getPort(): number;
14
+ broadcast(event: HarnessEvent): void;
15
+ }
@@ -0,0 +1,61 @@
1
+ import { createServer } from "node:http";
2
+ import { readFileSync } from "node:fs";
3
+ import { join, dirname } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { WebSocketBroadcaster } from "./socket.js";
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ export class DashboardServer {
8
+ server;
9
+ broadcaster;
10
+ port;
11
+ running = false;
12
+ constructor(port = 3117) {
13
+ this.port = port;
14
+ this.server = createServer(this.handleRequest.bind(this));
15
+ this.broadcaster = new WebSocketBroadcaster(this.server);
16
+ }
17
+ handleRequest(req, res) {
18
+ // Serve the dashboard HTML for any request
19
+ try {
20
+ const htmlPath = join(__dirname, "static", "index.html");
21
+ const html = readFileSync(htmlPath, "utf-8");
22
+ res.writeHead(200, { "Content-Type": "text/html" });
23
+ res.end(html);
24
+ }
25
+ catch {
26
+ res.writeHead(500, { "Content-Type": "text/plain" });
27
+ res.end("Dashboard file not found");
28
+ }
29
+ }
30
+ async start() {
31
+ return new Promise((resolve, reject) => {
32
+ this.server.listen(this.port, () => {
33
+ this.running = true;
34
+ resolve();
35
+ });
36
+ this.server.on("error", reject);
37
+ });
38
+ }
39
+ async stop() {
40
+ return new Promise((resolve) => {
41
+ this.broadcaster.close();
42
+ this.server.close(() => {
43
+ this.running = false;
44
+ resolve();
45
+ });
46
+ });
47
+ }
48
+ isRunning() {
49
+ return this.running;
50
+ }
51
+ getUrl() {
52
+ return `http://localhost:${this.port}`;
53
+ }
54
+ getPort() {
55
+ return this.port;
56
+ }
57
+ broadcast(event) {
58
+ this.broadcaster.broadcast(event);
59
+ }
60
+ }
61
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,OAAO,eAAe;IAClB,MAAM,CAAS;IACf,WAAW,CAAuB;IAClC,IAAI,CAAS;IACb,OAAO,GAAG,KAAK,CAAC;IAExB,YAAY,IAAI,GAAG,IAAI;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,WAAW,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,CAAC;IAEO,aAAa,CAAC,GAAoB,EAAE,GAAmB;QAC7D,2CAA2C;QAC3C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;YACzD,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC7C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;gBACjC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;gBACrB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;gBACrB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,MAAM;QACJ,OAAO,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAC;IACzC,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,SAAS,CAAC,KAAmB;QAC3B,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ import type { Server } from "node:http";
2
+ import type { HarnessEvent } from "../core/types.js";
3
+ export declare class WebSocketBroadcaster {
4
+ private wss;
5
+ constructor(server: Server);
6
+ broadcast(event: HarnessEvent): void;
7
+ close(): void;
8
+ }
@@ -0,0 +1,22 @@
1
+ import { WebSocketServer, WebSocket } from "ws";
2
+ export class WebSocketBroadcaster {
3
+ wss;
4
+ constructor(server) {
5
+ this.wss = new WebSocketServer({ server });
6
+ }
7
+ broadcast(event) {
8
+ const data = JSON.stringify(event);
9
+ for (const client of this.wss.clients) {
10
+ if (client.readyState === WebSocket.OPEN) {
11
+ client.send(data);
12
+ }
13
+ }
14
+ }
15
+ close() {
16
+ for (const client of this.wss.clients) {
17
+ client.close();
18
+ }
19
+ this.wss.close();
20
+ }
21
+ }
22
+ //# sourceMappingURL=socket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/dashboard/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAIhD,MAAM,OAAO,oBAAoB;IACvB,GAAG,CAAkB;IAE7B,YAAY,MAAc;QACxB,IAAI,CAAC,GAAG,GAAG,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,SAAS,CAAC,KAAmB;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBACzC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YACtC,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export declare const DEFAULT_CRITERIA = "## Default Evaluation Criteria\n\n### Correctness\n- All features specified in the contract are implemented and functional\n- No placeholder, stubbed, or mocked implementations in production code\n- Code runs without runtime errors\n\n### Testing\n- New features have corresponding tests\n- All tests pass when the test suite is run\n- Tests cover the primary success path and key edge cases\n\n### Code Quality\n- Code follows project conventions (from CLAUDE.md if present)\n- No leftover TODO or FIXME comments\n- No debug logging or commented-out code left in place\n- Imports are clean \u2014 no unused imports\n\n### Integration\n- New code integrates with existing codebase without breaking existing functionality\n- Existing tests still pass after changes\n";
@@ -0,0 +1,23 @@
1
+ export const DEFAULT_CRITERIA = `## Default Evaluation Criteria
2
+
3
+ ### Correctness
4
+ - All features specified in the contract are implemented and functional
5
+ - No placeholder, stubbed, or mocked implementations in production code
6
+ - Code runs without runtime errors
7
+
8
+ ### Testing
9
+ - New features have corresponding tests
10
+ - All tests pass when the test suite is run
11
+ - Tests cover the primary success path and key edge cases
12
+
13
+ ### Code Quality
14
+ - Code follows project conventions (from CLAUDE.md if present)
15
+ - No leftover TODO or FIXME comments
16
+ - No debug logging or commented-out code left in place
17
+ - Imports are clean — no unused imports
18
+
19
+ ### Integration
20
+ - New code integrates with existing codebase without breaking existing functionality
21
+ - Existing tests still pass after changes
22
+ `;
23
+ //# sourceMappingURL=criteria.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"criteria.js","sourceRoot":"","sources":["../../src/defaults/criteria.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqB/B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ProjectContext, AgentRole } from "../core/types.js";
2
+ /**
3
+ * Format a ProjectContext into a readable text block for inclusion in system prompts.
4
+ */
5
+ export declare function formatProjectContext(ctx: ProjectContext): string;
6
+ /**
7
+ * Build a full system prompt for an agent role.
8
+ *
9
+ * Assembles:
10
+ * 1. Base prompt for the role
11
+ * 2. PROJECT CONTEXT section (formatted project context)
12
+ * 3. EVALUATION CRITERIA section (evaluator only — default + custom criteria)
13
+ * 4. ADDITIONAL INSTRUCTIONS section (appendPrompt if provided)
14
+ */
15
+ export declare function buildSystemPrompt(role: AgentRole, ctx: ProjectContext, appendPrompt?: string): string;