infinity-harness 2.8.9 → 2.8.11
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 +18 -0
- package/dist/extensions/infinity-harness/index.js +3614 -0
- package/dist/extensions/infinity-harness/index.js.map +1 -0
- package/dist/src/approval.js +154 -0
- package/dist/src/approval.js.map +1 -0
- package/dist/src/core/brief.js +309 -0
- package/dist/src/core/brief.js.map +1 -0
- package/dist/src/core/config.js +539 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/exec.js +106 -0
- package/dist/src/core/exec.js.map +1 -0
- package/dist/src/core/featureList.js +365 -0
- package/dist/src/core/featureList.js.map +1 -0
- package/dist/src/core/fsx.js +123 -0
- package/dist/src/core/fsx.js.map +1 -0
- package/dist/src/core/gates.js +490 -0
- package/dist/src/core/gates.js.map +1 -0
- package/dist/src/core/init.js +480 -0
- package/dist/src/core/init.js.map +1 -0
- package/dist/src/core/lock.js +183 -0
- package/dist/src/core/lock.js.map +1 -0
- package/dist/src/core/modelRouter.js +185 -0
- package/dist/src/core/modelRouter.js.map +1 -0
- package/dist/src/core/paths.js +129 -0
- package/dist/src/core/paths.js.map +1 -0
- package/dist/src/core/phases.js +254 -0
- package/dist/src/core/phases.js.map +1 -0
- package/dist/src/core/plan.js +15 -0
- package/dist/src/core/plan.js.map +1 -0
- package/dist/src/core/runState.js +126 -0
- package/dist/src/core/runState.js.map +1 -0
- package/dist/src/core/settings.js +877 -0
- package/dist/src/core/settings.js.map +1 -0
- package/dist/src/core/skills.js +319 -0
- package/dist/src/core/skills.js.map +1 -0
- package/dist/src/core/skillsAudit.js +194 -0
- package/dist/src/core/skillsAudit.js.map +1 -0
- package/dist/src/core/types.js +77 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/daemon/budget.js +85 -0
- package/dist/src/daemon/budget.js.map +1 -0
- package/dist/src/daemon/guard.js +122 -0
- package/dist/src/daemon/guard.js.map +1 -0
- package/dist/src/daemon/index.js +461 -0
- package/dist/src/daemon/index.js.map +1 -0
- package/dist/src/daemon/isolation.js +84 -0
- package/dist/src/daemon/isolation.js.map +1 -0
- package/dist/src/daemon/preflight.js +131 -0
- package/dist/src/daemon/preflight.js.map +1 -0
- package/dist/src/daemon/server.js +174 -0
- package/dist/src/daemon/server.js.map +1 -0
- package/dist/src/daemon/supervisorState.js +42 -0
- package/dist/src/daemon/supervisorState.js.map +1 -0
- package/dist/src/daemon/worker.js +239 -0
- package/dist/src/daemon/worker.js.map +1 -0
- package/dist/src/daemon/worktree.js +102 -0
- package/dist/src/daemon/worktree.js.map +1 -0
- package/dist/src/escalate.js +312 -0
- package/dist/src/escalate.js.map +1 -0
- package/dist/src/exec/piWorker.js +630 -0
- package/dist/src/exec/piWorker.js.map +1 -0
- package/dist/src/goal.js +317 -0
- package/dist/src/goal.js.map +1 -0
- package/dist/src/goalLoop.js +374 -0
- package/dist/src/goalLoop.js.map +1 -0
- package/dist/src/goalSpec.js +397 -0
- package/dist/src/goalSpec.js.map +1 -0
- package/dist/src/goalState.js +255 -0
- package/dist/src/goalState.js.map +1 -0
- package/dist/src/handoff.js +205 -0
- package/dist/src/handoff.js.map +1 -0
- package/dist/src/intake.js +203 -0
- package/dist/src/intake.js.map +1 -0
- package/dist/src/loop.js +592 -0
- package/dist/src/loop.js.map +1 -0
- package/dist/src/modelRouter.js +216 -0
- package/dist/src/modelRouter.js.map +1 -0
- package/dist/src/remote.js +246 -0
- package/dist/src/remote.js.map +1 -0
- package/dist/src/replan.js +262 -0
- package/dist/src/replan.js.map +1 -0
- package/dist/src/review.js +54 -0
- package/dist/src/review.js.map +1 -0
- package/dist/src/rework.js +241 -0
- package/dist/src/rework.js.map +1 -0
- package/dist/src/runState.js +4 -0
- package/dist/src/runState.js.map +1 -0
- package/dist/src/scheduler.js +270 -0
- package/dist/src/scheduler.js.map +1 -0
- package/dist/src/supervisor.js +787 -0
- package/dist/src/supervisor.js.map +1 -0
- package/dist/src/taskList.js +430 -0
- package/dist/src/taskList.js.map +1 -0
- package/dist/src/ui/config.js +268 -0
- package/dist/src/ui/config.js.map +1 -0
- package/dist/src/ui/dashboard.js +1288 -0
- package/dist/src/ui/dashboard.js.map +1 -0
- package/dist/src/ui/display.js +229 -0
- package/dist/src/ui/display.js.map +1 -0
- package/dist/src/ui/planTree.js +219 -0
- package/dist/src/ui/planTree.js.map +1 -0
- package/dist/src/ui/theme.js +298 -0
- package/dist/src/ui/theme.js.map +1 -0
- package/dist/src/ui/viewState.js +65 -0
- package/dist/src/ui/viewState.js.map +1 -0
- package/dist/src/ui/widget.js +721 -0
- package/dist/src/ui/widget.js.map +1 -0
- package/dist/src/ui/wizard.js +540 -0
- package/dist/src/ui/wizard.js.map +1 -0
- package/dist/src/unstuck.js +210 -0
- package/dist/src/unstuck.js.map +1 -0
- package/dist/src/worker.js +267 -0
- package/dist/src/worker.js.map +1 -0
- package/dist/src/workflow.js +250 -0
- package/dist/src/workflow.js.map +1 -0
- package/dist/tests/approval.test.js +144 -0
- package/dist/tests/approval.test.js.map +1 -0
- package/dist/tests/brief.test.js +271 -0
- package/dist/tests/brief.test.js.map +1 -0
- package/dist/tests/config.test.js +320 -0
- package/dist/tests/config.test.js.map +1 -0
- package/dist/tests/dashboard.test.js +277 -0
- package/dist/tests/dashboard.test.js.map +1 -0
- package/dist/tests/display.test.js +229 -0
- package/dist/tests/display.test.js.map +1 -0
- package/dist/tests/escalate.test.js +272 -0
- package/dist/tests/escalate.test.js.map +1 -0
- package/dist/tests/featureList.test.js +429 -0
- package/dist/tests/featureList.test.js.map +1 -0
- package/dist/tests/gates.test.js +333 -0
- package/dist/tests/gates.test.js.map +1 -0
- package/dist/tests/goal.test.js +229 -0
- package/dist/tests/goal.test.js.map +1 -0
- package/dist/tests/goalLoop.test.js +170 -0
- package/dist/tests/goalLoop.test.js.map +1 -0
- package/dist/tests/goalSpec.test.js +146 -0
- package/dist/tests/goalSpec.test.js.map +1 -0
- package/dist/tests/goalState.test.js +202 -0
- package/dist/tests/goalState.test.js.map +1 -0
- package/dist/tests/handoff.test.js +127 -0
- package/dist/tests/handoff.test.js.map +1 -0
- package/dist/tests/init.test.js +264 -0
- package/dist/tests/init.test.js.map +1 -0
- package/dist/tests/intake.test.js +288 -0
- package/dist/tests/intake.test.js.map +1 -0
- package/dist/tests/loop.test.js +453 -0
- package/dist/tests/loop.test.js.map +1 -0
- package/dist/tests/modelRouter.test.js +131 -0
- package/dist/tests/modelRouter.test.js.map +1 -0
- package/dist/tests/phases.test.js +244 -0
- package/dist/tests/phases.test.js.map +1 -0
- package/dist/tests/planTree.test.js +190 -0
- package/dist/tests/planTree.test.js.map +1 -0
- package/dist/tests/remote.test.js +380 -0
- package/dist/tests/remote.test.js.map +1 -0
- package/dist/tests/replan.test.js +113 -0
- package/dist/tests/replan.test.js.map +1 -0
- package/dist/tests/review.test.js +77 -0
- package/dist/tests/review.test.js.map +1 -0
- package/dist/tests/rework.test.js +109 -0
- package/dist/tests/rework.test.js.map +1 -0
- package/dist/tests/routing-live.test.js +121 -0
- package/dist/tests/routing-live.test.js.map +1 -0
- package/dist/tests/runState.test.js +73 -0
- package/dist/tests/runState.test.js.map +1 -0
- package/dist/tests/settings.test.js +311 -0
- package/dist/tests/settings.test.js.map +1 -0
- package/dist/tests/skills.test.js +387 -0
- package/dist/tests/skills.test.js.map +1 -0
- package/dist/tests/supervisor.test.js +437 -0
- package/dist/tests/supervisor.test.js.map +1 -0
- package/dist/tests/surface.test.js +203 -0
- package/dist/tests/surface.test.js.map +1 -0
- package/dist/tests/taskList.test.js +376 -0
- package/dist/tests/taskList.test.js.map +1 -0
- package/dist/tests/theme.test.js +149 -0
- package/dist/tests/theme.test.js.map +1 -0
- package/dist/tests/unstuck.test.js +268 -0
- package/dist/tests/unstuck.test.js.map +1 -0
- package/dist/tests/widget.test.js +424 -0
- package/dist/tests/widget.test.js.map +1 -0
- package/dist/tests/worker.test.js +306 -0
- package/dist/tests/worker.test.js.map +1 -0
- package/dist/tests/workflow.test.js +187 -0
- package/dist/tests/workflow.test.js.map +1 -0
- package/extensions/infinity-harness/index.ts +39 -12
- package/package.json +5 -2
- package/src/core/modelRouter.ts +23 -1
- package/src/daemon/index.ts +3 -3
- package/src/daemon/worker.ts +28 -5
- package/src/ui/config.ts +25 -1
- package/src/ui/wizard.ts +10 -5
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { areGatesEnabled, checkTaskCriteria, getPhaseCheckNames, parseCoveragePercent, runChecks, } from "../src/core/gates.js";
|
|
6
|
+
import { defaultConfig, loadConfig } from "../src/core/config.js";
|
|
7
|
+
function mkTask(id, status, extra = {}) {
|
|
8
|
+
return { id, description: id.toUpperCase(), status, dependsOn: [], subtasks: [], ...extra };
|
|
9
|
+
}
|
|
10
|
+
function tmpProject(mutate = () => { }, list = null) {
|
|
11
|
+
const d = mkdtempSync(join(tmpdir(), "pi-gates-"));
|
|
12
|
+
mkdirSync(join(d, "harness", "features"), { recursive: true });
|
|
13
|
+
const c = defaultConfig();
|
|
14
|
+
mutate(c);
|
|
15
|
+
writeFileSync(join(d, "harness", "config.json"), JSON.stringify(c, null, 2), "utf-8");
|
|
16
|
+
if (list) {
|
|
17
|
+
writeFileSync(join(d, "harness", "features", "feature-list.json"), JSON.stringify(list, null, 2), "utf-8");
|
|
18
|
+
}
|
|
19
|
+
return d;
|
|
20
|
+
}
|
|
21
|
+
function onePlan(taskStatus, subtasks = []) {
|
|
22
|
+
return {
|
|
23
|
+
version: "2.0",
|
|
24
|
+
baseRevision: 1,
|
|
25
|
+
goals: [],
|
|
26
|
+
sprints: [],
|
|
27
|
+
features: [
|
|
28
|
+
{
|
|
29
|
+
id: "feature-001",
|
|
30
|
+
name: "F",
|
|
31
|
+
criteria: ["it works"],
|
|
32
|
+
tasks: [mkTask("task-1", taskStatus, { subtasks })],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function byName(checks, name) {
|
|
38
|
+
const c = checks.find((x) => x.name === name);
|
|
39
|
+
assert.ok(c, `expected a check named ${name}, got ${checks.map((x) => x.name).join(", ")}`);
|
|
40
|
+
return c;
|
|
41
|
+
}
|
|
42
|
+
// ── parseCoveragePercent ───────────────────────────────────────────────────
|
|
43
|
+
{
|
|
44
|
+
assert.equal(parseCoveragePercent(""), null, "nothing to parse");
|
|
45
|
+
assert.equal(parseCoveragePercent("tests passed, no numbers here"), null);
|
|
46
|
+
assert.equal(parseCoveragePercent("coverage: 87%"), 87);
|
|
47
|
+
assert.equal(parseCoveragePercent("coverage: 87.25%"), 87.25, "decimals survive");
|
|
48
|
+
assert.equal(parseCoveragePercent("coverage: 87 %"), 87, "a space before the sign is fine");
|
|
49
|
+
assert.equal(parseCoveragePercent("0%"), 0);
|
|
50
|
+
assert.equal(parseCoveragePercent("100%"), 100);
|
|
51
|
+
// Coverage tools print lines/branches/functions separately. Take the
|
|
52
|
+
// pessimistic figure — an optimistic maximum would open the gate on a report
|
|
53
|
+
// that says 40% of branches are untested.
|
|
54
|
+
assert.equal(parseCoveragePercent("All files | 92.1% stmts | 78.4% branch | 88% funcs | 92.1% lines"), 78.4, "the minimum wins");
|
|
55
|
+
assert.equal(parseCoveragePercent("first 10%\nsecond 90%"), 10, "across lines too");
|
|
56
|
+
// Figures that cannot be percentages are noise, not coverage.
|
|
57
|
+
assert.equal(parseCoveragePercent("speedup 150%"), null, "an out-of-range figure is not coverage");
|
|
58
|
+
assert.equal(parseCoveragePercent("speedup 150% but coverage 42%"), 42, "…and does not drag the minimum down");
|
|
59
|
+
assert.equal(parseCoveragePercent("999%"), null);
|
|
60
|
+
console.log("✓ parseCoveragePercent takes the minimum and ignores impossible figures");
|
|
61
|
+
}
|
|
62
|
+
// ── gates.enabled:false short-circuits ─────────────────────────────────────
|
|
63
|
+
{
|
|
64
|
+
const dir = tmpProject((c) => {
|
|
65
|
+
c.gates.enabled = false;
|
|
66
|
+
c.commands.test = "exit 1";
|
|
67
|
+
}, onePlan("pending"));
|
|
68
|
+
try {
|
|
69
|
+
assert.equal(areGatesEnabled(dir), false);
|
|
70
|
+
const gate = await runChecks(dir, "build");
|
|
71
|
+
assert.equal(gate.overall, true, "with gates off, nothing is enforced");
|
|
72
|
+
assert.deepEqual(gate.failures, []);
|
|
73
|
+
assert.equal(gate.checks.length, 1, "no real check is even attempted");
|
|
74
|
+
assert.equal(gate.checks[0].name, "gates-disabled");
|
|
75
|
+
assert.equal(gate.checks[0].advisory, true);
|
|
76
|
+
assert.match(gate.checks[0].detail, /disabled/);
|
|
77
|
+
assert.deepEqual(loadConfig(dir).config.gateHistory, [], "a short-circuited gate records nothing");
|
|
78
|
+
console.log("✓ gates.enabled:false short-circuits to pass");
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
rmSync(dir, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// ── no phase at all ────────────────────────────────────────────────────────
|
|
85
|
+
{
|
|
86
|
+
const dir = tmpProject(() => { }, onePlan("complete"));
|
|
87
|
+
try {
|
|
88
|
+
const gate = await runChecks(dir, null);
|
|
89
|
+
assert.equal(gate.phase, "none");
|
|
90
|
+
assert.equal(gate.overall, false, "there is nothing to validate against");
|
|
91
|
+
assert.deepEqual(gate.failures, ["no-phase"]);
|
|
92
|
+
assert.deepEqual(gate.checks, []);
|
|
93
|
+
assert.equal(areGatesEnabled(dir), true, "gates are on by default");
|
|
94
|
+
console.log("✓ runChecks with no phase");
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
rmSync(dir, { recursive: true, force: true });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// ── advisory checks never fail the gate ────────────────────────────────────
|
|
101
|
+
{
|
|
102
|
+
const dir = tmpProject(() => { }, onePlan("complete"));
|
|
103
|
+
try {
|
|
104
|
+
const gate = await runChecks(dir, "build", { record: false });
|
|
105
|
+
for (const name of ["lint", "tests", "coverage"]) {
|
|
106
|
+
const c = byName(gate.checks, name);
|
|
107
|
+
assert.equal(c.advisory, true, `${name} is advisory when it cannot run`);
|
|
108
|
+
assert.equal(c.pass, true, `${name} must not fail the gate just because it is unconfigured`);
|
|
109
|
+
assert.match(c.detail, /no .* command configured|coverage gate disabled/);
|
|
110
|
+
}
|
|
111
|
+
assert.equal(byName(gate.checks, "tasks-complete").pass, true);
|
|
112
|
+
assert.equal(byName(gate.checks, "anti-placeholder").pass, true);
|
|
113
|
+
assert.equal(gate.overall, true, "a gate made only of advisory skips and real passes opens");
|
|
114
|
+
assert.deepEqual(gate.failures, []);
|
|
115
|
+
// Advisory passes must not paper over a real failure.
|
|
116
|
+
writeFileSync(join(dir, "harness", "features", "feature-list.json"), JSON.stringify(onePlan("pending"), null, 2), "utf-8");
|
|
117
|
+
const failing = await runChecks(dir, "build", { record: false });
|
|
118
|
+
assert.equal(failing.overall, false);
|
|
119
|
+
assert.deepEqual(failing.failures, ["tasks-complete"]);
|
|
120
|
+
assert.equal(byName(failing.checks, "lint").pass, true, "the advisory checks are unchanged");
|
|
121
|
+
assert.match(byName(failing.checks, "tasks-complete").detail, /1 task\(s\) still open/);
|
|
122
|
+
console.log("✓ advisory checks do not fail the gate, and do not mask real failures");
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
rmSync(dir, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// ── a configured command is a real, non-advisory check ─────────────────────
|
|
129
|
+
{
|
|
130
|
+
const dir = tmpProject((c) => {
|
|
131
|
+
c.commands.test = "exit 3";
|
|
132
|
+
c.commands.lint = "echo all good";
|
|
133
|
+
}, onePlan("complete"));
|
|
134
|
+
try {
|
|
135
|
+
const gate = await runChecks(dir, "build", { record: false });
|
|
136
|
+
const tests = byName(gate.checks, "tests");
|
|
137
|
+
assert.equal(tests.pass, false, "a failing test command fails the gate");
|
|
138
|
+
assert.notEqual(tests.advisory, true, "a configured command is not advisory");
|
|
139
|
+
const lint = byName(gate.checks, "lint");
|
|
140
|
+
assert.equal(lint.pass, true);
|
|
141
|
+
assert.notEqual(lint.advisory, true);
|
|
142
|
+
assert.equal(gate.overall, false);
|
|
143
|
+
assert.deepEqual(gate.failures, ["tests"]);
|
|
144
|
+
console.log("✓ a configured command produces a real verdict");
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
rmSync(dir, { recursive: true, force: true });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// ── coverage threshold, end to end through parseCoveragePercent ────────────
|
|
151
|
+
{
|
|
152
|
+
const dir = tmpProject((c) => {
|
|
153
|
+
c.gates.coverage.enabled = true;
|
|
154
|
+
c.gates.coverage.threshold = 80;
|
|
155
|
+
c.commands.coverage = "node -e \"console.log('All files | 91.2% stmts | 84% branch')\"";
|
|
156
|
+
}, onePlan("complete"));
|
|
157
|
+
try {
|
|
158
|
+
const pass = await runChecks(dir, "build", { record: false });
|
|
159
|
+
const cov = byName(pass.checks, "coverage");
|
|
160
|
+
assert.equal(cov.pass, true, cov.detail);
|
|
161
|
+
assert.match(cov.detail, /84% ≥ 80% threshold/, "the pessimistic figure is the one compared");
|
|
162
|
+
const cfg = loadConfig(dir).config;
|
|
163
|
+
cfg.gates.coverage.threshold = 90;
|
|
164
|
+
writeFileSync(join(dir, "harness", "config.json"), JSON.stringify(cfg, null, 2), "utf-8");
|
|
165
|
+
const fail = await runChecks(dir, "build", { record: false });
|
|
166
|
+
const covFail = byName(fail.checks, "coverage");
|
|
167
|
+
assert.equal(covFail.pass, false);
|
|
168
|
+
assert.match(covFail.detail, /84% is below the 90% threshold/);
|
|
169
|
+
assert.equal(fail.overall, false);
|
|
170
|
+
console.log("✓ the coverage gate compares the parsed minimum against the threshold");
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
rmSync(dir, { recursive: true, force: true });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// ── task-scoped gates run only what is meaningful for one task ─────────────
|
|
177
|
+
{
|
|
178
|
+
const plan = {
|
|
179
|
+
version: "2.0",
|
|
180
|
+
baseRevision: 1,
|
|
181
|
+
goals: [],
|
|
182
|
+
sprints: [],
|
|
183
|
+
features: [
|
|
184
|
+
{
|
|
185
|
+
id: "feature-001",
|
|
186
|
+
name: "F",
|
|
187
|
+
criteria: ["it works"],
|
|
188
|
+
tasks: [
|
|
189
|
+
mkTask("task-1", "complete", { subtasks: [{ id: "st-1", title: "s", status: "complete" }] }),
|
|
190
|
+
mkTask("task-2", "pending"),
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
};
|
|
195
|
+
const dir = tmpProject(() => { }, plan);
|
|
196
|
+
try {
|
|
197
|
+
const gate = await runChecks(dir, "build", { feature: "feature-001", task: "task-1", record: false });
|
|
198
|
+
assert.deepEqual(gate.checks.map((c) => c.name), ["lint", "tests", "coverage", "task-criteria"], "only task-scoped checks plus the task's own criteria");
|
|
199
|
+
assert.ok(!gate.checks.some((c) => c.name === "tasks-complete"), "validating one task must not demand the whole phase is finished");
|
|
200
|
+
assert.ok(!gate.checks.some((c) => c.name === "anti-placeholder"), "whole-tree checks are phase-scoped");
|
|
201
|
+
assert.equal(gate.overall, true, "the task is done even though the phase is not");
|
|
202
|
+
assert.equal(gate.feature, "feature-001", "the scope is reported back");
|
|
203
|
+
assert.equal(gate.task, "task-1");
|
|
204
|
+
// The unfinished sibling still fails when it is the one being validated.
|
|
205
|
+
const sibling = await runChecks(dir, "build", { feature: "feature-001", task: "task-2", record: false });
|
|
206
|
+
assert.equal(sibling.overall, false);
|
|
207
|
+
assert.deepEqual(sibling.failures, ["task-criteria"]);
|
|
208
|
+
// A phase-scoped run of the same plan sees the whole picture.
|
|
209
|
+
const phaseWide = await runChecks(dir, "build", { record: false });
|
|
210
|
+
assert.ok(phaseWide.checks.some((c) => c.name === "tasks-complete"));
|
|
211
|
+
assert.equal(phaseWide.overall, false);
|
|
212
|
+
assert.equal(phaseWide.feature, undefined, "an unscoped gate reports no scope");
|
|
213
|
+
console.log("✓ task-scoped runChecks runs only task-scoped checks plus task-criteria");
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
rmSync(dir, { recursive: true, force: true });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// ── checkTaskCriteria ──────────────────────────────────────────────────────
|
|
220
|
+
{
|
|
221
|
+
const complete = tmpProject(() => { }, onePlan("complete", [
|
|
222
|
+
{ id: "st-1", title: "one", status: "complete" },
|
|
223
|
+
{ id: "st-2", title: "two", status: "complete" },
|
|
224
|
+
]));
|
|
225
|
+
const openSub = tmpProject(() => { }, onePlan("complete", [
|
|
226
|
+
{ id: "st-1", title: "one", status: "complete" },
|
|
227
|
+
{ id: "st-2", title: "two", status: "pending" },
|
|
228
|
+
{ id: "st-3", title: "three", status: "in_progress" },
|
|
229
|
+
]));
|
|
230
|
+
const notDone = tmpProject(() => { }, onePlan("in_progress"));
|
|
231
|
+
try {
|
|
232
|
+
const ok = checkTaskCriteria(complete, "feature-001", "task-1");
|
|
233
|
+
assert.equal(ok.pass, true, ok.detail);
|
|
234
|
+
assert.equal(ok.name, "task-criteria");
|
|
235
|
+
assert.match(ok.detail, /complete with all subtasks done/);
|
|
236
|
+
// An open subtask means the work is not finished, whatever the task says.
|
|
237
|
+
const sub = checkTaskCriteria(openSub, "feature-001", "task-1");
|
|
238
|
+
assert.equal(sub.pass, false);
|
|
239
|
+
assert.match(sub.detail, /2 subtask\(s\) still open on task-1/);
|
|
240
|
+
// A task that is not complete cannot pass its own criteria — no agent
|
|
241
|
+
// marks its own work done.
|
|
242
|
+
const open = checkTaskCriteria(notDone, "feature-001", "task-1");
|
|
243
|
+
assert.equal(open.pass, false);
|
|
244
|
+
assert.match(open.detail, /task-1 is "in_progress", not complete/);
|
|
245
|
+
// Unknown scopes fail loudly rather than passing vacuously.
|
|
246
|
+
const noFeature = checkTaskCriteria(complete, "feature-999", "task-1");
|
|
247
|
+
assert.equal(noFeature.pass, false);
|
|
248
|
+
assert.match(noFeature.detail, /unknown feature feature-999/);
|
|
249
|
+
const noTask = checkTaskCriteria(complete, "feature-001", "task-999");
|
|
250
|
+
assert.equal(noTask.pass, false);
|
|
251
|
+
assert.match(noTask.detail, /unknown task task-999/);
|
|
252
|
+
console.log("✓ checkTaskCriteria: open subtasks, incomplete task, unknown scope");
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
for (const d of [complete, openSub, notDone])
|
|
256
|
+
rmSync(d, { recursive: true, force: true });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// ── the verdict is recorded unless the caller opts out ─────────────────────
|
|
260
|
+
{
|
|
261
|
+
const dir = tmpProject(() => { }, onePlan("complete"));
|
|
262
|
+
try {
|
|
263
|
+
await runChecks(dir, "build", { record: false });
|
|
264
|
+
assert.deepEqual(loadConfig(dir).config.gateHistory, [], "record:false leaves no trace");
|
|
265
|
+
await runChecks(dir, "build");
|
|
266
|
+
const history = loadConfig(dir).config.gateHistory;
|
|
267
|
+
assert.equal(history.length, 1);
|
|
268
|
+
assert.equal(history[0].phase, "build");
|
|
269
|
+
assert.equal(history[0].result, "pass");
|
|
270
|
+
assert.equal("feature" in history[0], false, "an unscoped gate records no scope");
|
|
271
|
+
await runChecks(dir, "build", { feature: "feature-001", task: "task-1" });
|
|
272
|
+
const scoped = loadConfig(dir).config.gateHistory;
|
|
273
|
+
assert.equal(scoped.length, 2);
|
|
274
|
+
assert.equal(scoped[1].feature, "feature-001");
|
|
275
|
+
assert.equal(scoped[1].task, "task-1");
|
|
276
|
+
console.log("✓ gate verdicts are recorded to gateHistory");
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
rmSync(dir, { recursive: true, force: true });
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// ── phase → check mapping ──────────────────────────────────────────────────
|
|
283
|
+
{
|
|
284
|
+
assert.deepEqual(getPhaseCheckNames("init"), ["gitrepo", "configexists"]);
|
|
285
|
+
// Seeded tasks are visible as progress (dashboard + TUI lane) and block via phase-scoped tasks-complete
|
|
286
|
+
// in the loop, not as a hard gate — so research remains researchdoc/doc, define stays featurecriteria+skillsload
|
|
287
|
+
// and the synthetic converge walk is not frozen by pending seeded tasks.
|
|
288
|
+
assert.match(getPhaseCheckNames("research").join(","), /researchdoc/);
|
|
289
|
+
assert.deepEqual(getPhaseCheckNames("define"), ["featurecriteria", "skillsload"]);
|
|
290
|
+
assert.ok(getPhaseCheckNames("review").includes("skillsload"), "review re-checks the skills too");
|
|
291
|
+
assert.deepEqual(getPhaseCheckNames("build"), ["lint", "tests", "coverage", "noplaceholders", "taskscomplete"]);
|
|
292
|
+
assert.ok(getPhaseCheckNames("ship").includes("tagged"), "shipping demands a tag");
|
|
293
|
+
assert.ok(getPhaseCheckNames("ship").includes("changelog"));
|
|
294
|
+
// DEFINE demands criteria before any code is written.
|
|
295
|
+
const noCriteria = {
|
|
296
|
+
version: "2.0",
|
|
297
|
+
baseRevision: 0,
|
|
298
|
+
goals: [],
|
|
299
|
+
sprints: [],
|
|
300
|
+
features: [{ id: "feature-001", name: "F", tasks: [] }],
|
|
301
|
+
};
|
|
302
|
+
const dir = tmpProject(() => { }, noCriteria);
|
|
303
|
+
try {
|
|
304
|
+
const gate = await runChecks(dir, "define", { record: false });
|
|
305
|
+
assert.equal(gate.overall, false);
|
|
306
|
+
assert.match(byName(gate.checks, "feature-criteria").detail, /without criteria: feature-001/);
|
|
307
|
+
const planGate = await runChecks(dir, "plan", { record: false });
|
|
308
|
+
assert.equal(planGate.overall, false, "PLAN must produce tasks");
|
|
309
|
+
assert.ok(planGate.failures.includes("tasks-planned"));
|
|
310
|
+
assert.ok(planGate.failures.includes("feature-criteria"));
|
|
311
|
+
console.log("✓ phase → check mapping");
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
rmSync(dir, { recursive: true, force: true });
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// ── a project with no config at all still gets a verdict ───────────────────
|
|
318
|
+
{
|
|
319
|
+
const dir = mkdtempSync(join(tmpdir(), "pi-gates-bare-"));
|
|
320
|
+
try {
|
|
321
|
+
assert.equal(areGatesEnabled(dir), true, "the default is to enforce");
|
|
322
|
+
const gate = await runChecks(dir, "init");
|
|
323
|
+
assert.ok(gate.checks.some((c) => c.name === "config-exists"));
|
|
324
|
+
assert.equal(byName(gate.checks, "config-exists").pass, false, "there is no harness/config.json");
|
|
325
|
+
assert.equal(gate.overall, false);
|
|
326
|
+
console.log("✓ an uninitialised project fails the INIT gate rather than throwing");
|
|
327
|
+
}
|
|
328
|
+
finally {
|
|
329
|
+
rmSync(dir, { recursive: true, force: true });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
console.log("All gates tests PASS");
|
|
333
|
+
//# sourceMappingURL=gates.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gates.test.js","sourceRoot":"","sources":["../../tests/gates.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The goal loop, connected.
|
|
3
|
+
*
|
|
4
|
+
* `goalSpec`, `goalLoop` and `goalState` are 1,600 lines of complete,
|
|
5
|
+
* well-tested outer loop — state a goal, do a pass, judge whether the goal is
|
|
6
|
+
* actually met, go round again if it is not, under limits. And nothing ever
|
|
7
|
+
* turned the crank, which meant the harness could finish a pipeline and
|
|
8
|
+
* declare "complete" without anyone ever asking whether the thing the human
|
|
9
|
+
* asked for was done.
|
|
10
|
+
*
|
|
11
|
+
* The mapping this driver chooses is the design: one goal iteration is one
|
|
12
|
+
* full pass of the phase pipeline. The gate decides whether the WORK is done.
|
|
13
|
+
* The goal loop decides whether the GOAL is done. They are different
|
|
14
|
+
* questions, and a harness meant to run for days needs both.
|
|
15
|
+
*/
|
|
16
|
+
import assert from "node:assert/strict";
|
|
17
|
+
import { existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
18
|
+
import { tmpdir } from "node:os";
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
import { initHarness } from "../src/core/init.js";
|
|
21
|
+
import { loadConfig, saveConfig } from "../src/core/config.js";
|
|
22
|
+
import { loadFeatureList } from "../src/core/featureList.js";
|
|
23
|
+
import { buildBrief, renderBrief } from "../src/core/brief.js";
|
|
24
|
+
import { writeTaskList } from "../src/taskList.js";
|
|
25
|
+
import { startGoal, loadGoal, reviewGoal, cancelGoal, recordPipelinePass, readGoalSpec, viewOf, describeGoal, goalPointerPath, } from "../src/goal.js";
|
|
26
|
+
function project() {
|
|
27
|
+
const dir = mkdtempSync(join(tmpdir(), "pi-goal-"));
|
|
28
|
+
initHarness(dir);
|
|
29
|
+
return dir;
|
|
30
|
+
}
|
|
31
|
+
/** Walk the config to the last phase with every task done. */
|
|
32
|
+
function finishPipeline(dir) {
|
|
33
|
+
writeTaskList(dir, {
|
|
34
|
+
features: [{ id: "feature-001", name: "F", criteria: ["it works"] }],
|
|
35
|
+
tasks: [{ key: "feature-001/task-001", subject: "the work", status: "complete" }],
|
|
36
|
+
});
|
|
37
|
+
const { config } = loadConfig(dir);
|
|
38
|
+
config.currentPhase = "ship";
|
|
39
|
+
config.currentRole = "evaluator";
|
|
40
|
+
saveConfig(dir, config);
|
|
41
|
+
}
|
|
42
|
+
// ── stating a goal ─────────────────────────────────────────────────────────
|
|
43
|
+
{
|
|
44
|
+
const dir = project();
|
|
45
|
+
const { state, spec } = await startGoal({
|
|
46
|
+
targetDir: dir,
|
|
47
|
+
goal: "Ship the payments rewrite behind a flag",
|
|
48
|
+
runId: "goal-1",
|
|
49
|
+
});
|
|
50
|
+
assert.equal(state.status, "running");
|
|
51
|
+
assert.equal(state.currentIteration, 1, "stating a goal opens pass 1");
|
|
52
|
+
assert.equal(spec.originalGoal, "Ship the payments rewrite behind a flag");
|
|
53
|
+
assert.ok(existsSync(goalPointerPath(dir)), "a new session can find the run");
|
|
54
|
+
// The specification is committed, human-readable, and traceable to what was
|
|
55
|
+
// actually asked for.
|
|
56
|
+
const onDisk = readGoalSpec(dir);
|
|
57
|
+
assert.ok(onDisk, "the goal specification is written where a human can read it");
|
|
58
|
+
assert.equal(onDisk.traceability.originalUserGoal, "Ship the payments rewrite behind a flag");
|
|
59
|
+
// And it reaches the brief, because the goal lives in the plan — the one
|
|
60
|
+
// source of truth the brief, widget and dashboard all read.
|
|
61
|
+
assert.equal(loadFeatureList(dir).list.goals?.[0]?.title, "Ship the payments rewrite behind a flag");
|
|
62
|
+
const brief = await buildBrief(dir);
|
|
63
|
+
assert.match(renderBrief(brief), /GOAL Ship the payments rewrite behind a flag/);
|
|
64
|
+
rmSync(dir, { recursive: true, force: true });
|
|
65
|
+
console.log("✓ a goal is stated once and shows up everywhere that reads the plan");
|
|
66
|
+
}
|
|
67
|
+
// One at a time: two live goals means neither is the goal.
|
|
68
|
+
{
|
|
69
|
+
const dir = project();
|
|
70
|
+
await startGoal({ targetDir: dir, goal: "First", runId: "goal-1" });
|
|
71
|
+
await assert.rejects(() => startGoal({ targetDir: dir, goal: "Second", runId: "goal-2" }), /already pursuing a goal/);
|
|
72
|
+
await cancelGoal(dir, "changed my mind");
|
|
73
|
+
const after = await startGoal({ targetDir: dir, goal: "Second", runId: "goal-2" });
|
|
74
|
+
assert.equal(after.state.goal, "Second", "cancelling frees it");
|
|
75
|
+
rmSync(dir, { recursive: true, force: true });
|
|
76
|
+
console.log("✓ one goal at a time, and cancelling releases it");
|
|
77
|
+
}
|
|
78
|
+
{
|
|
79
|
+
const dir = project();
|
|
80
|
+
await assert.rejects(() => startGoal({ targetDir: dir, goal: " ", runId: "g" }), /needs to say something/);
|
|
81
|
+
assert.equal(await loadGoal(dir), null, "a project with no goal says so rather than throwing");
|
|
82
|
+
rmSync(dir, { recursive: true, force: true });
|
|
83
|
+
}
|
|
84
|
+
// ── the review is the point ────────────────────────────────────────────────
|
|
85
|
+
{
|
|
86
|
+
const dir = project();
|
|
87
|
+
await startGoal({ targetDir: dir, goal: "Make the thing good", runId: "goal-1" });
|
|
88
|
+
finishPipeline(dir);
|
|
89
|
+
const recorded = await recordPipelinePass(dir, "one pass done");
|
|
90
|
+
assert.ok(recorded, "a finished pipeline is recorded against the goal");
|
|
91
|
+
assert.equal(recorded.phase, "todo_executed", "and becomes reviewable");
|
|
92
|
+
// "Not done" with nothing named is a shrug, and the next pass would start no
|
|
93
|
+
// better informed than this one.
|
|
94
|
+
await assert.rejects(() => reviewGoal(dir, { decision: "incomplete", rationale: "not there yet" }), /must name what is still missing/);
|
|
95
|
+
const outcome = await reviewGoal(dir, {
|
|
96
|
+
decision: "incomplete",
|
|
97
|
+
rationale: "the flag is missing and nothing is measured",
|
|
98
|
+
remainingWork: ["put it behind a feature flag", "add the latency metric"],
|
|
99
|
+
});
|
|
100
|
+
assert.equal(outcome.terminal, false);
|
|
101
|
+
assert.equal(outcome.rewoundTo, "define", "another pass starts at the first phase");
|
|
102
|
+
assert.match(outcome.message, /Starting pass 2/);
|
|
103
|
+
// The pipeline really moved, and the retry budgets came back with it.
|
|
104
|
+
const { config } = loadConfig(dir);
|
|
105
|
+
assert.equal(config.currentPhase, "define");
|
|
106
|
+
assert.equal(config.currentRole, "planner");
|
|
107
|
+
assert.equal(config.phaseRetryCount, 0, "a new pass gets fresh budgets");
|
|
108
|
+
// And the next brief says what is left, so the agent does not re-plan the
|
|
109
|
+
// whole goal from scratch and rebuild what the review already accepted.
|
|
110
|
+
const brief = await buildBrief(dir);
|
|
111
|
+
const text = renderBrief(brief);
|
|
112
|
+
assert.match(text, /judged not yet met/);
|
|
113
|
+
assert.match(text, /put it behind a feature flag/);
|
|
114
|
+
assert.match(text, /add the latency metric/);
|
|
115
|
+
rmSync(dir, { recursive: true, force: true });
|
|
116
|
+
console.log("✓ an unmet goal rewinds the pipeline and carries the remaining work into the brief");
|
|
117
|
+
}
|
|
118
|
+
// A met goal ends the run.
|
|
119
|
+
{
|
|
120
|
+
const dir = project();
|
|
121
|
+
await startGoal({ targetDir: dir, goal: "Make the thing good", runId: "goal-1" });
|
|
122
|
+
finishPipeline(dir);
|
|
123
|
+
await recordPipelinePass(dir, "done");
|
|
124
|
+
const outcome = await reviewGoal(dir, {
|
|
125
|
+
decision: "complete",
|
|
126
|
+
rationale: "every acceptance criterion is met and proved",
|
|
127
|
+
});
|
|
128
|
+
assert.equal(outcome.terminal, true);
|
|
129
|
+
assert.equal(outcome.state.status, "done");
|
|
130
|
+
assert.match(outcome.message, /Goal met after 1 pass/);
|
|
131
|
+
const view = viewOf(outcome.state);
|
|
132
|
+
assert.match(describeGoal(view), /goal done/);
|
|
133
|
+
assert.ok(existsSync(join(outcome.state.goalRunDir, "GOAL_RESULT.md")), "the run leaves a result behind");
|
|
134
|
+
// Reviewing a finished loop is a no-op, not a second ending.
|
|
135
|
+
const again = await reviewGoal(dir, { decision: "complete", rationale: "again" });
|
|
136
|
+
assert.match(again.message, /already finished/);
|
|
137
|
+
rmSync(dir, { recursive: true, force: true });
|
|
138
|
+
console.log("✓ a met goal ends the run and writes its result");
|
|
139
|
+
}
|
|
140
|
+
// ── it is bounded ──────────────────────────────────────────────────────────
|
|
141
|
+
// An outer loop with no ceiling is how a harness runs for days and produces
|
|
142
|
+
// nothing.
|
|
143
|
+
{
|
|
144
|
+
const dir = project();
|
|
145
|
+
await startGoal({ targetDir: dir, goal: "Chase it forever", runId: "goal-1", maxIterations: 2 });
|
|
146
|
+
for (let pass = 1; pass <= 3; pass++) {
|
|
147
|
+
finishPipeline(dir);
|
|
148
|
+
await recordPipelinePass(dir, `pass ${pass}`);
|
|
149
|
+
const outcome = await reviewGoal(dir, {
|
|
150
|
+
decision: "incomplete",
|
|
151
|
+
rationale: "still not right",
|
|
152
|
+
remainingWork: ["more work"],
|
|
153
|
+
});
|
|
154
|
+
if (pass < 2) {
|
|
155
|
+
assert.equal(outcome.terminal, false, `pass ${pass} should continue`);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
assert.equal(outcome.terminal, true, "the iteration ceiling ends it");
|
|
159
|
+
assert.match(outcome.message, /maxIterations|stopped/);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const final = await loadGoal(dir);
|
|
164
|
+
assert.notEqual(final.status, "running", "and the loop really is over");
|
|
165
|
+
rmSync(dir, { recursive: true, force: true });
|
|
166
|
+
console.log("✓ the goal loop stops at its iteration ceiling instead of chasing forever");
|
|
167
|
+
}
|
|
168
|
+
// A blocked verdict ends it too — that is what blocked means.
|
|
169
|
+
{
|
|
170
|
+
const dir = project();
|
|
171
|
+
await startGoal({ targetDir: dir, goal: "Needs something I cannot get", runId: "goal-1" });
|
|
172
|
+
finishPipeline(dir);
|
|
173
|
+
await recordPipelinePass(dir, "pass");
|
|
174
|
+
const outcome = await reviewGoal(dir, {
|
|
175
|
+
decision: "blocked",
|
|
176
|
+
rationale: "the upstream API does not exist yet",
|
|
177
|
+
remainingWork: ["wait for the API"],
|
|
178
|
+
});
|
|
179
|
+
assert.equal(outcome.terminal, true);
|
|
180
|
+
assert.equal(outcome.state.status, "blocked");
|
|
181
|
+
rmSync(dir, { recursive: true, force: true });
|
|
182
|
+
console.log("✓ blocked ends the loop rather than looping on something that cannot move");
|
|
183
|
+
}
|
|
184
|
+
// ── no goal, no interference ───────────────────────────────────────────────
|
|
185
|
+
{
|
|
186
|
+
const dir = project();
|
|
187
|
+
assert.equal(await recordPipelinePass(dir, "x"), null, "no goal means nothing to record");
|
|
188
|
+
await assert.rejects(() => reviewGoal(dir, { decision: "complete", rationale: "x" }), /No goal is being pursued/);
|
|
189
|
+
assert.equal(await cancelGoal(dir, "x"), null);
|
|
190
|
+
rmSync(dir, { recursive: true, force: true });
|
|
191
|
+
console.log("✓ a project with no goal is left entirely alone");
|
|
192
|
+
}
|
|
193
|
+
// ── reviewing early ────────────────────────────────────────────────────────
|
|
194
|
+
// Found by running the shipped package against a real project, not by any of
|
|
195
|
+
// the tests above: they all recorded a pipeline pass first, so none of them
|
|
196
|
+
// ever asked what happens when a review arrives before one. The answer was
|
|
197
|
+
// `GoalLoopStateError: Cannot update goal iteration 2 from status pending` —
|
|
198
|
+
// an internal phase name thrown at whoever called the tool.
|
|
199
|
+
//
|
|
200
|
+
// Reviewing early is legitimate. You can see a pass will not meet the goal
|
|
201
|
+
// well before the pipeline agrees, and waiting for a doomed pipeline to finish
|
|
202
|
+
// first is theatre.
|
|
203
|
+
{
|
|
204
|
+
const dir = project();
|
|
205
|
+
await startGoal({ targetDir: dir, goal: "Do the thing properly", runId: "goal-1", maxIterations: 3 });
|
|
206
|
+
// Straight to a verdict, with no pipeline pass recorded at all.
|
|
207
|
+
const first = await reviewGoal(dir, {
|
|
208
|
+
decision: "incomplete",
|
|
209
|
+
rationale: "this approach was never going to work",
|
|
210
|
+
remainingWork: ["start again with the other approach"],
|
|
211
|
+
});
|
|
212
|
+
assert.equal(first.terminal, false);
|
|
213
|
+
assert.match(first.message, /Starting pass 2/);
|
|
214
|
+
// And again on the fresh pass, which is the exact sequence that threw.
|
|
215
|
+
const second = await reviewGoal(dir, {
|
|
216
|
+
decision: "incomplete",
|
|
217
|
+
rationale: "still not right",
|
|
218
|
+
remainingWork: ["one more thing"],
|
|
219
|
+
});
|
|
220
|
+
assert.equal(second.terminal, false);
|
|
221
|
+
assert.match(second.message, /Starting pass 3/);
|
|
222
|
+
const third = await reviewGoal(dir, { decision: "complete", rationale: "done at last" });
|
|
223
|
+
assert.equal(third.terminal, true);
|
|
224
|
+
assert.equal(third.state.status, "done");
|
|
225
|
+
rmSync(dir, { recursive: true, force: true });
|
|
226
|
+
console.log("✓ a review that arrives before the pipeline finishes is answered, not thrown at");
|
|
227
|
+
}
|
|
228
|
+
console.log("goal.test.ts ✓");
|
|
229
|
+
//# sourceMappingURL=goal.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goal.test.js","sourceRoot":"","sources":["../../tests/goal.test.ts"],"names":[],"mappings":"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"}
|