Skip to main content

ADR-117: Hierarchical Plan Location Strategy

Status

PROPOSED (2026-02-02)

Context

Problem Statement

CODITECT's project planning system evolved around a single internal project (PILOT), with track files at internal/project/plans/pilot-tracks/TRACK-*.md and internal/project/plans/tracks/. As the framework matures toward multi-tenant deployment, several structural problems have emerged:

  1. Single-Project Assumption: ADR-116 defines track-based plan architecture exclusively for PILOT. There is no mechanism for non-PILOT projects such as operational maintenance, customer onboarding, or contributor projects.

  2. Scattered Plan Files: Multiple PROJECT-PLAN.md files exist across the repository tree (rollout-master docs/project-management/, individual submodules, etc.) with no central registry or discovery mechanism.

  3. Incompatible Task ID Formats: The /project-new command and /project command generate E001-T001-style task IDs, which are incompatible with the A.9.1.3-style track nomenclature defined in ADR-054 and enforced by governance hooks (ADR-074).

  4. No Track Allocation Governance: ADR-054 defines three tiers of tracks (A-N, O-AA, AB-AK), but there is no mechanism to allocate tracks to specific projects, prevent collisions between customer projects, or namespace task IDs across tenants.

  5. Missing Project Registry: No central index maps project identifiers to their plan locations, track assignments, scope levels, or ownership.

  6. Template Without Instance: config/tracks.template.json exists as a customer track template, but no actual config/tracks.json is instantiated, leaving the template disconnected from runtime behavior.

Current State

internal/project/plans/
├── pilot-tracks/ # Original PILOT track files (TRACK-A through TRACK-N)
├── tracks/ # Extended tracks (O-AK, plus some framework tracks)
│ ├── MASTER-TRACK-INDEX.md # Track index (PILOT-centric)
│ └── track-*.md # Individual track files
├── master-project-plan.md # Monolithic plan (deprecated by ADR-116)
├── current-sprint-plan.md # Sprint planning
└── CLAUDE.md # Plans directory context

Requirements

  1. Multi-Scope Support: Plans for platform, organization, customer, and project levels
  2. Track Isolation: No task ID collisions across projects or tenants
  3. Discoverability: Central registry for all active plans
  4. Backward Compatibility: Existing PILOT task IDs (A.9.1.3) remain valid without modification
  5. Cloud Sync Alignment: Plan hierarchy must map cleanly to the multi-tenant cloud API (ADR-053)
  6. Governance Compliance: All plans must be enforceable by existing hooks (ADR-074)

Decision

We adopt a four-level hierarchical plan location strategy with a central project registry and namespaced task IDs.

1. Plan Location Hierarchy

Plans are organized into four scope levels, each with a defined storage location and ownership model:

┌─────────────────────────────────────────────────────────────────────┐
│ PLAN LOCATION HIERARCHY │
│ │
│ Level 1: PLATFORM │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ internal/project/plans/pilot-tracks/ │ │
│ │ • CODITECT core framework development (PILOT) │ │
│ │ • Track Tier 1 (A-N): Reserved exclusively for platform │ │
│ │ • Owner: Platform Architecture Team │ │
│ │ • SSOT: TRACK-{A..N}-*.md │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ Level 2: ORG │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ internal/project/plans/org-projects/ │ │
│ │ • AZ1.AI internal operational projects │ │
│ │ • Track Tier 2 (O-AA): Shared org-wide business tracks │ │
│ │ • Owner: Org-level teams (ops, marketing, compliance) │ │
│ │ • Examples: artifact-cleanup, compliance-audit, gtm-launch │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ Level 3: CUSTOMER │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ ~/.coditect-data/customer-plans/{tenant-id}/ │ │
│ │ • Multi-tenant customer project plans │ │
│ │ • Track Tier 2-3: Customer-allocated tracks with namespace │ │
│ │ • Owner: Customer tenant admin │ │
│ │ • Stored in user-data (ADR-114), NOT in framework repo │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ Level 4: PROJECT │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ {project-root}/PROJECT-PLAN.md │ │
│ │ {project-root}/.coditect/plans/ │ │
│ │ • Individual project scope (any git repository) │ │
│ │ • Track Tier 3 (AB+): Project-specific, namespaced │ │
│ │ • Owner: Project lead / contributor │ │
│ │ • Created by /project-new, self-contained │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

2. Project Registry

The authoritative project registry is stored in org.db (Tier 2, irreplaceable) as defined in ADR-144. The registry.json file is an optional human-readable export generated from org.db for developer convenience and documentation purposes. It is NOT the source of truth.

