compound-workflow 1.7.3 → 1.9.0

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.
Files changed (92) hide show
  1. package/README.md +61 -69
  2. package/package.json +2 -8
  3. package/scripts/check-pack-readme.mjs +1 -16
  4. package/scripts/check-workflow-contracts.mjs +34 -44
  5. package/scripts/install-cli.mjs +273 -417
  6. package/src/AGENTS.md +59 -192
  7. package/src/{.agents/agents → agents}/research/best-practices-researcher.md +2 -2
  8. package/src/{.agents/commands → commands}/assess.md +4 -4
  9. package/src/commands/install.md +43 -0
  10. package/src/{.agents/commands → commands}/metrics.md +1 -1
  11. package/src/commands/workflow-agents.md +101 -0
  12. package/src/{.agents/commands → commands}/workflow-compound.md +1 -1
  13. package/src/{.agents/commands → commands}/workflow-plan.md +24 -33
  14. package/src/commands/workflow-work.md +836 -0
  15. package/src/{.agents/references → references}/README.md +1 -1
  16. package/src/{.agents/skills → skills}/capture-skill/SKILL.md +1 -1
  17. package/src/{.agents/skills → skills}/compound-docs/SKILL.md +6 -6
  18. package/src/{.agents/skills → skills}/compound-docs/references/yaml-schema.md +2 -2
  19. package/src/skills/setup-agents/SKILL.md +250 -0
  20. package/src/skills/standards/SKILL.md +79 -0
  21. package/src/skills/standards/references/architecture.md +228 -0
  22. package/src/skills/standards/references/code-quality.md +192 -0
  23. package/src/skills/standards/references/presentation.md +515 -0
  24. package/src/skills/standards/references/services.md +172 -0
  25. package/src/skills/standards/references/state-management.md +936 -0
  26. package/.claude-plugin/plugin.json +0 -7
  27. package/.cursor-plugin/plugin.json +0 -20
  28. package/.cursor-plugin/registration.json +0 -5
  29. package/scripts/check-version-parity.mjs +0 -36
  30. package/scripts/generate-platform-artifacts.mjs +0 -230
  31. package/src/.agents/commands/install.md +0 -51
  32. package/src/.agents/commands/workflow-work.md +0 -690
  33. package/src/.agents/registry.json +0 -48
  34. package/src/.agents/scripts/self-check.mjs +0 -227
  35. package/src/.agents/scripts/sync-opencode.mjs +0 -362
  36. package/src/.agents/skills/presentation-composability/SKILL.md +0 -72
  37. package/src/.agents/skills/react-ddd-mvc-frontend/SKILL.md +0 -51
  38. package/src/.agents/skills/react-ddd-mvc-frontend/references/feature-structure.md +0 -25
  39. package/src/.agents/skills/react-ddd-mvc-frontend/references/implementation-principles.md +0 -21
  40. package/src/.agents/skills/react-ddd-mvc-frontend/references/responsibility-gates.md +0 -41
  41. package/src/.agents/skills/react-ddd-mvc-frontend/references/source-map.md +0 -11
  42. package/src/.agents/skills/standards/SKILL.md +0 -747
  43. package/src/.agents/skills/xstate-actor-orchestration/SKILL.md +0 -197
  44. package/src/.agents/skills/xstate-actor-orchestration/agents/openai.yaml +0 -4
  45. package/src/.agents/skills/xstate-actor-orchestration/assets/statecharts/.gitkeep +0 -0
  46. package/src/.agents/skills/xstate-actor-orchestration/references/actor-system-patterns.md +0 -71
  47. package/src/.agents/skills/xstate-actor-orchestration/references/event-contracts.md +0 -73
  48. package/src/.agents/skills/xstate-actor-orchestration/references/functional-domain-patterns.md +0 -53
  49. package/src/.agents/skills/xstate-actor-orchestration/references/machine-structure-and-tags.md +0 -36
  50. package/src/.agents/skills/xstate-actor-orchestration/references/react-container-pattern.md +0 -45
  51. package/src/.agents/skills/xstate-actor-orchestration/references/reliability-observability.md +0 -39
  52. package/src/.agents/skills/xstate-actor-orchestration/references/skill-validation.md +0 -33
  53. package/src/.agents/skills/xstate-actor-orchestration/references/source-map.md +0 -44
  54. package/src/.agents/skills/xstate-actor-orchestration/references/statechart-review-and-signoff.md +0 -59
  55. package/src/.agents/skills/xstate-actor-orchestration/references/testing-strategy.md +0 -35
  56. package/src/.agents/skills/xstate-actor-orchestration/scripts/create-statechart-artifact.sh +0 -71
  57. package/src/.agents/skills/xstate-actor-orchestration/scripts/validate-skill.sh +0 -138
  58. package/src/generated/opencode.managed.json +0 -115
  59. /package/src/{.agents/agents → agents}/research/framework-docs-researcher.md +0 -0
  60. /package/src/{.agents/agents → agents}/research/git-history-analyzer.md +0 -0
  61. /package/src/{.agents/agents → agents}/research/learnings-researcher.md +0 -0
  62. /package/src/{.agents/agents → agents}/research/repo-research-analyst.md +0 -0
  63. /package/src/{.agents/agents → agents}/review/agent-native-reviewer.md +0 -0
  64. /package/src/{.agents/agents → agents}/review/planning-technical-reviewer.md +0 -0
  65. /package/src/{.agents/agents → agents}/workflow/bug-reproduction-validator.md +0 -0
  66. /package/src/{.agents/agents → agents}/workflow/lint.md +0 -0
  67. /package/src/{.agents/agents → agents}/workflow/spec-flow-analyzer.md +0 -0
  68. /package/src/{.agents/commands → commands}/test-browser.md +0 -0
  69. /package/src/{.agents/commands → commands}/workflow-brainstorm.md +0 -0
  70. /package/src/{.agents/commands → commands}/workflow-review.md +0 -0
  71. /package/src/{.agents/commands → commands}/workflow-tech-review.md +0 -0
  72. /package/src/{.agents/commands → commands}/workflow-triage.md +0 -0
  73. /package/src/{.agents/references → references}/standards/README.md +0 -0
  74. /package/src/{.agents/skills → skills}/agent-browser/SKILL.md +0 -0
  75. /package/src/{.agents/skills → skills}/audit-traceability/SKILL.md +0 -0
  76. /package/src/{.agents/skills → skills}/brainstorming/SKILL.md +0 -0
  77. /package/src/{.agents/skills → skills}/compound-docs/assets/critical-pattern-template.md +0 -0
  78. /package/src/{.agents/skills → skills}/compound-docs/assets/resolution-template.md +0 -0
  79. /package/src/{.agents/skills → skills}/compound-docs/schema.project.yaml +0 -0
  80. /package/src/{.agents/skills → skills}/compound-docs/schema.yaml +0 -0
  81. /package/src/{.agents/skills → skills}/data-foundations/SKILL.md +0 -0
  82. /package/src/{.agents/skills → skills}/document-review/SKILL.md +0 -0
  83. /package/src/{.agents/skills → skills}/file-todos/SKILL.md +0 -0
  84. /package/src/{.agents/skills → skills}/file-todos/assets/todo-template.md +0 -0
  85. /package/src/{.agents/skills → skills}/financial-workflow-integrity/SKILL.md +0 -0
  86. /package/src/{.agents/skills → skills}/git-worktree/SKILL.md +0 -0
  87. /package/src/{.agents/skills → skills}/pii-protection-prisma/SKILL.md +0 -0
  88. /package/src/{.agents/skills → skills}/process-metrics/SKILL.md +0 -0
  89. /package/src/{.agents/skills → skills}/process-metrics/assets/daily-template.md +0 -0
  90. /package/src/{.agents/skills → skills}/process-metrics/assets/monthly-template.md +0 -0
  91. /package/src/{.agents/skills → skills}/process-metrics/assets/weekly-template.md +0 -0
  92. /package/src/{.agents/skills → skills}/technical-review/SKILL.md +0 -0
