# Technical Specification: Roadcrew Submodule Isolation

> **Type:** Technical Specification  
> **Version:** 1.0  
> **Date:** 2025-01-24  
> **Status:** Draft

**Related Documents:**
- [PRD: Submodule Isolation](../prds/submodule-isolation-prd.md) - Product requirements and business context
- [Monetization Strategy](../../docs/monetization-strategy.md) - Business model and premium features
- [Vision](../vision.md) - Product vision and roadmap

---

## Overview

This specification defines the technical implementation for Roadcrew's submodule isolation model, enabling clean installation into user projects without namespace conflicts. It covers installation scripts, command path resolution, template instantiation, mode detection, and premium feature gating.

**Scope:**
- Mode 0: Template repository structure
- Mode 1: Submodule installation process
- Mode 2: Multi-repo orchestration (Enterprise)
- License validation system
- Update/upgrade mechanisms

---

## Architecture Overview

### Three Deployment Modes

```
Mode 0 (Template Repo)          Mode 1 (Submodule)              Mode 2 (Multi-Repo)
├── .submodule/                 ├── .roadcrew/                  ├── .cursor/commands/
│   ├── commands/               │   ├── commands/               ├── milestones/
│   ├── templates/              │   ├── templates/              │   ├── frontend-v2.md
│   └── install.js              │   └── install.js              │   └── backend-v3.md
├── milestones/                 ├── .cursor/commands/           └── config/
│   └── vision.md          │   ├── context/                    ├── repos.yml
└── .cursor/commands/           │   └── milestones/             └── tech-stack-*.md
                                └── src/
```

**Key Relationships:**
- Mode 0 → Mode 1: `.submodule/` contents deployed as `.roadcrew/` submodule
- Mode 0 → Mode 2: Template repo forked/cloned, commands used directly from `.cursor/commands/`
- Mode 1 → Mode 2: Not applicable (different use cases)

---

## Mode 0: Template Repository Structure

### Directory Layout

```
roadcrew/                              # github.com/org/roadcrew
├── .cursor/
│   └── commands/                      # Active commands for Roadcrew development
│       └── *.md                       # Dogfooding: use Roadcrew to build Roadcrew
│
├── .github/
│   └── workflows/
│       ├── ci.yml                     # TypeScript compilation, linting, tests
│       └── release.yml                # Version tagging, changelog generation
│
├── .submodule/                        # What gets deployed in Mode 1
│   ├── commands/                      # ALL commands (free + gated premium)
│   │   ├── advance-release.md
│   │   ├── analyze-repo.md
│   │   ├── complete-release.md
│   │   ├── enrich-release.md          # FREE: manual, PREMIUM: --ai flag
│   │   ├── guide-release.md
│   │   ├── release-flow.md            # PREMIUM: Starter tier
│   │   ├── scope-release.md           # FREE: basic, PREMIUM: --toc flag
│   │   ├── sync-release-status.md
│   │   ├── validate-release.md
│   │   └── watch-milestone.md         # PREMIUM: Starter tier
│   │
│   ├── templates/                     # Document templates (all free tier)
│   │   ├── vision.template.md
│   │   ├── epic.template.md
│   │   ├── spec.template.md
│   │   ├── current-release.template.md
│   │   ├── future-releases.template.md
│   │   └── ai-context.template.yml
│   │
│   ├── scripts/                       # Utility scripts for commands
│   │   ├── utils/
│   │   │   ├── github.ts              # GitHub API helpers
│   │   │   ├── markdown-parser.ts     # Parse release files
│   │   │   ├── license-validator.ts   # Premium feature gating
│   │   │   ├── mode-detector.ts       # Detect submodule/multi-repo/standalone
│   │   │   └── path-resolver.ts       # Resolve .roadcrew/ paths
│   │   └── lib/
│   │       ├── api-client.ts          # Roadcrew API client (premium features)
│   │       └── toc-classifier.ts      # Theory of Constraints classification
│   │
│   ├── install.js                     # Installation script for Mode 1
│   ├── package.json                   # Minimal dependencies (free tier)
│   └── README.md                      # Quick reference + links to online docs
│
├── context/                           # Strategic documents
│   ├── vision.md                      # Roadcrew's product vision
│   ├── brds/                          # Business requirements
│   │   └── monetization-strategy.md
│   ├── prds/                          # Product requirements
│   │   ├── ai-prd.md
│   │   └── submodule-isolation-prd.md
│   ├── specs/                         # Technical specifications
│   │   ├── ai-issue-classification.md
│   │   ├── classification-guide.md
│   │   └── submodule-isolation-spec.md
│   └── research/                      # Research and analysis
│       └── ai-issue-refs.md
│
├── milestones/                        # Roadcrew's own planning (dogfooding)
│   ├── current-release.md             # Current release planning
│   ├── future-releases.md             # Future roadmap
│   ├── minor-release.md               # Minor release tracking
│   └── past-releases.md               # Release history
│
├── config/                            # Configuration files
│   ├── reports/                       # Analysis reports (gitignored)
│   │   ├── exemplars/                 # Code example files
│   │   └── YYYY-MM-DD-HHMMSS.md      # Timestamped reports
│   ├── schema/                        # Database/data schemas
│   │   └── schema.prisma              # Prisma schema
│   ├── current-schema.md              # Current database schema docs
│   └── tech-stack.md                  # Auto-generated tech stack
│
├── docs/                              # Documentation
│   ├── commands.md                    # Command reference
│   ├── deployment-modes.md            # Mode 0/1/2 explanation
│   ├── monetization-strategy.md       # Business model
│   └── architecture.md                # System architecture
│
├── scripts/                           # Build and utility scripts
│   ├── build-submodule.sh            # Copy .submodule/ for distribution
│   └── utils/                         # Shared utilities
│
├── tests/                             # Test suite
│   ├── install.test.ts               # Installation tests
│   ├── mode-detection.test.ts        # Mode detection tests
│   └── license-validation.test.ts    # Premium gating tests
│
├── .cursorrules.md                    # Cursor IDE rules for development
├── .env.local                         # Local environment variables
├── .gitignore                         # Git ignore rules
├── ai-context.yml                     # AI context configuration
├── CHANGELOG.md                       # Version history
├── eslint.config.js                   # ESLint configuration
├── LICENSE                            # MIT License
├── package.json                       # Node.js dependencies
├── README.md                          # Project documentation
└── tsconfig.json                      # TypeScript configuration
```

