context-engineer 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -0
- package/bin/cli.mjs +91 -0
- package/lib/copy.mjs +102 -0
- package/lib/init.mjs +166 -0
- package/lib/prompts.mjs +144 -0
- package/lib/update.mjs +198 -0
- package/package.json +35 -0
- package/templates/checksums.json +68 -0
- package/templates/claude/.claude/rules/context-maintenance.md +38 -0
- package/templates/claude/.claude/rules/experience-capture.md +46 -0
- package/templates/claude/.claude/settings.project.json +22 -0
- package/templates/claude/.claude/skills/bootstrap/SKILL.md +223 -0
- package/templates/claude/.claude/skills/dev/SKILL.md +119 -0
- package/templates/claude/.claude/skills/dev-capture/SKILL.md +111 -0
- package/templates/claude/.claude/skills/dev-commit/SKILL.md +90 -0
- package/templates/claude/.claude/skills/dev-decompose/SKILL.md +113 -0
- package/templates/claude/.claude/skills/dev-deps/SKILL.md +108 -0
- package/templates/claude/.claude/skills/dev-execute/SKILL.md +196 -0
- package/templates/claude/.claude/skills/dev-prd/SKILL.md +100 -0
- package/templates/claude/.claude/skills/dev-quality/SKILL.md +109 -0
- package/templates/claude/.claude/skills/dev-requirements/SKILL.md +75 -0
- package/templates/claude/.claude/skills/review-context/SKILL.md +120 -0
- package/templates/claude/.claude/skills/sync/SKILL.md +107 -0
- package/templates/claude/.claude/skills/update-context/SKILL.md +105 -0
- package/templates/claude/.claude/workflow/agents/implementer.md +65 -0
- package/templates/claude/.claude/workflow/agents/reviewer.md +96 -0
- package/templates/claude/.claude/workflow/agents/team-config.md +97 -0
- package/templates/claude/.claude/workflow/agents/tester.md +98 -0
- package/templates/claude/.claude/workflow/interfaces/phase-contract.md +157 -0
- package/templates/claude/CLAUDE.md +50 -0
- package/templates/core/.context/_meta/concepts.md +9 -0
- package/templates/core/.context/_meta/drift-report.md +16 -0
- package/templates/core/.context/_meta/last-sync.json +6 -0
- package/templates/core/.context/_meta/schema.md +242 -0
- package/templates/core/.context/architecture/api-surface.md +52 -0
- package/templates/core/.context/architecture/class-index.md +49 -0
- package/templates/core/.context/architecture/data-flow.md +103 -0
- package/templates/core/.context/architecture/data-model.md +35 -0
- package/templates/core/.context/architecture/decisions/001-template.md +35 -0
- package/templates/core/.context/architecture/dependencies.md +35 -0
- package/templates/core/.context/architecture/infrastructure.md +42 -0
- package/templates/core/.context/architecture/module-graph.md +68 -0
- package/templates/core/.context/architecture/overview.md +87 -0
- package/templates/core/.context/business/domain-model.md +43 -0
- package/templates/core/.context/business/glossary.md +23 -0
- package/templates/core/.context/business/overview.md +29 -0
- package/templates/core/.context/business/workflows.md +61 -0
- package/templates/core/.context/constitution.md +84 -0
- package/templates/core/.context/conventions/code-style.md +47 -0
- package/templates/core/.context/conventions/error-handling.md +50 -0
- package/templates/core/.context/conventions/git.md +46 -0
- package/templates/core/.context/conventions/patterns.md +41 -0
- package/templates/core/.context/conventions/testing.md +49 -0
- package/templates/core/.context/experience/debugging.md +21 -0
- package/templates/core/.context/experience/incidents.md +26 -0
- package/templates/core/.context/experience/lessons.md +23 -0
- package/templates/core/.context/experience/performance.md +29 -0
- package/templates/core/.context/index.md +93 -0
- package/templates/core/.context/progress/backlog.md +23 -0
- package/templates/core/.context/progress/status.md +30 -0
- package/templates/core/.context/workflow/artifacts/.gitkeep +0 -0
- package/templates/core/.context/workflow/config.md +35 -0
- package/templates/core/AGENTS.md +53 -0
- package/templates/core/scripts/compact-experience.sh +83 -0
- package/templates/core/scripts/detect-drift.sh +388 -0
- package/templates/core/scripts/extract-structure.sh +757 -0
- package/templates/core/scripts/sync-context.sh +510 -0
- package/templates/cursor/.cursor/rules/always.mdc +18 -0
- package/templates/cursor/.cursor/rules/backend.mdc +16 -0
- package/templates/cursor/.cursor/rules/database.mdc +16 -0
- package/templates/cursor/.cursor/rules/frontend.mdc +13 -0
- package/templates/cursor/.cursorrules +23 -0
- package/templates/github/.github/copilot-instructions.md +15 -0
- package/templates/github/.github/workflows/context-drift.yml +73 -0
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# extract-structure.sh — Extract project structure for context engineering
|
|
4
|
+
#
|
|
5
|
+
# Capabilities:
|
|
6
|
+
# 1. Namespace/module listing with file counts
|
|
7
|
+
# 2. Class/struct/interface definitions with inheritance
|
|
8
|
+
# 3. Import/include dependency graph (module-level)
|
|
9
|
+
# 4. Public function/method signatures
|
|
10
|
+
#
|
|
11
|
+
# Usage: bash scripts/extract-structure.sh [OPTIONS]
|
|
12
|
+
#
|
|
13
|
+
# Options:
|
|
14
|
+
# --all Run all extractions (default)
|
|
15
|
+
# --class-index Extract class/struct/interface index
|
|
16
|
+
# --module-graph Extract module dependency graph
|
|
17
|
+
# --namespaces Extract namespace/directory mapping
|
|
18
|
+
# --functions Extract public function signatures
|
|
19
|
+
# --src-dir DIR Source directory to scan (default: auto-detect)
|
|
20
|
+
# --output-dir DIR Output directory (default: .context/architecture)
|
|
21
|
+
#
|
|
22
|
+
# Supported languages:
|
|
23
|
+
# C/C++: class/struct, #include, namespace
|
|
24
|
+
# C#: class/interface, using, namespace
|
|
25
|
+
# TypeScript: class/interface, import, export
|
|
26
|
+
# Python: class, import, def
|
|
27
|
+
# Rust: struct/trait/impl, use, mod
|
|
28
|
+
# Go: struct/interface, import, package
|
|
29
|
+
# Java: class/interface, import, package
|
|
30
|
+
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
|
|
33
|
+
CONTEXT_DIR=".context"
|
|
34
|
+
OUTPUT_DIR="$CONTEXT_DIR/architecture"
|
|
35
|
+
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
36
|
+
SRC_DIR=""
|
|
37
|
+
|
|
38
|
+
# ============================================================
|
|
39
|
+
# Language Detection
|
|
40
|
+
# ============================================================
|
|
41
|
+
|
|
42
|
+
detect_languages() {
|
|
43
|
+
local langs=()
|
|
44
|
+
|
|
45
|
+
# C/C++
|
|
46
|
+
if find . -maxdepth 5 -name "*.cpp" -o -name "*.h" -o -name "*.hpp" -o -name "*.cc" 2>/dev/null | head -1 | grep -q .; then
|
|
47
|
+
langs+=("cpp")
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# C#
|
|
51
|
+
if find . -maxdepth 5 -name "*.cs" 2>/dev/null | head -1 | grep -q .; then
|
|
52
|
+
langs+=("csharp")
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# TypeScript/JavaScript
|
|
56
|
+
if find . -maxdepth 5 -name "*.ts" -o -name "*.tsx" 2>/dev/null | head -1 | grep -q .; then
|
|
57
|
+
langs+=("typescript")
|
|
58
|
+
elif find . -maxdepth 5 -name "*.js" -o -name "*.jsx" 2>/dev/null | head -1 | grep -q .; then
|
|
59
|
+
langs+=("javascript")
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Python
|
|
63
|
+
if find . -maxdepth 5 -name "*.py" 2>/dev/null | head -1 | grep -q .; then
|
|
64
|
+
langs+=("python")
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Rust
|
|
68
|
+
if find . -maxdepth 5 -name "*.rs" 2>/dev/null | head -1 | grep -q .; then
|
|
69
|
+
langs+=("rust")
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Go
|
|
73
|
+
if find . -maxdepth 5 -name "*.go" 2>/dev/null | head -1 | grep -q .; then
|
|
74
|
+
langs+=("go")
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Java
|
|
78
|
+
if find . -maxdepth 5 -name "*.java" 2>/dev/null | head -1 | grep -q .; then
|
|
79
|
+
langs+=("java")
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
echo "${langs[*]}"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# ============================================================
|
|
86
|
+
# Source Directory Detection
|
|
87
|
+
# ============================================================
|
|
88
|
+
|
|
89
|
+
detect_src_dir() {
|
|
90
|
+
# Common source directory names
|
|
91
|
+
for dir in src source lib app Sources pkg cmd internal; do
|
|
92
|
+
if [ -d "$dir" ]; then
|
|
93
|
+
echo "$dir"
|
|
94
|
+
return
|
|
95
|
+
fi
|
|
96
|
+
done
|
|
97
|
+
# Fallback: current directory
|
|
98
|
+
echo "."
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# ============================================================
|
|
102
|
+
# Namespace / Directory Mapping
|
|
103
|
+
# ============================================================
|
|
104
|
+
|
|
105
|
+
extract_namespaces() {
|
|
106
|
+
local langs="$1"
|
|
107
|
+
echo "Extracting namespace/directory mapping..."
|
|
108
|
+
|
|
109
|
+
local output="$OUTPUT_DIR/module-graph.md"
|
|
110
|
+
|
|
111
|
+
# We'll append the namespace table to the module-graph if it exists
|
|
112
|
+
# For now, output to stdout for integration
|
|
113
|
+
echo ""
|
|
114
|
+
echo "## Namespace / Directory Mapping"
|
|
115
|
+
echo ""
|
|
116
|
+
echo "| Namespace / Package | Directory | File Count |"
|
|
117
|
+
echo "|---------------------|-----------|------------|"
|
|
118
|
+
|
|
119
|
+
if [[ "$langs" == *"cpp"* ]]; then
|
|
120
|
+
# C++: Extract namespaces from source files
|
|
121
|
+
find "$SRC_DIR" -name "*.h" -o -name "*.hpp" -o -name "*.cpp" -o -name "*.cc" 2>/dev/null | while read -r file; do
|
|
122
|
+
grep -oP 'namespace\s+\K[a-zA-Z_][a-zA-Z0-9_:]*' "$file" 2>/dev/null
|
|
123
|
+
done | sort -u | while read -r ns; do
|
|
124
|
+
local dir
|
|
125
|
+
dir=$(find "$SRC_DIR" -name "*.h" -o -name "*.hpp" -o -name "*.cpp" -o -name "*.cc" 2>/dev/null | xargs grep -l "namespace $ns" 2>/dev/null | head -1 | xargs dirname 2>/dev/null || echo "unknown")
|
|
126
|
+
local count
|
|
127
|
+
count=$(find "$SRC_DIR" -name "*.h" -o -name "*.hpp" -o -name "*.cpp" -o -name "*.cc" 2>/dev/null | xargs grep -l "namespace $ns" 2>/dev/null | wc -l || echo "0")
|
|
128
|
+
echo "| $ns | $dir | $count |"
|
|
129
|
+
done
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
if [[ "$langs" == *"csharp"* ]]; then
|
|
133
|
+
# C#: Extract namespaces
|
|
134
|
+
find "$SRC_DIR" -name "*.cs" 2>/dev/null | while read -r file; do
|
|
135
|
+
grep -oP 'namespace\s+\K[a-zA-Z_][a-zA-Z0-9_.]*' "$file" 2>/dev/null
|
|
136
|
+
done | sort -u | while read -r ns; do
|
|
137
|
+
local count
|
|
138
|
+
count=$(find "$SRC_DIR" -name "*.cs" 2>/dev/null | xargs grep -l "namespace $ns" 2>/dev/null | wc -l || echo "0")
|
|
139
|
+
local dir
|
|
140
|
+
dir=$(find "$SRC_DIR" -name "*.cs" 2>/dev/null | xargs grep -l "namespace $ns" 2>/dev/null | head -1 | xargs dirname 2>/dev/null || echo "unknown")
|
|
141
|
+
echo "| $ns | $dir | $count |"
|
|
142
|
+
done
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
if [[ "$langs" == *"python"* ]]; then
|
|
146
|
+
# Python: Extract packages (directories with __init__.py)
|
|
147
|
+
find "$SRC_DIR" -name "__init__.py" 2>/dev/null | while read -r init; do
|
|
148
|
+
local dir
|
|
149
|
+
dir=$(dirname "$init")
|
|
150
|
+
local pkg
|
|
151
|
+
pkg=$(echo "$dir" | tr '/' '.')
|
|
152
|
+
local count
|
|
153
|
+
count=$(find "$dir" -maxdepth 1 -name "*.py" 2>/dev/null | wc -l || echo "0")
|
|
154
|
+
echo "| $pkg | $dir | $count |"
|
|
155
|
+
done
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
if [[ "$langs" == *"go"* ]]; then
|
|
159
|
+
# Go: Extract packages
|
|
160
|
+
find "$SRC_DIR" -name "*.go" 2>/dev/null | while read -r file; do
|
|
161
|
+
grep -oP 'package\s+\K[a-zA-Z_][a-zA-Z0-9_]*' "$file" 2>/dev/null
|
|
162
|
+
done | sort -u | while read -r pkg; do
|
|
163
|
+
local dir
|
|
164
|
+
dir=$(find "$SRC_DIR" -name "*.go" 2>/dev/null | xargs grep -l "package $pkg" 2>/dev/null | head -1 | xargs dirname 2>/dev/null || echo "unknown")
|
|
165
|
+
local count
|
|
166
|
+
count=$(find "$SRC_DIR" -name "*.go" 2>/dev/null | xargs grep -l "package $pkg" 2>/dev/null | wc -l || echo "0")
|
|
167
|
+
echo "| $pkg | $dir | $count |"
|
|
168
|
+
done
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
if [[ "$langs" == *"java"* ]]; then
|
|
172
|
+
# Java: Extract packages
|
|
173
|
+
find "$SRC_DIR" -name "*.java" 2>/dev/null | while read -r file; do
|
|
174
|
+
grep -oP 'package\s+\K[a-zA-Z_][a-zA-Z0-9_.]*' "$file" 2>/dev/null
|
|
175
|
+
done | sort -u | while read -r pkg; do
|
|
176
|
+
local count
|
|
177
|
+
count=$(find "$SRC_DIR" -name "*.java" 2>/dev/null | xargs grep -l "package $pkg" 2>/dev/null | wc -l || echo "0")
|
|
178
|
+
local dir
|
|
179
|
+
dir=$(find "$SRC_DIR" -name "*.java" 2>/dev/null | xargs grep -l "package $pkg" 2>/dev/null | head -1 | xargs dirname 2>/dev/null || echo "unknown")
|
|
180
|
+
echo "| $pkg | $dir | $count |"
|
|
181
|
+
done
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
if [[ "$langs" == *"rust"* ]]; then
|
|
185
|
+
# Rust: Extract modules from mod declarations and directory structure
|
|
186
|
+
find "$SRC_DIR" -name "*.rs" 2>/dev/null | while read -r file; do
|
|
187
|
+
local dir
|
|
188
|
+
dir=$(dirname "$file")
|
|
189
|
+
local modname
|
|
190
|
+
modname=$(basename "$file" .rs)
|
|
191
|
+
if [ "$modname" != "mod" ] && [ "$modname" != "lib" ] && [ "$modname" != "main" ]; then
|
|
192
|
+
echo "| $modname | $dir | 1 |"
|
|
193
|
+
fi
|
|
194
|
+
done | sort -u
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
if [[ "$langs" == *"typescript"* ]] || [[ "$langs" == *"javascript"* ]]; then
|
|
198
|
+
# TypeScript/JavaScript: Extract by directory structure
|
|
199
|
+
find "$SRC_DIR" -maxdepth 3 -type d 2>/dev/null | while read -r dir; do
|
|
200
|
+
local count
|
|
201
|
+
count=$(find "$dir" -maxdepth 1 \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) 2>/dev/null | wc -l || echo "0")
|
|
202
|
+
if [ "$count" -gt 0 ]; then
|
|
203
|
+
echo "| $(basename "$dir") | $dir | $count |"
|
|
204
|
+
fi
|
|
205
|
+
done
|
|
206
|
+
fi
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
# ============================================================
|
|
210
|
+
# Class / Struct / Interface Extraction
|
|
211
|
+
# ============================================================
|
|
212
|
+
|
|
213
|
+
extract_classes() {
|
|
214
|
+
local langs="$1"
|
|
215
|
+
echo "Extracting class/struct/interface definitions..."
|
|
216
|
+
|
|
217
|
+
echo ""
|
|
218
|
+
echo "## Core Classes by Module"
|
|
219
|
+
echo ""
|
|
220
|
+
|
|
221
|
+
if [[ "$langs" == *"cpp"* ]]; then
|
|
222
|
+
echo "### C/C++ Classes"
|
|
223
|
+
echo ""
|
|
224
|
+
echo "| Class | File | Type | Base Class |"
|
|
225
|
+
echo "|-------|------|------|-----------|"
|
|
226
|
+
find "$SRC_DIR" \( -name "*.h" -o -name "*.hpp" \) 2>/dev/null | sort | while read -r file; do
|
|
227
|
+
# Extract class/struct declarations with optional inheritance
|
|
228
|
+
grep -nP '^\s*(class|struct)\s+([A-Z][a-zA-Z0-9_]+)(\s*:\s*(public|protected|private)\s+([A-Z][a-zA-Z0-9_:]+))?' "$file" 2>/dev/null | while IFS=: read -r lineno match; do
|
|
229
|
+
local type name base
|
|
230
|
+
type=$(echo "$match" | grep -oP '^\s*\K(class|struct)')
|
|
231
|
+
name=$(echo "$match" | grep -oP '(class|struct)\s+\K[A-Z][a-zA-Z0-9_]+')
|
|
232
|
+
base=$(echo "$match" | grep -oP '(public|protected|private)\s+\K[A-Z][a-zA-Z0-9_:]+' || echo "—")
|
|
233
|
+
[ -n "$name" ] && echo "| $name | $file:$lineno | $type | $base |"
|
|
234
|
+
done
|
|
235
|
+
done
|
|
236
|
+
echo ""
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
if [[ "$langs" == *"csharp"* ]]; then
|
|
240
|
+
echo "### C# Classes"
|
|
241
|
+
echo ""
|
|
242
|
+
echo "| Class | File | Type | Base Class |"
|
|
243
|
+
echo "|-------|------|------|-----------|"
|
|
244
|
+
find "$SRC_DIR" -name "*.cs" 2>/dev/null | sort | while read -r file; do
|
|
245
|
+
grep -nP '^\s*(public|internal|protected)?\s*(abstract|sealed|static|partial)?\s*(class|interface|struct|record|enum)\s+([A-Z][a-zA-Z0-9_<>]+)(\s*:\s*([A-Z][a-zA-Z0-9_<>,\s]+))?' "$file" 2>/dev/null | while IFS=: read -r lineno match; do
|
|
246
|
+
local type name base
|
|
247
|
+
type=$(echo "$match" | grep -oP '(class|interface|struct|record|enum)')
|
|
248
|
+
name=$(echo "$match" | grep -oP '(class|interface|struct|record|enum)\s+\K[A-Z][a-zA-Z0-9_<>]+')
|
|
249
|
+
base=$(echo "$match" | grep -oP ':\s*\K[A-Z][a-zA-Z0-9_<>]+' || echo "—")
|
|
250
|
+
[ -n "$name" ] && echo "| $name | $file:$lineno | $type | $base |"
|
|
251
|
+
done
|
|
252
|
+
done
|
|
253
|
+
echo ""
|
|
254
|
+
fi
|
|
255
|
+
|
|
256
|
+
if [[ "$langs" == *"python"* ]]; then
|
|
257
|
+
echo "### Python Classes"
|
|
258
|
+
echo ""
|
|
259
|
+
echo "| Class | File | Base Class |"
|
|
260
|
+
echo "|-------|------|-----------|"
|
|
261
|
+
find "$SRC_DIR" -name "*.py" 2>/dev/null | sort | while read -r file; do
|
|
262
|
+
grep -nP '^\s*class\s+([A-Z][a-zA-Z0-9_]+)\s*(\(([^)]*)\))?\s*:' "$file" 2>/dev/null | while IFS=: read -r lineno match; do
|
|
263
|
+
local name base
|
|
264
|
+
name=$(echo "$match" | grep -oP 'class\s+\K[A-Z][a-zA-Z0-9_]+')
|
|
265
|
+
base=$(echo "$match" | grep -oP '\(\K[^)]+' || echo "—")
|
|
266
|
+
[ -n "$name" ] && echo "| $name | $file:$lineno | $base |"
|
|
267
|
+
done
|
|
268
|
+
done
|
|
269
|
+
echo ""
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
if [[ "$langs" == *"typescript"* ]] || [[ "$langs" == *"javascript"* ]]; then
|
|
273
|
+
echo "### TypeScript/JavaScript Classes"
|
|
274
|
+
echo ""
|
|
275
|
+
echo "| Class | File | Type | Base/Implements |"
|
|
276
|
+
echo "|-------|------|------|----------------|"
|
|
277
|
+
find "$SRC_DIR" \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" 2>/dev/null | sort | while read -r file; do
|
|
278
|
+
grep -nP '^\s*(export\s+)?(abstract\s+)?(class|interface)\s+([A-Z][a-zA-Z0-9_<>]+)(\s+(extends|implements)\s+([A-Z][a-zA-Z0-9_<>,\s]+))?' "$file" 2>/dev/null | while IFS=: read -r lineno match; do
|
|
279
|
+
local type name base
|
|
280
|
+
type=$(echo "$match" | grep -oP '(class|interface)')
|
|
281
|
+
name=$(echo "$match" | grep -oP '(class|interface)\s+\K[A-Z][a-zA-Z0-9_<>]+')
|
|
282
|
+
base=$(echo "$match" | grep -oP '(extends|implements)\s+\K[A-Z][a-zA-Z0-9_<>]+' || echo "—")
|
|
283
|
+
[ -n "$name" ] && echo "| $name | $file:$lineno | $type | $base |"
|
|
284
|
+
done
|
|
285
|
+
done
|
|
286
|
+
echo ""
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
if [[ "$langs" == *"rust"* ]]; then
|
|
290
|
+
echo "### Rust Types"
|
|
291
|
+
echo ""
|
|
292
|
+
echo "| Type | File | Kind |"
|
|
293
|
+
echo "|------|------|------|"
|
|
294
|
+
find "$SRC_DIR" -name "*.rs" 2>/dev/null | sort | while read -r file; do
|
|
295
|
+
grep -nP '^\s*pub\s+(struct|enum|trait)\s+([A-Z][a-zA-Z0-9_<>]+)' "$file" 2>/dev/null | while IFS=: read -r lineno match; do
|
|
296
|
+
local kind name
|
|
297
|
+
kind=$(echo "$match" | grep -oP '(struct|enum|trait)')
|
|
298
|
+
name=$(echo "$match" | grep -oP '(struct|enum|trait)\s+\K[A-Z][a-zA-Z0-9_<>]+')
|
|
299
|
+
[ -n "$name" ] && echo "| $name | $file:$lineno | $kind |"
|
|
300
|
+
done
|
|
301
|
+
done
|
|
302
|
+
echo ""
|
|
303
|
+
fi
|
|
304
|
+
|
|
305
|
+
if [[ "$langs" == *"go"* ]]; then
|
|
306
|
+
echo "### Go Types"
|
|
307
|
+
echo ""
|
|
308
|
+
echo "| Type | File | Kind |"
|
|
309
|
+
echo "|------|------|------|"
|
|
310
|
+
find "$SRC_DIR" -name "*.go" -not -name "*_test.go" 2>/dev/null | sort | while read -r file; do
|
|
311
|
+
grep -nP '^\s*type\s+([A-Z][a-zA-Z0-9_]+)\s+(struct|interface)' "$file" 2>/dev/null | while IFS=: read -r lineno match; do
|
|
312
|
+
local kind name
|
|
313
|
+
kind=$(echo "$match" | grep -oP '(struct|interface)$')
|
|
314
|
+
name=$(echo "$match" | grep -oP 'type\s+\K[A-Z][a-zA-Z0-9_]+')
|
|
315
|
+
[ -n "$name" ] && echo "| $name | $file:$lineno | $kind |"
|
|
316
|
+
done
|
|
317
|
+
done
|
|
318
|
+
echo ""
|
|
319
|
+
fi
|
|
320
|
+
|
|
321
|
+
if [[ "$langs" == *"java"* ]]; then
|
|
322
|
+
echo "### Java Classes"
|
|
323
|
+
echo ""
|
|
324
|
+
echo "| Class | File | Type | Base/Implements |"
|
|
325
|
+
echo "|-------|------|------|----------------|"
|
|
326
|
+
find "$SRC_DIR" -name "*.java" 2>/dev/null | sort | while read -r file; do
|
|
327
|
+
grep -nP '^\s*(public|protected)?\s*(abstract|final)?\s*(class|interface|enum|record)\s+([A-Z][a-zA-Z0-9_<>]+)(\s+(extends|implements)\s+([A-Z][a-zA-Z0-9_<>,\s]+))?' "$file" 2>/dev/null | while IFS=: read -r lineno match; do
|
|
328
|
+
local type name base
|
|
329
|
+
type=$(echo "$match" | grep -oP '(class|interface|enum|record)')
|
|
330
|
+
name=$(echo "$match" | grep -oP '(class|interface|enum|record)\s+\K[A-Z][a-zA-Z0-9_<>]+')
|
|
331
|
+
base=$(echo "$match" | grep -oP '(extends|implements)\s+\K[A-Z][a-zA-Z0-9_<>]+' || echo "—")
|
|
332
|
+
[ -n "$name" ] && echo "| $name | $file:$lineno | $type | $base |"
|
|
333
|
+
done
|
|
334
|
+
done
|
|
335
|
+
echo ""
|
|
336
|
+
fi
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
# ============================================================
|
|
340
|
+
# Module Dependency Graph
|
|
341
|
+
# ============================================================
|
|
342
|
+
|
|
343
|
+
extract_module_deps() {
|
|
344
|
+
local langs="$1"
|
|
345
|
+
echo "Extracting module dependency graph..."
|
|
346
|
+
|
|
347
|
+
echo ""
|
|
348
|
+
echo "## Module Dependencies (Import/Include Analysis)"
|
|
349
|
+
echo ""
|
|
350
|
+
|
|
351
|
+
if [[ "$langs" == *"cpp"* ]]; then
|
|
352
|
+
echo "### C/C++ Include Dependencies"
|
|
353
|
+
echo ""
|
|
354
|
+
echo "| Source Directory | Includes From |"
|
|
355
|
+
echo "|-----------------|--------------|"
|
|
356
|
+
# Analyze #include patterns at directory level
|
|
357
|
+
find "$SRC_DIR" \( -name "*.cpp" -o -name "*.cc" -o -name "*.h" -o -name "*.hpp" \) 2>/dev/null | while read -r file; do
|
|
358
|
+
local src_dir
|
|
359
|
+
src_dir=$(dirname "$file")
|
|
360
|
+
grep -oP '#include\s*["<]\K[^">]+' "$file" 2>/dev/null | while read -r inc; do
|
|
361
|
+
local inc_dir
|
|
362
|
+
inc_dir=$(dirname "$inc")
|
|
363
|
+
if [ "$inc_dir" != "." ] && [ "$inc_dir" != "$src_dir" ]; then
|
|
364
|
+
echo "$src_dir → $inc_dir"
|
|
365
|
+
fi
|
|
366
|
+
done
|
|
367
|
+
done | sort -u | head -50 | while read -r dep; do
|
|
368
|
+
local src tgt
|
|
369
|
+
src=$(echo "$dep" | cut -d'→' -f1 | xargs)
|
|
370
|
+
tgt=$(echo "$dep" | cut -d'→' -f2 | xargs)
|
|
371
|
+
echo "| $src | $tgt |"
|
|
372
|
+
done
|
|
373
|
+
echo ""
|
|
374
|
+
fi
|
|
375
|
+
|
|
376
|
+
if [[ "$langs" == *"csharp"* ]]; then
|
|
377
|
+
echo "### C# Namespace Dependencies"
|
|
378
|
+
echo ""
|
|
379
|
+
echo "| Namespace | Uses Namespaces |"
|
|
380
|
+
echo "|-----------|----------------|"
|
|
381
|
+
find "$SRC_DIR" -name "*.cs" 2>/dev/null | while read -r file; do
|
|
382
|
+
local ns
|
|
383
|
+
ns=$(grep -oP 'namespace\s+\K[a-zA-Z_][a-zA-Z0-9_.]*' "$file" 2>/dev/null | head -1)
|
|
384
|
+
[ -z "$ns" ] && continue
|
|
385
|
+
local usings
|
|
386
|
+
usings=$(grep -oP 'using\s+\K[a-zA-Z_][a-zA-Z0-9_.]*' "$file" 2>/dev/null | grep -v "^System" | sort -u | tr '\n' ', ' | sed 's/,$//')
|
|
387
|
+
[ -n "$usings" ] && echo "| $ns | $usings |"
|
|
388
|
+
done | sort -u | head -50
|
|
389
|
+
echo ""
|
|
390
|
+
fi
|
|
391
|
+
|
|
392
|
+
if [[ "$langs" == *"typescript"* ]] || [[ "$langs" == *"javascript"* ]]; then
|
|
393
|
+
echo "### TypeScript/JavaScript Import Dependencies"
|
|
394
|
+
echo ""
|
|
395
|
+
echo "| Source Module | Imports From |"
|
|
396
|
+
echo "|--------------|-------------|"
|
|
397
|
+
find "$SRC_DIR" \( -name "*.ts" -o -name "*.tsx" \) -not -path "*/node_modules/*" 2>/dev/null | while read -r file; do
|
|
398
|
+
local src_mod
|
|
399
|
+
src_mod=$(dirname "$file")
|
|
400
|
+
grep -oP "from\s+['\"]\.{1,2}/\K[^'\"]*" "$file" 2>/dev/null | while read -r imp; do
|
|
401
|
+
local imp_dir
|
|
402
|
+
imp_dir=$(dirname "$imp" 2>/dev/null)
|
|
403
|
+
if [ "$imp_dir" != "." ]; then
|
|
404
|
+
echo "$src_mod → $imp_dir"
|
|
405
|
+
fi
|
|
406
|
+
done
|
|
407
|
+
done | sort -u | head -50 | while read -r dep; do
|
|
408
|
+
local src tgt
|
|
409
|
+
src=$(echo "$dep" | cut -d'→' -f1 | xargs)
|
|
410
|
+
tgt=$(echo "$dep" | cut -d'→' -f2 | xargs)
|
|
411
|
+
echo "| $src | $tgt |"
|
|
412
|
+
done
|
|
413
|
+
echo ""
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
if [[ "$langs" == *"python"* ]]; then
|
|
417
|
+
echo "### Python Import Dependencies"
|
|
418
|
+
echo ""
|
|
419
|
+
echo "| Module | Imports From |"
|
|
420
|
+
echo "|--------|-------------|"
|
|
421
|
+
find "$SRC_DIR" -name "*.py" 2>/dev/null | while read -r file; do
|
|
422
|
+
local src_mod
|
|
423
|
+
src_mod=$(dirname "$file" | tr '/' '.')
|
|
424
|
+
grep -oP '^\s*(from\s+\K[a-zA-Z_][a-zA-Z0-9_.]*|import\s+\K[a-zA-Z_][a-zA-Z0-9_.]*)' "$file" 2>/dev/null | while read -r imp; do
|
|
425
|
+
# Only show project-internal imports (skip stdlib and third-party)
|
|
426
|
+
if [ -d "$(echo "$imp" | tr '.' '/')" ] || [ -f "$(echo "$imp" | tr '.' '/').py" ]; then
|
|
427
|
+
echo "$src_mod → $imp"
|
|
428
|
+
fi
|
|
429
|
+
done
|
|
430
|
+
done | sort -u | head -50 | while read -r dep; do
|
|
431
|
+
local src tgt
|
|
432
|
+
src=$(echo "$dep" | cut -d'→' -f1 | xargs)
|
|
433
|
+
tgt=$(echo "$dep" | cut -d'→' -f2 | xargs)
|
|
434
|
+
echo "| $src | $tgt |"
|
|
435
|
+
done
|
|
436
|
+
echo ""
|
|
437
|
+
fi
|
|
438
|
+
|
|
439
|
+
if [[ "$langs" == *"go"* ]]; then
|
|
440
|
+
echo "### Go Package Dependencies"
|
|
441
|
+
echo ""
|
|
442
|
+
echo "| Package | Imports |"
|
|
443
|
+
echo "|---------|--------|"
|
|
444
|
+
# Get the module name from go.mod
|
|
445
|
+
local go_module=""
|
|
446
|
+
[ -f "go.mod" ] && go_module=$(head -1 go.mod | awk '{print $2}')
|
|
447
|
+
find "$SRC_DIR" -name "*.go" -not -name "*_test.go" 2>/dev/null | while read -r file; do
|
|
448
|
+
local pkg
|
|
449
|
+
pkg=$(grep -oP 'package\s+\K[a-zA-Z_]+' "$file" 2>/dev/null | head -1)
|
|
450
|
+
[ -z "$pkg" ] && continue
|
|
451
|
+
local imports
|
|
452
|
+
imports=$(grep -oP "\"${go_module}/\K[^\"]*" "$file" 2>/dev/null | sort -u | tr '\n' ', ' | sed 's/,$//')
|
|
453
|
+
[ -n "$imports" ] && echo "| $pkg | $imports |"
|
|
454
|
+
done | sort -u | head -50
|
|
455
|
+
echo ""
|
|
456
|
+
fi
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
# ============================================================
|
|
460
|
+
# Public Function Signatures
|
|
461
|
+
# ============================================================
|
|
462
|
+
|
|
463
|
+
extract_functions() {
|
|
464
|
+
local langs="$1"
|
|
465
|
+
echo "Extracting public function signatures..."
|
|
466
|
+
|
|
467
|
+
echo ""
|
|
468
|
+
echo "## Public Function Signatures"
|
|
469
|
+
echo ""
|
|
470
|
+
|
|
471
|
+
if [[ "$langs" == *"cpp"* ]]; then
|
|
472
|
+
echo "### C/C++ Public Methods (from headers)"
|
|
473
|
+
echo ""
|
|
474
|
+
echo "| Class | Method | File |"
|
|
475
|
+
echo "|-------|--------|------|"
|
|
476
|
+
find "$SRC_DIR" \( -name "*.h" -o -name "*.hpp" \) 2>/dev/null | sort | while read -r file; do
|
|
477
|
+
# Extract public method declarations (simplified — after "public:" until "private:" or "protected:" or end of class)
|
|
478
|
+
grep -nP '^\s*(virtual\s+)?\S+\s+\S+\s*\([^;]*\)\s*(const)?\s*(override)?\s*(=\s*0)?\s*;' "$file" 2>/dev/null | head -20 | while IFS=: read -r lineno match; do
|
|
479
|
+
local method
|
|
480
|
+
method=$(echo "$match" | sed 's/^\s*//' | sed 's/\s*;$//')
|
|
481
|
+
echo "| — | \`$method\` | $file:$lineno |"
|
|
482
|
+
done
|
|
483
|
+
done | head -100
|
|
484
|
+
echo ""
|
|
485
|
+
fi
|
|
486
|
+
|
|
487
|
+
if [[ "$langs" == *"csharp"* ]]; then
|
|
488
|
+
echo "### C# Public Methods"
|
|
489
|
+
echo ""
|
|
490
|
+
echo "| Class | Method | File |"
|
|
491
|
+
echo "|-------|--------|------|"
|
|
492
|
+
find "$SRC_DIR" -name "*.cs" 2>/dev/null | sort | while read -r file; do
|
|
493
|
+
grep -nP '^\s*public\s+(static\s+)?(async\s+)?(virtual\s+)?(override\s+)?\S+\s+\S+\s*\(' "$file" 2>/dev/null | head -20 | while IFS=: read -r lineno match; do
|
|
494
|
+
local method
|
|
495
|
+
method=$(echo "$match" | sed 's/^\s*//' | grep -oP 'public\s+\K.*')
|
|
496
|
+
local class
|
|
497
|
+
class=$(head -n "$lineno" "$file" 2>/dev/null | grep -oP '(class|struct)\s+\K[A-Z][a-zA-Z0-9_]+' | tail -1 || echo "—")
|
|
498
|
+
echo "| $class | \`$method\` | $file:$lineno |"
|
|
499
|
+
done
|
|
500
|
+
done | head -100
|
|
501
|
+
echo ""
|
|
502
|
+
fi
|
|
503
|
+
|
|
504
|
+
if [[ "$langs" == *"python"* ]]; then
|
|
505
|
+
echo "### Python Public Functions/Methods"
|
|
506
|
+
echo ""
|
|
507
|
+
echo "| Module | Function | File |"
|
|
508
|
+
echo "|--------|----------|------|"
|
|
509
|
+
find "$SRC_DIR" -name "*.py" 2>/dev/null | sort | while read -r file; do
|
|
510
|
+
# Public functions (not starting with _)
|
|
511
|
+
grep -nP '^\s*def\s+([a-z][a-zA-Z0-9_]*)\s*\(' "$file" 2>/dev/null | grep -v '^\s*def\s+_' | head -20 | while IFS=: read -r lineno match; do
|
|
512
|
+
local func
|
|
513
|
+
func=$(echo "$match" | grep -oP 'def\s+\K[a-zA-Z0-9_]+\s*\([^)]*\)')
|
|
514
|
+
local mod
|
|
515
|
+
mod=$(basename "$file" .py)
|
|
516
|
+
echo "| $mod | \`$func\` | $file:$lineno |"
|
|
517
|
+
done
|
|
518
|
+
done | head -100
|
|
519
|
+
echo ""
|
|
520
|
+
fi
|
|
521
|
+
|
|
522
|
+
if [[ "$langs" == *"go"* ]]; then
|
|
523
|
+
echo "### Go Exported Functions"
|
|
524
|
+
echo ""
|
|
525
|
+
echo "| Package | Function | File |"
|
|
526
|
+
echo "|---------|----------|------|"
|
|
527
|
+
find "$SRC_DIR" -name "*.go" -not -name "*_test.go" 2>/dev/null | sort | while read -r file; do
|
|
528
|
+
grep -nP '^\s*func\s+(\([^)]+\)\s+)?[A-Z][a-zA-Z0-9_]*\s*\(' "$file" 2>/dev/null | head -20 | while IFS=: read -r lineno match; do
|
|
529
|
+
local func
|
|
530
|
+
func=$(echo "$match" | sed 's/^\s*func\s*//' | sed 's/\s*{$//')
|
|
531
|
+
local pkg
|
|
532
|
+
pkg=$(grep -oP 'package\s+\K[a-zA-Z_]+' "$file" 2>/dev/null | head -1)
|
|
533
|
+
echo "| $pkg | \`$func\` | $file:$lineno |"
|
|
534
|
+
done
|
|
535
|
+
done | head -100
|
|
536
|
+
echo ""
|
|
537
|
+
fi
|
|
538
|
+
|
|
539
|
+
if [[ "$langs" == *"rust"* ]]; then
|
|
540
|
+
echo "### Rust Public Functions"
|
|
541
|
+
echo ""
|
|
542
|
+
echo "| Module | Function | File |"
|
|
543
|
+
echo "|--------|----------|------|"
|
|
544
|
+
find "$SRC_DIR" -name "*.rs" 2>/dev/null | sort | while read -r file; do
|
|
545
|
+
grep -nP '^\s*pub\s+(async\s+)?fn\s+[a-z_][a-zA-Z0-9_]*' "$file" 2>/dev/null | head -20 | while IFS=: read -r lineno match; do
|
|
546
|
+
local func
|
|
547
|
+
func=$(echo "$match" | grep -oP 'pub\s+(async\s+)?fn\s+\K[a-zA-Z0-9_]+[^{]*' | sed 's/\s*{$//')
|
|
548
|
+
local mod
|
|
549
|
+
mod=$(basename "$file" .rs)
|
|
550
|
+
echo "| $mod | \`$func\` | $file:$lineno |"
|
|
551
|
+
done
|
|
552
|
+
done | head -100
|
|
553
|
+
echo ""
|
|
554
|
+
fi
|
|
555
|
+
|
|
556
|
+
if [[ "$langs" == *"java"* ]]; then
|
|
557
|
+
echo "### Java Public Methods"
|
|
558
|
+
echo ""
|
|
559
|
+
echo "| Class | Method | File |"
|
|
560
|
+
echo "|-------|--------|------|"
|
|
561
|
+
find "$SRC_DIR" -name "*.java" 2>/dev/null | sort | while read -r file; do
|
|
562
|
+
grep -nP '^\s*public\s+(static\s+)?\S+\s+\S+\s*\(' "$file" 2>/dev/null | head -20 | while IFS=: read -r lineno match; do
|
|
563
|
+
local method
|
|
564
|
+
method=$(echo "$match" | sed 's/^\s*//' | grep -oP 'public\s+\K.*')
|
|
565
|
+
local class
|
|
566
|
+
class=$(grep -oP '(class|interface)\s+\K[A-Z][a-zA-Z0-9_]+' "$file" 2>/dev/null | head -1 || echo "—")
|
|
567
|
+
echo "| $class | \`$method\` | $file:$lineno |"
|
|
568
|
+
done
|
|
569
|
+
done | head -100
|
|
570
|
+
echo ""
|
|
571
|
+
fi
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
# ============================================================
|
|
575
|
+
# Generate class-index.md
|
|
576
|
+
# ============================================================
|
|
577
|
+
|
|
578
|
+
generate_class_index() {
|
|
579
|
+
local langs="$1"
|
|
580
|
+
local output="$OUTPUT_DIR/class-index.md"
|
|
581
|
+
|
|
582
|
+
echo "Generating $output..."
|
|
583
|
+
|
|
584
|
+
{
|
|
585
|
+
echo "# Class Index"
|
|
586
|
+
echo ""
|
|
587
|
+
echo "<!-- AUTO-GENERATED: Do not edit manually. Run scripts/extract-structure.sh to regenerate. -->"
|
|
588
|
+
echo "<!-- generated-from: source code analysis -->"
|
|
589
|
+
echo "<!-- generated-at: $TIMESTAMP -->"
|
|
590
|
+
echo ""
|
|
591
|
+
echo "## Summary"
|
|
592
|
+
echo ""
|
|
593
|
+
echo "Auto-generated index of core classes, interfaces, and key data structures per module."
|
|
594
|
+
echo ""
|
|
595
|
+
extract_classes "$langs"
|
|
596
|
+
} > "$output"
|
|
597
|
+
|
|
598
|
+
echo " → Generated $output"
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
# ============================================================
|
|
602
|
+
# Generate module-graph.md (partial — dependencies + namespaces)
|
|
603
|
+
# ============================================================
|
|
604
|
+
|
|
605
|
+
generate_module_graph() {
|
|
606
|
+
local langs="$1"
|
|
607
|
+
local output="$OUTPUT_DIR/module-graph.md"
|
|
608
|
+
local temp_file="${output}.tmp"
|
|
609
|
+
local marker="<!-- AUTO-GENERATED SECTIONS BELOW -->"
|
|
610
|
+
|
|
611
|
+
echo "Generating module dependency data for $output..."
|
|
612
|
+
|
|
613
|
+
# If file exists and has the auto-generated marker, preserve human-curated sections above it
|
|
614
|
+
if [ -f "$output" ] && grep -q "$marker" "$output" 2>/dev/null; then
|
|
615
|
+
# Keep everything up to and including the marker line
|
|
616
|
+
sed "/$marker/q" "$output" > "$temp_file"
|
|
617
|
+
{
|
|
618
|
+
cat "$temp_file"
|
|
619
|
+
echo ""
|
|
620
|
+
extract_module_deps "$langs"
|
|
621
|
+
extract_namespaces "$langs"
|
|
622
|
+
echo ""
|
|
623
|
+
echo "## Circular Dependencies"
|
|
624
|
+
echo ""
|
|
625
|
+
echo "None detected. <!-- Update if circular dependencies are found -->"
|
|
626
|
+
} > "$output"
|
|
627
|
+
rm -f "$temp_file"
|
|
628
|
+
else
|
|
629
|
+
# First time: generate full file with template
|
|
630
|
+
{
|
|
631
|
+
echo "# Module Graph"
|
|
632
|
+
echo ""
|
|
633
|
+
echo "<!-- confidence: medium -->"
|
|
634
|
+
echo "<!-- source: auto-extracted via scripts/extract-structure.sh -->"
|
|
635
|
+
echo "<!-- last-updated: $(date +%Y-%m-%d) -->"
|
|
636
|
+
echo ""
|
|
637
|
+
echo "## Summary"
|
|
638
|
+
echo ""
|
|
639
|
+
echo "Module dependency graph and namespace mapping. Auto-generated sections are marked below."
|
|
640
|
+
echo ""
|
|
641
|
+
echo "## Subsystems"
|
|
642
|
+
echo ""
|
|
643
|
+
echo "<!-- HUMAN-CURATED: Fill in module responsibilities and key classes -->"
|
|
644
|
+
echo ""
|
|
645
|
+
echo "| Module | Directory | Responsibility | Key Classes |"
|
|
646
|
+
echo "|--------|-----------|---------------|-------------|"
|
|
647
|
+
echo "| [TO BE FILLED] | | | |"
|
|
648
|
+
echo ""
|
|
649
|
+
echo "## Dependency Graph"
|
|
650
|
+
echo ""
|
|
651
|
+
echo "<!-- HUMAN-CURATED: Draw ASCII dependency diagram based on the data below -->"
|
|
652
|
+
echo ""
|
|
653
|
+
echo '```'
|
|
654
|
+
echo "[Draw based on Module Dependencies section below]"
|
|
655
|
+
echo '```'
|
|
656
|
+
echo ""
|
|
657
|
+
echo "## Module Interfaces"
|
|
658
|
+
echo ""
|
|
659
|
+
echo "<!-- HUMAN-CURATED: Document key public interfaces per module -->"
|
|
660
|
+
echo ""
|
|
661
|
+
echo "### [Module Name]"
|
|
662
|
+
echo ""
|
|
663
|
+
echo "**Public Interface**:"
|
|
664
|
+
echo '- `ClassName::method(params)` — One-line description'
|
|
665
|
+
echo ""
|
|
666
|
+
echo "**Depends on**: [Module1, Module2]"
|
|
667
|
+
echo "**Depended by**: [Module3, Module4]"
|
|
668
|
+
echo ""
|
|
669
|
+
echo "---"
|
|
670
|
+
echo ""
|
|
671
|
+
echo "$marker"
|
|
672
|
+
echo ""
|
|
673
|
+
extract_module_deps "$langs"
|
|
674
|
+
extract_namespaces "$langs"
|
|
675
|
+
echo ""
|
|
676
|
+
echo "## Circular Dependencies"
|
|
677
|
+
echo ""
|
|
678
|
+
echo "None detected. <!-- Update if circular dependencies are found -->"
|
|
679
|
+
} > "$output"
|
|
680
|
+
fi
|
|
681
|
+
|
|
682
|
+
echo " → Generated $output"
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
# ============================================================
|
|
686
|
+
# Main
|
|
687
|
+
# ============================================================
|
|
688
|
+
|
|
689
|
+
echo "========================================="
|
|
690
|
+
echo " Structure Extraction"
|
|
691
|
+
echo "========================================="
|
|
692
|
+
echo ""
|
|
693
|
+
|
|
694
|
+
LANGS=$(detect_languages)
|
|
695
|
+
echo "Detected languages: $LANGS"
|
|
696
|
+
|
|
697
|
+
if [ -z "$LANGS" ]; then
|
|
698
|
+
echo "Error: No supported source files found."
|
|
699
|
+
exit 1
|
|
700
|
+
fi
|
|
701
|
+
|
|
702
|
+
# Detect or use provided source directory
|
|
703
|
+
if [ -z "$SRC_DIR" ]; then
|
|
704
|
+
SRC_DIR=$(detect_src_dir)
|
|
705
|
+
fi
|
|
706
|
+
echo "Source directory: $SRC_DIR"
|
|
707
|
+
echo ""
|
|
708
|
+
|
|
709
|
+
# Parse arguments
|
|
710
|
+
TARGET="${1:---all}"
|
|
711
|
+
shift || true
|
|
712
|
+
|
|
713
|
+
while [ $# -gt 0 ]; do
|
|
714
|
+
case "$1" in
|
|
715
|
+
--src-dir)
|
|
716
|
+
SRC_DIR="$2"
|
|
717
|
+
shift 2
|
|
718
|
+
;;
|
|
719
|
+
--output-dir)
|
|
720
|
+
OUTPUT_DIR="$2"
|
|
721
|
+
shift 2
|
|
722
|
+
;;
|
|
723
|
+
*)
|
|
724
|
+
shift
|
|
725
|
+
;;
|
|
726
|
+
esac
|
|
727
|
+
done
|
|
728
|
+
|
|
729
|
+
case "$TARGET" in
|
|
730
|
+
--all)
|
|
731
|
+
generate_class_index "$LANGS"
|
|
732
|
+
generate_module_graph "$LANGS"
|
|
733
|
+
;;
|
|
734
|
+
--class-index)
|
|
735
|
+
generate_class_index "$LANGS"
|
|
736
|
+
;;
|
|
737
|
+
--module-graph)
|
|
738
|
+
generate_module_graph "$LANGS"
|
|
739
|
+
;;
|
|
740
|
+
--namespaces)
|
|
741
|
+
extract_namespaces "$LANGS"
|
|
742
|
+
;;
|
|
743
|
+
--functions)
|
|
744
|
+
extract_functions "$LANGS"
|
|
745
|
+
;;
|
|
746
|
+
*)
|
|
747
|
+
echo "Usage: bash scripts/extract-structure.sh [--all | --class-index | --module-graph | --namespaces | --functions]"
|
|
748
|
+
echo ""
|
|
749
|
+
echo "Options:"
|
|
750
|
+
echo " --src-dir DIR Source directory to scan (default: auto-detect)"
|
|
751
|
+
echo " --output-dir DIR Output directory (default: .context/architecture)"
|
|
752
|
+
exit 1
|
|
753
|
+
;;
|
|
754
|
+
esac
|
|
755
|
+
|
|
756
|
+
echo ""
|
|
757
|
+
echo "Done. Review the generated files and fill in human-curated sections."
|