Export location: internal/project/plans/registry.json Generate: python3 scripts/project_registry.py --export Authoritative source: org.db tables projects and project_tracks (see ADR-144)

Schema:

{
"$schema": "https://coditect.ai/schemas/project-registry-v1.schema.json",
"version": "1.0.0",
"updated": "2026-02-02T00:00:00Z",
"projects": [
{
"id": "pilot",
"name": "CODITECT PILOT",
"scope": "platform",
"plan_location": "internal/project/plans/pilot-tracks/",
"track_assignments": {
"tier": 1,
"tracks": ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"],
"namespace": null
},
"owner": {
"team": "platform-architecture",
"lead": "hal-casteel"
},
"status": "active",
"cloud_sync": {
"enabled": true,
"tenant_id": "az1ai",
"project_id": "pilot"
},
"created": "2025-09-01T00:00:00Z"
},
{
"id": "pcf-operations",
"name": "AZ1.AI Business Operations",
"scope": "org",
"plan_location": "internal/project/plans/org-projects/pcf-operations/",
"track_assignments": {
"tier": 2,
"tracks": ["O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA"],
"namespace": null
},
"owner": {
"team": "operations",
"lead": "hal-casteel"
},
"status": "active",
"cloud_sync": {
"enabled": true,
"tenant_id": "az1ai",
"project_id": "pcf-operations"
},
"created": "2026-01-05T00:00:00Z"
}
]
}

Registry Fields:

FieldTypeRequiredDescription
idstringYesUnique project identifier (slug format)
namestringYesHuman-readable project name
scopeenumYesOne of: platform, org, customer, project
plan_locationstringYesRelative path (platform/org) or absolute path (customer/project) to plan directory
track_assignments.tierintegerYesPrimary track tier (1, 2, or 3)
track_assignments.tracksarrayYesList of assigned track letters
track_assignments.namespacestringNoNamespace prefix for task IDs (null for Tier 1)
owner.teamstringYesOwning team identifier
owner.leadstringYesProject lead username
statusenumYesOne of: active, paused, completed, archived
cloud_sync.enabledbooleanYesWhether cloud sync is active
cloud_sync.tenant_idstringYesMulti-tenant identifier (ADR-053)
cloud_sync.project_idstringYesCloud project identifier
createdstringYesISO 8601 creation timestamp

3. Track Allocation Rules

Track allocation follows strict tiering to prevent collisions:

Tier 1: Platform-Reserved (A-N)

  • Exclusively allocated to the PILOT platform project
  • No other project may use tracks A through N
  • Task IDs use bare track format: A.9.1.3
  • Governance hooks enforce this reservation

Tier 2: Organization-Shared (O-AA)

  • Available to org-level and customer-level projects
  • Multiple projects may reference the same Tier 2 track when work spans organizational boundaries
  • Org projects use bare track format: O.1.2.3
  • Customer projects accessing Tier 2 tracks MUST use namespaced format: {project-id}:O.1.2.3

Tier 3: Project-Specific (AB+)

  • Available to any project at any scope level
  • Always namespaced to the owning project to prevent collision
  • Format: {project-id}:AB.1.2.3
  • Customer projects: {project-id}:AB.1.2.3

Custom Tracks

Projects may define custom tracks beyond AK by creating a tracks.json file (instantiated from config/tracks.template.json):

ScopeLocation
Platformconfig/tracks.json (in coditect-core)
Organizationinternal/project/plans/org-projects/{slug}/tracks.json
Customer~/.coditect-data/customer-plans/{tenant-id}/tracks.json
Project{project-root}/.coditect/tracks.json

4. Task ID Namespacing

Task IDs are extended with an optional namespace prefix to guarantee global uniqueness:

┌─────────────────────────────────────────────────────────────────┐
│ TASK ID FORMATS │
│ │
│ Platform (PILOT): │
│ A.9.1.3 │
│ │ └─── Section.Task.Subtask │
│ └───── Track letter (Tier 1, no namespace needed) │
│ │
│ Org: │
│ O.3.2.1 │
│ │ └─── Section.Task.Subtask │
│ └───── Track letter (Tier 2, no namespace for internal) │
│ │
│ Org (project-scoped): │
│ OPS-AC:C.2.1 │
│ ├─────┘ └──── Track.Section.Task │
│ └── Project namespace (when org project uses shared track) │
│ │
│ Customer: │
│ CUST-001:A.3.1.2 │
│ ├───────┘ └──── Track.Section.Task.Subtask │
│ └── Project namespace (required for all customer tasks) │
│ │
│ Customer (with project): │
│ ACME-WEBAPP:AB.1.2 │
│ ├──────────┘ └── Track.Section.Task │
│ └── Project namespace (case-insensitive, no slashes) │
│ │
└─────────────────────────────────────────────────────────────────┘