### Key Design Decisions

**1. `.submodule/` Folder:**
- Contains ONLY files deployed to Mode 1 users
- Mirrors exactly what appears in user's `.roadcrew/` folder
- Git-tracked, versioned, tagged for releases

**2. Dual Command Sets:**
- `.cursor/commands/` → Active commands for Roadcrew development (dogfooding)
- `.submodule/commands/` → Distribution source for Mode 1 installations

**3. Separated `context/` and `milestones/`:**
- `context/` contains strategic documents (vision, BRDs, PRDs, specs, research)
- `milestones/` contains release planning (current, future, minor, past releases)
- Clearer hierarchy: vision → PRDs → specs → milestones → issues

**4. `config/reports/` for Analysis:**
- Single location for all `analyze-repo` outputs
- Gitignored (too large, ephemeral)
- Replaces scattered `.analysis/` and `config/repo-analysis/`

---

## Mode 1: Submodule Installation

### Installation Flow

**User Actions:**
```bash
cd my-saas-app

# 1. Add Roadcrew as submodule
git submodule add https://github.com/org/roadcrew .roadcrew

# 2. Initialize submodule
git submodule update --init --recursive

# 3. Run installation script
node .roadcrew/install.js

# Or via npm script (if package.json configured)
npm run roadcrew:install
```

### install.js Implementation

**File:** `.submodule/install.js`