@@ -9,4 +9,4 @@ Rules of thumb:
9
9
 
10
10
  Indexing:
11
11
 
12
- - Link relevant reference docs from `src/AGENTS.md` (Skill Index) or from the owning skill under `src/.agents/skills/`.
12
+ - Link relevant reference docs from `src/AGENTS.md` (Skill Index) or from the owning skill under `src/skills/`.
@@ -12,7 +12,7 @@ This skill extracts reusable knowledge from the current conversation and stores
12
12
  `capture-skill` uses an overlay model by default:
13
13
 
14
14
  - Treat existing repo-provided skills as immutable unless the user explicitly asks to edit a specific one.
15
- - Store project-specific refinements in a project overlay skill (for example, `.agents/skills/project-standards/`).
15
+ - Store project-specific refinements in a project overlay skill (for example, a `project-standards/` skill in the current harness skills directory — resolve from `harnesses` in AGENTS.md Repo Config).
16
16
  - Only modify an existing skill when the user clearly says to do so (for example, "update skill X").
17
17
  - Promote overlay content into base skills only as an explicit, deliberate follow-up action.
18
18
 
@@ -153,8 +153,8 @@ Format: `YYYY-MM-DD-<module-slug>-<symptom-slug>.md`
153
153
 
154
154
  **Validate against schema:**
155
155
 
