@jaguilar87/gaia 5.0.4 → 5.0.6
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +65 -0
- package/INSTALL.md +0 -2
- package/README.md +1 -6
- package/bin/README.md +0 -1
- package/bin/cli/_install_helpers.py +1 -1
- package/bin/cli/cleanup.py +0 -1
- package/bin/cli/doctor.py +2 -2
- package/bin/cli/memory.py +2 -0
- package/bin/cli/update.py +1 -1
- package/bin/pre-publish-validate.js +48 -5
- package/config/README.md +22 -44
- package/config/surface-routing.json +0 -1
- package/dist/gaia-ops/.claude-plugin/plugin.json +1 -1
- package/dist/gaia-ops/config/README.md +22 -44
- package/dist/gaia-ops/config/surface-routing.json +0 -1
- package/dist/gaia-ops/hooks/modules/agents/handoff_persister.py +2 -0
- package/dist/gaia-ops/hooks/modules/security/approval_grants.py +2 -0
- package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +2 -0
- package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +90 -55
- package/dist/gaia-ops/skills/README.md +1 -1
- package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +1 -1
- package/dist/gaia-ops/skills/gaia-patterns/reference.md +0 -1
- package/dist/gaia-ops/skills/gaia-release/SKILL.md +60 -24
- package/dist/gaia-ops/skills/gaia-release/reference.md +35 -11
- package/dist/gaia-ops/skills/git-conventions/SKILL.md +6 -2
- package/dist/gaia-ops/skills/orchestrator-present-approval/SKILL.md +10 -2
- package/dist/gaia-ops/skills/readme-writing/SKILL.md +1 -1
- package/dist/gaia-ops/skills/readme-writing/reference.md +0 -1
- package/dist/gaia-ops/tools/scan/ui.py +20 -4
- package/dist/gaia-ops/tools/scan/verify.py +3 -3
- package/dist/gaia-ops/tools/validation/README.md +15 -24
- package/dist/gaia-security/.claude-plugin/plugin.json +1 -1
- package/dist/gaia-security/hooks/modules/agents/handoff_persister.py +2 -0
- package/dist/gaia-security/hooks/modules/security/approval_grants.py +2 -0
- package/dist/gaia-security/hooks/modules/tools/bash_validator.py +2 -0
- package/dist/gaia-security/hooks/modules/validation/commit_validator.py +90 -55
- package/hooks/modules/agents/handoff_persister.py +2 -0
- package/hooks/modules/security/approval_grants.py +2 -0
- package/hooks/modules/tools/bash_validator.py +2 -0
- package/hooks/modules/validation/commit_validator.py +90 -55
- package/index.js +2 -12
- package/package.json +4 -6
- package/pyproject.toml +3 -3
- package/scripts/bootstrap_database.sh +88 -439
- package/scripts/check_schema_drift.py +208 -0
- package/scripts/migrations/README.md +78 -28
- package/scripts/migrations/schema.checksum +8 -0
- package/scripts/release-prepare.mjs +199 -0
- package/skills/README.md +1 -1
- package/skills/gaia-patterns/SKILL.md +1 -1
- package/skills/gaia-patterns/reference.md +0 -1
- package/skills/gaia-release/SKILL.md +60 -24
- package/skills/gaia-release/reference.md +35 -11
- package/skills/git-conventions/SKILL.md +6 -2
- package/skills/orchestrator-present-approval/SKILL.md +10 -2
- package/skills/readme-writing/SKILL.md +1 -1
- package/skills/readme-writing/reference.md +0 -1
- package/tools/scan/ui.py +20 -4
- package/tools/scan/verify.py +3 -3
- package/tools/validation/README.md +15 -24
- package/commands/README.md +0 -64
- package/commands/gaia.md +0 -37
- package/commands/scan-project.md +0 -74
- package/config/crons-schema.md +0 -81
- package/config/git_standards.json +0 -72
- package/dist/gaia-ops/commands/gaia.md +0 -37
- package/dist/gaia-ops/config/crons-schema.md +0 -81
- package/dist/gaia-ops/config/git_standards.json +0 -72
- package/dist/gaia-ops/tools/agentic-loop/decide-status.py +0 -210
- package/dist/gaia-ops/tools/agentic-loop/parse-metric.py +0 -106
- package/dist/gaia-ops/tools/agentic-loop/record-iteration.py +0 -223
- package/git-hooks/commit-msg +0 -41
- package/scripts/migrations/v10_to_v11.sql +0 -170
- package/scripts/migrations/v10_to_v11_fresh.sql +0 -18
- package/scripts/migrations/v11_to_v12.sql +0 -195
- package/scripts/migrations/v11_to_v12_fresh.sql +0 -19
- package/scripts/migrations/v12_to_v13.sql +0 -48
- package/scripts/migrations/v12_to_v13_fresh.sql +0 -17
- package/scripts/migrations/v13_to_v14.sql +0 -44
- package/scripts/migrations/v13_to_v14_fresh.sql +0 -17
- package/scripts/migrations/v14_to_v15.sql +0 -71
- package/scripts/migrations/v14_to_v15_fresh.sql +0 -19
- package/scripts/migrations/v15_to_v16.sql +0 -57
- package/scripts/migrations/v15_to_v16_fresh.sql +0 -18
- package/scripts/migrations/v16_to_v17.sql +0 -51
- package/scripts/migrations/v16_to_v17_fresh.sql +0 -18
- package/scripts/migrations/v17_to_v18.sql +0 -66
- package/scripts/migrations/v17_to_v18_fresh.sql +0 -24
- package/scripts/migrations/v1_to_v2.sql +0 -97
- package/scripts/migrations/v2_to_v3.sql +0 -68
- package/scripts/migrations/v2_to_v3_merge.sql +0 -69
- package/scripts/migrations/v3_to_v4.sql +0 -67
- package/scripts/migrations/v3_to_v4_fresh.sql +0 -20
- package/scripts/migrations/v4_to_v5.sql +0 -55
- package/scripts/migrations/v4_to_v5_fresh.sql +0 -20
- package/scripts/migrations/v5_to_v6.sql +0 -48
- package/scripts/migrations/v5_to_v6_fresh.sql +0 -17
- package/scripts/migrations/v6_to_v7.sql +0 -26
- package/scripts/migrations/v6_to_v7_fresh.sql +0 -13
- package/scripts/migrations/v7_to_v8.sql +0 -44
- package/scripts/migrations/v7_to_v8_fresh.sql +0 -14
- package/scripts/migrations/v8_to_v9.sql +0 -87
- package/scripts/migrations/v8_to_v9_fresh.sql +0 -15
- package/scripts/migrations/v9_to_v10.sql +0 -109
- package/scripts/migrations/v9_to_v10_episodes_workspace.sql +0 -109
- package/scripts/migrations/v9_to_v10_fresh.sql +0 -18
- package/templates/README.md +0 -70
- package/templates/managed-settings.template.json +0 -43
- package/tools/agentic-loop/decide-status.py +0 -210
- package/tools/agentic-loop/parse-metric.py +0 -106
- package/tools/agentic-loop/record-iteration.py +0 -223
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
-- Migration v12 -> v13 (gaia-scan-overhaul: workspace->group->repo model, AC-2)
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- v12 schema has the durable approvals / approval_events tables from the
|
|
6
|
-
-- approval-model-redesign brief. v13 adds a `group_name` column to the
|
|
7
|
-
-- `projects` table to support the workspace->group->repo hierarchy introduced
|
|
8
|
-
-- by the gaia-scan-overhaul brief (AC-2).
|
|
9
|
-
--
|
|
10
|
-
-- Why `group_name` and not `group`
|
|
11
|
-
-- ---------------------------------
|
|
12
|
-
-- `group` is a reserved keyword in SQL. Using it as a column name requires
|
|
13
|
-
-- quoting everywhere and produces subtle bugs in hand-written queries.
|
|
14
|
-
-- `group_name` is the canonical column name for this feature.
|
|
15
|
-
--
|
|
16
|
-
-- Column semantics
|
|
17
|
-
-- ----------------
|
|
18
|
-
-- group_name TEXT (nullable)
|
|
19
|
-
-- The optional organizational group or team this project belongs to within
|
|
20
|
-
-- its workspace. For example, in a GitHub organization the group_name might
|
|
21
|
-
-- be a team slug, a monorepo sub-directory, or any intermediate container
|
|
22
|
-
-- between the workspace and the individual project (repo).
|
|
23
|
-
--
|
|
24
|
-
-- NULL = ungrouped (the default for all pre-existing rows after migration).
|
|
25
|
-
-- The value is assigned by populate_project (T2.2 of the plan) using
|
|
26
|
-
-- scanner-specific detection logic. This migration only adds the column;
|
|
27
|
-
-- it does NOT back-fill existing rows.
|
|
28
|
-
--
|
|
29
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
30
|
-
-- A failure mid-flight rolls back to v12 state; the ledger row is NOT
|
|
31
|
-
-- inserted, so the next bootstrap retry sees the same pending migration.
|
|
32
|
-
-- Closes T1.1 (schema + writer plumbing) of brief gaia-scan-overhaul.
|
|
33
|
-
|
|
34
|
-
-- ---------------------------------------------------------------------------
|
|
35
|
-
-- Step 1: Add group_name column to projects
|
|
36
|
-
-- ---------------------------------------------------------------------------
|
|
37
|
-
ALTER TABLE projects ADD COLUMN group_name TEXT;
|
|
38
|
-
|
|
39
|
-
-- ---------------------------------------------------------------------------
|
|
40
|
-
-- Step 2: Bump schema_version to 13
|
|
41
|
-
-- ---------------------------------------------------------------------------
|
|
42
|
-
INSERT OR IGNORE INTO schema_version (version, applied_at, description)
|
|
43
|
-
VALUES (13, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
|
|
44
|
-
'projects.group_name column (workspace->group->repo, AC-2)');
|
|
45
|
-
|
|
46
|
-
-- Verification queries (run after applying):
|
|
47
|
-
-- SELECT MAX(version) FROM schema_version; -- expect: 13
|
|
48
|
-
-- PRAGMA table_info(projects); -- expect group_name column present
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
-- Migration v12 -> v13 fresh-install variant
|
|
2
|
-
--
|
|
3
|
-
-- Used by bootstrap_database.sh when the live DB was created directly from
|
|
4
|
-
-- schema.sql at v13 state (i.e. schema.sql already declares the group_name
|
|
5
|
-
-- column on the projects table).
|
|
6
|
-
--
|
|
7
|
-
-- On a fresh install:
|
|
8
|
-
-- - schema.sql creates projects with all columns including group_name -> no DDL needed
|
|
9
|
-
--
|
|
10
|
-
-- This variant is a no-op; it only exists so the bootstrap guard-probe branch
|
|
11
|
-
-- can select it and stamp the ledger without applying DDL.
|
|
12
|
-
--
|
|
13
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
14
|
-
-- No DDL is executed; the COMMIT is harmless.
|
|
15
|
-
|
|
16
|
-
-- No-op: fresh install already at v13 state (schema.sql created all objects).
|
|
17
|
-
SELECT 1;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
-- Migration v13 -> v14 (gaia-scan-overhaul: projects.path column, findability)
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- v13 schema added `group_name` to the `projects` table (workspace->group->repo
|
|
6
|
-
-- hierarchy). v14 adds a `path TEXT` column to the same table so that the
|
|
7
|
-
-- scanner can persist the absolute on-disk path of each project, enabling
|
|
8
|
-
-- name-based findability (project name -> path + workspace) without
|
|
9
|
-
-- re-scanning or relying on external tooling.
|
|
10
|
-
--
|
|
11
|
-
-- Column semantics
|
|
12
|
-
-- ----------------
|
|
13
|
-
-- path TEXT (nullable)
|
|
14
|
-
-- Absolute filesystem path to the project root directory on the machine
|
|
15
|
-
-- where the scanner ran. For example: '/home/jorge/ws/me/gaia'.
|
|
16
|
-
--
|
|
17
|
-
-- NULL = path not yet recorded (the default for all pre-existing rows
|
|
18
|
-
-- after migration; also the default for rows created before the scanner
|
|
19
|
-
-- logic that assigns the value is deployed).
|
|
20
|
-
-- The value is assigned by populate_project (T2.x of the plan) using
|
|
21
|
-
-- the project_path argument already threaded through the scanner API.
|
|
22
|
-
-- This migration only adds the column; it does NOT back-fill existing
|
|
23
|
-
-- rows.
|
|
24
|
-
--
|
|
25
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
26
|
-
-- A failure mid-flight rolls back to v13 state; the ledger row is NOT
|
|
27
|
-
-- inserted, so the next bootstrap retry sees the same pending migration.
|
|
28
|
-
-- Closes T1.2 (schema + writer plumbing) of brief gaia-scan-overhaul.
|
|
29
|
-
|
|
30
|
-
-- ---------------------------------------------------------------------------
|
|
31
|
-
-- Step 1: Add path column to projects
|
|
32
|
-
-- ---------------------------------------------------------------------------
|
|
33
|
-
ALTER TABLE projects ADD COLUMN path TEXT;
|
|
34
|
-
|
|
35
|
-
-- ---------------------------------------------------------------------------
|
|
36
|
-
-- Step 2: Bump schema_version to 14
|
|
37
|
-
-- ---------------------------------------------------------------------------
|
|
38
|
-
INSERT OR IGNORE INTO schema_version (version, applied_at, description)
|
|
39
|
-
VALUES (14, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
|
|
40
|
-
'projects.path column (findability: project -> path + workspace)');
|
|
41
|
-
|
|
42
|
-
-- Verification queries (run after applying):
|
|
43
|
-
-- SELECT MAX(version) FROM schema_version; -- expect: 14
|
|
44
|
-
-- PRAGMA table_info(projects); -- expect path column present
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
-- Migration v13 -> v14 fresh-install variant
|
|
2
|
-
--
|
|
3
|
-
-- Used by bootstrap_database.sh when the live DB was created directly from
|
|
4
|
-
-- schema.sql at v14 state (i.e. schema.sql already declares the path column
|
|
5
|
-
-- on the projects table).
|
|
6
|
-
--
|
|
7
|
-
-- On a fresh install:
|
|
8
|
-
-- - schema.sql creates projects with all columns including path -> no DDL needed
|
|
9
|
-
--
|
|
10
|
-
-- This variant is a no-op; it only exists so the bootstrap guard-probe branch
|
|
11
|
-
-- can select it and stamp the ledger without applying DDL.
|
|
12
|
-
--
|
|
13
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
14
|
-
-- No DDL is executed; the COMMIT is harmless.
|
|
15
|
-
|
|
16
|
-
-- No-op: fresh install already at v14 state (schema.sql created all objects).
|
|
17
|
-
SELECT 1;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
-- Migration v14 -> v15 (child-table FK column rename: repo -> project)
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- Commit be9698f ("feat(substrate): rename projects->workspaces, repos->projects")
|
|
6
|
-
-- renamed the substrate hierarchy. The OLD `repos` concept (git-bearing units)
|
|
7
|
-
-- became `projects`, and the OLD `projects` container became `workspaces`.
|
|
8
|
-
--
|
|
9
|
-
-- schema.sql and the writer/populator code were updated to use the `project`
|
|
10
|
-
-- column on the nine per-project child tables:
|
|
11
|
-
-- apps, libraries, services, features, tf_modules, tf_live, releases,
|
|
12
|
-
-- workloads, clusters_defined
|
|
13
|
-
-- ...but NO migration was ever shipped to rename the live column. Because every
|
|
14
|
-
-- child table is declared with `CREATE TABLE IF NOT EXISTS`, schema.sql silently
|
|
15
|
-
-- no-ops on a DB that already has these tables, so existing installations (at
|
|
16
|
-
-- v14) still carry the legacy column name `repo`. The writer/populator code,
|
|
17
|
-
-- which already emits `project` in every INSERT / SELECT / ON CONFLICT /
|
|
18
|
-
-- delete_missing path, then fails at runtime with "no such column: project" the
|
|
19
|
-
-- first time `gaia scan` populates infra/app rows.
|
|
20
|
-
--
|
|
21
|
-
-- This was latent because scan_workspace_to_store had never run end-to-end via
|
|
22
|
-
-- the CLI (it was only wired in T3.1), and the unit tests mock the writer or
|
|
23
|
-
-- use fixtures with no infra/app content, so the column mismatch never executed.
|
|
24
|
-
--
|
|
25
|
-
-- Fix direction
|
|
26
|
-
-- -------------
|
|
27
|
-
-- `project` is the canonical name: it is what schema.sql declares, what every
|
|
28
|
-
-- writer/populator SQL path emits, and what the writer's PK maps in
|
|
29
|
-
-- delete_missing_in use. The live DB is the sole outlier. The lowest-blast-
|
|
30
|
-
-- radius fix is therefore a forward migration that renames the legacy `repo`
|
|
31
|
-
-- column to `project` on each of the nine child tables. No code change is
|
|
32
|
-
-- required.
|
|
33
|
-
--
|
|
34
|
-
-- Mechanism
|
|
35
|
-
-- ---------
|
|
36
|
-
-- SQLite >= 3.25 supports `ALTER TABLE ... RENAME COLUMN`, which rewrites the
|
|
37
|
-
-- stored DDL in place, automatically updating the column's appearance in the
|
|
38
|
-
-- table's PRIMARY KEY and in its own FOREIGN KEY clause. The FTS5 mirror tables
|
|
39
|
-
-- (apps_fts, services_fts) index text content columns (name, etc.), NOT the FK
|
|
40
|
-
-- column, so they are unaffected. Verified on sqlite 3.45.x: PRAGMA
|
|
41
|
-
-- foreign_key_check returns no rows after the rename and project-keyed INSERTs
|
|
42
|
-
-- succeed.
|
|
43
|
-
--
|
|
44
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT. A failure
|
|
45
|
-
-- mid-flight rolls back to v14 state; the ledger row is NOT inserted, so the
|
|
46
|
-
-- next bootstrap retry sees the same pending migration.
|
|
47
|
-
|
|
48
|
-
-- ---------------------------------------------------------------------------
|
|
49
|
-
-- Step 1: Rename repo -> project on each per-project child table
|
|
50
|
-
-- ---------------------------------------------------------------------------
|
|
51
|
-
ALTER TABLE apps RENAME COLUMN repo TO project;
|
|
52
|
-
ALTER TABLE libraries RENAME COLUMN repo TO project;
|
|
53
|
-
ALTER TABLE services RENAME COLUMN repo TO project;
|
|
54
|
-
ALTER TABLE features RENAME COLUMN repo TO project;
|
|
55
|
-
ALTER TABLE tf_modules RENAME COLUMN repo TO project;
|
|
56
|
-
ALTER TABLE tf_live RENAME COLUMN repo TO project;
|
|
57
|
-
ALTER TABLE releases RENAME COLUMN repo TO project;
|
|
58
|
-
ALTER TABLE workloads RENAME COLUMN repo TO project;
|
|
59
|
-
ALTER TABLE clusters_defined RENAME COLUMN repo TO project;
|
|
60
|
-
|
|
61
|
-
-- ---------------------------------------------------------------------------
|
|
62
|
-
-- Step 2: Bump schema_version to 15
|
|
63
|
-
-- ---------------------------------------------------------------------------
|
|
64
|
-
INSERT OR IGNORE INTO schema_version (version, applied_at, description)
|
|
65
|
-
VALUES (15, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
|
|
66
|
-
'rename child-table FK column repo -> project (substrate rename catch-up)');
|
|
67
|
-
|
|
68
|
-
-- Verification queries (run after applying):
|
|
69
|
-
-- SELECT MAX(version) FROM schema_version; -- expect: 15
|
|
70
|
-
-- PRAGMA table_info(apps); -- expect: project (not repo)
|
|
71
|
-
-- PRAGMA foreign_key_check; -- expect: no rows
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
-- Migration v14 -> v15 fresh-install variant
|
|
2
|
-
--
|
|
3
|
-
-- Used by bootstrap_database.sh when the live DB was created directly from
|
|
4
|
-
-- schema.sql at v15 state -- i.e. the per-project child tables (apps, services,
|
|
5
|
-
-- tf_modules, ...) already carry the `project` column because schema.sql
|
|
6
|
-
-- declared them that way.
|
|
7
|
-
--
|
|
8
|
-
-- On a fresh install there is no legacy `repo` column to rename, so the
|
|
9
|
-
-- RENAME COLUMN statements in v14_to_v15.sql would fail with "no such column:
|
|
10
|
-
-- repo". This variant is a no-op; it exists only so the bootstrap guard-probe
|
|
11
|
-
-- branch (Section 3c, case 15) can select it and stamp the ledger without
|
|
12
|
-
-- attempting the rename.
|
|
13
|
-
--
|
|
14
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
15
|
-
-- No DDL is executed; the COMMIT is harmless.
|
|
16
|
-
|
|
17
|
-
-- No-op: fresh install already at v15 state (schema.sql created child tables
|
|
18
|
-
-- with the `project` column).
|
|
19
|
-
SELECT 1;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
-- Migration v15 -> v16 (gaia-scan-overhaul: projects soft-delete columns)
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- The prune step in scan_workspace_to_store currently issues hard DELETEs for
|
|
6
|
-
-- projects that are no longer found on disk. Brief gaia-scan-overhaul replaces
|
|
7
|
-
-- that with a soft-delete: projects are marked 'missing' instead of removed,
|
|
8
|
-
-- so historical context (memory atoms, episodes, briefs keyed on that project)
|
|
9
|
-
-- survives the scan cycle.
|
|
10
|
-
--
|
|
11
|
-
-- This migration adds two scanner-owned columns to the `projects` table:
|
|
12
|
-
--
|
|
13
|
-
-- status TEXT NOT NULL DEFAULT 'active'
|
|
14
|
-
-- Values: 'active' | 'missing'.
|
|
15
|
-
-- 'active' -- project was present on the last scan run.
|
|
16
|
-
-- 'missing' -- project was NOT found on the most recent scan; kept as a
|
|
17
|
-
-- tombstone so child-table data and historical context survive.
|
|
18
|
-
-- Default 'active': existing rows (which were present at migration time)
|
|
19
|
-
-- are classified as active. New rows inserted by the scanner also default
|
|
20
|
-
-- to 'active' without requiring callers to supply the column.
|
|
21
|
-
--
|
|
22
|
-
-- missing_since TEXT (nullable)
|
|
23
|
-
-- ISO8601 UTC timestamp of when status was first set to 'missing'.
|
|
24
|
-
-- NULL when status='active'. The scanner sets this on the first cycle
|
|
25
|
-
-- where it cannot find the project; subsequent cycles leave it unchanged
|
|
26
|
-
-- (the timestamp records the FIRST disappearance, not the most recent).
|
|
27
|
-
--
|
|
28
|
-
-- Scope of this migration
|
|
29
|
-
-- -----------------------
|
|
30
|
-
-- ONLY the DDL changes. The prune logic (DELETE -> UPDATE status='missing') is
|
|
31
|
-
-- implemented in the NEXT task (scan populator changes). This migration only
|
|
32
|
-
-- ensures the columns exist and that the writer accepts them.
|
|
33
|
-
--
|
|
34
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT. A failure
|
|
35
|
-
-- mid-flight rolls back to v15 state; the ledger row is NOT inserted, so the
|
|
36
|
-
-- next bootstrap retry sees the same pending migration.
|
|
37
|
-
|
|
38
|
-
-- ---------------------------------------------------------------------------
|
|
39
|
-
-- Step 1: Add status column to projects (NOT NULL DEFAULT 'active')
|
|
40
|
-
-- ---------------------------------------------------------------------------
|
|
41
|
-
ALTER TABLE projects ADD COLUMN status TEXT NOT NULL DEFAULT 'active';
|
|
42
|
-
|
|
43
|
-
-- ---------------------------------------------------------------------------
|
|
44
|
-
-- Step 2: Add missing_since column to projects (nullable)
|
|
45
|
-
-- ---------------------------------------------------------------------------
|
|
46
|
-
ALTER TABLE projects ADD COLUMN missing_since TEXT;
|
|
47
|
-
|
|
48
|
-
-- ---------------------------------------------------------------------------
|
|
49
|
-
-- Step 3: Bump schema_version to 16
|
|
50
|
-
-- ---------------------------------------------------------------------------
|
|
51
|
-
INSERT OR IGNORE INTO schema_version (version, applied_at, description)
|
|
52
|
-
VALUES (16, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
|
|
53
|
-
'projects soft-delete: status + missing_since columns');
|
|
54
|
-
|
|
55
|
-
-- Verification queries (run after applying):
|
|
56
|
-
-- SELECT MAX(version) FROM schema_version; -- expect: 16
|
|
57
|
-
-- PRAGMA table_info(projects); -- expect: status, missing_since columns present
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
-- Migration v15 -> v16 fresh-install variant
|
|
2
|
-
--
|
|
3
|
-
-- Used by bootstrap_database.sh when the live DB was created directly from
|
|
4
|
-
-- schema.sql at v16 state -- i.e. the `projects` table already carries the
|
|
5
|
-
-- `status` and `missing_since` columns because schema.sql declared them that way.
|
|
6
|
-
--
|
|
7
|
-
-- On a fresh install there are no legacy rows to alter, so the ALTER TABLE
|
|
8
|
-
-- statements in v15_to_v16.sql would fail with "duplicate column name".
|
|
9
|
-
-- This variant is a no-op; it exists only so the bootstrap guard-probe branch
|
|
10
|
-
-- (Section 3c, case 16) can select it and stamp the ledger without attempting
|
|
11
|
-
-- the ALTER.
|
|
12
|
-
--
|
|
13
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
14
|
-
-- No DDL is executed; the COMMIT is harmless.
|
|
15
|
-
|
|
16
|
-
-- No-op: fresh install already at v16 state (schema.sql created projects with
|
|
17
|
-
-- status and missing_since columns).
|
|
18
|
-
SELECT 1;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
-- Migration v16 -> v17 (DEMOTE case: workspaces soft-delete columns)
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- v16 added soft-delete (status / missing_since) to the `projects` table. The
|
|
6
|
-
-- multi-workspace DEMOTE test revealed the same gap one level up: when a
|
|
7
|
-
-- workspace loses its Gaia install footprint (the user removes its `.claude/`,
|
|
8
|
-
-- "demoting" it), the `workspaces` row had no way to record that. A re-scan of
|
|
9
|
-
-- a demoted directory would persist the row and refresh `last_scan_at` as if it
|
|
10
|
-
-- were still a live workspace.
|
|
11
|
-
--
|
|
12
|
-
-- This migration adds two scanner-owned columns to the `workspaces` table,
|
|
13
|
-
-- mirroring the v16 projects soft-delete contract:
|
|
14
|
-
--
|
|
15
|
-
-- status TEXT NOT NULL DEFAULT 'active'
|
|
16
|
-
-- Values: 'active' | 'missing'.
|
|
17
|
-
-- 'active' -- the workspace carried a Gaia install on the last scan.
|
|
18
|
-
-- 'missing' -- the workspace's install footprint disappeared (demoted);
|
|
19
|
-
-- kept as a tombstone so its projects/history survive.
|
|
20
|
-
-- Default 'active': existing rows (live workspaces at migration time) are
|
|
21
|
-
-- classified active without requiring callers to supply the column.
|
|
22
|
-
--
|
|
23
|
-
-- missing_since TEXT (nullable)
|
|
24
|
-
-- ISO8601 UTC timestamp of when status was first set to 'missing'.
|
|
25
|
-
-- NULL when status='active'. Set on the first scan that finds the install
|
|
26
|
-
-- gone; subsequent scans leave it unchanged (records the FIRST demote).
|
|
27
|
-
--
|
|
28
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT. A failure
|
|
29
|
-
-- mid-flight rolls back to v16 state; the ledger row is NOT inserted, so the
|
|
30
|
-
-- next bootstrap retry sees the same pending migration.
|
|
31
|
-
|
|
32
|
-
-- ---------------------------------------------------------------------------
|
|
33
|
-
-- Step 1: Add status column to workspaces (NOT NULL DEFAULT 'active')
|
|
34
|
-
-- ---------------------------------------------------------------------------
|
|
35
|
-
ALTER TABLE workspaces ADD COLUMN status TEXT NOT NULL DEFAULT 'active';
|
|
36
|
-
|
|
37
|
-
-- ---------------------------------------------------------------------------
|
|
38
|
-
-- Step 2: Add missing_since column to workspaces (nullable)
|
|
39
|
-
-- ---------------------------------------------------------------------------
|
|
40
|
-
ALTER TABLE workspaces ADD COLUMN missing_since TEXT;
|
|
41
|
-
|
|
42
|
-
-- ---------------------------------------------------------------------------
|
|
43
|
-
-- Step 3: Bump schema_version to 17
|
|
44
|
-
-- ---------------------------------------------------------------------------
|
|
45
|
-
INSERT OR IGNORE INTO schema_version (version, applied_at, description)
|
|
46
|
-
VALUES (17, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
|
|
47
|
-
'workspaces soft-delete: status + missing_since columns (DEMOTE)');
|
|
48
|
-
|
|
49
|
-
-- Verification queries (run after applying):
|
|
50
|
-
-- SELECT MAX(version) FROM schema_version; -- expect: 17
|
|
51
|
-
-- PRAGMA table_info(workspaces); -- expect: status, missing_since columns present
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
-- Migration v16 -> v17 fresh-install variant
|
|
2
|
-
--
|
|
3
|
-
-- Used by bootstrap_database.sh when the live DB was created directly from
|
|
4
|
-
-- schema.sql at v17 state -- i.e. the `workspaces` table already carries the
|
|
5
|
-
-- `status` and `missing_since` columns because schema.sql declared them that way.
|
|
6
|
-
--
|
|
7
|
-
-- On a fresh install there are no legacy rows to alter, so the ALTER TABLE
|
|
8
|
-
-- statements in v16_to_v17.sql would fail with "duplicate column name".
|
|
9
|
-
-- This variant is a no-op; it exists only so the bootstrap guard-probe branch
|
|
10
|
-
-- (Section 3c, case 17) can select it and stamp the ledger without attempting
|
|
11
|
-
-- the ALTER.
|
|
12
|
-
--
|
|
13
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
14
|
-
-- No DDL is executed; the COMMIT is harmless.
|
|
15
|
-
|
|
16
|
-
-- No-op: fresh install already at v17 state (schema.sql created workspaces with
|
|
17
|
-
-- status and missing_since columns).
|
|
18
|
-
SELECT 1;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
-- Migration v17 -> v18 (stable project identity: collapse same repo across vantages)
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- The `projects` table is keyed (workspace, name). The scanner derives `name`
|
|
6
|
-
-- from the on-disk basename and `workspace` from the scan vantage's identity.
|
|
7
|
-
-- The SAME physical repository scanned from two different roots -- e.g. once
|
|
8
|
-
-- from the workspace root and once from inside the repo's own subdirectory
|
|
9
|
-
-- (which resolves a different *workspace* identity) -- produced TWO distinct
|
|
10
|
-
-- (workspace, name) rows: a duplicate of one physical project.
|
|
11
|
-
--
|
|
12
|
-
-- This migration adds a stable, vantage-independent project identity so the
|
|
13
|
-
-- UPSERT can collapse those duplicates into one row. Identity is resolved by
|
|
14
|
-
-- the scanner (tools/scan/store_populator.resolve_project_identity) in this
|
|
15
|
-
-- order: git-common-dir (realpath) > normalized remote (host/owner/repo) >
|
|
16
|
-
-- realpath of the project path.
|
|
17
|
-
--
|
|
18
|
-
-- Two additive, NON-DESTRUCTIVE changes:
|
|
19
|
-
--
|
|
20
|
-
-- 1. ALTER TABLE projects ADD COLUMN project_identity TEXT (nullable)
|
|
21
|
-
-- Scanner-owned. NULL allowed for legacy/uninitialized rows so the column
|
|
22
|
-
-- adds cleanly to an existing DB without backfill. A subsequent `gaia scan`
|
|
23
|
-
-- populates it for every live project.
|
|
24
|
-
--
|
|
25
|
-
-- 2. CREATE UNIQUE INDEX idx_projects_identity ... WHERE project_identity IS NOT NULL
|
|
26
|
-
-- PARTIAL unique index. Enforces one row per physical repo for rows that
|
|
27
|
-
-- HAVE an identity, while exempting legacy NULL-identity rows from the
|
|
28
|
-
-- uniqueness constraint (so multiple NULL rows can coexist until the next
|
|
29
|
-
-- scan backfills them). This is the ON CONFLICT target the writer uses.
|
|
30
|
-
--
|
|
31
|
-
-- Backfill note
|
|
32
|
-
-- -------------
|
|
33
|
-
-- This migration does NOT backfill project_identity for existing rows -- it
|
|
34
|
-
-- cannot derive git-common-dir from SQL alone, and the value is cheap to
|
|
35
|
-
-- recompute on the next scan. Existing duplicate rows (if any) are left intact;
|
|
36
|
-
-- the first scan after migration assigns identities and any genuine duplicate
|
|
37
|
-
-- collapses on the following scan once both rows share an identity. Because the
|
|
38
|
-
-- index is PARTIAL, the ADD COLUMN (all rows NULL) cannot fail on existing
|
|
39
|
-
-- duplicates.
|
|
40
|
-
--
|
|
41
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT. A failure
|
|
42
|
-
-- mid-flight rolls back to v17 state; the ledger row is NOT inserted, so the
|
|
43
|
-
-- next bootstrap retry sees the same pending migration.
|
|
44
|
-
|
|
45
|
-
-- ---------------------------------------------------------------------------
|
|
46
|
-
-- Step 1: Add project_identity column to projects (nullable, scanner-owned)
|
|
47
|
-
-- ---------------------------------------------------------------------------
|
|
48
|
-
ALTER TABLE projects ADD COLUMN project_identity TEXT;
|
|
49
|
-
|
|
50
|
-
-- ---------------------------------------------------------------------------
|
|
51
|
-
-- Step 2: Partial UNIQUE index that collapses the same physical repo to one row
|
|
52
|
-
-- ---------------------------------------------------------------------------
|
|
53
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_projects_identity
|
|
54
|
-
ON projects(project_identity) WHERE project_identity IS NOT NULL;
|
|
55
|
-
|
|
56
|
-
-- ---------------------------------------------------------------------------
|
|
57
|
-
-- Step 3: Bump schema_version to 18
|
|
58
|
-
-- ---------------------------------------------------------------------------
|
|
59
|
-
INSERT OR IGNORE INTO schema_version (version, applied_at, description)
|
|
60
|
-
VALUES (18, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
|
|
61
|
-
'projects stable identity: project_identity column + partial unique index (collapse same repo across vantages)');
|
|
62
|
-
|
|
63
|
-
-- Verification queries (run after applying):
|
|
64
|
-
-- SELECT MAX(version) FROM schema_version; -- expect: 18
|
|
65
|
-
-- SELECT name FROM pragma_table_info('projects') WHERE name='project_identity'; -- expect: project_identity
|
|
66
|
-
-- SELECT name FROM sqlite_master WHERE type='index' AND name='idx_projects_identity'; -- expect: idx_projects_identity
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
-- Migration v17 -> v18 fresh-install variant
|
|
2
|
-
--
|
|
3
|
-
-- Used by bootstrap_database.sh when the live DB was created directly from
|
|
4
|
-
-- schema.sql at v18 state -- i.e. the `projects` table already carries the
|
|
5
|
-
-- `project_identity` column because schema.sql declared it that way.
|
|
6
|
-
--
|
|
7
|
-
-- On a fresh install there are no legacy rows to alter, so the ALTER TABLE
|
|
8
|
-
-- statement in v17_to_v18.sql would fail with "duplicate column name".
|
|
9
|
-
-- This variant therefore SKIPS the ALTER but still creates the partial unique
|
|
10
|
-
-- index -- the index is intentionally NOT declared in schema.sql because
|
|
11
|
-
-- referencing project_identity there would parse-fail when bootstrapping a
|
|
12
|
-
-- legacy (pre-v18) DB whose CREATE TABLE IF NOT EXISTS short-circuits before
|
|
13
|
-
-- the column exists. Creating it here (idempotent IF NOT EXISTS) is the only
|
|
14
|
-
-- place the index lands on a fresh install. Same convention as
|
|
15
|
-
-- idx_memory_class_status (scripts/migrations/v3_to_v4_fresh.sql).
|
|
16
|
-
--
|
|
17
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
18
|
-
|
|
19
|
-
-- Step 1 (skipped on fresh install): the project_identity column already exists.
|
|
20
|
-
|
|
21
|
-
-- Step 2: create the partial unique index that collapses the same physical repo
|
|
22
|
-
-- (same project_identity) to one row, exempting NULL-identity legacy rows.
|
|
23
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_projects_identity
|
|
24
|
-
ON projects(project_identity) WHERE project_identity IS NOT NULL;
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
-- Migration v1 -> v2: widen memory.type CHECK constraint.
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- v1 schema: memory.type CHECK (type IN ('project', 'user', 'feedback'))
|
|
6
|
-
-- v2 schema: memory.type CHECK (type IN ('project', 'user', 'feedback', 'atom', 'decision', 'negative'))
|
|
7
|
-
--
|
|
8
|
-
-- The bug this migration fixes
|
|
9
|
-
-- ----------------------------
|
|
10
|
-
-- bootstrap_database.sh applies schema.sql with `CREATE TABLE IF NOT EXISTS`.
|
|
11
|
-
-- On DBs created under v1 the CREATE short-circuits and the widened CHECK in
|
|
12
|
-
-- schema.sql never lands -- yet the bootstrap historically stamped the
|
|
13
|
-
-- schema_version ledger row for v2 unconditionally. Result: the ledger lied
|
|
14
|
-
-- and writes of the new types ('atom', 'decision', 'negative') failed at
|
|
15
|
-
-- runtime with CHECK constraint errors while `gaia doctor` reported OK.
|
|
16
|
-
--
|
|
17
|
-
-- Pattern: SQLite cannot ALTER a CHECK constraint. Canonical workaround:
|
|
18
|
-
-- 1. Drop the FTS5 mirror triggers (avoid duplicate writes during copy).
|
|
19
|
-
-- 2. Rename the old table out of the way.
|
|
20
|
-
-- 3. Create the new table with the widened CHECK matching schema.sql.
|
|
21
|
-
-- 4. Copy rows preserving rowid (memory_fts joins on rowid).
|
|
22
|
-
-- 5. Drop the renamed old table.
|
|
23
|
-
-- 6. Recreate the indexes on the new table.
|
|
24
|
-
-- 7. Recreate the FTS5 mirror triggers verbatim.
|
|
25
|
-
-- 8. Rebuild memory_fts from the new memory table.
|
|
26
|
-
--
|
|
27
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT. A
|
|
28
|
-
-- failure mid-flight rolls back to the v1 state and the ledger row is NOT
|
|
29
|
-
-- inserted -- the next bootstrap retry will see the same pending migration.
|
|
30
|
-
--
|
|
31
|
-
-- Pre-conditions: caller has verified that the live memory.type CHECK does
|
|
32
|
-
-- NOT yet include 'atom'. Applying this on an already-widened table would
|
|
33
|
-
-- still succeed (the rename-create-copy ends in the same state) but the
|
|
34
|
-
-- caller skips it to avoid unnecessary work.
|
|
35
|
-
|
|
36
|
-
-- 1. Drop the FTS5 trigger trio. They mirror writes into memory_fts; we do
|
|
37
|
-
-- not want them to fire during the bulk copy below. memory_fts itself is
|
|
38
|
-
-- untouched here -- we will rebuild it after the copy completes.
|
|
39
|
-
DROP TRIGGER IF EXISTS memory_ai;
|
|
40
|
-
DROP TRIGGER IF EXISTS memory_ad;
|
|
41
|
-
DROP TRIGGER IF EXISTS memory_au;
|
|
42
|
-
|
|
43
|
-
-- 2. Rename the old table out of the way. The indexes (idx_memory_project,
|
|
44
|
-
-- idx_memory_workspace, idx_memory_type) move with the table under their
|
|
45
|
-
-- original names -- SQLite ALTER TABLE RENAME carries indexes along.
|
|
46
|
-
ALTER TABLE memory RENAME TO memory_v1_legacy;
|
|
47
|
-
|
|
48
|
-
-- 3. Create the new memory table with the widened CHECK constraint that
|
|
49
|
-
-- matches schema.sql verbatim (6 allowed types).
|
|
50
|
-
CREATE TABLE memory (
|
|
51
|
-
workspace TEXT NOT NULL,
|
|
52
|
-
name TEXT NOT NULL,
|
|
53
|
-
type TEXT NOT NULL CHECK (type IN ('project', 'user', 'feedback', 'atom', 'decision', 'negative')),
|
|
54
|
-
description TEXT,
|
|
55
|
-
body TEXT NOT NULL,
|
|
56
|
-
origin_session_id TEXT,
|
|
57
|
-
updated_at TEXT,
|
|
58
|
-
PRIMARY KEY (workspace, name),
|
|
59
|
-
FOREIGN KEY (workspace) REFERENCES workspaces(name) ON DELETE CASCADE
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
-- 4. Copy all rows preserving rowid. This is critical: memory_fts joins on
|
|
63
|
-
-- rowid, so changing them would invalidate the FTS5 index. We list rowid
|
|
64
|
-
-- explicitly to bypass SQLite's default rowid allocation.
|
|
65
|
-
INSERT INTO memory (rowid, workspace, name, type, description, body, origin_session_id, updated_at)
|
|
66
|
-
SELECT rowid, workspace, name, type, description, body, origin_session_id, updated_at
|
|
67
|
-
FROM memory_v1_legacy;
|
|
68
|
-
|
|
69
|
-
-- 5. Drop the renamed old table. Its indexes go with it.
|
|
70
|
-
DROP TABLE memory_v1_legacy;
|
|
71
|
-
|
|
72
|
-
-- 6. Recreate the indexes on the new table. Same names as schema.sql.
|
|
73
|
-
CREATE INDEX IF NOT EXISTS idx_memory_workspace ON memory(workspace);
|
|
74
|
-
CREATE INDEX IF NOT EXISTS idx_memory_type ON memory(type);
|
|
75
|
-
|
|
76
|
-
-- 7. Recreate the three FTS5 mirror triggers verbatim from schema.sql.
|
|
77
|
-
CREATE TRIGGER memory_ai AFTER INSERT ON memory BEGIN
|
|
78
|
-
INSERT INTO memory_fts(rowid, workspace, name, description, body)
|
|
79
|
-
VALUES (new.rowid, new.workspace, new.name, new.description, new.body);
|
|
80
|
-
END;
|
|
81
|
-
|
|
82
|
-
CREATE TRIGGER memory_ad AFTER DELETE ON memory BEGIN
|
|
83
|
-
INSERT INTO memory_fts(memory_fts, rowid, workspace, name, description, body)
|
|
84
|
-
VALUES ('delete', old.rowid, old.workspace, old.name, old.description, old.body);
|
|
85
|
-
END;
|
|
86
|
-
|
|
87
|
-
CREATE TRIGGER memory_au AFTER UPDATE ON memory BEGIN
|
|
88
|
-
INSERT INTO memory_fts(memory_fts, rowid, workspace, name, description, body)
|
|
89
|
-
VALUES ('delete', old.rowid, old.workspace, old.name, old.description, old.body);
|
|
90
|
-
INSERT INTO memory_fts(rowid, workspace, name, description, body)
|
|
91
|
-
VALUES (new.rowid, new.workspace, new.name, new.description, new.body);
|
|
92
|
-
END;
|
|
93
|
-
|
|
94
|
-
-- 8. Rebuild memory_fts from the new memory table. FTS5's native reindex:
|
|
95
|
-
-- clears the internal state and rescans the backing table. Cleaner than
|
|
96
|
-
-- DELETE + INSERT loops.
|
|
97
|
-
INSERT INTO memory_fts(memory_fts) VALUES('rebuild');
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
-- Migration v2 -> v3 (rename path).
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- v2 schema had:
|
|
6
|
-
-- context_contracts (workspace, section_name, payload, metadata, updated_at)
|
|
7
|
-
-- PK: (workspace, section_name)
|
|
8
|
-
--
|
|
9
|
-
-- v3 schema has:
|
|
10
|
-
-- project_context_contracts (workspace, contract_name, payload, metadata, updated_at)
|
|
11
|
-
-- PK: (workspace, contract_name)
|
|
12
|
-
-- + new table agent_contract_permissions
|
|
13
|
-
-- + new index idx_agent_contract_perms_agent
|
|
14
|
-
--
|
|
15
|
-
-- The rename of `context_contracts` -> `project_context_contracts` reflects
|
|
16
|
-
-- its actual role: rows are project-context contracts, not permission grants.
|
|
17
|
-
-- The column rename `section_name` -> `contract_name` aligns the vocabulary
|
|
18
|
-
-- with the permission model introduced alongside it.
|
|
19
|
-
--
|
|
20
|
-
-- Three real-world entry states
|
|
21
|
-
-- -----------------------------
|
|
22
|
-
-- State 1 (only old): context_contracts exists, project_context_contracts does NOT.
|
|
23
|
-
-- Typical of a clean v2 install upgrading for the first time.
|
|
24
|
-
-- This script handles state 1 via ALTER TABLE RENAME.
|
|
25
|
-
-- State 2 (only new): project_context_contracts exists, context_contracts does NOT,
|
|
26
|
-
-- agent_contract_permissions exists. Nothing to do -- the guard
|
|
27
|
-
-- probe in bootstrap_database.sh detects state 2 and stamps the
|
|
28
|
-
-- ledger without invoking this script.
|
|
29
|
-
-- State 3 (both): Both tables exist. Caused by a previous bootstrap where
|
|
30
|
-
-- schema.sql under v3 was applied (CREATE TABLE IF NOT EXISTS
|
|
31
|
-
-- created the new table) but the legacy context_contracts was
|
|
32
|
-
-- never dropped. State 3 needs row migration + drop, handled
|
|
33
|
-
-- by v2_to_v3_merge.sql -- not by this script.
|
|
34
|
-
--
|
|
35
|
-
-- bootstrap_database.sh selects state 1 vs 3 via the guard probe and runs the
|
|
36
|
-
-- matching script. Each script is therefore single-purpose and atomic.
|
|
37
|
-
--
|
|
38
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT. A failure
|
|
39
|
-
-- mid-flight rolls back to v2 state and the ledger row is NOT inserted, so the
|
|
40
|
-
-- next bootstrap retry will see the same pending migration.
|
|
41
|
-
|
|
42
|
-
-- 1. Rename the table.
|
|
43
|
-
ALTER TABLE context_contracts RENAME TO project_context_contracts;
|
|
44
|
-
|
|
45
|
-
-- 2. Rename the column.
|
|
46
|
-
ALTER TABLE project_context_contracts RENAME COLUMN section_name TO contract_name;
|
|
47
|
-
|
|
48
|
-
-- 3. Index on workspace -- name reflects the new table identity. The old
|
|
49
|
-
-- index moved with the table on RENAME TO, but its name still references
|
|
50
|
-
-- the legacy table. Drop + recreate keeps the index name consistent
|
|
51
|
-
-- with the new table identity.
|
|
52
|
-
DROP INDEX IF EXISTS idx_context_contracts_workspace;
|
|
53
|
-
CREATE INDEX IF NOT EXISTS idx_project_context_contracts_workspace
|
|
54
|
-
ON project_context_contracts(workspace);
|
|
55
|
-
|
|
56
|
-
-- 4. New permissions table + its index. IF NOT EXISTS makes the script
|
|
57
|
-
-- safe to re-run if a partial earlier attempt already created them.
|
|
58
|
-
CREATE TABLE IF NOT EXISTS agent_contract_permissions (
|
|
59
|
-
agent_name TEXT NOT NULL,
|
|
60
|
-
contract_name TEXT NOT NULL,
|
|
61
|
-
can_read INTEGER NOT NULL DEFAULT 0,
|
|
62
|
-
can_write INTEGER NOT NULL DEFAULT 0,
|
|
63
|
-
cloud_scope TEXT,
|
|
64
|
-
PRIMARY KEY (agent_name, contract_name, cloud_scope)
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
CREATE INDEX IF NOT EXISTS idx_agent_contract_perms_agent
|
|
68
|
-
ON agent_contract_permissions(agent_name);
|