```javascript
#!/usr/bin/env node

/**
 * Roadcrew Installation Script
 * 
 * Installs Roadcrew into a project by:
 * 1. Creating required directories
 * 2. Copying commands to .cursor/commands/
 * 3. Instantiating templates
 * 4. Updating .gitignore
 * 5. Displaying next steps
 */

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

// Configuration
const ROADCREW_DIR = '.roadcrew';
const COMMANDS_SOURCE = path.join(ROADCREW_DIR, 'commands');
const COMMANDS_DEST = '.cursor/commands';
const TEMPLATES_DIR = path.join(ROADCREW_DIR, 'templates');

// Required directories at project root
const REQUIRED_DIRS = [
  'context',
  'context/specs',
  'milestones',
  'config'
];

// Files to create from templates
const TEMPLATE_FILES = [
  { template: 'vision.template.md', output: 'memory-bank/activeContext.md (legacy: context/vision.md)' },
  { template: 'current-release.template.md', output: 'milestones/current-release.md' },
  { template: 'future-releases.template.md', output: 'milestones/future-releases.md' },
  { template: 'ai-context.template.yml', output: '.ai-context.yml' }
];

// Main installation function
async function install() {
  console.log('🚀 Installing Roadcrew...\n');

  try {
    // Step 1: Verify submodule exists
    verifySubmodule();

    // Step 2: Create directory structure
    createDirectories();

    // Step 3: Copy commands
    copyCommands();

    // Step 4: Instantiate templates
    instantiateTemplates();

    // Step 5: Update .gitignore
    updateGitignore();

    // Step 6: Display success message
    displayNextSteps();

  } catch (error) {
    console.error('❌ Installation failed:', error.message);
    process.exit(1);
  }
}

function verifySubmodule() {
  if (!fs.existsSync(ROADCREW_DIR)) {
    throw new Error(
      `.roadcrew/ submodule not found. Run:\n` +
      `  git submodule add https://github.com/org/roadcrew .roadcrew`
    );
  }

  if (!fs.existsSync(COMMANDS_SOURCE)) {
    throw new Error(
      `Commands not found in ${COMMANDS_SOURCE}. ` +
      `Run: git submodule update --init --recursive`
    );
  }

  console.log('✓ Verified .roadcrew/ submodule');
}

function createDirectories() {
  REQUIRED_DIRS.forEach(dir => {
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
      console.log(`✓ Created ${dir}/`);
    } else {
      console.log(`  Skipped ${dir}/ (already exists)`);
    }
  });
}

function copyCommands() {
  // Create .cursor/commands/ if needed
  if (!fs.existsSync(COMMANDS_DEST)) {
    fs.mkdirSync(COMMANDS_DEST, { recursive: true });
  }

  // Copy all command files
  const commandFiles = fs.readdirSync(COMMANDS_SOURCE)
    .filter(file => file.endsWith('.md'));

  let copiedCount = 0;
  let skippedCount = 0;

  commandFiles.forEach(file => {
    const source = path.join(COMMANDS_SOURCE, file);
    const dest = path.join(COMMANDS_DEST, file);

    if (!fs.existsSync(dest)) {
      fs.copyFileSync(source, dest);
      copiedCount++;
    } else {
      skippedCount++;
    }
  });

  console.log(`✓ Copied ${copiedCount} commands to ${COMMANDS_DEST}/`);
  if (skippedCount > 0) {
    console.log(`  Skipped ${skippedCount} commands (already exist)`);
  }
}

function instantiateTemplates() {
  let createdCount = 0;
  let skippedCount = 0;

  TEMPLATE_FILES.forEach(({ template, output }) => {
    if (fs.existsSync(output)) {
      console.log(`  Skipped ${output} (already exists)`);
      skippedCount++;
      return;
    }

    const templatePath = path.join(TEMPLATES_DIR, template);
    
    if (!fs.existsSync(templatePath)) {
      console.warn(`⚠️  Template not found: ${templatePath}`);
      return;
    }

    let content = fs.readFileSync(templatePath, 'utf-8');

    // Replace placeholders with project-specific values
    content = replacePlaceholders(content);

    // Write output file
    fs.writeFileSync(output, content);
    console.log(`✓ Created ${output}`);
    createdCount++;
  });

  if (createdCount === 0 && skippedCount > 0) {
    console.log('  All template files already exist');
  }
}

function replacePlaceholders(content) {
  // Get project name from package.json or directory name
  const projectName = getProjectName();
  
  // Common placeholder replacements
  const replacements = {
    '{{PROJECT_NAME}}': projectName,
    '{{ORGANIZATION}}': 'your-org',
    '{{YEAR}}': new Date().getFullYear(),
    '{{DATE}}': new Date().toISOString().split('T')[0]
  };

  Object.entries(replacements).forEach(([placeholder, value]) => {
    content = content.replace(new RegExp(placeholder, 'g'), value);
  });

  return content;
}

