guardian-framework 0.1.11 → 0.1.13

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/dist/cli.js CHANGED
@@ -1335,7 +1335,7 @@ __export(exports_package, {
1335
1335
  bin: () => bin,
1336
1336
  author: () => author
1337
1337
  });
1338
- var name = "guardian-framework", version = "0.1.11", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
1338
+ var name = "guardian-framework", version = "0.1.13", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
1339
1339
  var init_package = __esm(() => {
1340
1340
  exports = {
1341
1341
  ".": {
package/dist/exports.js CHANGED
@@ -995,7 +995,7 @@ __export(exports_package, {
995
995
  bin: () => bin,
996
996
  author: () => author
997
997
  });
998
- var name = "guardian-framework", version = "0.1.11", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
998
+ var name = "guardian-framework", version = "0.1.13", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
999
999
  var init_package = __esm(() => {
1000
1000
  exports = {
1001
1001
  ".": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guardian-framework",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Token-optimized agentic framework scaffolder with pi-first architecture",
5
5
  "type": "module",
6
6
  "main": "dist/exports.js",
@@ -7,6 +7,7 @@ export function generateIssueMarkdown(
7
7
  slice: ArchitectureSlice,
8
8
  issueIndex: number,
9
9
  totalIssues: number,
10
+ codegenSkill?: string,
10
11
  ): string {
11
12
  const moduleId = slice.module.replace(/^module-/, "");
12
13
  const componentName = component.name.toLowerCase().replace(/\s+/g, "-");
@@ -64,6 +65,7 @@ ${component.dependencies.map((d) => ` - "${d}"`).join("\n")}
64
65
 
65
66
  implementation_notes: |
66
67
  ${component.description || "Implement this component according to the architecture module."}
68
+ ${codegenSkill ? `Follow: .pi/skills/agents/${codegenSkill}.md` : ""}
67
69
 
68
70
  file_changes:
69
71
  - "create: src/${moduleId}/${componentName}/"
@@ -221,6 +221,27 @@ export function readGroupId(cwd: string): string {
221
221
  return "com.example";
222
222
  }
223
223
 
224
+ export function readLanguage(cwd: string): string {
225
+ const manifestPath = join(cwd, "guardian-manifest.json");
226
+ try {
227
+ const raw = readFileSync(manifestPath, "utf-8");
228
+ const manifest = JSON.parse(raw) as { language?: string };
229
+ if (manifest.language) return manifest.language;
230
+ } catch {}
231
+ return "typescript";
232
+ }
233
+
234
+ export function codegenSkillName(language: string): string {
235
+ const map: Record<string, string> = {
236
+ "rust": "rust-codegen",
237
+ "go": "go-codegen",
238
+ "python": "python-codegen",
239
+ "typescript": "typescript-codegen",
240
+ "java": "java-codegen",
241
+ };
242
+ return map[language] || "typescript-codegen";
243
+ }
244
+
224
245
  export function findModuleByName(cwd: string, name: string): string | null {
225
246
  const files = discoverModules(cwd);
226
247
  const nameLower = name.toLowerCase().replace(/[^a-z0-9]/g, "");
@@ -180,6 +180,29 @@ function readRepository(cwd: string): string | null {
180
180
  return null;
181
181
  }
182
182
 
183
+ function readLanguage(cwd: string): string {
184
+ const manifestPath = join(cwd, "guardian-manifest.json");
185
+ try {
186
+ if (existsSync(manifestPath)) {
187
+ const raw = readFileSync(manifestPath, "utf-8");
188
+ const manifest = JSON.parse(raw) as { language?: string };
189
+ if (manifest.language) return manifest.language;
190
+ }
191
+ } catch {}
192
+ return "typescript";
193
+ }
194
+
195
+ function codegenSkillName(language: string): string {
196
+ const map: Record<string, string> = {
197
+ rust: "rust-codegen",
198
+ go: "go-codegen",
199
+ python: "python-codegen",
200
+ typescript: "typescript-codegen",
201
+ java: "java-codegen",
202
+ };
203
+ return map[language] || "typescript-codegen";
204
+ }
205
+
183
206
  /**
184
207
  * Get Git platform base URL. For GitLab, tries to detect self-hosted instances.
185
208
  */
@@ -693,6 +716,7 @@ function generateIssueMarkdown(
693
716
  slice: ArchitectureSlice,
694
717
  issueIndex: number,
695
718
  totalIssues: number,
719
+ codegenSkill?: string,
696
720
  ): string {
697
721
  const moduleId = slice.module.replace(/^module-/, "");
698
722
  const componentName = component.name.toLowerCase().replace(/\s+/g, "-");
@@ -750,6 +774,7 @@ ${component.dependencies.map((d) => ` - "${d}"`).join("\n")}
750
774
 
751
775
  implementation_notes: |
752
776
  ${component.description || "Implement this component according to the architecture module."}
777
+ ${codegenSkill ? `Follow: .pi/skills/agents/${codegenSkill}.md` : ""}
753
778
 
754
779
  file_changes:
755
780
  - "create: src/${moduleId}/${componentName}/"
@@ -1275,6 +1300,8 @@ class EpicManager {
1275
1300
  name: string,
1276
1301
  trackingIssueId?: string,
1277
1302
  ): Promise<EpicState> {
1303
+ const lang = readLanguage(this.cwd);
1304
+ const skillName = codegenSkillName(lang);
1278
1305
  const moduleFiles = discoverModules(this.cwd);
1279
1306
  if (moduleFiles.length === 0) {
1280
1307
  throw new Error("No architecture modules found in .pi/architecture/modules/.");
@@ -1411,7 +1438,7 @@ class EpicManager {
1411
1438
  status: "planned" as string,
1412
1439
  remoteIssueId: null as string | null,
1413
1440
  };
1414
- const md = generateIssueMarkdown(comp, slice, i, slice.nextLogicalSlice.length);
1441
+ const md = generateIssueMarkdown(comp, slice, i, slice.nextLogicalSlice.length, skillName);
1415
1442
  writeFileSync(join(issuesDir, `${id}.md`), md);
1416
1443
  if (hasRemote && remoteRepo) {
1417
1444
  const result = createRemoteIssue(this.cwd, entry.title, join(issuesDir, `${id}.md`), "epic,implementation", remoteRepo);
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-07-03T04:44:32Z",
2
+ "timestamp": "2026-07-03T05:22:36Z",
3
3
  "mode": "all",
4
4
  "stages_run": [],
5
5
  "summary": {
@@ -8,7 +8,7 @@
8
8
  "failed": 1,
9
9
  "skipped": 12
10
10
  },
11
- "duration_seconds": 1,
11
+ "duration_seconds": 0,
12
12
  "results": [
13
13
  {
14
14
  "name": "check_mr_traceability.sh",
@@ -674,7 +674,7 @@ check_import_boundaries() {
674
674
  esac
675
675
 
676
676
  # Basic check: no cross-layer violations
677
- # Layer structure: app/domainapp/applicationapp/infrastructureapp/api
677
+ # DDD 4-layer structure: domain/ → application/ → infrastructure/ → interfaces/
678
678
  local violations=0
679
679
 
680
680
  for layer_dir in app/domain app/application app/infrastructure app/api src/domain src/application src/infrastructure src/api; do
@@ -682,20 +682,49 @@ check_import_boundaries() {
682
682
  while IFS= read -r file; do
683
683
  [[ -f "$file" ]] || continue
684
684
  if [[ "$layer_dir" == *"domain" ]]; then
685
- if grep -qE "from.*infrastructure|from.*api|import.*infrastructure|import.*api" "$file" 2>/dev/null; then
685
+ if grep -qE "from.*infrastructure|from.*api|from.*interfaces|import.*infrastructure|import.*api|import.*interfaces" "$file" 2>/dev/null; then
686
686
  ((violations++))
687
- log_fail "$check_name" "Domain layer imports from infrastructure/api in $(basename "$file")"
687
+ log_fail "$check_name" "Domain layer imports from outer layer in $(basename "$file")"
688
688
  fi
689
689
  fi
690
690
  if [[ "$layer_dir" == *"application" ]]; then
691
- if grep -qE "from.*api|import.*api" "$file" 2>/dev/null; then
691
+ if grep -qE "from.*api|from.*interfaces|import.*api|import.*interfaces" "$file" 2>/dev/null; then
692
692
  ((violations++))
693
- log_fail "$check_name" "Application layer imports from api in $(basename "$file")"
693
+ log_fail "$check_name" "Application layer imports from api/interfaces in $(basename "$file")"
694
694
  fi
695
695
  fi
696
696
  done < <(find "$layer_dir" -name "*.py" -o -name "*.ts" -o -name "*.rs" -o -name "*.go" 2>/dev/null | head -20)
697
697
  done
698
698
 
699
+ # Also check per-module 4-layer DDD structure directly under src/
700
+ local module_dirs
701
+ module_dirs=$(find src -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort)
702
+ for module_dir in $module_dirs; do
703
+ module=$(basename "$module_dir")
704
+ # Skip non-DDD modules (CLI, config, shared)
705
+ case "$module" in shared|common|config|lib|bin) continue ;; esac
706
+
707
+ # Check contracts/ anti-pattern
708
+ if [[ -d "${module_dir}/contracts" ]]; then
709
+ log_fail "$check_name" "Module '${module}' has contracts/ wrapper — should use domain/ application/ infrastructure/ interfaces/"
710
+ fi
711
+
712
+ # Check required DDD layers
713
+ local layers_present=0
714
+ local layers_missing=""
715
+ for layer in domain application infrastructure interfaces; do
716
+ if [[ -d "${module_dir}/${layer}" ]]; then
717
+ layers_present=$((layers_present + 1))
718
+ else
719
+ layers_missing="${layers_missing} ${layer}"
720
+ fi
721
+ done
722
+
723
+ if [[ "$layers_present" -gt 0 ]] && [[ "$layers_present" -lt 4 ]]; then
724
+ log_fail "$check_name" "Module '${module}' has incomplete DDD layers (missing:${layers_missing})"
725
+ fi
726
+ done
727
+
699
728
  if [[ $violations -eq 0 ]]; then
700
729
  log_pass "Import boundary conformance (no cross-layer violations)"
701
730
  fi
@@ -0,0 +1,290 @@
1
+ #!/usr/bin/env bash
2
+ # ============================================================================
3
+ # check_ddd_structure.sh — Validate DDD Clean Architecture layer structure
4
+ #
5
+ # Ensures every module in src/ follows the correct 4-layer DDD structure:
6
+ # src/[module]/domain/
7
+ # src/[module]/application/
8
+ # src/[module]/infrastructure/
9
+ # src/[module]/interfaces/
10
+ #
11
+ # Also checks NO contracts/ wrapper exists (v0.1.10+ pattern) and validates
12
+ # dependency direction (domain must not import from outer layers).
13
+ #
14
+ # Usage:
15
+ # bash .pi/scripts/ci/check_ddd_structure.sh # Run all checks
16
+ # bash .pi/scripts/ci/check_ddd_structure.sh --module X # Single module
17
+ # bash .pi/scripts/ci/check_ddd_structure.sh --fix # Suggest fixes
18
+ #
19
+ # Exit: 0 = all modules conform, 1 = violations found
20
+ # ============================================================================
21
+ set -euo pipefail
22
+
23
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
24
+ PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
25
+ SRC_DIR="${PROJECT_ROOT}/src"
26
+
27
+ RED='\033[0;31m'
28
+ GREEN='\033[0;32m'
29
+ YELLOW='\033[1;33m'
30
+ BLUE='\033[0;34m'
31
+ NC='\033[0m'
32
+
33
+ PASS_COUNT=0
34
+ FAIL_COUNT=0
35
+ ERRORS=()
36
+ CHECK_MODE="full"
37
+ SINGLE_MODULE=""
38
+
39
+ # ── Options ──
40
+ while [[ $# -gt 0 ]]; do
41
+ case $1 in
42
+ --module) SINGLE_MODULE="$2"; shift 2 ;;
43
+ --fix) CHECK_MODE="fix"; shift ;;
44
+ --help)
45
+ sed -n '3,14p' "$0" | sed 's/^#//'
46
+ exit 0
47
+ ;;
48
+ *) shift ;;
49
+ esac
50
+ done
51
+
52
+ pass() { echo -e "${GREEN}✅ PASS${NC} $1"; PASS_COUNT=$((PASS_COUNT + 1)); }
53
+ fail() { echo -e "${RED}❌ FAIL${NC} $1"; FAIL_COUNT=$((FAIL_COUNT + 1)); ERRORS+=("$1"); }
54
+ warn() { echo -e "${YELLOW}⚠️ WARN${NC} $1"; }
55
+
56
+ echo "============================================"
57
+ echo " DDD Layer Structure Check"
58
+ echo "============================================"
59
+ echo ""
60
+
61
+ # ── Language Detection ──
62
+ detect_language() {
63
+ if [[ -f "${PROJECT_ROOT}/Cargo.toml" ]]; then echo "rust"
64
+ elif [[ -f "${PROJECT_ROOT}/go.mod" ]]; then echo "go"
65
+ elif [[ -f "${PROJECT_ROOT}/package.json" || -f "${PROJECT_ROOT}/tsconfig.json" ]]; then echo "typescript"
66
+ elif [[ -f "${PROJECT_ROOT}/pyproject.toml" || -f "${PROJECT_ROOT}/requirements.txt" ]]; then echo "python"
67
+ elif [[ -f "${PROJECT_ROOT}/pom.xml" || -f "${PROJECT_ROOT}/build.gradle" ]]; then echo "java"
68
+ else echo "unknown"; fi
69
+ }
70
+
71
+ PROJECT_LANG=$(detect_language)
72
+ echo "Language: ${BLUE}${PROJECT_LANG}${NC}"
73
+ echo ""
74
+
75
+ # ── File extension mapping ──
76
+ get_source_extensions() {
77
+ case "$1" in
78
+ rust) echo "rs" ;;
79
+ go) echo "go" ;;
80
+ typescript) echo "ts" ;;
81
+ python) echo "py" ;;
82
+ java) echo "java" ;;
83
+ *) echo "rs go ts py java" ;;
84
+ esac
85
+ }
86
+
87
+ get_import_pattern() {
88
+ # Returns regex patterns for import statements that violate dependency direction
89
+ case "$1" in
90
+ rust)
91
+ # Domain importing from infrastructure/application/interfaces is wrong
92
+ echo "use crate::.*infrastructure|use crate::.*application|use crate::.*interfaces"
93
+ ;;
94
+ go)
95
+ echo '"\.\./infrastructure|"\.\./application|"\.\./interfaces'
96
+ ;;
97
+ typescript)
98
+ echo "from.*infrastructure|from.*application|from.*interfaces"
99
+ ;;
100
+ python)
101
+ echo "from.*infrastructure|from.*application|from.*interfaces|import.*infrastructure|import.*application|import.*interfaces"
102
+ ;;
103
+ java)
104
+ echo "import.*infrastructure|import.*application|import.*interfaces"
105
+ ;;
106
+ *)
107
+ echo "infrastructure|application|interfaces"
108
+ ;;
109
+ esac
110
+ }
111
+
112
+ SRC_EXTS=$(get_source_extensions "$PROJECT_LANG")
113
+ IMPORT_PATTERN=$(get_import_pattern "$PROJECT_LANG")
114
+
115
+ # ── Discover modules ──
116
+ declare -a MODULES
117
+ if [[ -n "$SINGLE_MODULE" ]]; then
118
+ if [[ -d "${SRC_DIR}/${SINGLE_MODULE}" ]]; then
119
+ MODULES=("${SINGLE_MODULE}")
120
+ else
121
+ echo -e "${RED}Module '${SINGLE_MODULE}' not found in src/${NC}"
122
+ exit 1
123
+ fi
124
+ else
125
+ # Find top-level directories in src/ — these are modules/bounded contexts
126
+ while IFS= read -r -d '' dir; do
127
+ module=$(basename "$dir")
128
+ # Skip shared/ common/ config/ if they exist
129
+ case "$module" in
130
+ shared|common|config|lib) continue ;;
131
+ esac
132
+ MODULES+=("$module")
133
+ done < <(find "$SRC_DIR" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null | sort -z)
134
+ fi
135
+
136
+ if [[ ${#MODULES[@]} -eq 0 ]]; then
137
+ warn "No modules found in src/ — nothing to check"
138
+ echo ""
139
+ echo "============================================"
140
+ echo " Summary"
141
+ echo "============================================"
142
+ echo -e " Passed: ${GREEN}${PASS_COUNT}${NC}"
143
+ echo -e " Failed: ${RED}${FAIL_COUNT}${NC}"
144
+ echo ""
145
+ echo -e "${YELLOW}No modules to validate.${NC}"
146
+ exit 0
147
+ fi
148
+
149
+ echo "Found ${#MODULES[@]} module(s): ${MODULES[*]}"
150
+ echo ""
151
+
152
+ # ── Required DDD layers ──
153
+ DDD_LAYERS=("domain" "application" "infrastructure" "interfaces")
154
+
155
+ # ── Check 1: Every module has the 4 DDD layers ──
156
+ echo "--- Layer Structure ---"
157
+
158
+ for module in "${MODULES[@]}"; do
159
+ module_dir="${SRC_DIR}/${module}"
160
+ missing=()
161
+ contracts_wrapper=false
162
+
163
+ # Check for contracts/ anti-pattern
164
+ if [[ -d "${module_dir}/contracts" ]]; then
165
+ contracts_wrapper=true
166
+ fi
167
+
168
+ for layer in "${DDD_LAYERS[@]}"; do
169
+ if [[ ! -d "${module_dir}/${layer}" ]]; then
170
+ missing+=("$layer")
171
+ fi
172
+ done
173
+
174
+ if [[ ${#missing[@]} -eq 0 ]] && [[ "$contracts_wrapper" == false ]]; then
175
+ pass "${module} — all 4 DDD layers present"
176
+ elif [[ ${#missing[@]} -eq 0 ]] && [[ "$contracts_wrapper" == true ]]; then
177
+ fail "${module} — has contracts/ wrapper (should be domain/ application/ infrastructure/ interfaces/)"
178
+ else
179
+ fail "${module} — missing layers: ${missing[*]}"
180
+ fi
181
+ done
182
+
183
+ echo ""
184
+
185
+ # ── Check 2: No contracts/ wrapper ──
186
+ echo "--- Anti-Pattern: contracts/ Wrapper ---"
187
+ CONTRACTS_COUNT=0
188
+ for module in "${MODULES[@]}"; do
189
+ if [[ -d "${SRC_DIR}/${module}/contracts" ]]; then
190
+ CONTRACTS_COUNT=$((CONTRACTS_COUNT + 1))
191
+
192
+ # In --fix mode, suggest the rename
193
+ if [[ "$CHECK_MODE" == "fix" ]]; then
194
+ echo -e "${YELLOW} Would fix: git mv ${SRC_DIR}/${module}/contracts/* ${SRC_DIR}/${module}/ && rmdir ${SRC_DIR}/${module}/contracts${NC}"
195
+ fi
196
+ fi
197
+ done
198
+
199
+ if [[ $CONTRACTS_COUNT -eq 0 ]]; then
200
+ pass "No contracts/ wrapper directories found"
201
+ else
202
+ fail "Found ${CONTRACTS_COUNT} module(s) with contracts/ wrapper — should use direct DDD layers"
203
+ fi
204
+
205
+ echo ""
206
+
207
+ # ── Check 3: Dependency direction (domain must not import outer layers) ──
208
+ echo "--- Dependency Direction ---"
209
+ VIOLATIONS=0
210
+
211
+ for module in "${MODULES[@]}"; do
212
+ domain_dir="${SRC_DIR}/${module}/domain"
213
+ if [[ ! -d "$domain_dir" ]]; then
214
+ continue
215
+ fi
216
+
217
+ # Find source files in domain/ and check for illegal imports
218
+ while IFS= read -r -d '' file; do
219
+ if grep -Eq "$IMPORT_PATTERN" "$file" 2>/dev/null; then
220
+ violations=$(grep -En "$IMPORT_PATTERN" "$file" 2>/dev/null || true)
221
+ if [[ -n "$violations" ]]; then
222
+ echo -e "${RED} Illegal import in ${file}${NC}"
223
+ while IFS= read -r line; do
224
+ echo " ${line}"
225
+ done <<< "$violations"
226
+ VIOLATIONS=$((VIOLATIONS + 1))
227
+ fi
228
+ fi
229
+ done < <(find "$domain_dir" -type f \( -name "*.${SRC_EXTS%% *}" $(for ext in ${SRC_EXTS#* }; do echo -o -name "*.$ext"; done) \) -print0 2>/dev/null)
230
+ done
231
+
232
+ if [[ $VIOLATIONS -eq 0 ]]; then
233
+ pass "No dependency direction violations (domain does not import outer layers)"
234
+ else
235
+ fail "Found ${VIOLATIONS} dependency direction violation(s) — domain/ must not import from outer layers"
236
+ fi
237
+
238
+ echo ""
239
+
240
+ # ── Check 4: Repository interfaces defined in domain, implemented in infrastructure ──
241
+ echo "--- Repository Pattern ---"
242
+ REPO_INFRA_ONLY=0
243
+ REPO_MISSING_INFRA=0
244
+
245
+ for module in "${MODULES[@]}"; do
246
+ infra_repo_dir="${SRC_DIR}/${module}/infrastructure/repository"
247
+ domain_repo_file=""
248
+
249
+ # Check for repository file in domain/
250
+ domain_repo=$(find "${SRC_DIR}/${module}/domain" -maxdepth 2 -name "*repository*" -o -name "*repo*" 2>/dev/null | head -1)
251
+
252
+ # Check for repository implementation in infrastructure/
253
+ infra_repo=$(find "${SRC_DIR}/${module}/infrastructure" -maxdepth 3 -name "*repository*" -o -name "*repo*" 2>/dev/null | head -1)
254
+
255
+ if [[ -n "$domain_repo" ]] && [[ -z "$infra_repo" ]]; then
256
+ warn "${module} — repository interface in domain/ but no implementation in infrastructure/"
257
+ REPO_MISSING_INFRA=$((REPO_MISSING_INFRA + 1))
258
+ fi
259
+ done
260
+
261
+ if [[ $REPO_MISSING_INFRA -eq 0 ]]; then
262
+ pass "Repository interfaces have implementations in infrastructure/ (where applicable)"
263
+ else
264
+ warn "${REPO_MISSING_INFRA} module(s) with unreferenced repository interfaces"
265
+ fi
266
+
267
+ echo ""
268
+
269
+ # ── Summary ──
270
+ echo "============================================"
271
+ echo " Summary"
272
+ echo "============================================"
273
+ echo -e " Language: ${BLUE}${PROJECT_LANG}${NC}"
274
+ echo -e " Modules: ${BLUE}${#MODULES[@]}${NC}"
275
+ echo -e " Passed: ${GREEN}${PASS_COUNT}${NC}"
276
+ echo -e " Failed: ${RED}${FAIL_COUNT}${NC}"
277
+ echo ""
278
+
279
+ if [[ ${#ERRORS[@]} -gt 0 ]]; then
280
+ echo "FAILURES:"
281
+ for err in "${ERRORS[@]}"; do
282
+ echo " - $err"
283
+ done
284
+ echo ""
285
+ echo -e "${RED}DDD structure violations found. Fix before merging.${NC}"
286
+ exit 1
287
+ fi
288
+
289
+ echo -e "${GREEN}All modules conform to DDD Clean Architecture layer structure.${NC}"
290
+ exit 0
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: go-codegen
3
+ description: Minimal skill for Go code generation with DDD + Clean Architecture. References full patterns on demand — never loads inline. Use when implementing Go modules following enterprise patterns.
4
+ model: inherit
5
+ tools: [Read, Grep]
6
+ ---
7
+
8
+ # Go Code Generation — DDD + Clean Architecture Patterns
9
+
10
+ > Do NOT load the full reference document. Read specific sections when needed.
11
+ > Full reference: `.pi/skills/go-enterprise-codegen.md`
12
+
13
+ ## Quick Reference
14
+
15
+ | When you need... | Read this section |
16
+ |-----------------|-------------------|
17
+ | Module structure | Section 1 — 4-layer DDD layout + dependency direction |
18
+ | Domain entities | Section 2 — entity.go, value.go, repository interface |
19
+ | Error handling | Section 3 — *DomainError, ErrorCode, sentinel errors |
20
+ | Application services | Section 4 — Service interface + implementation |
21
+ | Repository impl | Section 5 — GORM/sql implementation pattern |
22
+ | HTTP handlers | Section 6 — Handler → Service → Domain flow |
23
+ | Configuration | Section 7 — envconfig/viper pattern |
24
+ | Testing | Section 8 — unit tests, repository tests |
25
+ | Anti-patterns | Section 9 — what NOT to do |
26
+ | Project structure | Section 10 — cmd/ internal/ pkg/ layout |
27
+
28
+ ## DDD Layer Contract
29
+
30
+ | Layer | Purpose | Dependencies |
31
+ |-------|---------|-------------|
32
+ | `domain/` | Pure business logic | None (stdlib only) |
33
+ | `application/` | Use case orchestration | `domain/` |
34
+ | `infrastructure/` | External adapters | `domain/` + `application/` |
35
+ | `interfaces/` | API contracts | `application/` |
36
+
37
+ ## Rules
38
+ - NEVER read full reference — read specific sections
39
+ - Use `grep` + `Read offset/limit` to target sections
40
+ - Follow the DDD layer structure — no `contracts/` wrapper
41
+ - Always define repository interfaces in `domain/`, implement in `infrastructure/`
42
+ - Always use typed `*DomainError`, never bare strings
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: java-codegen
3
+ description: Minimal skill for Java/Spring Boot code generation with DDD + Clean Architecture. References full patterns on demand — never loads inline. Use when implementing Java modules following enterprise patterns.
4
+ model: inherit
5
+ tools: [Read, Grep]
6
+ ---
7
+
8
+ # Java/Spring Boot Code Generation — DDD + Clean Architecture Patterns
9
+
10
+ > Do NOT load the full reference document. Read specific sections when needed.
11
+ > Full reference: `.pi/skills/java-spring-enterprise-codegen.md`
12
+
13
+ ## Quick Reference
14
+
15
+ | When you need... | Read this section |
16
+ |-----------------|-------------------|
17
+ | Module structure | Section 1 — 4-layer DDD layout + dependency direction |
18
+ | Domain entities | Section 2 — Entity.java, Value Object record, Repository interface |
19
+ | Error handling | Section 3 — DomainError, ErrorCode enum |
20
+ | Application services | Section 4 — @Service, interface + impl pattern |
21
+ | Repository impl | Section 5 — JPA EntityManager repository |
22
+ | REST controllers | Section 6 — @RestController, @ExceptionHandler |
23
+ | Testing | Section 7 — MockMvc, @SpringBootTest |
24
+ | Anti-patterns | Section 8 — what NOT to do |
25
+ | Project structure | Section 9 — Maven/Gradle module layout |
26
+
27
+ ## DDD Layer Contract
28
+
29
+ | Layer | Purpose | Dependencies |
30
+ |-------|---------|-------------|
31
+ | `domain/` | Pure business logic | None (pure Java, no Spring) |
32
+ | `application/` | Use case orchestration | `domain/` |
33
+ | `infrastructure/` | External adapters | `domain/` + `application/` |
34
+ | `interfaces/` | API contracts | `application/` |
35
+
36
+ ## Rules
37
+ - NEVER read full reference — read specific sections
38
+ - Use `grep` + `Read offset/limit` to target sections
39
+ - Follow the DDD layer structure — no `contracts/` wrapper
40
+ - Domain layer has ZERO Spring annotations
41
+ - Use constructor injection, NEVER field injection
42
+ - Use `record` for value objects (Java 16+)
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: python-codegen
3
+ description: Minimal skill for Python code generation with DDD + Clean Architecture. References full patterns on demand — never loads inline. Use when implementing Python modules following enterprise patterns.
4
+ model: inherit
5
+ tools: [Read, Grep]
6
+ ---
7
+
8
+ # Python Code Generation — DDD + Clean Architecture Patterns
9
+
10
+ > Do NOT load the full reference document. Read specific sections when needed.
11
+ > Full reference: `.pi/skills/python-enterprise-codegen.md`
12
+
13
+ ## Quick Reference
14
+
15
+ | When you need... | Read this section |
16
+ |-----------------|-------------------|
17
+ | Module structure | Section 1 — 4-layer DDD layout + dependency direction |
18
+ | Domain entities | Section 2 — entity.py, value.py, repository ABC |
19
+ | Error handling | Section 3 — DomainError, ErrorCode enum |
20
+ | Application services | Section 4 — Service class |
21
+ | Repository impl | Section 5 — SQLAlchemy implementation pattern |
22
+ | API controllers | Section 6 — FastAPI route handlers, error mapping |
23
+ | Testing | Section 7 — pytest unit tests |
24
+ | Anti-patterns | Section 8 — what NOT to do |
25
+ | Project structure | Section 9 — src/ module layout |
26
+
27
+ ## DDD Layer Contract
28
+
29
+ | Layer | Purpose | Dependencies |
30
+ |-------|---------|-------------|
31
+ | `domain/` | Pure business logic | None (stdlib only) |
32
+ | `application/` | Use case orchestration | `domain/` |
33
+ | `infrastructure/` | External adapters | `domain/` + `application/` |
34
+ | `interfaces/` | API contracts | `application/` |
35
+
36
+ ## Rules
37
+ - NEVER read full reference — read specific sections
38
+ - Use `grep` + `Read offset/limit` to target sections
39
+ - Follow the DDD layer structure — no `contracts/` wrapper
40
+ - Use `@dataclass(frozen=True)` for value objects
41
+ - Use `ABC` for repository interfaces