ADR-121: Path Discovery Consolidation
Status
ACCEPTED (2026-01-27)
Context
Problem Statement
Following ADR-120 (Customer Extensions Architecture), which established ~/.coditect-data/ as the single location for all customer data and extensions, we discovered that 135+ files across the codebase have inconsistent path handling:
| Issue Type | Count | Description |
|---|---|---|
| Wrong import | 70+ | from paths import instead of from scripts.core.paths import |
| Hardcoded paths | 50+ | Path.home() / "PROJECTS" / ".coditect-data" inline |
| Inconsistent fallbacks | 30+ | Mixed patterns for handling import failures |
| MCP servers | 3 | Hardcoded paths, no centralized module usage |
Why This Matters
- ADR-114 Compliance: The path discovery module (
scripts/core/paths.py) implements configurable PROJECTS location, but most files bypass it - Customer Portability: Customers with non-standard PROJECTS locations will have broken tools
- Maintenance Burden: Path changes require updating 135+ files instead of one
- Extensions Support: ADR-120 added
extensions/directory which no existing code knows about
Discovery Process
MoE analysis using codebase exploration agents identified:
hooks/ 24 files with issues
hooks/validators/ 8 files with issues
scripts/ 100+ files with issues
scripts/core/ 15 files with issues
tools/mcp-*/ 3 files with issues
─────────────────────────────────────────
Total ~135 files need updating
Decision
1. Create Standardized Import Helper
Create scripts/core/paths_helper.py that:
- Automatically discovers and adds coditect-core to sys.path
- Re-exports all paths.py constants and functions
- Provides graceful fallbacks for bootstrapping scenarios
- Adds EXTENSIONS_DIR constant (ADR-120)
2. Establish Standard Import Pattern
All hooks and scripts MUST use this pattern:
# Path discovery (ADR-114, ADR-120)
import sys
from pathlib import Path
_script_dir = Path(__file__).resolve().parent.parent
if str(_script_dir) not in sys.path:
sys.path.insert(0, str(_script_dir))
try:
from scripts.core.paths import (
USER_DATA_LOC, CONTEXT_STORAGE, SESSION_LOGS, EXTENSIONS_DIR,
get_user_data_dir, get_context_storage_dir, get_session_logs_dir
)
PATHS_AVAILABLE = True
except ImportError:
PATHS_AVAILABLE = False
USER_DATA_LOC = Path.home() / "PROJECTS" / ".coditect-data"
CONTEXT_STORAGE = USER_DATA_LOC / "context-storage"
SESSION_LOGS = USER_DATA_LOC / "session-logs"
EXTENSIONS_DIR = USER_DATA_LOC / "extensions"
3. Add Extensions Directory to paths.py
Added get_extensions_dir() function and EXTENSIONS_DIR constant:
def get_extensions_dir() -> Path:
"""Get the customer extensions directory (ADR-120)."""
return get_user_data_dir() / "extensions"
EXTENSIONS_DIR = get_extensions_dir()
4. Update All Affected Files
Batch update all 135+ files to use the standardized import pattern.
Implementation
Phase 1: Infrastructure (Complete)
| File | Status | Purpose |
|---|---|---|
scripts/core/paths_helper.py | Created | Standardized import helper |
scripts/core/paths.py | Updated | Added get_extensions_dir(), EXTENSIONS_DIR |
Phase 2: Hooks (24 files)
Files in hooks/:
- dispatcher.py, pre-backup.py, post-backup.py, pre-restore.py, post-restore.py
- session-retrospective.py, session-retrospective-v2.py
- auto-session-namer.py, proactive-error-suggester.py
- session-start-context.py, session-auto-recall.py
- task-tracking-enforcer.py, task-plan-sync.py
- antipattern-detector.py, classify_document.py
- component-database-sync.py, hook_logger.py
- migration-safety-validator.py, scheduled-backup-monitor.py
- skill-preflight-validator.py, token-limit-pivot-detector.py
- context-threshold-monitor.py, export-centralizer.py
- post-meeting-analysis-hook.py
Phase 3: Validators (8 files)
Files in hooks/validators/:
- backup-integrity-validator.py
- context-extraction-validator.py
- context-query-validator.py
- orient-context-validator.py
- install-script-validator.py
- project-plan-update-validator.py
- task-id-protocol-validator.py
- deprecation-audit-validator.py
Phase 4: Core Scripts (15 files)
Files in scripts/core/:
- activation_test_suite.py, capability_discovery.py, cloud_sync_client.py
- component_metadata_registry.py, db_backup.py, db_init.py, db_migrate.py, db_seed.py
- ensure_component_registered.py, intent_context_manager.py
- license_validator.py, license-activate.py
- memory_context_integration.py, nested_learning.py, trajectory_logging.py
Phase 5: Main Scripts (85+ files)
Files in scripts/ using from paths import:
- work_items.py, query-work-items.py, migrate-tasks-to-v2.py
- trajectory_extractor.py, backup-status.py, generate-session-insights.py
- task-extraction-pipeline.py, migrate-ralph-wiggum-schema.py
- import-tasks-from-markdown.py, task-dispatcher.py, sync-project-plan.py
- memory-retrieval.py, learning-db-migrate.py, autonomous-orchestrator.py
- agent-executor.py, sync-daemon.py, skill-selector.py
- learning_db_query.py, component-discover.py, skill-mentor.py
- deduplicate-all-tables.py, audit_trail.py, context_snapshot.py
- component-indexer.py, reset-skill-learnings-baseline.py
- ... (70+ more)
Phase 6: MCP Servers (3 files)
Files in tools/:
- tools/mcp-impact-analysis/server.py
- tools/mcp-semantic-search/server.py
- tools/mcp-call-graph/server.py
Consequences
Positive
- Single Source of Truth: All path discovery goes through
paths.py - Customer Portability: $CODITECT_PROJECTS env var works everywhere
- ADR-120 Ready: Extensions directory available in all scripts
- Maintainability: Future path changes need only one file update
- Graceful Degradation: Fallback pattern handles bootstrapping
Negative
- Large Refactor: 135+ files need updating
- Risk of Regressions: Any file missed could break
- Import Overhead: Additional sys.path manipulation
Mitigation
- Batch Updates: Process files by category
- Verification Script: Run after each batch to verify imports work
- Fallbacks Preserved: Hardcoded fallbacks still work if import fails
Verification
# Test paths.py directly
python3 scripts/core/paths.py
# Test paths_helper.py
python3 scripts/core/paths_helper.py
# Test import from hook location
cd hooks && python3 -c "from scripts.core.paths import USER_DATA_LOC; print(USER_DATA_LOC)"
# Verify specific hook
python3 hooks/dispatcher.py --help
Related ADRs
| ADR | Title | Relationship |
|---|---|---|
| ADR-114 | User Data Separation | Parent - defines paths.py |
| ADR-120 | Customer Extensions | Adds extensions/ directory |
| ADR-118 | Four-Tier Database | Database paths in paths.py |
| ADR-057 | Initial Setup | Creates symlinks and paths |
Path Discovery Priority (ADR-114)
1. Environment variable: $CODITECT_PROJECTS
2. Config file: ~/.coditect/config/config.json → projects_dir
3. Symlink discovery: Find .coditect symlink parent
4. Default fallback: ~/PROJECTS
Final Structure
~/PROJECTS/.coditect-data/ # USER_DATA_LOC
├── machine-id.json # MACHINE_ID_FILE
├── checkpoints/
├── backups/ # BACKUPS_DIR
├── context-storage/ # CONTEXT_STORAGE
│ ├── org.db # ORG_DB
│ ├── sessions.db # SESSIONS_DB
│ ├── platform.db
│ └── unified_messages.jsonl
├── session-logs/ # SESSION_LOGS
│ └── SESSION-LOG-*.md
└── extensions/ # EXTENSIONS_DIR (NEW)
├── agents/
├── skills/
├── hooks/
├── commands/
├── scripts/
├── tools/
└── config/
Changelog
| Date | Author | Change |
|---|---|---|
| 2026-01-27 | Claude Opus 4.5 | Initial creation |
| 2026-01-27 | MoE Analysis | 135 files identified for update |