Namespace Resolution Rules:

  1. If no namespace prefix, assume PILOT (platform scope) for Tier 1 tracks
  2. If no namespace prefix, assume org scope for Tier 2 tracks
  3. Tier 3 tracks always require a namespace prefix
  4. Customer task IDs always require a project namespace prefix
  5. The colon (:) separates project prefix from track ID
  6. No slashes in local task IDs; slashes are reserved for cloud global IDs: {tenant_id}/{project_id}/{track.section.task}

Validation Regex:

# Full task ID pattern with optional project prefix (case-insensitive, no slashes)
NAMESPACED_TASK_ID = re.compile(
r'^'
r'(?:(?P<project>[A-Za-z][A-Za-z0-9-]{0,23}):)?' # Optional project prefix (1-24 chars)
r'(?P<track>[A-Z]{1,2})' # Track letter(s)
r'\.(?P<section>\d+)' # Section number
r'\.(?P<task>\d+)' # Task number
r'(?:\.(?P<subtask>\d+))?' # Optional subtask
r':\s*' # Colon + description
, re.IGNORECASE)

# Examples that match:
# A.9.1.3: Check migration status (platform)
# O.3.2.1: Review compliance checklist (org)
# CUST-001:A.3.1.2: Build user auth (customer)
# ACME-WEBAPP:AB.1.2: Create component (customer project)
# OPS-AC:C.2.1: Clean old images (org project)

5. Directory Structure

The complete plan directory structure after this ADR is implemented:

internal/project/plans/
├── registry.json # Optional human-readable export from org.db

├── pilot-tracks/ # Level 1: PILOT platform plans (A-N)
│ ├── TRACK-A-backend-api.md
│ ├── TRACK-B-frontend-ui.md
│ ├── TRACK-C-devops-infra.md
│ ├── TRACK-D-security.md
│ ├── TRACK-E-testing-qa.md
│ ├── TRACK-F-documentation.md
│ ├── TRACK-G-dms-product.md
│ ├── TRACK-H-framework-autonomy.md
│ ├── TRACK-I-ui-components.md
│ ├── TRACK-J-memory-intelligence.md
│ ├── TRACK-K-workflow-automation.md
│ ├── TRACK-L-extended-testing.md
│ ├── TRACK-M-extended-security.md
│ ├── TRACK-N-gtm-launch.md
│ └── MASTER-TRACK-INDEX.md # Platform track index

├── org-projects/ # Level 2: Org plans
│ ├── pcf-operations/ # PCF business tracks (O-AA)
│ │ ├── PROJECT-PLAN.md
│ │ └── tracks.json # Track configuration
│ ├── artifact-cleanup/ # Example operational project
│ │ ├── PROJECT-PLAN.md
│ │ └── tracks.json
│ └── gtm-launch/ # Example go-to-market project
│ ├── PROJECT-PLAN.md
│ └── tracks.json

├── tracks/ # Extended track definitions (O-AK)
│ ├── track-o-pcf-01-vision-strategy.md
│ ├── track-p-pcf-02-products-services.md
│ ├── ...
│ └── track-ak-sustainability-esg.md

├── templates/ # Plan templates
│ ├── PROJECT-PLAN-TEMPLATE.md # Standard plan template
│ ├── TRACK-TEMPLATE.md # Track file template
│ └── tracks-template.json # Track config template

└── archive/ # Completed/deprecated plans
└── master-project-plan.md # Deprecated monolithic plan

Customer and project-level plans (Levels 3 and 4) are stored outside the framework repository:

~/.coditect-data/customer-plans/           # Level 3: Customer plans
├── {tenant-id}/
│ ├── registry-entry.json # Cached registry entry
│ ├── tracks.json # Customer track config
│ └── projects/
│ └── {project-slug}/
│ ├── PROJECT-PLAN.md
│ └── tracks/
│ └── TRACK-*.md

{project-root}/ # Level 4: Project plans
├── .coditect/
│ ├── plans/
│ │ └── PROJECT-PLAN.md
│ └── tracks.json # Project-specific tracks
└── PROJECT-PLAN.md # Alternative location

6. Relationship to Cloud Sync (ADR-053)

