mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-30 03:12:32 +00:00
fix(engines): pre-add v0.27 subagent_messages.provider_id in bootstrap
PR #682 covered v0.20 (chunks) + v0.26.3 (mcp_request_log) but missed v0.27's subagent_messages.provider_id. The composite index `idx_subagent_messages_provider ON subagent_messages (job_id, provider_id)` in PGLITE_SCHEMA_SQL crashes on brains pinned at v0.18-v0.26 because provider_id is the SECOND column in the composite — array-extraction patterns that scan only first-column references miss it entirely. This is the wedge surfaced by issue #670 (v0.22.0 → v0.27.0 init --migrate-only crashes with "column 'provider_id' does not exist") and contributing to #661/#657. Both engines now probe for subagent_messages.provider_id and pre-add the column via ALTER TABLE ADD COLUMN IF NOT EXISTS before SCHEMA_SQL runs. Migration v36 (subagent_provider_neutral_persistence_v0_27) still runs later via runMigrations and remains idempotent. Note on the test side: REQUIRED_BOOTSTRAP_COVERAGE is hand-maintained and just gained a v0.27 entry. v0.28.5's Step 3 replaces this array with a SQL parser that auto-derives coverage from PGLITE_SCHEMA_SQL, including composite-index columns. This commit is the targeted follow-up to PR #682's cherry-pick; A2's parser closes the class permanently. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
68adcb4fa6
commit
1a1dcf6e92
@@ -223,6 +223,8 @@ export class PGLiteEngine implements BrainEngine {
|
||||
* - `pages.deleted_at` column (indexed by `pages_deleted_at_purge_idx`) — v0.26.5
|
||||
* - `mcp_request_log.agent_name` + `params` + `error_message` columns
|
||||
* (indexed by `idx_mcp_log_agent_time`) — v0.26.3
|
||||
* - `subagent_messages.provider_id` column (indexed by
|
||||
* `idx_subagent_messages_provider`) — v0.27
|
||||
*
|
||||
* **Maintenance contract:** when a future migration adds a column-with-index
|
||||
* or new-table-with-FK referenced by PGLITE_SCHEMA_SQL, extend this method
|
||||
@@ -256,7 +258,11 @@ export class PGLiteEngine implements BrainEngine {
|
||||
EXISTS (SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema='public' AND table_name='mcp_request_log') AS mcp_log_exists,
|
||||
EXISTS (SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema='public' AND table_name='mcp_request_log' AND column_name='agent_name') AS agent_name_exists
|
||||
WHERE table_schema='public' AND table_name='mcp_request_log' AND column_name='agent_name') AS agent_name_exists,
|
||||
EXISTS (SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema='public' AND table_name='subagent_messages') AS subagent_messages_exists,
|
||||
EXISTS (SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema='public' AND table_name='subagent_messages' AND column_name='provider_id') AS subagent_provider_id_exists
|
||||
`);
|
||||
const probe = rows[0] as {
|
||||
pages_exists: boolean;
|
||||
@@ -271,6 +277,8 @@ export class PGLiteEngine implements BrainEngine {
|
||||
search_vector_exists: boolean;
|
||||
mcp_log_exists: boolean;
|
||||
agent_name_exists: boolean;
|
||||
subagent_messages_exists: boolean;
|
||||
subagent_provider_id_exists: boolean;
|
||||
};
|
||||
|
||||
const needsPagesBootstrap = probe.pages_exists && !probe.source_id_exists;
|
||||
@@ -281,9 +289,12 @@ export class PGLiteEngine implements BrainEngine {
|
||||
const needsPagesDeletedAt = probe.pages_exists && !probe.deleted_at_exists;
|
||||
// v0.26.3 (v33): idx_mcp_log_agent_time in PGLITE_SCHEMA_SQL needs agent_name col.
|
||||
const needsMcpLogBootstrap = probe.mcp_log_exists && !probe.agent_name_exists;
|
||||
// v0.27 (v36): idx_subagent_messages_provider in PGLITE_SCHEMA_SQL needs
|
||||
// provider_id (the SECOND column in the composite index `(job_id, provider_id)`).
|
||||
const needsSubagentProviderId = probe.subagent_messages_exists && !probe.subagent_provider_id_exists;
|
||||
|
||||
// Fresh installs (no tables yet) and modern brains both no-op.
|
||||
if (!needsPagesBootstrap && !needsLinksBootstrap && !needsChunksBootstrap && !needsPagesDeletedAt && !needsMcpLogBootstrap) return;
|
||||
if (!needsPagesBootstrap && !needsLinksBootstrap && !needsChunksBootstrap && !needsPagesDeletedAt && !needsMcpLogBootstrap && !needsSubagentProviderId) return;
|
||||
|
||||
console.log(' Pre-v0.21 brain detected, applying forward-reference bootstrap');
|
||||
|
||||
@@ -359,6 +370,18 @@ export class PGLiteEngine implements BrainEngine {
|
||||
ALTER TABLE mcp_request_log ADD COLUMN IF NOT EXISTS error_message TEXT;
|
||||
`);
|
||||
}
|
||||
|
||||
if (needsSubagentProviderId) {
|
||||
// v36 (subagent_provider_neutral_persistence_v0_27) adds provider_id +
|
||||
// schema_version on subagent_messages and subagent_tool_executions.
|
||||
// PGLITE_SCHEMA_SQL's `CREATE INDEX idx_subagent_messages_provider ON
|
||||
// subagent_messages (job_id, provider_id)` crashes without provider_id
|
||||
// (composite-index second column). v36 runs later via runMigrations and
|
||||
// is idempotent.
|
||||
await this.db.exec(`
|
||||
ALTER TABLE subagent_messages ADD COLUMN IF NOT EXISTS provider_id TEXT;
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
async withReservedConnection<T>(fn: (conn: ReservedConnection) => Promise<T>): Promise<T> {
|
||||
|
||||
@@ -167,6 +167,8 @@ export class PostgresEngine implements BrainEngine {
|
||||
* - `pages.deleted_at` column (indexed by `pages_deleted_at_purge_idx`) — v0.26.5
|
||||
* - `mcp_request_log.agent_name` + `params` + `error_message` columns
|
||||
* (indexed by `idx_mcp_log_agent_time`) — v0.26.3
|
||||
* - `subagent_messages.provider_id` column (indexed by
|
||||
* `idx_subagent_messages_provider`) — v0.27
|
||||
*
|
||||
* Keep this in sync with the PGLite version; covered by
|
||||
* `test/schema-bootstrap-coverage.test.ts` (PGLite side) and
|
||||
@@ -191,6 +193,8 @@ export class PostgresEngine implements BrainEngine {
|
||||
search_vector_exists: boolean;
|
||||
mcp_log_exists: boolean;
|
||||
agent_name_exists: boolean;
|
||||
subagent_messages_exists: boolean;
|
||||
subagent_provider_id_exists: boolean;
|
||||
}[]>`
|
||||
SELECT
|
||||
EXISTS (SELECT 1 FROM information_schema.tables
|
||||
@@ -216,7 +220,11 @@ export class PostgresEngine implements BrainEngine {
|
||||
EXISTS (SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema = current_schema() AND table_name = 'mcp_request_log') AS mcp_log_exists,
|
||||
EXISTS (SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = current_schema() AND table_name = 'mcp_request_log' AND column_name = 'agent_name') AS agent_name_exists
|
||||
WHERE table_schema = current_schema() AND table_name = 'mcp_request_log' AND column_name = 'agent_name') AS agent_name_exists,
|
||||
EXISTS (SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema = current_schema() AND table_name = 'subagent_messages') AS subagent_messages_exists,
|
||||
EXISTS (SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = current_schema() AND table_name = 'subagent_messages' AND column_name = 'provider_id') AS subagent_provider_id_exists
|
||||
`;
|
||||
const probe = probeRows[0]!;
|
||||
|
||||
@@ -230,8 +238,11 @@ export class PostgresEngine implements BrainEngine {
|
||||
const needsPagesDeletedAt = probe.pages_exists && !probe.deleted_at_exists;
|
||||
// v0.26.3 (v33): idx_mcp_log_agent_time in SCHEMA_SQL needs agent_name col.
|
||||
const needsMcpLogBootstrap = probe.mcp_log_exists && !probe.agent_name_exists;
|
||||
// v0.27 (v36): idx_subagent_messages_provider in SCHEMA_SQL needs provider_id
|
||||
// (the SECOND column in the composite index `(job_id, provider_id)`).
|
||||
const needsSubagentProviderId = probe.subagent_messages_exists && !probe.subagent_provider_id_exists;
|
||||
|
||||
if (!needsPagesBootstrap && !needsLinksBootstrap && !needsChunksBootstrap && !needsPagesDeletedAt && !needsMcpLogBootstrap) return;
|
||||
if (!needsPagesBootstrap && !needsLinksBootstrap && !needsChunksBootstrap && !needsPagesDeletedAt && !needsMcpLogBootstrap && !needsSubagentProviderId) return;
|
||||
|
||||
console.log(' Pre-v0.21 brain detected, applying forward-reference bootstrap');
|
||||
|
||||
@@ -307,6 +318,18 @@ export class PostgresEngine implements BrainEngine {
|
||||
ALTER TABLE mcp_request_log ADD COLUMN IF NOT EXISTS error_message TEXT;
|
||||
`);
|
||||
}
|
||||
|
||||
if (needsSubagentProviderId) {
|
||||
// v36 (subagent_provider_neutral_persistence_v0_27) adds provider_id +
|
||||
// schema_version on subagent_messages and subagent_tool_executions.
|
||||
// SCHEMA_SQL's `CREATE INDEX idx_subagent_messages_provider ON
|
||||
// subagent_messages (job_id, provider_id)` crashes without provider_id
|
||||
// (composite-index second column). v36 runs later via runMigrations and
|
||||
// is idempotent.
|
||||
await conn.unsafe(`
|
||||
ALTER TABLE subagent_messages ADD COLUMN IF NOT EXISTS provider_id TEXT;
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
async transaction<T>(fn: (engine: BrainEngine) => Promise<T>): Promise<T> {
|
||||
|
||||
@@ -76,6 +76,12 @@ const REQUIRED_BOOTSTRAP_COVERAGE: ForwardReference[] = [
|
||||
// v0.26.3 (v33) — forward-referenced by `CREATE INDEX idx_mcp_log_agent_time
|
||||
// ON mcp_request_log(agent_name, created_at DESC)`.
|
||||
{ kind: 'column', table: 'mcp_request_log', column: 'agent_name' },
|
||||
// v0.27 (v36) — forward-referenced by `CREATE INDEX
|
||||
// idx_subagent_messages_provider ON subagent_messages (job_id, provider_id)`.
|
||||
// Composite-index second column; the array-based test pattern misses these
|
||||
// by default, which is why this fix wave's Step 3 replaces this with a
|
||||
// SQL parser that extracts every column referenced by any DDL.
|
||||
{ kind: 'column', table: 'subagent_messages', column: 'provider_id' },
|
||||
];
|
||||
|
||||
test('applyForwardReferenceBootstrap covers every forward reference declared in REQUIRED_BOOTSTRAP_COVERAGE', async () => {
|
||||
@@ -122,6 +128,9 @@ test('applyForwardReferenceBootstrap covers every forward reference declared in
|
||||
ALTER TABLE mcp_request_log DROP COLUMN IF EXISTS agent_name;
|
||||
ALTER TABLE mcp_request_log DROP COLUMN IF EXISTS params;
|
||||
ALTER TABLE mcp_request_log DROP COLUMN IF EXISTS error_message;
|
||||
|
||||
DROP INDEX IF EXISTS idx_subagent_messages_provider;
|
||||
ALTER TABLE subagent_messages DROP COLUMN IF EXISTS provider_id;
|
||||
`);
|
||||
|
||||
// Run bootstrap in isolation (NOT initSchema). This is what we're testing.
|
||||
|
||||
Reference in New Issue
Block a user