@ghostwater/soulforge 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/cli/cli.js +41 -7
- package/dist/cli/cli.js.map +1 -1
- package/dist/daemon/daemon.js +17 -8
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/runner.d.ts +2 -0
- package/dist/daemon/runner.js +98 -13
- package/dist/daemon/runner.js.map +1 -1
- package/dist/db/database.d.ts +13 -2
- package/dist/db/database.js +66 -17
- package/dist/db/database.js.map +1 -1
- package/dist/executors/codex-cli.d.ts +9 -0
- package/dist/executors/codex-cli.js +69 -0
- package/dist/executors/codex-cli.js.map +1 -0
- package/dist/executors/registry.js +2 -0
- package/dist/executors/registry.js.map +1 -1
- package/dist/lib/logger.js +16 -8
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/worktree.d.ts +1 -0
- package/dist/lib/worktree.js +13 -3
- package/dist/lib/worktree.js.map +1 -1
- package/dist/test-setup.js +29 -0
- package/dist/test-setup.js.map +1 -0
- package/dist/workflow/parser.js +26 -1
- package/dist/workflow/parser.js.map +1 -1
- package/dist/workflow/types.d.ts +4 -1
- package/package.json +2 -2
- package/workflows/bugfix/workflow.yml +174 -0
- package/workflows/feature-dev/workflow.yml +2 -0
- package/dist/db/database.test.js +0 -378
- package/dist/db/database.test.js.map +0 -1
- /package/dist/{db/database.test.d.ts → test-setup.d.ts} +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Soulforge Bugfix Workflow
|
|
2
|
+
# Diagnose → human review → fix → verify → PR
|
|
3
|
+
id: bugfix
|
|
4
|
+
name: Bug Fix
|
|
5
|
+
version: 1
|
|
6
|
+
description: |
|
|
7
|
+
Surgical bugfix pipeline. Diagnoses the bug and writes a failing test first,
|
|
8
|
+
then waits for human approval before implementing the fix.
|
|
9
|
+
Keeps scope tight — no "while I'm here" improvements.
|
|
10
|
+
|
|
11
|
+
defaults:
|
|
12
|
+
executor: claude-code
|
|
13
|
+
model: opus
|
|
14
|
+
timeout: 600
|
|
15
|
+
max_retries: 2
|
|
16
|
+
notify: [on_complete, on_fail]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- id: diagnose
|
|
20
|
+
executor: claude-code
|
|
21
|
+
model: opus
|
|
22
|
+
workdir: "{{workdir}}"
|
|
23
|
+
input: |
|
|
24
|
+
You are working in {{workdir}}. Diagnose the following bug.
|
|
25
|
+
|
|
26
|
+
BUG REPORT:
|
|
27
|
+
{{task}}
|
|
28
|
+
|
|
29
|
+
Instructions:
|
|
30
|
+
1. Read the bug report carefully
|
|
31
|
+
2. Explore the codebase to find the affected area
|
|
32
|
+
3. Reproduce the bug: find or write a test that FAILS due to this bug
|
|
33
|
+
4. Trace to root cause — understand exactly WHY it fails
|
|
34
|
+
5. Propose a minimal fix (what files change, what the change is, why it works)
|
|
35
|
+
|
|
36
|
+
IMPORTANT:
|
|
37
|
+
- You MUST have a failing test before you can claim diagnosis is complete
|
|
38
|
+
- Do NOT implement the fix yet — only diagnose and propose
|
|
39
|
+
- Keep the fix proposal minimal — bugfixes should be surgical
|
|
40
|
+
- Commit the failing test: test: failing test for {{task}}
|
|
41
|
+
|
|
42
|
+
Reply with:
|
|
43
|
+
STATUS: done
|
|
44
|
+
AFFECTED_FILES: which files are involved
|
|
45
|
+
ROOT_CAUSE: exactly what's wrong and why
|
|
46
|
+
FAILING_TEST: what test you wrote and how it demonstrates the bug
|
|
47
|
+
FIX_PROPOSAL: what needs to change (be specific — file, function, what changes)
|
|
48
|
+
SCOPE: list of files that will be modified in the fix (max)
|
|
49
|
+
expects: "STATUS: done"
|
|
50
|
+
|
|
51
|
+
- id: review-diagnosis
|
|
52
|
+
executor: self
|
|
53
|
+
notify: on_waiting
|
|
54
|
+
on_reject:
|
|
55
|
+
reset_to: diagnose
|
|
56
|
+
input: |
|
|
57
|
+
Review the diagnosis before any fix is implemented.
|
|
58
|
+
|
|
59
|
+
BUG: {{task}}
|
|
60
|
+
ROOT CAUSE: {{root_cause}}
|
|
61
|
+
FAILING TEST: {{failing_test}}
|
|
62
|
+
FIX PROPOSAL: {{fix_proposal}}
|
|
63
|
+
SCOPE: {{scope}}
|
|
64
|
+
|
|
65
|
+
Questions to consider:
|
|
66
|
+
- Is the root cause correct?
|
|
67
|
+
- Does the failing test actually prove the bug?
|
|
68
|
+
- Is the proposed fix minimal and surgical?
|
|
69
|
+
- Is the scope reasonable?
|
|
70
|
+
|
|
71
|
+
- id: fix
|
|
72
|
+
executor: claude-code
|
|
73
|
+
model: opus
|
|
74
|
+
workdir: "{{workdir}}"
|
|
75
|
+
input: |
|
|
76
|
+
Implement the approved fix for this bug.
|
|
77
|
+
|
|
78
|
+
WORKDIR: {{workdir}}
|
|
79
|
+
BUILD_CMD: {{build_cmd}}
|
|
80
|
+
TEST_CMD: {{test_cmd}}
|
|
81
|
+
|
|
82
|
+
BUG: {{task}}
|
|
83
|
+
ROOT CAUSE: {{root_cause}}
|
|
84
|
+
FIX PROPOSAL: {{fix_proposal}}
|
|
85
|
+
SCOPE: {{scope}}
|
|
86
|
+
|
|
87
|
+
Instructions:
|
|
88
|
+
1. Implement the fix — ONLY the approved changes in SCOPE
|
|
89
|
+
2. The failing test from the diagnose step MUST now pass
|
|
90
|
+
3. Run the full test suite: {{test_cmd}}
|
|
91
|
+
4. Run build: {{build_cmd}}
|
|
92
|
+
5. All tests must pass — no regressions
|
|
93
|
+
6. Commit: fix: {{task}}
|
|
94
|
+
|
|
95
|
+
DO NOT:
|
|
96
|
+
- Refactor unrelated code
|
|
97
|
+
- Add features
|
|
98
|
+
- Change files outside SCOPE unless absolutely necessary
|
|
99
|
+
- "Improve" things while you're in there
|
|
100
|
+
|
|
101
|
+
Reply with:
|
|
102
|
+
STATUS: done
|
|
103
|
+
CHANGES: exactly what you changed and why
|
|
104
|
+
TEST_RESULTS: full test suite results
|
|
105
|
+
expects: "STATUS: done"
|
|
106
|
+
|
|
107
|
+
- id: verify
|
|
108
|
+
executor: claude-code
|
|
109
|
+
model: opus
|
|
110
|
+
workdir: "{{workdir}}"
|
|
111
|
+
input: |
|
|
112
|
+
Verify the bugfix independently.
|
|
113
|
+
|
|
114
|
+
WORKDIR: {{workdir}}
|
|
115
|
+
TEST_CMD: {{test_cmd}}
|
|
116
|
+
BUILD_CMD: {{build_cmd}}
|
|
117
|
+
|
|
118
|
+
BUG: {{task}}
|
|
119
|
+
ROOT CAUSE: {{root_cause}}
|
|
120
|
+
CHANGES: {{changes}}
|
|
121
|
+
SCOPE: {{scope}}
|
|
122
|
+
|
|
123
|
+
Verify:
|
|
124
|
+
1. Run {{test_cmd}} — all tests pass (including the new regression test)
|
|
125
|
+
2. Run {{build_cmd}} — build succeeds
|
|
126
|
+
3. Review the diff: are changes limited to SCOPE?
|
|
127
|
+
4. Does the fix actually address the root cause (not just mask symptoms)?
|
|
128
|
+
5. Are there any edge cases the fix misses?
|
|
129
|
+
|
|
130
|
+
Reply with:
|
|
131
|
+
STATUS: done
|
|
132
|
+
VERIFIED: what you confirmed
|
|
133
|
+
DIFF_REVIEW: summary of actual changes vs approved scope
|
|
134
|
+
|
|
135
|
+
Or if issues found:
|
|
136
|
+
STATUS: retry
|
|
137
|
+
ISSUES:
|
|
138
|
+
- What's wrong
|
|
139
|
+
expects: "STATUS: done"
|
|
140
|
+
|
|
141
|
+
- id: pr
|
|
142
|
+
executor: claude-code
|
|
143
|
+
model: opus
|
|
144
|
+
workdir: "{{workdir}}"
|
|
145
|
+
notify: on_complete
|
|
146
|
+
input: |
|
|
147
|
+
Create a pull request for this bugfix.
|
|
148
|
+
|
|
149
|
+
WORKDIR: {{workdir}}
|
|
150
|
+
BUG: {{task}}
|
|
151
|
+
ROOT_CAUSE: {{root_cause}}
|
|
152
|
+
CHANGES: {{changes}}
|
|
153
|
+
|
|
154
|
+
Create a PR with gh pr create. The PR body should include:
|
|
155
|
+
- What the bug was
|
|
156
|
+
- Root cause
|
|
157
|
+
- What the fix does
|
|
158
|
+
- Link to the issue if one exists
|
|
159
|
+
|
|
160
|
+
Reply with:
|
|
161
|
+
STATUS: done
|
|
162
|
+
PR: URL to the pull request
|
|
163
|
+
expects: "STATUS: done"
|
|
164
|
+
|
|
165
|
+
- id: final-review
|
|
166
|
+
executor: self
|
|
167
|
+
notify: on_waiting
|
|
168
|
+
input: |
|
|
169
|
+
Final review of the bugfix PR.
|
|
170
|
+
PR: {{pr}}
|
|
171
|
+
BUG: {{task}}
|
|
172
|
+
ROOT CAUSE: {{root_cause}}
|
|
173
|
+
CHANGES: {{changes}}
|
|
174
|
+
VERIFIED: {{verified}}
|
|
@@ -56,6 +56,7 @@ steps:
|
|
|
56
56
|
executor: claude-code
|
|
57
57
|
model: opus
|
|
58
58
|
workdir: "{{workdir}}"
|
|
59
|
+
notify: [on_complete, on_fail]
|
|
59
60
|
type: loop
|
|
60
61
|
loop:
|
|
61
62
|
over: stories
|
|
@@ -151,6 +152,7 @@ steps:
|
|
|
151
152
|
executor: claude-code
|
|
152
153
|
model: opus
|
|
153
154
|
workdir: "{{workdir}}"
|
|
155
|
+
notify: on_complete
|
|
154
156
|
input: |
|
|
155
157
|
Create a pull request.
|
|
156
158
|
|
package/dist/db/database.test.js
DELETED
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
import { describe, it, before, after, beforeEach } from "node:test";
|
|
2
|
-
import assert from "node:assert";
|
|
3
|
-
import { DatabaseSync } from "node:sqlite";
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import os from "node:os";
|
|
7
|
-
// Test-specific database setup
|
|
8
|
-
let testDb;
|
|
9
|
-
let testDbPath;
|
|
10
|
-
// We'll test resetToStep by directly testing the database operations
|
|
11
|
-
// Since the actual functions use a singleton, we'll create test helpers
|
|
12
|
-
function setupTestDb() {
|
|
13
|
-
const testDir = fs.mkdtempSync(path.join(os.tmpdir(), "soulforge-test-"));
|
|
14
|
-
testDbPath = path.join(testDir, "test.db");
|
|
15
|
-
testDb = new DatabaseSync(testDbPath);
|
|
16
|
-
testDb.exec("PRAGMA journal_mode=WAL");
|
|
17
|
-
testDb.exec("PRAGMA foreign_keys=ON");
|
|
18
|
-
// Create schema
|
|
19
|
-
testDb.exec(`
|
|
20
|
-
CREATE TABLE IF NOT EXISTS runs (
|
|
21
|
-
id TEXT PRIMARY KEY,
|
|
22
|
-
workflow_id TEXT NOT NULL,
|
|
23
|
-
workflow_path TEXT NOT NULL,
|
|
24
|
-
task TEXT NOT NULL,
|
|
25
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
26
|
-
context TEXT NOT NULL DEFAULT '{}',
|
|
27
|
-
callback TEXT,
|
|
28
|
-
worktree TEXT,
|
|
29
|
-
created_at TEXT NOT NULL,
|
|
30
|
-
updated_at TEXT NOT NULL
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
CREATE TABLE IF NOT EXISTS steps (
|
|
34
|
-
id TEXT PRIMARY KEY,
|
|
35
|
-
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
36
|
-
step_id TEXT NOT NULL,
|
|
37
|
-
executor TEXT NOT NULL DEFAULT 'openclaw',
|
|
38
|
-
model TEXT,
|
|
39
|
-
agent_id TEXT,
|
|
40
|
-
step_index INTEGER NOT NULL,
|
|
41
|
-
input_template TEXT NOT NULL,
|
|
42
|
-
expects TEXT,
|
|
43
|
-
status TEXT NOT NULL DEFAULT 'waiting',
|
|
44
|
-
output TEXT,
|
|
45
|
-
error TEXT,
|
|
46
|
-
retry_count INTEGER DEFAULT 0,
|
|
47
|
-
max_retries INTEGER DEFAULT 2,
|
|
48
|
-
duration_ms INTEGER,
|
|
49
|
-
type TEXT NOT NULL DEFAULT 'single',
|
|
50
|
-
loop_config TEXT,
|
|
51
|
-
current_story_id TEXT,
|
|
52
|
-
triggered_by_loop_step_id TEXT,
|
|
53
|
-
workdir TEXT,
|
|
54
|
-
created_at TEXT NOT NULL,
|
|
55
|
-
updated_at TEXT NOT NULL
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
CREATE TABLE IF NOT EXISTS stories (
|
|
59
|
-
id TEXT PRIMARY KEY,
|
|
60
|
-
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
61
|
-
story_index INTEGER NOT NULL,
|
|
62
|
-
story_id TEXT NOT NULL,
|
|
63
|
-
title TEXT NOT NULL,
|
|
64
|
-
description TEXT NOT NULL,
|
|
65
|
-
acceptance_criteria TEXT NOT NULL,
|
|
66
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
67
|
-
output TEXT,
|
|
68
|
-
retry_count INTEGER DEFAULT 0,
|
|
69
|
-
max_retries INTEGER DEFAULT 2,
|
|
70
|
-
created_at TEXT NOT NULL,
|
|
71
|
-
updated_at TEXT NOT NULL
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
CREATE TABLE IF NOT EXISTS events (
|
|
75
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
76
|
-
run_id TEXT NOT NULL,
|
|
77
|
-
step_id TEXT,
|
|
78
|
-
type TEXT NOT NULL,
|
|
79
|
-
summary TEXT NOT NULL,
|
|
80
|
-
details TEXT,
|
|
81
|
-
created_at TEXT NOT NULL
|
|
82
|
-
);
|
|
83
|
-
`);
|
|
84
|
-
return testDb;
|
|
85
|
-
}
|
|
86
|
-
function cleanupTestDb() {
|
|
87
|
-
if (testDb) {
|
|
88
|
-
try {
|
|
89
|
-
testDb.close();
|
|
90
|
-
}
|
|
91
|
-
catch { }
|
|
92
|
-
}
|
|
93
|
-
if (testDbPath) {
|
|
94
|
-
try {
|
|
95
|
-
fs.unlinkSync(testDbPath);
|
|
96
|
-
fs.rmdirSync(path.dirname(testDbPath));
|
|
97
|
-
}
|
|
98
|
-
catch { }
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// resetToStep implementation for testing (mirrors the actual implementation)
|
|
102
|
-
function resetToStep(db, runId, targetStepId, feedback) {
|
|
103
|
-
const now = new Date().toISOString();
|
|
104
|
-
// Get all steps for the run
|
|
105
|
-
const steps = db.prepare("SELECT * FROM steps WHERE run_id = ? ORDER BY step_index ASC").all(runId);
|
|
106
|
-
const targetStep = steps.find((s) => s.step_id === targetStepId);
|
|
107
|
-
if (!targetStep) {
|
|
108
|
-
throw new Error(`Target step "${targetStepId}" not found in run ${runId}`);
|
|
109
|
-
}
|
|
110
|
-
const targetIndex = targetStep.step_index;
|
|
111
|
-
db.exec("BEGIN");
|
|
112
|
-
try {
|
|
113
|
-
// Set target step to 'pending'
|
|
114
|
-
db.prepare("UPDATE steps SET status = 'pending', error = NULL, output = NULL, retry_count = 0, current_story_id = NULL, updated_at = ? WHERE run_id = ? AND step_index = ?").run(now, runId, targetIndex);
|
|
115
|
-
// Set all steps after target to 'waiting'
|
|
116
|
-
db.prepare("UPDATE steps SET status = 'waiting', error = NULL, output = NULL, retry_count = 0, current_story_id = NULL, updated_at = ? WHERE run_id = ? AND step_index > ?").run(now, runId, targetIndex);
|
|
117
|
-
// Delete all stories for the run
|
|
118
|
-
db.prepare("DELETE FROM stories WHERE run_id = ?").run(runId);
|
|
119
|
-
// Update context with rejection_feedback
|
|
120
|
-
const run = db.prepare("SELECT * FROM runs WHERE id = ?").get(runId);
|
|
121
|
-
if (run) {
|
|
122
|
-
const context = JSON.parse(run.context);
|
|
123
|
-
context.rejection_feedback = feedback;
|
|
124
|
-
db.prepare("UPDATE runs SET context = ?, status = 'running', updated_at = ? WHERE id = ?").run(JSON.stringify(context), now, runId);
|
|
125
|
-
}
|
|
126
|
-
db.exec("COMMIT");
|
|
127
|
-
}
|
|
128
|
-
catch (err) {
|
|
129
|
-
db.exec("ROLLBACK");
|
|
130
|
-
throw err;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
describe("resetToStep", () => {
|
|
134
|
-
before(() => {
|
|
135
|
-
setupTestDb();
|
|
136
|
-
});
|
|
137
|
-
after(() => {
|
|
138
|
-
cleanupTestDb();
|
|
139
|
-
});
|
|
140
|
-
beforeEach(() => {
|
|
141
|
-
// Clear tables before each test
|
|
142
|
-
testDb.exec("DELETE FROM events");
|
|
143
|
-
testDb.exec("DELETE FROM stories");
|
|
144
|
-
testDb.exec("DELETE FROM steps");
|
|
145
|
-
testDb.exec("DELETE FROM runs");
|
|
146
|
-
});
|
|
147
|
-
it("should set target step to pending", () => {
|
|
148
|
-
const now = new Date().toISOString();
|
|
149
|
-
const runId = "test-run-1";
|
|
150
|
-
// Create test run
|
|
151
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
152
|
-
// Create test steps
|
|
153
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-1", runId, "analyze", 0, "input", "done", now, now);
|
|
154
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-2", runId, "implement", 1, "input", "done", now, now);
|
|
155
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-3", runId, "review-plan", 2, "input", "waiting_approval", now, now);
|
|
156
|
-
// Reset to 'analyze' step
|
|
157
|
-
resetToStep(testDb, runId, "analyze", "Plan needs revision");
|
|
158
|
-
// Check target step is pending
|
|
159
|
-
const targetStep = testDb.prepare("SELECT * FROM steps WHERE step_id = ?").get("analyze");
|
|
160
|
-
assert.strictEqual(targetStep.status, "pending");
|
|
161
|
-
});
|
|
162
|
-
it("should set all steps after target to waiting", () => {
|
|
163
|
-
const now = new Date().toISOString();
|
|
164
|
-
const runId = "test-run-2";
|
|
165
|
-
// Create test run
|
|
166
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
167
|
-
// Create test steps
|
|
168
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-1", runId, "analyze", 0, "input", "done", now, now);
|
|
169
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-2", runId, "implement", 1, "input", "done", now, now);
|
|
170
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-3", runId, "review-plan", 2, "input", "waiting_approval", now, now);
|
|
171
|
-
// Reset to 'analyze' step
|
|
172
|
-
resetToStep(testDb, runId, "analyze", "Plan needs revision");
|
|
173
|
-
// Check steps after target are waiting
|
|
174
|
-
const implementStep = testDb.prepare("SELECT * FROM steps WHERE step_id = ?").get("implement");
|
|
175
|
-
const reviewStep = testDb.prepare("SELECT * FROM steps WHERE step_id = ?").get("review-plan");
|
|
176
|
-
assert.strictEqual(implementStep.status, "waiting");
|
|
177
|
-
assert.strictEqual(reviewStep.status, "waiting");
|
|
178
|
-
});
|
|
179
|
-
it("should delete all stories for the run", () => {
|
|
180
|
-
const now = new Date().toISOString();
|
|
181
|
-
const runId = "test-run-3";
|
|
182
|
-
// Create test run
|
|
183
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
184
|
-
// Create test steps
|
|
185
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-1", runId, "analyze", 0, "input", "done", now, now);
|
|
186
|
-
// Create test stories
|
|
187
|
-
testDb.prepare("INSERT INTO stories (id, run_id, story_index, story_id, title, description, acceptance_criteria, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run("story-uuid-1", runId, 0, "story-1", "Story 1", "Description 1", "[]", "pending", now, now);
|
|
188
|
-
testDb.prepare("INSERT INTO stories (id, run_id, story_index, story_id, title, description, acceptance_criteria, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run("story-uuid-2", runId, 1, "story-2", "Story 2", "Description 2", "[]", "done", now, now);
|
|
189
|
-
// Verify stories exist
|
|
190
|
-
const storiesBefore = testDb.prepare("SELECT COUNT(*) as count FROM stories WHERE run_id = ?").get(runId);
|
|
191
|
-
assert.strictEqual(storiesBefore.count, 2);
|
|
192
|
-
// Reset to 'analyze' step
|
|
193
|
-
resetToStep(testDb, runId, "analyze", "Plan needs revision");
|
|
194
|
-
// Check all stories deleted
|
|
195
|
-
const storiesAfter = testDb.prepare("SELECT COUNT(*) as count FROM stories WHERE run_id = ?").get(runId);
|
|
196
|
-
assert.strictEqual(storiesAfter.count, 0);
|
|
197
|
-
});
|
|
198
|
-
it("should update context with rejection_feedback", () => {
|
|
199
|
-
const now = new Date().toISOString();
|
|
200
|
-
const runId = "test-run-4";
|
|
201
|
-
const feedback = "The plan is missing error handling";
|
|
202
|
-
// Create test run with existing context
|
|
203
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", '{"existing_key":"value"}', now, now);
|
|
204
|
-
// Create test step
|
|
205
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-1", runId, "analyze", 0, "input", "done", now, now);
|
|
206
|
-
// Reset to 'analyze' step
|
|
207
|
-
resetToStep(testDb, runId, "analyze", feedback);
|
|
208
|
-
// Check context has rejection_feedback
|
|
209
|
-
const run = testDb.prepare("SELECT * FROM runs WHERE id = ?").get(runId);
|
|
210
|
-
const context = JSON.parse(run.context);
|
|
211
|
-
assert.strictEqual(context.rejection_feedback, feedback);
|
|
212
|
-
assert.strictEqual(context.existing_key, "value"); // Existing context preserved
|
|
213
|
-
});
|
|
214
|
-
it("should set run status to running", () => {
|
|
215
|
-
const now = new Date().toISOString();
|
|
216
|
-
const runId = "test-run-5";
|
|
217
|
-
// Create test run with waiting_approval status
|
|
218
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "waiting_approval", "{}", now, now);
|
|
219
|
-
// Create test step
|
|
220
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-1", runId, "analyze", 0, "input", "waiting_approval", now, now);
|
|
221
|
-
// Reset to 'analyze' step
|
|
222
|
-
resetToStep(testDb, runId, "analyze", "Needs work");
|
|
223
|
-
// Check run status is running
|
|
224
|
-
const run = testDb.prepare("SELECT * FROM runs WHERE id = ?").get(runId);
|
|
225
|
-
assert.strictEqual(run.status, "running");
|
|
226
|
-
});
|
|
227
|
-
it("should throw error if target step not found", () => {
|
|
228
|
-
const now = new Date().toISOString();
|
|
229
|
-
const runId = "test-run-6";
|
|
230
|
-
// Create test run
|
|
231
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
232
|
-
// Create test step
|
|
233
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-1", runId, "analyze", 0, "input", "done", now, now);
|
|
234
|
-
// Try to reset to non-existent step
|
|
235
|
-
assert.throws(() => resetToStep(testDb, runId, "non-existent-step", "Needs work"), /Target step "non-existent-step" not found/);
|
|
236
|
-
});
|
|
237
|
-
it("should reset retry_count and clear output/error on target step", () => {
|
|
238
|
-
const now = new Date().toISOString();
|
|
239
|
-
const runId = "test-run-7";
|
|
240
|
-
// Create test run
|
|
241
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
242
|
-
// Create test step with retry_count, output, and error
|
|
243
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, output, error, retry_count, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run("step-uuid-1", runId, "analyze", 0, "input", "done", "some output", "some error", 2, now, now);
|
|
244
|
-
// Reset to 'analyze' step
|
|
245
|
-
resetToStep(testDb, runId, "analyze", "Needs work");
|
|
246
|
-
// Check step has reset fields
|
|
247
|
-
const step = testDb.prepare("SELECT * FROM steps WHERE step_id = ?").get("analyze");
|
|
248
|
-
assert.strictEqual(step.retry_count, 0);
|
|
249
|
-
assert.strictEqual(step.output, null);
|
|
250
|
-
assert.strictEqual(step.error, null);
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
describe("triggered_by_loop_step_id", () => {
|
|
254
|
-
before(() => {
|
|
255
|
-
setupTestDb();
|
|
256
|
-
});
|
|
257
|
-
after(() => {
|
|
258
|
-
cleanupTestDb();
|
|
259
|
-
});
|
|
260
|
-
beforeEach(() => {
|
|
261
|
-
// Clear tables before each test
|
|
262
|
-
testDb.exec("DELETE FROM events");
|
|
263
|
-
testDb.exec("DELETE FROM stories");
|
|
264
|
-
testDb.exec("DELETE FROM steps");
|
|
265
|
-
testDb.exec("DELETE FROM runs");
|
|
266
|
-
});
|
|
267
|
-
it("should store triggered_by_loop_step_id on verify step", () => {
|
|
268
|
-
const now = new Date().toISOString();
|
|
269
|
-
const runId = "test-run-loop-1";
|
|
270
|
-
const loopStepId = "loop-step-uuid";
|
|
271
|
-
const verifyStepId = "verify-step-uuid";
|
|
272
|
-
// Create test run
|
|
273
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
274
|
-
// Create loop step
|
|
275
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, type, loop_config, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(loopStepId, runId, "implement", 0, "input", "running", "loop", '{"over":"stories","verifyEach":true,"verifyStep":"verify"}', now, now);
|
|
276
|
-
// Create verify step without triggered_by_loop_step_id
|
|
277
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(verifyStepId, runId, "verify", 1, "input", "waiting", now, now);
|
|
278
|
-
// Simulate loop step triggering verify step (set triggered_by_loop_step_id)
|
|
279
|
-
testDb.prepare("UPDATE steps SET status = 'pending', triggered_by_loop_step_id = ?, updated_at = ? WHERE id = ?").run(loopStepId, now, verifyStepId);
|
|
280
|
-
// Verify the triggered_by_loop_step_id is set
|
|
281
|
-
const verifyStep = testDb.prepare("SELECT * FROM steps WHERE id = ?").get(verifyStepId);
|
|
282
|
-
assert.strictEqual(verifyStep.triggered_by_loop_step_id, loopStepId);
|
|
283
|
-
assert.strictEqual(verifyStep.status, "pending");
|
|
284
|
-
});
|
|
285
|
-
it("should clear triggered_by_loop_step_id after verify completes", () => {
|
|
286
|
-
const now = new Date().toISOString();
|
|
287
|
-
const runId = "test-run-loop-2";
|
|
288
|
-
const loopStepId = "loop-step-uuid";
|
|
289
|
-
const verifyStepId = "verify-step-uuid";
|
|
290
|
-
// Create test run
|
|
291
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
292
|
-
// Create loop step
|
|
293
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, type, loop_config, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(loopStepId, runId, "implement", 0, "input", "running", "loop", '{"over":"stories","verifyEach":true,"verifyStep":"verify"}', now, now);
|
|
294
|
-
// Create verify step with triggered_by_loop_step_id set (as if triggered by loop)
|
|
295
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, triggered_by_loop_step_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)").run(verifyStepId, runId, "verify", 1, "input", "pending", loopStepId, now, now);
|
|
296
|
-
// Simulate verify step completing and clearing triggered_by_loop_step_id
|
|
297
|
-
testDb.prepare("UPDATE steps SET status = 'done', triggered_by_loop_step_id = NULL, updated_at = ? WHERE id = ?").run(now, verifyStepId);
|
|
298
|
-
// Verify the triggered_by_loop_step_id is cleared
|
|
299
|
-
const verifyStep = testDb.prepare("SELECT * FROM steps WHERE id = ?").get(verifyStepId);
|
|
300
|
-
assert.strictEqual(verifyStep.triggered_by_loop_step_id, null);
|
|
301
|
-
assert.strictEqual(verifyStep.status, "done");
|
|
302
|
-
});
|
|
303
|
-
it("should set loop step back to pending when more stories remain", () => {
|
|
304
|
-
const now = new Date().toISOString();
|
|
305
|
-
const runId = "test-run-loop-3";
|
|
306
|
-
const loopStepId = "loop-step-uuid";
|
|
307
|
-
const verifyStepId = "verify-step-uuid";
|
|
308
|
-
// Create test run
|
|
309
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
310
|
-
// Create loop step (running, processing first story)
|
|
311
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, type, loop_config, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(loopStepId, runId, "implement", 0, "input", "running", "loop", '{"over":"stories","completion":"all_done","verifyEach":true,"verifyStep":"verify"}', now, now);
|
|
312
|
-
// Create verify step with triggered_by_loop_step_id
|
|
313
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, triggered_by_loop_step_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)").run(verifyStepId, runId, "verify", 1, "input", "pending", loopStepId, now, now);
|
|
314
|
-
// Create stories - first is done, second is pending
|
|
315
|
-
testDb.prepare("INSERT INTO stories (id, run_id, story_index, story_id, title, description, acceptance_criteria, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run("story-1-uuid", runId, 0, "story-1", "Story 1", "Description 1", "[]", "done", now, now);
|
|
316
|
-
testDb.prepare("INSERT INTO stories (id, run_id, story_index, story_id, title, description, acceptance_criteria, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run("story-2-uuid", runId, 1, "story-2", "Story 2", "Description 2", "[]", "pending", now, now);
|
|
317
|
-
// Simulate continueLoop behavior: check for next pending story
|
|
318
|
-
const nextStory = testDb.prepare("SELECT * FROM stories WHERE run_id = ? AND status = 'pending' ORDER BY story_index ASC LIMIT 1").get(runId);
|
|
319
|
-
assert.ok(nextStory, "There should be a pending story");
|
|
320
|
-
assert.strictEqual(nextStory.story_id, "story-2");
|
|
321
|
-
// Since there are more stories, loop step should go back to pending
|
|
322
|
-
testDb.prepare("UPDATE steps SET status = 'pending', current_story_id = NULL, updated_at = ? WHERE id = ?").run(now, loopStepId);
|
|
323
|
-
const loopStep = testDb.prepare("SELECT * FROM steps WHERE id = ?").get(loopStepId);
|
|
324
|
-
assert.strictEqual(loopStep.status, "pending");
|
|
325
|
-
});
|
|
326
|
-
it("should mark loop step done when all stories complete", () => {
|
|
327
|
-
const now = new Date().toISOString();
|
|
328
|
-
const runId = "test-run-loop-4";
|
|
329
|
-
const loopStepId = "loop-step-uuid";
|
|
330
|
-
const verifyStepId = "verify-step-uuid";
|
|
331
|
-
// Create test run
|
|
332
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", "{}", now, now);
|
|
333
|
-
// Create loop step
|
|
334
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, type, loop_config, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(loopStepId, runId, "implement", 0, "input", "running", "loop", '{"over":"stories","completion":"all_done","verifyEach":true,"verifyStep":"verify"}', now, now);
|
|
335
|
-
// Create verify step
|
|
336
|
-
testDb.prepare("INSERT INTO steps (id, run_id, step_id, step_index, input_template, status, triggered_by_loop_step_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)").run(verifyStepId, runId, "verify", 1, "input", "pending", loopStepId, now, now);
|
|
337
|
-
// Create stories - all done
|
|
338
|
-
testDb.prepare("INSERT INTO stories (id, run_id, story_index, story_id, title, description, acceptance_criteria, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run("story-1-uuid", runId, 0, "story-1", "Story 1", "Description 1", "[]", "done", now, now);
|
|
339
|
-
testDb.prepare("INSERT INTO stories (id, run_id, story_index, story_id, title, description, acceptance_criteria, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run("story-2-uuid", runId, 1, "story-2", "Story 2", "Description 2", "[]", "done", now, now);
|
|
340
|
-
// Simulate continueLoop behavior: check for next pending story
|
|
341
|
-
const nextStory = testDb.prepare("SELECT * FROM stories WHERE run_id = ? AND status = 'pending' ORDER BY story_index ASC LIMIT 1").get(runId);
|
|
342
|
-
assert.ok(!nextStory, "There should be no pending stories");
|
|
343
|
-
// Since no more stories, loop step should be marked done
|
|
344
|
-
testDb.prepare("UPDATE steps SET status = 'done', updated_at = ? WHERE id = ?").run(now, loopStepId);
|
|
345
|
-
const loopStep = testDb.prepare("SELECT * FROM steps WHERE id = ?").get(loopStepId);
|
|
346
|
-
assert.strictEqual(loopStep.status, "done");
|
|
347
|
-
});
|
|
348
|
-
});
|
|
349
|
-
describe("progress path", () => {
|
|
350
|
-
const PROGRESS_DIR = path.join(os.homedir(), ".soulforge", "progress");
|
|
351
|
-
it("should store progress outside worktree in ~/.soulforge/progress/", () => {
|
|
352
|
-
const runId = "test-run-uuid-123";
|
|
353
|
-
const expectedPath = path.join(PROGRESS_DIR, `${runId}.txt`);
|
|
354
|
-
// Verify the path format is correct
|
|
355
|
-
assert.ok(expectedPath.includes(".soulforge/progress"), "should be in ~/.soulforge/progress/");
|
|
356
|
-
assert.ok(expectedPath.endsWith(`${runId}.txt`), "should be keyed by run ID");
|
|
357
|
-
assert.ok(!expectedPath.includes("worktree"), "should NOT be inside a worktree");
|
|
358
|
-
});
|
|
359
|
-
it("should inject progress_path into run context", () => {
|
|
360
|
-
// Check that createRun adds progress_path to initial context
|
|
361
|
-
// by verifying the database schema includes it
|
|
362
|
-
setupTestDb();
|
|
363
|
-
const now = new Date().toISOString();
|
|
364
|
-
const runId = "test-progress-run";
|
|
365
|
-
const context = JSON.stringify({
|
|
366
|
-
task: "test task",
|
|
367
|
-
progress_path: path.join(PROGRESS_DIR, `${runId}.txt`),
|
|
368
|
-
});
|
|
369
|
-
testDb.prepare("INSERT INTO runs (id, workflow_id, workflow_path, task, status, context, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(runId, "test-workflow", "/path/to/workflow", "test task", "running", context, now, now);
|
|
370
|
-
const run = testDb.prepare("SELECT * FROM runs WHERE id = ?").get(runId);
|
|
371
|
-
const parsedContext = JSON.parse(run.context);
|
|
372
|
-
assert.ok(parsedContext.progress_path, "progress_path should be in context");
|
|
373
|
-
assert.ok(parsedContext.progress_path.includes(runId), "should include run ID");
|
|
374
|
-
assert.ok(parsedContext.progress_path.includes("progress"), "should include progress dir");
|
|
375
|
-
cleanupTestDb();
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
//# sourceMappingURL=database.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"database.test.js","sourceRoot":"","sources":["../../src/db/database.test.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|