function getProjectName() {
  try {
    const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
    return packageJson.name || path.basename(process.cwd());
  } catch {
    return path.basename(process.cwd());
  }
}

function updateGitignore() {
  const gitignorePath = '.gitignore';
  const entriesToAdd = [
    '',
    '# Roadcrew generated files',
    '.analysis/',
    'config/reports/',
    '.env.local'
  ].join('\n');

  let gitignoreContent = '';
  
  if (fs.existsSync(gitignorePath)) {
    gitignoreContent = fs.readFileSync(gitignorePath, 'utf-8');
  }

  // Check if entries already exist
  if (gitignoreContent.includes('.analysis/')) {
    console.log('  .gitignore already configured');
    return;
  }

  // Append entries
  fs.appendFileSync(gitignorePath, '\n' + entriesToAdd);
  console.log('✓ Updated .gitignore');
}

function displayNextSteps() {
  console.log('\n✅ Roadcrew installed successfully!\n');
  console.log('Next steps:');
  console.log('  1. Edit milestones/current-release.md with your release plan');
  console.log('  2. Run /analyze-repo to detect your tech stack');
  console.log('  3. Run /guide-release to start your first release');
  console.log('  4. See .roadcrew/README.md for command reference\n');
  console.log('Free tier features:');
  console.log('  ✓ Manual command execution');
  console.log('  ✓ Template library');
  console.log('  ✓ GitHub integration\n');
  console.log('Premium features (Starter $49/mo):');
  console.log('  → /enrich-release --ai (AI-powered enrichment)');
  console.log('  → /scope-release --toc (Theory of Constraints)');
  console.log('  → /release-flow (one-command release)');
  console.log('  → Visit https://roadcrew.dev/pricing\n');
}

// Run installation
install();
```

### Update Process

**File:** `.submodule/scripts/update.sh`

```bash
#!/bin/bash

# Roadcrew Update Script
# Updates submodule and reinstalls commands

set -e

echo "🔄 Updating Roadcrew..."

# Step 1: Pull latest submodule
echo "Pulling latest .roadcrew/ submodule..."
git submodule update --remote .roadcrew

# Step 2: Reinstall commands (overwrites existing)
echo "Reinstalling commands..."
node .roadcrew/install.js --update

echo "✅ Roadcrew updated successfully!"
echo ""
echo "New features available:"
git -C .roadcrew log --oneline -5
```

**Usage:**
```bash
# Via npm script (add to package.json)
npm run roadcrew:update

# Or directly
bash .roadcrew/scripts/update.sh
```

---

## Mode Detection & Path Resolution

### Mode Detection Logic

**File:** `.submodule/scripts/utils/mode-detector.ts`

```typescript
/**
 * Detects Roadcrew deployment mode
 * 
 * - Mode 0: Template repository (has .submodule/ folder)
 * - Mode 1: Submodule installation (has .roadcrew/ folder)
 * - Mode 2: Multi-repo orchestration (has config/repos.yml)
 */

import fs from 'fs';
import path from 'path';

export type DeploymentMode = 'template' | 'submodule' | 'multi-repo' | 'unknown';

export interface ModeConfig {
  mode: DeploymentMode;
  commandsPath: string;
  templatesPath: string;
  scriptsPath: string;
  contexPath: string;
  milestonesPath: string;
}

export function detectMode(): ModeConfig {
  const cwd = process.cwd();

  // Check for Mode 2: Multi-repo
  if (fs.existsSync(path.join(cwd, 'config/repos.yml'))) {
    return {
      mode: 'multi-repo',
      commandsPath: '.cursor/commands',
      templatesPath: 'templates',
      scriptsPath: 'scripts',
      contextPath: 'context',
      milestonesPath: 'milestones'
    };
  }

  // Check for Mode 1: Submodule
  if (fs.existsSync(path.join(cwd, '.roadcrew'))) {
    return {
      mode: 'submodule',
      commandsPath: '.cursor/commands',           // Installed commands
      templatesPath: '.roadcrew/templates',        // Reference submodule
      scriptsPath: '.roadcrew/scripts',            // Reference submodule
      contextPath: 'context',                      // User's docs
      milestonesPath: 'milestones'                 // User's releases
    };
  }

  // Check for Mode 0: Template repository
  if (fs.existsSync(path.join(cwd, '.submodule'))) {
    return {
      mode: 'template',
      commandsPath: '.cursor/commands',            // Active dev commands
      templatesPath: '.submodule/templates',       // Distribution templates
      scriptsPath: '.submodule/scripts',           // Distribution scripts
      contextPath: 'context',                      // Roadcrew's own docs
      milestonesPath: 'milestones'                 // Roadcrew's releases
    };
  }

  // Unknown configuration
  return {
    mode: 'unknown',
    commandsPath: '.cursor/commands',
    templatesPath: 'templates',
    scriptsPath: 'scripts',
    contextPath: 'context',
    milestonesPath: 'milestones'
  };
}