The plan hierarchy maps directly to the multi-tenant cloud API:

┌─────────────────────────────────────────────────────────────────┐
│ CLOUD SYNC MAPPING │
│ │
│ LOCAL CLOUD (api.coditect.ai) │
│ │
│ registry.json GET /api/v1/projects/ │
│ ├── project.id ────────▶ project_id │
│ ├── project.scope ────────▶ scope (platform/org/customer) │
│ ├── project.cloud_sync auto-resolve tenant │
│ │ ├── tenant_id ────────▶ X-Tenant-ID header │
│ │ └── project_id ────────▶ URL path parameter │
│ └── project.status ────────▶ project.status │
│ │
│ TRACK-*.md tasks POST /api/v1/context/tasks/ │
│ ├── task_id (namespaced) ───────▶ task_id │
│ ├── track ───────▶ track │
│ └── status ───────▶ status │
│ │
│ Multi-Tenant Isolation: │
│ django-multitenant auto-isolates by tenant_id │
│ Platform (AZ1.AI) │
│ └── Tenant (az1ai / acme-corp / ...) │
│ └── Project (pilot / webapp / ...) │
│ └── Tasks (A.9.1.3 / acme-corp:A.3.1.2 / ...) │
│ │
└─────────────────────────────────────────────────────────────────┘

Sync Behavior by Scope:

ScopeSync DirectionStorageConflict Resolution
PlatformLocal→Cloudorg.db + Cloudorg.db is SSOT, cloud is mirror
OrgLocal→Cloudorg.db + Cloudorg.db is SSOT, cloud is mirror
CustomerCloud→LocalCloud + local cacheCloud (PostgreSQL) is SSOT, local is cache
ProjectLocal→Cloud (optional)org.db + optional cloudorg.db is SSOT, cloud is optional

7. Integration with /project-new and /project Commands

The /project-new command MUST be updated to:

  1. Generate track-compatible task IDs instead of E001-T001 format
  2. Register the project in registry.json (or customer registry)
  3. Allocate tracks based on scope and availability
  4. Create the directory structure at the appropriate level
  5. Instantiate tracks.json from config/tracks.template.json if custom tracks are needed

The /project command MUST be updated to:

  1. Discover the active project from registry or local .coditect/ directory
  2. Resolve task IDs using the namespace appropriate to the project scope
  3. Route cloud sync to the correct tenant and project

8. Governance Hook Updates

The task ID validator (ADR-074) must be extended to support namespaced task IDs:

# hooks/task-id-validator.py changes:

# Current pattern (platform only):
TASK_ID_PATTERN = re.compile(r'^[A-Z]{1,2}\.\d+\.\d+(\.\d+)?:\s*')

# Extended pattern (all scopes, case-insensitive project prefix, no slashes):
TASK_ID_PATTERN = re.compile(
r'^(?:[A-Za-z][A-Za-z0-9-]{0,23}:)?'
r'[A-Z]{1,2}\.\d+\.\d+(?:\.\d+)?:\s*'
)

The task tracking enforcer must validate that:

  1. The namespace matches the active project context
  2. The track is allocated to the referenced project
  3. Tier 1 tracks without namespace are only used in platform context

Consequences

Positive

  1. Multi-Project Support: Any number of projects can coexist without collision, each with its own plan location and track assignments
  2. Clean Multi-Tenancy: Customer projects are fully isolated by tenant namespace, aligning with the cloud API's django-multitenant architecture
  3. Backward Compatibility: All existing PILOT task IDs (A.9.1.3) remain valid without any modification; the namespace is optional for platform scope
  4. Discoverability: The central registry.json provides a single lookup point for all known projects, their locations, and their track assignments
  5. Separation of Concerns: Platform plans stay in the framework repo (version-controlled), customer plans stay in user-data (ADR-114), and project plans stay with their source code
  6. Cloud Sync Clarity: The scope-to-tenant mapping is explicit, making cloud sync configuration straightforward
  7. Track Reuse: Org and customer projects can reference shared Tier 2 business tracks (O-AA) for cross-cutting concerns like compliance or strategy
  8. Template-Driven: New projects get consistent structure via templates, reducing setup friction

Negative

  1. Registry Maintenance: The org.db registry must be kept current; the optional registry.json export may drift from org.db if not regenerated
  2. Namespace Verbosity: Customer task IDs (ACME-WEBAPP:AB.1.2) are longer than bare IDs (A.9.1.3), increasing cognitive overhead
  3. Hook Complexity: The governance hooks become more complex with namespace parsing and project-context resolution
  4. Migration Effort: Existing scattered PROJECT-PLAN.md files must be consolidated or registered
  5. Cloud Dependency for Customers: Platform/org projects use local org.db (SSOT, pushed to cloud), while customer projects use cloud PostgreSQL (SSOT, cached locally), requiring connectivity for full customer project visibility

