guardian-framework 0.1.24 → 0.1.26

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.
@@ -190,6 +190,132 @@ function buildExplorationPrompt(context: string): string {
190
190
  ].join("\n");
191
191
  }
192
192
 
193
+ function readLanguage(cwd: string): string {
194
+ try {
195
+ const manifestPath = path.join(cwd, "guardian-manifest.json");
196
+ if (fs.existsSync(manifestPath)) {
197
+ const raw = fs.readFileSync(manifestPath, "utf-8");
198
+ const manifest = JSON.parse(raw) as { language?: string };
199
+ if (manifest.language) return manifest.language;
200
+ }
201
+ } catch {}
202
+ return "typescript";
203
+ }
204
+
205
+ function buildFrontendExplorationPrompt(context: string): string {
206
+ return [
207
+ "You are a frontend architecture expert. Analyze the following web application",
208
+ "description and extract a structured model focused on user experience,",
209
+ "UI concepts, and design principles. Respond with valid JSON only.",
210
+ "",
211
+ "## Business Context",
212
+ "",
213
+ context,
214
+ "",
215
+ "## Output Format (JSON)",
216
+ "",
217
+ "\`\`\`json",
218
+ "{",
219
+ ' "businessContext": "Brief one-line summary",',
220
+ ' "actors": [',
221
+ " {",
222
+ ' "name": "UserRole",',
223
+ ' "description": "Who this user is",',
224
+ ' "interactions": "What they do in the application"',
225
+ " }",
226
+ " ],",
227
+ ' "functionalRequirements": [',
228
+ " {",
229
+ ' "id": "FR-001",',
230
+ ' "requirement": "The user shall be able to...",',
231
+ ' "priority": "critical|high|medium|low",',
232
+ ' "boundedContext": "FeatureName"',
233
+ " }",
234
+ " ],",
235
+ ' "nonFunctionalRequirements": [',
236
+ " {",
237
+ ' "id": "NFR-001",',
238
+ ' "requirement": "The application shall...",',
239
+ ' "category": "performance|accessibility|usability|security|maintainability",',
240
+ ' "target": "Specific measurable target"',
241
+ " }",
242
+ " ],",
243
+ ' "assumptions": [',
244
+ " {",
245
+ ' "assumption": "We assume that...",',
246
+ ' "impactIfWrong": "What breaks if this is false",',
247
+ ' "mitigation": "How we handle it being wrong"',
248
+ " }",
249
+ " ],",
250
+ ' "boundedContexts": [',
251
+ " {",
252
+ ' "name": "FeatureName",',
253
+ ' "description": "Brief description of this app feature/section",',
254
+ ' "entities": ["UIConcept1", "UIConcept2"]',
255
+ " }",
256
+ " ],",
257
+ ' "entities": [',
258
+ " {",
259
+ ' "name": "UIConceptName",',
260
+ ' "context": "FeatureName",',
261
+ ' "type": "ui-concept | user-intent | design-token | app-shell | value-object",',
262
+ ' "description": "What this UI concept represents"',
263
+ " }",
264
+ " ],",
265
+ ' "userIntents": [',
266
+ " {",
267
+ ' "name": "UserIntentName",',
268
+ ' "context": "FeatureName",',
269
+ ' "description": "What the user is trying to do",',
270
+ ' "triggeredBy": "What UI action triggers this intent"',
271
+ " }",
272
+ " ],",
273
+ ' "designPrinciples": [',
274
+ " {",
275
+ ' "principle": "The application is...",',
276
+ ' "description": "What this principle means in practice",',
277
+ ' "rationale": "Why this principle exists"',
278
+ " }",
279
+ " ],",
280
+ ' "navigationPhilosophy": {',
281
+ ' "contextPreservation": "How the user never loses context",',
282
+ ' "deepLinking": "How every page is deep-linkable",',
283
+ ' "multiTab": "How multiple tabs are supported"',
284
+ " },",
285
+ ' "appShell": {',
286
+ ' "navigation": "Navigation structure",',
287
+ ' "header": "Header content",',
288
+ ' "sidebar": "Sidebar content",',
289
+ ' "commandPalette": "Command palette actions",',
290
+ ' "globalSearch": "Global search behavior"',
291
+ " },",
292
+ ' "degradationStrategy": [',
293
+ " {",
294
+ ' "feature": "FeatureName",',
295
+ ' "whenUnavailable": "What happens when this feature API is down",',
296
+ ' "degradesTo": "What still works"',
297
+ " }",
298
+ " ],",
299
+ ' "ubiquitousLanguage": [',
300
+ " {",
301
+ ' "term": "CanonicalTerm",',
302
+ ' "definition": "Clear definition",',
303
+ ' "boundedContext": "FeatureName",',
304
+ ' "aliases": ["AlternativeName1"],',
305
+ ' "examples": "Usage example"',
306
+ " }",
307
+ " ],",
308
+ ' "openQuestions": "Any open questions about the application",',
309
+ ' "designSystem": {',
310
+ ' "componentLibrary": "Which component library or approach",',
311
+ ' "theming": "How theming works",',
312
+ ' "accessibility": "Accessibility requirements"',
313
+ " }",
314
+ "}",
315
+ "\`\`\`",
316
+ ].join("\n");
317
+ }
318
+
193
319
  // ── Domain Explore Tool (deprecated) ──