export function requireMode(allowedModes: DeploymentMode[]): ModeConfig {
  const config = detectMode();

  if (!allowedModes.includes(config.mode)) {
    throw new Error(
      `This command requires one of: ${allowedModes.join(', ')}\n` +
      `Current mode: ${config.mode}`
    );
  }

  return config;
}
```

### Path Resolution

**File:** `.submodule/scripts/utils/path-resolver.ts`

```typescript
/**
 * Resolves file paths based on deployment mode
 */

import path from 'path';
import { detectMode, ModeConfig } from './mode-detector';

export class PathResolver {
  private config: ModeConfig;

  constructor() {
    this.config = detectMode();
  }

  /**
   * Resolve template file path
   */
  template(templateName: string): string {
    return path.join(this.config.templatesPath, templateName);
  }

  /**
   * Resolve script file path
   */
  script(scriptPath: string): string {
    return path.join(this.config.scriptsPath, scriptPath);
  }

  /**
   * Resolve context file path (vision, specs, etc.)
   */
  context(contextPath: string): string {
    return path.join(this.config.contextPath, contextPath);
  }

  /**
   * Resolve milestone file path
   */
  milestone(milestoneName: string): string {
    return path.join(this.config.milestonesPath, milestoneName);
  }

  /**
   * Get current deployment mode
   */
  getMode(): string {
    return this.config.mode;
  }

  /**
   * Check if running in specific mode
   */
  isMode(mode: string): boolean {
    return this.config.mode === mode;
  }
}

// Singleton instance
export const pathResolver = new PathResolver();
```

**Usage in Commands:**

```typescript
// In any command file
import { pathResolver } from '../scripts/utils/path-resolver';

// Read template (works in all modes)
const templatePath = pathResolver.template('epic.template.md');
const template = fs.readFileSync(templatePath, 'utf-8');

// Read user's current release (works in Mode 1 & 2)
const releasePath = pathResolver.milestone('current-release.md');
const release = fs.readFileSync(releasePath, 'utf-8');

// Read spec file
const specPath = pathResolver.context('specs/feature-spec.md');
const spec = fs.readFileSync(specPath, 'utf-8');
```

---

## Premium Feature Gating

### License Validation

**File:** `.submodule/scripts/utils/license-validator.ts`

```typescript
/**
 * License validation for premium features
 * 
 * Free tier: All commands work manually
 * Starter tier ($49/mo): --ai, --toc flags, /release-flow, /watch-milestone
 * Enterprise tier ($999/mo): Multi-repo, autonomous agents, unlimited tokens
 */

import fetch from 'node-fetch';

const API_BASE = process.env.ROADCREW_API_URL || 'https://api.roadcrew.dev';
const API_KEY = process.env.ROADCREW_API_KEY;

export interface LicenseValidationResponse {
  valid: boolean;
  tier: 'free' | 'starter' | 'enterprise';
  features: string[];
  tokenQuota?: number;
  tokenUsed?: number;
  expiresAt?: string;
  error?: string;
}

/**
 * Validate API key and check feature access
 */