Mitigations

  1. Registry Validation Script: A scripts/validate-registry.py script will verify that all registered plan locations exist and all plan files are registered
  2. Namespace Aliases: Frequently-used namespaces can be aliased in config/config.json (e.g., ac for acme-corp)
  3. Context Detection: Hooks will auto-detect project context from the current working directory, reducing the need to manually specify namespaces
  4. Migration Script: A scripts/migrate-scattered-plans.py script will discover and register existing PROJECT-PLAN.md files
  5. Unified Discovery API: The cloud API will expose a /api/v1/projects/ endpoint that merges both local and cloud registries for unified project discovery

Implementation Plan

Phase 1: Foundation (Week 1)

TaskDescription
Create registry.json schemaDefine JSON Schema at config/schemas/project-registry-v1.schema.json
Create initial registry.jsonRegister PILOT and pcf-operations projects
Create directory structureSet up org-projects/, templates/, archive/ (pilot-tracks/ stays in place)
Seed org.db registryRegister PILOT and pcf-operations in org.db per ADR-144
Create plan templatesPROJECT-PLAN-TEMPLATE.md, TRACK-TEMPLATE.md

Phase 2: Namespace Support (Week 2)

TaskDescription
Update task ID validatorExtend regex to support namespaced task IDs
Update task tracking enforcerAdd namespace validation and project-context resolution
Update /project-new commandGenerate track-compatible IDs, register in registry
Update /project commandSupport namespace resolution and registry lookup
Create validate-registry.pyScript to validate registry consistency

Phase 3: Customer Support (Week 3)

TaskDescription
Create customer plan directory structureUnder ~/.coditect-data/customer-plans/
Implement customer track allocationNamespace assignment and collision prevention
Update cloud sync clientMap project scope to tenant/project in API calls
Instantiate tracks.json from templateOn /project-new for customer projects

Phase 4: Migration (Week 4)

TaskDescription
Create migrate-scattered-plans.pyDiscover and register existing plan files
Migrate extended tracksMove tracks/ content under appropriate scope
Archive deprecated filesMove master-project-plan.md to archive/
Update CLAUDE.mdDocument new hierarchy in all relevant CLAUDE.md files
Update MASTER-TRACK-INDEX.mdReflect new directory locations

Migration Strategy

Existing PILOT Plan Files

PILOT track files remain at their current location: internal/project/plans/pilot-tracks/. No directory move is required. The pilot-tracks/ directory stays at the top level of the plans hierarchy, not nested under a platform/ subdirectory.

Extended Track Files

Track files at internal/project/plans/tracks/ (O-AK) remain at their current location as shared definitions. They are not project-specific; they define the track schema. Individual project plans that use these tracks store their task lists in their own PROJECT-PLAN.md or project-specific track files.

Scattered PROJECT-PLAN.md Files

The migration script will:

  1. Scan the repository tree for PROJECT-PLAN.md files
  2. Determine the appropriate scope for each (platform, org, project)
  3. Register each in registry.json with its current location
  4. Optionally relocate files to the canonical directory structure
  5. Generate a migration report listing all discovered plans and their disposition

E001-T001 Task IDs

Existing E001-T001-format task IDs in /project command output are not migrated retroactively. The /project and /project-new commands are updated to generate track-format IDs going forward. Legacy task IDs remain valid in their original context but are not registered in the new system.

ADRRelationship
ADR-054Defines the three-tier track nomenclature that this ADR extends with namespacing
ADR-053Defines the cloud sync architecture that this ADR maps plan hierarchy onto
ADR-115Defines hybrid task specification that must support namespaced IDs
ADR-116Defines track-based plan architecture for PILOT that this ADR generalizes to all projects
ADR-114Defines user-data separation; customer plans stored in user-data, not framework
ADR-118Defines four-tier database architecture; project registry is Tier 2 (org.db) data
ADR-074Defines governance hooks that must be updated for namespace validation
ADR-144Defines the authoritative project registry in org.db; registry.json is an export of this data
ADR-145Defines RBAC for project-level operations; plan scopes map to RBAC role scopes
ADR-146Defines unified task ID format with optional project prefix; aligns namespace strategy

Version: 1.0.0 Author: Hal Casteel Approved By: Pending review