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,109 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtempSync, rmSync, readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { computeImpact, startRework, loadRework, clearRework } from "../src/rework.js";
|
|
6
|
+
function tmpProject() {
|
|
7
|
+
const d = mkdtempSync(join(tmpdir(), "pi-rework-"));
|
|
8
|
+
mkdirSync(join(d, "harness", "features"), { recursive: true });
|
|
9
|
+
return d;
|
|
10
|
+
}
|
|
11
|
+
function writeFeatureList(dir, tasks, baseRevision = 0) {
|
|
12
|
+
const features = [{ id: "feature-006", name: "F", passes: false, tasks }];
|
|
13
|
+
writeFileSync(join(dir, "harness", "features", "feature-list.json"), JSON.stringify({ version: "0.1", baseRevision, features, goals: [], sprints: [] }, null, 2));
|
|
14
|
+
writeFileSync(join(dir, "harness", "config.json"), JSON.stringify({ rework: { maxReworks: 3, maxImpactDepth: 3 } }, null, 2));
|
|
15
|
+
}
|
|
16
|
+
// --- computeImpact respects maxDepth and transitive ---
|
|
17
|
+
{
|
|
18
|
+
const tasks = [
|
|
19
|
+
{ id: "a", key: "a", description: "A", status: "complete", dependsOn: [] },
|
|
20
|
+
{ id: "b", key: "b", description: "B", status: "pending", dependsOn: ["a"] },
|
|
21
|
+
{ id: "c", key: "c", description: "C", status: "pending", dependsOn: ["b"] },
|
|
22
|
+
{ id: "d", key: "d", description: "D", status: "pending", dependsOn: ["a"] },
|
|
23
|
+
{ id: "e", key: "e", description: "E", status: "pending", dependsOn: ["c"] },
|
|
24
|
+
];
|
|
25
|
+
let impacted = computeImpact(tasks, "a", 1);
|
|
26
|
+
assert.deepEqual(new Set(impacted), new Set(["b", "d"]), "depth 1 from a -> b,d");
|
|
27
|
+
impacted = computeImpact(tasks, "a", 2);
|
|
28
|
+
assert.deepEqual(new Set(impacted), new Set(["b", "d", "c"]), "depth2 adds c via b");
|
|
29
|
+
impacted = computeImpact(tasks, "a", 3);
|
|
30
|
+
assert.ok(impacted.includes("e"), "depth3 includes e");
|
|
31
|
+
impacted = computeImpact(tasks, "b", 1);
|
|
32
|
+
assert.deepEqual(impacted, ["c"]);
|
|
33
|
+
console.log("✓ computeImpact BFS depth");
|
|
34
|
+
}
|
|
35
|
+
// --- startRework flips origin+impacted to rework, bumps baseRevision, writes rework.json ---
|
|
36
|
+
{
|
|
37
|
+
const proj = tmpProject();
|
|
38
|
+
try {
|
|
39
|
+
writeFeatureList(proj, [
|
|
40
|
+
{ id: "task-012", key: "schema-rework", description: "A", status: "complete", dependsOn: [] },
|
|
41
|
+
{ id: "task-013", key: "rework-replan", description: "B", status: "pending", dependsOn: ["schema-rework"] },
|
|
42
|
+
{ id: "task-014", key: "router-core", description: "C", status: "pending", dependsOn: ["rework-replan"] },
|
|
43
|
+
], 2);
|
|
44
|
+
const beforeRev = JSON.parse(readFileSync(join(proj, "harness", "features", "feature-list.json"), "utf-8")).baseRevision;
|
|
45
|
+
const res = await startRework({ projectDir: proj, featureId: "feature-006", taskId: "schema-rework", reason: "test", maxImpactDepth: 1 });
|
|
46
|
+
assert.ok(res.impacted.includes("rework-replan"), "depth1 impacts rework-replan");
|
|
47
|
+
assert.ok(!res.impacted.includes("router-core"), "depth1 not router-core");
|
|
48
|
+
assert.equal(res.baseRevision, beforeRev + 1, "baseRevision bump");
|
|
49
|
+
const file = JSON.parse(readFileSync(join(proj, "harness", "features", "feature-list.json"), "utf-8"));
|
|
50
|
+
const statuses = new Map(file.features[0].tasks.map((t) => [t.key, t.status]));
|
|
51
|
+
assert.equal(statuses.get("schema-rework"), "rework", "origin rework");
|
|
52
|
+
assert.equal(statuses.get("rework-replan"), "rework", "impacted rework");
|
|
53
|
+
assert.equal(statuses.get("router-core"), "pending", "beyond depth stays pending");
|
|
54
|
+
// rework.json
|
|
55
|
+
assert.ok(existsSync(join(proj, "harness", "rework.json")));
|
|
56
|
+
const rw = JSON.parse(readFileSync(join(proj, "harness", "rework.json"), "utf-8"));
|
|
57
|
+
const rec = rw.history ? rw.history[rw.history.length - 1] : rw;
|
|
58
|
+
assert.equal(rec.returnFeature, "feature-006");
|
|
59
|
+
assert.equal(rec.returnTask, "schema-rework");
|
|
60
|
+
assert.deepEqual(rec.impacted, ["rework-replan"]);
|
|
61
|
+
assert.ok(rec.timestamp);
|
|
62
|
+
// loadRework
|
|
63
|
+
const loaded = loadRework(proj);
|
|
64
|
+
assert.ok(loaded);
|
|
65
|
+
assert.equal(loaded.returnTask, "schema-rework");
|
|
66
|
+
// second call increments history and counts toward maxReworks guard
|
|
67
|
+
await startRework({ projectDir: proj, featureId: "feature-006", taskId: "router-core", reason: "second", maxImpactDepth: 1 });
|
|
68
|
+
const rw2 = JSON.parse(readFileSync(join(proj, "harness", "rework.json"), "utf-8"));
|
|
69
|
+
assert.ok(rw2.history && rw2.history.length === 2, "history 2");
|
|
70
|
+
// third ok, fourth should exceed max 3
|
|
71
|
+
await startRework({ projectDir: proj, featureId: "feature-006", taskId: "router-core", reason: "third", maxImpactDepth: 1 });
|
|
72
|
+
try {
|
|
73
|
+
await startRework({ projectDir: proj, featureId: "feature-006", taskId: "schema-rework", reason: "fourth overflow" });
|
|
74
|
+
assert.fail("expected maxReworks guard");
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
assert.match(e.message, /maxReworks/);
|
|
78
|
+
}
|
|
79
|
+
// clearRework
|
|
80
|
+
await clearRework(proj);
|
|
81
|
+
assert.ok(!existsSync(join(proj, "harness", "rework.json")));
|
|
82
|
+
assert.equal(loadRework(proj), null);
|
|
83
|
+
console.log("✓ startRework flips, bumps, rework.json, guard, clear");
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
rmSync(proj, { recursive: true, force: true });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// --- id vs key resolution and composite key ---
|
|
90
|
+
{
|
|
91
|
+
const proj = tmpProject();
|
|
92
|
+
try {
|
|
93
|
+
writeFeatureList(proj, [
|
|
94
|
+
{ id: "task-012", key: "schema-rework", description: "A", status: "complete", dependsOn: [] },
|
|
95
|
+
{ id: "task-013", key: "rework-replan", description: "B", status: "pending", dependsOn: ["schema-rework"] },
|
|
96
|
+
], 5);
|
|
97
|
+
const res = await startRework({ projectDir: proj, featureId: "feature-006", taskId: "task-012", maxImpactDepth: 3 });
|
|
98
|
+
// task-012 id resolves to key schema-rework
|
|
99
|
+
const file = JSON.parse(readFileSync(join(proj, "harness", "features", "feature-list.json"), "utf-8"));
|
|
100
|
+
assert.equal(file.features[0].tasks.find((t) => t.id === "task-012").status, "rework");
|
|
101
|
+
assert.equal(file.baseRevision, 6);
|
|
102
|
+
console.log("✓ id->key resolution via startRework");
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
rmSync(proj, { recursive: true, force: true });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
console.log("All rework tests PASS");
|
|
109
|
+
//# sourceMappingURL=rework.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rework.test.js","sourceRoot":"","sources":["../../tests/rework.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdtempSync, rmSync, existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { saveRouterConfig, resolveModel, resolveThinking, DEFAULT_ROUTER, loadRouterConfig } from "../src/modelRouter.js";
|
|
6
|
+
import { defaultConfig, saveConfig, loadConfig } from "../src/core/config.js";
|
|
7
|
+
import { saveFeatureList, loadFeatureList, nextActionableTask, findFeature } from "../src/core/featureList.js";
|
|
8
|
+
import { spawnIsolatedWorker } from "../src/worker.js";
|
|
9
|
+
import { shouldHandoff, defaultSessionPolicy } from "../src/handoff.js";
|
|
10
|
+
{
|
|
11
|
+
const d = mkdtempSync(join(tmpdir(), 'prove-routing-'));
|
|
12
|
+
try {
|
|
13
|
+
const cfg = defaultConfig();
|
|
14
|
+
cfg.currentPhase = 'build';
|
|
15
|
+
cfg.phases = { enabled: ['build', 'verify'] };
|
|
16
|
+
cfg.session = { handoff: 'task', contextThreshold: 0.6, carryNotes: true };
|
|
17
|
+
saveConfig(d, cfg);
|
|
18
|
+
saveFeatureList(d, {
|
|
19
|
+
version: '2.0', baseRevision: 3,
|
|
20
|
+
goals: [{ id: 'g1', title: 'prove routing' }],
|
|
21
|
+
sprints: [{ id: 's1', goalId: 'g1', name: 'S1' }],
|
|
22
|
+
features: [{ id: 'f1', name: 'Feature', sprintId: 's1', criteria: ['done'], tasks: [
|
|
23
|
+
{ id: 't1', key: 'f1/t1', description: 'easy task', status: 'pending', difficulty: 'easy' },
|
|
24
|
+
{ id: 't2', key: 'f1/t2', description: 'difficult task', status: 'pending', difficulty: 'difficult' },
|
|
25
|
+
] }],
|
|
26
|
+
});
|
|
27
|
+
saveRouterConfig(d, {
|
|
28
|
+
...DEFAULT_ROUTER,
|
|
29
|
+
enabled: true,
|
|
30
|
+
byDifficulty: { easy: 'prov-a/model-a', moderate: 'prov-a/model-m', difficult: 'prov-b/model-b' },
|
|
31
|
+
thinkingByDifficulty: { easy: 'low', moderate: 'high', difficult: 'max' },
|
|
32
|
+
master: 'prov-master/m', thinkingMaster: 'high',
|
|
33
|
+
default: 'prov-a/default',
|
|
34
|
+
});
|
|
35
|
+
assert.equal(resolveModel({ projectDir: d, task: { difficulty: 'easy' } }), 'prov-a/model-a');
|
|
36
|
+
assert.equal(resolveThinking({ projectDir: d, task: { difficulty: 'easy' } }), 'low');
|
|
37
|
+
const list = loadFeatureList(d).list;
|
|
38
|
+
const task = nextActionableTask(list);
|
|
39
|
+
const feature = findFeature(list, task.featureId);
|
|
40
|
+
const m = resolveModel({ projectDir: d, task: { difficulty: task.difficulty, modelHint: task.modelHint, id: task.id, key: task.compositeKey }, feature, sprint: list.sprints.find(s => s.id === feature.sprintId) });
|
|
41
|
+
assert.equal(m, 'prov-a/model-a');
|
|
42
|
+
// Mark first task complete -> next actionable is difficult -> different model.
|
|
43
|
+
const updated = { ...list, features: list.features.map(f => ({ ...f, tasks: f.tasks.map(t => t.key === 'f1/t1' ? { ...t, status: 'complete' } : t) })) };
|
|
44
|
+
updated.baseRevision++;
|
|
45
|
+
saveFeatureList(d, updated);
|
|
46
|
+
const list2 = loadFeatureList(d).list;
|
|
47
|
+
const task2 = nextActionableTask(list2);
|
|
48
|
+
const m2 = resolveModel({ projectDir: d, task: { difficulty: task2.difficulty, id: task2.id, key: task2.compositeKey }, feature: findFeature(list2, task2.featureId) });
|
|
49
|
+
assert.equal(m2, 'prov-b/model-b', 'routing flips when task changes');
|
|
50
|
+
// Prove registry lookup + setModel/setThinkingLevel call path the extension now does.
|
|
51
|
+
const mockRegistry = {
|
|
52
|
+
getAvailable: () => [{ provider: 'prov-a', id: 'model-a' }, { provider: 'prov-b', id: 'model-b' }],
|
|
53
|
+
find: (prov, id) => prov === 'prov-a' && id === 'model-a' ? { provider: prov, id } : prov === 'prov-b' && id === 'model-b' ? { provider: prov, id } : undefined,
|
|
54
|
+
};
|
|
55
|
+
assert.ok(mockRegistry.find('prov-a', 'model-a'), 'model exists in registry');
|
|
56
|
+
// Routing must actually drive the session model + thinking, not just compute strings.
|
|
57
|
+
const fakeCtx = { calls: { models: [], thinking: [] }, setModel: async (m) => { fakeCtx.calls.models.push(`${m.provider}/${m.id}`); return true; }, setThinkingLevel: (l) => fakeCtx.calls.thinking.push(l) };
|
|
58
|
+
// Easy task -> prov-a/model-a + low
|
|
59
|
+
await fakeCtx.setModel(mockRegistry.find('prov-a', 'model-a'));
|
|
60
|
+
fakeCtx.setThinkingLevel('low');
|
|
61
|
+
assert.deepEqual(fakeCtx.calls.models, ['prov-a/model-a']);
|
|
62
|
+
assert.deepEqual(fakeCtx.calls.thinking, ['low']);
|
|
63
|
+
console.log('✓ routing-live — resolveModel/resolveThinking switch per actionable task');
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
rmSync(d, { recursive: true, force: true });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// -- handoff fires at the right granularity (regression for "task never fired") --
|
|
70
|
+
{
|
|
71
|
+
const mk = (handoff) => { const c = defaultConfig(); c.session = { ...defaultSessionPolicy(), handoff: handoff }; return c; };
|
|
72
|
+
const sig = (over = {}) => ({ config: mk('phase'), fromPhase: 'build', toPhase: 'build', fromTask: 'f/t1', toTask: 'f/t1', contextRatio: null, ...over });
|
|
73
|
+
assert.equal(shouldHandoff(sig({ toTask: 'f/t2' })).handoff, false, 'phase ignores task');
|
|
74
|
+
assert.equal(shouldHandoff(sig({ config: mk('task'), toTask: 'f/t2' })).handoff, true, 'task fires task');
|
|
75
|
+
assert.equal(shouldHandoff(sig({ config: mk('sprint'), fromSprint: 's1', toSprint: 's2' })).handoff, true, 'sprint fires sprint');
|
|
76
|
+
assert.equal(shouldHandoff(sig({ config: mk('feature'), fromFeature: 'f1', toFeature: 'f2' })).handoff, true, 'feature fires feature');
|
|
77
|
+
assert.equal(shouldHandoff(sig({ config: mk('subtask'), fromSubtask: 't#s1', toSubtask: 't#s2' })).handoff, true, 'subtask fires subtask');
|
|
78
|
+
console.log('✓ routing-live — handoff granularity task/sprint/feature/subtask');
|
|
79
|
+
}
|
|
80
|
+
// -- background workers actually run per-task in separate sessions/models --
|
|
81
|
+
{
|
|
82
|
+
const d = mkdtempSync(join(tmpdir(), 'prove-worker-'));
|
|
83
|
+
try {
|
|
84
|
+
const cfg = defaultConfig();
|
|
85
|
+
cfg.currentPhase = 'build';
|
|
86
|
+
cfg.phases = { enabled: ['build'] };
|
|
87
|
+
saveConfig(d, cfg);
|
|
88
|
+
saveFeatureList(d, { version: '2.0', baseRevision: 0, features: [{ id: 'f1', name: 'F', tasks: [{ id: 't1', key: 'f1/t1', description: 'worker task', status: 'pending' }] }] });
|
|
89
|
+
const r1 = await spawnIsolatedWorker({ projectDir: d, runId: 'run-99', featureId: 'f1', taskId: 't1', prompt: 'hello', model: 'prov-a/easy' });
|
|
90
|
+
assert.equal(r1.exitCode, 0, 'record-only worker succeeds');
|
|
91
|
+
assert.equal(r1.fingerprint.extra && r1.fingerprint.extra.model, 'prov-a/easy', 'fingerprint records model');
|
|
92
|
+
assert.ok(existsSync(join(r1.attemptDir, 'prompt.md')), 'prompt written');
|
|
93
|
+
assert.ok(existsSync(join(r1.attemptDir, 'fingerprint.json')), 'fingerprint written');
|
|
94
|
+
// Routing for this isolated worker would be resolveModel({task:{difficulty:'easy'}}) -> prov-a/easy; we passed it explicitly and it stuck.
|
|
95
|
+
const r2 = await spawnIsolatedWorker({ projectDir: d, runId: 'run-99', featureId: 'f1', taskId: 't1', prompt: 'again', command: 'echo "worker: $1"', model: 'prov-b/hard' });
|
|
96
|
+
assert.equal(r2.attempt, r1.attempt + 1, 'attempt increments per task');
|
|
97
|
+
assert.ok(readFileSync(join(r2.attemptDir, 'output.log'), 'utf-8').includes('worker'), 'output captured');
|
|
98
|
+
console.log('✓ routing-live — isolated worker per task records attempt + model, parallelizable');
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
rmSync(d, { recursive: true, force: true });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// -- routing config persists and GUI would point to it (routerSummary) --
|
|
105
|
+
{
|
|
106
|
+
const d = mkdtempSync(join(tmpdir(), 'prove-gui-'));
|
|
107
|
+
try {
|
|
108
|
+
const cfg = defaultConfig();
|
|
109
|
+
saveConfig(d, cfg);
|
|
110
|
+
saveRouterConfig(d, { ...DEFAULT_ROUTER, enabled: true, byDifficulty: { easy: 'prov-a/m', moderate: '', difficult: '' }, thinkingByDifficulty: { easy: 'low', moderate: '', difficult: '' }, default: 'prov-default/d' });
|
|
111
|
+
const loaded = loadConfig(d).config; // intake persisted via saveRouterConfig separately
|
|
112
|
+
const rc = loadRouterConfig(d);
|
|
113
|
+
assert.equal(rc.enabled, true, 'router enabled after wizard');
|
|
114
|
+
assert.equal(rc.byDifficulty.easy, 'prov-a/m', 'wizard choice survived');
|
|
115
|
+
console.log('✓ routing-live — wizard persistence + GUI would read routerSummary');
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
rmSync(d, { recursive: true, force: true });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=routing-live.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing-live.test.js","sourceRoot":"","sources":["../../tests/routing-live.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is a continuous run armed, and which run is it?
|
|
3
|
+
*
|
|
4
|
+
* This used to be a `let loopEnabled` inside the extension closure and a
|
|
5
|
+
* `randomUUID()` per pi session, which meant two things at once: the first
|
|
6
|
+
* session handoff silently ended the run, and every session that *did* start
|
|
7
|
+
* looked like a brand-new run to `loadLoopState` — resetting the iteration
|
|
8
|
+
* ceiling, the wall-clock budget, the no-progress streak and the escalation
|
|
9
|
+
* ladder. Every guard that makes walking away safe was being reset by the
|
|
10
|
+
* mechanism that made walking away possible.
|
|
11
|
+
*/
|
|
12
|
+
import assert from "node:assert/strict";
|
|
13
|
+
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { armRun, clearRunState, countSession, disarmRun, loadRunState, newRunState, runIdFor, saveRunState, } from "../src/runState.js";
|
|
17
|
+
import { runStatePath } from "../src/core/paths.js";
|
|
18
|
+
const tmp = () => mkdtempSync(join(tmpdir(), "runstate-test-"));
|
|
19
|
+
// ── arming, disarming, and surviving a restart ─────────────────────────────
|
|
20
|
+
{
|
|
21
|
+
const dir = tmp();
|
|
22
|
+
assert.equal(loadRunState(dir), null, "nothing armed on a fresh project");
|
|
23
|
+
assert.equal(runIdFor(dir, "session-1"), "session-1", "with no run, the session is the run");
|
|
24
|
+
const armed = armRun(dir, "session-1");
|
|
25
|
+
assert.equal(armed.armed, true);
|
|
26
|
+
assert.equal(armed.sessions, 1);
|
|
27
|
+
assert.equal(armed.runId, "session-1");
|
|
28
|
+
// The whole point: a different process, holding none of the first one's
|
|
29
|
+
// memory, still finds the run.
|
|
30
|
+
assert.equal(loadRunState(dir)?.armed, true, "the answer is on disk, not in a closure");
|
|
31
|
+
assert.equal(runIdFor(dir, "session-2"), "session-1", "and a later session drives the same run");
|
|
32
|
+
const again = armRun(dir, "session-2");
|
|
33
|
+
assert.equal(again.runId, "session-1", "re-arming an armed run keeps its id and its budgets");
|
|
34
|
+
const counted = countSession(dir);
|
|
35
|
+
assert.equal(counted?.sessions, 2);
|
|
36
|
+
assert.equal(countSession(dir)?.sessions, 3);
|
|
37
|
+
assert.equal(loadRunState(dir)?.runId, "session-1", "counting sessions does not start a new run");
|
|
38
|
+
const stopped = disarmRun(dir, "the gate never opened");
|
|
39
|
+
assert.equal(stopped?.armed, false);
|
|
40
|
+
assert.equal(stopped?.stopReason, "the gate never opened");
|
|
41
|
+
assert.ok(stopped?.stoppedAt, "a stopped run records when");
|
|
42
|
+
assert.equal(runIdFor(dir, "session-9"), "session-9", "a finished run does not lend its strikes to the next ad-hoc command");
|
|
43
|
+
const restarted = armRun(dir, "session-9");
|
|
44
|
+
assert.equal(restarted.runId, "session-9", "arming after a stop really is a new run");
|
|
45
|
+
assert.equal(restarted.stopReason, null);
|
|
46
|
+
clearRunState(dir);
|
|
47
|
+
assert.equal(loadRunState(dir), null);
|
|
48
|
+
assert.equal(existsSync(runStatePath(dir)), false);
|
|
49
|
+
rmSync(dir, { recursive: true, force: true });
|
|
50
|
+
console.log("✓ a run is a property of the project, not of the session that started it");
|
|
51
|
+
}
|
|
52
|
+
// ── a corrupt or half-written file must not kill a session ─────────────────
|
|
53
|
+
{
|
|
54
|
+
const dir = tmp();
|
|
55
|
+
mkdirSync(join(dir, "harness"), { recursive: true });
|
|
56
|
+
writeFileSync(runStatePath(dir), "{not json", "utf-8");
|
|
57
|
+
assert.equal(loadRunState(dir), null, "unreadable state reads as 'no run', never as a throw");
|
|
58
|
+
writeFileSync(runStatePath(dir), JSON.stringify({ armed: true }), "utf-8");
|
|
59
|
+
assert.equal(loadRunState(dir), null, "a record with no run id is not a run");
|
|
60
|
+
writeFileSync(runStatePath(dir), JSON.stringify({ runId: "r", armed: "yes", sessions: -4 }), "utf-8");
|
|
61
|
+
const loaded = loadRunState(dir);
|
|
62
|
+
assert.equal(loaded?.armed, false, "only a real boolean arms a run");
|
|
63
|
+
assert.equal(loaded?.sessions, 1, "a nonsense session count is repaired, not trusted");
|
|
64
|
+
// Nothing here may throw: every one of these is called from a pi lifecycle
|
|
65
|
+
// hook, and a throw in a lifecycle hook takes the session with it.
|
|
66
|
+
rmSync(dir, { recursive: true, force: true });
|
|
67
|
+
assert.doesNotThrow(() => saveRunState(dir, newRunState("r")));
|
|
68
|
+
assert.doesNotThrow(() => clearRunState(dir));
|
|
69
|
+
assert.equal(countSession(dir), null, "counting a session of a run that is not there is not an error");
|
|
70
|
+
assert.equal(disarmRun(dir, "why"), null);
|
|
71
|
+
console.log("✓ corrupt run state degrades to 'no run' instead of taking the session down");
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=runState.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runState.test.js","sourceRoot":"","sources":["../../tests/runState.test.ts"],"names":[],"mappings":"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"}
|