export async function validateLicense(
  featureName: string
): Promise<LicenseValidationResponse> {
  
  // No API key = free tier
  if (!API_KEY) {
    return {
      valid: false,
      tier: 'free',
      features: [],
      error: 'No API key provided'
    };
  }

  try {
    const response = await fetch(`${API_BASE}/v1/validate`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
        'User-Agent': 'Roadcrew-CLI/1.0'
      },
      body: JSON.stringify({
        feature: featureName,
        version: require('../../../package.json').version,
        mode: require('./mode-detector').detectMode().mode
      }),
      timeout: 5000
    });

    if (!response.ok) {
      if (response.status === 401) {
        return {
          valid: false,
          tier: 'free',
          features: [],
          error: 'Invalid API key'
        };
      }

      if (response.status === 403) {
        return {
          valid: false,
          tier: 'free',
          features: [],
          error: 'Feature not available in your tier'
        };
      }

      throw new Error(`API error: ${response.status}`);
    }

    const data = await response.json();
    return data;

  } catch (error) {
    // Network error, API down, etc.
    console.error('License validation failed:', error.message);
    
    return {
      valid: false,
      tier: 'free',
      features: [],
      error: `Validation failed: ${error.message}`
    };
  }
}

/**
 * Require premium feature or exit with upgrade prompt
 */
export async function requireFeature(
  featureName: string,
  tierRequired: 'starter' | 'enterprise' = 'starter'
): Promise<void> {
  
  const result = await validateLicense(featureName);

  if (!result.valid || result.tier === 'free') {
    const tierPricing = tierRequired === 'starter' ? '$49/mo' : '$999/mo';
    
    console.error(`\n❌ Premium feature: ${featureName}`);
    console.error(`   Requires: ${tierRequired} tier (${tierPricing})`);
    console.error(`   Your tier: ${result.tier}`);
    console.error(`\n   Try 14-day free trial: https://roadcrew.dev/trial`);
    console.error(`   Set ROADCREW_API_KEY environment variable\n`);
    
    if (result.error) {
      console.error(`   Error: ${result.error}\n`);
    }
    
    process.exit(1);
  }

  // Check tier matches requirement
  const tierHierarchy = { free: 0, starter: 1, enterprise: 2 };
  
  if (tierHierarchy[result.tier] < tierHierarchy[tierRequired]) {
    console.error(`\n❌ Feature requires ${tierRequired} tier`);
    console.error(`   Your tier: ${result.tier}`);
    console.error(`   Upgrade at: https://roadcrew.dev/pricing\n`);
    process.exit(1);
  }

  // Valid license, feature allowed
}

/**
 * Check if feature is available (non-blocking)
 */
export async function hasFeature(featureName: string): Promise<boolean> {
  const result = await validateLicense(featureName);
  return result.valid && result.tier !== 'free';
}

/**
 * Get current license info
 */
export async function getLicenseInfo(): Promise<LicenseValidationResponse> {
  return validateLicense('license-info');
}
```

### Premium Feature Implementation

**Example: `/enrich-release --ai` Flag**

```typescript
// .cursor/commands/enrich-release.md (pseudo-code section)

import { requireFeature, hasFeature } from '../.roadcrew/scripts/utils/license-validator';

async function enrichRelease(argv: any) {
  const { ai, from, to, force } = argv;

  // Check for premium flag
  if (ai) {
    await requireFeature('ai-enrichment', 'starter');
  }

  // Load release file
  const releasePath = pathResolver.milestone('current-release.md');
  const release = parseRelease(fs.readFileSync(releasePath, 'utf-8'));

  // Enrich issues
  for (const epic of release.epics) {
    for (const issue of epic.issues) {
      if (ai) {
        // PREMIUM: AI-powered enrichment via API
        const enriched = await enrichWithAI(issue);
        issue.details = enriched;
      } else {
        // FREE: Manual enrichment prompt
        console.log(`\nIssue ${issue.number}: ${issue.title}`);
        console.log('Read spec and add details manually.');
        console.log('Tip: Use --ai flag for AI-powered enrichment (Starter tier)\n');
      }
    }
  }

  // Save enriched release
  fs.writeFileSync(releasePath, formatRelease(release));
}

async function enrichWithAI(issue: Issue): Promise<string> {
  const response = await fetch(`${API_BASE}/v1/enrich`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.ROADCREW_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      issue: issue,
      specs: issue.linkedSpecs,
      context: getTechStackContext()
    })
  });

  const data = await response.json();
  return data.enrichedContent;
}
```

**Example: `/scope-release --toc` Flag**

```typescript
// .cursor/commands/scope-release.md (pseudo-code section)

import { requireFeature } from '../.roadcrew/scripts/utils/license-validator';

