infinity-harness 2.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/CHANGELOG.md +114 -0
- package/LICENSE +21 -0
- package/README.md +266 -0
- package/extensions/infinity-harness/index.ts +870 -0
- package/harness/docs/ARCHITECTURE.md +159 -0
- package/harness/docs/CONSTRAINTS.md +19 -0
- package/harness/docs/DECISIONS.md +107 -0
- package/harness/docs/DOMAIN.md +13 -0
- package/harness/docs/agents/evaluator.md +14 -0
- package/harness/docs/agents/generator.md +13 -0
- package/harness/docs/agents/planner.md +13 -0
- package/harness/docs/agents/simplifier.md +13 -0
- package/harness/docs/api-patterns.md +23 -0
- package/harness/docs/phases/build.md +47 -0
- package/harness/docs/phases/define.md +58 -0
- package/harness/docs/phases/plan.md +50 -0
- package/harness/docs/phases/review.md +47 -0
- package/harness/docs/phases/ship.md +43 -0
- package/harness/docs/phases/simplify.md +45 -0
- package/harness/docs/phases/verify.md +46 -0
- package/harness/model-router.json +28 -0
- package/harness/skills/README.md +60 -0
- package/harness/skills/auth-security.md +56 -0
- package/harness/skills/building-mcp-servers.md +70 -0
- package/harness/skills/building-tools.md +60 -0
- package/harness/skills/capability-acquisition.md +72 -0
- package/harness/skills/cli-design.md +55 -0
- package/harness/skills/code-review.md +57 -0
- package/harness/skills/codebase-design.md +70 -0
- package/harness/skills/concurrency-async.md +61 -0
- package/harness/skills/config-and-secrets.md +52 -0
- package/harness/skills/context-hygiene.md +51 -0
- package/harness/skills/databases.md +63 -0
- package/harness/skills/diagnosing-bugs.md +84 -0
- package/harness/skills/domain-modeling.md +65 -0
- package/harness/skills/error-handling-logging.md +56 -0
- package/harness/skills/frontend-ui.md +56 -0
- package/harness/skills/grilling.md +48 -0
- package/harness/skills/http-apis.md +60 -0
- package/harness/skills/performance.md +53 -0
- package/harness/skills/pi-todo-adapted.md +41 -0
- package/harness/skills/planning-tasks.md +86 -0
- package/harness/skills/prototype.md +39 -0
- package/harness/skills/research.md +32 -0
- package/harness/skills/resolving-merge-conflicts.md +30 -0
- package/harness/skills/scope-discipline.md +49 -0
- package/harness/skills/self-review.md +45 -0
- package/harness/skills/stuck-protocol.md +51 -0
- package/harness/skills/tdd.md +80 -0
- package/harness/skills/testing-infra.md +57 -0
- package/harness/skills/writing-skills.md +60 -0
- package/package.json +61 -0
- package/src/core/brief.ts +242 -0
- package/src/core/config.ts +265 -0
- package/src/core/exec.ts +130 -0
- package/src/core/featureList.ts +286 -0
- package/src/core/fsx.ts +119 -0
- package/src/core/gates.ts +444 -0
- package/src/core/lock.ts +192 -0
- package/src/core/paths.ts +95 -0
- package/src/core/phases.ts +143 -0
- package/src/core/settings.ts +445 -0
- package/src/core/types.ts +245 -0
- package/src/goalLoop.ts +628 -0
- package/src/goalSpec.ts +679 -0
- package/src/goalState.ts +338 -0
- package/src/loop.ts +355 -0
- package/src/modelRouter.ts +184 -0
- package/src/remote.ts +244 -0
- package/src/replan.ts +300 -0
- package/src/review.ts +53 -0
- package/src/rework.ts +274 -0
- package/src/taskList.ts +355 -0
- package/src/ui/config.ts +286 -0
- package/src/ui/dashboard.ts +1066 -0
- package/src/ui/theme.ts +317 -0
- package/src/ui/widget.ts +370 -0
- package/src/unstuck.ts +214 -0
- package/src/worker.ts +351 -0
- package/types/proper-lockfile.d.ts +19 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* infinity-harness — shared domain types.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for every shape that crosses a module boundary.
|
|
5
|
+
* Nothing here does I/O; it is safe to import from anywhere.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ── Phases ──────────────────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
export const PHASE_ORDER = [
|
|
11
|
+
"init",
|
|
12
|
+
"define",
|
|
13
|
+
"plan",
|
|
14
|
+
"build",
|
|
15
|
+
"verify",
|
|
16
|
+
"simplify",
|
|
17
|
+
"review",
|
|
18
|
+
"ship",
|
|
19
|
+
] as const;
|
|
20
|
+
|
|
21
|
+
export type Phase = (typeof PHASE_ORDER)[number];
|
|
22
|
+
|
|
23
|
+
/** Phases enabled by default — SIMPLIFY is opt-in. */
|
|
24
|
+
export const DEFAULT_ENABLED_PHASES: Phase[] = [
|
|
25
|
+
"define",
|
|
26
|
+
"plan",
|
|
27
|
+
"build",
|
|
28
|
+
"verify",
|
|
29
|
+
"review",
|
|
30
|
+
"ship",
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
export type Role = "planner" | "generator" | "evaluator" | "simplifier";
|
|
34
|
+
|
|
35
|
+
/** Which role owns each phase. Drives the "put on this hat" brief line. */
|
|
36
|
+
export const PHASE_ROLE: Record<Phase, Role> = {
|
|
37
|
+
init: "planner",
|
|
38
|
+
define: "planner",
|
|
39
|
+
plan: "planner",
|
|
40
|
+
build: "generator",
|
|
41
|
+
verify: "evaluator",
|
|
42
|
+
simplify: "simplifier",
|
|
43
|
+
review: "evaluator",
|
|
44
|
+
ship: "evaluator",
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// ── Task / feature status ───────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
export const TASK_STATUSES = [
|
|
50
|
+
"pending",
|
|
51
|
+
"in_progress",
|
|
52
|
+
"complete",
|
|
53
|
+
"blocked",
|
|
54
|
+
"rework",
|
|
55
|
+
] as const;
|
|
56
|
+
|
|
57
|
+
export type TaskStatus = (typeof TASK_STATUSES)[number];
|
|
58
|
+
|
|
59
|
+
export const SUBTASK_STATUSES = ["pending", "in_progress", "complete"] as const;
|
|
60
|
+
export type SubtaskStatus = (typeof SUBTASK_STATUSES)[number];
|
|
61
|
+
|
|
62
|
+
export type Difficulty = "easy" | "moderate" | "difficult";
|
|
63
|
+
|
|
64
|
+
// ── Feature list (the SSOT on disk) ─────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
export type Subtask = {
|
|
67
|
+
id: string;
|
|
68
|
+
title: string;
|
|
69
|
+
status: SubtaskStatus;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type Task = {
|
|
73
|
+
id: string;
|
|
74
|
+
/** Stable key; defaults to `id`, may be `featureId/taskId`. */
|
|
75
|
+
key?: string;
|
|
76
|
+
description: string;
|
|
77
|
+
status: TaskStatus;
|
|
78
|
+
dependsOn?: string[];
|
|
79
|
+
subtasks?: Subtask[];
|
|
80
|
+
difficulty?: Difficulty;
|
|
81
|
+
modelHint?: string;
|
|
82
|
+
criteria?: string[];
|
|
83
|
+
/** Free-form extras are preserved verbatim on round-trip. */
|
|
84
|
+
[k: string]: unknown;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export type Feature = {
|
|
88
|
+
id: string;
|
|
89
|
+
name: string;
|
|
90
|
+
description?: string;
|
|
91
|
+
passes?: boolean;
|
|
92
|
+
sprintId?: string;
|
|
93
|
+
goalId?: string;
|
|
94
|
+
criteria?: string[];
|
|
95
|
+
tasks: Task[];
|
|
96
|
+
[k: string]: unknown;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type Sprint = {
|
|
100
|
+
id: string;
|
|
101
|
+
name: string;
|
|
102
|
+
goalId?: string;
|
|
103
|
+
[k: string]: unknown;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export type Goal = {
|
|
107
|
+
id: string;
|
|
108
|
+
title: string;
|
|
109
|
+
description?: string;
|
|
110
|
+
[k: string]: unknown;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export type FeatureList = {
|
|
114
|
+
version: string;
|
|
115
|
+
/** Optimistic-concurrency counter. Bumped on every mutating write. */
|
|
116
|
+
baseRevision: number;
|
|
117
|
+
goals?: Goal[];
|
|
118
|
+
sprints?: Sprint[];
|
|
119
|
+
features: Feature[];
|
|
120
|
+
[k: string]: unknown;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// ── Config (harness/config.json) ────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
export type GateHistoryEntry = {
|
|
126
|
+
phase: string;
|
|
127
|
+
result: "pass" | "fail";
|
|
128
|
+
timestamp: string;
|
|
129
|
+
feature?: string;
|
|
130
|
+
task?: string;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export type RetryBucket = {
|
|
134
|
+
enabled: boolean;
|
|
135
|
+
maxRetries: number | null;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export type HarnessConfig = {
|
|
139
|
+
version: string;
|
|
140
|
+
stack: string | null;
|
|
141
|
+
mode: "copilot" | "autopilot";
|
|
142
|
+
currentPhase: Phase | null;
|
|
143
|
+
currentRole: Role | null;
|
|
144
|
+
currentFeature: string | null;
|
|
145
|
+
currentTask: string | null;
|
|
146
|
+
paused: boolean;
|
|
147
|
+
features: { remaining: number; passing: number; total: number };
|
|
148
|
+
gates: {
|
|
149
|
+
enabled: boolean;
|
|
150
|
+
checks: string[];
|
|
151
|
+
coverage: { enabled: boolean; threshold: number };
|
|
152
|
+
cleanState: { enabled: boolean; stalePatterns: string[]; startupCmd: string | null };
|
|
153
|
+
antiPlaceholder: { enabled: boolean; patterns: string[] };
|
|
154
|
+
};
|
|
155
|
+
commands: {
|
|
156
|
+
lint: string | null;
|
|
157
|
+
test: string | null;
|
|
158
|
+
coverage: string | null;
|
|
159
|
+
build: string | null;
|
|
160
|
+
};
|
|
161
|
+
git: {
|
|
162
|
+
autoCommit: boolean;
|
|
163
|
+
autoTag: boolean;
|
|
164
|
+
branch: string | null;
|
|
165
|
+
clean: boolean;
|
|
166
|
+
hasUpstream: boolean;
|
|
167
|
+
lastCommitMessage: string | null;
|
|
168
|
+
};
|
|
169
|
+
phases: { enabled: Phase[] };
|
|
170
|
+
roles: { strict: boolean };
|
|
171
|
+
/** Budgets that bound an unattended continuous run. See src/loop.ts. */
|
|
172
|
+
loop: {
|
|
173
|
+
maxIterations: number;
|
|
174
|
+
maxWallClockMs: number;
|
|
175
|
+
noProgressLimit: number;
|
|
176
|
+
};
|
|
177
|
+
retry: {
|
|
178
|
+
tasks: RetryBucket;
|
|
179
|
+
features: RetryBucket;
|
|
180
|
+
phases: RetryBucket;
|
|
181
|
+
};
|
|
182
|
+
maxRetries: number;
|
|
183
|
+
retryCount: number;
|
|
184
|
+
taskRetryCount: number;
|
|
185
|
+
featureRetryCount: number;
|
|
186
|
+
phaseRetryCount: number;
|
|
187
|
+
pipelineIteration: number;
|
|
188
|
+
gateHistory: GateHistoryEntry[];
|
|
189
|
+
[k: string]: unknown;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// ── Gates ───────────────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
export type CheckResult = {
|
|
195
|
+
name: string;
|
|
196
|
+
pass: boolean;
|
|
197
|
+
detail: string;
|
|
198
|
+
/** Advisory checks never fail the gate; they are reported for context. */
|
|
199
|
+
advisory?: boolean;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
export type GateResult = {
|
|
203
|
+
phase: string;
|
|
204
|
+
checks: CheckResult[];
|
|
205
|
+
overall: boolean;
|
|
206
|
+
failures: string[];
|
|
207
|
+
feature?: string;
|
|
208
|
+
task?: string;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// ── Brief ───────────────────────────────────────────────────────────────────
|
|
212
|
+
|
|
213
|
+
export type Brief = {
|
|
214
|
+
phase: Phase | null;
|
|
215
|
+
role: Role | null;
|
|
216
|
+
paused: boolean;
|
|
217
|
+
complete: boolean;
|
|
218
|
+
goal: string | null;
|
|
219
|
+
feature: { id: string; name: string } | null;
|
|
220
|
+
task: { id: string; key: string; description: string; status: TaskStatus } | null;
|
|
221
|
+
criteria: string[];
|
|
222
|
+
validateCommand: string;
|
|
223
|
+
gate: GateResult | null;
|
|
224
|
+
progress: { tasksDone: number; tasksTotal: number; featuresDone: number; featuresTotal: number };
|
|
225
|
+
retries: { task: number; feature: number; phase: number; max: number };
|
|
226
|
+
notes: string[];
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// ── Errors ──────────────────────────────────────────────────────────────────
|
|
230
|
+
|
|
231
|
+
export class ValidationError extends Error {
|
|
232
|
+
override readonly name = "ValidationError";
|
|
233
|
+
constructor(message: string) {
|
|
234
|
+
super(message);
|
|
235
|
+
Object.setPrototypeOf(this, ValidationError.prototype);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export class HarnessError extends Error {
|
|
240
|
+
override readonly name = "HarnessError";
|
|
241
|
+
constructor(message: string) {
|
|
242
|
+
super(message);
|
|
243
|
+
Object.setPrototypeOf(this, HarnessError.prototype);
|
|
244
|
+
}
|
|
245
|
+
}
|