#!/usr/bin/env python3 """ Migration: Add dashboard columns to org.db:projects (ADR-170 Phase 0.1)
Adds dashboard_enabled and dashboard_config columns to the projects table in org.db to support autonomous dashboard refresh per ADR-170.
Usage: python3 scripts/migrations/add_dashboard_columns.py python3 scripts/migrations/add_dashboard_columns.py --dry-run python3 scripts/migrations/add_dashboard_columns.py --register-bioqms
ADR: ADR-170 (Multi-Project Executive Dashboard) Task: J.17.1, J.17.2 Created: 2026-02-16 """
import argparse import json import sqlite3 import sys from pathlib import Path
Add parent for imports
sys.path.insert(0, str(Path(file).resolve().parent.parent.parent)) from scripts.core.paths import get_org_db_path
def add_dashboard_columns(db_path: Path, dry_run: bool = False) -> bool: """Add dashboard_enabled and dashboard_config columns to projects table.""" conn = sqlite3.connect(str(db_path)) cursor = conn.cursor()
# Check if columns already exist
cursor.execute("PRAGMA table_info(projects)")
existing_cols = {row[1] for row in cursor.fetchall()}
added = []
if "dashboard_enabled" not in existing_cols:
if dry_run:
print("[DRY RUN] Would add: dashboard_enabled INTEGER DEFAULT 0")
else:
cursor.execute(
"ALTER TABLE projects ADD COLUMN dashboard_enabled INTEGER DEFAULT 0"
)
added.append("dashboard_enabled")
else:
print("Column dashboard_enabled already exists — skipping")
if "dashboard_config" not in existing_cols:
if dry_run:
print("[DRY RUN] Would add: dashboard_config TEXT")
else:
cursor.execute(
"ALTER TABLE projects ADD COLUMN dashboard_config TEXT"
)
added.append("dashboard_config")
else:
print("Column dashboard_config already exists — skipping")
if not dry_run and added:
conn.commit()
print(f"Added columns: {', '.join(added)}")
conn.close()
return len(added) > 0 or dry_run
def register_bioqms(db_path: Path, dry_run: bool = False) -> bool: """Register BIO-QMS as a dashboard-enabled project in org.db.""" conn = sqlite3.connect(str(db_path)) cursor = conn.cursor()
project_id = "BIO-QMS"
# Check if already registered
cursor.execute("SELECT project_id FROM projects WHERE project_id = ?", (project_id,))
existing = cursor.fetchone()
dashboard_config = {
"generator_script": "scripts/generate-project-dashboard-data.js",
"project_root": "submodules/dev/coditect-biosciences-qms-platform",
"output_dir": "public/",
"track_dir": "research/tracks/",
"phase2_enabled": True,
"refresh_triggers": ["session_log", "task_completion", "orient", "checkpoint"],
}
config_json = json.dumps(dashboard_config)
if existing:
if dry_run:
print(f"[DRY RUN] Would UPDATE {project_id}: dashboard_enabled=1")
else:
cursor.execute(
"UPDATE projects SET dashboard_enabled = 1, dashboard_config = ?, "
"updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now') "
"WHERE project_id = ?",
(config_json, project_id),
)
conn.commit()
print(f"Updated {project_id}: dashboard_enabled=1")
else:
if dry_run:
print(f"[DRY RUN] Would INSERT {project_id} with dashboard_enabled=1")
else:
cursor.execute(
"INSERT INTO projects (project_id, slug, name, description, scope, owner, "
"plan_location, status, dashboard_enabled, dashboard_config) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(
project_id,
"bio-qms",
"CODITECT Biosciences QMS Platform",
"AI-powered Quality Management System for regulated biosciences",
"project",
"hal@coditect.ai",
"submodules/dev/coditect-biosciences-qms-platform",
"active",
1,
config_json,
),
)
conn.commit()
print(f"Registered {project_id}: dashboard_enabled=1")
conn.close()
return True
def main(): parser = argparse.ArgumentParser( description="Add dashboard columns to org.db:projects (ADR-170)" ) parser.add_argument("--dry-run", action="store_true", help="Preview changes") parser.add_argument( "--register-bioqms", action="store_true", help="Also register BIO-QMS as dashboard-enabled", ) args = parser.parse_args()
db_path = get_org_db_path()
if not db_path.exists():
print(f"ERROR: org.db not found at {db_path}")
sys.exit(1)
print(f"Database: {db_path}")
print(f"Mode: {'DRY RUN' if args.dry_run else 'LIVE'}")
print()
# Step 1: Add columns
print("=== Step 1: Add dashboard columns ===")
add_dashboard_columns(db_path, dry_run=args.dry_run)
# Step 2: Register BIO-QMS (if requested)
if args.register_bioqms:
print()
print("=== Step 2: Register BIO-QMS ===")
register_bioqms(db_path, dry_run=args.dry_run)
print()
print("Done.")
if name == "main": main()