guardian-framework 0.1.12 → 0.1.14
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
CHANGED
|
@@ -1,471 +1,155 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<
|
|
3
|
-
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/badge/Guardian-Architecture%20Enforcement-00bcd4?style=for-the-badge&labelColor=222">
|
|
4
|
+
<img alt="Guardian" src="https://img.shields.io/badge/Guardian-Architecture%20Enforcement-00bcd4?style=for-the-badge&labelColor=fff">
|
|
5
|
+
</picture>
|
|
6
|
+
|
|
7
|
+
<h3>From idea to production code — with architecture that's actually enforced.</h3>
|
|
8
|
+
|
|
9
|
+
<br/>
|
|
4
10
|
|
|
5
11
|
<a href="https://github.com/arman-jalili/guardian-framework/blob/main/package.json"><img src="https://img.shields.io/github/package-json/v/arman-jalili/guardian-framework?style=flat&colorA=222&colorB=00bcd4" alt="version"/></a>
|
|
6
|
-
<a href="https://github.com/arman-jalili/guardian-framework/actions"><img src="https://img.shields.io/github/actions/workflow/status/arman-jalili/guardian-framework/ci.yml?style=flat&colorA=222&colorB=00bcd4" alt="CI
|
|
12
|
+
<a href="https://github.com/arman-jalili/guardian-framework/actions"><img src="https://img.shields.io/github/actions/workflow/status/arman-jalili/guardian-framework/ci.yml?style=flat&colorA=222&colorB=00bcd4" alt="CI"/></a>
|
|
7
13
|
<a href="LICENSE"><img src="https://img.shields.io/github/license/arman-jalili/guardian-framework?style=flat&colorA=222&colorB=00bcd4" alt="license"/></a>
|
|
8
|
-
<a href="https://bun.sh"><img src="https://img.shields.io/badge/runtime-Bun-f472b6?style=flat&colorA=222" alt="Bun"/></a>
|
|
9
14
|
<br/>
|
|
10
|
-
<a href="https://github.com/arman-jalili/rigorix-oss"><img src="https://img.shields.io/badge/
|
|
15
|
+
<a href="https://github.com/arman-jalili/rigorix-oss"><img src="https://img.shields.io/badge/Built%20with%20Guardian-Rigorix%20(146K%20LOC%20Rust)-00bcd4?style=flat&colorA=222" alt="Rigorix"/></a>
|
|
11
16
|
</div>
|
|
12
17
|
|
|
13
18
|
---
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
It does not analyze architecture once. It integrates with development workflows so every implementation, issue, pull request, and merge is validated against architectural constraints. Violations become CI failures rather than documentation comments.
|
|
18
|
-
|
|
19
|
-
For example, if the architecture specifies that the Payment context may not depend on Authentication, Guardian detects the dependency during CI and blocks the change before merge.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## How It Works
|
|
24
|
-
|
|
25
|
-
Guardian centers on a single `.pi/` directory — the architectural source of truth. From this model it generates the concrete artifacts that enforce architecture across the full development lifecycle:
|
|
26
|
-
|
|
27
|
-
| Artifact | What It Generates |
|
|
28
|
-
|----------|-------------------|
|
|
29
|
-
| Architecture specifications | Module boundaries, component breakdowns, dependency rules, interface contracts |
|
|
30
|
-
| Architecture Decision Records | Structured ADR documents with status tracking and cross-references |
|
|
31
|
-
| Implementation epics | Component-level issues sliced from architecture modules, ordered by dependency |
|
|
32
|
-
| CI enforcement policies | Validator scripts, hardening stages, and merge gates that block violations |
|
|
33
|
-
| Agent workflows | 21 prompt templates covering feature development, bug fixes, hotfixes, refactoring, and issue lifecycle |
|
|
34
|
-
| Tool-specific exports | `.claude/`, `.github/`, `.opencode/`, `.agents/` directories generated from the same `.pi/` source |
|
|
35
|
-
|
|
36
|
-
The `.pi/` model also supports domain modeling with concepts like bounded contexts, entities, and domain events for teams that use those techniques. For everyone else, it works directly from architecture modules and ADRs — no DDD background required.
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## Enforcement Through CI
|
|
20
|
+
### What if your architecture was more than a document?
|
|
41
21
|
|
|
42
|
-
|
|
22
|
+
Most projects start with great architecture ideas, then drift. Implementation strays. Dependencies sneak in the wrong direction. By the time anyone notices, the codebase is fighting the original design.
|
|
43
23
|
|
|
44
|
-
|
|
45
|
-
|-------|-------|-------|---------------------|
|
|
46
|
-
| Simple | 1-2 | <= 50 | CI + canonical |
|
|
47
|
-
| Moderate | 3-5 | 51-200 | CI + architecture + canonical |
|
|
48
|
-
| Complex | 6-15 | 201-500 | CI + architecture + security + tests + integration + canonical |
|
|
49
|
-
| Critical | 16+ | 501+ | All 7 + human approval |
|
|
24
|
+
**Guardian is the tool that prevents that drift — not by documentation, but by enforcement.**
|
|
50
25
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
| Validator | What It Checks | Runs At |
|
|
54
|
-
|-----------|----------------|---------|
|
|
55
|
-
| CI | Build, test, lint, format, audit | All changes |
|
|
56
|
-
| Architecture | Module boundaries, dependency direction, ADR compliance | Moderate+ |
|
|
57
|
-
| Canonical | Every code file references its architecture source; docs match code | All changes |
|
|
58
|
-
| Security | Secrets, injection, path traversal, auth bypass | Complex+ |
|
|
59
|
-
| Tests | Unit, integration, coverage thresholds | Complex+ |
|
|
60
|
-
| Integration | Component wiring, interface contracts | Complex+ |
|
|
61
|
-
| Operations | Tracing, cancellation, atomic writes, error handling | Critical |
|
|
62
|
-
|
|
63
|
-
The canonical validator is the linchpin: every implementation file carries a header tracing it to a specific architecture section. When code and architecture diverge, the reference breaks and CI fails.
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
/**
|
|
67
|
-
* Canonical Reference: .pi/architecture/modules/auth-system.md#token-validation
|
|
68
|
-
* Implements: AC-1, AC-2
|
|
69
|
-
* Issue: #42
|
|
70
|
-
* Last Sync: 2026-06-28
|
|
71
|
-
*/
|
|
72
|
-
```
|
|
26
|
+
It works with AI coding agents (Claude Code, pi, Cursor, Copilot — any of them). You define your architecture once in simple markdown files. Guardian turns those files into executable constraints: CI scripts that validate every change, prompt templates that guide every implementation, and a verification pipeline that blocks merges when code violates architecture.
|
|
73
27
|
|
|
74
28
|
---
|
|
75
29
|
|
|
76
|
-
##
|
|
77
|
-
|
|
78
|
-
Guardian was used to build **[Rigorix](https://github.com/arman-jalili/rigorix-oss)** — a deterministic coding-agent runtime comprising 146,312 lines of Rust across 30 modules, 3 crates, and 580 commits — written by a single developer over 11 active days.
|
|
79
|
-
|
|
80
|
-
During that build:
|
|
81
|
-
|
|
82
|
-
- 18 ADRs defined the architecture
|
|
83
|
-
- 38 module specs described component contracts
|
|
84
|
-
- 44 issue drafts drove implementation across 120+ feature branches
|
|
85
|
-
- 7 validator scripts ran on every merge
|
|
86
|
-
- Architecture violations were detected in CI, reducing reliance on manual code review
|
|
30
|
+
## How It Works — A Complete Walkthrough
|
|
87
31
|
|
|
88
|
-
|
|
32
|
+
**The process is a flow, not a one-time setup. Here's the full loop:**
|
|
89
33
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
## Installation
|
|
34
|
+
### 1. Explore the Domain
|
|
35
|
+
Start by understanding the problem space. Guardian guides you through domain exploration — identifying bounded contexts, entities, and the language your business speaks.
|
|
93
36
|
|
|
94
|
-
```bash
|
|
95
|
-
# CLI tool — scaffold in any project
|
|
96
|
-
npx guardian-framework init
|
|
97
|
-
npm install -g guardian-framework
|
|
98
37
|
```
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
**Prerequisites:** [Bun](https://bun.sh) >= 1.0.0
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## Quick Start
|
|
106
|
-
|
|
107
|
-
### 1. Scaffold the framework
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
cd your-project
|
|
111
|
-
npx guardian-framework init
|
|
38
|
+
/domain --explore "Audit logging for regulated financial transactions"
|
|
112
39
|
```
|
|
113
40
|
|
|
114
|
-
|
|
41
|
+
> Output: structured domain analysis with contexts, entities, and a shared glossary.
|
|
115
42
|
|
|
116
|
-
### 2. Define
|
|
117
|
-
|
|
118
|
-
Architecture modules in `.pi/architecture/modules/` define components, dependencies, and status:
|
|
43
|
+
### 2. Define the Architecture
|
|
44
|
+
From the exploration, Guardian scaffolds architecture modules. Each module describes one bounded context: its components, dependencies, and contract interfaces.
|
|
119
45
|
|
|
120
46
|
```markdown
|
|
121
|
-
#
|
|
47
|
+
# Audit Ingestion
|
|
122
48
|
|
|
123
|
-
##
|
|
49
|
+
## HMAC Signature Verifier
|
|
124
50
|
status: planned
|
|
125
|
-
description:
|
|
51
|
+
description: Verifies HMAC-SHA256 signatures on incoming audit records.
|
|
126
52
|
depends: none
|
|
127
|
-
|
|
128
|
-
## OAuth2 Provider Integration
|
|
129
|
-
status: planned
|
|
130
|
-
description: Google, GitHub OAuth2 for SSO.
|
|
131
|
-
depends: JWT Token Validation
|
|
132
53
|
```
|
|
133
54
|
|
|
134
|
-
### 3.
|
|
55
|
+
### 3. Review & Decide
|
|
56
|
+
Architecture Decision Records (ADRs) capture every meaningful choice — why this approach, not that one. They're version-controlled, cross-referenced, and enforced.
|
|
135
57
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
Generates source tree, build config, and CI pipeline with enforcement pre-wired.
|
|
58
|
+
> **ADR-004:** "Use HMAC-SHA256 with JCS canonicalization for audit signatures."
|
|
59
|
+
> Status: Accepted. Depends on: ADR-003 (JSON Canonicalization Scheme).
|
|
141
60
|
|
|
142
|
-
### 4. Plan
|
|
61
|
+
### 4. Plan the Roadmap
|
|
62
|
+
Group modules into delivery phases with dependencies, migrations, and acceptance criteria.
|
|
143
63
|
|
|
144
64
|
```
|
|
145
|
-
/architect --
|
|
146
|
-
/epic-plan --module auth docs/auth.md # Module-specific slice
|
|
65
|
+
/architect --roadmap
|
|
147
66
|
```
|
|
148
67
|
|
|
149
|
-
|
|
68
|
+
> Shows: Phase 0: Foundation (5 modules, Days 1–5), Phase 1: Core Pipeline (3 modules, Days 6–12)...
|
|
150
69
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
bash .pi/scripts/validate-canonical.sh
|
|
154
|
-
guardian validate # TOML-based declarative validators
|
|
155
|
-
```
|
|
70
|
+
### 5. Execute Phases or Epics
|
|
71
|
+
Guardian generates issue files from your architecture — one issue per component, with full context, acceptance criteria, and auto-generated file changes.
|
|
156
72
|
|
|
157
|
-
### 6. Update and export
|
|
158
|
-
|
|
159
|
-
```bash
|
|
160
|
-
guardian update --dryRun # Preview framework changes
|
|
161
|
-
guardian generate # Export to .claude/, .github/, .opencode/
|
|
162
73
|
```
|
|
163
|
-
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
## CLI Commands
|
|
167
|
-
|
|
168
|
-
| Command | Purpose |
|
|
169
|
-
|---------|---------|
|
|
170
|
-
| `init` | Scaffold `.pi/` framework and exports interactively |
|
|
171
|
-
| `generate` | Regenerate exports from `.pi/` source |
|
|
172
|
-
| `update` | Smart merge new templates, preserving user edits |
|
|
173
|
-
| `upgrade` | Migrate to new framework version |
|
|
174
|
-
| `uninstall` | Remove Guardian-managed files |
|
|
175
|
-
| `info` | Display manifest status, token stats, export sync |
|
|
176
|
-
| `stats` | Token savings analytics and USD estimation |
|
|
177
|
-
| `validate` | Run TOML-based declarative validators |
|
|
178
|
-
| `verify` | SHA-256 file integrity check |
|
|
179
|
-
| `trust` | Trust-gated config management |
|
|
180
|
-
| `domain` | Domain exploration — explore, scaffold, answer, list |
|
|
181
|
-
| `project create` | Generate source tree, build config, CI from architecture |
|
|
182
|
-
|
|
183
|
-
### `update` — Smart Merge
|
|
184
|
-
|
|
185
|
-
```bash
|
|
186
|
-
guardian update --dryRun # Preview changes
|
|
187
|
-
guardian update # Apply with confirmation
|
|
188
|
-
guardian update --force # Override user-modified files
|
|
189
|
-
guardian update --regenerate # Update and regenerate exports
|
|
74
|
+
/architect --phase "Phase 0"
|
|
190
75
|
```
|
|
191
76
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
| New template file | Add to project |
|
|
195
|
-
| Unchanged framework file | Update to new version |
|
|
196
|
-
| User file with YAML front matter | Merge — keep user config, replace body |
|
|
197
|
-
| User file without front matter | Preserve — keep as-is |
|
|
198
|
-
| Generated export | Mark for regeneration |
|
|
199
|
-
| Removed from templates | Orphan — noted, not deleted |
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## Architecture
|
|
204
|
-
|
|
205
|
-
### Directory Structure
|
|
77
|
+
> Creates 5 epics × N component issues each, organized in a pipeline.
|
|
78
|
+
> Each issue includes: `Follow: .pi/skills/agents/rust-codegen.md` — the implementing agent gets the right DDD patterns automatically.
|
|
206
79
|
|
|
80
|
+
The agent implements each component. When done, it calls `pipeline_advance`. Guardian auto-advances through:
|
|
207
81
|
```
|
|
208
|
-
|
|
209
|
-
agent/AGENTS.md Project instructions + YAML runtime config
|
|
210
|
-
architecture/
|
|
211
|
-
modules/ Module architecture docs
|
|
212
|
-
decisions/ ADRs (Architecture Decision Records)
|
|
213
|
-
diagrams/ System overview, data flow diagrams
|
|
214
|
-
context/ Shared knowledge loaded once per session
|
|
215
|
-
domain/ Domain exploration artifacts
|
|
216
|
-
extensions/ 20 TypeScript extensions
|
|
217
|
-
prompts/ 21 workflow prompt templates
|
|
218
|
-
scripts/ 74 validator and utility shell scripts
|
|
219
|
-
ci/ 17 CI stage scripts
|
|
220
|
-
git/ 5 Git management scripts
|
|
221
|
-
languages/ Language-specific validators (Go=7, Java=9, Python=7, Rust=7, TypeScript=7)
|
|
222
|
-
skills/
|
|
223
|
-
agents/ 27 agent definitions
|
|
224
|
-
validators/ 10 validator skill definitions
|
|
225
|
-
validators/ TOML declarative validation configs
|
|
82
|
+
implement → validate → create-mr → merge
|
|
226
83
|
```
|
|
227
84
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
| Tool | Directory | Contents |
|
|
231
|
-
|------|-----------|----------|
|
|
232
|
-
| Claude Code | `.claude/` | Context, agents, workflows, scripts, architecture |
|
|
233
|
-
| OpenCode | `.opencode/` | Context, prompts, workflows, scripts |
|
|
234
|
-
| Agents (Antigravity) | `.agents/` | Agents, context, workflows, scripts |
|
|
235
|
-
| GitHub Copilot | `.github/` | Instructions, agents, copilot configs, workflows |
|
|
236
|
-
| oh-my-pi | `.omp/` | Agents, extensions |
|
|
237
|
-
| pi | `.pi/skills/` | SKILL.md packages |
|
|
238
|
-
|
|
239
|
-
---
|
|
240
|
-
|
|
241
|
-
## Extensions
|
|
242
|
-
|
|
243
|
-
20 TypeScript extensions for pi (`.pi/extensions/`), zero external npm dependencies:
|
|
244
|
-
|
|
245
|
-
| Extension | Purpose |
|
|
246
|
-
|-----------|---------|
|
|
247
|
-
| `architect.ts` | Epic orchestration — discover, implement, validate, merge, close |
|
|
248
|
-
| `pipeline.ts` | Multi-step workflow engine with per-step acceptance gates |
|
|
249
|
-
| `goal-loop.ts` | Standing goals with validator judge — auto-iterates until validated |
|
|
250
|
-
| `kanban.ts` | Durable task board with state machine, dependencies, comments |
|
|
251
|
-
| `domain-explorer.ts` | Domain exploration — explore, answer, scaffold, validate |
|
|
252
|
-
| `project-scaffolder.ts` | Project scaffolding from architecture decisions (Epic 0) |
|
|
253
|
-
| `coordinator.ts` | Scope classification + validation orchestration |
|
|
254
|
-
| `curator.ts` | Skill lifecycle — usage tracking, stale detection, archival |
|
|
255
|
-
| `bash-guard.ts` | Destructive command blocking with risk analysis |
|
|
256
|
-
| `filechanges.ts` | File change tracking with accept/decline review |
|
|
257
|
-
| `plan-mode.ts` | Queued edits for batch review |
|
|
258
|
-
| `snippets.ts` | `#handle` token expansion |
|
|
259
|
-
| `session-persistence.ts` | Structured session lifecycle with auto-titling |
|
|
260
|
-
| `redaction.ts` | Automatic secret redaction |
|
|
261
|
-
| `hooks.ts` | Declarative shell hooks for lifecycle events |
|
|
262
|
-
| `config-reload.ts` | Hot config reload |
|
|
263
|
-
| `read-only-mode.ts` | Safe codebase exploration |
|
|
264
|
-
| `ask-user-question.ts` | Structured user prompts (text, single-select, multi-select) |
|
|
265
|
-
| `slash-commands.ts` | `/init`, `/validate`, `/scope`, `/snippet` commands |
|
|
266
|
-
| `validation-runner.ts` | `/validate` command for running validators |
|
|
85
|
+
If CI fails (architecture violation, security issue, broken test), the pipeline blocks until fixed.
|
|
267
86
|
|
|
268
87
|
---
|
|
269
88
|
|
|
270
|
-
##
|
|
271
|
-
|
|
272
|
-
21 workflow prompt templates in `.pi/prompts/`:
|
|
273
|
-
|
|
274
|
-
### Implementation Workflows
|
|
275
|
-
| Workflow | File | Use When |
|
|
276
|
-
|----------|------|----------|
|
|
277
|
-
| Feature Development | `feature-development.md` | New features (Moderate+ scope) |
|
|
278
|
-
| Bug Fix | `bug-fix.md` | Bug fixes (Simple/Moderate) |
|
|
279
|
-
| Emergency Hotfix | `hotfix.md` | Production issues (skip planning) |
|
|
280
|
-
| Refactoring | `refactoring.md` | Code improvement (behavior unchanged) |
|
|
281
|
-
| Issue Implementation Series | `issue-implementation-series.md` | Batch implementation via pipeline |
|
|
282
|
-
|
|
283
|
-
### Epic and Issue Management
|
|
284
|
-
| Workflow | File | Purpose |
|
|
285
|
-
|----------|------|---------|
|
|
286
|
-
| Epic Plan | `epic-plan.md` | Cross-module, module-slice, or free-form epic planning |
|
|
287
|
-
| Epic Template | `epic-template.md` | Epic definition template |
|
|
288
|
-
| Issue Template | `issue-template.md` | Single issue template |
|
|
289
|
-
| Issue Template Set | `issue-template-set.md` | Full template set for all issue types |
|
|
290
|
-
| Issue Draft | `issue-draft.md` | Create draft issues from approved epic |
|
|
291
|
-
| Git Issues | `git-issues.md` | Create epics/issues on GitHub/GitLab |
|
|
292
|
-
| Issue Closeout | `issue-closeout.md` | Verify AC, validators, canonical, MR |
|
|
293
|
-
| Issue Merge | `issue-merge.md` | Merge MR, close issue, update epic |
|
|
294
|
-
| Plan to Issues | `plan-to-issues.md` | Convert plan documents to GitHub/GitLab issues |
|
|
295
|
-
|
|
296
|
-
### Blueprint and Maintenance
|
|
297
|
-
| Workflow | File | Purpose |
|
|
298
|
-
|----------|------|---------|
|
|
299
|
-
| Blueprint Validate | `blueprint-validate.md` | Validate `.pi/` structure and integrity |
|
|
300
|
-
| CI Blueprint | `ci-blueprint.md` | CI pipeline configuration blueprint |
|
|
301
|
-
| Sync Check | `sync-check.md` | Verify exports match blueprint source |
|
|
302
|
-
| Context Refresh | `context-refresh.md` | Update context from codebase |
|
|
303
|
-
| Scope Analyzer | `scope-analyzer.md` | Auto-determine change scope + validators |
|
|
304
|
-
| Pattern Extract | `pattern-extract.md` | Extract patterns to `patterns.md` |
|
|
305
|
-
| Blueprint Update | `blueprint-update.md` | Reverse-sync implementation to blueprint |
|
|
306
|
-
|
|
307
|
-
---
|
|
89
|
+
## What Makes Guardian Different
|
|
308
90
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
|
312
|
-
|
|
313
|
-
|
|
|
314
|
-
|
|
|
315
|
-
|
|
|
316
|
-
| `/architect abort` | Cancel epic |
|
|
317
|
-
| `/architect --roadmap` | Show all roadmap phases with status |
|
|
318
|
-
| `/architect --phase "Phase 1"` | Start a roadmap phase — creates epics for all modules |
|
|
319
|
-
| `/architect --phase-status` | Show current/next pending phase |
|
|
320
|
-
| `/architect --phase-done <N>` | Mark a phase complete |
|
|
321
|
-
| `/architect --phase-module-done <N> "Module"` | Mark a module done within a phase |
|
|
322
|
-
| `/domain --explore "..."` | Start domain exploration |
|
|
323
|
-
| `/domain --validate <id>` | Validate against domain files |
|
|
324
|
-
| `/domain --architect-scaffold <id>` | Generate module docs from exploration |
|
|
325
|
-
| `/project create --lang java ...` | Scaffold project |
|
|
326
|
-
| `/project status` | Check scaffold status |
|
|
327
|
-
| `/pipeline "Name" --items "A,B" --steps "x,y"` | Start multi-step pipeline |
|
|
328
|
-
| `/pipeline status | pause | resume | abort` | Manage pipeline |
|
|
329
|
-
| `/goal "objective" --validators=ci,tests` | Set persistent goal |
|
|
330
|
-
| `/goal status | pause | resume | clear` | Manage goal |
|
|
331
|
-
| `/subgoal "..." | list | remove | clear` | Manage subgoals |
|
|
332
|
-
| `/kanban create | list | status` | Task board |
|
|
333
|
-
| `/curator review | pin | unpin` | Skill lifecycle |
|
|
334
|
-
| `/snippet list | add | remove | edit` | Token expansion snippets |
|
|
335
|
-
| `/plan` / `/plan-apply` | Queue edits for batch review |
|
|
336
|
-
| `/validate` | Run validators |
|
|
91
|
+
| Instead of... | Guardian does this |
|
|
92
|
+
|---------------|-------------------|
|
|
93
|
+
| Drawing diagrams that go stale | Generates CI scripts that check structure on every commit |
|
|
94
|
+
| Writing "domain must not depend on infrastructure" in a doc | Creates a `check_ddd_structure.sh` that literally greps for illegal imports and fails if found |
|
|
95
|
+
| Trusting code review to catch drift | Blocks merges when architecture is violated — no human oversight needed |
|
|
96
|
+
| Onboarding new devs with 30-page docs | Every issue carries its full context: architecture reference, codegen patterns, acceptance criteria |
|
|
97
|
+
| One-size-fits-all prompts | Generates language-specific codegen skills (Rust, Go, Python, TypeScript, Java/Spring Boot) with DDD + Clean Architecture patterns |
|
|
337
98
|
|
|
338
99
|
---
|
|
339
100
|
|
|
340
|
-
##
|
|
341
|
-
|
|
342
|
-
Tools callable programmatically by the agent during a session:
|
|
343
|
-
|
|
344
|
-
| Tool | Purpose |
|
|
345
|
-
|------|---------|
|
|
346
|
-
| `guardian_scope` | Classify change scope (Simple to Critical) |
|
|
347
|
-
| `guardian_validate` | Run validation scripts by category |
|
|
348
|
-
| `guardian_coordinate` | Orchestrate scope + validation workflow |
|
|
349
|
-
| `guardian_goal_evaluate` | Evaluate goal progress (validator + LLM judge) |
|
|
350
|
-
| `architect_status` | Show epic state |
|
|
351
|
-
| `architect_discover` | Find modules + next slice |
|
|
352
|
-
| `architect_roadmap` | Show roadmap phases and status |
|
|
353
|
-
| `pipeline_status` | Pipeline progress |
|
|
354
|
-
| `pipeline_advance` | Mark step passed |
|
|
355
|
-
| `pipeline_fail` | Mark step failed |
|
|
356
|
-
| `pipeline_start` | Start pipeline programmatically |
|
|
357
|
-
| `pipeline_next_task` | Get current item + step context |
|
|
358
|
-
| `pipeline_run_acceptance` | Run step acceptance gates |
|
|
359
|
-
| `kanban_create` | Create task |
|
|
360
|
-
| `kanban_list` | List tasks |
|
|
361
|
-
| `kanban_show` | Show task details |
|
|
362
|
-
| `kanban_complete` | Mark done |
|
|
363
|
-
| `kanban_block` | Block with reason |
|
|
364
|
-
| `kanban_comment` | Add comment |
|
|
365
|
-
| `domain_explore` | Create exploration prompt |
|
|
366
|
-
| `domain_save_result` | Save analysis session |
|
|
367
|
-
| `domain_validate` | Validate against glossary |
|
|
368
|
-
| `curator_review` | Detect stale skills |
|
|
369
|
-
| `curator_pin` | Protect from archival |
|
|
370
|
-
| `curator_unpin` | Allow archival |
|
|
371
|
-
| `ask_user_question` | Ask user structured questions |
|
|
372
|
-
|
|
373
|
-
---
|
|
374
|
-
|
|
375
|
-
## Token Optimization
|
|
376
|
-
|
|
377
|
-
Guardian includes several mechanisms to reduce token consumption when working with LLM-based coding agents:
|
|
378
|
-
|
|
379
|
-
| Mechanism | How It Works |
|
|
380
|
-
|-----------|-------------|
|
|
381
|
-
| DRY Context | Shared templates loaded once per session rather than per-turn |
|
|
382
|
-
| Snippet Expansion | `#handle` tokens expand to full content on demand |
|
|
383
|
-
| TOML Filters | 8-stage filter pipeline compresses command output before sending to LLM |
|
|
384
|
-
| Validator Scripts | Shell scripts replace LLM-based checks for mechanical validations |
|
|
385
|
-
| Context Compaction | Budget-aware truncation prioritizing structurally important lines |
|
|
101
|
+
## Built with Guardian
|
|
386
102
|
|
|
387
|
-
|
|
103
|
+
**[Rigorix](https://github.com/arman-jalili/rigorix-oss)** — a deterministic coding-agent runtime built using Guardian's own workflow:
|
|
104
|
+
- 146,312 lines of Rust
|
|
105
|
+
- 30 modules across 3 crates
|
|
106
|
+
- 18 ADRs, 38 module specs, 44 issue drafts
|
|
107
|
+
- 580 commits over 11 active days
|
|
108
|
+
- Built by a single developer — Guardian handled orchestration and enforcement
|
|
388
109
|
|
|
389
110
|
---
|
|
390
111
|
|
|
391
|
-
##
|
|
392
|
-
|
|
393
|
-
| Language | Build | Test | Lint | Format | Validators |
|
|
394
|
-
|----------|-------|------|------|--------|------------|
|
|
395
|
-
| TypeScript | `bun build` | `bun test` | `biome check` | `biome format` | 7 |
|
|
396
|
-
| Rust | `cargo build` | `cargo test` | `cargo clippy` | `cargo fmt` | 7 |
|
|
397
|
-
| Python | `python -m build` | `pytest` | `ruff check` | `ruff format` | 7 |
|
|
398
|
-
| Go | `go build ./...` | `go test ./...` | `golangci-lint` | `gofmt` | 7 |
|
|
399
|
-
| Java / Spring Boot | `mvn` / `gradle` | JUnit + Mockito | Checkstyle / Spotless | Spotless | 9 |
|
|
400
|
-
|
|
401
|
-
---
|
|
402
|
-
|
|
403
|
-
## Workflow Configuration
|
|
404
|
-
|
|
405
|
-
`.pi/agent/AGENTS.md` carries YAML front matter defining runtime settings:
|
|
406
|
-
|
|
407
|
-
```yaml
|
|
408
|
-
agent:
|
|
409
|
-
max_turns: 20
|
|
410
|
-
max_retry_backoff_ms: 300000
|
|
411
|
-
stall_timeout_ms: 300000
|
|
412
|
-
|
|
413
|
-
generate:
|
|
414
|
-
on_conflict: warn
|
|
415
|
-
atomic_writes: true
|
|
416
|
-
|
|
417
|
-
validate:
|
|
418
|
-
fail_fast: false
|
|
419
|
-
timeout_ms: 300000
|
|
420
|
-
|
|
421
|
-
goal:
|
|
422
|
-
enabled: true
|
|
423
|
-
max_turns: 20
|
|
424
|
-
judge_validator: true
|
|
425
|
-
|
|
426
|
-
kanban:
|
|
427
|
-
enabled: true
|
|
428
|
-
auto_create_tasks: true
|
|
112
|
+
## Quick Start
|
|
429
113
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
stale_after_days: 30
|
|
433
|
-
archive_after_days: 90
|
|
434
|
-
auto_review: true
|
|
114
|
+
```bash
|
|
115
|
+
npx guardian-framework init
|
|
435
116
|
```
|
|
436
117
|
|
|
437
|
-
|
|
118
|
+
Answer 4 prompts (project name, language, AI tools, validators). You get:
|
|
119
|
+
- A `.pi/` directory with full architecture scaffolding
|
|
120
|
+
- 20 TypeScript extensions (orchestration, pipeline, kanban, validation, etc.)
|
|
121
|
+
- 21 workflow prompt templates
|
|
122
|
+
- 74 CI scripts with language-specific validators
|
|
123
|
+
- Agent export files for Claude Code, pi, Copilot, Cursor, and more
|
|
438
124
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
bun run lint # biome check .
|
|
446
|
-
bun run format # biome format . --write
|
|
447
|
-
bun run typecheck # tsc --noEmit
|
|
125
|
+
Then:
|
|
126
|
+
```
|
|
127
|
+
cd your-project && pi
|
|
128
|
+
/domain --explore "your business domain"
|
|
129
|
+
/architect --roadmap
|
|
130
|
+
/architect --phase "Phase 0"
|
|
448
131
|
```
|
|
449
132
|
|
|
450
133
|
---
|
|
451
134
|
|
|
452
|
-
##
|
|
135
|
+
## One File, One Constraint
|
|
453
136
|
|
|
454
|
-
|
|
455
|
-
- **Contributing:** [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
456
|
-
- **Security:** [SECURITY.md](SECURITY.md)
|
|
457
|
-
- **Changelog:** [CHANGELOG.md](CHANGELOG.md)
|
|
458
|
-
- **Code of Conduct:** [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
|
|
459
|
-
- **Architecture:** See `.pi/architecture/decisions/` for all ADRs
|
|
137
|
+
At the heart of every file is a canonical reference:
|
|
460
138
|
|
|
461
|
-
|
|
139
|
+
```typescript
|
|
140
|
+
//! @canonical .pi/architecture/modules/auth-system.md#token-validation
|
|
141
|
+
//! Issue: #42
|
|
142
|
+
```
|
|
462
143
|
|
|
463
|
-
|
|
144
|
+
When code and architecture diverge, the reference breaks. CI catches it. The merge is blocked. Architecture drift becomes a compile-time error, not a documentation comment.
|
|
464
145
|
|
|
465
|
-
|
|
146
|
+
---
|
|
466
147
|
|
|
467
148
|
## Links
|
|
468
149
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
150
|
+
| | |
|
|
151
|
+
|---|---|
|
|
152
|
+
| **Full User Manual** | [docs/USER_MANUAL.md](docs/USER_MANUAL.md) — every workflow, every command, validated against source |
|
|
153
|
+
| **Reference Implementation** | [Rigorix](https://github.com/arman-jalili/rigorix-oss) — 146K LOC Rust, 30 modules, built with Guardian |
|
|
154
|
+
| **Source** | [github.com/arman-jalili/guardian-framework](https://github.com/arman-jalili/guardian-framework) |
|
|
155
|
+
| **License** | MIT |
|
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.
|
|
1338
|
+
var name = "guardian-framework", version = "0.1.14", 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.
|
|
998
|
+
var name = "guardian-framework", version = "0.1.14", 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
|
@@ -674,7 +674,7 @@ check_import_boundaries() {
|
|
|
674
674
|
esac
|
|
675
675
|
|
|
676
676
|
# Basic check: no cross-layer violations
|
|
677
|
-
#
|
|
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
|
|
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
|