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:
-
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.
-
Scattered Plan Files: Multiple
PROJECT-PLAN.mdfiles exist across the repository tree (rollout-masterdocs/project-management/, individual submodules, etc.) with no central registry or discovery mechanism. -
Incompatible Task ID Formats: The
/project-newcommand and/projectcommand generateE001-T001-style task IDs, which are incompatible with theA.9.1.3-style track nomenclature defined in ADR-054 and enforced by governance hooks (ADR-074). -
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.
-
Missing Project Registry: No central index maps project identifiers to their plan locations, track assignments, scope levels, or ownership.
-
Template Without Instance:
config/tracks.template.jsonexists as a customer track template, but no actualconfig/tracks.jsonis 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
- Multi-Scope Support: Plans for platform, organization, customer, and project levels
- Track Isolation: No task ID collisions across projects or tenants
- Discoverability: Central registry for all active plans
- Backward Compatibility: Existing PILOT task IDs (
A.9.1.3) remain valid without modification - Cloud Sync Alignment: Plan hierarchy must map cleanly to the multi-tenant cloud API (ADR-053)
- 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:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique project identifier (slug format) |
name | string | Yes | Human-readable project name |
scope | enum | Yes | One of: platform, org, customer, project |
plan_location | string | Yes | Relative path (platform/org) or absolute path (customer/project) to plan directory |
track_assignments.tier | integer | Yes | Primary track tier (1, 2, or 3) |
track_assignments.tracks | array | Yes | List of assigned track letters |
track_assignments.namespace | string | No | Namespace prefix for task IDs (null for Tier 1) |
owner.team | string | Yes | Owning team identifier |
owner.lead | string | Yes | Project lead username |
status | enum | Yes | One of: active, paused, completed, archived |
cloud_sync.enabled | boolean | Yes | Whether cloud sync is active |
cloud_sync.tenant_id | string | Yes | Multi-tenant identifier (ADR-053) |
cloud_sync.project_id | string | Yes | Cloud project identifier |
created | string | Yes | ISO 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):
| Scope | Location |
|---|---|
| Platform | config/tracks.json (in coditect-core) |
| Organization | internal/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:
- If no namespace prefix, assume PILOT (platform scope) for Tier 1 tracks
- If no namespace prefix, assume org scope for Tier 2 tracks
- Tier 3 tracks always require a namespace prefix
- Customer task IDs always require a project namespace prefix
- The colon (
:) separates project prefix from track ID - 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:
| Scope | Sync Direction | Storage | Conflict Resolution |
|---|---|---|---|
| Platform | Local→Cloud | org.db + Cloud | org.db is SSOT, cloud is mirror |
| Org | Local→Cloud | org.db + Cloud | org.db is SSOT, cloud is mirror |
| Customer | Cloud→Local | Cloud + local cache | Cloud (PostgreSQL) is SSOT, local is cache |
| Project | Local→Cloud (optional) | org.db + optional cloud | org.db is SSOT, cloud is optional |
7. Integration with /project-new and /project Commands
The /project-new command MUST be updated to:
- Generate track-compatible task IDs instead of
E001-T001format - Register the project in
registry.json(or customer registry) - Allocate tracks based on scope and availability
- Create the directory structure at the appropriate level
- Instantiate
tracks.jsonfromconfig/tracks.template.jsonif custom tracks are needed
The /project command MUST be updated to:
- Discover the active project from registry or local
.coditect/directory - Resolve task IDs using the namespace appropriate to the project scope
- 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:
- The namespace matches the active project context
- The track is allocated to the referenced project
- Tier 1 tracks without namespace are only used in platform context
Consequences
Positive
- Multi-Project Support: Any number of projects can coexist without collision, each with its own plan location and track assignments
- Clean Multi-Tenancy: Customer projects are fully isolated by tenant namespace, aligning with the cloud API's django-multitenant architecture
- Backward Compatibility: All existing PILOT task IDs (
A.9.1.3) remain valid without any modification; the namespace is optional for platform scope - Discoverability: The central
registry.jsonprovides a single lookup point for all known projects, their locations, and their track assignments - 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
- Cloud Sync Clarity: The scope-to-tenant mapping is explicit, making cloud sync configuration straightforward
- Track Reuse: Org and customer projects can reference shared Tier 2 business tracks (O-AA) for cross-cutting concerns like compliance or strategy
- Template-Driven: New projects get consistent structure via templates, reducing setup friction
Negative
- Registry Maintenance: The org.db registry must be kept current; the optional
registry.jsonexport may drift from org.db if not regenerated - Namespace Verbosity: Customer task IDs (
ACME-WEBAPP:AB.1.2) are longer than bare IDs (A.9.1.3), increasing cognitive overhead - Hook Complexity: The governance hooks become more complex with namespace parsing and project-context resolution
- Migration Effort: Existing scattered
PROJECT-PLAN.mdfiles must be consolidated or registered - 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
- Registry Validation Script: A
scripts/validate-registry.pyscript will verify that all registered plan locations exist and all plan files are registered - Namespace Aliases: Frequently-used namespaces can be aliased in
config/config.json(e.g.,acforacme-corp) - Context Detection: Hooks will auto-detect project context from the current working directory, reducing the need to manually specify namespaces
- Migration Script: A
scripts/migrate-scattered-plans.pyscript will discover and register existingPROJECT-PLAN.mdfiles - 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)
| Task | Description |
|---|---|
Create registry.json schema | Define JSON Schema at config/schemas/project-registry-v1.schema.json |
Create initial registry.json | Register PILOT and pcf-operations projects |
| Create directory structure | Set up org-projects/, templates/, archive/ (pilot-tracks/ stays in place) |
| Seed org.db registry | Register PILOT and pcf-operations in org.db per ADR-144 |
| Create plan templates | PROJECT-PLAN-TEMPLATE.md, TRACK-TEMPLATE.md |
Phase 2: Namespace Support (Week 2)
| Task | Description |
|---|---|
| Update task ID validator | Extend regex to support namespaced task IDs |
| Update task tracking enforcer | Add namespace validation and project-context resolution |
Update /project-new command | Generate track-compatible IDs, register in registry |
Update /project command | Support namespace resolution and registry lookup |
Create validate-registry.py | Script to validate registry consistency |
Phase 3: Customer Support (Week 3)
| Task | Description |
|---|---|
| Create customer plan directory structure | Under ~/.coditect-data/customer-plans/ |
| Implement customer track allocation | Namespace assignment and collision prevention |
| Update cloud sync client | Map project scope to tenant/project in API calls |
Instantiate tracks.json from template | On /project-new for customer projects |
Phase 4: Migration (Week 4)
| Task | Description |
|---|---|
Create migrate-scattered-plans.py | Discover and register existing plan files |
| Migrate extended tracks | Move tracks/ content under appropriate scope |
| Archive deprecated files | Move master-project-plan.md to archive/ |
| Update CLAUDE.md | Document new hierarchy in all relevant CLAUDE.md files |
| Update MASTER-TRACK-INDEX.md | Reflect 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:
- Scan the repository tree for
PROJECT-PLAN.mdfiles - Determine the appropriate scope for each (platform, org, project)
- Register each in
registry.jsonwith its current location - Optionally relocate files to the canonical directory structure
- 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.
Related ADRs
| ADR | Relationship |
|---|---|
| ADR-054 | Defines the three-tier track nomenclature that this ADR extends with namespacing |
| ADR-053 | Defines the cloud sync architecture that this ADR maps plan hierarchy onto |
| ADR-115 | Defines hybrid task specification that must support namespaced IDs |
| ADR-116 | Defines track-based plan architecture for PILOT that this ADR generalizes to all projects |
| ADR-114 | Defines user-data separation; customer plans stored in user-data, not framework |
| ADR-118 | Defines four-tier database architecture; project registry is Tier 2 (org.db) data |
| ADR-074 | Defines governance hooks that must be updated for namespace validation |
| ADR-144 | Defines the authoritative project registry in org.db; registry.json is an export of this data |
| ADR-145 | Defines RBAC for project-level operations; plan scopes map to RBAC role scopes |
| ADR-146 | Defines unified task ID format with optional project prefix; aligns namespace strategy |
Version: 1.0.0 Author: Hal Casteel Approved By: Pending review