@ludecker/aaac 1.1.4 → 1.1.6
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 +27 -12
- package/package.json +1 -1
- package/src/cli.mjs +19 -7
- package/src/generators/generate-commands.mjs +25 -1
- package/src/generators/generate-graph.mjs +9 -1
- package/src/lib/install.mjs +13 -1
- package/src/lib/sweep-project-docs.mjs +348 -0
- package/src/run-engine/advance-phase.mjs +25 -5
- package/src/run-engine/debug-run.mjs +6 -0
- package/src/run-engine/gate-write.mjs +13 -0
- package/src/run-engine/lib.mjs +165 -0
- package/src/run-engine/log.mjs +1 -1
- package/src/run-engine/record-task.mjs +25 -4
- package/templates/cursor/aaac/enforcement.json +20 -4
- package/templates/cursor/aaac/graph.project.yaml +16 -5
- package/templates/cursor/aaac/lifecycle/lifecycle.json +12 -0
- package/templates/cursor/aaac/lifecycle/phases.json +2 -0
- package/templates/cursor/aaac/run/schema.json +5 -0
- package/templates/cursor/aaac/scripts/run-engine/advance-phase.mjs +25 -5
- package/templates/cursor/aaac/scripts/run-engine/debug-run.mjs +6 -0
- package/templates/cursor/aaac/scripts/run-engine/gate-write.mjs +13 -0
- package/templates/cursor/aaac/scripts/run-engine/lib.mjs +165 -0
- package/templates/cursor/aaac/scripts/run-engine/log.mjs +1 -1
- package/templates/cursor/aaac/scripts/run-engine/record-task.mjs +25 -4
- package/templates/cursor/agents/doc-conformance.md +25 -0
- package/templates/cursor/agents/implementation-review.md +21 -0
- package/templates/cursor/agents/test-author.md +27 -0
- package/templates/cursor/rules/aaac-enforcement.mdc +18 -6
- package/templates/cursor/skills/shared/_task-prompt-policy.md +18 -0
- package/templates/cursor/skills/shared/check/SKILL.md +4 -0
- package/templates/cursor/skills/shared/discovery/SKILL.md +4 -0
- package/templates/cursor/skills/shared/execution/SKILL.md +7 -3
- package/templates/cursor/skills/shared/governance/implementation/SKILL.md +396 -28
- package/templates/cursor/skills/shared/implementation-review/SKILL.md +49 -0
- package/templates/cursor/skills/shared/investigation/SKILL.md +1 -1
- package/templates/cursor/skills/shared/investigation-lite/SKILL.md +2 -0
- package/templates/cursor/skills/shared/planning/SKILL.md +5 -0
- package/templates/cursor/skills/shared/test-authoring/SKILL.md +58 -0
- package/templates/cursor/skills/shared/testing/SKILL.md +9 -3
- package/templates/cursor/skills/shared/verbs/create/orchestrator/SKILL.md +5 -3
- package/templates/cursor/skills/shared/verbs/fix/orchestrator/SKILL.md +5 -3
- package/templates/cursor/skills/shared/verbs/update/orchestrator/SKILL.md +5 -3
- package/templates/cursor/skills/shared/verification/SKILL.md +5 -3
- package/templates/docs/agentic_architecture.md +168 -97
|
@@ -1,56 +1,424 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: implementation
|
|
3
|
-
description: Enforces
|
|
3
|
+
description: Enforces Lüdecker master rules, architecture patterns, and design system when implementing, editing, or refactoring code. Use for any code change — new features, bug fixes, UI work, API routes, migrations, or refactors. Read docs/master_rules.md, docs/architecture.md, and packages/ui tokens before writing code.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Implementation
|
|
7
7
|
|
|
8
|
-
All code changes must comply with
|
|
8
|
+
All code changes in this repo must comply with three authoritative documents. **If implementation conflicts with these docs, the docs win.**
|
|
9
9
|
|
|
10
10
|
| Document | Path | Governs |
|
|
11
11
|
|----------|------|---------|
|
|
12
|
-
| Master Rules | [
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
| Architecture | [{{DOCS_ROOT}}/architecture.md](../../../../{{DOCS_ROOT}}/architecture.md) | System shape, modules, data flow, deploy |
|
|
12
|
+
| Master Rules | [docs/master_rules.md](../../../../docs/master_rules.md) | Architecture, layers, SSOT, async, testing, logging |
|
|
13
|
+
| Architecture | [docs/architecture.md](../../../../docs/architecture.md) | System shape, routing, state, API, DB, integrations |
|
|
14
|
+
| Design System | [packages/ui/src/tokens.css](../../../../packages/ui/src/tokens.css), [skills/ludecker/design-system/SKILL.md](../../../ludecker/design-system/SKILL.md) | Tokens, base components, typography |
|
|
16
15
|
|
|
17
|
-
Read the relevant sections **before** implementing.
|
|
16
|
+
Read the relevant sections **before** implementing. Use this skill as the workflow and checklist; use the docs as the full specification.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Why God Files Still Happen
|
|
21
|
+
|
|
22
|
+
The skill enforces **layer placement** (UI vs store vs routes) but historically did **not** enforce **size budgets** or **split-before-add**. Combined with "minimal diff" in File Conventions, agents default to **appending** to existing files — which complies with layer rules while violating Rule 2 ("if a file does more than one thing, it is doing too much").
|
|
23
|
+
|
|
24
|
+
**Fix:** treat size budgets as hard gates (Master Rules §19). When a touched file is near its limit, extraction is **part of the task**, not a follow-up refactor.
|
|
18
25
|
|
|
19
26
|
---
|
|
20
27
|
|
|
21
28
|
## Before You Write Code
|
|
22
29
|
|
|
23
|
-
1. **Identify the layer** you are touching (UI, state, domain, infrastructure).
|
|
24
|
-
2. **Read** the matching
|
|
25
|
-
3. **
|
|
26
|
-
4. **
|
|
27
|
-
5. **
|
|
30
|
+
1. **Identify the layer** you are touching (UI, state, domain, infrastructure, server route).
|
|
31
|
+
2. **Read** the matching sections in the three docs above — do not rely on memory.
|
|
32
|
+
3. **Find existing patterns** in the same layer (grep/read neighbors; match conventions).
|
|
33
|
+
4. **Plan the SSOT** — where does this data live? Who owns this state? What schema validates it?
|
|
34
|
+
5. **Check file budgets** — run `wc -l` on files you will edit. If any file is ≥80% of its budget (see [Size Budgets](#size-budgets)), plan extraction **before** adding code.
|
|
35
|
+
6. **If an AAAC domain exists** for this area (`.cursor/domains/<slug>/update/inventory/`), read it for inventory, boundaries, and invariants before planning.
|
|
36
|
+
7. **If editing a legacy god file** (>300 lines or Fallow flagged), read [.cursor/skills/shared/architecture/refactor-analysis.md](../architecture/refactor-analysis.md) and split as part of this change unless the user scoped a hotfix only.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Layer Placement (Architecture)
|
|
41
|
+
|
|
42
|
+
| Change type | Location | Must NOT |
|
|
43
|
+
|-------------|----------|----------|
|
|
44
|
+
| UI rendering | `src/app/components/` | Fetch, business logic, state orchestration |
|
|
45
|
+
| Global state | `src/app/store/slices/` | UI knowledge, rendering |
|
|
46
|
+
| Business rules | `src/app/domain/` or `shared/domain/` | React, HTTP, DB |
|
|
47
|
+
| Client HTTP | `src/app/api/` (domain modules) | Business decisions |
|
|
48
|
+
| Server routes | `server/routes/` | Business logic beyond validation + orchestration |
|
|
49
|
+
| Server workflows | `server/lib/` or `server/services/` | Express req/res, route registration |
|
|
50
|
+
| Shared validation | `shared/schemas/` | Layer-specific logic |
|
|
51
|
+
| Marketing site UI | `src/site/components/` | Dashboard app patterns |
|
|
52
|
+
| OpenRouter / LLM | `server/openrouter/` | Supabase, auth, DB (see [openrouter.md](../../../../docs/openrouter.md)) |
|
|
53
|
+
|
|
54
|
+
**URL is SSOT for navigation.** Path construction lives in `src/app/domain/paths.ts`. Store reflects URL; it does not own it.
|
|
55
|
+
|
|
56
|
+
**Data loading state machine:** `idle → loading → ready | error`. Derived data via `useMemo`, never stored separately.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Size Budgets
|
|
61
|
+
|
|
62
|
+
Authoritative limits: [docs/master_rules.md §19](../../../../docs/master_rules.md#19-module-size-budgets). Architecture patterns: [docs/architecture.md § Module Composition](../../../../docs/architecture.md#module-composition-size-budgets).
|
|
63
|
+
|
|
64
|
+
| File kind | Max lines | When adding code |
|
|
65
|
+
|-----------|-----------|------------------|
|
|
66
|
+
| React component / hook | 250 | Extract subcomponents + `use<Feature>*.ts` hooks |
|
|
67
|
+
| Route file | 200 | Move logic to `server/lib/`; keep handler ≤15 lines |
|
|
68
|
+
| Domain / lib | 300 | Split by capability |
|
|
69
|
+
| OpenRouter module | 350 | New file per AI capability |
|
|
70
|
+
|
|
71
|
+
**Split-before-add:** at ≥80% of budget, extract first. **Never** grow `ImportFromFiles`-style monoliths.
|
|
72
|
+
|
|
73
|
+
### Extend vs new file
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
Adding to existing file?
|
|
77
|
+
└─ File under 80% budget AND same single responsibility → extend
|
|
78
|
+
└─ File at/above 80% budget → extract module first, then wire
|
|
79
|
+
└─ New capability domain (new endpoint, new import source, new AI feature) → new file always
|
|
80
|
+
└─ Touching route file with inline DB/LLM logic → move logic to server/lib/ as part of this task
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Implementation Checklist
|
|
86
|
+
|
|
87
|
+
Copy and track before finishing:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Implementation Progress:
|
|
91
|
+
- [ ] Layer placement correct (UI / state / domain / infrastructure)
|
|
92
|
+
- [ ] SSOT identified — no duplicated state or constants
|
|
93
|
+
- [ ] Size budgets respected (Master Rules §19) — split before add if near limit
|
|
94
|
+
- [ ] Zod schema at boundaries (shared/schemas/)
|
|
95
|
+
- [ ] No hardcoded values (IDs, strings, sizes, flags)
|
|
96
|
+
- [ ] No inline styles or style objects (except --depth / --progress)
|
|
97
|
+
- [ ] No inline or nested components — each in its own file
|
|
98
|
+
- [ ] Base components: data props only, no className
|
|
99
|
+
- [ ] Async logic cancellable and lifecycle-scoped via explicit state machine transitions — not guards
|
|
100
|
+
- [ ] Complex multi-step/async coordination modeled as a state machine (not booleans + useEffect)
|
|
101
|
+
- [ ] Errors explicit — logged with context, never swallowed
|
|
102
|
+
- [ ] Structured logging on async paths (server)
|
|
103
|
+
- [ ] PostHog track() if user-facing action (store action or handler)
|
|
104
|
+
- [ ] Tests planned in `tests_to_add[]` — authored in `test_execute`, not here
|
|
105
|
+
- [ ] Realtime vs fetch-on-action chosen correctly
|
|
106
|
+
- [ ] Fallow check_changed on touched files — no new budget violations
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Master Rules — Quick Reference
|
|
112
|
+
|
|
113
|
+
Non-negotiables. Full detail: [docs/master_rules.md](../../../../docs/master_rules.md).
|
|
114
|
+
|
|
115
|
+
| # | Rule | Implementation implication |
|
|
116
|
+
|---|------|---------------------------|
|
|
117
|
+
| 1 | SSOT | One owner for each piece of state/config. Derive, don't duplicate. |
|
|
118
|
+
| 2 | Separation of concerns | One responsibility per file/module. |
|
|
119
|
+
| 4 | No hardcoding | Constants, schemas, config, tokens — never inline literals. |
|
|
120
|
+
| 5–6 | No inline styling/components | Token classes; named components in separate files. |
|
|
121
|
+
| 8 | Unidirectional flow | Input → State → Logic → Output. No magic. |
|
|
122
|
+
| 9 | Explicit state machines | Named states and transitions for complex flows. |
|
|
123
|
+
| 10 | Race avoidance | Cancellable async, no overlapping uncoordinated requests. |
|
|
124
|
+
| 13 | Validation at boundaries | Zod on ingress and client responses. |
|
|
125
|
+
| 16 | Explicit errors | Visible, traceable, actionable. Log before propagate. |
|
|
126
|
+
| 19 | Debug logging | `[level] [module:operation] message { context }` |
|
|
127
|
+
| 18 | Scalability | Size budgets §19; split before add. |
|
|
128
|
+
| 19 | Module size budgets | Numeric limits; Fallow gate after changes. |
|
|
129
|
+
| 20 | Testing | Behavior tests at unit/integration/e2e as appropriate. |
|
|
130
|
+
| 21 | Documented exceptions | If a rule must break, document why in code. |
|
|
131
|
+
| 22 | Prime directive | Clarity > cleverness. Predictability > shortcuts. |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## No Race Guards, Fallbacks, or Quick Fixes (Hard Ban)
|
|
136
|
+
|
|
137
|
+
When async work overlaps (delete during suggest, navigation during load, overlapping API calls), **do not** paper over timing with:
|
|
138
|
+
|
|
139
|
+
- **Race guards** — `if (!stillExists) return`, “discard stale response”, `useEffect` re-firing side effects, duplicate-request Sets without a owning machine
|
|
140
|
+
- **Fallback branches** — silent defaults that hide invalid state instead of preventing the transition
|
|
141
|
+
- **Quick fixes** — reordering `await` without modeling the flow, extra booleans, or comment-only “fixes”
|
|
142
|
+
|
|
143
|
+
These patterns hide bugs and violate Rules 9–10. They are **never** acceptable, including for regressions or hotfixes.
|
|
144
|
+
|
|
145
|
+
### Required approach
|
|
146
|
+
|
|
147
|
+
1. **Name the flow** — finite states, finite events, explicit transitions (XState machine or pure `transition*` domain module + store dispatch).
|
|
148
|
+
2. **One owner** — the machine owns coordination; UI reads derived selectors only.
|
|
149
|
+
3. **Cancel by generation/token** — bump a generation when the machine emits `CANCEL_*`; in-flight work checks generation **once** at completion to dispatch `*_ABORTED` / `*_COMPLETE`, not to silently drop data.
|
|
150
|
+
4. **Enter blocking phases before I/O** — e.g. `REMOVE_BEGIN` synchronously before `await api.delete…` so dependent UI cannot start new work.
|
|
151
|
+
5. **No reactive orchestration** — do not start mutations from `useEffect` watching derived emptiness; start only from valid machine transitions or user/store actions.
|
|
152
|
+
|
|
153
|
+
**Examples in this repo:** `requirementFocusMachine` + `requirementFocus` slice (selection + suggestion + removal), `deleteEntity.machine`, `routerResolver.machine`.
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
WRONG: useEffect(() => { if (selected && questions.length === 0) suggest(); }, [...])
|
|
157
|
+
WRONG: if (!requirements.find(r => r.id)) { discard suggestions; return; }
|
|
158
|
+
RIGHT: REMOVE_BEGIN → CANCEL_SUGGESTION → API → graph cleanup → REMOVE_END
|
|
159
|
+
RIGHT: SYNC_SELECTION → (machine decides) RUN_SUGGESTION effect → runQuestionSuggestion(generation)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## useState vs XState (and Pure Transition Modules)
|
|
165
|
+
|
|
166
|
+
**Pragmatic rule:**
|
|
167
|
+
|
|
168
|
+
> **Use `useState` when the state can be fully understood by reading a single component.**
|
|
169
|
+
>
|
|
170
|
+
> **Use a state machine when the state represents a process, workflow, or lifecycle with multiple valid states and transitions.**
|
|
171
|
+
|
|
172
|
+
For agentic applications: **default toward state machines for orchestration and workflows**; use hooks only for local UI state.
|
|
173
|
+
|
|
174
|
+
### `useState` — local, single-component UI
|
|
175
|
+
|
|
176
|
+
State is obvious from one file; no async coordination; no cross-system coupling.
|
|
177
|
+
|
|
178
|
+
| Example | Why hooks |
|
|
179
|
+
|---------|-----------|
|
|
180
|
+
| Modal open/closed | Binary, scoped to one component |
|
|
181
|
+
| Selected tab | Local presentation |
|
|
182
|
+
| Search input | Controlled field |
|
|
183
|
+
| Dropdown expanded/collapsed | Ephemeral UI |
|
|
184
|
+
| Local form fields | Pre-submit draft in one form |
|
|
185
|
+
|
|
186
|
+
### State machine — process, workflow, lifecycle
|
|
187
|
+
|
|
188
|
+
Multiple named states; explicit transitions; async, side effects, or coordination across store/router/API/AI.
|
|
189
|
+
|
|
190
|
+
| Example | Why a machine |
|
|
191
|
+
|---------|----------------|
|
|
192
|
+
| Authentication flow | Multi-step, errors, redirects |
|
|
193
|
+
| Multi-step wizard / import | Ordered steps, back/next, validation gates |
|
|
194
|
+
| Routing resolution | URL ↔ workspace ↔ project ↔ selection |
|
|
195
|
+
| Data loading with retries | `idle → loading → ready \| error` |
|
|
196
|
+
| AI agent / suggestion workflows | In-flight work, cancel, completion |
|
|
197
|
+
| Requirement → Question → Answer → Summary | Cross-column coordination |
|
|
198
|
+
| Delete/deactivate during async work | Blocking phases, cancellation |
|
|
199
|
+
|
|
200
|
+
**Implementation forms (pick one per flow):**
|
|
201
|
+
|
|
202
|
+
1. **XState + `useMachine`** — React lifecycle integration (e.g. `routerResolver.machine`, `deleteEntity.machine`).
|
|
203
|
+
2. **Pure `transition*` module + store dispatch** — Zustand-owned coordination without React actor (e.g. `requirementFocusMachine` + `requirementFocus` slice).
|
|
204
|
+
|
|
205
|
+
Both are state machines. Do not substitute a pile of booleans for either form.
|
|
206
|
+
|
|
207
|
+
### Smell test
|
|
208
|
+
|
|
209
|
+
> If you're adding flags like `isLoading`, `isFetching`, `isSaving`, `isRetrying`, `hasError`, `isReady`, `hasInitialized`, `shouldRefetch` — you're probably describing a state machine already.
|
|
210
|
+
|
|
211
|
+
Replace the flags with named states and events. One owner; UI reads derived selectors.
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
WRONG: isSuggesting + isRemoving + useEffect(() => suggest(), [selected, questions.length])
|
|
215
|
+
RIGHT: phase: 'selected' | 'removing', suggestion: 'idle' | 'requesting' | 'complete'
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Architecture Patterns
|
|
221
|
+
|
|
222
|
+
Full detail: [docs/architecture.md](../../../../docs/architecture.md).
|
|
223
|
+
|
|
224
|
+
### Server (BFF)
|
|
225
|
+
|
|
226
|
+
- Dashboard CRUD: `createUserClient(jwt)` — RLS enforced.
|
|
227
|
+
- OAuth callbacks, webhooks, background jobs: `supabaseAdmin` — no user JWT.
|
|
228
|
+
- Validate `req.body` with Zod middleware. Parse responses with domain schemas.
|
|
229
|
+
- Bind to `0.0.0.0:$PORT`. Secrets via `process.env` only.
|
|
230
|
+
|
|
231
|
+
### Client (Dashboard)
|
|
232
|
+
|
|
233
|
+
- Auth: Supabase Auth → Bearer JWT on `/api/*` calls.
|
|
234
|
+
- Zustand slices per domain. Store actions are SSOT for API-backed mutations.
|
|
235
|
+
- `track()` in store actions (API flows) or component handlers (pure UI events). Never in render.
|
|
236
|
+
- Realtime for externally-modified data; fetch-on-action for user's own mutations.
|
|
237
|
+
|
|
238
|
+
### Schemas
|
|
239
|
+
|
|
240
|
+
`shared/schemas/` — row schema (snake_case), domain schema (camelCase), mutation schemas. Consumed by client and server.
|
|
241
|
+
|
|
242
|
+
### New API endpoint
|
|
243
|
+
|
|
244
|
+
1. Zod mutation schema in `shared/schemas/`
|
|
245
|
+
2. Workflow logic in `server/lib/<feature>.ts` (if >15 lines or reusable)
|
|
246
|
+
3. Thin route in `server/routes/` with `requireAuth` + `validateBody` — delegate to lib
|
|
247
|
+
4. Client method in `src/app/api/<domain>Api.ts` with response parsing
|
|
248
|
+
5. Store action in appropriate slice
|
|
249
|
+
6. UI calls store action only
|
|
250
|
+
|
|
251
|
+
If `server/routes/<resource>.ts` exceeds **200 lines**, new endpoints must not be added inline — extract handlers to `server/lib/` first (see `requirementsRouteHelpers.ts` for error-mapping pattern).
|
|
252
|
+
|
|
253
|
+
### AI / OpenRouter feature
|
|
254
|
+
|
|
255
|
+
Read [docs/openrouter.md](../../../../docs/openrouter.md) first.
|
|
256
|
+
|
|
257
|
+
1. Context loading in `server/context.ts` or `server/lib/*Context*.ts`
|
|
258
|
+
2. Prompt + LLM I/O in new `server/openrouter/<feature>.ts` (one capability per file)
|
|
259
|
+
3. Route/job calls openrouter with context as arguments
|
|
260
|
+
4. Schema validation on LLM output at module boundary
|
|
261
|
+
5. Unit tests for schemas and pure helpers — no live OpenRouter calls
|
|
262
|
+
|
|
263
|
+
### Multi-step UI (modals, import flows, wizards)
|
|
264
|
+
|
|
265
|
+
Use a **feature folder** (see architecture doc). Step flow must be an **explicit state machine** (XState or pure `transition*` module) — not ad-hoc step booleans.
|
|
266
|
+
|
|
267
|
+
1. `<Feature>.tsx` — thin shell (~100 lines max)
|
|
268
|
+
2. `<feature>.machine.ts` or `use<Feature>State.ts` — step machine (finite states + transitions)
|
|
269
|
+
3. `use<Feature>Actions.ts` — store mutations and side effects triggered by machine effects
|
|
270
|
+
4. One subcomponent per step/section
|
|
271
|
+
|
|
272
|
+
Do not add steps to a 300+ line modal component.
|
|
273
|
+
|
|
274
|
+
### New integration
|
|
275
|
+
|
|
276
|
+
Follow OAuth pattern in architecture doc. Store slice in `store/slices/<provider>.ts`. Connection table with RLS `user_id = auth.uid()`.
|
|
28
277
|
|
|
29
278
|
---
|
|
30
279
|
|
|
31
|
-
##
|
|
280
|
+
## Design System
|
|
281
|
+
|
|
282
|
+
Full detail: [docs/design_system.md](../../../../docs/design_system.md). Component specs: [docs/design_components.md](../../../../docs/design_components.md).
|
|
283
|
+
|
|
284
|
+
### Token SSOT
|
|
285
|
+
|
|
286
|
+
All visual values from `src/styles/theme.css` via Tailwind utilities. **No** hardcoded hex/rgba, arbitrary `rounded-[Npx]`, `font-[N]`, or `shadow-[...]`.
|
|
287
|
+
|
|
288
|
+
### Base Component Architecture (CRITICAL)
|
|
289
|
+
|
|
290
|
+
Base components (`src/app/components/ui/`) own **all** visual styling.
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
CORRECT: <DropdownPanel variant="attached" position="above">...</DropdownPanel>
|
|
294
|
+
WRONG: <DropdownPanel className="absolute bottom-full ...">...</DropdownPanel>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
- Consumers pass **data props only** (`variant`, `label`, `icon`, `onClick`).
|
|
298
|
+
- Base components do **not** accept `className`. Zero exceptions.
|
|
299
|
+
- New visual variation → new prop on base, styled internally.
|
|
300
|
+
- Use typography presets (`.text-h1`, `.text-caption`, `.text-label`) — do not override with extra `font-*` / `tracking-*` / `uppercase`.
|
|
301
|
+
|
|
302
|
+
### Only permitted inline styles
|
|
303
|
+
|
|
304
|
+
`style={{ '--depth': N }}` and `style={{ '--progress': 'N%' }}` for tree indentation and progress bars.
|
|
305
|
+
|
|
306
|
+
### New UI component workflow
|
|
307
|
+
|
|
308
|
+
1. Check for existing base component or pattern.
|
|
309
|
+
2. If reusable visual pattern → extend or create base in `ui/`.
|
|
310
|
+
3. Consumer component imports base; passes props only.
|
|
311
|
+
4. New tokens → add to `theme.css` `:root` + `@theme inline` + document in design_system.md.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Decision Trees
|
|
316
|
+
|
|
317
|
+
### Where does this logic go?
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
User clicked something?
|
|
321
|
+
└─ Pure UI event (modal open, palette) → component handler + track()
|
|
322
|
+
└─ Mutates app data → store action → api.ts → server route
|
|
323
|
+
|
|
324
|
+
Business rule or invariant?
|
|
325
|
+
└─ src/app/domain/ or shared/domain/
|
|
326
|
+
|
|
327
|
+
Validation?
|
|
328
|
+
└─ shared/schemas/ (Zod)
|
|
329
|
+
|
|
330
|
+
Visual styling?
|
|
331
|
+
└─ Base component in ui/ (tokens only)
|
|
332
|
+
|
|
333
|
+
Navigation?
|
|
334
|
+
└─ paths.ts + URL params → routerResolver.machine → store
|
|
335
|
+
|
|
336
|
+
Async workflow or multi-system coordination?
|
|
337
|
+
└─ XState (React) or transition* module + store dispatch — never useState flags + useEffect
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Realtime or fetch-on-action?
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
Data changed by external system (webhook, other user, job)?
|
|
344
|
+
└─ Supabase Realtime → silent store refresh
|
|
345
|
+
|
|
346
|
+
Data changed by current user's action?
|
|
347
|
+
└─ Use API response / store update from action (no Realtime needed)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Which Supabase client?
|
|
351
|
+
|
|
352
|
+
```
|
|
353
|
+
User-initiated dashboard CRUD?
|
|
354
|
+
└─ createUserClient(jwt)
|
|
355
|
+
|
|
356
|
+
OAuth callback, webhook, background job?
|
|
357
|
+
└─ supabaseAdmin
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## File Conventions
|
|
363
|
+
|
|
364
|
+
Match existing code in the target directory:
|
|
365
|
+
|
|
366
|
+
- **Naming:** intent over implementation. No vague abbreviations.
|
|
367
|
+
- **Imports:** explicit interfaces between modules. No circular deps.
|
|
368
|
+
- **Components:** one named export per file. No render helpers inside component bodies.
|
|
369
|
+
- **Scope:** minimal *behavioral* diff — but **structural extraction is in scope** when size budgets require it. Do not append to god files to avoid file churn.
|
|
370
|
+
- **Comments:** only for non-obvious business logic.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## After Implementation
|
|
375
|
+
|
|
376
|
+
1. **Do not self-review** — [implementation-review](../implementation-review/SKILL.md) runs in `review_swarm` with separate readonly agents.
|
|
377
|
+
2. **Do not write tests here** — [test-authoring](../test-authoring/SKILL.md) runs in `test_execute` with a separate agent.
|
|
378
|
+
3. **Run Fallow on changed files** — MCP `check_changed` or `npx fallow health --changed-since HEAD --file-scores`. Fix any new budget violations before finishing.
|
|
379
|
+
4. **Read lints** on edited files; fix introduced issues.
|
|
380
|
+
5. **Verify layer boundaries** — no fetch in UI, no business logic in routes beyond orchestration.
|
|
381
|
+
6. **Verify design system** — grep edited files for hardcoded colors, `className` on base components, inline `style={{}}`.
|
|
382
|
+
|
|
383
|
+
---
|
|
32
384
|
|
|
33
|
-
|
|
34
|
-
|-------|----------------|----------|
|
|
35
|
-
| UI | Render + interaction | Fetch, business rules, direct DB |
|
|
36
|
-
| State | Transitions | UI markup, persistence |
|
|
37
|
-
| Domain | Rules, invariants | Framework imports where avoidable |
|
|
38
|
-
| Infrastructure | APIs, DB, adapters | Business decisions |
|
|
385
|
+
## Common Violations to Avoid
|
|
39
386
|
|
|
40
|
-
|
|
387
|
+
| Violation | Fix |
|
|
388
|
+
|-----------|-----|
|
|
389
|
+
| Fetch in component | Move to store action or dedicated hook that delegates to store |
|
|
390
|
+
| Duplicated constant | Centralize in `constants.ts`, schema, or config |
|
|
391
|
+
| Local state mirroring server data | Store owns it; derive in render |
|
|
392
|
+
| `className` on `DropdownPanel`, `IconButton`, etc. | Add/use variant prop on base |
|
|
393
|
+
| `#10b981` or `rgba(...)` in className | Use token class (`bg-indicator-high`, etc.) |
|
|
394
|
+
| Nested component in parent file | Extract to own file |
|
|
395
|
+
| Unvalidated API body | Add Zod schema + validateBody middleware |
|
|
396
|
+
| `console.log` in server code | Use structured logger |
|
|
397
|
+
| New user action without `track()` | Add to store action or handler |
|
|
398
|
+
| Ad-hoc boolean flags for multi-step flow | Explicit state machine (XState or `transition*` module) |
|
|
399
|
+
| `isLoading` / `isSaving` / `shouldRefetch` flag pile | Named machine states + transitions |
|
|
400
|
+
| Race guard / stale-response discard | Machine phase + generation token + explicit abort/complete events |
|
|
401
|
+
| useEffect-driven auto-mutations | Store action or machine effect from a valid transition |
|
|
402
|
+
| Appending to file over size budget | Extract to `server/lib/`, feature folder, or new openrouter module |
|
|
403
|
+
| 500-line modal/import component | Feature folder + hooks + step subcomponents |
|
|
404
|
+
| God route file with inline DB/LLM | Thin route + `server/lib/` workflow |
|
|
405
|
+
| Skipping Fallow after edit | Run `check_changed`; fix new violations |
|
|
41
406
|
|
|
42
407
|
---
|
|
43
408
|
|
|
44
|
-
##
|
|
409
|
+
## Related Skills
|
|
45
410
|
|
|
46
|
-
- [
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
- [ ] Tests appropriate to the change (unit for domain, integration for boundaries)
|
|
411
|
+
- **AAAC commands:** [docs/agentic_architecture.md](../../../../docs/agentic_architecture.md) — `/update-module`, `/create-feature`, `/fix-bug`, etc.; sync `domains/<slug>/update/inventory` after changes
|
|
412
|
+
- **Refactoring analysis (required when editing files >300 lines):** [.cursor/skills/shared/architecture/refactor-analysis.md](../architecture/refactor-analysis.md) via `/review-module`
|
|
413
|
+
- **Code health gate:** Fallow MCP `check_changed` after every implementation when Fallow is configured
|
|
414
|
+
- **MDA demos (marketing site):** [.cursor/skills/mda-director/SKILL.md](../../../mda-director/SKILL.md), [.cursor/skills/mda-scriptwriter/SKILL.md](../../../mda-scriptwriter/SKILL.md)
|
|
51
415
|
|
|
52
416
|
---
|
|
53
417
|
|
|
54
|
-
##
|
|
418
|
+
## References
|
|
55
419
|
|
|
56
|
-
|
|
420
|
+
- [docs/master_rules.md](../../../../docs/master_rules.md)
|
|
421
|
+
- [docs/architecture.md](../../../../docs/architecture.md)
|
|
422
|
+
- [docs/design_system.md](../../../../docs/design_system.md)
|
|
423
|
+
- [docs/design_components.md](../../../../docs/design_components.md)
|
|
424
|
+
- [docs/openrouter.md](../../../../docs/openrouter.md) — LLM adapter patterns (when touching AI features)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: shared-implementation-review
|
|
3
|
+
description: >-
|
|
4
|
+
Phase review_swarm — readonly agents review diff against docs and plan.
|
|
5
|
+
Independent from execute agent. Not user-facing.
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Implementation review (review_swarm phase)
|
|
10
|
+
|
|
11
|
+
## When
|
|
12
|
+
|
|
13
|
+
After `verify`, before `report`, on **create / update / fix / remove**.
|
|
14
|
+
|
|
15
|
+
**Hard rule:** The agent that ran `execute` must **not** perform this review — launch separate readonly Task subagents only.
|
|
16
|
+
|
|
17
|
+
## Swarm (mandatory)
|
|
18
|
+
|
|
19
|
+
Launch **3** parallel `Task` subagents (`explore`, `readonly: true`) in **one message**:
|
|
20
|
+
|
|
21
|
+
| Agent spec | Angle |
|
|
22
|
+
|------------|-------|
|
|
23
|
+
| [boundary-review.md](../../../agents/boundary-review.md) | Layer boundaries, fetch-in-UI, coupling |
|
|
24
|
+
| [doc-conformance.md](../../../agents/doc-conformance.md) | master_rules, policies, inventory |
|
|
25
|
+
| [implementation-review.md](../../../agents/implementation-review.md) | Plan scope, defects, budgets |
|
|
26
|
+
|
|
27
|
+
Every prompt **must** include [_task-prompt-policy.md](../_task-prompt-policy.md) plus: plan path, verify artifact, git diff summary or changed file list.
|
|
28
|
+
|
|
29
|
+
## Merge
|
|
30
|
+
|
|
31
|
+
Parent synthesizes Run `artifacts/review.yaml`:
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
findings:
|
|
35
|
+
- agent: boundary-review | doc-conformance | implementation-review
|
|
36
|
+
severity: critical | suggestion
|
|
37
|
+
finding: "<one line>"
|
|
38
|
+
evidence: "<path:line>"
|
|
39
|
+
blocking_critical: <count>
|
|
40
|
+
pass: true | false
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Fail
|
|
44
|
+
|
|
45
|
+
If `blocking_critical` > 0 → return to `execute` or `test_execute` to fix, then re-run verify + review_swarm. Do **not** advance to `report` with open critical findings.
|
|
46
|
+
|
|
47
|
+
## Replaces
|
|
48
|
+
|
|
49
|
+
Self-review checklist in [governance/implementation](../governance/implementation/SKILL.md) — independent review happens here, not in execute.
|
|
@@ -53,7 +53,7 @@ Launch **7 parallel** `Task` subagents in **one message**. `readonly: true` unle
|
|
|
53
53
|
| 6 | [fix-runtime-evidence.md](../../../agents/fix-runtime-evidence.md) | `generalPurpose` | CI/logs/MCP evidence |
|
|
54
54
|
| 7 | [fix-inventory-confirm.md](../../../agents/fix-inventory-confirm.md) | `explore` | Inventory scope + constraints |
|
|
55
55
|
|
|
56
|
-
**Parent prompt must include:** intent, domain, inventory path, discovery brief summary, frame fields.
|
|
56
|
+
**Parent prompt must include:** intent, domain, inventory path, discovery brief summary, frame fields, and the policy excerpt from [_task-prompt-policy.md](../_task-prompt-policy.md).
|
|
57
57
|
|
|
58
58
|
**Anti-patterns (hard fail):**
|
|
59
59
|
|
|
@@ -36,3 +36,5 @@ Pass output to [validation](../validation/SKILL.md). If any confidence below thr
|
|
|
36
36
|
## Agents
|
|
37
37
|
|
|
38
38
|
Reuse readonly specs: [discovery-inventory.md](../../../agents/discovery-inventory.md), [discovery-ssot.md](../../../agents/discovery-ssot.md), [dependency-analysis.md](../../../agents/dependency-analysis.md) — 2–3 parallel max for lite path.
|
|
39
|
+
|
|
40
|
+
Every Task prompt **must** include the policy excerpt from [_task-prompt-policy.md](../_task-prompt-policy.md).
|
|
@@ -66,6 +66,10 @@ rejected_alternatives:
|
|
|
66
66
|
complexity_score: <number>
|
|
67
67
|
rejected_because: "<no requirement / reuse suffices>"
|
|
68
68
|
paths_to_touch: ["<concrete file paths>"]
|
|
69
|
+
tests_to_add:
|
|
70
|
+
- behavior: "<from requirement_map>"
|
|
71
|
+
kind: unit | integration | e2e
|
|
72
|
+
target_path: "<test file path>"
|
|
69
73
|
rollback_notes: "<when protected/critical object>"
|
|
70
74
|
```
|
|
71
75
|
|
|
@@ -74,6 +78,7 @@ Also include:
|
|
|
74
78
|
- SSOT owner for new state
|
|
75
79
|
- Extract before add if any file ≥80% budget
|
|
76
80
|
- Named machine states/events **only** if user requirement demands async coordination
|
|
81
|
+
- **`tests_to_add[]`** — behaviors needing new tests (see [test-authoring](../test-authoring/SKILL.md)); empty array with reason when docs-only
|
|
77
82
|
|
|
78
83
|
## Complexity score
|
|
79
84
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: shared-test-authoring
|
|
3
|
+
description: >-
|
|
4
|
+
Phase test_execute — separate Task agent authors tests after execute.
|
|
5
|
+
Parent must not write test files. Not user-facing.
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Test authoring (test_execute phase)
|
|
10
|
+
|
|
11
|
+
## When
|
|
12
|
+
|
|
13
|
+
After `execute`, before `verify`, on **create / update / fix / remove** (mutating verbs).
|
|
14
|
+
|
|
15
|
+
**Hard rule:** Parent orchestrator must **not** Write/StrReplace test paths in `execute` — hooks deny them. Only `test_execute` phase (or test-author Task subagent in that phase) may author tests.
|
|
16
|
+
|
|
17
|
+
## Swarm (mandatory)
|
|
18
|
+
|
|
19
|
+
Launch **1** `Task` subagent in **one message**:
|
|
20
|
+
|
|
21
|
+
| Agent spec | `subagent_type` | Role |
|
|
22
|
+
|------------|-----------------|------|
|
|
23
|
+
| [test-author.md](../../../agents/test-author.md) | `generalPurpose` | Author tests from plan |
|
|
24
|
+
|
|
25
|
+
Every Task prompt **must** include [_task-prompt-policy.md](../_task-prompt-policy.md) plus: Run `artifacts/plan.yaml` path, list of files changed in execute, domain inventory test paths.
|
|
26
|
+
|
|
27
|
+
## Plan input
|
|
28
|
+
|
|
29
|
+
Run `artifacts.plan` must include:
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
tests_to_add:
|
|
33
|
+
- behavior: "<from requirement_map>"
|
|
34
|
+
kind: unit | integration | e2e
|
|
35
|
+
target_path: "<package test file path>"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If `tests_to_add` is empty and no tests are required, record on artifact:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
tests_to_add: []
|
|
42
|
+
skipped_reason: "<why no new tests — e.g. docs-only change>"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Store merged result on Run `artifacts/test_plan.yaml` before advancing.
|
|
46
|
+
|
|
47
|
+
## Output
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
files_written: ["<test paths>"]
|
|
51
|
+
behaviors_covered: ["<strings>"]
|
|
52
|
+
gaps: ["<untested behaviors>"]
|
|
53
|
+
author_agent: test-author
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Fail
|
|
57
|
+
|
|
58
|
+
Do not advance if tests were required by plan but `files_written` is empty.
|
|
@@ -12,21 +12,27 @@ disable-model-invocation: true
|
|
|
12
12
|
|
|
13
13
|
Phase `verify` (and `test_only` orchestrators). On **fix** paths, run fix verify swarm **before** declaring tests complete.
|
|
14
14
|
|
|
15
|
+
**Agent separation:** Test **authorship** happens in `test_execute` ([test-authoring](../test-authoring/SKILL.md)). This phase **runs** tests only — parent and subagents must not author new test files here.
|
|
16
|
+
|
|
15
17
|
## Standard steps
|
|
16
18
|
|
|
17
19
|
1. Run tests from domain inventory relevant to change
|
|
18
20
|
2. Invoke [unit-test-run.md](../../../agents/unit-test-run.md) pattern for targeted vitest
|
|
19
21
|
3. Fallow MCP → `check_changed` on touched files when configured
|
|
20
22
|
4. `ReadLints` on edited paths
|
|
21
|
-
5. **
|
|
23
|
+
5. **Website build gate (mandatory on create / update / fix):** before advancing `verify`, run:
|
|
22
24
|
```bash
|
|
23
25
|
node .cursor/aaac/scripts/run-engine/verify-website-build.mjs --run-id <run_id>
|
|
24
26
|
```
|
|
25
|
-
|
|
27
|
+
This checks `index.html` static asset paths resolve under `apps/website/public/` (or project root for Vite dev) and runs `pnpm --filter @ludecker/website build`. `advance-phase.mjs verify` **blocks** until this passes and writes `artifacts/verify.yaml`.
|
|
26
28
|
|
|
27
29
|
## Fix verify swarm (mandatory on fix verb / fix_mode)
|
|
28
30
|
|
|
29
|
-
After unit tests, launch **3 parallel** `Task` subagents in **one message
|
|
31
|
+
After unit tests, launch **3 parallel** `Task` subagents in **one message**. Each prompt **must** include [_task-prompt-policy.md](../_task-prompt-policy.md) and investigation artifact paths.
|
|
32
|
+
|
|
33
|
+
## Verify swarm (mandatory on all mutating verbs)
|
|
34
|
+
|
|
35
|
+
After `test_execute`, launch **3 parallel** `Task` subagents in **one message** (same roster as fix verify when on fix paths; on create/update use run + static checks):
|
|
30
36
|
|
|
31
37
|
| # | Agent spec | `subagent_type` | Role |
|
|
32
38
|
|---|------------|-----------------|------|
|
|
@@ -30,9 +30,11 @@ Lifecycle: graph `verb_runtime.create` (work + gates on Run)
|
|
|
30
30
|
9. **fitness_functions** — [fitness-functions](../../fitness-functions/SKILL.md)
|
|
31
31
|
10. **rollback** — [rollback](../../rollback/SKILL.md) when object maturity protected or impact high
|
|
32
32
|
11. **execute** — [execution](../../execution/SKILL.md) + object_skills + module-authoring when listed
|
|
33
|
-
12. **
|
|
34
|
-
13. **
|
|
35
|
-
14. **
|
|
33
|
+
12. **test_execute** — [test-authoring](../../test-authoring/SKILL.md) — **1** test-author Task agent; parent must not write tests
|
|
34
|
+
13. **verify** — [testing](../../testing/SKILL.md) + [verification](../../verification/SKILL.md) — **3** verify subagents (all mutating verbs)
|
|
35
|
+
14. **review_swarm** — [implementation-review](../../implementation-review/SKILL.md) — **3** readonly reviewers; block on critical findings
|
|
36
|
+
15. **sync_inventory** — when domain inventory exists and execute ran
|
|
37
|
+
16. **report** — [reporting](../../reporting/SKILL.md)
|
|
36
38
|
|
|
37
39
|
Domain slugs with graph resolver use domain orchestrator instead (e.g. `create-feature` → `create-feature-by-slug`).
|
|
38
40
|
|