@cluesmith/codev 3.3.1 → 3.3.3
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/dashboard-dist/assets/{index-D3XaKpZW.js → index-CUIjS_Vb.js} +41 -41
- package/dashboard-dist/assets/index-CUIjS_Vb.js.map +1 -0
- package/dashboard-dist/assets/index-DnYLy5C_.css +32 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +52 -1
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/inbox.d.ts.map +1 -1
- package/dist/agent-farm/commands/inbox.js +67 -10
- package/dist/agent-farm/commands/inbox.js.map +1 -1
- package/dist/agent-farm/commands/interrupt.d.ts +4 -1
- package/dist/agent-farm/commands/interrupt.d.ts.map +1 -1
- package/dist/agent-farm/commands/interrupt.js +6 -3
- package/dist/agent-farm/commands/interrupt.js.map +1 -1
- package/dist/agent-farm/commands/reset/constants.d.ts +118 -0
- package/dist/agent-farm/commands/reset/constants.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/constants.js +118 -0
- package/dist/agent-farm/commands/reset/constants.js.map +1 -1
- package/dist/agent-farm/commands/reset/context.d.ts +18 -0
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/context.js +41 -0
- package/dist/agent-farm/commands/reset/context.js.map +1 -1
- package/dist/agent-farm/commands/reset/receipt.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/receipt.js +16 -5
- package/dist/agent-farm/commands/reset/receipt.js.map +1 -1
- package/dist/agent-farm/commands/reset/reorient.d.ts +1 -1
- package/dist/agent-farm/commands/reset/reorient.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/reorient.js +8 -1
- package/dist/agent-farm/commands/reset/reorient.js.map +1 -1
- package/dist/agent-farm/commands/reset/self.d.ts +335 -0
- package/dist/agent-farm/commands/reset/self.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/self.js +636 -0
- package/dist/agent-farm/commands/reset/self.js.map +1 -0
- package/dist/agent-farm/commands/reset.d.ts +4 -1
- package/dist/agent-farm/commands/reset.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset.js +29 -21
- package/dist/agent-farm/commands/reset.js.map +1 -1
- package/dist/agent-farm/commands/self-refresh.d.ts +60 -0
- package/dist/agent-farm/commands/self-refresh.d.ts.map +1 -0
- package/dist/agent-farm/commands/self-refresh.js +506 -0
- package/dist/agent-farm/commands/self-refresh.js.map +1 -0
- package/dist/agent-farm/commands/send.d.ts +28 -0
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +90 -7
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts +7 -0
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +13 -1
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/db/index.d.ts +3 -1
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +8 -443
- package/dist/agent-farm/db/index.js.map +1 -1
- package/dist/agent-farm/db/mailbox.d.ts +47 -7
- package/dist/agent-farm/db/mailbox.d.ts.map +1 -1
- package/dist/agent-farm/db/mailbox.js +56 -12
- package/dist/agent-farm/db/mailbox.js.map +1 -1
- package/dist/agent-farm/db/migrations.d.ts +57 -0
- package/dist/agent-farm/db/migrations.d.ts.map +1 -0
- package/dist/agent-farm/db/migrations.js +530 -0
- package/dist/agent-farm/db/migrations.js.map +1 -0
- package/dist/agent-farm/db/schema.d.ts +1 -1
- package/dist/agent-farm/db/schema.d.ts.map +1 -1
- package/dist/agent-farm/db/schema.js +1 -0
- package/dist/agent-farm/db/schema.js.map +1 -1
- package/dist/agent-farm/db/types.d.ts +22 -0
- package/dist/agent-farm/db/types.d.ts.map +1 -1
- package/dist/agent-farm/db/types.js.map +1 -1
- package/dist/agent-farm/lib/tower-client.d.ts +12 -0
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js +12 -0
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +43 -14
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/cron-delivery.d.ts +7 -1
- package/dist/agent-farm/servers/cron-delivery.d.ts.map +1 -1
- package/dist/agent-farm/servers/cron-delivery.js +2 -1
- package/dist/agent-farm/servers/cron-delivery.js.map +1 -1
- package/dist/agent-farm/servers/gate-profiles.d.ts +21 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts.map +1 -1
- package/dist/agent-farm/servers/gate-profiles.js +36 -4
- package/dist/agent-farm/servers/gate-profiles.js.map +1 -1
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +218 -15
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-delivery.js +259 -27
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +66 -11
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.js +202 -48
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -1
- package/dist/agent-farm/servers/message-write.d.ts +58 -18
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +73 -28
- package/dist/agent-farm/servers/message-write.js.map +1 -1
- package/dist/agent-farm/servers/render-gate.d.ts +37 -1
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -1
- package/dist/agent-farm/servers/render-gate.js +71 -12
- package/dist/agent-farm/servers/render-gate.js.map +1 -1
- package/dist/agent-farm/servers/session-submit.d.ts +220 -27
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -1
- package/dist/agent-farm/servers/session-submit.js +333 -42
- package/dist/agent-farm/servers/session-submit.js.map +1 -1
- package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-cron.js +3 -2
- package/dist/agent-farm/servers/tower-cron.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +11 -3
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts +32 -0
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +245 -36
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +15 -2
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +21 -0
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +53 -5
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.js +14 -0
- package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts +35 -0
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +39 -0
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.js +8 -1
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
- package/dist/agent-farm/types.d.ts +36 -1
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.d.ts +136 -4
- package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.js +212 -22
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/agent-farm/utils/server-utils.d.ts +8 -2
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +19 -2
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/generate-image.d.ts +20 -1
- package/dist/commands/generate-image.d.ts.map +1 -1
- package/dist/commands/generate-image.js +188 -1
- package/dist/commands/generate-image.js.map +1 -1
- package/dist/commands/porch/context-refresh.d.ts +181 -0
- package/dist/commands/porch/context-refresh.d.ts.map +1 -0
- package/dist/commands/porch/context-refresh.js +270 -0
- package/dist/commands/porch/context-refresh.js.map +1 -0
- package/dist/commands/porch/index.d.ts +6 -0
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +46 -0
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/next.d.ts +0 -9
- package/dist/commands/porch/next.d.ts.map +1 -1
- package/dist/commands/porch/next.js +133 -4
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/commands/porch/prompts.d.ts.map +1 -1
- package/dist/commands/porch/prompts.js +18 -2
- package/dist/commands/porch/prompts.js.map +1 -1
- package/dist/commands/porch/protocol.d.ts.map +1 -1
- package/dist/commands/porch/protocol.js +102 -0
- package/dist/commands/porch/protocol.js.map +1 -1
- package/dist/commands/porch/types.d.ts +61 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/lib/forge-contracts.d.ts +66 -5
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/forge.d.ts +1 -1
- package/dist/lib/forge.d.ts.map +1 -1
- package/dist/lib/forge.js +33 -11
- package/dist/lib/forge.js.map +1 -1
- package/dist/lib/self-refresh-invocation.d.ts +60 -0
- package/dist/lib/self-refresh-invocation.d.ts.map +1 -0
- package/dist/lib/self-refresh-invocation.js +64 -0
- package/dist/lib/self-refresh-invocation.js.map +1 -0
- package/dist/lib/test-env.d.ts +50 -0
- package/dist/lib/test-env.d.ts.map +1 -1
- package/dist/lib/test-env.js +76 -0
- package/dist/lib/test-env.js.map +1 -1
- package/dist/terminal/pty-manager.d.ts +10 -1
- package/dist/terminal/pty-manager.d.ts.map +1 -1
- package/dist/terminal/pty-manager.js +38 -9
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +52 -4
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +157 -18
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/shellper-client.d.ts +73 -0
- package/dist/terminal/shellper-client.d.ts.map +1 -1
- package/dist/terminal/shellper-client.js +151 -0
- package/dist/terminal/shellper-client.js.map +1 -1
- package/dist/terminal/shellper-main.js +20 -3
- package/dist/terminal/shellper-main.js.map +1 -1
- package/dist/terminal/shellper-process.d.ts +2 -0
- package/dist/terminal/shellper-process.d.ts.map +1 -1
- package/dist/terminal/shellper-process.js +17 -1
- package/dist/terminal/shellper-process.js.map +1 -1
- package/dist/terminal/shellper-protocol.d.ts +28 -0
- package/dist/terminal/shellper-protocol.d.ts.map +1 -1
- package/dist/terminal/shellper-protocol.js.map +1 -1
- package/package.json +4 -4
- package/scripts/forge/gitea/_lib.sh +214 -0
- package/scripts/forge/gitea/issue-comment.sh +8 -1
- package/scripts/forge/gitea/issue-view.sh +95 -4
- package/scripts/forge/gitea/pr-create.sh +155 -0
- package/scripts/forge/gitea/pr-exists.sh +32 -4
- package/scripts/forge/gitea/pr-list.sh +40 -31
- package/scripts/forge/gitea/pr-view.sh +65 -4
- package/scripts/forge/gitea/recently-merged.sh +91 -21
- package/scripts/forge/gitea/user-identity.sh +30 -1
- package/scripts/forge/github/issue-view.sh +5 -2
- package/scripts/forge/github/pr-create.sh +47 -0
- package/scripts/forge/github/pr-search.sh +3 -1
- package/scripts/forge/gitlab/issue-view.sh +24 -4
- package/scripts/forge/gitlab/pr-create.sh +53 -0
- package/scripts/forge/gitlab/pr-search.sh +3 -1
- package/scripts/forge/linear/issue-view.sh +13 -2
- package/skeleton/.claude/skills/arch-save/SKILL.md +8 -2
- package/skeleton/.claude/skills/builder-refresh/SKILL.md +138 -0
- package/skeleton/.claude/skills/generate-image/SKILL.md +22 -1
- package/skeleton/.codex/skills/arch-save/SKILL.md +8 -2
- package/skeleton/.codex/skills/builder-refresh/SKILL.md +138 -0
- package/skeleton/.codex/skills/generate-image/SKILL.md +22 -1
- package/skeleton/protocol-schema.json +17 -0
- package/skeleton/protocols/air/prompts/pr.md +6 -1
- package/skeleton/protocols/air/protocol.json +1 -1
- package/skeleton/protocols/aspir/prompts/review.md +6 -1
- package/skeleton/protocols/aspir/protocol.json +5 -1
- package/skeleton/protocols/bugfix/prompts/pr.md +6 -1
- package/skeleton/protocols/bugfix/protocol.json +1 -1
- package/skeleton/protocols/bugfix/protocol.md +2 -1
- package/skeleton/protocols/experiment/protocol.json +1 -1
- package/skeleton/protocols/maintain/prompts/review.md +6 -1
- package/skeleton/protocols/maintain/protocol.json +1 -1
- package/skeleton/protocols/pir/prompts/review.md +10 -7
- package/skeleton/protocols/pir/protocol.json +1 -1
- package/skeleton/protocols/protocol-schema.json +17 -0
- package/skeleton/protocols/research/protocol.json +1 -1
- package/skeleton/protocols/spike/protocol.json +1 -1
- package/skeleton/protocols/spir/prompts/review.md +6 -1
- package/skeleton/protocols/spir/protocol.json +5 -1
- package/skeleton/resources/commands/agent-farm.md +1 -1
- package/templates/tower.html +16 -1
- package/dashboard-dist/assets/index-BZRTEMtH.css +0 -32
- package/dashboard-dist/assets/index-D3XaKpZW.js.map +0 -1
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* Uses better-sqlite3 for synchronous operations with proper concurrency handling.
|
|
6
6
|
*/
|
|
7
7
|
import Database from 'better-sqlite3';
|
|
8
|
-
import { existsSync, mkdirSync
|
|
9
|
-
import {
|
|
10
|
-
import { resolve, dirname, join } from 'node:path';
|
|
8
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
9
|
+
import { resolve, dirname } from 'node:path';
|
|
11
10
|
import { AGENT_FARM_DIR } from '../lib/tower-client.js';
|
|
12
11
|
import { GLOBAL_SCHEMA } from './schema.js';
|
|
12
|
+
import { GLOBAL_CURRENT_VERSION, runGlobalMigrations } from './migrations.js';
|
|
13
13
|
// Singleton instance. Issue #1118: there is now a single user-global database
|
|
14
14
|
// (~/.agent-farm/global.db). getDb() and getGlobalDb() both return it; the
|
|
15
15
|
// retired per-workspace state.db is no longer opened.
|
|
@@ -123,8 +123,6 @@ function ensureGlobalDatabase() {
|
|
|
123
123
|
// Create/open database
|
|
124
124
|
const db = new Database(dbPath);
|
|
125
125
|
configurePragmas(db);
|
|
126
|
-
// Current migration version — bump when adding new migrations
|
|
127
|
-
const GLOBAL_CURRENT_VERSION = 17;
|
|
128
126
|
// Detect fresh vs existing database by checking if content tables exist.
|
|
129
127
|
// On existing databases, GLOBAL_SCHEMA must NOT run because it references column names
|
|
130
128
|
// (workspace_path) that don't exist until migration v9 renames them from project_path.
|
|
@@ -143,447 +141,14 @@ function ensureGlobalDatabase() {
|
|
|
143
141
|
console.log('[info] Created new global.db at', dbPath);
|
|
144
142
|
return db;
|
|
145
143
|
}
|
|
146
|
-
// Existing database: only run migrations (skip GLOBAL_SCHEMA to avoid column
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
151
|
-
)`);
|
|
152
|
-
// Migration v2: No-op (previously added columns to port_allocations, now removed by Spec 0098)
|
|
153
|
-
const v2 = db.prepare('SELECT version FROM _migrations WHERE version = 2').get();
|
|
154
|
-
if (!v2) {
|
|
155
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (2)').run();
|
|
156
|
-
}
|
|
157
|
-
// Migration v3: Add terminal_sessions table (Spec 0090 TICK-001)
|
|
158
|
-
const v3 = db.prepare('SELECT version FROM _migrations WHERE version = 3').get();
|
|
159
|
-
if (!v3) {
|
|
160
|
-
// Create terminal_sessions table if it doesn't exist
|
|
161
|
-
db.exec(`
|
|
162
|
-
CREATE TABLE IF NOT EXISTS terminal_sessions (
|
|
163
|
-
id TEXT PRIMARY KEY,
|
|
164
|
-
project_path TEXT NOT NULL,
|
|
165
|
-
type TEXT NOT NULL CHECK(type IN ('architect', 'builder', 'shell')),
|
|
166
|
-
role_id TEXT,
|
|
167
|
-
pid INTEGER,
|
|
168
|
-
tmux_session TEXT,
|
|
169
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
170
|
-
);
|
|
171
|
-
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_project ON terminal_sessions(project_path);
|
|
172
|
-
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);
|
|
173
|
-
`);
|
|
174
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (3)').run();
|
|
175
|
-
console.log('[info] Created terminal_sessions table (Spec 0090 TICK-001)');
|
|
176
|
-
}
|
|
177
|
-
// Migration v4: Add file_tabs table (Spec 0099 Phase 4)
|
|
178
|
-
const v4 = db.prepare('SELECT version FROM _migrations WHERE version = 4').get();
|
|
179
|
-
if (!v4) {
|
|
180
|
-
db.exec(`
|
|
181
|
-
CREATE TABLE IF NOT EXISTS file_tabs (
|
|
182
|
-
id TEXT PRIMARY KEY,
|
|
183
|
-
project_path TEXT NOT NULL,
|
|
184
|
-
file_path TEXT NOT NULL,
|
|
185
|
-
created_at INTEGER NOT NULL
|
|
186
|
-
);
|
|
187
|
-
CREATE INDEX IF NOT EXISTS idx_file_tabs_project ON file_tabs(project_path);
|
|
188
|
-
`);
|
|
189
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (4)').run();
|
|
190
|
-
console.log('[info] Created file_tabs table (Spec 0099 Phase 4)');
|
|
191
|
-
}
|
|
192
|
-
// Migration v5: Add known_projects table for persistent project registry
|
|
193
|
-
const v5 = db.prepare('SELECT version FROM _migrations WHERE version = 5').get();
|
|
194
|
-
if (!v5) {
|
|
195
|
-
db.exec(`
|
|
196
|
-
CREATE TABLE IF NOT EXISTS known_projects (
|
|
197
|
-
project_path TEXT PRIMARY KEY,
|
|
198
|
-
name TEXT NOT NULL,
|
|
199
|
-
last_launched_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
200
|
-
);
|
|
201
|
-
`);
|
|
202
|
-
// Seed from existing terminal_sessions so current projects appear immediately
|
|
203
|
-
db.exec(`
|
|
204
|
-
INSERT OR IGNORE INTO known_projects (project_path, name, last_launched_at)
|
|
205
|
-
SELECT DISTINCT project_path, '', datetime('now') FROM terminal_sessions;
|
|
206
|
-
`);
|
|
207
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (5)').run();
|
|
208
|
-
console.log('[info] Created known_projects table');
|
|
209
|
-
}
|
|
210
|
-
// Migration v6: Add shepherd columns to terminal_sessions (Spec 0104)
|
|
211
|
-
const v6 = db.prepare('SELECT version FROM _migrations WHERE version = 6').get();
|
|
212
|
-
if (!v6) {
|
|
213
|
-
const cols = ['shepherd_socket TEXT', 'shepherd_pid INTEGER', 'shepherd_start_time INTEGER'];
|
|
214
|
-
for (const col of cols) {
|
|
215
|
-
try {
|
|
216
|
-
db.exec(`ALTER TABLE terminal_sessions ADD COLUMN ${col}`);
|
|
217
|
-
}
|
|
218
|
-
catch {
|
|
219
|
-
// Column already exists (fresh install ran updated schema)
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (6)').run();
|
|
223
|
-
console.log('[info] Added shepherd columns to terminal_sessions (Spec 0104)');
|
|
224
|
-
}
|
|
225
|
-
// Migration v7: Drop tmux_session column from terminal_sessions (Spec 0104 Phase 4)
|
|
226
|
-
const v7 = db.prepare('SELECT version FROM _migrations WHERE version = 7').get();
|
|
227
|
-
if (!v7) {
|
|
228
|
-
// SQLite table-rebuild pattern to drop the tmux_session column
|
|
229
|
-
try {
|
|
230
|
-
db.exec(`
|
|
231
|
-
CREATE TABLE IF NOT EXISTS terminal_sessions_new (
|
|
232
|
-
id TEXT PRIMARY KEY,
|
|
233
|
-
project_path TEXT NOT NULL,
|
|
234
|
-
type TEXT NOT NULL CHECK(type IN ('architect', 'builder', 'shell')),
|
|
235
|
-
role_id TEXT,
|
|
236
|
-
pid INTEGER,
|
|
237
|
-
shepherd_socket TEXT,
|
|
238
|
-
shepherd_pid INTEGER,
|
|
239
|
-
shepherd_start_time INTEGER,
|
|
240
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
241
|
-
);
|
|
242
|
-
INSERT OR IGNORE INTO terminal_sessions_new
|
|
243
|
-
SELECT id, project_path, type, role_id, pid, shepherd_socket, shepherd_pid, shepherd_start_time, created_at
|
|
244
|
-
FROM terminal_sessions;
|
|
245
|
-
DROP TABLE terminal_sessions;
|
|
246
|
-
ALTER TABLE terminal_sessions_new RENAME TO terminal_sessions;
|
|
247
|
-
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_project ON terminal_sessions(project_path);
|
|
248
|
-
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);
|
|
249
|
-
`);
|
|
250
|
-
}
|
|
251
|
-
catch {
|
|
252
|
-
// Table may already be in the correct schema (fresh install)
|
|
253
|
-
}
|
|
254
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (7)').run();
|
|
255
|
-
console.log('[info] Dropped tmux_session column from terminal_sessions (Spec 0104)');
|
|
256
|
-
}
|
|
257
|
-
// Migration v8: Rename shepherd_* columns to shellper_* (Spec 0106)
|
|
258
|
-
const v8 = db.prepare('SELECT version FROM _migrations WHERE version = 8').get();
|
|
259
|
-
if (!v8) {
|
|
260
|
-
try {
|
|
261
|
-
db.exec(`
|
|
262
|
-
CREATE TABLE IF NOT EXISTS terminal_sessions_new (
|
|
263
|
-
id TEXT PRIMARY KEY,
|
|
264
|
-
project_path TEXT NOT NULL,
|
|
265
|
-
type TEXT NOT NULL CHECK(type IN ('architect', 'builder', 'shell')),
|
|
266
|
-
role_id TEXT,
|
|
267
|
-
pid INTEGER,
|
|
268
|
-
shellper_socket TEXT,
|
|
269
|
-
shellper_pid INTEGER,
|
|
270
|
-
shellper_start_time INTEGER,
|
|
271
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
272
|
-
);
|
|
273
|
-
INSERT OR IGNORE INTO terminal_sessions_new
|
|
274
|
-
SELECT id, project_path, type, role_id, pid, shepherd_socket, shepherd_pid, shepherd_start_time, created_at
|
|
275
|
-
FROM terminal_sessions;
|
|
276
|
-
DROP TABLE terminal_sessions;
|
|
277
|
-
ALTER TABLE terminal_sessions_new RENAME TO terminal_sessions;
|
|
278
|
-
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_project ON terminal_sessions(project_path);
|
|
279
|
-
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);
|
|
280
|
-
UPDATE terminal_sessions SET shellper_socket = REPLACE(shellper_socket, 'shepherd-', 'shellper-')
|
|
281
|
-
WHERE shellper_socket LIKE '%shepherd-%';
|
|
282
|
-
`);
|
|
283
|
-
}
|
|
284
|
-
catch {
|
|
285
|
-
// Table may already be in the correct schema (fresh install)
|
|
286
|
-
}
|
|
287
|
-
// Rename physical socket files on disk
|
|
288
|
-
try {
|
|
289
|
-
const runDir = join(homedir(), '.codev', 'run');
|
|
290
|
-
if (existsSync(runDir)) {
|
|
291
|
-
const files = readdirSync(runDir);
|
|
292
|
-
for (const file of files) {
|
|
293
|
-
if (file.startsWith('shepherd-') && file.endsWith('.sock')) {
|
|
294
|
-
const newName = file.replace('shepherd-', 'shellper-');
|
|
295
|
-
try {
|
|
296
|
-
renameSync(join(runDir, file), join(runDir, newName));
|
|
297
|
-
}
|
|
298
|
-
catch {
|
|
299
|
-
// Skip files that can't be renamed (missing, permissions, etc.)
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
catch {
|
|
306
|
-
// Skip if run directory doesn't exist or can't be read
|
|
307
|
-
}
|
|
308
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (8)').run();
|
|
309
|
-
console.log('[info] Renamed shepherd columns to shellper in terminal_sessions (Spec 0106)');
|
|
310
|
-
}
|
|
311
|
-
// Migration v9: Rename project_path → workspace_path in all tables (Spec 0112)
|
|
312
|
-
// Note: Fresh installs never reach here (handled above), so old column names are guaranteed.
|
|
313
|
-
// Wrapped in a transaction for atomicity — all three renames succeed or none do.
|
|
314
|
-
const v9 = db.prepare('SELECT version FROM _migrations WHERE version = 9').get();
|
|
315
|
-
if (!v9) {
|
|
316
|
-
const migrate = db.transaction(() => {
|
|
317
|
-
// 1. Rename terminal_sessions.project_path → workspace_path
|
|
318
|
-
db.exec(`
|
|
319
|
-
CREATE TABLE IF NOT EXISTS terminal_sessions_new (
|
|
320
|
-
id TEXT PRIMARY KEY,
|
|
321
|
-
workspace_path TEXT NOT NULL,
|
|
322
|
-
type TEXT NOT NULL CHECK(type IN ('architect', 'builder', 'shell')),
|
|
323
|
-
role_id TEXT,
|
|
324
|
-
pid INTEGER,
|
|
325
|
-
shellper_socket TEXT,
|
|
326
|
-
shellper_pid INTEGER,
|
|
327
|
-
shellper_start_time INTEGER,
|
|
328
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
329
|
-
);
|
|
330
|
-
INSERT OR IGNORE INTO terminal_sessions_new
|
|
331
|
-
SELECT id, project_path, type, role_id, pid, shellper_socket, shellper_pid, shellper_start_time, created_at
|
|
332
|
-
FROM terminal_sessions;
|
|
333
|
-
DROP TABLE terminal_sessions;
|
|
334
|
-
ALTER TABLE terminal_sessions_new RENAME TO terminal_sessions;
|
|
335
|
-
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_workspace ON terminal_sessions(workspace_path);
|
|
336
|
-
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);
|
|
337
|
-
`);
|
|
338
|
-
// 2. Rename file_tabs.project_path → workspace_path
|
|
339
|
-
db.exec(`
|
|
340
|
-
CREATE TABLE IF NOT EXISTS file_tabs_new (
|
|
341
|
-
id TEXT PRIMARY KEY,
|
|
342
|
-
workspace_path TEXT NOT NULL,
|
|
343
|
-
file_path TEXT NOT NULL,
|
|
344
|
-
created_at INTEGER NOT NULL
|
|
345
|
-
);
|
|
346
|
-
INSERT OR IGNORE INTO file_tabs_new
|
|
347
|
-
SELECT id, project_path, file_path, created_at
|
|
348
|
-
FROM file_tabs;
|
|
349
|
-
DROP TABLE file_tabs;
|
|
350
|
-
ALTER TABLE file_tabs_new RENAME TO file_tabs;
|
|
351
|
-
CREATE INDEX IF NOT EXISTS idx_file_tabs_workspace ON file_tabs(workspace_path);
|
|
352
|
-
`);
|
|
353
|
-
// 3. Rename known_projects → known_workspaces with project_path → workspace_path
|
|
354
|
-
db.exec(`
|
|
355
|
-
CREATE TABLE IF NOT EXISTS known_workspaces (
|
|
356
|
-
workspace_path TEXT PRIMARY KEY,
|
|
357
|
-
name TEXT NOT NULL,
|
|
358
|
-
last_launched_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
359
|
-
);
|
|
360
|
-
INSERT OR IGNORE INTO known_workspaces (workspace_path, name, last_launched_at)
|
|
361
|
-
SELECT project_path, name, last_launched_at FROM known_projects;
|
|
362
|
-
DROP TABLE IF EXISTS known_projects;
|
|
363
|
-
`);
|
|
364
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (9)').run();
|
|
365
|
-
});
|
|
366
|
-
migrate();
|
|
367
|
-
console.log('[info] Renamed project_path → workspace_path in global tables (Spec 0112)');
|
|
368
|
-
}
|
|
369
|
-
// Migration v10: Add cron_tasks table (Spec 399)
|
|
370
|
-
const v10 = db.prepare('SELECT version FROM _migrations WHERE version = 10').get();
|
|
371
|
-
if (!v10) {
|
|
372
|
-
db.exec(`
|
|
373
|
-
CREATE TABLE IF NOT EXISTS cron_tasks (
|
|
374
|
-
id TEXT PRIMARY KEY,
|
|
375
|
-
workspace_path TEXT NOT NULL,
|
|
376
|
-
task_name TEXT NOT NULL,
|
|
377
|
-
last_run INTEGER,
|
|
378
|
-
last_result TEXT,
|
|
379
|
-
last_output TEXT,
|
|
380
|
-
enabled INTEGER NOT NULL DEFAULT 1,
|
|
381
|
-
UNIQUE(workspace_path, task_name)
|
|
382
|
-
);
|
|
383
|
-
`);
|
|
384
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (10)').run();
|
|
385
|
-
console.log('[info] Created cron_tasks table (Spec 399)');
|
|
386
|
-
}
|
|
387
|
-
// Migration v11: Add label column to terminal_sessions (Spec 468)
|
|
388
|
-
const v11 = db.prepare('SELECT version FROM _migrations WHERE version = 11').get();
|
|
389
|
-
if (!v11) {
|
|
390
|
-
try {
|
|
391
|
-
db.exec(`ALTER TABLE terminal_sessions ADD COLUMN label TEXT`);
|
|
392
|
-
}
|
|
393
|
-
catch {
|
|
394
|
-
// Column may already exist from a fresh install
|
|
395
|
-
}
|
|
396
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (11)').run();
|
|
397
|
-
console.log('[info] Added label column to terminal_sessions (Spec 468)');
|
|
398
|
-
}
|
|
399
|
-
// Migration v12: Add cwd column to terminal_sessions (Bugfix #506)
|
|
400
|
-
const v12 = db.prepare('SELECT version FROM _migrations WHERE version = 12').get();
|
|
401
|
-
if (!v12) {
|
|
402
|
-
try {
|
|
403
|
-
db.exec(`ALTER TABLE terminal_sessions ADD COLUMN cwd TEXT`);
|
|
404
|
-
}
|
|
405
|
-
catch {
|
|
406
|
-
// Column may already exist from a fresh install
|
|
407
|
-
}
|
|
408
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (12)').run();
|
|
409
|
-
console.log('[info] Added cwd column to terminal_sessions (Bugfix #506)');
|
|
410
|
-
}
|
|
411
|
-
// Migration v13: Backfill terminal_sessions.role_id for legacy architect rows (Spec 755)
|
|
412
|
-
// Pre-v13 rows for architects always stored role_id as NULL because there was only
|
|
413
|
-
// ever one architect per workspace. Multi-architect support requires the name to be
|
|
414
|
-
// present in role_id so reconnect can re-key the in-memory map. The idempotent
|
|
415
|
-
// backfill sets role_id = 'main' for legacy rows; subsequent architect rows write
|
|
416
|
-
// their explicit name and are unaffected.
|
|
417
|
-
const v13 = db.prepare('SELECT version FROM _migrations WHERE version = 13').get();
|
|
418
|
-
if (!v13) {
|
|
419
|
-
db.prepare(`
|
|
420
|
-
UPDATE terminal_sessions
|
|
421
|
-
SET role_id = 'main'
|
|
422
|
-
WHERE type = 'architect' AND role_id IS NULL
|
|
423
|
-
`).run();
|
|
424
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (13)').run();
|
|
425
|
-
console.log('[info] Backfilled architect role_id with \'main\' (Spec 755)');
|
|
426
|
-
}
|
|
427
|
-
// Migration v14: Absorb the retired state.db tables (Issue #1118).
|
|
428
|
-
// Creates architect/builders/utils/annotations in global.db at their final
|
|
429
|
-
// shape. architect/utils/annotations move as-is; builders is RESHAPED with a
|
|
430
|
-
// workspace_path column + composite PK (workspace_path, id) so the same
|
|
431
|
-
// builder id can exist in multiple workspaces. Idempotent via
|
|
432
|
-
// `CREATE TABLE IF NOT EXISTS`. The one-time data migration of legacy
|
|
433
|
-
// state.db files is a separate, marker-gated step run at Tower boot
|
|
434
|
-
// (db/consolidate.ts) — NOT here — so opening global.db never moves data.
|
|
435
|
-
const v14 = db.prepare('SELECT version FROM _migrations WHERE version = 14').get();
|
|
436
|
-
if (!v14) {
|
|
437
|
-
db.exec(`
|
|
438
|
-
CREATE TABLE IF NOT EXISTS architect (
|
|
439
|
-
workspace_path TEXT NOT NULL,
|
|
440
|
-
id TEXT NOT NULL,
|
|
441
|
-
pid INTEGER NOT NULL,
|
|
442
|
-
port INTEGER NOT NULL,
|
|
443
|
-
cmd TEXT NOT NULL,
|
|
444
|
-
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
445
|
-
terminal_id TEXT,
|
|
446
|
-
session_id TEXT,
|
|
447
|
-
PRIMARY KEY (workspace_path, id)
|
|
448
|
-
);
|
|
449
|
-
CREATE INDEX IF NOT EXISTS idx_architect_workspace ON architect(workspace_path);
|
|
450
|
-
|
|
451
|
-
CREATE TABLE IF NOT EXISTS builders (
|
|
452
|
-
workspace_path TEXT NOT NULL,
|
|
453
|
-
id TEXT NOT NULL,
|
|
454
|
-
name TEXT NOT NULL,
|
|
455
|
-
port INTEGER NOT NULL DEFAULT 0,
|
|
456
|
-
pid INTEGER NOT NULL DEFAULT 0,
|
|
457
|
-
status TEXT NOT NULL DEFAULT 'spawning'
|
|
458
|
-
CHECK(status IN ('spawning', 'implementing', 'blocked', 'pr', 'complete')),
|
|
459
|
-
phase TEXT NOT NULL DEFAULT '',
|
|
460
|
-
worktree TEXT NOT NULL,
|
|
461
|
-
branch TEXT NOT NULL,
|
|
462
|
-
type TEXT NOT NULL DEFAULT 'spec'
|
|
463
|
-
CHECK(type IN ('spec', 'task', 'protocol', 'shell', 'worktree', 'bugfix', 'pir')),
|
|
464
|
-
task_text TEXT,
|
|
465
|
-
protocol_name TEXT,
|
|
466
|
-
issue_number TEXT,
|
|
467
|
-
terminal_id TEXT,
|
|
468
|
-
spawned_by_architect TEXT,
|
|
469
|
-
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
470
|
-
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
471
|
-
PRIMARY KEY (workspace_path, id)
|
|
472
|
-
);
|
|
473
|
-
CREATE INDEX IF NOT EXISTS idx_builders_status ON builders(status);
|
|
474
|
-
CREATE INDEX IF NOT EXISTS idx_builders_port ON builders(port);
|
|
475
|
-
CREATE TRIGGER IF NOT EXISTS builders_updated_at
|
|
476
|
-
AFTER UPDATE ON builders
|
|
477
|
-
FOR EACH ROW
|
|
478
|
-
BEGIN
|
|
479
|
-
UPDATE builders SET updated_at = datetime('now')
|
|
480
|
-
WHERE workspace_path = NEW.workspace_path AND id = NEW.id;
|
|
481
|
-
END;
|
|
482
|
-
|
|
483
|
-
CREATE TABLE IF NOT EXISTS utils (
|
|
484
|
-
id TEXT PRIMARY KEY,
|
|
485
|
-
name TEXT NOT NULL,
|
|
486
|
-
port INTEGER NOT NULL DEFAULT 0,
|
|
487
|
-
pid INTEGER NOT NULL DEFAULT 0,
|
|
488
|
-
terminal_id TEXT,
|
|
489
|
-
started_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
490
|
-
);
|
|
491
|
-
|
|
492
|
-
CREATE TABLE IF NOT EXISTS annotations (
|
|
493
|
-
id TEXT PRIMARY KEY,
|
|
494
|
-
file TEXT NOT NULL,
|
|
495
|
-
port INTEGER NOT NULL DEFAULT 0,
|
|
496
|
-
pid INTEGER NOT NULL DEFAULT 0,
|
|
497
|
-
parent_type TEXT NOT NULL CHECK(parent_type IN ('architect', 'builder', 'util')),
|
|
498
|
-
parent_id TEXT,
|
|
499
|
-
started_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
500
|
-
);
|
|
501
|
-
`);
|
|
502
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (14)').run();
|
|
503
|
-
console.log('[info] Absorbed state.db tables into global.db (Issue #1118)');
|
|
504
|
-
}
|
|
505
|
-
// Migration v15: Add mailbox table (Spec 1313 — mailbox-first delivery).
|
|
506
|
-
// Additive new table: every `afx send` is persisted here before the send
|
|
507
|
-
// response returns, so nothing is lost to a Tower crash/restart/shutdown.
|
|
508
|
-
// Rows address AGENTS (to_agent), not PTYs, so a respawned terminal drains its
|
|
509
|
-
// predecessor's mail. No rows to migrate — the retired SendBuffer was in-memory.
|
|
510
|
-
// Idempotent via CREATE TABLE / CREATE INDEX IF NOT EXISTS (fresh installs
|
|
511
|
-
// already created it from GLOBAL_SCHEMA and reach the marker as a no-op).
|
|
512
|
-
const v15 = db.prepare('SELECT version FROM _migrations WHERE version = 15').get();
|
|
513
|
-
if (!v15) {
|
|
514
|
-
db.exec(`
|
|
515
|
-
CREATE TABLE IF NOT EXISTS mailbox (
|
|
516
|
-
id TEXT PRIMARY KEY,
|
|
517
|
-
workspace_path TEXT NOT NULL,
|
|
518
|
-
to_agent TEXT NOT NULL,
|
|
519
|
-
terminal_id TEXT,
|
|
520
|
-
from_agent TEXT,
|
|
521
|
-
from_workspace TEXT,
|
|
522
|
-
body TEXT NOT NULL,
|
|
523
|
-
formatted_message TEXT NOT NULL,
|
|
524
|
-
no_enter INTEGER NOT NULL DEFAULT 0,
|
|
525
|
-
status TEXT NOT NULL DEFAULT 'held'
|
|
526
|
-
CHECK(status IN ('held', 'delivered', 'superseded', 'dismissed')),
|
|
527
|
-
reason TEXT CHECK(reason IN ('busy', 'no-profile', 'no-live-pty')),
|
|
528
|
-
supersede_key TEXT,
|
|
529
|
-
escalated INTEGER NOT NULL DEFAULT 0,
|
|
530
|
-
created_at INTEGER NOT NULL,
|
|
531
|
-
updated_at INTEGER NOT NULL,
|
|
532
|
-
resolved_at INTEGER
|
|
533
|
-
);
|
|
534
|
-
CREATE INDEX IF NOT EXISTS idx_mailbox_workspace_status ON mailbox(workspace_path, status);
|
|
535
|
-
CREATE INDEX IF NOT EXISTS idx_mailbox_agent_drain ON mailbox(workspace_path, to_agent, status);
|
|
536
|
-
CREATE INDEX IF NOT EXISTS idx_mailbox_supersede ON mailbox(supersede_key);
|
|
537
|
-
`);
|
|
538
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (15)').run();
|
|
539
|
-
console.log('[info] Created mailbox table (Spec 1313)');
|
|
540
|
-
}
|
|
541
|
-
// Migration v16: Add command column to terminal_sessions (Spec 1313).
|
|
542
|
-
// The render-gate resolves an agent's classifier profile from its launch
|
|
543
|
-
// command (PtySession.command). Shellper-backed sessions were created with
|
|
544
|
-
// command: '' and the profile fell back to reading `.builder-start.sh` —
|
|
545
|
-
// which only builder worktrees have. Architects run in the workspace root
|
|
546
|
-
// (no launch script), so they never resolved and every `afx send architect`
|
|
547
|
-
// held `no-profile`. Persisting the command lets the reconcile/reconnect
|
|
548
|
-
// paths restore identity after a Tower restart, so architects resolve
|
|
549
|
-
// directly and survive restart (builders keep the launch-script backstop).
|
|
550
|
-
// Mirrors the label (v11) / cwd (v12) column adds.
|
|
551
|
-
const v16 = db.prepare('SELECT version FROM _migrations WHERE version = 16').get();
|
|
552
|
-
if (!v16) {
|
|
553
|
-
// Only skip the ALTER when the column genuinely exists already (fresh install
|
|
554
|
-
// ran GLOBAL_SCHEMA). A blanket try/catch would let a REAL alter failure be
|
|
555
|
-
// recorded as "migrated" — and since saveTerminalSession's INSERT now names
|
|
556
|
-
// `command`, every future write would then fail against a table missing it.
|
|
557
|
-
const hasCommand = db.prepare(`PRAGMA table_info(terminal_sessions)`).all()
|
|
558
|
-
.some((c) => c.name === 'command');
|
|
559
|
-
if (!hasCommand) {
|
|
560
|
-
db.exec(`ALTER TABLE terminal_sessions ADD COLUMN command TEXT`);
|
|
561
|
-
}
|
|
562
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (16)').run();
|
|
563
|
-
console.log('[info] Added command column to terminal_sessions (Spec 1313 restart-safe render-gate identity)');
|
|
564
|
-
}
|
|
565
|
-
// Migration v17: Add not_before column to mailbox (Spec 1313 round 3 — durable `--delay`).
|
|
566
|
-
// `afx send --delay` now persists its row at REQUEST time with not_before = now + delay*1000
|
|
567
|
-
// and defers delivery through the render gate, so a delayed send survives a Tower restart
|
|
568
|
-
// (the conscious reversal of Spec 1307's drop-on-restart semantics). A row is deliverable
|
|
569
|
-
// only when `not_before IS NULL OR not_before <= now`; null means deliver-ASAP (every
|
|
570
|
-
// pre-round-3 row). PRAGMA-gated ADD COLUMN mirroring v16 — a blanket try/catch would let a
|
|
571
|
-
// real ALTER failure be recorded as "migrated" and every subsequent mailbox insert (which
|
|
572
|
-
// now names not_before) would then fail against a table missing it. Do NOT edit v15 in place:
|
|
573
|
-
// dev machines on this branch already applied it, so the column must arrive as its own step.
|
|
574
|
-
const v17 = db.prepare('SELECT version FROM _migrations WHERE version = 17').get();
|
|
575
|
-
if (!v17) {
|
|
576
|
-
const hasNotBefore = db.prepare(`PRAGMA table_info(mailbox)`).all()
|
|
577
|
-
.some((c) => c.name === 'not_before');
|
|
578
|
-
if (!hasNotBefore) {
|
|
579
|
-
db.exec(`ALTER TABLE mailbox ADD COLUMN not_before INTEGER`);
|
|
580
|
-
}
|
|
581
|
-
db.prepare('INSERT INTO _migrations (version) VALUES (17)').run();
|
|
582
|
-
console.log('[info] Added not_before column to mailbox (Spec 1313 durable --delay)');
|
|
583
|
-
}
|
|
144
|
+
// Existing database: only run migrations (skip GLOBAL_SCHEMA to avoid column
|
|
145
|
+
// name conflicts). The migration sequence itself lives in db/migrations.ts so
|
|
146
|
+
// production init and the migration tests drive the same runner (Issue #1476).
|
|
147
|
+
runGlobalMigrations(db);
|
|
584
148
|
return db;
|
|
585
149
|
}
|
|
586
150
|
// Re-export types and utilities
|
|
587
151
|
export { LOCAL_SCHEMA, GLOBAL_SCHEMA } from './schema.js';
|
|
588
152
|
export { withRetry } from './errors.js';
|
|
153
|
+
export { GLOBAL_CURRENT_VERSION, runGlobalMigrations } from './migrations.js';
|
|
589
154
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent-farm/db/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent-farm/db/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* that is still `held`.
|
|
22
22
|
*/
|
|
23
23
|
import type Database from 'better-sqlite3';
|
|
24
|
-
import type { DbMailbox, MailboxReason } from './types.js';
|
|
24
|
+
import type { DbMailbox, MailboxGateDetail, MailboxReason } from './types.js';
|
|
25
25
|
/**
|
|
26
26
|
* Fields a caller supplies to persist a new held row. The repository fills in the
|
|
27
27
|
* id, `held` status, `escalated=0`, and the timestamps.
|
|
@@ -126,13 +126,32 @@ export declare function heldSummaryForWorkspace(db: Database.Database, workspace
|
|
|
126
126
|
*/
|
|
127
127
|
export declare function markDelivered(db: Database.Database, id: string, now?: number): boolean;
|
|
128
128
|
/**
|
|
129
|
-
* Refresh the why-held `reason` on a still-held row
|
|
130
|
-
* `afx inbox
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* gate verdict (e.g. `busy` → `no-live-pty`
|
|
129
|
+
* Refresh the why-held verdict — `reason` AND its gate `detail` — on a still-held row
|
|
130
|
+
* (informational: the values `afx inbox`, the send response, the escalation broadcast and the
|
|
131
|
+
* owner starvation notice report). Only touches `held` rows, so it can never relabel or
|
|
132
|
+
* resurrect a terminal row. Returns true if a held row was updated. The delivery pass calls
|
|
133
|
+
* this so a held row's verdict tracks the current gate verdict (e.g. `busy` → `no-live-pty`
|
|
134
|
+
* when the terminal dies).
|
|
135
|
+
*
|
|
136
|
+
* ONE statement, not two (Issue #1482): the pair is a single verdict, and writing it in two
|
|
137
|
+
* updates would leave a window — and a second `updated_at` bump — where a reader could see a
|
|
138
|
+
* new reason beside the previous reason's detail. Callers that hold for a NON-gate cause pass
|
|
139
|
+
* `detail: null` so a stale detail can never outlive the verdict that produced it.
|
|
140
|
+
*
|
|
141
|
+
* `updated_at` therefore keeps meaning "when this row's verdict last MOVED", and that is
|
|
142
|
+
* enforced HERE, by the `(reason IS NOT ? OR detail IS NOT ?)` predicate — not merely by the
|
|
143
|
+
* callers that happen to check first. The delivery pass does guard before calling (see
|
|
144
|
+
* `mailbox-delivery.ts`), but a guard living only at the call site is one new caller away from
|
|
145
|
+
* silently breaking the starvation notice, which reads elapsed time off `updated_at` to say how
|
|
146
|
+
* long a composer has been occupied. `IS NOT` rather than `<>` because both columns are
|
|
147
|
+
* nullable and SQL's `<>` is not null-safe: `NULL <> NULL` is NULL, not false, so a
|
|
148
|
+
* `null`→`null` no-op would slip through the predicate and bump the timestamp anyway.
|
|
149
|
+
*
|
|
150
|
+
* Returns true only when a held row's verdict actually moved. A repeat of the same pair, a
|
|
151
|
+
* terminal row, and an unknown id are all `false` — callers wanting "does this row exist"
|
|
152
|
+
* should ask {@link getById}, not this.
|
|
134
153
|
*/
|
|
135
|
-
export declare function
|
|
154
|
+
export declare function setHeldVerdict(db: Database.Database, id: string, reason: MailboxReason | null, detail: MailboxGateDetail | null, now?: number): boolean;
|
|
136
155
|
/**
|
|
137
156
|
* Flag a still-held row as escalated — **visibility only, NEVER affects delivery**. The
|
|
138
157
|
* drainer's escalation pass calls this when a row crosses the escalation age, then emits
|
|
@@ -141,6 +160,20 @@ export declare function setHeldReason(db: Database.Database, id: string, reason:
|
|
|
141
160
|
* row is untouched. Returns true if it flipped.
|
|
142
161
|
*/
|
|
143
162
|
export declare function markEscalated(db: Database.Database, id: string, now?: number): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* Flag an already-DELIVERED row as escalated (Issue #1584) — visibility only, and the
|
|
165
|
+
* counterpart to {@link markEscalated} for the one case that flags a row *after* it has left
|
|
166
|
+
* the held set: a delivery whose write completed but whose echo never confirmed.
|
|
167
|
+
*
|
|
168
|
+
* A separate function rather than a relaxed guard on {@link markEscalated}, because that one's
|
|
169
|
+
* held-only contract is what makes the drainer's escalation pass safe to call blindly. Here the
|
|
170
|
+
* ordering is the point: the row is marked `delivered` FIRST (that commit is what makes the
|
|
171
|
+
* write un-repeatable even across a crash), so by the time the verdict is known the held-only
|
|
172
|
+
* guard would silently no-op and the flag would be lost.
|
|
173
|
+
*
|
|
174
|
+
* Delivered-only and idempotent (the `escalated = 0` guard). Returns true if it flipped.
|
|
175
|
+
*/
|
|
176
|
+
export declare function markEscalatedDelivered(db: Database.Database, id: string, now?: number): boolean;
|
|
144
177
|
/**
|
|
145
178
|
* Supersede-key prefix for architect starvation notices (Spec 1313 round 3, change 3). A
|
|
146
179
|
* notice row carries `${NOTICE_SUPERSEDE_PREFIX}<starving-agent>` so (a) one pending notice
|
|
@@ -163,6 +196,13 @@ export interface StarvingAgent {
|
|
|
163
196
|
count: number;
|
|
164
197
|
/** Representative why-held reason (held rows for one agent share the gate's verdict). */
|
|
165
198
|
reason: MailboxReason | null;
|
|
199
|
+
/**
|
|
200
|
+
* Representative gate detail beside {@link reason} (Issue #1482) — the same MAX() aggregate,
|
|
201
|
+
* for the same reason: an agent's held rows all carry the verdict of the last delivery pass.
|
|
202
|
+
* It is what lets the owner starvation notice distinguish "a human is at the composer" from
|
|
203
|
+
* "the classifier cannot verify this composer", which have different remedies.
|
|
204
|
+
*/
|
|
205
|
+
detail: MailboxGateDetail | null;
|
|
166
206
|
}
|
|
167
207
|
/**
|
|
168
208
|
* Per-agent view of currently-STARVING mail (Spec 1313 round 3, change 3): agents with at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mailbox.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/db/mailbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"mailbox.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/db/mailbox.ts"],"names":[],"mappings":"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"}
|