async function scopeRelease(argv: any) {
  const { toc, current, dryRun } = argv;

  // Check for TOC flag
  if (toc) {
    await requireFeature('toc-assignment', 'starter');
  }

  // Load release
  const release = parseRelease(...);

  // Classify and assign issues
  for (const epic of release.epics) {
    for (const issue of epic.issues) {
      if (toc) {
        // PREMIUM: AI classification + TOC routing via API
        const classified = await classifyIssue(issue);
        issue.classification = classified.score;
        issue.assignee = classified.assignee;
        
        console.log(`Issue ${issue.number}: Classification ${classified.score}/10 → ${classified.assignee}`);
      } else {
        // FREE: Basic assignment from config
        issue.assignee = getBasicAssignment(issue);
        console.log(`Issue ${issue.number}: Assigned to ${issue.assignee}`);
      }
    }
  }

  // Create GitHub issues
  createGitHubIssues(release);
}

async function classifyIssue(issue: Issue): Promise<Classification> {
  const response = await fetch(`${API_BASE}/v1/classify`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.ROADCREW_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      issue: issue,
      assignmentRules: loadAssignmentRules(),
      techStack: getTechStack()
    })
  });

  const data = await response.json();
  return {
    score: data.classification,  // 1-10
    assignee: data.assignee,     // Based on TOC routing
    zone: data.zone              // ai-solo, ai-led, ai-assisted, ai-limited
  };
}
```

---

## Mode 2: Multi-Repo Orchestration

### Project Resolution

**File:** `.submodule/scripts/utils/project-resolver.ts`

```typescript
/**
 * Resolves project configuration in multi-repo mode
 */

import fs from 'fs';
import yaml from 'js-yaml';
import { detectMode } from './mode-detector';

export interface ProjectConfig {
  mode: 'submodule' | 'multi-repo';
  projectName?: string;
  releaseFile: string;
  contextPath: string;
  repo: string | null;
  techStack: string;
  defaultLabels: string[];
  createIssuesLocally: boolean;
}

export function resolveProject(projectFlag?: string): ProjectConfig {
  const { mode } = detectMode();

  if (mode === 'submodule') {
    // Submodule mode: ignore --project flag, use local files
    return {
      mode: 'submodule',
      releaseFile: 'milestones/current-release.md',
      contextPath: 'context/',
      repo: null,
      techStack: 'memory-bank/techContext.md',
      defaultLabels: [],
      createIssuesLocally: true
    };
  }

  if (mode === 'multi-repo') {
    // Multi-repo mode: require --project flag
    if (!projectFlag) {
      throw new Error(
        'Multi-repo mode requires --project flag.\n' +
        'Example: /scope-release --project frontend\n' +
        'Available projects: ' + getAvailableProjects().join(', ')
      );
    }

    const config = loadReposConfig();
    const project = config.projects[projectFlag];

    if (!project) {
      throw new Error(
        `Project '${projectFlag}' not found in config/repos.yml\n` +
        'Available projects: ' + Object.keys(config.projects).join(', ')
      );
    }

    return {
      mode: 'multi-repo',
      projectName: projectFlag,
      releaseFile: project.release_file,
      contextPath: 'context/',
      repo: project.repo,
      techStack: project.tech_stack,
      defaultLabels: project.default_labels || [],
      createIssuesLocally: false
    };
  }

  throw new Error(`Unsupported mode: ${mode}`);
}

function loadReposConfig(): any {
  const configPath = 'config/repos.yml';
  
  if (!fs.existsSync(configPath)) {
    throw new Error(
      'config/repos.yml not found. Multi-repo mode requires this configuration.'
    );
  }

  return yaml.load(fs.readFileSync(configPath, 'utf-8'));
}