156
- 1. Load `.agents/skills/compound-docs/schema.yaml`.
157
- 2. If `.agents/skills/compound-docs/schema.project.yaml` exists, validate against it as the repo-specific overlay.
156
+ 1. Load `schema.yaml` from the same directory as this skill file.
157
+ 2. If `schema.project.yaml` exists in the same directory, validate against it as the repo-specific overlay.
158
158
  3. Use [yaml-schema.md](./references/yaml-schema.md) as the human-readable reference.
159
159
 
160
160
  Ensure all required fields are present and match allowed values exactly for enum fields.
@@ -335,8 +335,8 @@ Action:
335
335
 
336
336
  Example:
337
337
 
338
- - Add to `.agents/skills/<skill-name>/references/resources.md` under "Project-Specific Resources" (if it exists)
339
- - Add to `.agents/skills/<skill-name>/references/examples.md` with a link to the solution doc (if it exists)
338
+ - Add to `<skill-name>/references/resources.md` in the current harness skills directory (resolve from `harnesses` in AGENTS.md Repo Config) under "Project-Specific Resources" (if it exists)
339
+ - Add to `<skill-name>/references/examples.md` in the current harness skills directory with a link to the solution doc (if it exists)
340
340
 
341
341
  **Option 6: Create new skill**
342
342
 
@@ -344,8 +344,8 @@ User selects this when the solution represents the start of a new learning domai
344
344
 
345
345
  Action:
346
346
  1. Prompt: "What should the new skill be called? (e.g., stripe-billing, email-processing)"
347
- 2. Create a new skill directory: `.agents/skills/<skill-name>/`
348
- 3. Add `.agents/skills/<skill-name>/SKILL.md` with a clear description (what + when to use)
347
+ 2. Create a new skill directory: `<skill-name>/` in the skills directory of the current harness (resolve from `harnesses` in AGENTS.md Repo Config)
348
+ 3. Add `SKILL.md` in the new skill directory with a clear description (what + when to use)
349
349
  4. Create initial reference files (optional) and add this solution doc as the first example
350
350
  5. Confirm: "✓ Created new <skill-name> skill with this solution as first example"
351
351
 
@@ -1,8 +1,8 @@
1
1
  # YAML Frontmatter Schema
2
2
 
3
- **See `.agents/skills/compound-docs/schema.yaml` for the core portable schema specification.**
3
+ **See `schema.yaml` in the same directory as this skill for the core portable schema specification.**
4
4
 
5
- If present, `.agents/skills/compound-docs/schema.project.yaml` acts as an optional repo-specific overlay for stricter enums.
5
+ If present, `schema.project.yaml` in the same directory acts as an optional repo-specific overlay for stricter enums.
6
6
 
7
7
  ## Required Fields
8
8
 
