ADR-144: Multi-Project Registry Architecture
Status
ACCEPTED (2026-02-03)
Context
Problem Statement
CODITECT currently manages projects in a fragmented manner across multiple systems with no unified registry:
-
Scattered PROJECT-PLAN.md files - The coditect-rollout-master repository contains 74 git submodules, many of which have their own PROJECT-PLAN.md. There is no central index that maps all projects to their plan files, tracks, or ownership.
-
PILOT project has tracks but no registry entry - The primary PILOT project is tracked via TRACK-A through TRACK-N files under
internal/project/plans/pilot-tracks/, but there is no formal registry record connecting the PILOT project to these tracks, its metadata, or its lifecycle status. -
/projectcommand uses sessions.db with E001-T001 format - The existing/projectcommand (backed byscripts/work_items.py) stores work items in sessions.db using an epic-task format (E001-T001). This format does not align with the track-based nomenclature (A.9.1.3) defined in ADR-054, creating a dual-system confusion. -
/project-newcreates directories without registration - The/project-newcommand creates project directories under~/PROJECTS/with symlinks and component activation, but does not register the project in any central database. There is no way to list all projects created this way. -
No multi-tenant project isolation - The cloud API at
api.coditect.aisupports multi-tenant isolation via django-multitenant, but there is no local registry that distinguishes between internal CODITECT projects, customer projects (tenant-scoped), and contributor projects. -
No project switching - When working across multiple projects (e.g., switching between coditect-core framework work and a customer project), there is no mechanism to set the active project context, which affects task ID resolution, track loading, and session attribution.
Current State
| Component | Storage | Format | Limitation |
|---|---|---|---|
| PILOT tracks | Markdown files | TRACK-{X}-*.md | No registry, single project only |
/project command | sessions.db | E001-T001 | Disconnected from tracks, regenerable tier |
/project-new | Filesystem | Directory + symlinks | No registration, no discovery |
| Cloud API | PostgreSQL | django-multitenant | No local cache of project metadata |
| Submodule plans | Scattered .md files | Various | No central index |
Requirements
- A single registry that catalogs all projects regardless of origin (internal, customer, contributor)
- Storage in org.db (Tier 2, irreplaceable) since project metadata is organizational knowledge
- Mapping from projects to their track files, plan locations, and ownership
- Support for multi-tenant customer projects with cloud synchronization
- Backward compatibility with the existing E001-T001 work item format
- Project switching to set active context for task IDs, track loading, and session attribution
- Migration path for existing scattered PROJECT-PLAN.md files without requiring file moves
Decision
1. Project Registry in org.db (Tier 2)
Create a central project registry as two tables in org.db, the irreplaceable Tier 2 database (ADR-118). Project metadata represents accumulated organizational knowledge about what projects exist, who owns them, and how they are structured. This data cannot be regenerated from source files alone.
2. Database Schema
-- ============================================================
-- Table: projects
-- Purpose: Central registry of all CODITECT projects
-- Location: org.db (Tier 2 - irreplaceable)
-- ============================================================
CREATE TABLE IF NOT EXISTS projects (
project_id TEXT PRIMARY KEY,
slug TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
description TEXT,
scope TEXT NOT NULL CHECK (scope IN ('platform', 'org', 'customer', 'project')),
tenant_id TEXT,
owner TEXT NOT NULL,
plan_location TEXT NOT NULL,
tracks_config TEXT,
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'paused', 'completed', 'archived')),
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
metadata TEXT,
cloud_synced_at TEXT,
cloud_project_uuid TEXT
);
-- ============================================================
-- Table: project_tracks
-- Purpose: Map projects to their assigned tracks
-- Location: org.db (Tier 2 - irreplaceable)
-- ============================================================
CREATE TABLE IF NOT EXISTS project_tracks (
project_id TEXT NOT NULL REFERENCES projects(project_id) ON DELETE CASCADE,
track_letter TEXT NOT NULL,
track_name TEXT NOT NULL,
track_file TEXT NOT NULL,
tier INTEGER NOT NULL CHECK (tier IN (1, 2, 3)),
progress_pct REAL DEFAULT 0.0,
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'paused', 'completed', 'deferred')),
PRIMARY KEY (project_id, track_letter)
);
-- ============================================================
-- Indexes for common query patterns
-- ============================================================
CREATE INDEX IF NOT EXISTS idx_projects_scope ON projects(scope);
CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status);
CREATE INDEX IF NOT EXISTS idx_projects_tenant ON projects(tenant_id);
CREATE INDEX IF NOT EXISTS idx_projects_slug ON projects(slug);
CREATE INDEX IF NOT EXISTS idx_project_tracks_project ON project_tracks(project_id);
CREATE INDEX IF NOT EXISTS idx_project_tracks_letter ON project_tracks(track_letter);
-- ============================================================
-- View: active_projects
-- Purpose: Convenience view for common filtering
-- ============================================================
CREATE VIEW IF NOT EXISTS active_projects AS
SELECT
p.project_id,
p.slug,
p.name,
p.scope,
p.owner,
p.plan_location,
p.status,
COUNT(pt.track_letter) AS track_count,
AVG(pt.progress_pct) AS avg_progress
FROM projects p
LEFT JOIN project_tracks pt ON p.project_id = pt.project_id
WHERE p.status = 'active'
GROUP BY p.project_id;
3. Schema Field Definitions
| Field | Type | Description |
|---|---|---|
project_id | TEXT PK | Unique identifier. Convention: PILOT, ORG-<slug>, CUST-<tenant>-<slug>, PROJ-<slug> |
slug | TEXT UNIQUE | URL-safe identifier for API routes and file paths (e.g., pilot, artifact-cleanup, acme-webapp) |
name | TEXT | Human-readable display name (e.g., "CODITECT PILOT Launch") |
description | TEXT | Optional project description |
scope | TEXT | Isolation scope: platform (CODITECT internal), org (organization-level), customer (tenant-scoped), project (standalone) |
tenant_id | TEXT | NULL for internal projects. UUID for customer projects, matching django-multitenant tenant_id |
owner | TEXT | Team or user identifier (e.g., "core-team", "hal.casteel", "CUST-acme") |
plan_location | TEXT | Relative path from repository root to PROJECT-PLAN.md or equivalent (e.g., internal/project/plans/pilot-tracks/) |
tracks_config | TEXT | JSON object defining track configuration: {"letters": ["A","B","C"], "prefix": null, "tier": 1} |
status | TEXT | Lifecycle status: active, paused, completed, archived |
metadata | TEXT | JSON blob for project-specific configuration (e.g., {"launch_date": "2026-03-11", "budget": "50000"}) |
cloud_synced_at | TEXT | ISO 8601 timestamp of last successful cloud sync |
cloud_project_uuid | TEXT | UUID assigned by cloud API for cross-reference |
4. Scope Hierarchy
platform
scope: Internal CODITECT framework projects (e.g., PILOT)
tenant_id: NULL
tracks: Tier 1 (A-N framework tracks)
cloud_sync: Yes (to platform admin dashboard)
example: PILOT, coditect-core-v3
org
scope: Organization-level projects owned by AZ1.AI
tenant_id: NULL
tracks: Tier 2 (O-AA business tracks) or custom
cloud_sync: Yes (to org dashboard)
example: ORG-artifact-cleanup, ORG-docs-migration
customer
scope: Customer tenant projects, isolated by tenant_id
tenant_id: UUID (from django-multitenant)
tracks: Tier 2-3 (customer-defined). Tier 1 (A-N) requires explicit Platform Admin grant.
cloud_sync: Yes (to customer tenant dashboard)
example: CUST-acme-001-webapp, CUST-globex-002-api
project
scope: Standalone contributor or personal projects
tenant_id: NULL
tracks: Tier 3 (project-specific) or none
cloud_sync: Optional
example: PROJ-hal-experiment, PROJ-hackathon-q1
5. Registry Operations
5.1 CLI Tool: scripts/project_registry.py
# Register a project
python3 scripts/project_registry.py register \
--id PILOT \
--name "CODITECT PILOT Launch" \
--scope platform \
--owner core-team \
--plan-location "internal/project/plans/pilot-tracks/" \
--tracks A,B,C,D,E,F,G,H,I,J,K,L,M,N
# List projects
python3 scripts/project_registry.py list
python3 scripts/project_registry.py list --scope customer --status active
# Show project details
python3 scripts/project_registry.py show PILOT
# Update project
python3 scripts/project_registry.py update PILOT --status completed
# Scan and auto-register from submodules
python3 scripts/project_registry.py scan --root ~/PROJECTS/coditect-rollout-master
# Sync to cloud
python3 scripts/project_registry.py sync --project PILOT
python3 scripts/project_registry.py sync --all
5.2 Command Enhancements
/project register - New subcommand to register an existing project:
/project register # Interactive: detect from current directory
/project register --id ORG-docs --plan ./PROJECT-PLAN.md --scope org
/project list - Enhanced to query registry:
/project list # All active projects
/project list --scope customer # Customer projects only
/project list --owner hal.casteel # Projects by owner
/project show <id> - Enhanced with track details:
/project show PILOT
# Output:
# Project: CODITECT PILOT Launch (PILOT)
# Scope: platform | Owner: core-team | Status: active
# Plan: internal/project/plans/tracks/
# Tracks: A(100%) B(84%) C(81%) D(100%) E(100%) F(40%) ...
# Cloud: synced 2026-02-02T10:30:00Z
/project switch <id> - Set active project context:
/project switch PILOT
# Sets: $CODITECT_PROJECT=PILOT
# Loads: Track files A-N
# Updates: Statusline task section
/project-new enhancement - Auto-register on creation:
/project-new my-webapp --scope project --owner hal.casteel
# 1. Creates ~/PROJECTS/my-webapp/
# 2. Sets up symlinks
# 3. Registers as PROJ-my-webapp in org.db
# 4. Creates PROJECT-PLAN.md
# 5. Activates components
6. Project Discovery
6.1 Auto-Detection from Working Directory
When a session starts or /orient runs, the system resolves the active project by matching the current working directory against registered plan_location paths:
def discover_project(cwd: str) -> Optional[str]:
"""Resolve active project from current working directory."""
# 1. Check $CODITECT_PROJECT env var (explicit override)
if os.environ.get('CODITECT_PROJECT'):
return os.environ['CODITECT_PROJECT']
# 2. Query registry for matching plan_location
db = get_org_db_path()
conn = sqlite3.connect(db)
projects = conn.execute(
"SELECT project_id, plan_location FROM projects WHERE status = 'active'"
).fetchall()
# 3. Match cwd against plan locations (longest prefix match)
cwd_path = Path(cwd).resolve()
best_match = None
best_length = 0
for project_id, plan_loc in projects:
plan_path = Path(plan_loc).resolve()
try:
cwd_path.relative_to(plan_path.parent)
if len(str(plan_path)) > best_length:
best_match = project_id
best_length = len(str(plan_path))
except ValueError:
continue
return best_match
6.2 Agent Integration
Agents receive active project context through the $CODITECT_PROJECT environment variable:
# In agent invocation, project context is passed
/agent senior-architect "Design API for user service"
# Agent receives: CODITECT_PROJECT=PILOT
# Agent loads: PILOT track files (A-N)
# Agent uses: Task ID format A.x.y.z
7. Multi-Tenant Integration
7.1 Data Flow
┌─────────────────────────────────────┐
│ LOCAL (org.db) │
│ │
│ projects table │
│ ├─ PILOT (platform, tenant=NULL) │
│ ├─ ORG-docs (org, tenant=NULL) │
│ └─ CUST-acme-webapp (customer, │
│ tenant=abc-123-uuid) │
│ │
│ │ sync (ADR-053) │
│ ▼ │
├─────────────────────────────────────┤
│ CLOUD (api.coditect.ai) │
│ │
│ Project model (PostgreSQL) │
│ ├─ django-multitenant isolation │
│ ├─ tenant_id foreign key │
│ └─ RBAC via DRF permissions │
│ │
│ API Endpoints: │
│ POST /api/v1/projects/ │
│ GET /api/v1/projects/ │
│ GET /api/v1/projects/{uuid}/ │
│ PUT /api/v1/projects/{uuid}/ │
│ GET /api/v1/projects/{uuid}/tracks/│
└─────────────────────────────────────┘
7.2 Sync Rules
| Scope | Direction | Frequency | Source of Truth |
|---|---|---|---|
platform | local -> cloud | On change | Local (org.db) |
org | local -> cloud | On change | Local (org.db) |
customer | bidirectional | Periodic (5 min) | Cloud (PostgreSQL) |
project | local -> cloud (optional) | Manual | Local (org.db) |
For customer scope projects, the cloud API is the source of truth. Local org.db acts as a cache to enable offline access. Conflict resolution uses last-write-wins with the cloud timestamp taking precedence.
7.3 Cloud API Schema (Django Model)
# In coditect-cloud-infra/backend/coditect_license/projects/models.py
from django_multitenant.models import TenantModel
class Project(TenantModel):
tenant_id = 'tenant_id'
uuid = models.UUIDField(primary_key=True, default=uuid4)
tenant = models.ForeignKey('tenants.Tenant', on_delete=models.CASCADE)
project_id = models.CharField(max_length=128, unique=True)
slug = models.SlugField(max_length=128, unique=True)
name = models.CharField(max_length=256)
description = models.TextField(blank=True, default='')
scope = models.CharField(max_length=32, choices=SCOPE_CHOICES)
owner = models.CharField(max_length=128)
plan_location = models.CharField(max_length=512)
tracks_config = models.JSONField(default=dict, blank=True)
status = models.CharField(max_length=32, choices=STATUS_CHOICES, default='active')
metadata = models.JSONField(default=dict, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-updated_at']
class ProjectTrack(TenantModel):
tenant_id = 'tenant_id'
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='tracks')
tenant = models.ForeignKey('tenants.Tenant', on_delete=models.CASCADE)
track_letter = models.CharField(max_length=8)
track_name = models.CharField(max_length=128)
track_file = models.CharField(max_length=512)
tier = models.IntegerField()
progress_pct = models.FloatField(default=0.0)
status = models.CharField(max_length=32, choices=TRACK_STATUS_CHOICES, default='active')
class Meta:
unique_together = ['project', 'track_letter']
8. Reconciliation with work_items.py
The existing scripts/work_items.py uses an E001-T001 format (epic-task) stored in sessions.db (Tier 3). This system must coexist with the project registry during a transition period.
8.1 Bridge Mapping
| work_items.py | Project Registry | Mapping Rule |
|---|---|---|
| E001 | project_id | E001 = "PILOT" (default mapping) |
| E002 | project_id | E002 = "ORG-docs" (configured in metadata) |
| T001 | Track task | Sequential task within the epic/project |
8.2 Transition Plan
| Phase | Timeline | Action |
|---|---|---|
| Phase 1 | Immediate | Registry created, coexists with work_items.py |
| Phase 2 | +2 weeks | /project command reads from registry first, falls back to work_items.py |
| Phase 3 | +4 weeks | work_items.py writes to both sessions.db (legacy) and org.db (registry) |
| Phase 4 | +8 weeks | work_items.py deprecated; /project reads exclusively from registry |
8.3 Compatibility Layer
def resolve_epic_to_project(epic_id: str) -> Optional[str]:
"""Map legacy E001 epic ID to project registry project_id."""
# Check explicit mapping in org.db
conn = sqlite3.connect(get_org_db_path())
result = conn.execute(
"SELECT project_id FROM projects WHERE json_extract(metadata, '$.legacy_epic_id') = ?",
(epic_id,)
).fetchone()
if result:
return result[0]
# Default: E001 = PILOT
if epic_id == 'E001':
return 'PILOT'
return None
9. Migration Plan
9.1 Scan Existing Projects
A migration script scans all submodules and known project locations to discover unregistered projects:
python3 scripts/project_registry.py scan \
--root ~/PROJECTS/coditect-rollout-master \
--dry-run
The scanner:
- Walks all subdirectories of
submodules/looking forPROJECT-PLAN.md - Extracts project name from the plan file frontmatter or first heading
- Generates a
project_idfrom the directory path (e.g.,submodules/dev/coditect-clibecomesORG-coditect-cli) - Generates a
slugfrom the directory name - Outputs a registration plan for review
9.2 Seed Data
The following projects are registered at initialization:
-- PILOT project (primary)
INSERT INTO projects (project_id, slug, name, scope, owner, plan_location, tracks_config, status)
VALUES (
'PILOT',
'pilot',
'CODITECT PILOT Launch',
'platform',
'core-team',
'internal/project/plans/pilot-tracks/',
'{"letters": ["A","B","C","D","E","F","G","H","I","J","K","L","M","N"], "tier": 1}',
'active'
);
-- PILOT track registrations
INSERT INTO project_tracks (project_id, track_letter, track_name, track_file, tier, progress_pct, status) VALUES
('PILOT', 'A', 'Backend API', 'internal/project/plans/pilot-tracks/TRACK-A-backend-api.md', 1, 100.0, 'completed'),
('PILOT', 'B', 'Frontend UI', 'internal/project/plans/pilot-tracks/TRACK-B-frontend-ui.md', 1, 84.0, 'active'),
('PILOT', 'C', 'DevOps Infra', 'internal/project/plans/pilot-tracks/TRACK-C-devops-infra.md', 1, 81.0, 'active'),
('PILOT', 'D', 'Security', 'internal/project/plans/pilot-tracks/TRACK-D-security.md', 1, 100.0, 'completed'),
('PILOT', 'E', 'Testing QA', 'internal/project/plans/pilot-tracks/TRACK-E-testing-qa.md', 1, 100.0, 'completed'),
('PILOT', 'F', 'Documentation', 'internal/project/plans/pilot-tracks/TRACK-F-documentation.md', 1, 40.0, 'active'),
('PILOT', 'G', 'DMS Product', 'internal/project/plans/pilot-tracks/TRACK-G-dms-product.md', 1, 0.0, 'deferred'),
('PILOT', 'H', 'Framework Autonomy', 'internal/project/plans/pilot-tracks/TRACK-H-framework-autonomy.md', 1, 56.0, 'active'),
('PILOT', 'I', 'UI Components', 'internal/project/plans/pilot-tracks/TRACK-I-ui-components.md', 1, 100.0, 'completed'),
('PILOT', 'J', 'Memory Intelligence', 'internal/project/plans/pilot-tracks/TRACK-J-memory-intelligence.md', 1, 67.0, 'active'),
('PILOT', 'K', 'Workflow Automation', 'internal/project/plans/pilot-tracks/TRACK-K-workflow-automation.md', 1, 0.0, 'deferred'),
('PILOT', 'L', 'Extended Testing', 'internal/project/plans/pilot-tracks/TRACK-L-extended-testing.md', 1, 0.0, 'deferred'),
('PILOT', 'M', 'Extended Security', 'internal/project/plans/pilot-tracks/TRACK-M-extended-security.md', 1, 0.0, 'deferred'),
('PILOT', 'N', 'GTM Launch', 'internal/project/plans/pilot-tracks/TRACK-N-gtm-launch.md', 1, 61.0, 'active');
9.3 Migration Steps
| Step | Action | Impact |
|---|---|---|
| 1 | Run ALTER TABLE or CREATE TABLE on org.db | Adds two new tables, no existing data affected |
| 2 | Insert PILOT seed data | Registers primary project |
| 3 | Run scanner on submodules | Discovers and registers existing projects |
| 4 | Update /project command to read from registry | New code path, fallback to sessions.db |
| 5 | Update /project-new to auto-register | Enhancement, no breaking change |
| 6 | Add cloud sync endpoint for projects | New API endpoint, no migration needed |
| 7 | Deprecate E001-T001 format in work_items.py | Warning messages, dual-write |
No file moves are required. The registry points to existing plan file locations. Projects remain where they are; only the index is centralized.
10. Implementation Architecture
┌─────────────────────────────────────────────────────────────────┐
│ User Interface Layer │
│ │
│ /project list /project show /project switch │
│ /project register /project-new (enhanced) │
│ │
├───────────────────────────┬─────────────────────────────────────┤
│ Command Layer │ Agent Layer │
│ │ │
│ commands/project.md │ $CODITECT_PROJECT env var │
│ commands/project-new.md │ discover_project(cwd) │
│ │ Track loading per project │
│ │ │
├───────────────────────────┴─────────────────────────────────────┤
│ Registry Service Layer │
│ │
│ scripts/project_registry.py │
│ ├── register(project_id, name, scope, ...) │
│ ├── list(scope=None, status=None, owner=None) │
│ ├── show(project_id) -> ProjectDetail │
│ ├── update(project_id, **fields) │
│ ├── switch(project_id) -> sets env + loads tracks │
│ ├── scan(root_dir) -> List[UnregisteredProject] │
│ ├── sync(project_id=None) -> cloud push/pull │
│ └── resolve_epic(epic_id) -> project_id │
│ │
├─────────────────────────────────────────────────────────────────┤
│ Storage Layer │
│ │
│ org.db (Tier 2) │ Cloud API (PostgreSQL) │
│ ├── projects │ ├── Project model │
│ ├── project_tracks │ ├── ProjectTrack model │
│ └── active_projects (view) │ └── tenant isolation │
│ │ │
│ sessions.db (Tier 3) │ Filesystem │
│ └── work_items (legacy) │ └── PROJECT-PLAN.md files │
│ │
└─────────────────────────────────────────────────────────────────┘
11. Environment Variable Protocol
When a project is switched or auto-detected, the following environment variable is set:
| Variable | Example | Purpose |
|---|---|---|
CODITECT_PROJECT | PILOT | Active project ID for task routing |
This variable is consumed by:
- Statusline (Section 7: task) - Displays active project
- Task ID validator (
hooks/task_id_validator.py) - Validates track letters against project tracks - Agent dispatcher (
scripts/core/agent_dispatcher.py) - Passes project context to agents - Session logger - Attributes session work to the correct project
Consequences
Positive
- Unified project discovery - All projects indexed in one place, queryable by scope, status, owner, or track
- Multi-tenant readiness - Customer projects are cleanly isolated by tenant_id, matching the cloud API model
- Project switching - Agents and commands can load the correct tracks and validate task IDs for the active project
- No file reorganization - Registry points to existing file locations; no moves required
- Irreplaceable storage - org.db (Tier 2) ensures project metadata survives regenerable data loss
- Cloud synchronization - Projects sync to cloud dashboard for multi-device and team visibility
- Backward compatible - E001-T001 work items coexist during transition via explicit mapping
Negative
- Schema addition to org.db - Two new tables added to the critical Tier 2 database; requires careful migration
- Dual system during transition - work_items.py and project registry will coexist for approximately 8 weeks
- Registration overhead - Existing projects must be scanned and registered (one-time migration cost)
- Cloud API dependency - Customer project sync depends on the cloud API being available; offline mode mitigates this
Risks and Mitigations
| Risk | Likelihood | Mitigation |
|---|---|---|
| org.db corruption during migration | Low | Backup before ALTER TABLE; test on copy first |
| Stale registry entries for moved projects | Medium | Periodic scan validates plan_location exists |
| Cloud sync conflicts for customer projects | Medium | Last-write-wins with cloud timestamp precedence |
| Legacy E001 format confusion during transition | Medium | Clear deprecation warnings in work_items.py output |
Implementation Plan
Phase 1: Foundation (Week 1)
- Create
projectsandproject_trackstables in org.db schema - Implement
scripts/project_registry.pywith register, list, show, update operations - Add PILOT seed data migration
- Add
discover_project()function toscripts/core/paths.py
Phase 2: Command Integration (Week 2)
- Update
/projectcommand to read from registry (with sessions.db fallback) - Update
/project-newto auto-register created projects - Add
/project registersubcommand - Add
/project switchsubcommand with$CODITECT_PROJECTmanagement
Phase 3: Migration (Week 3)
- Implement submodule scanner (
project_registry.py scan) - Run migration to register all existing projects
- Add E001-to-project_id mapping layer in work_items.py
- Update statusline to display active project from registry
Phase 4: Cloud Sync (Week 4)
- Add Project and ProjectTrack Django models to cloud backend
- Create REST API endpoints for project CRUD
- Implement
project_registry.py synccommand - Add periodic sync for customer-scope projects
Phase 5: Deprecation (Weeks 5-8)
- Add deprecation warnings to work_items.py E001-T001 format
- Dual-write: work_items.py writes to both sessions.db and org.db
- Monitor for issues during transition
- Remove sessions.db work_items dependency after validation
Related ADRs
| ADR | Relationship |
|---|---|
| ADR-053 | Cloud sync architecture; project registry sync follows the same patterns |
| ADR-054 | Track nomenclature standard; project registry enforces track assignment |
| ADR-116 | Track-based plan architecture; registry indexes track files |
| ADR-117 | Hierarchical plan locations; registry stores plan_location per project |
| ADR-118 | Four-tier database; registry lives in org.db (Tier 2, irreplaceable) |
| ADR-145 | Project-level RBAC; uses project registry tenant_id for access scoping |
| ADR-146 | Unified task ID strategy; project prefix resolves against registry |