function getAvailableProjects(): string[] {
  try {
    const config = loadReposConfig();
    return Object.keys(config.projects);
  } catch {
    return [];
  }
}
```

---

## Testing Strategy

### Test Coverage Requirements

**Installation Tests** (`tests/install.test.ts`):
```typescript
describe('install.js', () => {
  test('creates required directories', () => {
    // Verify context/, milestones/, config/ created
  });

  test('copies commands to .cursor/commands/', () => {
    // Verify all .md files copied
  });

  test('instantiates templates with placeholders replaced', () => {
    // Verify {{PROJECT_NAME}} replaced
  });

  test('updates .gitignore', () => {
    // Verify .analysis/ added
  });

  test('handles existing files gracefully', () => {
    // Verify no overwrites
  });
});
```

**Mode Detection Tests** (`tests/mode-detection.test.ts`):
```typescript
describe('detectMode', () => {
  test('detects Mode 0 (template)', () => {
    // Mock .submodule/ folder
  });

  test('detects Mode 1 (submodule)', () => {
    // Mock .roadcrew/ folder
  });

  test('detects Mode 2 (multi-repo)', () => {
    // Mock config/repos.yml
  });

  test('returns unknown for ambiguous setup', () => {
    // No indicators present
  });
});
```

**License Validation Tests** (`tests/license-validation.test.ts`):
```typescript
describe('validateLicense', () => {
  test('returns free tier when no API key', () => {
    delete process.env.ROADCREW_API_KEY;
    // Expect free tier
  });

  test('validates API key with server', async () => {
    // Mock API response
  });

  test('handles network errors gracefully', async () => {
    // Mock network failure
  });

  test('requireFeature exits for invalid license', async () => {
    // Expect process.exit(1)
  });
});
```

---

## Deployment & Release Process

### Version Tagging

```bash
# Update version in package.json
npm version minor  # or patch, major

# Tag release
git tag -a v1.2.0 -m "Release v1.2.0: Add multi-repo support"
git push origin v1.2.0

# GitHub Actions automatically:
# 1. Runs CI tests
# 2. Builds .submodule/
# 3. Creates GitHub release
# 4. Publishes to npm (optional)
```

### Changelog Generation

**CHANGELOG.md:**
```markdown
# Changelog

## [1.2.0] - 2025-01-24

### Added
- Multi-repo orchestration (Mode 2)
- Premium feature gating (--ai, --toc flags)
- License validation system
- /release-flow command (Starter tier)
- /watch-milestone command (Starter tier)

### Changed
- Consolidated milestones/ folder structure
- Moved analysis outputs to config/reports/

### Fixed
- Submodule update overwrites user files
- Command path resolution in multi-repo mode
```

---

## Security Considerations

1. **API Key Storage:**
   - Never commit `ROADCREW_API_KEY` to git
   - Use environment variables or .env.local (gitignored)
   - Rotate keys via web dashboard

2. **Template Injection:**
   - Sanitize user input in placeholder replacements
   - Validate file paths to prevent directory traversal

3. **Submodule Trust:**
   - Users trust upstream roadcrew repo
   - Pin to specific commit/tag for stability
   - Review submodule updates before merging

4. **Premium Feature Bypass:**
   - Server-side validation (can't be bypassed by editing local files)
   - API endpoints enforce tier restrictions
   - Token usage tracked server-side

---

## Performance Optimization

1. **Lazy Loading:**
   - Only import license validator when needed
   - Cache mode detection results per command execution

2. **Parallel Operations:**
   - Enrich multiple issues concurrently (respecting API rate limits)
   - Batch GitHub API calls

3. **Minimal Dependencies:**
   - Keep .submodule/package.json lean
   - Avoid heavy dependencies in free tier

---

## Future Enhancements

### Phase 1 (v1.2)
- [ ] Implement install.js
- [ ] Add mode detection
- [ ] Build license validation system
- [ ] Gate --ai and --toc flags

### Phase 2 (v1.3)
- [ ] Add /release-flow command
- [ ] Add /watch-milestone command
- [ ] Implement token tracking
- [ ] Build usage dashboard API

### Phase 3 (v1.4)
- [ ] Multi-repo orchestration (Mode 2)
- [ ] Cross-repo dependency tracking
- [ ] Enterprise tier features

---

## Related Documentation

- [PRD: Submodule Isolation](../prds/submodule-isolation-prd.md)
- [Monetization Strategy](../../docs/monetization-strategy.md)
- [Commands Reference](../../docs/commands.md)
- [Deployment Modes Guide](../../docs/deployment-modes.md)

---

**Implementation Priority:**
1. install.js (core requirement)
2. Mode detection & path resolution (core requirement)
3. License validation (enables monetization)
4. Premium flags (--ai, --toc)
5. Multi-repo support (Enterprise feature)