194
320
 
195
321
  export default function (pi: ExtensionAPI) {
@@ -473,7 +599,9 @@ export default function (pi: ExtensionAPI) {
473
599
  return "(domain command handled)";
474
600
  }
475
601
  const sanitized = sanitizeContext(context);
476
- const prompt = buildExplorationPrompt(sanitized);
602
+ const lang = readLanguage(ctx.cwd);
603
+ const isFrontend = lang === "nextjs" || lang === "angular";
604
+ const prompt = isFrontend ? buildFrontendExplorationPrompt(sanitized) : buildExplorationPrompt(sanitized);
477
605
  const sessionId = crypto.randomUUID();
478
606
  const explorationDir = path.join(ctx.cwd, ".pi", "domain", "exploration");
479
607
  fs.mkdirSync(explorationDir, { recursive: true });
@@ -502,99 +630,237 @@ export default function (pi: ExtensionAPI) {
502
630
 
503
631
  // Write stub exploration.md with business context filled in
504
632
  const explorationMdPath = path.join(ctx.cwd, ".pi", "domain", "exploration.md");
505
- const stubContent = [
506
- "---",
507
- "session_id: " + sessionId,
508
- "created: " + new Date().toISOString().split("T")[0],
509
- 'business_context: "' + sanitized.replace(/"/g, '\\"') + '"',
510
- "status: draft",
511
- "---",
512
- "",
513
- "# Domain Exploration: " + sessionId,
514
- "",
515
- "> **Status:** draft — agent needs to fill in the analysis below.",
516
- "",
517
- "---",
518
- "",
519
- "## Business Context",
520
- "",
521
- sanitized,
522
- "",
523
- "---",
524
- "",
525
- "## Actors & Roles",
526
- "",
527
- "| Actor | Description | Interactions |",
528
- "|-------|-------------|-------------|",
529
- "| | | |",
530
- "",
531
- "---",
532
- "",
533
- "## Functional Requirements",
534
- "",
535
- "| ID | Requirement | Priority | Bounded Context |",
536
- "|----|-------------|----------|----------------|",
537
- "| | | | |",
538
- "",
539
- "---",
540
- "",
541
- "## Non-Functional Requirements",
542
- "",
543
- "| ID | Requirement | Category | Target |",
544
- "|----|-------------|----------|--------|",
545
- "| | | | |",
546
- "",
547
- "---",
548
- "",
549
- "## Assumptions",
550
- "",
551
- "| Assumption | Impact if Wrong | Mitigation |",
552
- "|------------|----------------|-----------|",
553
- "| | | |",
554
- "",
555
- "---",
556
- "",
557
- "## Bounded Contexts",
558
- "",
559
- "| Context | Description | Entities |",
560
- "|---------|-------------|----------|",
561
- "| | | |",
562
- "",
563
- "---",
564
- "",
565
- "## Entities",
566
- "",
567
- "| Entity | Context | Type | Description |",
568
- "|--------|---------|------|-------------|",
569
- "| | | | |",
570
- "",
571
- "---",
572
- "",
573
- "## Domain Events",
574
- "",
575
- "| Event | Context | Description | Triggered By |",
576
- "|-------|---------|-------------|-------------|",
577
- "| | | | |",
578
- "",
579
- "---",
580
- "",
581
- "## Ubiquitous Language",
582
- "",
583
- "| Term | Definition | Bounded Context | Aliases/Synonyms |",
584
- "|------|-----------|----------------|-----------------|",
585
- "| | | | |",
586
- "",
587
- "---",
588
- "",
589
- "## Open Questions",
590
- "",
591
- "",
592
- "---",
593
- "",
594
- "## Aggregate Roots",
595
- "",
596
- "",
597
- ].join("\n");
633
+ const stubContent = isFrontend
634
+ ? [
635
+ "---",
636
+ "session_id: " + sessionId,
637
+ "created: " + new Date().toISOString().split("T")[0],
638
+ 'business_context: "' + sanitized.replace(/"/g, '\\"') + '"',
639
+ "status: draft",
640
+ "---",
641
+ "",
642
+ "# Domain Exploration: " + sessionId,
643
+ "",
644
+ "> **Status:** draft — agent needs to fill in the analysis below.",
645
+ "",
646
+ "---",
647
+ "",
648
+ "## Business Context",
649
+ "",
650
+ sanitized,
651
+ "",
652
+ "---",
653
+ "",
654
+ "## Actors & Roles",
655
+ "",
656
+ "| Actor | Description | Interactions |",
657
+ "|-------|-------------|-------------|",
658
+ "| | | |",
659
+ "",
660
+ "---",
661
+ "",
662
+ "## Functional Requirements",
663
+ "",
664
+ "| ID | Requirement | Priority | Feature |",
665
+ "|----|-------------|----------|--------|",
666
+ "| | | | |",
667
+ "",
668
+ "---",
669
+ "",
670
+ "## Non-Functional Requirements",
671
+ "",
672
+ "| ID | Requirement | Category | Target |",
673
+ "|----|-------------|----------|--------|",
674
+ "| | | | |",
675
+ "",
676
+ "---",
677
+ "",
678
+ "## Assumptions",
679
+ "",
680
+ "| Assumption | Impact if Wrong | Mitigation |",
681
+ "|------------|----------------|-----------|",
682
+ "| | | |",
683
+ "",
684
+ "---",
685
+ "",
686
+ "## Features (Bounded Contexts)",
687
+ "",
688
+ "| Feature | Description | UI Concepts |",
689
+ "|---------|-------------|------------|",
690
+ "| | | |",
691
+ "",
692
+ "---",
693
+ "",
694
+ "## UI Concepts",
695
+ "",
696
+ "| Concept | Feature | Type | Description |",
697
+ "|---------|---------|------|-------------|",
698
+ "| | | | |",
699
+ "",
700
+ "---",
701
+ "",
702
+ "## User Intents",
703
+ "",
704
+ "| Intent | Feature | Description | Triggered By |",
705
+ "|--------|---------|-------------|-------------|",
706
+ "| | | | |",
707
+ "",
708
+ "---",
709
+ "",
710
+ "## Design Principles",
711
+ "",
712
+ "| Principle | Description | Rationale |",
713
+ "|-----------|-------------|----------|",
714
+ "| | | |",
715
+ "",
716
+ "---",
717
+ "",
718
+ "## Navigation Philosophy",
719
+ "",
720
+ "| Aspect | Description |",
721
+ "|--------|-------------|",
722
+ "| Context Preservation | |",
723
+ "| Deep Linking | |",
724
+ "| Multi-Tab Support | |",
725
+ "",
726
+ "---",
727
+ "",
728
+ "## App Shell",
729
+ "",
730
+ "| Component | Description |",
731
+ "|-----------|-------------|",
732
+ "| Navigation | |",
733
+ "| Header | |",
734
+ "| Sidebar | |",
735
+ "| Command Palette | |",
736
+ "| Global Search | |",
737
+ "| Status Bar | |",
738
+ "",
739
+ "---",
740
+ "",
741
+ "## Degradation Strategy",
742
+ "",
743
+ "| Feature | When Unavailable | Degrades To |",
744
+ "|---------|-----------------|-------------|",
745
+ "| | | |",
746
+ "",
747
+ "---",
748
+ "",
749
+ "## Ubiquitous Language",
750
+ "",
751
+ "| Term | Definition | Feature | Aliases/Synonyms |",
752
+ "|------|-----------|---------|-----------------|",
753
+ "| | | | |",
754
+ "",
755
+ "---",
756
+ "",
757
+ "## Design System",
758
+ "",
759
+ "| Aspect | Decision |",
760
+ "|--------|----------|",
761
+ "| Component Library | |",
762
+ "| Theming | |",
763
+ "| Accessibility | |",
764
+ "",
765
+ "---",
766
+ "",
767
+ "## Open Questions",
768
+ "",
769
+ "",
770
+ ].join("\n")
771
+ : [
772
+ "---",
773
+ "session_id: " + sessionId,
774
+ "created: " + new Date().toISOString().split("T")[0],
775
+ 'business_context: "' + sanitized.replace(/"/g, '\\"') + '"',
776
+ "status: draft",
777
+ "---",
778
+ "",
779
+ "# Domain Exploration: " + sessionId,
780
+ "",
781
+ "> **Status:** draft — agent needs to fill in the analysis below.",
782
+ "",
783
+ "---",
784
+ "",
785
+ "## Business Context",
786
+ "",
787
+ sanitized,
788
+ "",
789
+ "---",
790
+ "",
791
+ "## Actors & Roles",
792
+ "",
793
+ "| Actor | Description | Interactions |",
794
+ "|-------|-------------|-------------|",
795
+ "| | | |",
796
+ "",
797
+ "---",
798
+ "",
799
+ "## Functional Requirements",
800
+ "",
801
+ "| ID | Requirement | Priority | Bounded Context |",
802
+ "|----|-------------|----------|----------------|",
803
+ "| | | | |",
804
+ "",
805
+ "---",
806
+ "",
807
+ "## Non-Functional Requirements",
808
+ "",
809
+ "| ID | Requirement | Category | Target |",
810
+ "|----|-------------|----------|--------|",
811
+ "| | | | |",
812
+ "",
813
+ "---",
814
+ "",
815
+ "## Assumptions",
816
+ "",
817
+ "| Assumption | Impact if Wrong | Mitigation |",
818
+ "|------------|----------------|-----------|",
819
+ "| | | |",
820
+ "",
821
+ "---",
822
+ "",
823
+ "## Bounded Contexts",
824
+ "",
825
+ "| Context | Description | Entities |",
826
+ "|---------|-------------|----------|",
827
+ "| | | |",
828
+ "",
829
+ "---",
830
+ "",
831
+ "## Entities",
832
+ "",
833
+ "| Entity | Context | Type | Description |",
834
+ "|--------|---------|------|-------------|",
835
+ "| | | | |",
836
+ "",
837
+ "---",
838
+ "",
839
+ "## Domain Events",
840
+ "",
841
+ "| Event | Context | Description | Triggered By |",
842
+ "|-------|---------|-------------|-------------|",
843
+ "| | | | |",
844
+ "",
845
+ "---",
846
+ "",
847
+ "## Ubiquitous Language",
848
+ "",
849
+ "| Term | Definition | Bounded Context | Aliases/Synonyms |",
850
+ "|------|-----------|----------------|-----------------|",
851
+ "| | | | |",
852
+ "",
853
+ "---",
854
+ "",
855
+ "## Open Questions",
856
+ "",
857
+ "",
858
+ "---",
859
+ "",
860
+ "## Aggregate Roots",
861
+ "",
862
+ "",
863
+ ].join("\n");
598
864
  fs.writeFileSync(explorationMdPath + ".tmp", stubContent, "utf-8");
599
865
  fs.renameSync(explorationMdPath + ".tmp", explorationMdPath);
600
866
 
@@ -626,12 +892,18 @@ export default function (pi: ExtensionAPI) {
626
892
  // Using sendMessage with triggerTurn=true causes the agent to process
627
893
  // this as a new conversation turn, not as a command response.
628
894
  const analysisPrompt = [
629
- "I need you to analyze the following business domain using Domain-Driven Design.",
895
+ "I need you to analyze the following business domain.",
630
896
  "I have created stub files in .pi/domain/exploration.md and .pi/domain/ubiquitous-language.md.",
631
897
  "",
898
+ "IMPORTANT: Read .pi/domain/exploration.md FIRST. It contains empty tables.",
899
+ "FILL IN the existing tables exactly as structured. Do NOT change the section names or table columns.",
900
+ "Do NOT add new sections that aren't in the stub. Do NOT use 'Domain Events' or 'Aggregate Roots' — those are backend concepts.",
901
+ "",
632
902
  "Your task:",
633
903
  "1. READ .pi/domain/exploration.md — it has the business context and empty tables",
634
- "2. ANALYZE the domain: actors, FR/NFR, assumptions, bounded contexts, entities, events , glossary",
904
+ (isFrontend
905
+ ? "2. ANALYZE the domain: actors, FR/NFR, assumptions, features (bounded contexts), UI concepts, user intents, glossary"
906
+ : "2. ANALYZE the domain: actors, FR/NFR, assumptions, bounded contexts, entities, events, glossary"),
635
907
  "3. FILL IN all empty tables in .pi/domain/exploration.md with your analysis",
636
908
  "4. UPDATE .pi/domain/ubiquitous-language.md with the glossary terms",
637
909
  "",
@@ -639,18 +911,40 @@ export default function (pi: ExtensionAPI) {
639
911
  sanitized,
640
912
  "",
641
913
  "Use this JSON schema as a reference for structuring your analysis:",
642
- '```json',
643
- "{",
644
- ' "actors": [{ "name": "", "description": "", "interactions": "" }],',
645
- ' "functionalRequirements": [{ "id": "FR-001", "requirement": "", "priority": "critical|high|medium|low", "boundedContext": "" }],',
646
- ' "nonFunctionalRequirements": [{ "id": "NFR-001", "requirement": "", "category": "performance|security|scalability|availability|maintainability", "target": "" }],',
647
- ' "assumptions": [{ "assumption": "", "impactIfWrong": "", "mitigation": "" }],',
648
- ' "boundedContexts": [{ "name": "", "description": "", "entities": [""] }],',
649
- ' "entities": [{ "name": "", "context": "", "type": "entity|value-object|aggregate-root", "description": "" }],',
650
- ' "domainEvents": [{ "name": "", "context": "", "description": "", "triggeredBy": "" }],',
651
- ' "ubiquitousLanguage": [{ "term": "", "definition": "", "boundedContext": "", "aliases": [""], "examples": "" }]',
652
- "}",
653
- '```',
914
+ isFrontend
915
+ ? [
916
+ '\`\`\`json',
917
+ "{",
918
+ ' "actors": [{ "name": "", "description": "", "interactions": "" }],',
919
+ ' "functionalRequirements": [{ "id": "FR-001", "requirement": "", "priority": "critical|high|medium|low", "boundedContext": "" }],',
920
+ ' "nonFunctionalRequirements": [{ "id": "NFR-001", "requirement": "", "category": "performance|accessibility|usability|security|maintainability", "target": "" }],',
921
+ ' "assumptions": [{ "assumption": "", "impactIfWrong": "", "mitigation": "" }],',
922
+ ' "boundedContexts": [{ "name": "", "description": "", "entities": [""] }],',
923
+ ' "entities": [{ "name": "", "context": "", "type": "ui-concept|user-intent|design-token|app-shell|value-object", "description": "" }],',
924
+ ' "userIntents": [{ "name": "", "context": "", "description": "", "triggeredBy": "" }],',
925
+ ' "designPrinciples": [{ "principle": "", "description": "", "rationale": "" }],',
926
+ ' "navigationPhilosophy": { "contextPreservation": "", "deepLinking": "", "multiTab": "" },',
927
+ ' "appShell": { "navigation": "", "header": "", "sidebar": "", "commandPalette": "", "globalSearch": "" },',
928
+ ' "degradationStrategy": [{ "feature": "", "whenUnavailable": "", "degradesTo": "" }],',
929
+ ' "ubiquitousLanguage": [{ "term": "", "definition": "", "boundedContext": "", "aliases": [""], "examples": "" }],',
930
+ ' "designSystem": { "componentLibrary": "", "theming": "", "accessibility": "" }',
931
+ "}",
932
+ '\`\`\`',
933
+ ].join("\n")
934
+ : [
935
+ '\`\`\`json',
936
+ "{",
937
+ ' "actors": [{ "name": "", "description": "", "interactions": "" }],',
938
+ ' "functionalRequirements": [{ "id": "FR-001", "requirement": "", "priority": "critical|high|medium|low", "boundedContext": "" }],',
939
+ ' "nonFunctionalRequirements": [{ "id": "NFR-001", "requirement": "", "category": "performance|security|scalability|availability|maintainability", "target": "" }],',
940
+ ' "assumptions": [{ "assumption": "", "impactIfWrong": "", "mitigation": "" }],',
941
+ ' "boundedContexts": [{ "name": "", "description": "", "entities": [""] }],',
942
+ ' "entities": [{ "name": "", "context": "", "type": "entity|value-object|aggregate-root", "description": "" }],',
943
+ ' "domainEvents": [{ "name": "", "context": "", "description": "", "triggeredBy": "" }],',
944
+ ' "ubiquitousLanguage": [{ "term": "", "definition": "", "boundedContext": "", "aliases": [""], "examples": "" }]',
945
+ "}",
946
+ '\`\`\`',
947
+ ].join("\n"),
654
948
  ].join("\n");
655
949
 
656
950
  try {
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-07-03T07:45:52Z",
2
+ "timestamp": "2026-07-03T11:03:52Z",
3
3
  "mode": "all",
4
4
  "stages_run": [],
5
5
  "summary": {
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: design-system-codegen
3
+ description: Minimal skill for design system architecture with DDD + adapter pattern. References full patterns on demand — never loads inline. Use when building design system components, tokens, or CSS integration.
4
+ model: inherit
5
+ tools: [Read, Grep]
6
+ ---
7
+
8
+ # Design System Code Generation — DDD + Adapter Pattern
9
+
10
+ > Full reference: `.pi/skills/design-system-enterprise-codegen.md`
11
+
12
+ ## Quick Reference
13
+
14
+ | When you need... | Read this section |
15
+ |-----------------|-------------------|
16
+ | Structure overview | Section 1 — DDD module layout, framework agnostic |
17
+ | Design tokens | Section 2 — ColorToken, SpacingToken, TypeScale as domain values |
18
+ | Variant engine | Section 3 — defineVariants(), type-safe component props |
19
+ | CSS adapter (Tailwind) | Section 4 — Tailwind class generation from tokens |
20
+ | CSS adapter (CSS Modules) | Section 4 — CSS variable generation |
21
+ | CSS adapter (MUI/Material) | Section 4 — MUI theme mapping |
22
+ | Component pattern | Section 5 — Button component using application layer |
23
+ | Theming (dark mode) | Section 6 — ThemeService, data-theme attribute |
24
+ | Testing | Section 7 — token tests, variant engine tests |
25
+ | Choosing your stack | Section 8 — Tailwind vs CSS Modules vs MUI by use case |
26
+
27
+ ## DDD Layer Contract for Design Systems
28
+
29
+ | Layer | Purpose | Example | CSS framework aware? |
30
+ |-------|---------|---------|---------------------|
31
+ | `domain/tokens/` | Typed design tokens | `ColorToken.PRIMARY` | No |
32
+ | `application/` | Variant resolution, theming | `defineVariants()` | No |
33
+ | `infrastructure/` | CSS adapter | `tailwind-adapter.ts` | **Yes** — this is the only layer |
34
+ | `interfaces/` | Rendered components | `button.tsx` | No (uses application layer) |
35
+
36
+ ## Rules
37
+ - NEVER read full reference — read specific sections
38
+ - Design tokens are pure TypeScript — zero CSS, zero framework imports
39
+ - Components import from `application/`, never from `infrastructure/` directly
40
+ - The adapter is the **only file** that changes when you switch CSS frameworks
41
+ - Pick one adapter per project — never mix Tailwind and MUI in the same component