@jaguilar87/gaia 5.0.2 → 5.0.5
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/ARCHITECTURE.md +0 -1
- package/CHANGELOG.md +110 -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/approvals.py +23 -21
- package/bin/cli/cleanup.py +0 -1
- package/bin/cli/doctor.py +1 -1
- 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 -2
- 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 -2
- package/dist/gaia-ops/hooks/modules/agents/contract_validator.py +18 -0
- package/dist/gaia-ops/hooks/modules/agents/handoff_persister.py +214 -2
- package/dist/gaia-ops/hooks/modules/agents/response_contract.py +26 -0
- package/dist/gaia-ops/hooks/modules/agents/transcript_reader.py +15 -0
- package/dist/gaia-ops/hooks/modules/security/__init__.py +0 -5
- package/dist/gaia-ops/hooks/modules/security/approval_grants.py +124 -19
- package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +99 -7
- package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +127 -24
- 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/agent-contract-handoff/SKILL.md +3 -0
- package/dist/gaia-ops/skills/agent-response/SKILL.md +4 -2
- package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +1 -1
- package/dist/gaia-ops/skills/gaia-patterns/reference.md +2 -3
- 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 +30 -7
- package/dist/gaia-ops/skills/orchestrator-present-approval/reference.md +32 -15
- 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/skills/security-tiers/SKILL.md +5 -1
- package/dist/gaia-ops/skills/security-tiers/reference.md +3 -1
- package/dist/gaia-ops/skills/subagent-request-approval/SKILL.md +43 -6
- package/dist/gaia-ops/skills/subagent-request-approval/reference.md +66 -16
- package/dist/gaia-ops/tools/context/README.md +1 -1
- package/dist/gaia-ops/tools/gaia_simulator/extractor.py +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/contract_validator.py +18 -0
- package/dist/gaia-security/hooks/modules/agents/handoff_persister.py +214 -2
- package/dist/gaia-security/hooks/modules/agents/response_contract.py +26 -0
- package/dist/gaia-security/hooks/modules/agents/transcript_reader.py +15 -0
- package/dist/gaia-security/hooks/modules/security/__init__.py +0 -5
- package/dist/gaia-security/hooks/modules/security/approval_grants.py +124 -19
- package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +99 -7
- package/dist/gaia-security/hooks/modules/tools/bash_validator.py +127 -24
- package/dist/gaia-security/hooks/modules/validation/commit_validator.py +90 -55
- package/gaia/state/transitions.py +4 -4
- package/gaia/store/writer.py +56 -0
- package/hooks/modules/README.md +2 -4
- package/hooks/modules/agents/contract_validator.py +18 -0
- package/hooks/modules/agents/handoff_persister.py +214 -2
- package/hooks/modules/agents/response_contract.py +26 -0
- package/hooks/modules/agents/transcript_reader.py +15 -0
- package/hooks/modules/security/__init__.py +0 -5
- package/hooks/modules/security/approval_grants.py +124 -19
- package/hooks/modules/security/mutative_verbs.py +99 -7
- package/hooks/modules/tools/bash_validator.py +127 -24
- 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/agent-contract-handoff/SKILL.md +3 -0
- package/skills/agent-response/SKILL.md +4 -2
- package/skills/gaia-patterns/SKILL.md +1 -1
- package/skills/gaia-patterns/reference.md +2 -3
- 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 +30 -7
- package/skills/orchestrator-present-approval/reference.md +32 -15
- package/skills/readme-writing/SKILL.md +1 -1
- package/skills/readme-writing/reference.md +0 -1
- package/skills/security-tiers/SKILL.md +5 -1
- package/skills/security-tiers/reference.md +3 -1
- package/skills/subagent-request-approval/SKILL.md +43 -6
- package/skills/subagent-request-approval/reference.md +66 -16
- package/tools/context/README.md +1 -1
- package/tools/gaia_simulator/extractor.py +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/hooks/modules/security/gitops_validator.py +0 -179
- 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/dist/gaia-security/hooks/modules/security/gitops_validator.py +0 -179
- package/git-hooks/commit-msg +0 -41
- package/hooks/modules/security/gitops_validator.py +0 -179
- 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,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);
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
-- Migration v2 -> v3 (merge path).
|
|
2
|
-
--
|
|
3
|
-
-- Runs when the guard probe in bootstrap_database.sh detects "state 3" --
|
|
4
|
-
-- both `context_contracts` (legacy v2 table) AND `project_context_contracts`
|
|
5
|
-
-- (new v3 table) exist. This happens when an earlier bootstrap under v3
|
|
6
|
-
-- code applied schema.sql (which created the new table with IF NOT EXISTS)
|
|
7
|
-
-- but the old table was never dropped because schema.sql no longer declares
|
|
8
|
-
-- it and IF NOT EXISTS only creates -- it never drops.
|
|
9
|
-
--
|
|
10
|
-
-- See v2_to_v3.sql for the rename path (state 1) and for the full discussion
|
|
11
|
-
-- of the three entry states.
|
|
12
|
-
--
|
|
13
|
-
-- Strategy
|
|
14
|
-
-- --------
|
|
15
|
-
-- The new table is created in v3 shape (column `contract_name`), the old
|
|
16
|
-
-- table is in v2 shape (column `section_name`). The two columns are
|
|
17
|
-
-- semantically identical, so we copy rows with column aliasing:
|
|
18
|
-
--
|
|
19
|
-
-- INSERT INTO project_context_contracts (workspace, contract_name, ...)
|
|
20
|
-
-- SELECT workspace, section_name, ...
|
|
21
|
-
-- FROM context_contracts
|
|
22
|
-
-- WHERE (workspace, section_name) NOT IN (
|
|
23
|
-
-- SELECT workspace, contract_name FROM project_context_contracts
|
|
24
|
-
-- );
|
|
25
|
-
--
|
|
26
|
-
-- The NOT IN guard makes the copy idempotent: rows that were already
|
|
27
|
-
-- migrated by a prior partial run are skipped instead of duplicating PK
|
|
28
|
-
-- conflicts. Once the copy is complete and verified, the legacy table is
|
|
29
|
-
-- dropped along with its index.
|
|
30
|
-
--
|
|
31
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT. If
|
|
32
|
-
-- the copy or the drop fails, the transaction rolls back, the ledger is
|
|
33
|
-
-- NOT stamped, and the next bootstrap retry observes state 3 again.
|
|
34
|
-
|
|
35
|
-
-- 1. Copy rows from the legacy table into the new one, skipping any whose
|
|
36
|
-
-- primary key already exists in the new table.
|
|
37
|
-
INSERT INTO project_context_contracts (workspace, contract_name, payload, metadata, updated_at)
|
|
38
|
-
SELECT workspace, section_name, payload, metadata, updated_at
|
|
39
|
-
FROM context_contracts
|
|
40
|
-
WHERE (workspace, section_name) NOT IN (
|
|
41
|
-
SELECT workspace, contract_name FROM project_context_contracts
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
-- 2. Drop the legacy index explicitly. SQLite drops indexes with their
|
|
45
|
-
-- table on DROP TABLE, but being explicit catches the case where the
|
|
46
|
-
-- index was created standalone or renamed without us noticing.
|
|
47
|
-
DROP INDEX IF EXISTS idx_context_contracts_workspace;
|
|
48
|
-
|
|
49
|
-
-- 3. Drop the legacy table. Its rows have already been copied above.
|
|
50
|
-
DROP TABLE context_contracts;
|
|
51
|
-
|
|
52
|
-
-- 4. Ensure the new index exists with the canonical name (in case an
|
|
53
|
-
-- earlier partial run created the table but not its index).
|
|
54
|
-
CREATE INDEX IF NOT EXISTS idx_project_context_contracts_workspace
|
|
55
|
-
ON project_context_contracts(workspace);
|
|
56
|
-
|
|
57
|
-
-- 5. Permissions table + index. IF NOT EXISTS makes this safe whether
|
|
58
|
-
-- schema.sql already created them in a previous bootstrap or not.
|
|
59
|
-
CREATE TABLE IF NOT EXISTS agent_contract_permissions (
|
|
60
|
-
agent_name TEXT NOT NULL,
|
|
61
|
-
contract_name TEXT NOT NULL,
|
|
62
|
-
can_read INTEGER NOT NULL DEFAULT 0,
|
|
63
|
-
can_write INTEGER NOT NULL DEFAULT 0,
|
|
64
|
-
cloud_scope TEXT,
|
|
65
|
-
PRIMARY KEY (agent_name, contract_name, cloud_scope)
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
CREATE INDEX IF NOT EXISTS idx_agent_contract_perms_agent
|
|
69
|
-
ON agent_contract_permissions(agent_name);
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
-- Migration v3 -> v4 (memory model: class + status + memory_links).
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- v3 schema had:
|
|
6
|
-
-- memory(workspace, name, type, description, body, origin_session_id, updated_at)
|
|
7
|
-
-- PK: (workspace, name)
|
|
8
|
-
-- type CHECK constraint: ('project','user','feedback','atom','decision','negative')
|
|
9
|
-
--
|
|
10
|
-
-- v4 schema adds two ortogonal axes to the memory model:
|
|
11
|
-
-- * class -- semantic role (anchor | thread | log), nullable for legacy rows.
|
|
12
|
-
-- * status -- lifecycle for class=thread (open | carry_forward | graduated | closed).
|
|
13
|
-
--
|
|
14
|
-
-- Plus a new table:
|
|
15
|
-
-- memory_links(workspace, src_name, dst_name, kind, created_at)
|
|
16
|
-
-- PK: (workspace, src_name, dst_name, kind)
|
|
17
|
-
-- kind CHECK: ('relates_to','supersedes','derived_from','graduated_to')
|
|
18
|
-
--
|
|
19
|
-
-- Design decision: NO CHECK constraint on memory.class / memory.status
|
|
20
|
-
-- ---------------------------------------------------------------------
|
|
21
|
-
-- SQLite's ALTER TABLE ADD COLUMN cannot attach a CHECK that depends on
|
|
22
|
-
-- the new column's enum values. The standard workaround is a full table
|
|
23
|
-
-- rebuild (CREATE new, INSERT SELECT, DROP old, RENAME), which would:
|
|
24
|
-
-- 1. Force re-creation of memory_fts triggers (drift risk on live DBs).
|
|
25
|
-
-- 2. Move all existing memory rows through a copy step, complicating the
|
|
26
|
-
-- AC-2 contract that "the 36 me-workspace rows survive intact" with
|
|
27
|
-
-- byte-identical bodies.
|
|
28
|
-
-- 3. Add complexity disproportionate to the gain -- the writer layer
|
|
29
|
-
-- validates the enum on every upsert in T3 anyway.
|
|
30
|
-
--
|
|
31
|
-
-- Therefore: schema declares class/status as plain TEXT nullable columns.
|
|
32
|
-
-- Enum enforcement is the writer's job (gaia/store/writer.py, T3).
|
|
33
|
-
-- memory_links.kind keeps its CHECK because it is a brand-new table with
|
|
34
|
-
-- no rebuild cost.
|
|
35
|
-
--
|
|
36
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT. A
|
|
37
|
-
-- failure mid-flight rolls back to v3 state and the ledger row is NOT
|
|
38
|
-
-- inserted, so the next bootstrap retry sees the same pending migration.
|
|
39
|
-
|
|
40
|
-
-- 1. Add the two nullable columns to memory. Existing rows get NULL,
|
|
41
|
-
-- which is the documented "legacy row" state and is what T8/T9 will
|
|
42
|
-
-- reclassify interactively.
|
|
43
|
-
ALTER TABLE memory ADD COLUMN class TEXT;
|
|
44
|
-
ALTER TABLE memory ADD COLUMN status TEXT;
|
|
45
|
-
|
|
46
|
-
-- 2. Index on (workspace, class, status) -- supports the injector path
|
|
47
|
-
-- that picks class=thread/status=carry_forward first.
|
|
48
|
-
CREATE INDEX IF NOT EXISTS idx_memory_class_status
|
|
49
|
-
ON memory(workspace, class, status);
|
|
50
|
-
|
|
51
|
-
-- 3. New table memory_links + indexes. IF NOT EXISTS makes the script
|
|
52
|
-
-- idempotent if a partial earlier attempt already created them.
|
|
53
|
-
CREATE TABLE IF NOT EXISTS memory_links (
|
|
54
|
-
workspace TEXT NOT NULL,
|
|
55
|
-
src_name TEXT NOT NULL,
|
|
56
|
-
dst_name TEXT NOT NULL,
|
|
57
|
-
kind TEXT NOT NULL CHECK (kind IN ('relates_to', 'supersedes', 'derived_from', 'graduated_to')),
|
|
58
|
-
created_at TEXT,
|
|
59
|
-
PRIMARY KEY (workspace, src_name, dst_name, kind),
|
|
60
|
-
FOREIGN KEY (workspace) REFERENCES workspaces(name) ON DELETE CASCADE
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
CREATE INDEX IF NOT EXISTS memory_links_src
|
|
64
|
-
ON memory_links(workspace, src_name);
|
|
65
|
-
|
|
66
|
-
CREATE INDEX IF NOT EXISTS idx_memory_links_dst_kind
|
|
67
|
-
ON memory_links(workspace, dst_name, kind);
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
-- v3 -> v4 fresh-install variant.
|
|
2
|
-
--
|
|
3
|
-
-- Used by bootstrap_database.sh Section 3c case 4 when the live DDL is
|
|
4
|
-
-- already at the v4 target state (memory.class column present, memory_links
|
|
5
|
-
-- table present). This happens on a clean install where schema.sql already
|
|
6
|
-
-- created the v4 column layout and the memory_links table.
|
|
7
|
-
--
|
|
8
|
-
-- The default v3_to_v4.sql cannot run here because ALTER TABLE ADD COLUMN
|
|
9
|
-
-- fails when the column already exists. This variant carries only the DDL
|
|
10
|
-
-- that schema.sql cannot declare safely:
|
|
11
|
-
-- * idx_memory_class_status -- references columns added at ALTER time,
|
|
12
|
-
-- so schema.sql cannot pre-declare it (the replay on v3 DBs would parse-
|
|
13
|
-
-- fail before the migration ran).
|
|
14
|
-
--
|
|
15
|
-
-- Everything else (memory_links table, memory_links indexes) is declared in
|
|
16
|
-
-- schema.sql and is therefore already present on a fresh install. CREATE
|
|
17
|
-
-- INDEX IF NOT EXISTS makes this script safe to re-run.
|
|
18
|
-
|
|
19
|
-
CREATE INDEX IF NOT EXISTS idx_memory_class_status
|
|
20
|
-
ON memory(workspace, class, status);
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
-- Migration v4 -> v5 (state-machine completion: status columns on AC + milestones).
|
|
2
|
-
--
|
|
3
|
-
-- Background
|
|
4
|
-
-- ----------
|
|
5
|
-
-- v4 schema has:
|
|
6
|
-
-- acceptance_criteria(id, brief_id, ac_id, description, evidence_type,
|
|
7
|
-
-- evidence_shape, artifact_path)
|
|
8
|
-
-- milestones(id, brief_id, order_num, name, description)
|
|
9
|
-
--
|
|
10
|
-
-- v5 schema adds a status lifecycle column to both tables:
|
|
11
|
-
-- * acceptance_criteria.status -- lifecycle (pending | done | blocked)
|
|
12
|
-
-- * milestones.status -- lifecycle (pending | done | blocked)
|
|
13
|
-
--
|
|
14
|
-
-- Design decision: CHECK constraint inline on ADD COLUMN
|
|
15
|
-
-- -------------------------------------------------------
|
|
16
|
-
-- SQLite >= 3.37 supports ADD COLUMN with NOT NULL + DEFAULT + CHECK in a
|
|
17
|
-
-- single statement without a full table rebuild. The bootstrap environment
|
|
18
|
-
-- is confirmed at SQLite 3.45.1, so this is safe.
|
|
19
|
-
--
|
|
20
|
-
-- The enum values are intentionally small: pending (default), done (AC
|
|
21
|
-
-- satisfied / milestone reached), blocked (cannot progress, needs action).
|
|
22
|
-
-- They mirror the task lifecycle (pending|done|skipped) but substitute
|
|
23
|
-
-- 'blocked' for 'skipped' to distinguish an actively-stuck entity from one
|
|
24
|
-
-- that was explicitly bypassed.
|
|
25
|
-
--
|
|
26
|
-
-- D2 (backfill): explicit UPDATE after ALTER ensures pre-existing rows
|
|
27
|
-
-- carry 'pending'. The NOT NULL DEFAULT 'pending' covers new rows; the
|
|
28
|
-
-- UPDATE covers rows inserted before this migration.
|
|
29
|
-
--
|
|
30
|
-
-- Atomicity: bootstrap_database.sh wraps this script in BEGIN/COMMIT.
|
|
31
|
-
-- A failure mid-flight rolls back to v4 state and the ledger row is NOT
|
|
32
|
-
-- inserted, so the next bootstrap retry sees the same pending migration.
|
|
33
|
-
|
|
34
|
-
-- 1. Add status column to acceptance_criteria.
|
|
35
|
-
ALTER TABLE acceptance_criteria
|
|
36
|
-
ADD COLUMN status TEXT NOT NULL DEFAULT 'pending'
|
|
37
|
-
CHECK (status IN ('pending', 'done', 'blocked'));
|
|
38
|
-
|
|
39
|
-
-- 2. Backfill existing AC rows (D2: explicit UPDATE, all rows -> 'pending').
|
|
40
|
-
UPDATE acceptance_criteria SET status = 'pending' WHERE status IS NULL;
|
|
41
|
-
|
|
42
|
-
-- 3. Add status column to milestones.
|
|
43
|
-
ALTER TABLE milestones
|
|
44
|
-
ADD COLUMN status TEXT NOT NULL DEFAULT 'pending'
|
|
45
|
-
CHECK (status IN ('pending', 'done', 'blocked'));
|
|
46
|
-
|
|
47
|
-
-- 4. Backfill existing milestone rows (D2).
|
|
48
|
-
UPDATE milestones SET status = 'pending' WHERE status IS NULL;
|
|
49
|
-
|
|
50
|
-
-- 5. Indexes to support brief-scoped status queries efficiently.
|
|
51
|
-
CREATE INDEX IF NOT EXISTS idx_ac_brief_status
|
|
52
|
-
ON acceptance_criteria(brief_id, status);
|
|
53
|
-
|
|
54
|
-
CREATE INDEX IF NOT EXISTS idx_milestones_brief_status
|
|
55
|
-
ON milestones(brief_id, status);
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
-- v4 -> v5 fresh-install variant.
|
|
2
|
-
--
|
|
3
|
-
-- Used by bootstrap_database.sh Section 3c case 5 when the live DDL is
|
|
4
|
-
-- already at the v5 target state (acceptance_criteria.status column present,
|
|
5
|
-
-- milestones.status column present). This happens on a clean install where
|
|
6
|
-
-- schema.sql already created the v5 column layout.
|
|
7
|
-
--
|
|
8
|
-
-- The default v4_to_v5.sql cannot run here because ALTER TABLE ADD COLUMN
|
|
9
|
-
-- fails when the column already exists. This variant carries only the DDL
|
|
10
|
-
-- that schema.sql cannot declare safely:
|
|
11
|
-
-- * idx_ac_brief_status -- index on acceptance_criteria(brief_id, status)
|
|
12
|
-
-- * idx_milestones_brief_status -- index on milestones(brief_id, status)
|
|
13
|
-
--
|
|
14
|
-
-- Both indexes are CREATE INDEX IF NOT EXISTS, making this script safe to re-run.
|
|
15
|
-
|
|
16
|
-
CREATE INDEX IF NOT EXISTS idx_ac_brief_status
|
|
17
|
-
ON acceptance_criteria(brief_id, status);
|
|
18
|
-
|
|
19
|
-
CREATE INDEX IF NOT EXISTS idx_milestones_brief_status
|
|
20
|
-
ON milestones(brief_id, status);
|