@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
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* global.db forward-only migrations (Issue #1476).
|
|
3
|
+
*
|
|
4
|
+
* The migration sequence used to live inline inside the private
|
|
5
|
+
* `ensureGlobalDatabase()` path in `db/index.ts`, so migration tests could only
|
|
6
|
+
* drive hand-maintained *replicas* of it. This module is the single source of
|
|
7
|
+
* truth both production init and the tests call:
|
|
8
|
+
*
|
|
9
|
+
* - `ensureGlobalDatabase()` calls `runGlobalMigrations(db)` on an existing
|
|
10
|
+
* database (fresh installs get the final shape from GLOBAL_SCHEMA and stamp
|
|
11
|
+
* every marker up to `GLOBAL_CURRENT_VERSION` instead).
|
|
12
|
+
* - `__tests__/spec-1313-migration.test.ts` builds a database at a historical
|
|
13
|
+
* version and calls the very same function, so the SQL under test is the SQL
|
|
14
|
+
* that ships.
|
|
15
|
+
*
|
|
16
|
+
* The runner takes an explicit `db` handle (matching `db/mailbox.ts` /
|
|
17
|
+
* `db/consolidate.ts`) — it never opens a connection, reads a singleton, or sets
|
|
18
|
+
* pragmas. Every step is idempotent and gated on its `_migrations` marker, so
|
|
19
|
+
* calling it repeatedly on the same handle is a no-op. Migrations are
|
|
20
|
+
* forward-only by project convention; there is no reverse SQL.
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync, readdirSync, renameSync } from 'node:fs';
|
|
23
|
+
import { homedir } from 'node:os';
|
|
24
|
+
import { join } from 'node:path';
|
|
25
|
+
/** Current migration version — bump when adding new migrations. */
|
|
26
|
+
export const GLOBAL_CURRENT_VERSION = 18;
|
|
27
|
+
/**
|
|
28
|
+
* Run every outstanding global.db migration against `db`.
|
|
29
|
+
*
|
|
30
|
+
* Safe to call on any existing database that reached its recorded version through
|
|
31
|
+
* migrations: each step checks its own `_migrations` marker first, so applied steps
|
|
32
|
+
* are skipped and the call converges on the `GLOBAL_CURRENT_VERSION` shape.
|
|
33
|
+
*
|
|
34
|
+
* NOT for a fresh database. A GLOBAL_SCHEMA-shaped database with no markers would run
|
|
35
|
+
* v5 against the long-renamed `terminal_sessions.project_path` — which is why
|
|
36
|
+
* `ensureGlobalDatabase()` stamps every marker on the fresh path instead of running
|
|
37
|
+
* the chain. That shape is rejected at entry with a named error rather than an opaque
|
|
38
|
+
* mid-chain SQLite failure.
|
|
39
|
+
*
|
|
40
|
+
* @throws if the database carries the post-v9 `workspace_path` shape without the v9
|
|
41
|
+
* marker to match (a fresh schema that never walked the chain).
|
|
42
|
+
*/
|
|
43
|
+
export function runGlobalMigrations(db, options = {}) {
|
|
44
|
+
const log = options.log ?? ((message) => console.log(message));
|
|
45
|
+
const runDir = options.runDir ?? join(homedir(), '.codev', 'run');
|
|
46
|
+
// Ensure _migrations table exists for tracking
|
|
47
|
+
db.exec(`CREATE TABLE IF NOT EXISTS _migrations (
|
|
48
|
+
version INTEGER PRIMARY KEY,
|
|
49
|
+
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
50
|
+
)`);
|
|
51
|
+
// Precondition. Steps v5/v7/v8/v9 read and rebuild the project_path-era tables, so
|
|
52
|
+
// the chain only makes sense on a database that reached its recorded version through
|
|
53
|
+
// migrations. A fresh GLOBAL_SCHEMA database with no markers would instead die at v5
|
|
54
|
+
// with an opaque `no such column: project_path` — so name that shape here. Production
|
|
55
|
+
// never reaches this (ensureGlobalDatabase stamps every marker on the fresh path); it
|
|
56
|
+
// exists because the runner is now callable from anywhere.
|
|
57
|
+
const terminalSessions = db
|
|
58
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='terminal_sessions'")
|
|
59
|
+
.get();
|
|
60
|
+
if (terminalSessions) {
|
|
61
|
+
const renamed = db.prepare(`PRAGMA table_info(terminal_sessions)`).all()
|
|
62
|
+
.some((c) => c.name === 'workspace_path');
|
|
63
|
+
const v9Marker = db.prepare('SELECT version FROM _migrations WHERE version = 9').get();
|
|
64
|
+
if (renamed && !v9Marker) {
|
|
65
|
+
throw new Error('runGlobalMigrations: refusing to run on a database whose terminal_sessions is already ' +
|
|
66
|
+
'workspace_path-shaped but has no v9 migration marker. This is a fresh GLOBAL_SCHEMA ' +
|
|
67
|
+
'database that never walked the chain — stamp markers 1..GLOBAL_CURRENT_VERSION instead ' +
|
|
68
|
+
'(see ensureGlobalDatabase), or the chain will fail mid-way on renamed columns.');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Migration v2: No-op (previously added columns to port_allocations, now removed by Spec 0098)
|
|
72
|
+
const v2 = db.prepare('SELECT version FROM _migrations WHERE version = 2').get();
|
|
73
|
+
if (!v2) {
|
|
74
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (2)').run();
|
|
75
|
+
}
|
|
76
|
+
// Migration v3: Add terminal_sessions table (Spec 0090 TICK-001)
|
|
77
|
+
const v3 = db.prepare('SELECT version FROM _migrations WHERE version = 3').get();
|
|
78
|
+
if (!v3) {
|
|
79
|
+
// Create terminal_sessions table if it doesn't exist
|
|
80
|
+
db.exec(`
|
|
81
|
+
CREATE TABLE IF NOT EXISTS terminal_sessions (
|
|
82
|
+
id TEXT PRIMARY KEY,
|
|
83
|
+
project_path TEXT NOT NULL,
|
|
84
|
+
type TEXT NOT NULL CHECK(type IN ('architect', 'builder', 'shell')),
|
|
85
|
+
role_id TEXT,
|
|
86
|
+
pid INTEGER,
|
|
87
|
+
tmux_session TEXT,
|
|
88
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
89
|
+
);
|
|
90
|
+
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_project ON terminal_sessions(project_path);
|
|
91
|
+
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);
|
|
92
|
+
`);
|
|
93
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (3)').run();
|
|
94
|
+
log('[info] Created terminal_sessions table (Spec 0090 TICK-001)');
|
|
95
|
+
}
|
|
96
|
+
// Migration v4: Add file_tabs table (Spec 0099 Phase 4)
|
|
97
|
+
const v4 = db.prepare('SELECT version FROM _migrations WHERE version = 4').get();
|
|
98
|
+
if (!v4) {
|
|
99
|
+
db.exec(`
|
|
100
|
+
CREATE TABLE IF NOT EXISTS file_tabs (
|
|
101
|
+
id TEXT PRIMARY KEY,
|
|
102
|
+
project_path TEXT NOT NULL,
|
|
103
|
+
file_path TEXT NOT NULL,
|
|
104
|
+
created_at INTEGER NOT NULL
|
|
105
|
+
);
|
|
106
|
+
CREATE INDEX IF NOT EXISTS idx_file_tabs_project ON file_tabs(project_path);
|
|
107
|
+
`);
|
|
108
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (4)').run();
|
|
109
|
+
log('[info] Created file_tabs table (Spec 0099 Phase 4)');
|
|
110
|
+
}
|
|
111
|
+
// Migration v5: Add known_projects table for persistent project registry
|
|
112
|
+
const v5 = db.prepare('SELECT version FROM _migrations WHERE version = 5').get();
|
|
113
|
+
if (!v5) {
|
|
114
|
+
db.exec(`
|
|
115
|
+
CREATE TABLE IF NOT EXISTS known_projects (
|
|
116
|
+
project_path TEXT PRIMARY KEY,
|
|
117
|
+
name TEXT NOT NULL,
|
|
118
|
+
last_launched_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
119
|
+
);
|
|
120
|
+
`);
|
|
121
|
+
// Seed from existing terminal_sessions so current projects appear immediately
|
|
122
|
+
db.exec(`
|
|
123
|
+
INSERT OR IGNORE INTO known_projects (project_path, name, last_launched_at)
|
|
124
|
+
SELECT DISTINCT project_path, '', datetime('now') FROM terminal_sessions;
|
|
125
|
+
`);
|
|
126
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (5)').run();
|
|
127
|
+
log('[info] Created known_projects table');
|
|
128
|
+
}
|
|
129
|
+
// Migration v6: Add shepherd columns to terminal_sessions (Spec 0104)
|
|
130
|
+
const v6 = db.prepare('SELECT version FROM _migrations WHERE version = 6').get();
|
|
131
|
+
if (!v6) {
|
|
132
|
+
const cols = ['shepherd_socket TEXT', 'shepherd_pid INTEGER', 'shepherd_start_time INTEGER'];
|
|
133
|
+
for (const col of cols) {
|
|
134
|
+
try {
|
|
135
|
+
db.exec(`ALTER TABLE terminal_sessions ADD COLUMN ${col}`);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// Column already exists (fresh install ran updated schema)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (6)').run();
|
|
142
|
+
log('[info] Added shepherd columns to terminal_sessions (Spec 0104)');
|
|
143
|
+
}
|
|
144
|
+
// Migration v7: Drop tmux_session column from terminal_sessions (Spec 0104 Phase 4)
|
|
145
|
+
const v7 = db.prepare('SELECT version FROM _migrations WHERE version = 7').get();
|
|
146
|
+
if (!v7) {
|
|
147
|
+
// SQLite table-rebuild pattern to drop the tmux_session column
|
|
148
|
+
try {
|
|
149
|
+
db.exec(`
|
|
150
|
+
CREATE TABLE IF NOT EXISTS terminal_sessions_new (
|
|
151
|
+
id TEXT PRIMARY KEY,
|
|
152
|
+
project_path TEXT NOT NULL,
|
|
153
|
+
type TEXT NOT NULL CHECK(type IN ('architect', 'builder', 'shell')),
|
|
154
|
+
role_id TEXT,
|
|
155
|
+
pid INTEGER,
|
|
156
|
+
shepherd_socket TEXT,
|
|
157
|
+
shepherd_pid INTEGER,
|
|
158
|
+
shepherd_start_time INTEGER,
|
|
159
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
160
|
+
);
|
|
161
|
+
INSERT OR IGNORE INTO terminal_sessions_new
|
|
162
|
+
SELECT id, project_path, type, role_id, pid, shepherd_socket, shepherd_pid, shepherd_start_time, created_at
|
|
163
|
+
FROM terminal_sessions;
|
|
164
|
+
DROP TABLE terminal_sessions;
|
|
165
|
+
ALTER TABLE terminal_sessions_new RENAME TO terminal_sessions;
|
|
166
|
+
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_project ON terminal_sessions(project_path);
|
|
167
|
+
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);
|
|
168
|
+
`);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Table may already be in the correct schema (fresh install)
|
|
172
|
+
}
|
|
173
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (7)').run();
|
|
174
|
+
log('[info] Dropped tmux_session column from terminal_sessions (Spec 0104)');
|
|
175
|
+
}
|
|
176
|
+
// Migration v8: Rename shepherd_* columns to shellper_* (Spec 0106)
|
|
177
|
+
const v8 = db.prepare('SELECT version FROM _migrations WHERE version = 8').get();
|
|
178
|
+
if (!v8) {
|
|
179
|
+
try {
|
|
180
|
+
db.exec(`
|
|
181
|
+
CREATE TABLE IF NOT EXISTS terminal_sessions_new (
|
|
182
|
+
id TEXT PRIMARY KEY,
|
|
183
|
+
project_path TEXT NOT NULL,
|
|
184
|
+
type TEXT NOT NULL CHECK(type IN ('architect', 'builder', 'shell')),
|
|
185
|
+
role_id TEXT,
|
|
186
|
+
pid INTEGER,
|
|
187
|
+
shellper_socket TEXT,
|
|
188
|
+
shellper_pid INTEGER,
|
|
189
|
+
shellper_start_time INTEGER,
|
|
190
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
191
|
+
);
|
|
192
|
+
INSERT OR IGNORE INTO terminal_sessions_new
|
|
193
|
+
SELECT id, project_path, type, role_id, pid, shepherd_socket, shepherd_pid, shepherd_start_time, created_at
|
|
194
|
+
FROM terminal_sessions;
|
|
195
|
+
DROP TABLE terminal_sessions;
|
|
196
|
+
ALTER TABLE terminal_sessions_new RENAME TO terminal_sessions;
|
|
197
|
+
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_project ON terminal_sessions(project_path);
|
|
198
|
+
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);
|
|
199
|
+
UPDATE terminal_sessions SET shellper_socket = REPLACE(shellper_socket, 'shepherd-', 'shellper-')
|
|
200
|
+
WHERE shellper_socket LIKE '%shepherd-%';
|
|
201
|
+
`);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Table may already be in the correct schema (fresh install)
|
|
205
|
+
}
|
|
206
|
+
// Rename physical socket files on disk
|
|
207
|
+
try {
|
|
208
|
+
if (existsSync(runDir)) {
|
|
209
|
+
const files = readdirSync(runDir);
|
|
210
|
+
for (const file of files) {
|
|
211
|
+
if (file.startsWith('shepherd-') && file.endsWith('.sock')) {
|
|
212
|
+
const newName = file.replace('shepherd-', 'shellper-');
|
|
213
|
+
try {
|
|
214
|
+
renameSync(join(runDir, file), join(runDir, newName));
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// Skip files that can't be renamed (missing, permissions, etc.)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// Skip if run directory doesn't exist or can't be read
|
|
225
|
+
}
|
|
226
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (8)').run();
|
|
227
|
+
log('[info] Renamed shepherd columns to shellper in terminal_sessions (Spec 0106)');
|
|
228
|
+
}
|
|
229
|
+
// Migration v9: Rename project_path → workspace_path in all tables (Spec 0112)
|
|
230
|
+
// Note: Fresh installs never reach here (handled by the caller), so old column
|
|
231
|
+
// names are guaranteed.
|
|
232
|
+
// Wrapped in a transaction for atomicity — all three renames succeed or none do.
|
|
233
|
+
const v9 = db.prepare('SELECT version FROM _migrations WHERE version = 9').get();
|
|
234
|
+
if (!v9) {
|
|
235
|
+
const migrate = db.transaction(() => {
|
|
236
|
+
// 1. Rename terminal_sessions.project_path → workspace_path
|
|
237
|
+
db.exec(`
|
|
238
|
+
CREATE TABLE IF NOT EXISTS terminal_sessions_new (
|
|
239
|
+
id TEXT PRIMARY KEY,
|
|
240
|
+
workspace_path TEXT NOT NULL,
|
|
241
|
+
type TEXT NOT NULL CHECK(type IN ('architect', 'builder', 'shell')),
|
|
242
|
+
role_id TEXT,
|
|
243
|
+
pid INTEGER,
|
|
244
|
+
shellper_socket TEXT,
|
|
245
|
+
shellper_pid INTEGER,
|
|
246
|
+
shellper_start_time INTEGER,
|
|
247
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
248
|
+
);
|
|
249
|
+
INSERT OR IGNORE INTO terminal_sessions_new
|
|
250
|
+
SELECT id, project_path, type, role_id, pid, shellper_socket, shellper_pid, shellper_start_time, created_at
|
|
251
|
+
FROM terminal_sessions;
|
|
252
|
+
DROP TABLE terminal_sessions;
|
|
253
|
+
ALTER TABLE terminal_sessions_new RENAME TO terminal_sessions;
|
|
254
|
+
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_workspace ON terminal_sessions(workspace_path);
|
|
255
|
+
CREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);
|
|
256
|
+
`);
|
|
257
|
+
// 2. Rename file_tabs.project_path → workspace_path
|
|
258
|
+
db.exec(`
|
|
259
|
+
CREATE TABLE IF NOT EXISTS file_tabs_new (
|
|
260
|
+
id TEXT PRIMARY KEY,
|
|
261
|
+
workspace_path TEXT NOT NULL,
|
|
262
|
+
file_path TEXT NOT NULL,
|
|
263
|
+
created_at INTEGER NOT NULL
|
|
264
|
+
);
|
|
265
|
+
INSERT OR IGNORE INTO file_tabs_new
|
|
266
|
+
SELECT id, project_path, file_path, created_at
|
|
267
|
+
FROM file_tabs;
|
|
268
|
+
DROP TABLE file_tabs;
|
|
269
|
+
ALTER TABLE file_tabs_new RENAME TO file_tabs;
|
|
270
|
+
CREATE INDEX IF NOT EXISTS idx_file_tabs_workspace ON file_tabs(workspace_path);
|
|
271
|
+
`);
|
|
272
|
+
// 3. Rename known_projects → known_workspaces with project_path → workspace_path
|
|
273
|
+
db.exec(`
|
|
274
|
+
CREATE TABLE IF NOT EXISTS known_workspaces (
|
|
275
|
+
workspace_path TEXT PRIMARY KEY,
|
|
276
|
+
name TEXT NOT NULL,
|
|
277
|
+
last_launched_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
278
|
+
);
|
|
279
|
+
INSERT OR IGNORE INTO known_workspaces (workspace_path, name, last_launched_at)
|
|
280
|
+
SELECT project_path, name, last_launched_at FROM known_projects;
|
|
281
|
+
DROP TABLE IF EXISTS known_projects;
|
|
282
|
+
`);
|
|
283
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (9)').run();
|
|
284
|
+
});
|
|
285
|
+
migrate();
|
|
286
|
+
log('[info] Renamed project_path → workspace_path in global tables (Spec 0112)');
|
|
287
|
+
}
|
|
288
|
+
// Migration v10: Add cron_tasks table (Spec 399)
|
|
289
|
+
const v10 = db.prepare('SELECT version FROM _migrations WHERE version = 10').get();
|
|
290
|
+
if (!v10) {
|
|
291
|
+
db.exec(`
|
|
292
|
+
CREATE TABLE IF NOT EXISTS cron_tasks (
|
|
293
|
+
id TEXT PRIMARY KEY,
|
|
294
|
+
workspace_path TEXT NOT NULL,
|
|
295
|
+
task_name TEXT NOT NULL,
|
|
296
|
+
last_run INTEGER,
|
|
297
|
+
last_result TEXT,
|
|
298
|
+
last_output TEXT,
|
|
299
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
300
|
+
UNIQUE(workspace_path, task_name)
|
|
301
|
+
);
|
|
302
|
+
`);
|
|
303
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (10)').run();
|
|
304
|
+
log('[info] Created cron_tasks table (Spec 399)');
|
|
305
|
+
}
|
|
306
|
+
// Migration v11: Add label column to terminal_sessions (Spec 468)
|
|
307
|
+
const v11 = db.prepare('SELECT version FROM _migrations WHERE version = 11').get();
|
|
308
|
+
if (!v11) {
|
|
309
|
+
try {
|
|
310
|
+
db.exec(`ALTER TABLE terminal_sessions ADD COLUMN label TEXT`);
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
// Column may already exist from a fresh install
|
|
314
|
+
}
|
|
315
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (11)').run();
|
|
316
|
+
log('[info] Added label column to terminal_sessions (Spec 468)');
|
|
317
|
+
}
|
|
318
|
+
// Migration v12: Add cwd column to terminal_sessions (Bugfix #506)
|
|
319
|
+
const v12 = db.prepare('SELECT version FROM _migrations WHERE version = 12').get();
|
|
320
|
+
if (!v12) {
|
|
321
|
+
try {
|
|
322
|
+
db.exec(`ALTER TABLE terminal_sessions ADD COLUMN cwd TEXT`);
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
// Column may already exist from a fresh install
|
|
326
|
+
}
|
|
327
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (12)').run();
|
|
328
|
+
log('[info] Added cwd column to terminal_sessions (Bugfix #506)');
|
|
329
|
+
}
|
|
330
|
+
// Migration v13: Backfill terminal_sessions.role_id for legacy architect rows (Spec 755)
|
|
331
|
+
// Pre-v13 rows for architects always stored role_id as NULL because there was only
|
|
332
|
+
// ever one architect per workspace. Multi-architect support requires the name to be
|
|
333
|
+
// present in role_id so reconnect can re-key the in-memory map. The idempotent
|
|
334
|
+
// backfill sets role_id = 'main' for legacy rows; subsequent architect rows write
|
|
335
|
+
// their explicit name and are unaffected.
|
|
336
|
+
const v13 = db.prepare('SELECT version FROM _migrations WHERE version = 13').get();
|
|
337
|
+
if (!v13) {
|
|
338
|
+
db.prepare(`
|
|
339
|
+
UPDATE terminal_sessions
|
|
340
|
+
SET role_id = 'main'
|
|
341
|
+
WHERE type = 'architect' AND role_id IS NULL
|
|
342
|
+
`).run();
|
|
343
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (13)').run();
|
|
344
|
+
log('[info] Backfilled architect role_id with \'main\' (Spec 755)');
|
|
345
|
+
}
|
|
346
|
+
// Migration v14: Absorb the retired state.db tables (Issue #1118).
|
|
347
|
+
// Creates architect/builders/utils/annotations in global.db at their final
|
|
348
|
+
// shape. architect/utils/annotations move as-is; builders is RESHAPED with a
|
|
349
|
+
// workspace_path column + composite PK (workspace_path, id) so the same
|
|
350
|
+
// builder id can exist in multiple workspaces. Idempotent via
|
|
351
|
+
// `CREATE TABLE IF NOT EXISTS`. The one-time data migration of legacy
|
|
352
|
+
// state.db files is a separate, marker-gated step run at Tower boot
|
|
353
|
+
// (db/consolidate.ts) — NOT here — so opening global.db never moves data.
|
|
354
|
+
const v14 = db.prepare('SELECT version FROM _migrations WHERE version = 14').get();
|
|
355
|
+
if (!v14) {
|
|
356
|
+
db.exec(`
|
|
357
|
+
CREATE TABLE IF NOT EXISTS architect (
|
|
358
|
+
workspace_path TEXT NOT NULL,
|
|
359
|
+
id TEXT NOT NULL,
|
|
360
|
+
pid INTEGER NOT NULL,
|
|
361
|
+
port INTEGER NOT NULL,
|
|
362
|
+
cmd TEXT NOT NULL,
|
|
363
|
+
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
364
|
+
terminal_id TEXT,
|
|
365
|
+
session_id TEXT,
|
|
366
|
+
PRIMARY KEY (workspace_path, id)
|
|
367
|
+
);
|
|
368
|
+
CREATE INDEX IF NOT EXISTS idx_architect_workspace ON architect(workspace_path);
|
|
369
|
+
|
|
370
|
+
CREATE TABLE IF NOT EXISTS builders (
|
|
371
|
+
workspace_path TEXT NOT NULL,
|
|
372
|
+
id TEXT NOT NULL,
|
|
373
|
+
name TEXT NOT NULL,
|
|
374
|
+
port INTEGER NOT NULL DEFAULT 0,
|
|
375
|
+
pid INTEGER NOT NULL DEFAULT 0,
|
|
376
|
+
status TEXT NOT NULL DEFAULT 'spawning'
|
|
377
|
+
CHECK(status IN ('spawning', 'implementing', 'blocked', 'pr', 'complete')),
|
|
378
|
+
phase TEXT NOT NULL DEFAULT '',
|
|
379
|
+
worktree TEXT NOT NULL,
|
|
380
|
+
branch TEXT NOT NULL,
|
|
381
|
+
type TEXT NOT NULL DEFAULT 'spec'
|
|
382
|
+
CHECK(type IN ('spec', 'task', 'protocol', 'shell', 'worktree', 'bugfix', 'pir')),
|
|
383
|
+
task_text TEXT,
|
|
384
|
+
protocol_name TEXT,
|
|
385
|
+
issue_number TEXT,
|
|
386
|
+
terminal_id TEXT,
|
|
387
|
+
spawned_by_architect TEXT,
|
|
388
|
+
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
389
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
390
|
+
PRIMARY KEY (workspace_path, id)
|
|
391
|
+
);
|
|
392
|
+
CREATE INDEX IF NOT EXISTS idx_builders_status ON builders(status);
|
|
393
|
+
CREATE INDEX IF NOT EXISTS idx_builders_port ON builders(port);
|
|
394
|
+
CREATE TRIGGER IF NOT EXISTS builders_updated_at
|
|
395
|
+
AFTER UPDATE ON builders
|
|
396
|
+
FOR EACH ROW
|
|
397
|
+
BEGIN
|
|
398
|
+
UPDATE builders SET updated_at = datetime('now')
|
|
399
|
+
WHERE workspace_path = NEW.workspace_path AND id = NEW.id;
|
|
400
|
+
END;
|
|
401
|
+
|
|
402
|
+
CREATE TABLE IF NOT EXISTS utils (
|
|
403
|
+
id TEXT PRIMARY KEY,
|
|
404
|
+
name TEXT NOT NULL,
|
|
405
|
+
port INTEGER NOT NULL DEFAULT 0,
|
|
406
|
+
pid INTEGER NOT NULL DEFAULT 0,
|
|
407
|
+
terminal_id TEXT,
|
|
408
|
+
started_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
CREATE TABLE IF NOT EXISTS annotations (
|
|
412
|
+
id TEXT PRIMARY KEY,
|
|
413
|
+
file TEXT NOT NULL,
|
|
414
|
+
port INTEGER NOT NULL DEFAULT 0,
|
|
415
|
+
pid INTEGER NOT NULL DEFAULT 0,
|
|
416
|
+
parent_type TEXT NOT NULL CHECK(parent_type IN ('architect', 'builder', 'util')),
|
|
417
|
+
parent_id TEXT,
|
|
418
|
+
started_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
419
|
+
);
|
|
420
|
+
`);
|
|
421
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (14)').run();
|
|
422
|
+
log('[info] Absorbed state.db tables into global.db (Issue #1118)');
|
|
423
|
+
}
|
|
424
|
+
// Migration v15: Add mailbox table (Spec 1313 — mailbox-first delivery).
|
|
425
|
+
// Additive new table: every `afx send` is persisted here before the send
|
|
426
|
+
// response returns, so nothing is lost to a Tower crash/restart/shutdown.
|
|
427
|
+
// Rows address AGENTS (to_agent), not PTYs, so a respawned terminal drains its
|
|
428
|
+
// predecessor's mail. No rows to migrate — the retired SendBuffer was in-memory.
|
|
429
|
+
// Idempotent via CREATE TABLE / CREATE INDEX IF NOT EXISTS (fresh installs
|
|
430
|
+
// already created it from GLOBAL_SCHEMA and reach the marker as a no-op).
|
|
431
|
+
const v15 = db.prepare('SELECT version FROM _migrations WHERE version = 15').get();
|
|
432
|
+
if (!v15) {
|
|
433
|
+
db.exec(`
|
|
434
|
+
CREATE TABLE IF NOT EXISTS mailbox (
|
|
435
|
+
id TEXT PRIMARY KEY,
|
|
436
|
+
workspace_path TEXT NOT NULL,
|
|
437
|
+
to_agent TEXT NOT NULL,
|
|
438
|
+
terminal_id TEXT,
|
|
439
|
+
from_agent TEXT,
|
|
440
|
+
from_workspace TEXT,
|
|
441
|
+
body TEXT NOT NULL,
|
|
442
|
+
formatted_message TEXT NOT NULL,
|
|
443
|
+
no_enter INTEGER NOT NULL DEFAULT 0,
|
|
444
|
+
status TEXT NOT NULL DEFAULT 'held'
|
|
445
|
+
CHECK(status IN ('held', 'delivered', 'superseded', 'dismissed')),
|
|
446
|
+
reason TEXT CHECK(reason IN ('busy', 'no-profile', 'no-live-pty')),
|
|
447
|
+
supersede_key TEXT,
|
|
448
|
+
escalated INTEGER NOT NULL DEFAULT 0,
|
|
449
|
+
created_at INTEGER NOT NULL,
|
|
450
|
+
updated_at INTEGER NOT NULL,
|
|
451
|
+
resolved_at INTEGER
|
|
452
|
+
);
|
|
453
|
+
CREATE INDEX IF NOT EXISTS idx_mailbox_workspace_status ON mailbox(workspace_path, status);
|
|
454
|
+
CREATE INDEX IF NOT EXISTS idx_mailbox_agent_drain ON mailbox(workspace_path, to_agent, status);
|
|
455
|
+
CREATE INDEX IF NOT EXISTS idx_mailbox_supersede ON mailbox(supersede_key);
|
|
456
|
+
`);
|
|
457
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (15)').run();
|
|
458
|
+
log('[info] Created mailbox table (Spec 1313)');
|
|
459
|
+
}
|
|
460
|
+
// Migration v16: Add command column to terminal_sessions (Spec 1313).
|
|
461
|
+
// The render-gate resolves an agent's classifier profile from its launch
|
|
462
|
+
// command (PtySession.command). Shellper-backed sessions were created with
|
|
463
|
+
// command: '' and the profile fell back to reading `.builder-start.sh` —
|
|
464
|
+
// which only builder worktrees have. Architects run in the workspace root
|
|
465
|
+
// (no launch script), so they never resolved and every `afx send architect`
|
|
466
|
+
// held `no-profile`. Persisting the command lets the reconcile/reconnect
|
|
467
|
+
// paths restore identity after a Tower restart, so architects resolve
|
|
468
|
+
// directly and survive restart (builders keep the launch-script backstop).
|
|
469
|
+
// Mirrors the label (v11) / cwd (v12) column adds.
|
|
470
|
+
const v16 = db.prepare('SELECT version FROM _migrations WHERE version = 16').get();
|
|
471
|
+
if (!v16) {
|
|
472
|
+
// Only skip the ALTER when the column genuinely exists already (fresh install
|
|
473
|
+
// ran GLOBAL_SCHEMA). A blanket try/catch would let a REAL alter failure be
|
|
474
|
+
// recorded as "migrated" — and since saveTerminalSession's INSERT now names
|
|
475
|
+
// `command`, every future write would then fail against a table missing it.
|
|
476
|
+
const hasCommand = db.prepare(`PRAGMA table_info(terminal_sessions)`).all()
|
|
477
|
+
.some((c) => c.name === 'command');
|
|
478
|
+
if (!hasCommand) {
|
|
479
|
+
db.exec(`ALTER TABLE terminal_sessions ADD COLUMN command TEXT`);
|
|
480
|
+
}
|
|
481
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (16)').run();
|
|
482
|
+
log('[info] Added command column to terminal_sessions (Spec 1313 restart-safe render-gate identity)');
|
|
483
|
+
}
|
|
484
|
+
// Migration v17: Add not_before column to mailbox (Spec 1313 round 3 — durable `--delay`).
|
|
485
|
+
// `afx send --delay` now persists its row at REQUEST time with not_before = now + delay*1000
|
|
486
|
+
// and defers delivery through the render gate, so a delayed send survives a Tower restart
|
|
487
|
+
// (the conscious reversal of Spec 1307's drop-on-restart semantics). A row is deliverable
|
|
488
|
+
// only when `not_before IS NULL OR not_before <= now`; null means deliver-ASAP (every
|
|
489
|
+
// pre-round-3 row). PRAGMA-gated ADD COLUMN mirroring v16 — a blanket try/catch would let a
|
|
490
|
+
// real ALTER failure be recorded as "migrated" and every subsequent mailbox insert (which
|
|
491
|
+
// now names not_before) would then fail against a table missing it. Do NOT edit v15 in place:
|
|
492
|
+
// dev machines on this branch already applied it, so the column must arrive as its own step.
|
|
493
|
+
const v17 = db.prepare('SELECT version FROM _migrations WHERE version = 17').get();
|
|
494
|
+
if (!v17) {
|
|
495
|
+
const hasNotBefore = db.prepare(`PRAGMA table_info(mailbox)`).all()
|
|
496
|
+
.some((c) => c.name === 'not_before');
|
|
497
|
+
if (!hasNotBefore) {
|
|
498
|
+
db.exec(`ALTER TABLE mailbox ADD COLUMN not_before INTEGER`);
|
|
499
|
+
}
|
|
500
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (17)').run();
|
|
501
|
+
log('[info] Added not_before column to mailbox (Spec 1313 durable --delay)');
|
|
502
|
+
}
|
|
503
|
+
// Migration v18: Add detail column to mailbox (Issue #1482 — the gate verdict's detail).
|
|
504
|
+
// The render gate already distinguishes a legitimately-occupied composer (`user-text` — a
|
|
505
|
+
// human at the line, the safe and intended hold) from a composer it CANNOT verify
|
|
506
|
+
// (`no-region-end`/`no-composer-marker` — a drifted profile, a torn frame, or a dims
|
|
507
|
+
// divergence, which will never clear on its own). That distinction lived only in memory on
|
|
508
|
+
// `DeliveryOutcome.detail`, so every operator surface — `afx inbox`, the send response, the
|
|
509
|
+
// held/escalation logs, the owner starvation notice — showed a bare `busy` for both. The two
|
|
510
|
+
// cases have DIFFERENT remedies, so the row has to carry which one it is.
|
|
511
|
+
//
|
|
512
|
+
// Deliberately NO CHECK constraint, unlike the sibling `reason` column: SQLite cannot add one
|
|
513
|
+
// via ALTER TABLE, so a CHECK present in GLOBAL_SCHEMA and absent here would make a fresh
|
|
514
|
+
// install and an upgraded install structurally different — the exact convergence the
|
|
515
|
+
// migration suite asserts. The value set is enforced in TypeScript (`MailboxGateDetail`).
|
|
516
|
+
// Same PRAGMA-gated ADD COLUMN shape as v16/v17: a blanket try/catch would let a real ALTER
|
|
517
|
+
// failure be recorded as "migrated", and every subsequent mailbox write (which now names
|
|
518
|
+
// `detail`) would then fail against a table missing it.
|
|
519
|
+
const v18 = db.prepare('SELECT version FROM _migrations WHERE version = 18').get();
|
|
520
|
+
if (!v18) {
|
|
521
|
+
const hasDetail = db.prepare(`PRAGMA table_info(mailbox)`).all()
|
|
522
|
+
.some((c) => c.name === 'detail');
|
|
523
|
+
if (!hasDetail) {
|
|
524
|
+
db.exec(`ALTER TABLE mailbox ADD COLUMN detail TEXT`);
|
|
525
|
+
}
|
|
526
|
+
db.prepare('INSERT INTO _migrations (version) VALUES (18)').run();
|
|
527
|
+
log('[info] Added detail column to mailbox (Issue #1482 gate-verdict detail)');
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
//# sourceMappingURL=migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../src/agent-farm/db/migrations.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,5 +19,5 @@ export declare const LOCAL_SCHEMA = "\n-- Schema versioning\nCREATE TABLE IF NOT
|
|
|
19
19
|
* Global registry schema (global.db)
|
|
20
20
|
* Stores terminal sessions and migrations across all workspaces
|
|
21
21
|
*/
|
|
22
|
-
export declare const GLOBAL_SCHEMA = "\n-- Schema versioning\nCREATE TABLE IF NOT EXISTS _migrations (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Terminal sessions (Spec 0090 TICK-001)\n-- Tracks all terminal sessions across all workspaces for persistence and reconciliation\nCREATE TABLE IF NOT EXISTS terminal_sessions (\n id TEXT PRIMARY KEY, -- terminal UUID from PtyManager\n workspace_path TEXT NOT NULL, -- workspace this terminal belongs to\n type TEXT NOT NULL -- 'architect', 'builder', 'shell'\n CHECK(type IN ('architect', 'builder', 'shell')),\n role_id TEXT, -- builder ID or shell ID (null for architect)\n pid INTEGER, -- process ID of the terminal\n shellper_socket TEXT, -- Unix socket path for shellper process\n shellper_pid INTEGER, -- shellper process PID\n shellper_start_time INTEGER, -- shellper process start time (epoch ms)\n label TEXT, -- custom display label (Spec 468)\n cwd TEXT, -- working directory of the terminal (Bugfix #506)\n command TEXT, -- launch command; render-gate identity seam (Spec 1313)\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_terminal_sessions_workspace ON terminal_sessions(workspace_path);\nCREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);\n\n-- File tabs (Spec 0099 Phase 4)\nCREATE TABLE IF NOT EXISTS file_tabs (\n id TEXT PRIMARY KEY,\n workspace_path TEXT NOT NULL,\n file_path TEXT NOT NULL,\n created_at INTEGER NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_file_tabs_workspace ON file_tabs(workspace_path);\n\n-- Known workspaces (persistent workspace registry)\nCREATE TABLE IF NOT EXISTS known_workspaces (\n workspace_path TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n last_launched_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Cron tasks (Spec 399)\n-- Tracks scheduled task state across all workspaces\nCREATE TABLE IF NOT EXISTS cron_tasks (\n id TEXT PRIMARY KEY,\n workspace_path TEXT NOT NULL,\n task_name TEXT NOT NULL,\n last_run INTEGER,\n last_result TEXT,\n last_output TEXT,\n enabled INTEGER NOT NULL DEFAULT 1,\n UNIQUE(workspace_path, task_name)\n);\n\n-- ===========================================================================\n-- Issue #1118: tables absorbed from the retired per-workspace state.db.\n-- architect/utils/annotations move as-is; builders is RESHAPED to be\n-- workspace-scoped (composite PK), mirroring architect (Bugfix #826) \u2014 builder\n-- ids are <protocol>-<issueNumber>, unique within a workspace but reused across\n-- repos, so a single shared table must disambiguate by workspace_path.\n-- ===========================================================================\n\n-- Architect sessions (Spec 755 multi-architect; Bugfix #826 workspace-scoped;\n-- Issue #832 session_id). id is the architect's name ('main', siblings).\nCREATE TABLE IF NOT EXISTS architect (\n workspace_path TEXT NOT NULL,\n id TEXT NOT NULL,\n pid INTEGER NOT NULL,\n port INTEGER NOT NULL,\n cmd TEXT NOT NULL,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n terminal_id TEXT,\n session_id TEXT,\n PRIMARY KEY (workspace_path, id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_architect_workspace ON architect(workspace_path);\n\n-- Builder sessions. Issue #1118: workspace_path + composite PK so the same\n-- builder id can exist in multiple workspaces without collision.\nCREATE TABLE IF NOT EXISTS builders (\n workspace_path TEXT NOT NULL,\n id TEXT NOT NULL,\n name TEXT NOT NULL,\n port INTEGER NOT NULL DEFAULT 0,\n pid INTEGER NOT NULL DEFAULT 0,\n status TEXT NOT NULL DEFAULT 'spawning'\n CHECK(status IN ('spawning', 'implementing', 'blocked', 'pr', 'complete')),\n phase TEXT NOT NULL DEFAULT '',\n worktree TEXT NOT NULL,\n branch TEXT NOT NULL,\n type TEXT NOT NULL DEFAULT 'spec'\n CHECK(type IN ('spec', 'task', 'protocol', 'shell', 'worktree', 'bugfix', 'pir')),\n task_text TEXT,\n protocol_name TEXT,\n issue_number TEXT,\n terminal_id TEXT,\n spawned_by_architect TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (workspace_path, id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_builders_status ON builders(status);\nCREATE INDEX IF NOT EXISTS idx_builders_port ON builders(port);\n\nCREATE TRIGGER IF NOT EXISTS builders_updated_at\n AFTER UPDATE ON builders\n FOR EACH ROW\n BEGIN\n UPDATE builders SET updated_at = datetime('now')\n WHERE workspace_path = NEW.workspace_path AND id = NEW.id;\n END;\n\n-- Utility terminals (UUID-keyed; moved as-is).\nCREATE TABLE IF NOT EXISTS utils (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n port INTEGER NOT NULL DEFAULT 0,\n pid INTEGER NOT NULL DEFAULT 0,\n terminal_id TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Annotations / file viewers (UUID-keyed; moved as-is).\nCREATE TABLE IF NOT EXISTS annotations (\n id TEXT PRIMARY KEY,\n file TEXT NOT NULL,\n port INTEGER NOT NULL DEFAULT 0,\n pid INTEGER NOT NULL DEFAULT 0,\n parent_type TEXT NOT NULL CHECK(parent_type IN ('architect', 'builder', 'util')),\n parent_id TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Mailbox (Spec 1313): durable home for every 'afx send'.\n-- Persist-first delivery \u2014 a row is written before the send response returns, so\n-- nothing is lost to a Tower crash/restart/shutdown (the retired in-memory\n-- SendBuffer lost held messages on both). Rows address AGENTS (to_agent within\n-- workspace_path), not PTYs, so a respawned terminal drains its predecessor's\n-- mail. Delivery is authorized elsewhere by the render-gate (Phases 2/4); this\n-- table is pure durable state. Timestamps are epoch-ms integers (not SQLite\n-- datetime) so ordering and age math are trivial. Additive new table \u2014 fresh\n-- installs get it here; existing installs get it from migration v15.\nCREATE TABLE IF NOT EXISTS mailbox (\n id TEXT PRIMARY KEY, -- uuid\n workspace_path TEXT NOT NULL, -- addressing scope\n to_agent TEXT NOT NULL, -- recipient agent identity (drains across respawn)\n terminal_id TEXT, -- last-known PTY hint (nullable; not the identity)\n from_agent TEXT,\n from_workspace TEXT,\n body TEXT NOT NULL, -- raw message (never logged)\n formatted_message TEXT NOT NULL, -- what gets written to the PTY\n no_enter INTEGER NOT NULL DEFAULT 0,\n status TEXT NOT NULL DEFAULT 'held'\n CHECK(status IN ('held', 'delivered', 'superseded', 'dismissed')),\n reason TEXT CHECK(reason IN ('busy', 'no-profile', 'no-live-pty')), -- why-held; null once delivered\n supersede_key TEXT, -- cron-only; null for direct sends\n escalated INTEGER NOT NULL DEFAULT 0, -- set once escalation age crossed (visibility only)\n not_before INTEGER, -- epoch ms; delayed-send due time (Spec 1313 round 3, --delay). null = deliver ASAP; a row is deliverable only when not_before IS NULL OR not_before <= now\n created_at INTEGER NOT NULL, -- epoch ms (enqueue order per agent)\n updated_at INTEGER NOT NULL,\n resolved_at INTEGER -- delivered/superseded/dismissed timestamp\n);\n\nCREATE INDEX IF NOT EXISTS idx_mailbox_workspace_status ON mailbox(workspace_path, status);\nCREATE INDEX IF NOT EXISTS idx_mailbox_agent_drain ON mailbox(workspace_path, to_agent, status);\nCREATE INDEX IF NOT EXISTS idx_mailbox_supersede ON mailbox(supersede_key);\n";
|
|
22
|
+
export declare const GLOBAL_SCHEMA = "\n-- Schema versioning\nCREATE TABLE IF NOT EXISTS _migrations (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Terminal sessions (Spec 0090 TICK-001)\n-- Tracks all terminal sessions across all workspaces for persistence and reconciliation\nCREATE TABLE IF NOT EXISTS terminal_sessions (\n id TEXT PRIMARY KEY, -- terminal UUID from PtyManager\n workspace_path TEXT NOT NULL, -- workspace this terminal belongs to\n type TEXT NOT NULL -- 'architect', 'builder', 'shell'\n CHECK(type IN ('architect', 'builder', 'shell')),\n role_id TEXT, -- builder ID or shell ID (null for architect)\n pid INTEGER, -- process ID of the terminal\n shellper_socket TEXT, -- Unix socket path for shellper process\n shellper_pid INTEGER, -- shellper process PID\n shellper_start_time INTEGER, -- shellper process start time (epoch ms)\n label TEXT, -- custom display label (Spec 468)\n cwd TEXT, -- working directory of the terminal (Bugfix #506)\n command TEXT, -- launch command; render-gate identity seam (Spec 1313)\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_terminal_sessions_workspace ON terminal_sessions(workspace_path);\nCREATE INDEX IF NOT EXISTS idx_terminal_sessions_type ON terminal_sessions(type);\n\n-- File tabs (Spec 0099 Phase 4)\nCREATE TABLE IF NOT EXISTS file_tabs (\n id TEXT PRIMARY KEY,\n workspace_path TEXT NOT NULL,\n file_path TEXT NOT NULL,\n created_at INTEGER NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_file_tabs_workspace ON file_tabs(workspace_path);\n\n-- Known workspaces (persistent workspace registry)\nCREATE TABLE IF NOT EXISTS known_workspaces (\n workspace_path TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n last_launched_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Cron tasks (Spec 399)\n-- Tracks scheduled task state across all workspaces\nCREATE TABLE IF NOT EXISTS cron_tasks (\n id TEXT PRIMARY KEY,\n workspace_path TEXT NOT NULL,\n task_name TEXT NOT NULL,\n last_run INTEGER,\n last_result TEXT,\n last_output TEXT,\n enabled INTEGER NOT NULL DEFAULT 1,\n UNIQUE(workspace_path, task_name)\n);\n\n-- ===========================================================================\n-- Issue #1118: tables absorbed from the retired per-workspace state.db.\n-- architect/utils/annotations move as-is; builders is RESHAPED to be\n-- workspace-scoped (composite PK), mirroring architect (Bugfix #826) \u2014 builder\n-- ids are <protocol>-<issueNumber>, unique within a workspace but reused across\n-- repos, so a single shared table must disambiguate by workspace_path.\n-- ===========================================================================\n\n-- Architect sessions (Spec 755 multi-architect; Bugfix #826 workspace-scoped;\n-- Issue #832 session_id). id is the architect's name ('main', siblings).\nCREATE TABLE IF NOT EXISTS architect (\n workspace_path TEXT NOT NULL,\n id TEXT NOT NULL,\n pid INTEGER NOT NULL,\n port INTEGER NOT NULL,\n cmd TEXT NOT NULL,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n terminal_id TEXT,\n session_id TEXT,\n PRIMARY KEY (workspace_path, id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_architect_workspace ON architect(workspace_path);\n\n-- Builder sessions. Issue #1118: workspace_path + composite PK so the same\n-- builder id can exist in multiple workspaces without collision.\nCREATE TABLE IF NOT EXISTS builders (\n workspace_path TEXT NOT NULL,\n id TEXT NOT NULL,\n name TEXT NOT NULL,\n port INTEGER NOT NULL DEFAULT 0,\n pid INTEGER NOT NULL DEFAULT 0,\n status TEXT NOT NULL DEFAULT 'spawning'\n CHECK(status IN ('spawning', 'implementing', 'blocked', 'pr', 'complete')),\n phase TEXT NOT NULL DEFAULT '',\n worktree TEXT NOT NULL,\n branch TEXT NOT NULL,\n type TEXT NOT NULL DEFAULT 'spec'\n CHECK(type IN ('spec', 'task', 'protocol', 'shell', 'worktree', 'bugfix', 'pir')),\n task_text TEXT,\n protocol_name TEXT,\n issue_number TEXT,\n terminal_id TEXT,\n spawned_by_architect TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (workspace_path, id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_builders_status ON builders(status);\nCREATE INDEX IF NOT EXISTS idx_builders_port ON builders(port);\n\nCREATE TRIGGER IF NOT EXISTS builders_updated_at\n AFTER UPDATE ON builders\n FOR EACH ROW\n BEGIN\n UPDATE builders SET updated_at = datetime('now')\n WHERE workspace_path = NEW.workspace_path AND id = NEW.id;\n END;\n\n-- Utility terminals (UUID-keyed; moved as-is).\nCREATE TABLE IF NOT EXISTS utils (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n port INTEGER NOT NULL DEFAULT 0,\n pid INTEGER NOT NULL DEFAULT 0,\n terminal_id TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Annotations / file viewers (UUID-keyed; moved as-is).\nCREATE TABLE IF NOT EXISTS annotations (\n id TEXT PRIMARY KEY,\n file TEXT NOT NULL,\n port INTEGER NOT NULL DEFAULT 0,\n pid INTEGER NOT NULL DEFAULT 0,\n parent_type TEXT NOT NULL CHECK(parent_type IN ('architect', 'builder', 'util')),\n parent_id TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Mailbox (Spec 1313): durable home for every 'afx send'.\n-- Persist-first delivery \u2014 a row is written before the send response returns, so\n-- nothing is lost to a Tower crash/restart/shutdown (the retired in-memory\n-- SendBuffer lost held messages on both). Rows address AGENTS (to_agent within\n-- workspace_path), not PTYs, so a respawned terminal drains its predecessor's\n-- mail. Delivery is authorized elsewhere by the render-gate (Phases 2/4); this\n-- table is pure durable state. Timestamps are epoch-ms integers (not SQLite\n-- datetime) so ordering and age math are trivial. Additive new table \u2014 fresh\n-- installs get it here; existing installs get it from migration v15.\nCREATE TABLE IF NOT EXISTS mailbox (\n id TEXT PRIMARY KEY, -- uuid\n workspace_path TEXT NOT NULL, -- addressing scope\n to_agent TEXT NOT NULL, -- recipient agent identity (drains across respawn)\n terminal_id TEXT, -- last-known PTY hint (nullable; not the identity)\n from_agent TEXT,\n from_workspace TEXT,\n body TEXT NOT NULL, -- raw message (never logged)\n formatted_message TEXT NOT NULL, -- what gets written to the PTY\n no_enter INTEGER NOT NULL DEFAULT 0,\n status TEXT NOT NULL DEFAULT 'held'\n CHECK(status IN ('held', 'delivered', 'superseded', 'dismissed')),\n reason TEXT CHECK(reason IN ('busy', 'no-profile', 'no-live-pty')), -- why-held; null once delivered\n detail TEXT, -- Issue #1482: the gate verdict's detail behind a busy hold ('user-text' = a human at the line; 'no-region-end'/'no-composer-marker' = the classifier could not verify). Null for non-gate holds and once delivered. NO CHECK on purpose -- SQLite cannot ALTER one in, so migration v18 could not match it and a fresh install would diverge from an upgraded one; the value set is enforced in TypeScript (MailboxGateDetail)\n supersede_key TEXT, -- cron-only; null for direct sends\n escalated INTEGER NOT NULL DEFAULT 0, -- set once escalation age crossed (visibility only)\n not_before INTEGER, -- epoch ms; delayed-send due time (Spec 1313 round 3, --delay). null = deliver ASAP; a row is deliverable only when not_before IS NULL OR not_before <= now\n created_at INTEGER NOT NULL, -- epoch ms (enqueue order per agent)\n updated_at INTEGER NOT NULL,\n resolved_at INTEGER -- delivered/superseded/dismissed timestamp\n);\n\nCREATE INDEX IF NOT EXISTS idx_mailbox_workspace_status ON mailbox(workspace_path, status);\nCREATE INDEX IF NOT EXISTS idx_mailbox_agent_drain ON mailbox(workspace_path, to_agent, status);\nCREATE INDEX IF NOT EXISTS idx_mailbox_supersede ON mailbox(supersede_key);\n";
|
|
23
23
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/db/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,0gGAqFxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/db/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,0gGAqFxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,wkQA6KzB,CAAC"}
|
|
@@ -265,6 +265,7 @@ CREATE TABLE IF NOT EXISTS mailbox (
|
|
|
265
265
|
status TEXT NOT NULL DEFAULT 'held'
|
|
266
266
|
CHECK(status IN ('held', 'delivered', 'superseded', 'dismissed')),
|
|
267
267
|
reason TEXT CHECK(reason IN ('busy', 'no-profile', 'no-live-pty')), -- why-held; null once delivered
|
|
268
|
+
detail TEXT, -- Issue #1482: the gate verdict's detail behind a busy hold ('user-text' = a human at the line; 'no-region-end'/'no-composer-marker' = the classifier could not verify). Null for non-gate holds and once delivered. NO CHECK on purpose -- SQLite cannot ALTER one in, so migration v18 could not match it and a fresh install would diverge from an upgraded one; the value set is enforced in TypeScript (MailboxGateDetail)
|
|
268
269
|
supersede_key TEXT, -- cron-only; null for direct sends
|
|
269
270
|
escalated INTEGER NOT NULL DEFAULT 0, -- set once escalation age crossed (visibility only)
|
|
270
271
|
not_before INTEGER, -- epoch ms; delayed-send due time (Spec 1313 round 3, --delay). null = deliver ASAP; a row is deliverable only when not_before IS NULL OR not_before <= now
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/agent-farm/db/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqF3B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/agent-farm/db/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqF3B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6K5B,CAAC"}
|
|
@@ -84,6 +84,27 @@ export type MailboxStatus = 'held' | 'delivered' | 'superseded' | 'dismissed';
|
|
|
84
84
|
* - `no-live-pty` — the recipient agent has no live terminal right now
|
|
85
85
|
*/
|
|
86
86
|
export type MailboxReason = 'busy' | 'no-profile' | 'no-live-pty';
|
|
87
|
+
/**
|
|
88
|
+
* The render gate's classification detail behind a `busy` hold (Issue #1482). Persisted
|
|
89
|
+
* beside {@link MailboxReason} so every operator surface can tell the two apart:
|
|
90
|
+
* - `user-text` — a draft or menu occupies the composer. A human is at the line;
|
|
91
|
+
* this is the SAFE, intended hold and it clears when they finish.
|
|
92
|
+
* - `no-region-end` — a composer marker with no rule/status line beneath it to bound
|
|
93
|
+
* the region (a partial/mid-repaint frame, or a mirror rendered at
|
|
94
|
+
* dims the real TUI never adopted).
|
|
95
|
+
* - `no-composer-marker` — no recognized marker at all (a wrapper/boot screen, a drifted
|
|
96
|
+
* profile, or an unrenderable frame).
|
|
97
|
+
* The latter two are the DEFECT class: the classifier could not verify anything, so the mail
|
|
98
|
+
* will not deliver on its own. `GateVerdict.detail`'s fourth value, `empty`, is never persisted
|
|
99
|
+
* — a clean verdict delivers the row (and delivery nulls both columns).
|
|
100
|
+
*
|
|
101
|
+
* Null for every non-gate hold (`no-live-pty`, `no-profile`) and for the post-classify
|
|
102
|
+
* token/settle re-holds, so a stale detail can never outlive the verdict that produced it.
|
|
103
|
+
*
|
|
104
|
+
* The DB column carries NO CHECK constraint (see `GLOBAL_SCHEMA` / migration v18); this type
|
|
105
|
+
* is the enforcement.
|
|
106
|
+
*/
|
|
107
|
+
export type MailboxGateDetail = 'user-text' | 'no-region-end' | 'no-composer-marker';
|
|
87
108
|
/**
|
|
88
109
|
* Database row type for the mailbox table (Spec 1313).
|
|
89
110
|
*
|
|
@@ -105,6 +126,7 @@ export interface DbMailbox {
|
|
|
105
126
|
no_enter: number;
|
|
106
127
|
status: MailboxStatus;
|
|
107
128
|
reason: MailboxReason | null;
|
|
129
|
+
detail: MailboxGateDetail | null;
|
|
108
130
|
supersede_key: string | null;
|
|
109
131
|
escalated: number;
|
|
110
132
|
not_before: number | null;
|