@@ -7,6 +7,7 @@ ACTION=""
77ARGS=()
88VIEWS=" core"
99ADR_HEURISTIC=" surprising"
10+ DECOMPOSE=true
1011
1112# Parse arguments
1213while [[ $# -gt 0 ]]; do
@@ -33,6 +34,14 @@ while [[ $# -gt 0 ]]; do
3334 ADR_HEURISTIC=" ${1#* =} "
3435 shift
3536 ;;
37+ --no-decompose)
38+ DECOMPOSE=false
39+ shift
40+ ;;
41+ --no-decompose=* )
42+ DECOMPOSE=false
43+ shift
44+ ;;
3645 init|map|update|review|specify|implement|clarify)
3746 ACTION=" $1 "
3847 shift
@@ -53,6 +62,7 @@ while [[ $# -gt 0 ]]; do
5362 echo " --json Output results in JSON format"
5463 echo " --views VIEWS Architecture views to generate: core (default), all, or comma-separated"
5564 echo " --adr-heuristic H ADR generation heuristic: surprising (default), all, minimal"
65+ echo " --no-decompose Disable automatic sub-system decomposition (default: auto-detect)"
5666 echo " --help Show this help message"
5767 echo " "
5868 echo " Examples:"
@@ -101,6 +111,151 @@ AD_TEMPLATE_FILE="$REPO_ROOT/.specify/templates/AD-template.md"
101111# Export for use in functions
102112export ARCHITECTURE_VIEWS=" $VIEWS "
103113export ADR_HEURISTIC=" $ADR_HEURISTIC "
114+ export DECOMPOSE=" $DECOMPOSE "
115+
116+ # Function to detect sub-systems from codebase structure
117+ detect_subsystems () {
118+ local subsystems=" "
119+ local count=0
120+
121+ echo " Detecting sub-systems from codebase structure..." >&2
122+
123+ # Check for common sub-system patterns
124+
125+ # 1. Top-level feature directories (src/, app/, services/)
126+ local dirs=()
127+ if [[ -d " src" ]]; then
128+ for d in src/* /; do
129+ if [[ -d " $d " ]]; then
130+ local dirname
131+ dirname=$( basename " $d " )
132+ # Skip common non-sub-system directories
133+ if [[ " $dirname " != " utils" && " $dirname " != " common" && " $dirname " != " lib" && " $dirname " != " shared" && " $dirname " != " core" ]]; then
134+ dirs+=(" $dirname " )
135+ fi
136+ fi
137+ done
138+ fi
139+
140+ if [[ -d " services" ]]; then
141+ for d in services/* /; do
142+ if [[ -d " $d " ]]; then
143+ local dirname
144+ dirname=$( basename " $d " )
145+ dirs+=(" $dirname " )
146+ fi
147+ done
148+ fi
149+
150+ if [[ -d " modules" ]]; then
151+ for d in modules/* /; do
152+ if [[ -d " $d " ]]; then
153+ local dirname
154+ dirname=$( basename " $d " )
155+ dirs+=(" $dirname " )
156+ fi
157+ done
158+ fi
159+
160+ if [[ -d " apps" ]]; then
161+ for d in apps/* /; do
162+ if [[ -d " $d " ]]; then
163+ local dirname
164+ dirname=$( basename " $d " )
165+ dirs+=(" $dirname " )
166+ fi
167+ done
168+ fi
169+
170+ # 2. Check for docker-compose services (microservices indicator)
171+ if [[ -f " docker-compose.yml" ]] || [[ -f " docker-compose.yaml" ]]; then
172+ local compose_file=" docker-compose.yml"
173+ [[ -f " docker-compose.yaml" ]] && compose_file=" docker-compose.yaml"
174+
175+ local services=()
176+ while IFS= read -r line; do
177+ if [[ " $line " =~ ^[[:space:]]* ([a-zA-Z0-9_-]+):[[:space:]]* $ ]]; then
178+ local svc=" ${BASH_REMATCH[1]} "
179+ # Skip common non-service entries
180+ if [[ " $svc " != " version" && " $svc " != " services" && " $svc " != " networks" && " $svc " != " volumes" ]]; then
181+ services+=(" $svc " )
182+ fi
183+ fi
184+ done < " $compose_file "
185+
186+ for svc in " ${services[@]} " ; do
187+ local found=false
188+ for d in " ${dirs[@]} " ; do
189+ if [[ " ${d,,} " == * " ${svc,,} " * ]] || [[ " ${svc,,} " == * " ${d,,} " * ]]; then
190+ found=true
191+ break
192+ fi
193+ done
194+ if [[ " $found " == " false" ]]; then
195+ dirs+=(" $svc " )
196+ fi
197+ done
198+ fi
199+
200+ # 3. Check for Node.js workspaces (monorepo indicator)
201+ if [[ -f " package.json" ]]; then
202+ if grep -q ' "workspaces"' package.json 2> /dev/null; then
203+ local pkgs
204+ pkgs=$( node -e " try { const p = require('./package.json'); console.log(Object.keys(p.workspaces?.packages || {}).join(' ')); } catch(e) { }" 2> /dev/null || true)
205+ for pkg in $pkgs ; do
206+ local dirname
207+ dirname=$( basename " $pkg " )
208+ if [[ " $dirname " != " node_modules" ]]; then
209+ dirs+=(" $dirname " )
210+ fi
211+ done
212+ fi
213+ fi
214+
215+ # 4. Check for Python namespace packages
216+ if [[ -f " pyproject.toml" ]]; then
217+ local pkg_dirs=()
218+ while IFS= read -r -d ' ' d; do
219+ pkg_dirs+=(" $( basename " $d " ) " )
220+ done < <( find . -maxdepth 3 -name " __init__.py" -printf ' %h\n' 2> /dev/null | grep -v node_modules | grep -v __pycache__ | sort -u || true)
221+
222+ for pdir in " ${pkg_dirs[@]} " ; do
223+ if [[ " $pdir " != " ." && " $pdir " != " src" ]]; then
224+ dirs+=(" $pdir " )
225+ fi
226+ done
227+ fi
228+
229+ # Remove duplicates and build output
230+ local unique_dirs=($( printf ' %s\n' " ${dirs[@]} " | sort -u) )
231+
232+ if [[ ${# unique_dirs[@]} -gt 0 ]]; then
233+ echo " Detected potential sub-systems:" >&2
234+ for d in " ${unique_dirs[@]} " ; do
235+ (( count++ ))
236+ echo " - $d " >&2
237+ done
238+ echo " Total: $count sub-system(s)" >&2
239+ else
240+ echo " No distinct sub-systems detected from directory structure." >&2
241+ fi
242+
243+ # Return as JSON if JSON mode
244+ if $JSON_MODE ; then
245+ echo " ["
246+ local first=true
247+ for d in " ${unique_dirs[@]} " ; do
248+ if [[ " $first " == " true" ]]; then
249+ first=false
250+ else
251+ echo " ,"
252+ fi
253+ echo -n " {\" id\" : \" $d \" , \" name\" : \" $d \" , \" detection_method\" : \" directory\" , \" evidence\" : \" directory: $d /\" }"
254+ done
255+ echo " "
256+ echo " ]"
257+ fi
258+ }
104259
105260# Function to detect tech stack from codebase
106261detect_tech_stack () {
@@ -444,6 +599,17 @@ action_specify() {
444599 # Ensure memory directory exists
445600 mkdir -p " $REPO_ROOT /.specify/memory"
446601
602+ # Show decomposition status
603+ if [[ " $DECOMPOSE " == " true" ]]; then
604+ echo " " >&2
605+ echo " 🔄 Sub-system decomposition: ENABLED" >&2
606+ echo " (AI agent will detect domains from PRD and propose sub-systems)" >&2
607+ else
608+ echo " " >&2
609+ echo " ⚠️ Sub-system decomposition: DISABLED (--no-decompose flag)" >&2
610+ echo " (AI agent will generate monolithic ADRs)" >&2
611+ fi
612+
447613 # Initialize ADR file from template if it doesn't exist
448614 if [[ ! -f " $adr_file " ]]; then
449615 if [[ -f " $adr_template " ]]; then
@@ -457,8 +623,8 @@ action_specify() {
457623
458624## ADR Index
459625
460- | ID | Decision | Status | Date | Owner |
461- |----|----------|--------|------|-------|
626+ | ID | Sub-System | Decision | Status | Date | Owner |
627+ |----|------------|---------- |--------|------|-------|
462628
463629---
464630
@@ -472,15 +638,22 @@ EOF
472638 echo " " >&2
473639 echo " Ready for interactive PRD exploration." >&2
474640 echo " The AI agent will:" >&2
641+ if [[ " $DECOMPOSE " == " true" ]]; then
642+ echo " 0. (Phase 0) Detect domains in PRD and propose sub-systems" >&2
643+ echo " → Ask user to confirm sub-system breakdown" >&2
644+ fi
475645 echo " 1. Analyze your PRD/requirements input" >&2
476646 echo " 2. Ask clarifying questions about architecture" >&2
477647 echo " 3. Create ADRs for each key decision" >&2
478648 echo " 4. Save decisions to .specify/memory/adr.md" >&2
649+ if [[ " $DECOMPOSE " == " true" ]]; then
650+ echo " 5. Organize ADRs by sub-system" >&2
651+ fi
479652 echo " " >&2
480653 echo " After completion, run '/architect.implement' to generate full AD.md" >&2
481654
482655 if $JSON_MODE ; then
483- echo " {\" status\" :\" success\" ,\" action\" :\" specify\" ,\" adr_file\" :\" $adr_file \" ,\" context\" :\" ${ARGS[*]} \" }"
656+ echo " {\" status\" :\" success\" ,\" action\" :\" specify\" ,\" adr_file\" :\" $adr_file \" ,\" context\" :\" ${ARGS[*]} \" , \" decomposition \" : \" $DECOMPOSE \" }"
484657 fi
485658}
486659
@@ -589,6 +762,26 @@ action_init() {
589762 local dir_structure
590763 dir_structure=$( map_directory_structure)
591764
765+ # Phase 0: Sub-system detection (if decomposition enabled)
766+ local subsystems_json=" "
767+ local decompose_status=" disabled"
768+
769+ if [[ " $DECOMPOSE " == " true" ]]; then
770+ echo " " >&2
771+ echo " 🔄 Phase 0: Sub-System Detection" >&2
772+ subsystems_json=$( detect_subsystems)
773+ decompose_status=" enabled"
774+
775+ if [[ -n " $subsystems_json " ]] && [[ " $subsystems_json " != " []" ]]; then
776+ echo " " >&2
777+ echo " 📦 Sub-systems will be used to organize ADRs" >&2
778+ echo " (AI agent will confirm with user before proceeding)" >&2
779+ fi
780+ else
781+ echo " " >&2
782+ echo " ⚠️ Sub-system decomposition disabled (--no-decompose flag)" >&2
783+ fi
784+
592785 # Initialize ADR file from template if it doesn't exist
593786 if [[ ! -f " $adr_file " ]]; then
594787 if [[ -f " $adr_template " ]]; then
@@ -602,8 +795,8 @@ action_init() {
602795
603796## ADR Index
604797
605- | ID | Decision | Status | Date | Owner |
606- |----|----------|--------|------|-------|
798+ | ID | Sub-System | Decision | Status | Date | Owner |
799+ |----|------------|---------- |--------|------|-------|
607800
608801---
609802
@@ -623,16 +816,23 @@ EOF
623816 echo " " >&2
624817 echo " Ready for brownfield architecture discovery." >&2
625818 echo " The AI agent will:" >&2
819+ if [[ " $DECOMPOSE " == " true" ]]; then
820+ echo " 0. (Phase 0) Propose sub-systems from code structure" >&2
821+ echo " → Ask user to confirm sub-system breakdown" >&2
822+ fi
626823 echo " 1. Analyze codebase structure and patterns" >&2
627824 echo " 2. Infer architectural decisions from code" >&2
628825 echo " 3. Create ADRs marked as 'Discovered (Inferred)'" >&2
629- echo " 4. Auto-trigger /architect.clarify to validate findings" >&2
826+ if [[ " $DECOMPOSE " == " true" ]]; then
827+ echo " 4. Organize ADRs by sub-system" >&2
828+ fi
829+ echo " 5. Auto-trigger /architect.clarify to validate findings" >&2
630830 echo " " >&2
631831 echo " NOTE: AD.md will NOT be created until ADRs are validated." >&2
632832 echo " After clarification, run /architect.implement to generate AD.md" >&2
633833
634834 if $JSON_MODE ; then
635- echo " {\" status\" :\" success\" ,\" action\" :\" init\" ,\" adr_file\" :\" $adr_file \" ,\" tech_stack\" :\" $tech_stack \" ,\" existing_docs\" :\" $existing_docs \" ,\" source\" :\" brownfield\" }"
835+ 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 }"
636836 fi
637837}
638838
0 commit comments