@@ -0,0 +1,250 @@
1
+ ---
2
+ name: setup-agents
3
+ description: Create or update AGENTS.md for any project. Detects project stack and installed harness directories, prompts for missing config, curates the Skill Index from installed skills, and writes a clean minimal AGENTS.md. Use when onboarding a new project or refreshing an existing config.
4
+ triggers:
5
+ - setting up a new project
6
+ - initialising AGENTS.md for the first time
7
+ - updating or refreshing an existing AGENTS.md
8
+ - onboarding a new repo to the workflow
9
+ ---
10
+
11
+ # Setup AGENTS.md
12
+
13
+ <!-- Structural source of truth for AGENTS.md format. The default template shipped in
14
+ src/AGENTS.md is a populated instance of the Phase 4 template below.
15
+ When changing the template here, update src/AGENTS.md to match (and vice versa). -->
16
+
17
+ Create or update a minimal, authoritative `AGENTS.md` for any project.
18
+
19
+ ## Mode Detection
20
+
21
+ Before doing anything, check whether `AGENTS.md` exists in the repo root.
22
+
23
+ - **If it does not exist:** run in `init` mode — build from scratch.
24
+ - **If it exists:** run in `update` mode — read the current file, preserve what is correct, update what is stale, and prompt for anything missing.
25
+
26
+ Announce the mode before proceeding.
27
+
28
+ ---
29
+
30
+ ## Phase 1: Detect Harness Directories and Project Stack
31
+
32
+ ### Harness detection
33
+
34
+ Check which directories exist at the project root. Do not assume any are present — record only what is actually found on disk.
35
+
36
+ Known harness patterns to check: directories named `.agents`, `.claude`, `.cursor`. Check all three; others may exist.
37
+
38
+ For each found harness, note where its skills live:
39
+ - `<harness>/skills/` — if that subdirectory exists
40
+ - `.claude/` has no skills directory (agents only, in `.claude/agents/`)
41
+
42
+ Record detected harnesses as `$harnesses` (ordered list of directories found). This will be written to AGENTS.md.
43
+
44
+ If **no harness directories exist**, stop and tell the user:
45
+ > No harness directories found. Run `npx compound-workflow install` first, then re-run this skill.
46
+
47
+ Use the **first found skills directory** across `$harnesses` as the canonical source for skill discovery in Phase 3. Record this as `$skills_dir`.
48
+
49
+ > **Note:** `harnesses` in AGENTS.md Repo Config may become stale if harness directories are added or removed. Re-run `/setup-agents` to refresh it.
50
+
51
+ ### Project stack detection
52
+
53
+ Read the following files if they exist (do not error if missing):
54
+
55
+ - `package.json` (scripts, dependencies, devDependencies)
56
+ - `vite.config.ts` / `vite.config.js`
57
+ - `tsconfig.json`
58
+ - `.eslintrc.*` / `eslint.config.*`
59
+ - `vitest.config.ts` / `jest.config.*`
60
+ - `turbo.json` / `nx.json` (monorepo signals)
61
+
62
+ From these, infer:
63
+
64
+ | Config key | Detection signal |
65
+ | --- | --- |
66
+ | `test_command` | `scripts.test` in package.json; vitest/jest config presence |
67
+ | `test_fast_command` | `scripts.test:fast`, `scripts.test:watch`, or vitest equivalent |
68
+ | `lint_command` | `scripts.lint` in package.json; eslint config presence |
69
+ | `typecheck_command` | `scripts.typecheck` or `scripts.type-check`; tsconfig presence |
70
+ | `format_command` | `scripts.format` in package.json; prettier config presence |
71
+ | `dev_server_url` | vite config `server.port`; default `http://localhost:5173` for Vite, `http://localhost:3000` for others |
72
+ | `worktree_install_command` | `package-lock.json` → `npm ci`; `yarn.lock` → `yarn install`; `pnpm-lock.yaml` → `pnpm install` |
73
+
74
+ For each value, state whether it was detected or assumed.
75
+
76
+ ---
77
+
78
+ ## Phase 2: Prompt for Missing or Undetectable Values
79
+
80
+ Ask for any values that could not be detected. Ask one at a time.
81
+
82
+ Required:
83
+
84
+ - `default_branch` — cannot be reliably detected; ask (suggest `main`)
85
+ - `project_tracker` — ask: `github`, `linear`, or none
86
+ - `dev_server_url` — confirm detected value or ask
87
+ - `worktree_dir` — suggest `.worktrees`
88
+ - `worktree_copy_files` — ask which env/config files should be copied into new worktrees (e.g. `.env.local`)
89
+ - `harnesses` — show detected list from Phase 1; confirm or correct
90
+
91
+ **Update mode only:** Show the current values and ask: "These values are already configured — confirm, update, or skip each?"
92
+
93
+ ---
94
+
95
+ ## Phase 3: Curate the Skill Index
96
+
97
+ List all directories under `$skills_dir` (resolved in Phase 1). For each one, read `SKILL.md` frontmatter to get `name` and `description`. These are the only skills that may appear in the Skill Index — never reference a skill not present on disk.
98
+
99
+ Present the full discovered list to the user as a numbered menu:
100
+
101
+ ```
102
+ Installed skills (from <$skills_dir>):
103
+ 1. <name> — <description from frontmatter>
104
+ 2. <name> — <description from frontmatter>
105
+ ...
106
+
107
+ Which should appear in the Skill Index? (Enter numbers, or "all", or "all except N,N")
108
+ ```
109
+
110
+ **Init mode:** Ask which to include.
111
+ **Update mode:** Show which are currently included and ask: "Keep, remove, or any to add?"
112
+
113
+ Do not categorise skills in advance — the user decides what is relevant for their project.
114
+
115
+ ---
116
+
117
+ ## Phase 4: Write AGENTS.md
118
+
119
+ Using all resolved values, write a clean `AGENTS.md` following this exact template.
120
+
121
+ **Init mode:** write the full file.
122
+ **Update mode:** preserve any sections the user confirmed as correct; replace only what changed.
123
+
124
+ ```markdown
125
+ # Agent Operating Principles
126
+
127
+ This workspace is portable and command-first.
128
+
129
+ ## Core Principles
130
+
131
+ 1. Commands are the public API. Skills and agents are composable internals.
132
+ 2. Core workflows stay generic. Domain-specific behavior loads only when context requires it.
133
+ 3. Planning quality is explicit via fidelity selection.
134
+ 4. Selection must be deterministic and visible: always state which skills/agents were selected and why.
135
+ 5. Brainstorm and plan do not write code.
136
+
137
+ ## Contract Precedence
138
+
139
+ If workflow documents conflict, resolve in this order:
140
+
141
+ 1. `docs/principles/workflow-baseline-principles.md`
142
+ 2. This file — non-negotiables and repo config
143
+ 3. Workflow command specs
144
+ 4. Skill docs
145
+
146
+ ## Canonical Workflow
147
+
148
+ 1. `/workflow:brainstorm` — clarify what to build
149
+ 2. `/workflow:plan` — define how to build it
150
+ 3. `/workflow:work` — implement (includes triage gate)
151
+ 4. `/workflow:review` — validate quality
152
+ 5. `/workflow:compound` — capture durable learnings
153
+
154
+ Optional:
155
+
156
+ - `/workflow:triage` — manually curate/prioritize queue before execution
157
+ - `/workflow:tech-review` — technical correctness check on a plan before build
158
+
159
+ Continuous improvement:
160
+
161
+ - `/metrics` — log + assess a session
162
+ - `/assess` — aggregate metrics and propose improvements
163
+
164
+ ## Non-negotiables (Structure Integrity)
165
+
166
+ - **Commands are the public API.** Keep `/workflow:*` command docs stable; add capability via skills/agents, not new command variants.
167
+ - **Brainstorm = WHAT, Plan = HOW.** `/workflow:plan` must not re-litigate decisions already captured in `docs/brainstorms/`.
168
+ - **Local grounding is mandatory.** Every plan must cite at least 1–3 internal file path/line refs and any relevant `docs/solutions/**` learnings.
169
+ - **Fidelity + confidence are required declarations** in every plan file.
170
+ - **Solution scope contract is mandatory in every plan.** Plans must declare `solution_scope` (`partial_fix|full_remediation|migration`) plus completion expectation and non-goals.
171
+ - **Isolation preflight is a hard gate.** `/workflow:work` must complete and record worktree/isolation preflight before any implementation commands.
172
+ - **Triage before execution is mandatory.** `/workflow:work` must run a triage pass before executing todos.
173
+ - **Independent review is required for code/config changes.** `/workflow:review` must emit `review_independence_mode: independent|degraded`.
174
+ - **Standards baseline is mandatory for code/config changes.** `/workflow:work` and `/workflow:review` must apply `skill: standards` as a hard gate.
175
+ - **Todo completion requires evidence.** A todo may move to `complete` only after success criteria and quality gate evidence are recorded.
176
+ - **No ad-hoc artifacts outside canonical outputs** (`docs/plans`, `todos`, `docs/solutions`, `docs/metrics`) unless explicitly requested.
177
+
178
+ ## Planning Fidelity Model
179
+
180
+ `/workflow:plan` must always declare: `Fidelity`, `Confidence`, `solution_scope`, rationale, research mode, and open questions.
181
+
182
+ - **Low** — problem, constraints, acceptance criteria, implementation outline, verification checklist.
183
+ - **Medium** — all Low + alternatives/tradeoffs, dependency/risk table, rollout notes, observability/test notes.
184
+ - **High** — all Medium + failure modes, rollback plan, deployment gates, migration/data safety checks, expanded test matrix.
185
+
186
+ Select `High` if any high-risk trigger exists (security, payments, privacy, data migration, production infra). Default to `Medium` for mixed signals. Otherwise `Low`.
187
+
188
+ ## Routing Rules
189
+
190
+ - **Centralized skill routing:** Add new domain/reference skill routing in this file (Skill Index) rather than per-command.
191
+ - **Default selection order:** (1) safety/guardrail standards, (2) domain architecture/reference skills, (3) workflow execution skills. Minimal set that covers the problem.
192
+ - **Explain selection:** Always state which skills were selected and why.
193
+ - Run local repo + institutional learnings research first for planning. External research based on fidelity and risk.
194
+
195
+ ## Repo Config Block
196
+
197
+ \`\`\`yaml
198
+ default_branch: <value>
199
+ project_tracker: <github|linear|none>
200
+ dev_server_url: <value>
201
+ test_command: <value>
202
+ test_fast_command: <value or omit>
203
+ lint_command: <value or omit>
204
+ typecheck_command: <value or omit>
205
+ format_command: <value or omit>
206
+ worktree_dir: <value>
207
+ worktree_install_command: <value>
208
+ worktree_copy_files:
209
+ - <file1>
210
+ harnesses:
211
+ - <detected harness dir 1>
212
+ \`\`\`
213
+
214
+ ## Skill Index
215
+
216
+ | Skill | Use when |
217
+ | --- | --- |
218
+ [... one row per skill the user selected in Phase 3; use the description from each skill's SKILL.md frontmatter ...]
219
+ ```
220
+
221
+ Confirm: "AGENTS.md written."
222
+
223
+ ---
224
+
225
+ ## Phase 5: Validation
226
+
227
+ After writing, verify:
228
+
229
+ - [ ] All required Repo Config Block keys are present and non-empty
230
+ - [ ] `harnesses` lists only directories detected on disk in Phase 1 — no invented entries
231
+ - [ ] Every skill in the Skill Index was discovered from `$skills_dir` — no invented entries
232
+ - [ ] All skill descriptions come from `SKILL.md` frontmatter — none invented by the agent
233
+ - [ ] No hardcoded tool, platform, or directory names
234
+ - [ ] File is under 130 lines
235
+
236
+ If any check fails, fix before confirming completion.
237
+
238
+ ---
239
+
240
+ ## Rules
241
+
242
+ - Never add sections beyond what the template defines — keep it minimal
243
+ - Never hardcode skill names — discover everything from the detected skills directory
244
+ - Never hardcode harness paths — detect what exists on disk first; `harnesses` in AGENTS.md reflects reality, not assumptions
245
+ - Never invent skill descriptions — always read from the skill's `SKILL.md` frontmatter
246
+ - Never hardcode tool or platform names
247
+ - Never duplicate content that lives in command or skill docs
248
+ - In update mode, never silently overwrite values the user confirmed as correct
249
+ - If a detected value looks wrong, surface it and ask — do not assume
250
+ - When the Phase 4 template changes, update `src/AGENTS.md` to match (it is the populated default instance)
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: standards
3
+ description: >
4
+ Enforce frontend code standards when writing, reviewing, or refactoring frontend code.
5
+ Use this skill for all frontend work — new features, PR reviews, refactors,
6
+ component creation, or any code quality assessment. This skill defines mandatory pass/fail gates.
7
+ If the user is writing, reading, or evaluating frontend code in any form, use this skill
8
+ immediately — do not rely on general knowledge.
9
+ ---
10
+
11
+ # Frontend Standards
12
+
13
+ Five themes apply to all frontend work. All must be satisfied.
14
+
15
+ | Theme | Concern |
16
+ |---|---|
17
+ | **Architecture** | Layered model, layer boundaries, data flow direction |
18
+ | **Code Quality** | Control flow, immutability, error handling |
19
+ | **Services** | IO boundary, Effect Layer structure, runtime composition |
20
+ | **State Management** | Controller responsibilities, state and event contracts |
21
+ | **Presentation** | Component structure, composition patterns, visual conventions |
22
+
23
+ ---
24
+
25
+ ## When to Load Reference Files
26
+
27
+ Load the relevant reference before reviewing or writing code in that area.
28
+
29
+ | Situation | Load |
30
+ |---|---|
31
+ | Layer structure, boundaries, or data flow | `references/architecture.md` |
32
+ | Control flow, error handling, or data transforms | `references/code-quality.md` |
33
+ | Effect services, Layers, or runtime composition | `references/services.md` |
34
+ | State machines, events, context, or actor patterns | `references/state-management.md` |
35
+ | Component structure or visual conventions | `references/presentation.md` |
36
+ | Full review or uncertainty about which layer applies | All five |
37
+
38
+ ---
39
+
40
+ ## Mandatory Gates
41
+
42
+ Each is **pass/fail**. A single `fail` means the work is incomplete.
43
+
44
+ | Gate | Theme | Rule |
45
+ |---|---|---|
46
+ | `architecture` | Architecture | All layers honour their boundaries — no layer reaches past its neighbour |
47
+ | `code_quality` | Code Quality | Control flow is flat, transforms are immutable, errors are handled explicitly |
48
+ | `services` | Services | All IO is isolated to the service layer — no IO in entities, controllers, or containers |
49
+ | `state_management` | State Management | Controllers own state; containers extract values and callbacks — never pass raw machine internals to components |
50
+ | `presentation` | Presentation | Components follow the folder, composition, and visual conventions |
51
+
52
+ ---
53
+
54
+ ## Required Evidence Format
55
+
56
+ Record in all work outputs and code reviews:
57
+
58
+ ```markdown
59
+ standards_compliance:
60
+ - architecture: pass|fail (evidence: file:line)
61
+ - code_quality: pass|fail (evidence: file:line)
62
+ - services: pass|fail (evidence: file:line)
63
+ - state_management: pass|fail (evidence: file:line)
64
+ - presentation: pass|fail (evidence: file:line)
65
+ ```
66
+
67
+ On any `fail`: load the relevant reference file, surface the specific violation with evidence, explain the rule broken, and show the corrected pattern. List **all** failures before summarising — do not stop at the first.
68
+
69
+ ---
70
+
71
+ ## Reference Files
72
+
73
+ | File | Theme | Contents |
74
+ |---|---|---|
75
+ | `references/architecture.md` | Architecture | Layered model, layer responsibilities, file structure, import rules |
76
+ | `references/code-quality.md` | Code Quality | Control flow, immutability, error handling, validation boundary |
77
+ | `references/services.md` | Services | Effect Layer pattern, service structure, runtime composition |
78
+ | `references/state-management.md` | State Management | XState v5 patterns, events, guards, actions, actor communication |
79
+ | `references/presentation.md` | Presentation | Folder structure, compound components, barrel pattern, visual conventions |
@@ -0,0 +1,228 @@
1
+ # Architecture Reference
2
+
3
+ ## The Layered Model
4
+
5
+ All frontend code follows a strict five-layer architecture. Data flows in one direction. Layers do not skip.
6
+
7
+ ```
8
+ Entities (pure functions — transforms and predicates)
9
+ ↓ consumed by
10
+ Services (Effect Layers — all IO and side effects)
11
+ ↓ consumed by
12
+ Controllers (XState machines — own state and transitions)
13
+ ↓ consumed by
14
+ Containers (composition layer — wire state to UI)
15
+ ↓ consumed by
16
+ Presentation (UI only)
17
+ ```
18
+
19
+ Each layer has a single responsibility. No layer reaches past its neighbour.
20
+
21
+ ---
22
+
23
+ ## Layer Responsibilities
24
+
25
+ ### Entities
26
+
27
+ Location: `src/features/{feature}/domain/entities/`
28
+
29
+ Entities are pure functions. They have no knowledge of state machines, services, React, or the UI. They do two things:
30
+
31
+ 1. **Transforms** — `toX` functions, input → output, inbound and outbound data shaping
32
+ 2. **Predicates** — `hasX`, `isX` functions, inferring facts from data
33
+
34
+ Entities are the data boundary for backend responses — they apply defaults and ensure correct shape as part of the transform. They may use Effect's typed utilities (`Effect.try`, `Option`, `Either`) for safe transforms, but must remain pure. No runtime, no Layer dependencies.
35
+
36
+ **Rules:**
37
+ - Pure functions only — no side effects, no framework imports, no IO
38
+ - No classes — functions only
39
+ - One file per concern (`PlaylistSelectionEntity.ts` vs `PlaylistReorderEntity.ts`)
40
+ - Private helpers stay internal — no `export`
41
+
42
+ **Naming conventions:**
43
+
44
+ | Prefix | Purpose | Example |
45
+ |---|---|---|
46
+ | `hasX` | Boolean predicate | `hasAddedPlaylists` |
47
+ | `isX` | Boolean predicate | `isValidState` |
48
+ | `getX` | Retrieve/extract | `getAddedPlaylists` |
49
+ | `toX` | Transform | `toPlaylistIds` |
50
+
51
+ **Function signatures** — use object params for 2+ arguments:
52
+
53
+ ```typescript
54
+ export const hasAddedPlaylists = ({
55
+ current,
56
+ incoming,
57
+ }: {
58
+ current: InputOption[];
59
+ incoming: InputOption[];
60
+ }): boolean => { ... };
61
+ ```
62
+
63
+ **Imports** — import as namespace:
64
+
65
+ ```typescript
66
+ import * as playlistSelectionEntity from "src/features/{feature}/domain/entities/PlaylistSelectionEntity";
67
+ playlistSelectionEntity.hasAddedPlaylists({ ... });
68
+ ```
69
+
70
+ ---
71
+
72
+ ### Services
73
+
74
+ Location: `src/features/{feature}/infrastructure/services/`
75
+
76
+ Services own all IO and side effects. Controllers call services — they never perform IO directly.
77
+
78
+ See `references/services.md` for the full Effect Layer pattern, service structure, and runtime composition.
79
+
80
+ ---
81
+
82
+ ### Controllers
83
+
84
+ Location: `src/features/{feature}/application/controllers/`
85
+
86
+ Controllers own state and transitions. They delegate transforms and predicates to entities, and IO to services via the injected runtime.
87
+
88
+ See `references/state-management.md` for the full XState v5 pattern.
89
+
90
+ ---
91
+
92
+ ### Containers
93
+
94
+ Location: `src/features/{feature}/application/containers/`
95
+
96
+ Containers are the composition layer. Three responsibilities:
97
+
98
+ 1. **Map state** from the controller via `useSelector` and tags
99
+ 2. **Forward events** to the controller — unconditionally
100
+ 3. **Compose** hooks, translations, and presentation components
101
+
102
+ **Rules:**
103
+ - One container per controller
104
+ - No logic — no transforms, no business rules
105
+ - No conditionals around events — forward unconditionally, let the controller decide
106
+ - Targeted `useSelector` — select only what this container needs
107
+ - Never pass `send` or raw `snapshot` to presentation components — extract values and create specific callbacks
108
+
109
+ ```typescript
110
+ // ❌ Bad — leaks machine internals into presentation
111
+ <Sidebar snapshot={snapshot} send={send} />
112
+
113
+ // ✅ Good — extract values, create specific callbacks
114
+ const { sidebarCollapsed, currentRoute } = snapshot.context;
115
+ const handleToggleSidebar = useCallback(() => send({ type: 'TOGGLE_SIDEBAR' }), [send]);
116
+
117
+ <Sidebar collapsed={sidebarCollapsed} onToggle={handleToggleSidebar} currentRoute={currentRoute} />
118
+ ```
119
+
120
+ **Folder naming:** The container folder name must match the exported component name **exactly**, including any suffix (e.g. `Container`). Never shorten the folder name.
121
+
122
+ ```
123
+ application/containers/
124
+ AuthGuardContainer/ ← exports AuthGuardContainer ✅
125
+ GlobalLoaderContainer/ ← exports GlobalLoaderContainer ✅
126
+
127
+ AuthGuard/ ← exports AuthGuardContainer ❌ (name mismatch)
128
+ ```
129
+
130
+ This keeps the folder path and the import name in sync — reading either one tells you the other without opening the file.
131
+
132
+ ```typescript
133
+ // ✅ Forwards unconditionally
134
+ const onAction = useCallback(() => {
135
+ actor.send({ type: "playlist.action" });
136
+ }, [actor]);
137
+
138
+ // ❌ Container deciding — belongs in the controller
139
+ const onAction = useCallback(() => {
140
+ if (isEditing) actor.send({ type: "playlist.save" });
141
+ else actor.send({ type: "playlist.cancel" });
142
+ }, [actor, isEditing]);
143
+ ```
144
+
145
+ ---
146
+
147
+ ### Presentation
148
+
149
+ Location: `src/features/{feature}/presentation/`
150
+
151
+ Presentation components are UI only. They receive props and render. No state machines, no services, no business logic.
152
+
153
+ See `references/presentation.md` for folder structure and composition rules.
154
+
155
+ ---
156
+
157
+ ## File Structure
158
+
159
+ ```
160
+ src/
161
+ ├── effects.ts # App runtime — composed once here
162
+ └── features/{feature}/
163
+ ├── application/
164
+ │ ├── containers/ # Composition layer
165
+ │ └── controllers/ # State machines
166
+ ├── domain/
167
+ │ └── entities/ # Pure functions
168
+ ├── infrastructure/
169
+ │ └── services/ # Effect Layers — all IO
170
+ │ ├── PlaylistService.ts
171
+ │ ├── FolderService.ts
172
+ │ └── index.ts # Feature layer composition
173
+ ├── presentation/ # UI components
174
+ └── types.ts # Public events (create only when needed)
175
+ ```
176
+
177
+ **Import paths** — use absolute paths from `src/`:
178
+
179
+ ```typescript
180
+ import * as playlistSelectionEntity from "src/features/{feature}/domain/entities/PlaylistSelectionEntity";
181
+ ```
182
+
183
+ Relative paths are acceptable within the same feature for deeply nested files.
184
+
185
+ ---
186
+
187
+ ## Quick Check — Common Violations
188
+
189
+ **Logic in a container:**
190
+ ```typescript
191
+ // ❌ Container deciding
192
+ if (isEditing) actor.send({ type: "playlist.save" });
193
+
194
+ // ✅ Controller decides — container forwards
195
+ actor.send({ type: "playlist.action", payload: { isEditing } });
196
+ ```
197
+
198
+ **Side effect in an entity:**
199
+ ```typescript
200
+ // ❌ Entity performing IO
201
+ export const fetchPlaylists = async (folderId: string) => {
202
+ return await api.get(`/folders/${folderId}/playlists`);
203
+ };
204
+
205
+ // ✅ Entity is a pure transform
206
+ export const toPlaylistItems = (raw: RawPlaylist[]): PlaylistItem[] =>
207
+ raw.map(r => ({ id: r.playlistId, label: r.playlistTitle ?? "Untitled" }));
208
+ ```
209
+
210
+ **Layer skipping:**
211
+ ```typescript
212
+ // ❌ Container importing an entity directly
213
+ import * as playlistEntity from "src/features/{feature}/domain/entities/PlaylistEntity";
214
+
215
+ // ✅ Container reads from controller state only
216
+ const playlists = useSelector(actor, s => s.context.playlists);
217
+ ```
218
+
219
+ **Passing machine internals to presentation:**
220
+ ```typescript
221
+ // ❌ Presentation receives send/snapshot — leaks machine contract into UI layer
222
+ <Sidebar snapshot={snapshot} send={send} />
223
+
224
+ // ✅ Container extracts values and creates callbacks
225
+ const collapsed = snapshot.context.sidebarCollapsed;
226
+ const onToggle = useCallback(() => send({ type: 'TOGGLE_SIDEBAR' }), [send]);
227
+ <Sidebar collapsed={collapsed} onToggle={onToggle} />
228
+ ```