sdg-agents 1.0.5
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/LICENSE +15 -0
- package/README.md +161 -0
- package/package.json +88 -0
- package/src/assets/dev-guides/agent-deep-flow.md +139 -0
- package/src/assets/dev-guides/prompt-tracks/00-lite-mode/01-project-scope-and-mvp.md +45 -0
- package/src/assets/dev-guides/prompt-tracks/00-lite-mode/02-stack-and-data-model.md +56 -0
- package/src/assets/dev-guides/prompt-tracks/00-lite-mode/03-external-integrations.md +44 -0
- package/src/assets/dev-guides/prompt-tracks/00-lite-mode/04-launch-checklist.md +26 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/01-project-vision.md +77 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/02-problem-definition.md +63 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/03-success-metrics.md +48 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/05-engineering-culture-and-silos.md +41 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/06-foundation-approval.md +57 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/01-tech-stack.md +62 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/02-local-environment.md +50 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/03-version-control-and-tracking.md +65 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/04-hello-world-validation.md +37 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/05-setup-approval.md +61 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/01-folder-structure.md +49 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/02-design-patterns.md +59 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/03-apis-and-communication.md +55 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/04-security-and-access.md +63 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/05-security-audit.md +64 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/06-design-system-ux.md +72 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/07-ai-strategy.md +72 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/08-observability.md +65 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/09-technical-documentation.md +64 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/10-infrastructure-and-costs.md +40 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/11-data-privacy-compliance.md +41 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/12-performance-and-scale.md +46 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/13-disaster-recovery.md +39 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/14-architecture-approval.md +81 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/01-ci-cd-pipeline.md +49 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/02-quality-standards.md +46 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/03-delivery-approval.md +58 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/00-feature-template.md +30 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/01-context-and-scope.md +46 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/02-business-rules.md +39 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/03-architecture-and-design.md +50 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/04-testing-strategy.md +48 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/05-implementation-plan.md +45 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/06-feature-approval.md +46 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/01-rfcs-and-changes.md +63 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/02-incident-postmortems.md +64 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/03-adr-template.md +66 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/00-foundation/01-legacy-vision.md +73 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/00-foundation/02-foundation-approval.md +53 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/01-tech-debt-inventory.md +55 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/02-security-audit.md +63 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/03-regression-baseline.md +49 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/04-analysis-approval.md +65 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/01-modernization-approach.md +60 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/02-versioning-and-coexistence.md +57 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/03-new-demands-triage.md +41 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/04-strategy-approval.md +56 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/03-refactor/01-cleanup-backlog.md +45 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/03-refactor/02-refactor-approval.md +53 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/01-migration-roadmap.md +47 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/02-data-sync-strategy.md +56 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/03-migration-approval.md +55 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/05-sunset/01-decommission-plan.md +47 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/05-sunset/02-sunset-approval.md +60 -0
- package/src/assets/dev-guides/prompt-tracks/README.md +144 -0
- package/src/assets/dev-guides/software-development-lifecycle-sdlc.md +147 -0
- package/src/assets/dev-guides/spec-driven-dev-guide.md +81 -0
- package/src/assets/dev-guides/ui-prompt-guide.md +181 -0
- package/src/assets/img/sdg-agents-icon-dark.svg +55 -0
- package/src/assets/img/sdg-agents-icon-light.svg +55 -0
- package/src/assets/img/sdg-agents-menu-v1.png +0 -0
- package/src/assets/img/sdg-icon.svg +110 -0
- package/src/assets/instructions/commands/sdg-docs.md +69 -0
- package/src/assets/instructions/commands/sdg-feat.md +45 -0
- package/src/assets/instructions/commands/sdg-fix.md +41 -0
- package/src/assets/instructions/commands/sdg-land.md +128 -0
- package/src/assets/instructions/competencies/backend.md +353 -0
- package/src/assets/instructions/competencies/frontend.md +439 -0
- package/src/assets/instructions/core/agent-roles.md +104 -0
- package/src/assets/instructions/core/api-design.md +65 -0
- package/src/assets/instructions/core/ci-cd.md +144 -0
- package/src/assets/instructions/core/cloud.md +63 -0
- package/src/assets/instructions/core/code-style.md +144 -0
- package/src/assets/instructions/core/containers.md +115 -0
- package/src/assets/instructions/core/data-access.md +119 -0
- package/src/assets/instructions/core/engineering-standards.md +502 -0
- package/src/assets/instructions/core/naming.md +136 -0
- package/src/assets/instructions/core/observability.md +73 -0
- package/src/assets/instructions/core/security-pipeline.md +209 -0
- package/src/assets/instructions/core/security.md +45 -0
- package/src/assets/instructions/core/sql-style.md +138 -0
- package/src/assets/instructions/core/staff-dna.md +72 -0
- package/src/assets/instructions/core/testing-principles.md +212 -0
- package/src/assets/instructions/core/ui/architecture.md +171 -0
- package/src/assets/instructions/core/ui/design-thinking.md +319 -0
- package/src/assets/instructions/core/ui/presets.md +200 -0
- package/src/assets/instructions/core/ui/standards.md +144 -0
- package/src/assets/instructions/core/writing-soul.md +82 -0
- package/src/assets/instructions/flavors/legacy/principles.md +64 -0
- package/src/assets/instructions/flavors/lite/principles.md +39 -0
- package/src/assets/instructions/flavors/mvc/principles.md +124 -0
- package/src/assets/instructions/flavors/vertical-slice/principles.md +178 -0
- package/src/assets/instructions/idioms/csharp/patterns.md +367 -0
- package/src/assets/instructions/idioms/flutter/patterns.md +97 -0
- package/src/assets/instructions/idioms/go/patterns.md +193 -0
- package/src/assets/instructions/idioms/java/patterns.md +233 -0
- package/src/assets/instructions/idioms/javascript/patterns.md +223 -0
- package/src/assets/instructions/idioms/kotlin/patterns.md +94 -0
- package/src/assets/instructions/idioms/python/patterns.md +185 -0
- package/src/assets/instructions/idioms/rust/patterns.md +189 -0
- package/src/assets/instructions/idioms/scripts/patterns.md +81 -0
- package/src/assets/instructions/idioms/sql/patterns.md +109 -0
- package/src/assets/instructions/idioms/swift/patterns.md +97 -0
- package/src/assets/instructions/idioms/typescript/patterns.md +304 -0
- package/src/assets/instructions/idioms/vbnet/patterns.md +96 -0
- package/src/assets/instructions/idioms/vbnet-legacy/patterns.md +104 -0
- package/src/assets/instructions/templates/workflow.md +244 -0
- package/src/assets/instructions/workflows/governance.md +162 -0
- package/src/engine/bin/add-idiom.mjs +186 -0
- package/src/engine/bin/index.mjs +226 -0
- package/src/engine/config/stack-display.mjs +75 -0
- package/src/engine/config/stack-versions.mjs +76 -0
- package/src/engine/lib/cli-parser.mjs +80 -0
- package/src/engine/lib/display-utils.mjs +20 -0
- package/src/engine/lib/fs-utils.mjs +99 -0
- package/src/engine/lib/instruction-assembler.mjs +487 -0
- package/src/engine/lib/manifest-utils.mjs +128 -0
- package/src/engine/lib/prompt-utils.mjs +137 -0
- package/src/engine/lib/result-utils.mjs +14 -0
- package/src/engine/lib/ruleset-injector.mjs +183 -0
- package/src/engine/lib/ui-utils.mjs +216 -0
- package/src/engine/lib/wizard.mjs +472 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
# Frontend Execution System
|
|
2
|
+
|
|
3
|
+
<ruleset name="FrontendSkill">
|
|
4
|
+
|
|
5
|
+
> [!IMPORTANT]
|
|
6
|
+
> **Do not create UI. Execute contracts.**
|
|
7
|
+
> The agent's role is to follow structural contracts defined in the spec, then apply the design system.
|
|
8
|
+
> Never invent structure, spacing, or visual treatment independently.
|
|
9
|
+
> **Start every UI task with Phase 0 (Design Thinking) from [design-thinking.md](../core/ui/design-thinking.md).** Code only begins after the Design Contract is declared.
|
|
10
|
+
> For code structure patterns and the L1-L4 spacing hierarchy, see [architecture.md](../core/ui/architecture.md).
|
|
11
|
+
> For visual aesthetic presets (Glass, Bento, etc.), see [presets.md](../core/ui/presets.md).
|
|
12
|
+
>
|
|
13
|
+
> **NarrativeCascade applies to all TypeScript logic files** — hooks, services, mappers, and utils follow the same rule: entry point first, each function either orchestrates or implements, no explanatory comments. UI components are exempt from ordering only when JSX structure demands it; all non-JSX logic inside them is not.
|
|
14
|
+
|
|
15
|
+
## Rule: Contract-Based Execution Flow
|
|
16
|
+
|
|
17
|
+
<rule name="ContractExecution">
|
|
18
|
+
|
|
19
|
+
Every UI task follows a mandatory 5-phase sequence:
|
|
20
|
+
|
|
21
|
+
0. **DESIGN THINKING** — declare the Design Contract (palette, preset, tone, differentiator, typography). See [design-thinking.md](../core/ui/design-thinking.md). Cannot be skipped.
|
|
22
|
+
1. **WIREFRAME** — structure only (`div`, `flex`, `grid`). No styles, no colors.
|
|
23
|
+
2. **CONTRACTS** — enforce the section structure defined in the spec.
|
|
24
|
+
3. **DESIGN SYSTEM** — apply spacing scale, color layers, typography.
|
|
25
|
+
4. **SELF-CHECK** — validate and auto-fix before returning output.
|
|
26
|
+
|
|
27
|
+
For new pages, always derive from an existing page via **clone-and-modify**. Never build from scratch — keep the header, footer, and layout; replace only the sections that differ. If no existing page is available, start from the closest `section.*` template defined in the Section Contract Templates rule.
|
|
28
|
+
</rule>
|
|
29
|
+
|
|
30
|
+
## Rule: Color Semantic Layers
|
|
31
|
+
|
|
32
|
+
<rule name="ColorLayers">
|
|
33
|
+
|
|
34
|
+
### Layer Mapping (shadcn tokens — always semantic, never raw)
|
|
35
|
+
|
|
36
|
+
Use shadcn semantic tokens for structural color. Never use raw colors (`bg-white`, `bg-black`, hardcoded hex, raw `oklch(...)` inline in JSX).
|
|
37
|
+
|
|
38
|
+
| Layer | Role | Light (shadcn) | Dark |
|
|
39
|
+
| :--------- | :-------------------------- | :-------------- | :-------------- |
|
|
40
|
+
| `base` | Page background — root only | `bg-background` | `bg-background` |
|
|
41
|
+
| `surface` | Section backgrounds | `bg-muted` | `bg-muted/40` |
|
|
42
|
+
| `elevated` | Cards and panels | `bg-card` | `bg-card` |
|
|
43
|
+
| `overlay` | Modals and drawers | `bg-popover` | `bg-popover` |
|
|
44
|
+
|
|
45
|
+
Nesting rules:
|
|
46
|
+
|
|
47
|
+
- `elevated` inside `elevated` is forbidden
|
|
48
|
+
- `surface` inside `surface` is forbidden
|
|
49
|
+
|
|
50
|
+
Text: `text-foreground` (primary content), `text-muted-foreground` (support/captions).
|
|
51
|
+
Never place `text-muted-foreground` on a `surface` or `elevated` background with insufficient contrast.
|
|
52
|
+
|
|
53
|
+
### Brand Palette Layer (`--color-primary-*` — complementary, not a replacement)
|
|
54
|
+
|
|
55
|
+
Shadcn owns the structural tokens. The brand palette is a **separate OKLCH layer** for interactive elements (buttons, links, highlights, badges) and accent surfaces.
|
|
56
|
+
|
|
57
|
+
```css
|
|
58
|
+
/* globals.css — brand layer extends shadcn, does not replace it */
|
|
59
|
+
@theme {
|
|
60
|
+
--color-primary-400: oklch(68% 0.13 250); /* dark-mode hover */
|
|
61
|
+
--color-primary-500: oklch(58% 0.15 250); /* action color */
|
|
62
|
+
--color-primary-600: oklch(48% 0.14 250); /* light-mode hover */
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<!-- Correct: shadcn token for layout, brand token for action -->
|
|
68
|
+
<section class="bg-muted">
|
|
69
|
+
<button class="bg-primary-500 hover:bg-primary-600 dark:hover:bg-primary-400">Ação</button>
|
|
70
|
+
</section>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
> The Hue, Chroma, and scale progression for `--color-primary-*` are defined in [design-thinking.md](../core/ui/design-thinking.md). Generate tokens there, consume them here.
|
|
74
|
+
> </rule>
|
|
75
|
+
|
|
76
|
+
## Rule: Spacing & Typography Scale
|
|
77
|
+
|
|
78
|
+
<rule name="SpacingTypography">
|
|
79
|
+
|
|
80
|
+
**Spacing scale** — use only these values: `gap-1` (4px), `gap-2` (8px), `gap-3` (12px), `gap-4` (16px), `gap-6` (24px), `gap-8` (32px).
|
|
81
|
+
|
|
82
|
+
- Prefer `gap` over `margin` for layout composition
|
|
83
|
+
- Arbitrary values (`w-[123px]`, `mt-[17px]`) are forbidden
|
|
84
|
+
- Use the L1-L4 hierarchy from [architecture.md](../core/ui/architecture.md) to pick the right level per context
|
|
85
|
+
|
|
86
|
+
**Typography** — default scale:
|
|
87
|
+
|
|
88
|
+
| Token | Classes |
|
|
89
|
+
| :-------- | :------------------------------ |
|
|
90
|
+
| `h1` | `text-2xl font-semibold` |
|
|
91
|
+
| `h2` | `text-xl font-semibold` |
|
|
92
|
+
| `h3` | `text-lg font-medium` |
|
|
93
|
+
| `body` | `text-sm font-normal` |
|
|
94
|
+
| `caption` | `text-xs text-muted-foreground` |
|
|
95
|
+
|
|
96
|
+
Max 2 font-weights per section. Never use `font-bold` across an entire section.
|
|
97
|
+
|
|
98
|
+
**Radius** — use only: `rounded-sm` (6px), `rounded-md` (10px), `rounded-lg` (16px). No arbitrary radius.
|
|
99
|
+
</rule>
|
|
100
|
+
|
|
101
|
+
## Rule: Section Contract Templates
|
|
102
|
+
|
|
103
|
+
<rule name="SectionContracts">
|
|
104
|
+
|
|
105
|
+
When the spec defines a section, execute its contract exactly. The spec's definition always takes precedence over these defaults.
|
|
106
|
+
|
|
107
|
+
**section.hero**
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
section(surface) > container > grid(2-col desktop / 1-col mobile)
|
|
111
|
+
├── left: text content
|
|
112
|
+
└── right: image or visual
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
- `gap-6`, max 2 CTAs, clear heading hierarchy.
|
|
116
|
+
|
|
117
|
+
**section.cards**
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
section(surface) > container > grid
|
|
121
|
+
└── card(elevated)[]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- `gap-6`, consistent card size, no nested cards.
|
|
125
|
+
|
|
126
|
+
**section.form**
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
section(surface) > container(max-w-md) > form
|
|
130
|
+
├── inputs
|
|
131
|
+
└── actions
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
- Vertical layout, `gap-4`.
|
|
135
|
+
|
|
136
|
+
**section.carousel**
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
section(surface) > container > horizontal-scroll
|
|
140
|
+
└── item[] (consistent width)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- `overflow-hidden`, consistent item width.
|
|
144
|
+
|
|
145
|
+
**page.simple** (docs, privacy, terms)
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
header > content(max-w-prose) > footer
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- Single column, readability focus. No hero, no cards.
|
|
152
|
+
</rule>
|
|
153
|
+
|
|
154
|
+
## Rule: Component Discipline
|
|
155
|
+
|
|
156
|
+
<rule name="ComponentDiscipline">
|
|
157
|
+
|
|
158
|
+
- Prefer shadcn/ui components as the base layer
|
|
159
|
+
- Use Tailwind for layout only (`flex`, `grid`, `gap`, sizing)
|
|
160
|
+
- Never override base component styles directly
|
|
161
|
+
- Wrap base components when project-specific defaults are needed:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
// Correct: define project-level wrapper, never touch the base
|
|
165
|
+
export const AppButton = ({ children, ...props }) => (
|
|
166
|
+
<Button className="h-10 px-4 rounded-md" {...props}>
|
|
167
|
+
{children}
|
|
168
|
+
</Button>
|
|
169
|
+
);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Use the project's wrappers (`AppButton`, etc.) in pages — not base components directly.
|
|
173
|
+
|
|
174
|
+
**Forbidden (global)**:
|
|
175
|
+
|
|
176
|
+
- Arbitrary values (`w-[123px]`)
|
|
177
|
+
- `margin` for layout composition
|
|
178
|
+
- Raw colors
|
|
179
|
+
- `border` + `shadow` + colored `bg` all together (visual pollution)
|
|
180
|
+
- Nested elevated cards with identical styling
|
|
181
|
+
</rule>
|
|
182
|
+
|
|
183
|
+
## Rule: HTTP Integration (API Client Contract)
|
|
184
|
+
|
|
185
|
+
<rule name="HttpIntegration">
|
|
186
|
+
|
|
187
|
+
> **UI never calls `fetch` directly. All HTTP flows through a single `apiClient` that returns `Result<T>`.**
|
|
188
|
+
> **UI is declarative — it displays state. It does not resolve problems.**
|
|
189
|
+
|
|
190
|
+
#### Architecture
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
Component (render + action)
|
|
194
|
+
↓
|
|
195
|
+
useApi hook (state: data / error / isLoading) ← hooks/useApi.ts
|
|
196
|
+
↓
|
|
197
|
+
Service (fetch + transform → delivers View)
|
|
198
|
+
↓
|
|
199
|
+
apiClient (infra — only file that imports fetch)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Error Boundaries vs `useApi` error state** — complementary, not alternatives:
|
|
203
|
+
|
|
204
|
+
| Mechanism | Catches | When to use |
|
|
205
|
+
| :------------------- | :------------------------------------------ | :----------------------------------------- |
|
|
206
|
+
| `useApi` error state | Expected API failures (404, 422, network) | Always — standard flow |
|
|
207
|
+
| Error Boundary | Unexpected render/runtime exceptions thrown | Wrap page-level components as a safety net |
|
|
208
|
+
|
|
209
|
+
`useApi` handles expected failures gracefully (shows error UI). Error Boundaries catch the unexpected (prevent a blank screen). Use both layers: `useApi` for the happy/failure path, Error Boundary as the outer safety net.
|
|
210
|
+
|
|
211
|
+
#### Core (always)
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
// 1. apiClient — production-grade: 204 safe, json-safe, single error shape
|
|
215
|
+
async function apiClient<T>(url: string, options?: RequestInit): Promise<Result<T>> {
|
|
216
|
+
try {
|
|
217
|
+
const response = await fetch(url, options);
|
|
218
|
+
|
|
219
|
+
const hasContent = response.status !== 204;
|
|
220
|
+
|
|
221
|
+
let body = null;
|
|
222
|
+
|
|
223
|
+
if (hasContent) {
|
|
224
|
+
try {
|
|
225
|
+
body = await response.json();
|
|
226
|
+
} catch {
|
|
227
|
+
body = null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const isError = !response.ok;
|
|
232
|
+
|
|
233
|
+
if (isError) {
|
|
234
|
+
const message = body?.error?.code || body?.error?.message || 'REQUEST_ERROR';
|
|
235
|
+
const result = fail<T>(message);
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const data = body?.data ?? null;
|
|
240
|
+
const result = ok<T>(data);
|
|
241
|
+
return result;
|
|
242
|
+
} catch {
|
|
243
|
+
const result = fail<T>('NETWORK_ERROR');
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 2. Service — fetches and transforms; UI never sees raw domain types
|
|
249
|
+
async function getOrderView(id: string): Promise<Result<OrderView>> {
|
|
250
|
+
const result = await apiClient<Order>(`/orders/${id}`, { method: 'GET' });
|
|
251
|
+
|
|
252
|
+
if (result.isFailure) {
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const view = toOrderView(result.data!);
|
|
257
|
+
const finalResult = ok(view);
|
|
258
|
+
return finalResult;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// 3. View function — pure transformation, not a class or hook
|
|
262
|
+
function toOrderView(data: Order): OrderView {
|
|
263
|
+
const view = {
|
|
264
|
+
id: data.id,
|
|
265
|
+
customerName: data.customer.name,
|
|
266
|
+
totalLabel: `$${data.total}`,
|
|
267
|
+
};
|
|
268
|
+
return view;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 4. useApi — standard state hook, lives in hooks/useApi.ts, reused across all components
|
|
272
|
+
function useApi() {
|
|
273
|
+
const [data, setData] = React.useState(null);
|
|
274
|
+
const [error, setError] = React.useState(null);
|
|
275
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
276
|
+
|
|
277
|
+
async function execute(promiseFn: () => Promise<Result<unknown>>) {
|
|
278
|
+
setIsLoading(true);
|
|
279
|
+
setError(null);
|
|
280
|
+
|
|
281
|
+
const result = await promiseFn();
|
|
282
|
+
|
|
283
|
+
if (result.isFailure) {
|
|
284
|
+
setError(result.error);
|
|
285
|
+
setIsLoading(false);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
setData(result.data);
|
|
290
|
+
setIsLoading(false);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const state = { data, error, isLoading, execute };
|
|
294
|
+
return state;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// 5. Component — render + named action only
|
|
298
|
+
function OrderPage({ id }: { id: string }) {
|
|
299
|
+
const { data, error, isLoading, execute } = useApi();
|
|
300
|
+
|
|
301
|
+
React.useEffect(() => {
|
|
302
|
+
loadOrder();
|
|
303
|
+
}, [id]);
|
|
304
|
+
|
|
305
|
+
async function loadOrder() {
|
|
306
|
+
await execute(() => getOrderView(id));
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (isLoading) {
|
|
310
|
+
const view = <div>Loading...</div>;
|
|
311
|
+
return view;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (error) {
|
|
315
|
+
const view = <div>Error: {error}</div>;
|
|
316
|
+
return view;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (!data) {
|
|
320
|
+
const view = null;
|
|
321
|
+
return view;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const view = (
|
|
325
|
+
<div>
|
|
326
|
+
<h1>Order #{data.id}</h1>
|
|
327
|
+
<p>{data.customerName}</p>
|
|
328
|
+
<p>{data.totalLabel}</p>
|
|
329
|
+
</div>
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
return view;
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
#### Naming convention (component functions)
|
|
337
|
+
|
|
338
|
+
| Prefix | Use |
|
|
339
|
+
| :--------- | :------------------------------------ |
|
|
340
|
+
| `loadX` | Initial data fetch on mount |
|
|
341
|
+
| `refreshX` | Reload triggered by user action |
|
|
342
|
+
| `submitX` | Form submission or mutation |
|
|
343
|
+
| `handleX` | UI event handler (click, change, etc) |
|
|
344
|
+
|
|
345
|
+
#### Optional — add only when the pain is real
|
|
346
|
+
|
|
347
|
+
```ts
|
|
348
|
+
// Error mapping — only when the app has user-facing messages at scale
|
|
349
|
+
const ErrorMap: Record<string, string> = {
|
|
350
|
+
ORDER_EMPTY: 'Pedido sem itens',
|
|
351
|
+
NETWORK_ERROR: 'Erro de conexão',
|
|
352
|
+
};
|
|
353
|
+
const message = ErrorMap[error] ?? 'Erro inesperado';
|
|
354
|
+
|
|
355
|
+
// Cache as service decorator — zero impact on the rest of the architecture
|
|
356
|
+
const cache = new Map();
|
|
357
|
+
async function withCache<T>(key: string, fn: () => Promise<Result<T>>): Promise<Result<T>> {
|
|
358
|
+
const cached = cache.get(key);
|
|
359
|
+
if (cached) {
|
|
360
|
+
const result = ok<T>(cached);
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
const result = await fn();
|
|
364
|
+
if (result.isSuccess) cache.set(key, result.data);
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
// Usage: withCache(`order:${id}`, () => getOrderView(id))
|
|
368
|
+
|
|
369
|
+
// Normalization — only when backend shape is unreliable
|
|
370
|
+
function normalizeOrder(data: unknown): Order {
|
|
371
|
+
const order = { id: (data as any).id, total: (data as any).total ?? 0 };
|
|
372
|
+
return order;
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### Rules of gold
|
|
377
|
+
|
|
378
|
+
- `apiClient` is the only file that imports `fetch`
|
|
379
|
+
- `async/await` always — never `.then()`
|
|
380
|
+
- No `try/catch` in UI — `apiClient` owns all error handling
|
|
381
|
+
- `Result` stops at the service — never stored in component state
|
|
382
|
+
- Service delivers the View type — UI never transforms raw domain data
|
|
383
|
+
- View function = pure function (`toOrderView`) — not a class, hook, or layer
|
|
384
|
+
- State = three separate fields: `data / error / isLoading` — never one object
|
|
385
|
+
- `useApi` lives in `hooks/useApi.ts` — never duplicated per component
|
|
386
|
+
- `useEffect` triggers a named action only — no logic inline
|
|
387
|
+
- Every JSX return goes through a named variable (`const view = ...`) — Explaining Returns applies to components
|
|
388
|
+
- `result.data!` (non-null assertion after `isFailure` guard) is the accepted tradeoff — `Result<T>` types `data` as `T | undefined`; after the guard the value is guaranteed present but TypeScript cannot infer it without a type predicate
|
|
389
|
+
|
|
390
|
+
#### Anti-patterns
|
|
391
|
+
|
|
392
|
+
| ❌ | Why |
|
|
393
|
+
| ------------------------------------------------------- | ------------------------------------------------- |
|
|
394
|
+
| `fetch` in a component | Bypasses error handling and coupling contract |
|
|
395
|
+
| `useState<Result<T>>` | Result is domain flow, not UI state |
|
|
396
|
+
| Logic inside `useEffect` (`execute(async () => {...})`) | Breaks Stepdown and makes breakpoints impossible |
|
|
397
|
+
| Transformation inside the component | Service owns the View contract |
|
|
398
|
+
| **Heavy ViewModel** (class, heavy hook) | Over-engineering — a pure function is enough |
|
|
399
|
+
| State with extra fields (`flags`, `meta`, `status`) | **Multiple sources of truth** (data dump) |
|
|
400
|
+
| `return <div>...</div>` directly | Explaining Returns — always assign before return |
|
|
401
|
+
| **Redundant Action** (CRUD / NONE) | meta.action is for server-driven UI state changes |
|
|
402
|
+
| `loading` bare noun in state | Boolean Prefixes — use `isLoading` |
|
|
403
|
+
| **Structure Duplication** across layers | Keep DTOs proportional to their purpose |
|
|
404
|
+
| **Overengineering** (premature abstraction) | Rule of Three — wait for real pain |
|
|
405
|
+
|
|
406
|
+
</rule>
|
|
407
|
+
|
|
408
|
+
## Rule: Self-Check (Mandatory Before Returning)
|
|
409
|
+
|
|
410
|
+
<rule name="SelfCheck">
|
|
411
|
+
|
|
412
|
+
Before returning any UI output, verify and auto-fix:
|
|
413
|
+
|
|
414
|
+
**Visual**
|
|
415
|
+
|
|
416
|
+
- Spacing value outside the allowed scale? → **FIX**
|
|
417
|
+
- Wrong color layer nesting (`elevated` inside `elevated`)? → **FIX**
|
|
418
|
+
- Base component used directly instead of project wrapper? → **FIX**
|
|
419
|
+
- Contrast issue (`muted` text on `muted` background)? → **FIX**
|
|
420
|
+
- Section structure doesn't match the spec's contract? → **FIX**
|
|
421
|
+
- Visual pollution (border + shadow + bg together)? → **SIMPLIFY**
|
|
422
|
+
|
|
423
|
+
**Color & Theme (OKLCH)**
|
|
424
|
+
|
|
425
|
+
- Raw color inline in JSX (`bg-[oklch(...)]`, `bg-white`, `bg-black`)? → **FIX** (use semantic or brand token)
|
|
426
|
+
- Dark mode hover goes darker instead of lighter (`dark:hover:bg-primary-600`)? → **FIX** (must be `dark:hover:bg-primary-400`)
|
|
427
|
+
- Design Contract not declared before code? → **STOP** and complete [Phase 0](../core/ui/design-thinking.md)
|
|
428
|
+
- 60-30-10 violated (secondary color dominates surface)? → **REDUCE** to accent-only usage
|
|
429
|
+
- `text-muted-foreground` on `bg-muted` or `bg-muted/40`? → **CHECK** Lightness delta: difference between L of text token and L of background token must be ≥ 40 percentage points. If below threshold → use `text-foreground` instead.
|
|
430
|
+
|
|
431
|
+
**Code**
|
|
432
|
+
|
|
433
|
+
- `fetch` used directly in a component? → **FIX** (move to `apiClient`)
|
|
434
|
+
- `Result` stored in component state (`useState<Result<T>>`)? → **FIX** (translate to `data / error / isLoading`)
|
|
435
|
+
- Logic or transformation inline inside `useEffect`? → **FIX** (extract named function)
|
|
436
|
+
- JSX returned without a named variable? → **FIX** (`const view = ...; return view;`)
|
|
437
|
+
</rule>
|
|
438
|
+
|
|
439
|
+
</ruleset>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Agent Roles — Multi-Agent Execution Protocol
|
|
2
|
+
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This protocol is active when running inside **Claude Code**.
|
|
5
|
+
> If you are a different agent or model, skip to **Fallback: Single-Agent Mode** at the bottom.
|
|
6
|
+
|
|
7
|
+
## Roles
|
|
8
|
+
|
|
9
|
+
| Role | Phases | Model default | Mindset |
|
|
10
|
+
| :----------- | :---------------------- | :------------------------- | :------------------------------- |
|
|
11
|
+
| **Planning** | SPEC, PLAN, Review, END | claude-sonnet-4-6 thinking | Analytical — strategy and design |
|
|
12
|
+
| **Fast** | CODE, TEST | claude-sonnet-4-6 | Operational — execute and verify |
|
|
13
|
+
|
|
14
|
+
## Execution Flow
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
Dev → Planning: SPEC + PLAN → [Dev approval]
|
|
18
|
+
↓
|
|
19
|
+
Planning spawns Fast via Agent tool
|
|
20
|
+
↓
|
|
21
|
+
Fast: CODE + TEST
|
|
22
|
+
↓
|
|
23
|
+
Fast returns output to Planning
|
|
24
|
+
↓
|
|
25
|
+
Planning: Review + Report → [Dev approval] → END
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Scope Rule — When to Use Multi-Agent
|
|
29
|
+
|
|
30
|
+
- **[M] and [L] tasks**: always spawn Fast after PLAN approval.
|
|
31
|
+
- **[S] tasks** (1–2 files, isolated scope): Planning executes CODE + TEST directly — no Fast spawn. Overhead exceeds benefit at this scale.
|
|
32
|
+
|
|
33
|
+
## Planning Role — Responsibilities
|
|
34
|
+
|
|
35
|
+
- Load full governance context before SPEC: backlog, flavor, competencies.
|
|
36
|
+
- Produce SPEC and PLAN. Stop and wait for Dev approval at each.
|
|
37
|
+
- When PLAN is approved, invoke the Agent tool to delegate CODE + TEST to Fast.
|
|
38
|
+
- **Handoff prompt must include** (never omit):
|
|
39
|
+
- The approved SPEC (goal, inputs/outputs, verification checklist)
|
|
40
|
+
- The approved PLAN (task list with file paths)
|
|
41
|
+
- Relevant context refs: `engineering-standards.md`, `code-style.md`, idiom patterns
|
|
42
|
+
- After Fast returns: review against the Narrative Gate and Verification Checklist.
|
|
43
|
+
- Report to Dev with PASS/FAIL per checklist item before proceeding to END.
|
|
44
|
+
|
|
45
|
+
## Fast Role — Responsibilities
|
|
46
|
+
|
|
47
|
+
- Load only what is required for CODE: engineering standards, code style, idiom patterns.
|
|
48
|
+
- Do not re-derive strategy. The SPEC and PLAN are the contract — follow them exactly.
|
|
49
|
+
- Apply Narrative Gate before every function body.
|
|
50
|
+
- Run tests and lint. Return a structured report: tasks completed, gate results, test status.
|
|
51
|
+
- Do not proceed to END. Return control to Planning.
|
|
52
|
+
|
|
53
|
+
## Handoff — Agent Tool Invocation
|
|
54
|
+
|
|
55
|
+
Planning invokes Fast using the Agent tool with `model: "sonnet"`:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Agent({
|
|
59
|
+
model: "sonnet",
|
|
60
|
+
prompt: `
|
|
61
|
+
## Role: Fast — CODE + TEST
|
|
62
|
+
|
|
63
|
+
You are the Fast agent. Execute only CODE and TEST phases.
|
|
64
|
+
Do not plan, do not strategize. Follow the contract below exactly.
|
|
65
|
+
|
|
66
|
+
## Approved SPEC
|
|
67
|
+
[paste SPEC here]
|
|
68
|
+
|
|
69
|
+
## Approved PLAN
|
|
70
|
+
[paste task list here]
|
|
71
|
+
|
|
72
|
+
## Context to load before coding
|
|
73
|
+
- .ai/instructions/core/engineering-standards.md
|
|
74
|
+
- .ai/instructions/core/code-style.md
|
|
75
|
+
- .ai/instructions/idioms/<stack>/patterns.md
|
|
76
|
+
|
|
77
|
+
## Deliverable
|
|
78
|
+
Return: tasks completed, Narrative Gate results per function, test PASS/FAIL, lint status.
|
|
79
|
+
`
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Review Gate (Planning, post-Fast)
|
|
84
|
+
|
|
85
|
+
Before reporting to Dev, Planning checks:
|
|
86
|
+
|
|
87
|
+
- [ ] Every PLAN task is marked complete in Fast's report
|
|
88
|
+
- [ ] Narrative Gate passed for all functions written
|
|
89
|
+
- [ ] Tests pass — no regressions
|
|
90
|
+
- [ ] Lint clean
|
|
91
|
+
|
|
92
|
+
Any ❌ → Planning fixes inline or sends back to Fast for a targeted correction (max 1 loop).
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Fallback: Single-Agent Mode
|
|
97
|
+
|
|
98
|
+
**If the Agent tool is not available** (Gemini, Cursor, Windsurf, Cline, or any non-Claude Code environment):
|
|
99
|
+
|
|
100
|
+
- Execute all phases as a single agent.
|
|
101
|
+
- Apply Planning mindset during SPEC and PLAN (analytical, stop for approval).
|
|
102
|
+
- Apply Fast mindset during CODE and TEST (operational, no strategic detours).
|
|
103
|
+
- The role annotations in the workflow (`> **Role: Planning**`, `> **Role: Fast**`) serve as mindset cues — treat them as discipline markers, not execution boundaries.
|
|
104
|
+
- Proceed through END normally.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# API Design — Consistency, Resilience, and Contracts
|
|
2
|
+
|
|
3
|
+
<ruleset name="Universal API Design Standard">
|
|
4
|
+
|
|
5
|
+
> [!NOTE]
|
|
6
|
+
> APIs represent the contract between logic and consumer. They must be predictable, resilient, and hardened.
|
|
7
|
+
|
|
8
|
+
## Rule: API Contract Resilience
|
|
9
|
+
|
|
10
|
+
<rule name="APIContractResilience">
|
|
11
|
+
|
|
12
|
+
> [!IMPORTANT]
|
|
13
|
+
> Business failures are first-class values in the API response. Applies **Law 2 (Resilience)** at the contract layer.
|
|
14
|
+
|
|
15
|
+
#### Instructions
|
|
16
|
+
|
|
17
|
+
- **Standard Envelope:** Every API response uses `{ success, data, error, meta: { action? } }`. See the [Backend Competency](.ai/instructions/competencies/backend.md) for the full envelope spec with TypeScript examples, the `meta.action` directive, and HTTP error code mapping.
|
|
18
|
+
- **Typed Error Payloads:** Error codes are explicit string constants (e.g., `NOT_FOUND`, `INVALID_INPUT`). Never return free-form error messages that the consumer must parse. For HTTP 409 specifically: use `CONFLICT` for unique constraint violations (duplicate email, concurrent edit) and `BUSINESS_RULE_VIOLATION` for domain rule violations (cannot cancel a shipped order). See the [Backend Competency](.ai/instructions/competencies/backend.md) for the full error code table.
|
|
19
|
+
- **Idempotency:** Require and enforce Idempotency-Key headers for all non-safe operations (POST/PUT/PATCH) that have financial or inventory side effects.
|
|
20
|
+
</rule>
|
|
21
|
+
|
|
22
|
+
## Rule: API Data Masking
|
|
23
|
+
|
|
24
|
+
<rule name="APIDataMasking">
|
|
25
|
+
|
|
26
|
+
> [!CAUTION]
|
|
27
|
+
> Never expose internal models. Strictly enforce ViewModels/DTOs. Applies **Law 1 (Hardening)** at the response layer.
|
|
28
|
+
|
|
29
|
+
#### Instructions
|
|
30
|
+
|
|
31
|
+
- **Zero Leakage:** Internal IDs (autoincrement), DB metadata, or framework-specific stack traces must NEVER appear in the envelope. Primary keys exposed to the client should be UUIDs or ULIDs.
|
|
32
|
+
- **Explicit Projection:** Only return the fields requested by the contract — enforced via the `OutputFilter` (Response DTO) rule in the [Backend Competency](.ai/instructions/competencies/backend.md). No raw entities, no over-fetching of sensitive fields (`passwordHash`, `internalMetadata`).
|
|
33
|
+
- **HTTP/S Only:** Enforce secure-only transport layers.
|
|
34
|
+
</rule>
|
|
35
|
+
|
|
36
|
+
## Rule: REST Endpoint Hierarchy
|
|
37
|
+
|
|
38
|
+
<rule name="RESTEndpointHierarchy">
|
|
39
|
+
|
|
40
|
+
> [!NOTE]
|
|
41
|
+
> RESTful paths should read as a hierarchy of intent. Applies **NarrativeCascade** at the API surface.
|
|
42
|
+
|
|
43
|
+
#### Instructions
|
|
44
|
+
|
|
45
|
+
- **Resource-Oriented:** Organize endpoints around Nouns, not Verbs (e.g., `POST /orders` instead of `POST /create-order`).
|
|
46
|
+
- **Sub-Resource Hierarchy:** Use deep paths for context (e.g., `/users/{id}/orders`).
|
|
47
|
+
- **Statelessness:** No session affinity should be required for a single request.
|
|
48
|
+
</rule>
|
|
49
|
+
|
|
50
|
+
## Rule: Standardization Protocols
|
|
51
|
+
|
|
52
|
+
<rule name="APIStandardization">
|
|
53
|
+
|
|
54
|
+
> [!IMPORTANT]
|
|
55
|
+
> Consistency is the soul of a clean API ecosystem.
|
|
56
|
+
|
|
57
|
+
#### Instructions
|
|
58
|
+
|
|
59
|
+
- **Naming:** CamelCase for JSON keys; kebab-case for headers and paths.
|
|
60
|
+
- **Pagination:** Mandatory for all collection endpoints. Cursor-based by default; offset only for bounded admin/backoffice UIs. See [Backend Competency](.ai/instructions/competencies/backend.md) for the canonical shapes.
|
|
61
|
+
- **Versioning:** Strictly via path prefix (e.g., `/v1/...`) to prevent breaking consumer integration.
|
|
62
|
+
- **HTTP Status Codes:** Use semantic ranges (2xx for success, 4xx for consumer errors, 5xx for system failures).
|
|
63
|
+
</rule>
|
|
64
|
+
|
|
65
|
+
</ruleset>
|