diff --git a/scripts/bash/setup-architecture.sh b/scripts/bash/setup-architecture.sh index c61e1553ef..2d52114c7c 100755 --- a/scripts/bash/setup-architecture.sh +++ b/scripts/bash/setup-architecture.sh @@ -7,6 +7,7 @@ ACTION="" ARGS=() VIEWS="core" ADR_HEURISTIC="surprising" +DECOMPOSE=true # Parse arguments while [[ $# -gt 0 ]]; do @@ -33,6 +34,14 @@ while [[ $# -gt 0 ]]; do ADR_HEURISTIC="${1#*=}" shift ;; + --no-decompose) + DECOMPOSE=false + shift + ;; + --no-decompose=*) + DECOMPOSE=false + shift + ;; init|map|update|review|specify|implement|clarify) ACTION="$1" shift @@ -53,6 +62,7 @@ while [[ $# -gt 0 ]]; do echo " --json Output results in JSON format" echo " --views VIEWS Architecture views to generate: core (default), all, or comma-separated" echo " --adr-heuristic H ADR generation heuristic: surprising (default), all, minimal" + echo " --no-decompose Disable automatic sub-system decomposition (default: auto-detect)" echo " --help Show this help message" echo "" echo "Examples:" @@ -101,6 +111,151 @@ AD_TEMPLATE_FILE="$REPO_ROOT/.specify/templates/AD-template.md" # Export for use in functions export ARCHITECTURE_VIEWS="$VIEWS" export ADR_HEURISTIC="$ADR_HEURISTIC" +export DECOMPOSE="$DECOMPOSE" + +# Function to detect sub-systems from codebase structure +detect_subsystems() { + local subsystems="" + local count=0 + + echo "Detecting sub-systems from codebase structure..." >&2 + + # Check for common sub-system patterns + + # 1. Top-level feature directories (src/, app/, services/) + local dirs=() + if [[ -d "src" ]]; then + for d in src/*/; do + if [[ -d "$d" ]]; then + local dirname + dirname=$(basename "$d") + # Skip common non-sub-system directories + if [[ "$dirname" != "utils" && "$dirname" != "common" && "$dirname" != "lib" && "$dirname" != "shared" && "$dirname" != "core" ]]; then + dirs+=("$dirname") + fi + fi + done + fi + + if [[ -d "services" ]]; then + for d in services/*/; do + if [[ -d "$d" ]]; then + local dirname + dirname=$(basename "$d") + dirs+=("$dirname") + fi + done + fi + + if [[ -d "modules" ]]; then + for d in modules/*/; do + if [[ -d "$d" ]]; then + local dirname + dirname=$(basename "$d") + dirs+=("$dirname") + fi + done + fi + + if [[ -d "apps" ]]; then + for d in apps/*/; do + if [[ -d "$d" ]]; then + local dirname + dirname=$(basename "$d") + dirs+=("$dirname") + fi + done + fi + + # 2. Check for docker-compose services (microservices indicator) + if [[ -f "docker-compose.yml" ]] || [[ -f "docker-compose.yaml" ]]; then + local compose_file="docker-compose.yml" + [[ -f "docker-compose.yaml" ]] && compose_file="docker-compose.yaml" + + local services=() + while IFS= read -r line; do + if [[ "$line" =~ ^[[:space:]]*([a-zA-Z0-9_-]+):[[:space:]]*$ ]]; then + local svc="${BASH_REMATCH[1]}" + # Skip common non-service entries + if [[ "$svc" != "version" && "$svc" != "services" && "$svc" != "networks" && "$svc" != "volumes" ]]; then + services+=("$svc") + fi + fi + done < "$compose_file" + + for svc in "${services[@]}"; do + local found=false + for d in "${dirs[@]}"; do + if [[ "${d,,}" == *"${svc,,}"* ]] || [[ "${svc,,}" == *"${d,,}"* ]]; then + found=true + break + fi + done + if [[ "$found" == "false" ]]; then + dirs+=("$svc") + fi + done + fi + + # 3. Check for Node.js workspaces (monorepo indicator) + if [[ -f "package.json" ]]; then + if grep -q '"workspaces"' package.json 2>/dev/null; then + local pkgs + pkgs=$(node -e "try { const p = require('./package.json'); console.log(Object.keys(p.workspaces?.packages || {}).join(' ')); } catch(e) { }" 2>/dev/null || true) + for pkg in $pkgs; do + local dirname + dirname=$(basename "$pkg") + if [[ "$dirname" != "node_modules" ]]; then + dirs+=("$dirname") + fi + done + fi + fi + + # 4. Check for Python namespace packages + if [[ -f "pyproject.toml" ]]; then + local pkg_dirs=() + while IFS= read -r -d '' d; do + pkg_dirs+=("$(basename "$d")") + done < <(find . -maxdepth 3 -name "__init__.py" -printf '%h\n' 2>/dev/null | grep -v node_modules | grep -v __pycache__ | sort -u || true) + + for pdir in "${pkg_dirs[@]}"; do + if [[ "$pdir" != "." && "$pdir" != "src" ]]; then + dirs+=("$pdir") + fi + done + fi + + # Remove duplicates and build output + local unique_dirs=($(printf '%s\n' "${dirs[@]}" | sort -u)) + + if [[ ${#unique_dirs[@]} -gt 0 ]]; then + echo "Detected potential sub-systems:" >&2 + for d in "${unique_dirs[@]}"; do + ((count++)) + echo " - $d" >&2 + done + echo "Total: $count sub-system(s)" >&2 + else + echo "No distinct sub-systems detected from directory structure." >&2 + fi + + # Return as JSON if JSON mode + if $JSON_MODE; then + echo "[" + local first=true + for d in "${unique_dirs[@]}"; do + if [[ "$first" == "true" ]]; then + first=false + else + echo "," + fi + echo -n " {\"id\": \"$d\", \"name\": \"$d\", \"detection_method\": \"directory\", \"evidence\": \"directory: $d/\"}" + done + echo "" + echo "]" + fi +} # Function to detect tech stack from codebase detect_tech_stack() { @@ -444,6 +599,17 @@ action_specify() { # Ensure memory directory exists mkdir -p "$REPO_ROOT/.specify/memory" + # Show decomposition status + if [[ "$DECOMPOSE" == "true" ]]; then + echo "" >&2 + echo "🔄 Sub-system decomposition: ENABLED" >&2 + echo " (AI agent will detect domains from PRD and propose sub-systems)" >&2 + else + echo "" >&2 + echo "⚠️ Sub-system decomposition: DISABLED (--no-decompose flag)" >&2 + echo " (AI agent will generate monolithic ADRs)" >&2 + fi + # Initialize ADR file from template if it doesn't exist if [[ ! -f "$adr_file" ]]; then if [[ -f "$adr_template" ]]; then @@ -457,8 +623,8 @@ action_specify() { ## ADR Index -| ID | Decision | Status | Date | Owner | -|----|----------|--------|------|-------| +| ID | Sub-System | Decision | Status | Date | Owner | +|----|------------|----------|--------|------|-------| --- @@ -472,15 +638,22 @@ EOF echo "" >&2 echo "Ready for interactive PRD exploration." >&2 echo "The AI agent will:" >&2 + if [[ "$DECOMPOSE" == "true" ]]; then + echo " 0. (Phase 0) Detect domains in PRD and propose sub-systems" >&2 + echo " → Ask user to confirm sub-system breakdown" >&2 + fi echo " 1. Analyze your PRD/requirements input" >&2 echo " 2. Ask clarifying questions about architecture" >&2 echo " 3. Create ADRs for each key decision" >&2 echo " 4. Save decisions to .specify/memory/adr.md" >&2 + if [[ "$DECOMPOSE" == "true" ]]; then + echo " 5. Organize ADRs by sub-system" >&2 + fi echo "" >&2 echo "After completion, run '/architect.implement' to generate full AD.md" >&2 if $JSON_MODE; then - echo "{\"status\":\"success\",\"action\":\"specify\",\"adr_file\":\"$adr_file\",\"context\":\"${ARGS[*]}\"}" + echo "{\"status\":\"success\",\"action\":\"specify\",\"adr_file\":\"$adr_file\",\"context\":\"${ARGS[*]}\",\"decomposition\":\"$DECOMPOSE\"}" fi } @@ -589,6 +762,26 @@ action_init() { local dir_structure dir_structure=$(map_directory_structure) + # Phase 0: Sub-system detection (if decomposition enabled) + local subsystems_json="" + local decompose_status="disabled" + + if [[ "$DECOMPOSE" == "true" ]]; then + echo "" >&2 + echo "🔄 Phase 0: Sub-System Detection" >&2 + subsystems_json=$(detect_subsystems) + decompose_status="enabled" + + if [[ -n "$subsystems_json" ]] && [[ "$subsystems_json" != "[]" ]]; then + echo "" >&2 + echo "📦 Sub-systems will be used to organize ADRs" >&2 + echo " (AI agent will confirm with user before proceeding)" >&2 + fi + else + echo "" >&2 + echo "⚠️ Sub-system decomposition disabled (--no-decompose flag)" >&2 + fi + # Initialize ADR file from template if it doesn't exist if [[ ! -f "$adr_file" ]]; then if [[ -f "$adr_template" ]]; then @@ -602,8 +795,8 @@ action_init() { ## ADR Index -| ID | Decision | Status | Date | Owner | -|----|----------|--------|------|-------| +| ID | Sub-System | Decision | Status | Date | Owner | +|----|------------|----------|--------|------|-------| --- @@ -623,16 +816,23 @@ EOF echo "" >&2 echo "Ready for brownfield architecture discovery." >&2 echo "The AI agent will:" >&2 + if [[ "$DECOMPOSE" == "true" ]]; then + echo " 0. (Phase 0) Propose sub-systems from code structure" >&2 + echo " → Ask user to confirm sub-system breakdown" >&2 + fi echo " 1. Analyze codebase structure and patterns" >&2 echo " 2. Infer architectural decisions from code" >&2 echo " 3. Create ADRs marked as 'Discovered (Inferred)'" >&2 - echo " 4. Auto-trigger /architect.clarify to validate findings" >&2 + if [[ "$DECOMPOSE" == "true" ]]; then + echo " 4. Organize ADRs by sub-system" >&2 + fi + echo " 5. Auto-trigger /architect.clarify to validate findings" >&2 echo "" >&2 echo "NOTE: AD.md will NOT be created until ADRs are validated." >&2 echo " After clarification, run /architect.implement to generate AD.md" >&2 if $JSON_MODE; then - echo "{\"status\":\"success\",\"action\":\"init\",\"adr_file\":\"$adr_file\",\"tech_stack\":\"$tech_stack\",\"existing_docs\":\"$existing_docs\",\"source\":\"brownfield\"}" + echo "{\"status\":\"success\",\"action\":\"init\",\"adr_file\":\"$adr_file\",\"tech_stack\":\"$tech_stack\",\"existing_docs\":\"$existing_docs\",\"source\":\"brownfield\",\"decomposition\":\"$decompose_status\",\"subsystems\":$subsystems_json}" fi } diff --git a/scripts/powershell/setup-architecture.ps1 b/scripts/powershell/setup-architecture.ps1 index e0ddee6314..d865c09698 100644 --- a/scripts/powershell/setup-architecture.ps1 +++ b/scripts/powershell/setup-architecture.ps1 @@ -8,10 +8,13 @@ param( [string[]]$Context, [string]$Views = 'core', [string]$AdrHeuristic = 'surprising', + [switch]$NoDecompose, [switch]$Json, [switch]$Help ) +$Decompose = -not $NoDecompose + $ErrorActionPreference = 'Stop' if ($Help) { @@ -29,6 +32,7 @@ if ($Help) { Write-Output "Options:" Write-Output " -Views VIEWS Architecture views to generate: core (default), all, or comma-separated" Write-Output " -AdrHeuristic H ADR generation heuristic: surprising (default), all, minimal" + Write-Output " -NoDecompose Disable automatic sub-system decomposition (default: auto-detect)" Write-Output " -Json Output results in JSON format" Write-Output " -Help Show this help message" Write-Output "" @@ -178,6 +182,116 @@ function Get-TechStack { return $techStack -join "`n" } +# Detect sub-systems from codebase structure +function Get-Subsystems { + Write-Host "Detecting sub-systems from codebase structure..." -ForegroundColor Cyan + + $dirs = @() + + # 1. Top-level feature directories (src/, app/, services/) + if (Test-Path "src") { + Get-ChildItem -Path "src" -Directory -ErrorAction SilentlyContinue | ForEach-Object { + $dirname = $_.Name + # Skip common non-sub-system directories + if (@("utils", "common", "lib", "shared", "core") -notcontains $dirname) { + $dirs += $dirname + } + } + } + + if (Test-Path "services") { + Get-ChildItem -Path "services" -Directory -ErrorAction SilentlyContinue | ForEach-Object { + $dirs += $_.Name + } + } + + if (Test-Path "modules") { + Get-ChildItem -Path "modules" -Directory -ErrorAction SilentlyContinue | ForEach-Object { + $dirs += $_.Name + } + } + + if (Test-Path "apps") { + Get-ChildItem -Path "apps" -Directory -ErrorAction SilentlyContinue | ForEach-Object { + $dirs += $_.Name + } + } + + # 2. Check for docker-compose services (microservices indicator) + $composeFile = $null + if (Test-Path "docker-compose.yml") { $composeFile = "docker-compose.yml" } + elseif (Test-Path "docker-compose.yaml") { $composeFile = "docker-compose.yaml" } + + if ($composeFile) { + $composeContent = Get-Content $composeFile -Raw + $services = [regex]::Matches($composeContent, '^\s*([a-zA-Z0-9_-]+):\s*$' | ForEach-Object { $_.Groups[1].Value } | Where-Object { @("version", "services", "networks", "volumes") -notcontains $_ }) + foreach ($svc in $services) { + $found = $false + foreach ($d in $dirs) { + if ($d.ToLower() -like "*$($svc.ToLower())*" -or $svc.ToLower() -like "*$($d.ToLower())*") { + $found = $true + break + } + } + if (-not $found) { + $dirs += $svc + } + } + } + + # 3. Check for Node.js workspaces (monorepo indicator) + if (Test-Path "package.json") { + $packageJson = Get-Content "package.json" -Raw | ConvertFrom-Json -ErrorAction SilentlyContinue + if ($packageJson.workspaces) { + $packageJson.workspaces | ForEach-Object { + $dirname = Split-Path $_ -Leaf + if ($dirname -ne "node_modules") { + $dirs += $dirname + } + } + } + } + + # 4. Check for Python namespace packages + if (Test-Path "pyproject.toml") { + Get-ChildItem -Path . -Recurse -Filter "__init__.py" -Depth 3 -ErrorAction SilentlyContinue | ForEach-Object { + $dirname = Split-Path $_.DirectoryName -Leaf + if ($dirname -ne "src" -and $dirname -ne ".") { + $dirs += $dirname + } + } | Select-Object -Unique + } + + # Remove duplicates + $uniqueDirs = $dirs | Select-Object -Unique + + if ($uniqueDirs.Count -gt 0) { + Write-Host "Detected potential sub-systems:" -ForegroundColor Cyan + $count = 0 + foreach ($d in $uniqueDirs) { + $count++ + Write-Host " - $d" -ForegroundColor Gray + } + Write-Host "Total: $count sub-system(s)" -ForegroundColor Cyan + } else { + Write-Host "No distinct sub-systems detected from directory structure." -ForegroundColor Yellow + } + + # Return as JSON if JSON mode + if ($Json) { + $subsystems = @() + foreach ($d in $uniqueDirs) { + $subsystems += @{ + id = $d + name = $d + detection_method = "directory" + evidence = "directory: $d/" + } + } + return $subsystems | ConvertTo-Json -Compress + } +} + # Map directory structure function Get-DirectoryStructure { Write-Host "Scanning directory structure..." -ForegroundColor Cyan @@ -375,6 +489,17 @@ function Invoke-Specify { Write-Host "📐 Setting up for interactive ADR creation..." -ForegroundColor Cyan + # Show decomposition status + if ($Decompose) { + Write-Host "" + Write-Host "🔄 Sub-system decomposition: ENABLED" -ForegroundColor Cyan + Write-Host " (AI agent will detect domains from PRD and propose sub-systems)" -ForegroundColor Gray + } else { + Write-Host "" + Write-Host "⚠️ Sub-system decomposition: DISABLED (-NoDecompose flag)" -ForegroundColor Yellow + Write-Host " (AI agent will generate monolithic ADRs)" -ForegroundColor Gray + } + # Ensure memory directory exists $memoryDir = Join-Path $repoRoot ".specify\memory" if (-not (Test-Path $memoryDir)) { @@ -394,8 +519,8 @@ function Invoke-Specify { ## ADR Index -| ID | Decision | Status | Date | Owner | -|----|----------|--------|------|-------| +| ID | Sub-System | Decision | Status | Date | Owner | +|----|------------|----------|--------|------|-------| --- @@ -410,15 +535,22 @@ function Invoke-Specify { Write-Host "" Write-Host "Ready for interactive PRD exploration." Write-Host "The AI agent will:" + if ($Decompose) { + Write-Host " 0. (Phase 0) Detect domains in PRD and propose sub-systems" -ForegroundColor Gray + Write-Host " → Ask user to confirm sub-system breakdown" -ForegroundColor Gray + } Write-Host " 1. Analyze your PRD/requirements input" Write-Host " 2. Ask clarifying questions about architecture" Write-Host " 3. Create ADRs for each key decision" Write-Host " 4. Save decisions to .specify/memory/adr.md" + if ($Decompose) { + Write-Host " 5. Organize ADRs by sub-system" + } Write-Host "" Write-Host "After completion, run '/architect.implement' to generate full AD.md" if ($Json) { - @{status="success"; action="specify"; adr_file=$adrFile; context=($contextArgs -join " ")} | ConvertTo-Json + @{status="success"; action="specify"; adr_file=$adrFile; context=($contextArgs -join " "); decomposition=$Decompose} | ConvertTo-Json } } @@ -529,6 +661,26 @@ function Invoke-Init { $techStack = Get-TechStack $dirStructure = Get-DirectoryStructure + # Phase 0: Sub-system detection (if decomposition enabled) + $subsystemsJson = "" + $decomposeStatus = "disabled" + + if ($Decompose) { + Write-Host "" + Write-Host "🔄 Phase 0: Sub-System Detection" -ForegroundColor Cyan + $subsystemsJson = Get-Subsystems + $decomposeStatus = "enabled" + + if ($subsystemsJson -and $subsystemsJson -ne "[]") { + Write-Host "" + Write-Host "📦 Sub-systems will be used to organize ADRs" -ForegroundColor Cyan + Write-Host " (AI agent will confirm with user before proceeding)" -ForegroundColor Gray + } + } else { + Write-Host "" + Write-Host "⚠️ Sub-system decomposition disabled (-NoDecompose flag)" -ForegroundColor Yellow + } + # Initialize ADR file from template if it doesn't exist if (-not (Test-Path $adrFile)) { if (Test-Path $adrTemplate) { @@ -542,8 +694,8 @@ function Invoke-Init { ## ADR Index -| ID | Decision | Status | Date | Owner | -|----|----------|--------|------|-------| +| ID | Sub-System | Decision | Status | Date | Owner | +|----|------------|----------|--------|------|-------| --- @@ -564,10 +716,17 @@ function Invoke-Init { Write-Host "" Write-Host "Ready for brownfield architecture discovery." Write-Host "The AI agent will:" + if ($Decompose) { + Write-Host " 0. (Phase 0) Propose sub-systems from code structure" -ForegroundColor Gray + Write-Host " → Ask user to confirm sub-system breakdown" -ForegroundColor Gray + } Write-Host " 1. Analyze codebase structure and patterns" Write-Host " 2. Infer architectural decisions from code" Write-Host " 3. Create ADRs marked as 'Discovered (Inferred)'" - Write-Host " 4. Auto-trigger /architect.clarify to validate findings" + if ($Decompose) { + Write-Host " 4. Organize ADRs by sub-system" + } + Write-Host " 5. Auto-trigger /architect.clarify to validate findings" Write-Host "" Write-Host "NOTE: AD.md will NOT be created until ADRs are validated." -ForegroundColor Yellow Write-Host " After clarification, run /architect.implement to generate AD.md" @@ -580,6 +739,8 @@ function Invoke-Init { tech_stack=$techStack existing_docs=$existingDocs source="brownfield" + decomposition=$decomposeStatus + subsystems=$subsystemsJson } | ConvertTo-Json } } diff --git a/templates/adr-template.md b/templates/adr-template.md index 105e12ecc9..be9181b1e7 100644 --- a/templates/adr-template.md +++ b/templates/adr-template.md @@ -2,9 +2,9 @@ ## ADR Index -| ID | Decision | Status | Date | Owner | -|----|----------|--------|------|-------| -| ADR-001 | [First decision title] | Proposed | YYYY-MM-DD | [Owner] | +| ID | Sub-System | Decision | Status | Date | Owner | +|----|------------|----------|--------|------|-------| +| ADR-001 | System | [First decision title] | Proposed | YYYY-MM-DD | [Owner] | --- @@ -22,6 +22,12 @@ YYYY-MM-DD [Decision maker or team] +### Sub-System + +[System | Auth | Payments | Users | Inventory | (other sub-system name)] + +This field indicates which sub-system this ADR belongs to. Use "System" for cross-cutting decisions that affect the entire architecture. + ### Context Describe the issue motivating this decision. What is the problem or opportunity? What constraints exist? diff --git a/templates/commands/architect.init.md b/templates/commands/architect.init.md index 65b9437d64..843f681cfa 100644 --- a/templates/commands/architect.init.md +++ b/templates/commands/architect.init.md @@ -64,6 +64,8 @@ This command focuses on **current state analysis** - what IS, not what SHOULD BE - `all`: Document all discovered decisions - `minimal`: Only high-risk decisions +- `--no-decompose`: Disable automatic sub-system detection from code structure (default: auto-detect if multiple modules detected) + ## Role & Context You are acting as an **Architecture Archaeologist** uncovering implicit architectural decisions from code. Your role involves: @@ -82,25 +84,143 @@ You are acting as an **Architecture Archaeologist** uncovering implicit architec ## Outline -1. **Codebase Scan**: Analyze project structure and detect technologies -2. **Documentation Deduplication**: Scan existing docs (README, AGENTS.md, team-ai-directives/AGENTS.md if configured, etc.) to avoid repeating -3. **Pattern Detection**: Identify architectural patterns in use -4. **ADR Generation**: Create ADRs for discovered decisions (marked "Discovered") -5. **Gap Analysis**: Identify areas where decisions are unclear -6. **Output**: Write ADRs to `.specify/memory/adr.md` (NO AD.md creation) -7. **Auto-Handoff**: Trigger `/architect.clarify` to validate brownfield findings +1. **Sub-System Detection** (Phase 0): Identify sub-systems from code structure (auto-detect) +2. **Codebase Scan**: Analyze project structure and detect technologies (per sub-system if decomposed) +3. **Documentation Deduplication**: Scan existing docs (README, AGENTS.md, team-ai-directives/AGENTS.md if configured, etc.) to avoid repeating +4. **Pattern Detection**: Identify architectural patterns in use +5. **ADR Generation**: Create ADRs for discovered decisions (marked "Discovered"), organized by sub-system +6. **Gap Analysis**: Identify areas where decisions are unclear +7. **Output**: Write ADRs to `.specify/memory/adr.md` (NO AD.md creation) +8. **Auto-Handoff**: Trigger `/architect.clarify` to validate brownfield findings ## Execution Steps +### Phase 0: Sub-System Detection (Brownfield) + +**Objective**: Identify sub-systems from existing code structure automatically + +**When**: This phase runs automatically when the codebase is detected as having multiple distinct modules/packages. Use `--no-decompose` to skip. + +#### Step 1: Directory Structure Analysis + +Analyze the codebase for distinct sub-systems based on directory structure: + +| Pattern | Likely Sub-System | +|---------|------------------| +| `src/auth/` | Authentication sub-system | +| `src/users/` | User management sub-system | +| `services/payment/` | Payment sub-system | +| `modules/inventory/` | Inventory sub-system | +| `apps/api/`, `apps/web/` | Monorepo with separate apps | +| `lib/core/`, `lib/shared/` | Shared libraries (not a sub-system) | + +#### Step 2: Package/Module Detection + +Detect sub-systems from package/module structures: + +| Pattern | Detection Method | Sub-System Evidence | +|---------|------------------|-------------------| +| **Node.js workspaces** | package.json workspaces | Multiple packages = multiple sub-systems | +| **Python namespaces** | `__init__.py` hierarchy | Multiple top-level packages | +| **Go modules** | go.mod + directories | Multiple directories under cmd/ | +| **Maven/Gradle** | pom.xml modules | Multiple modules in multi-module project | +| **Docker services** | docker-compose services | Each service = sub-system | + +#### Step 3: Database Schema Analysis + +If database is accessible, detect sub-systems from schema: + +| Pattern | Evidence | +|---------|----------| +| Table prefixes | `auth_`, `user_`, `payment_` tables = separate domains | +| PostgreSQL schemas | `auth.`, `payments.` schema separation | +| Separate databases | Multiple databases in docker-compose | + +#### Step 4: Sub-System Proposal (Interactive) + +Present detected sub-systems to user for confirmation: + +```markdown +## Detected Sub-Systems + +I've identified the following sub-systems from your codebase: + +| # | Sub-System | Detection Method | Evidence | +|---|------------|-----------------|----------| +| 1 | **auth** | Directory + Module | src/auth/, auth/ package | +| 2 | **users** | Directory | src/users/, services/user/ | +| 3 | **payments** | Directory + Docker | services/payment/, payment service in docker-compose | +| 4 | **inventory** | Directory | src/inventory/, modules/stock/ | + +### Questions for Confirmation: + +1. **Are these sub-systems correct?** [Y/n] +2. **Should any sub-systems be merged?** (e.g., auth + users → identity) +3. **Should any sub-systems be split?** (e.g., payments → billing + subscriptions) +4. **Any missing sub-systems?** (e.g., analytics, reporting) + +**Reply** with: +- `Y` to confirm and proceed +- `n` to disable decomposition (generate monolithic ADRs) +- Specific changes (e.g., "merge 1+2", "split 3", "add Notifications") +``` + +#### Step 5: Decomposition Decision + +Based on user response: + +| Response | Action | +|----------|--------| +| `Y` / Enter | Proceed with detected sub-systems | +| `n` | Skip decomposition, generate monolithic ADRs | +| Modifications | Adjust sub-systems, then proceed | +| Empty/Default | Auto-proceed if ≤3 sub-systems, ask if >3 | + +**Threshold Logic**: +- **≤3 sub-systems**: Auto-approve, show summary +- **4-6 sub-systems**: Show summary, ask to confirm +- **>6 sub-systems**: Show summary, suggest grouping, ask to confirm + +#### Step 6: Output + +After confirmation, output structured sub-system data: + +```json +{ + "decomposition": "enabled", + "subsystems": [ + {"id": "auth", "name": "Auth", "detection_method": "directory", "evidence": "src/auth/"}, + {"id": "users", "name": "Users", "detection_method": "directory", "evidence": "src/users/"}, + {"id": "payments", "name": "Payments", "detection_method": "docker", "evidence": "payment service in docker-compose"} + ], + "next_phase": "Codebase Analysis (per sub-system)" +} +``` + +**If decomposition disabled**: +```json +{ + "decomposition": "disabled", + "reason": "user_requested", + "next_phase": "Codebase Analysis (monolithic)" +} +``` + +--- + ### Phase 1: Codebase Analysis **Objective**: Discover what technologies and patterns are in use +**Note**: If sub-system decomposition is enabled (Phase 0), analyze each sub-system **separately** to provide focused insights. + 1. **Run Setup Script**: - Execute `{SCRIPT}` to initialize architecture files - Script scans codebase and outputs structured findings + - Pass `--no-decompose` if decomposition was disabled + - **If decomposed**: Script outputs sub-system breakdown for targeted analysis -2. **Technology Detection**: +2. **Technology Detection (Per Sub-System)**: | Indicator | Technology Category | Files to Check | |-----------|---------------------|----------------| @@ -269,6 +389,47 @@ Legacy/Inferred - **ADR-006**: CI/CD Approach (GitHub Actions vs Jenkins) - **Additional**: Any custom/in-house solutions, unusual patterns, risky choices +4. **Sub-System Organization** (if Phase 0 decomposition enabled): + + Structure ADRs by sub-system in the output file: + + ```markdown + # Architecture Decision Records + + ## ADR Index + + | ID | Sub-System | Decision | Status | Date | Confidence | + |----|------------|----------|--------|------|------------| + | ADR-001 | System | Monolithic Architecture | Discovered | 2026-02-26 | HIGH | + | ADR-002 | Auth | JWT Authentication | Discovered | 2026-02-26 | HIGH | + | ADR-003 | Payments | Stripe Integration | Discovered | 2026-02-26 | MEDIUM | + + --- + + ## System-Level ADRs + + ### ADR-001: Monolithic Architecture + [Full ADR content...] + + --- + + ## Auth Sub-System ADRs + + ### ADR-002: JWT Authentication + [Full ADR content...] + + --- + + ## Payments Sub-System ADRs + + ### ADR-003: Stripe Integration + [Full ADR content...] + ``` + + - Mark each ADR with its parent sub-system in the index + - Add section headers for each sub-system + - Document cross-cutting patterns (e.g., shared database) as System-Level + ### Phase 5: Gap Analysis **Objective**: Identify areas where decisions are unclear @@ -407,6 +568,16 @@ The clarify phase will refine ADRs based on your input, then you can run `/archi - For **contradictory evidence**, present options - For **gaps**, suggest clarification questions +### Sub-System Decomposition + +- **Auto-detect from code**: Analyze directory structure, packages, services automatically +- **Interactive confirmation**: Always confirm sub-system breakdown with user +- **Balanced granularity**: Aim for 3-7 sub-systems; avoid over-decomposition +- **Clear evidence**: Cite specific directories/modules as evidence for each sub-system +- **Per-sub-system analysis**: Run pattern detection per sub-system for focused ADRs +- **Cross-cutting patterns**: Detect and document system-wide patterns separately +- **Use --no-decompose**: Skip decomposition for simple/small codebases + ## Workflow Guidance & Transitions ### After `/architect.init` diff --git a/templates/commands/architect.specify.md b/templates/commands/architect.specify.md index 3d69ebb39b..5b72577737 100644 --- a/templates/commands/architect.specify.md +++ b/templates/commands/architect.specify.md @@ -59,6 +59,8 @@ Transform a PRD (Product Requirements Document) or high-level system description - `all`: Document all decisions discussed - `minimal`: Only high-risk/unconventional decisions +- `--no-decompose`: Disable automatic sub-system decomposition (default: auto-decompose if multiple domains detected) + ## Role & Context You are acting as a **Solutions Architect** facilitating an architectural discovery session. Your role involves: @@ -81,24 +83,132 @@ This command operates at the **System level**, creating ADRs in `.specify/memory Given the PRD input, execute this workflow: -1. **Parse PRD Context**: Extract key requirements, constraints, and quality attributes -2. **Load Governance**: Check `.specify/memory/constitution.md` for architectural constraints -3. **Exploration Phase**: Interactive discussion to surface trade-offs and options -4. **Decision Phase**: Document decisions as ADRs with full rationale -5. **Output**: Write ADRs to `.specify/memory/adr.md` +1. **Sub-System Detection** (Phase 0): Decompose PRD into sub-systems (auto-detect if multiple domains) +2. **Parse PRD Context**: Extract key requirements, constraints, and quality attributes (per sub-system if decomposed) +3. **Load Governance**: Check `.specify/memory/constitution.md` for architectural constraints +4. **Exploration Phase**: Interactive discussion to surface trade-offs and options (per sub-system) +5. **Decision Phase**: Document decisions as ADRs with full rationale (organized by sub-system) +6. **Output**: Write ADRs to `.specify/memory/adr.md` with sub-system organization **NOTE:** This is an interactive command. You will engage the user in conversation before finalizing ADRs. ## Execution Steps +### Phase 0: Sub-System Detection (Greenfield) + +**Objective**: Decompose large PRD into manageable sub-systems automatically + +**When**: This phase runs automatically when the PRD is detected as having multiple distinct domains. Use `--no-decompose` to skip. + +#### Step 1: Domain Analysis + +Analyze the PRD for distinct business domains and functional areas: + +| Domain Category | Typical Keywords | +|-----------------|------------------| +| Authentication | login, auth, oauth, sso, permissions, roles, access control | +| User Management | profile, registration, preferences, settings, account | +| Payments | billing, checkout, subscription, invoicing, pricing | +| Orders | cart, checkout, order management, fulfillment | +| Inventory | stock, warehouse, products, catalog, sku | +| Notifications | email, sms, push, alerts, webhooks | +| Analytics | metrics, reporting, dashboards, data | +| Search | search, indexing, elasticsearch | +| Media | upload, images, video, cdn | +| Messaging | chat, realtime, websocket | + +#### Step 2: Boundary Detection + +Identify boundaries between sub-systems based on: + +1. **Data Ownership**: What data belongs to which domain? +2. **Team Boundaries**: Are different teams responsible for different areas? +3. **Deployment Independence**: Can sub-systems be deployed separately? +4. **Integration Points**: How do sub-systems communicate? + +#### Step 3: Sub-System Proposal (Interactive) + +Present detected sub-systems to user for confirmation: + +```markdown +## Detected Sub-Systems + +I've identified the following sub-systems from your PRD: + +| # | Sub-System | Key Domains | Rationale | +|---|------------|-------------|-----------| +| 1 | **Auth** | Authentication, Authorization | Core security boundary | +| 2 | **Users** | User Management, Profiles | User data ownership | +| 3 | **Payments** | Billing, Subscriptions | Financial domain | +| 4 | **Inventory** | Products, Stock | Physical goods management | + +### Questions for Confirmation: + +1. **Are these sub-systems correct?** [Y/n] +2. **Should any sub-systems be merged?** (e.g., Auth + Users) +3. **Should any sub-systems be split?** (e.g., Payments into Billing + Subscriptions) +4. **Any missing sub-systems?** (e.g., Analytics, Search) + +**Reply** with: +- `Y` to confirm and proceed +- `n` to disable decomposition (generate monolithic ADRs) +- Specific changes (e.g., "merge 1+2", "split 3", "add Notifications") +``` + +#### Step 4: Decomposition Decision + +Based on user response: + +| Response | Action | +|----------|--------| +| `Y` / Enter | Proceed with detected sub-systems | +| `n` | Skip decomposition, generate monolithic ADRs | +| Modifications | Adjust sub-systems, then proceed | +| Empty/Default | Auto-proceed if ≤3 sub-systems, ask if >3 | + +**Threshold Logic**: +- **≤3 sub-systems**: Auto-approve, show summary +- **4-6 sub-systems**: Show summary, ask to confirm +- **>6 sub-systems**: Show summary, suggest grouping, ask to confirm + +#### Step 5: Output + +After confirmation, output structured sub-system data: + +```json +{ + "decomposition": "enabled", + "subsystems": [ + {"id": "auth", "name": "Auth", "domains": ["Authentication", "Authorization"], "rationale": "Security boundary"}, + {"id": "users", "name": "Users", "domains": ["User Management", "Profiles"], "rationale": "User data ownership"}, + {"id": "payments", "name": "Payments", "domains": ["Billing", "Subscriptions"], "rationale": "Financial domain"} + ], + "next_phase": "PRD Analysis (per sub-system)" +} +``` + +**If decomposition disabled**: +```json +{ + "decomposition": "disabled", + "reason": "user_requested", + "next_phase": "PRD Analysis (monolithic)" +} +``` + +--- + ### Phase 1: PRD Analysis **Objective**: Extract architectural drivers from the PRD +**Note**: If sub-system decomposition is enabled (Phase 0), repeat this analysis **per sub-system** to ensure focused, manageable ADRs. + 1. **Identify Functional Drivers**: - Core capabilities the system must provide - Key user interactions and workflows - Integration requirements with external systems + - **For sub-systems**: Focus on the specific sub-system's responsibilities 2. **Identify Quality Attribute Drivers**: - Performance requirements (latency, throughput) @@ -114,19 +224,21 @@ Given the PRD input, execute this workflow: - Regulatory or compliance requirements 4. **Load Constitution**: - - Read `.specify/memory/constitution.md` if it exists - - Extract architectural principles that must be honored - - Note any constraints that limit architectural choices + - Read `.specify/memory/constitution.md` if it exists + - Extract architectural principles that must be honored + - Note any constraints that limit architectural choices 5. **Check Existing Documentation**: - - Scan `README.md` for already-documented tech stack - - Check `AGENTS.md` for project context - - Check team directives: Run `{SCRIPT}` and look for `TEAM_AGENTS_MD` in output - if present, this file contains usage instructions for team-wide agent directives - - Review `CONTRIBUTING.md` for dev guidelines - - Note: Don't duplicate - reference existing docs + - Scan `README.md` for already-documented tech stack + - Check `AGENTS.md` for project context + - Check team directives: Run `{SCRIPT}` and look for `TEAM_AGENTS_MD` in output - if present, this file contains usage instructions for team-wide agent directives + - Review `CONTRIBUTING.md` for dev guidelines + - Note: Don't duplicate - reference existing docs **Output**: Internal summary of architectural drivers (do not write to file yet) +**If decomposed**: Generate separate analysis for each sub-system, noting cross-sub-system dependencies + ### Phase 2: Architectural Exploration (Interactive) **Objective**: Explore solution options through guided discussion @@ -201,14 +313,59 @@ Reply with your choice (A/B/C), or provide additional context. **Objective**: Convert exploration outcomes into formal ADRs +**Note**: If sub-system decomposition is enabled, organize ADRs **by sub-system** with clear section headers. + After each decision is confirmed: 1. **Create ADR Entry**: - Use MADR format from `templates/adr-template.md` - Document context, decision, consequences, and alternatives - Link to constitution principles if applicable + - **Include Sub-System tag**: Mark each ADR with its parent sub-system + +2. **Sub-System Organization**: + +If decomposed, structure the ADR file as: + +```markdown +# Architecture Decision Records + +## ADR Index + +| ID | Sub-System | Decision | Status | Date | Owner | +|----|------------|----------|--------|------|-------| +| ADR-001 | System | Architecture Style | Proposed | 2026-02-26 | User/AI | +| ADR-002 | Auth | JWT Authentication | Proposed | 2026-02-26 | User/AI | +| ADR-003 | Payments | Stripe Integration | Proposed | 2026-02-26 | User/AI | + +--- + +## System-Level ADRs + +### ADR-001: [Decision Title] + +[Full ADR content...] + +--- + +## Auth Sub-System ADRs + +### ADR-002: [Decision Title] + +[Full ADR content...] -2. **ADR Format**: +--- + +## Payments Sub-System ADRs + +### ADR-003: [Decision Title] + +[Full ADR content...] +``` + +3. **Cross-Cutting ADRs**: Some decisions affect multiple sub-systems (e.g., "Use PostgreSQL for all sub-systems"). Mark these as **System-Level** and note impact on each sub-system. + +4. **ADR Format**: ```markdown ## ADR-[NNN]: [Decision Title] @@ -261,17 +418,42 @@ Proposed 1. **Run Setup Script**: - Execute `{SCRIPT}` to ensure `.specify/memory/adr.md` exists - Script creates from template if file doesn't exist + - Pass `--no-decompose` if decomposition was disabled 2. **Write ADRs**: - Append new ADRs to `.specify/memory/adr.md` - - Update ADR index table at top of file + - Update ADR index table at top of file (include Sub-System column) - Preserve any existing ADRs (don't overwrite) + - **If decomposed**: Add section headers for each sub-system 3. **Report Summary**: - - List of ADRs created with IDs and titles + - List of sub-systems identified + - ADRs created per sub-system with IDs and titles - Constitution alignment status + - Cross-cutting decisions noted - Recommended next steps +**Summary Format**: + +```markdown +## Sub-System Decomposition Summary + +### Sub-Systems Identified: 3 + +| # | Sub-System | ADRs Created | +|---|------------|--------------| +| 1 | System-Level | ADR-001: Architecture Style | +| 2 | Auth | ADR-002: JWT Authentication, ADR-003: OAuth2 Integration | +| 3 | Payments | ADR-004: Stripe Integration, ADR-005: Payment Webhooks | + +### Cross-Cutting Decisions +- ADR-001 affects all sub-systems + +### Next Steps +1. Review ADRs with /architect.clarify +2. Generate AD.md with /architect.implement +``` + ## Key Rules ### Exploration First @@ -301,6 +483,16 @@ Proposed - **Alternatives** must explain why they were rejected - Decisions must be **actionable** - clear enough to implement +### Sub-System Decomposition + +- **Auto-detect domains**: Analyze PRD for distinct business domains automatically +- **Interactive confirmation**: Always confirm sub-system breakdown with user +- **Balanced granularity**: Aim for 3-7 sub-systems; avoid over-decomposition +- **Clear boundaries**: Each sub-system should have distinct responsibilities +- **Cross-cutting concerns**: Document system-level decisions separately +- **Per-sub-system exploration**: Run architectural exploration per sub-system for focused decisions +- **Use --no-decompose**: Skip decomposition for simple/small systems + ## Workflow Guidance & Transitions ### After `/architect.specify`