guardian-framework 0.1.12 → 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.12", 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.12", 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.12",
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",
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-07-03T05:15:47Z",
2
+ "timestamp": "2026-07-03T05:22:36Z",
3
3
  "mode": "all",
4
4
  "stages_run": [],
5
5
  "summary": {
@@ -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