@schilling.mark.a/software-methodology 1.0.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.
- package/.github/copilot-instructions.md +106 -0
- package/LICENSE +21 -0
- package/README.md +174 -0
- package/atdd-workflow/SKILL.md +117 -0
- package/atdd-workflow/references/green-phase.md +38 -0
- package/atdd-workflow/references/red-phase.md +62 -0
- package/atdd-workflow/references/refactor-phase.md +75 -0
- package/bdd-specification/SKILL.md +88 -0
- package/bdd-specification/references/example-mapping.md +105 -0
- package/bdd-specification/references/gherkin-patterns.md +214 -0
- package/cicd-pipeline/SKILL.md +64 -0
- package/cicd-pipeline/references/deployment-rollback.md +176 -0
- package/cicd-pipeline/references/environment-promotion.md +159 -0
- package/cicd-pipeline/references/pipeline-stages.md +198 -0
- package/clean-code/SKILL.md +77 -0
- package/clean-code/references/behavioral-patterns.md +329 -0
- package/clean-code/references/creational-patterns.md +197 -0
- package/clean-code/references/enterprise-patterns.md +334 -0
- package/clean-code/references/solid.md +230 -0
- package/clean-code/references/structural-patterns.md +238 -0
- package/continuous-improvement/SKILL.md +69 -0
- package/continuous-improvement/references/measurement.md +133 -0
- package/continuous-improvement/references/process-update.md +118 -0
- package/continuous-improvement/references/root-cause-analysis.md +144 -0
- package/dist/atdd-workflow.skill +0 -0
- package/dist/bdd-specification.skill +0 -0
- package/dist/cicd-pipeline.skill +0 -0
- package/dist/clean-code.skill +0 -0
- package/dist/continuous-improvement.skill +0 -0
- package/dist/green-implementation.skill +0 -0
- package/dist/product-strategy.skill +0 -0
- package/dist/story-mapping.skill +0 -0
- package/dist/ui-design-system.skill +0 -0
- package/dist/ui-design-workflow.skill +0 -0
- package/dist/ux-design.skill +0 -0
- package/dist/ux-research.skill +0 -0
- package/docs/INTEGRATION.md +229 -0
- package/docs/QUICKSTART.md +126 -0
- package/docs/SHARING.md +828 -0
- package/docs/SKILLS.md +296 -0
- package/green-implementation/SKILL.md +155 -0
- package/green-implementation/references/angular-patterns.md +239 -0
- package/green-implementation/references/common-rejections.md +180 -0
- package/green-implementation/references/playwright-patterns.md +321 -0
- package/green-implementation/references/rxjs-patterns.md +161 -0
- package/package.json +57 -0
- package/product-strategy/SKILL.md +71 -0
- package/product-strategy/references/business-model-canvas.md +199 -0
- package/product-strategy/references/canvas-alignment.md +108 -0
- package/product-strategy/references/value-proposition-canvas.md +159 -0
- package/project-templates/context.md.template +56 -0
- package/project-templates/test-strategy.md.template +87 -0
- package/story-mapping/SKILL.md +104 -0
- package/story-mapping/references/backbone.md +66 -0
- package/story-mapping/references/release-planning.md +92 -0
- package/story-mapping/references/task-template.md +78 -0
- package/story-mapping/references/walking-skeleton.md +63 -0
- package/ui-design-system/SKILL.md +48 -0
- package/ui-design-system/references/accessibility.md +134 -0
- package/ui-design-system/references/components.md +257 -0
- package/ui-design-system/references/design-tokens.md +209 -0
- package/ui-design-system/references/layout.md +136 -0
- package/ui-design-system/references/typography.md +114 -0
- package/ui-design-workflow/SKILL.md +90 -0
- package/ui-design-workflow/references/acceptance-targets.md +144 -0
- package/ui-design-workflow/references/component-selection.md +108 -0
- package/ui-design-workflow/references/scenario-to-ui.md +151 -0
- package/ui-design-workflow/references/screen-flows.md +116 -0
- package/ux-design/SKILL.md +75 -0
- package/ux-design/references/information-architecture.md +144 -0
- package/ux-design/references/interaction-patterns.md +141 -0
- package/ux-design/references/onboarding.md +159 -0
- package/ux-design/references/usability-evaluation.md +132 -0
- package/ux-research/SKILL.md +75 -0
- package/ux-research/references/journey-mapping.md +168 -0
- package/ux-research/references/mental-models.md +106 -0
- package/ux-research/references/personas.md +102 -0
package/docs/SKILLS.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# Software Methodology Skills Index
|
|
2
|
+
|
|
3
|
+
This document provides quick access to all skills in the methodology. Each skill has a SKILL.md entry point and detailed reference files.
|
|
4
|
+
|
|
5
|
+
**See also**: [Quick Start](QUICKSTART.md) | [Sharing Guide](SHARING.md) | [Main README](../README.md)
|
|
6
|
+
|
|
7
|
+
## Quick Navigation
|
|
8
|
+
|
|
9
|
+
Jump to: [Product](#product-strategy) | [Research](#ux-research) | [Planning](#story-mapping) | [Specification](#bdd-specification) | [Design](#design-skills) | [Development](#development-skills) | [Operations](#cicd-pipeline) | [Improvement](#continuous-improvement)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Product Strategy
|
|
14
|
+
|
|
15
|
+
**Location**: [`product-strategy/SKILL.md`](../product-strategy/SKILL.md)
|
|
16
|
+
|
|
17
|
+
**Purpose**: Create and maintain the Business Model Canvas and Value Proposition Canvas — the foundation documents that all other skills depend on.
|
|
18
|
+
|
|
19
|
+
**When to use**:
|
|
20
|
+
- Starting a new product
|
|
21
|
+
- Entering a new market or user segment
|
|
22
|
+
- After research reveals strategy changes needed
|
|
23
|
+
|
|
24
|
+
**Key references**:
|
|
25
|
+
- [Business Model Canvas](../product-strategy/references/business-model-canvas.md)
|
|
26
|
+
- [Value Proposition Canvas](../product-strategy/references/value-proposition-canvas.md)
|
|
27
|
+
- [Canvas Alignment](../product-strategy/references/canvas-alignment.md)
|
|
28
|
+
|
|
29
|
+
**Outputs**: `/docs/business-model-canvas.md`, `/docs/value-proposition-canvas.md`
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## UX Research
|
|
34
|
+
|
|
35
|
+
**Location**: [`ux-research/SKILL.md`](../ux-research/SKILL.md)
|
|
36
|
+
|
|
37
|
+
**Purpose**: Create personas, mental models, and user journey maps to understand customer needs deeply.
|
|
38
|
+
|
|
39
|
+
**When to use**:
|
|
40
|
+
- After creating the Value Proposition Canvas
|
|
41
|
+
- Before designing features
|
|
42
|
+
- When user feedback reveals gaps in understanding
|
|
43
|
+
|
|
44
|
+
**Key references**:
|
|
45
|
+
- Check the skill for persona templates and mental model formats
|
|
46
|
+
|
|
47
|
+
**Outputs**: `/docs/personas/`, `/docs/mental-models/`, `/docs/user-journey-maps/`
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Story Mapping
|
|
52
|
+
|
|
53
|
+
**Location**: [`story-mapping/SKILL.md`](../story-mapping/SKILL.md)
|
|
54
|
+
|
|
55
|
+
**Purpose**: Organize user activities into a backbone and sequence features into releases.
|
|
56
|
+
|
|
57
|
+
**When to use**:
|
|
58
|
+
- After personas and journey maps exist
|
|
59
|
+
- Planning a new release
|
|
60
|
+
- Reorganizing the product backlog
|
|
61
|
+
|
|
62
|
+
**Key references**:
|
|
63
|
+
- [Backbone Structure](../story-mapping/references/backbone.md)
|
|
64
|
+
- [Walking Skeleton](../story-mapping/references/walking-skeleton.md)
|
|
65
|
+
- [Release Planning](../story-mapping/references/release-planning.md)
|
|
66
|
+
- [Task Template](../story-mapping/references/task-template.md)
|
|
67
|
+
|
|
68
|
+
**Outputs**: `/docs/story-map/backbone.md`, `/docs/story-map/releases/*.md`
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## BDD Specification
|
|
73
|
+
|
|
74
|
+
**Location**: [`bdd-specification/SKILL.md`](../bdd-specification/SKILL.md)
|
|
75
|
+
|
|
76
|
+
**Purpose**: Write Gherkin feature files using example mapping to discover scenarios and rules.
|
|
77
|
+
|
|
78
|
+
**When to use**:
|
|
79
|
+
- After selecting tasks for a release
|
|
80
|
+
- Before implementation begins
|
|
81
|
+
- Clarifying feature acceptance criteria
|
|
82
|
+
|
|
83
|
+
**Outputs**: `/features/*.feature`
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Design Skills
|
|
88
|
+
|
|
89
|
+
### UX Design
|
|
90
|
+
|
|
91
|
+
**Location**: [`ux-design/SKILL.md`](../ux-design/SKILL.md)
|
|
92
|
+
|
|
93
|
+
**Purpose**: Design information architecture, interaction patterns, usability flows, and onboarding.
|
|
94
|
+
|
|
95
|
+
**When to use**:
|
|
96
|
+
- After feature specifications exist
|
|
97
|
+
- Designing new user flows
|
|
98
|
+
- Improving existing interactions
|
|
99
|
+
|
|
100
|
+
**Key references**:
|
|
101
|
+
- [Information Architecture](../ux-design/references/information-architecture.md)
|
|
102
|
+
- [Interaction Patterns](../ux-design/references/interaction-patterns.md)
|
|
103
|
+
- [Usability Evaluation](../ux-design/references/usability-evaluation.md)
|
|
104
|
+
- [Onboarding](../ux-design/references/onboarding.md)
|
|
105
|
+
|
|
106
|
+
**Outputs**: Design documents in `/docs/`
|
|
107
|
+
|
|
108
|
+
### UI Design Workflow
|
|
109
|
+
|
|
110
|
+
**Location**: [`ui-design-workflow/SKILL.md`](../ui-design-workflow/SKILL.md)
|
|
111
|
+
|
|
112
|
+
**Purpose**: Create screen flows, select components, and set acceptance targets for UI implementation.
|
|
113
|
+
|
|
114
|
+
**When to use**:
|
|
115
|
+
- After UX design is complete
|
|
116
|
+
- Before implementation
|
|
117
|
+
- Defining UI acceptance criteria
|
|
118
|
+
|
|
119
|
+
**Outputs**: `/docs/screen-flows/`, component selections, acceptance targets
|
|
120
|
+
|
|
121
|
+
### UI Design System
|
|
122
|
+
|
|
123
|
+
**Location**: [`ui-design-system/SKILL.md`](../ui-design-system/SKILL.md)
|
|
124
|
+
|
|
125
|
+
**Type**: Reference skill (consulted during UI design workflow)
|
|
126
|
+
|
|
127
|
+
**Purpose**: Define design tokens, typography, layout, components, and accessibility standards.
|
|
128
|
+
|
|
129
|
+
**When to use**:
|
|
130
|
+
- Referenced during `ui-design-workflow`
|
|
131
|
+
- Setting up a new design system
|
|
132
|
+
- Ensuring UI consistency
|
|
133
|
+
|
|
134
|
+
**Outputs**: Design system documentation
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Development Skills
|
|
139
|
+
|
|
140
|
+
### ATDD Workflow
|
|
141
|
+
|
|
142
|
+
**Location**: [`atdd-workflow/SKILL.md`](../atdd-workflow/SKILL.md)
|
|
143
|
+
|
|
144
|
+
**Purpose**: Implement features using RED-GREEN-REFACTOR test-driven development cycle.
|
|
145
|
+
|
|
146
|
+
**When to use**:
|
|
147
|
+
- Implementing any feature
|
|
148
|
+
- Writing production code
|
|
149
|
+
- Every development task
|
|
150
|
+
|
|
151
|
+
**Workflow**: RED (write failing test) → GREEN (make it pass) → REFACTOR (improve design)
|
|
152
|
+
|
|
153
|
+
**Outputs**: Implementation code and tests
|
|
154
|
+
|
|
155
|
+
### Green Implementation
|
|
156
|
+
|
|
157
|
+
**Location**: [`green-implementation/SKILL.md`](../green-implementation/SKILL.md)
|
|
158
|
+
|
|
159
|
+
**Purpose**: Detailed patterns for Angular/TypeScript/Playwright implementation during the GREEN phase.
|
|
160
|
+
|
|
161
|
+
**When to use**:
|
|
162
|
+
- During GREEN phase of ATDD workflow
|
|
163
|
+
- Implementing Angular components
|
|
164
|
+
- Writing Playwright tests
|
|
165
|
+
|
|
166
|
+
**Key references**:
|
|
167
|
+
- [Angular Patterns](../green-implementation/references/angular-patterns.md)
|
|
168
|
+
- [RxJS Patterns](../green-implementation/references/rxjs-patterns.md)
|
|
169
|
+
- [Playwright Patterns](../green-implementation/references/playwright-patterns.md)
|
|
170
|
+
- [Common Rejections](../green-implementation/references/common-rejections.md)
|
|
171
|
+
|
|
172
|
+
### Clean Code
|
|
173
|
+
|
|
174
|
+
**Location**: [`clean-code/SKILL.md`](../clean-code/SKILL.md)
|
|
175
|
+
|
|
176
|
+
**Type**: Reference skill (consulted during GREEN and REFACTOR phases)
|
|
177
|
+
|
|
178
|
+
**Purpose**: Apply SOLID principles and design patterns to create maintainable code.
|
|
179
|
+
|
|
180
|
+
**When to use**:
|
|
181
|
+
- During GREEN phase (choosing patterns)
|
|
182
|
+
- During REFACTOR phase (improving design)
|
|
183
|
+
- Code reviews
|
|
184
|
+
|
|
185
|
+
**Key references**:
|
|
186
|
+
- [SOLID Principles](../clean-code/references/solid.md)
|
|
187
|
+
- [Structural Patterns](../clean-code/references/structural-patterns.md)
|
|
188
|
+
- [Behavioral Patterns](../clean-code/references/behavioral-patterns.md)
|
|
189
|
+
- [Creational Patterns](../clean-code/references/creational-patterns.md)
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## CI/CD Pipeline
|
|
194
|
+
|
|
195
|
+
**Location**: [`cicd-pipeline/SKILL.md`](../cicd-pipeline/SKILL.md)
|
|
196
|
+
|
|
197
|
+
**Purpose**: Set up pipeline stages, environment promotion, deployment, and rollback procedures.
|
|
198
|
+
|
|
199
|
+
**When to use**:
|
|
200
|
+
- Setting up a new project
|
|
201
|
+
- Adding deployment environments
|
|
202
|
+
- Configuring CI/CD automation
|
|
203
|
+
|
|
204
|
+
**Outputs**: Pipeline configuration, deployment scripts
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Continuous Improvement
|
|
209
|
+
|
|
210
|
+
**Location**: [`continuous-improvement/SKILL.md`](../continuous-improvement/SKILL.md)
|
|
211
|
+
|
|
212
|
+
**Purpose**: Measure post-release outcomes, perform root cause analysis, and feed improvements back into the methodology.
|
|
213
|
+
|
|
214
|
+
**When to use**:
|
|
215
|
+
- After each release
|
|
216
|
+
- When production issues occur
|
|
217
|
+
- Regular improvement cycles
|
|
218
|
+
|
|
219
|
+
**Outputs**: Measurement reports, process improvements (feeds back to any upstream skill)
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## The Methodology Flow
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
┌─────────────────────┐
|
|
227
|
+
│ product-strategy │ Business Model Canvas + Value Proposition Canvas
|
|
228
|
+
└──────────┬──────────┘
|
|
229
|
+
│
|
|
230
|
+
▼
|
|
231
|
+
┌─────────────────────┐
|
|
232
|
+
│ ux-research │ Personas + Mental Models + Journey Maps
|
|
233
|
+
└──────────┬──────────┘
|
|
234
|
+
│
|
|
235
|
+
▼
|
|
236
|
+
┌─────────────────────┐
|
|
237
|
+
│ story-mapping │ Backbone + Release Plans
|
|
238
|
+
└──────────┬──────────┘
|
|
239
|
+
│
|
|
240
|
+
▼
|
|
241
|
+
┌─────────────────────┐
|
|
242
|
+
│ bdd-specification │ Feature Files (Gherkin)
|
|
243
|
+
└──────────┬──────────┘
|
|
244
|
+
│
|
|
245
|
+
▼
|
|
246
|
+
┌─────────────────────┐
|
|
247
|
+
│ ux-design │ Information Architecture + Interaction Patterns
|
|
248
|
+
└──────────┬──────────┘
|
|
249
|
+
│
|
|
250
|
+
▼
|
|
251
|
+
┌─────────────────────┐
|
|
252
|
+
│ ui-design-workflow │◄─────┐ ui-design-system (reference)
|
|
253
|
+
└──────────┬──────────┘ │
|
|
254
|
+
│ │
|
|
255
|
+
▼ │
|
|
256
|
+
┌─────────────────────┐ │
|
|
257
|
+
│ atdd-workflow │◄─────┤
|
|
258
|
+
│ (RED-GREEN-REFACTOR)│ │ clean-code (reference)
|
|
259
|
+
└──────────┬──────────┘ │
|
|
260
|
+
│ │
|
|
261
|
+
▼ │
|
|
262
|
+
┌─────────────────────┐ │
|
|
263
|
+
│ cicd-pipeline │ │
|
|
264
|
+
└──────────┬──────────┘ │
|
|
265
|
+
│ │
|
|
266
|
+
▼ │
|
|
267
|
+
┌─────────────────────┐ │
|
|
268
|
+
│ continuous- │──────┘
|
|
269
|
+
│ improvement │ Feeds improvements back upstream
|
|
270
|
+
└─────────────────────┘
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Using Skills with Different Tools
|
|
274
|
+
|
|
275
|
+
### With Claude Code
|
|
276
|
+
|
|
277
|
+
Deploy `.skill` files from `dist/` directory to `/mnt/skills/user/`. See main [README.md](../README.md) for details.
|
|
278
|
+
|
|
279
|
+
### With GitHub Copilot
|
|
280
|
+
|
|
281
|
+
Copilot reads `.github/copilot-instructions.md` and can reference these skill files directly. Ask Copilot about methodology questions and it will guide you to the right skill.
|
|
282
|
+
|
|
283
|
+
### With VS Code
|
|
284
|
+
|
|
285
|
+
Open this repository in VS Code. All skills are in markdown format and easily navigable. Use the VS Code workspace settings in `.vscode/settings.json` for optimized navigation.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Project Templates
|
|
290
|
+
|
|
291
|
+
When starting a new project, use the templates in [`project-templates/`](../project-templates/):
|
|
292
|
+
|
|
293
|
+
- **context.md.template** — Project context file for Claude Code
|
|
294
|
+
- **test-strategy.md.template** — Testing approach and commands
|
|
295
|
+
|
|
296
|
+
Copy these to your project's `/docs/` directory and fill in the project-specific details.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: green-implementation
|
|
3
|
+
description: >
|
|
4
|
+
Angular/TypeScript/Playwright implementation patterns for making tests green
|
|
5
|
+
while meeting team coding standards. Use during the GREEN and REFACTOR phases
|
|
6
|
+
of the ATDD workflow — when writing production code to pass failing tests.
|
|
7
|
+
Activates when: implementing features, making tests pass, writing Angular
|
|
8
|
+
components or services, creating Playwright page objects, fixing PR feedback,
|
|
9
|
+
or when the user says "make it green", "implement", "write the code",
|
|
10
|
+
"fix the PR comments". Works alongside atdd-workflow (which governs the
|
|
11
|
+
RED-GREEN-REFACTOR discipline) and clean-code (which governs design
|
|
12
|
+
principles). This skill governs the team-specific conventions that prevent
|
|
13
|
+
PR rejections. Reads acceptance criteria from the active feature context.
|
|
14
|
+
Produces code that passes both automated tests and peer review.
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# GREEN Implementation — Angular / TypeScript / Playwright
|
|
18
|
+
|
|
19
|
+
## Purpose
|
|
20
|
+
|
|
21
|
+
atdd-workflow tells the agent *how to work* (RED→GREEN→REFACTOR).
|
|
22
|
+
clean-code tells the agent *how to design* (SOLID, patterns).
|
|
23
|
+
This skill tells the agent *what the team will accept* — the conventions
|
|
24
|
+
that prevent PR rejections and rework.
|
|
25
|
+
|
|
26
|
+
Only codify patterns here where the wrong choice causes rework. If both
|
|
27
|
+
approaches are acceptable on the team, don't specify one.
|
|
28
|
+
|
|
29
|
+
## Before Writing Code
|
|
30
|
+
|
|
31
|
+
1. Read the failing test — understand EXACTLY what it asserts
|
|
32
|
+
2. Read the AC from the active feature context
|
|
33
|
+
3. Read `/docs/test-strategy.md` for test commands
|
|
34
|
+
4. Read `/docs/ubiquitous-language.md` for naming
|
|
35
|
+
|
|
36
|
+
## Architecture Rules
|
|
37
|
+
|
|
38
|
+
These are non-negotiable. Violations block PRs.
|
|
39
|
+
|
|
40
|
+
### Services Own HTTP — Components Never Touch HttpClient
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
// ✅
|
|
44
|
+
@Component({ ... })
|
|
45
|
+
export class UserListComponent {
|
|
46
|
+
users$ = this.userService.getUsers();
|
|
47
|
+
constructor(private userService: UserService) {}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ❌ PR REJECTED
|
|
51
|
+
@Component({ ... })
|
|
52
|
+
export class UserListComponent {
|
|
53
|
+
constructor(private http: HttpClient) {}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Business Logic in Services, Not Components
|
|
58
|
+
|
|
59
|
+
Components: template binding + user interaction.
|
|
60
|
+
Services: data transformation, validation, API calls, state.
|
|
61
|
+
|
|
62
|
+
### Barrel Exports for Public APIs
|
|
63
|
+
|
|
64
|
+
Every feature module exposes its public API through `index.ts`.
|
|
65
|
+
|
|
66
|
+
For full architecture patterns: see `references/angular-patterns.md`
|
|
67
|
+
|
|
68
|
+
## Naming Conventions
|
|
69
|
+
|
|
70
|
+
| Rule | Good | Bad |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| No Hungarian notation | `userName` | `strUserName` |
|
|
73
|
+
| Observable$ suffix | `users$` | `users: Observable<T>` |
|
|
74
|
+
| No I prefix on interfaces | `UserProfile` | `IUserProfile` |
|
|
75
|
+
| Named constants | `MAX_PAGE_SIZE = 20` | `if (x >= 20)` |
|
|
76
|
+
| Descriptive test names | `'should show error when invalid'` | `'test error'` |
|
|
77
|
+
|
|
78
|
+
## Error Handling
|
|
79
|
+
|
|
80
|
+
| Rule | Pattern |
|
|
81
|
+
|---|---|
|
|
82
|
+
| No empty catch blocks | Always log and handle: `catch (error: unknown) { this.logger.error(...) }` |
|
|
83
|
+
| Typed errors | `catch (error: unknown)` then narrow with `instanceof` |
|
|
84
|
+
| No console.log | Use the team's `LoggerService` |
|
|
85
|
+
| switchMap needs catchError | Every `switchMap` must have a `catchError` inside the inner observable |
|
|
86
|
+
|
|
87
|
+
For full error handling patterns: see `references/angular-patterns.md`
|
|
88
|
+
|
|
89
|
+
## RxJS Patterns
|
|
90
|
+
|
|
91
|
+
| Rule | Preferred | Avoid |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| Async style | `async/await` | `.then()` chains |
|
|
94
|
+
| Cleanup | `takeUntilDestroyed()` or `async` pipe | Bare `.subscribe()` without cleanup |
|
|
95
|
+
| Error in switchMap | `switchMap(x => obs.pipe(catchError(...)))` | `switchMap(x => obs)` without error handling |
|
|
96
|
+
|
|
97
|
+
For full reactive patterns: see `references/rxjs-patterns.md`
|
|
98
|
+
|
|
99
|
+
## Playwright Test Patterns
|
|
100
|
+
|
|
101
|
+
| Rule | Pattern |
|
|
102
|
+
|---|---|
|
|
103
|
+
| Page Object required | All selectors in PO classes, never raw selectors in test files |
|
|
104
|
+
| Web-first assertions | `await expect(locator).toBeVisible()` — no `waitForTimeout` |
|
|
105
|
+
| User-facing locators | `getByRole`, `getByLabel`, `getByText` preferred over CSS |
|
|
106
|
+
| Test data from fixtures | `TestDataBuilder.createUser()` — no hard-coded credentials |
|
|
107
|
+
|
|
108
|
+
For full Playwright and Page Object patterns: see `references/playwright-patterns.md`
|
|
109
|
+
|
|
110
|
+
## Security
|
|
111
|
+
|
|
112
|
+
- **No `innerHTML`** — use Angular template binding `[innerHTML]` with `DomSanitizer`
|
|
113
|
+
- **No `console.log`** — use LoggerService
|
|
114
|
+
- **No hard-coded secrets** — use environment config
|
|
115
|
+
|
|
116
|
+
## GREEN Phase Discipline
|
|
117
|
+
|
|
118
|
+
While applying the patterns above, remember:
|
|
119
|
+
|
|
120
|
+
1. Write ONLY enough code to make the current failing test pass
|
|
121
|
+
2. If you need a service, create a minimal one — just the method the test requires
|
|
122
|
+
3. Hard-coding is acceptable if it makes the test pass
|
|
123
|
+
4. Do NOT add methods no test calls
|
|
124
|
+
5. Do NOT implement edge cases no test covers
|
|
125
|
+
6. Do NOT optimize — REFACTOR handles that
|
|
126
|
+
7. After each green: run ALL tests to check for side effects
|
|
127
|
+
8. Commit: `🟢 GREEN: Make [test name] pass with minimal code`
|
|
128
|
+
|
|
129
|
+
## Integration
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
atdd-workflow → governs the RED-GREEN-REFACTOR cycle
|
|
133
|
+
↓ (during GREEN and REFACTOR)
|
|
134
|
+
green-implementation (this skill) → team conventions and patterns
|
|
135
|
+
↓ (during REFACTOR)
|
|
136
|
+
clean-code → SOLID principles and design patterns
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
During GREEN: follow this skill's patterns. Consult clean-code only if
|
|
140
|
+
a SOLID violation blocks the next test cycle.
|
|
141
|
+
|
|
142
|
+
During REFACTOR: use clean-code's decision tree for design improvements.
|
|
143
|
+
Keep this skill's conventions intact — refactoring should not introduce
|
|
144
|
+
pattern violations.
|
|
145
|
+
|
|
146
|
+
## Keeping This Skill Current
|
|
147
|
+
|
|
148
|
+
After every PR rejection:
|
|
149
|
+
1. Record feedback in the MCP server (`record_pr_feedback`)
|
|
150
|
+
2. Add automated rule if possible (`add_rule` in team-standards.json)
|
|
151
|
+
3. Add the same pattern here with ✅/❌ examples
|
|
152
|
+
4. If a violation type appears 3+ times, the section isn't clear — strengthen it
|
|
153
|
+
|
|
154
|
+
This skill and `team-standards.json` stay in sync. Every rule in the JSON
|
|
155
|
+
has a corresponding pattern here. The skill prevents; the MCP server catches.
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Angular Implementation Patterns
|
|
2
|
+
|
|
3
|
+
## Component Architecture
|
|
4
|
+
|
|
5
|
+
### Smart vs Presentational Components
|
|
6
|
+
|
|
7
|
+
**Smart (container) components:**
|
|
8
|
+
- Inject services
|
|
9
|
+
- Manage state and side effects
|
|
10
|
+
- Pass data down via `@Input()`
|
|
11
|
+
- React to events via `@Output()`
|
|
12
|
+
|
|
13
|
+
**Presentational (dumb) components:**
|
|
14
|
+
- Receive data via `@Input()` only
|
|
15
|
+
- Emit events via `@Output()` only
|
|
16
|
+
- No injected services (except simple utilities)
|
|
17
|
+
- Pure rendering — given the same inputs, same output
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// ✅ Smart component — owns the data
|
|
21
|
+
@Component({
|
|
22
|
+
selector: 'app-user-list-container',
|
|
23
|
+
template: `<app-user-list [users]="users$ | async" (select)="onSelect($event)" />`,
|
|
24
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
25
|
+
})
|
|
26
|
+
export class UserListContainerComponent {
|
|
27
|
+
users$ = this.userService.getUsers();
|
|
28
|
+
constructor(private userService: UserService) {}
|
|
29
|
+
onSelect(user: User) { this.router.navigate(['/users', user.id]); }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ✅ Presentational component — renders what it's given
|
|
33
|
+
@Component({
|
|
34
|
+
selector: 'app-user-list',
|
|
35
|
+
template: `
|
|
36
|
+
<ul>
|
|
37
|
+
<li *ngFor="let user of users; trackBy: trackById" (click)="select.emit(user)">
|
|
38
|
+
{{ user.name }}
|
|
39
|
+
</li>
|
|
40
|
+
</ul>
|
|
41
|
+
`,
|
|
42
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
43
|
+
})
|
|
44
|
+
export class UserListComponent {
|
|
45
|
+
@Input() users: User[] = [];
|
|
46
|
+
@Output() select = new EventEmitter<User>();
|
|
47
|
+
trackById = (_: number, user: User) => user.id;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Service Layer Pattern
|
|
52
|
+
|
|
53
|
+
Services own all business logic and HTTP communication.
|
|
54
|
+
Components never import `HttpClient`.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// ✅ Service — owns HTTP and business logic
|
|
58
|
+
@Injectable({ providedIn: 'root' })
|
|
59
|
+
export class UserService {
|
|
60
|
+
private readonly apiUrl = '/api/users';
|
|
61
|
+
|
|
62
|
+
constructor(
|
|
63
|
+
private http: HttpClient,
|
|
64
|
+
private logger: LoggerService
|
|
65
|
+
) {}
|
|
66
|
+
|
|
67
|
+
getUsers(): Observable<User[]> {
|
|
68
|
+
return this.http.get<User[]>(this.apiUrl).pipe(
|
|
69
|
+
catchError(error => {
|
|
70
|
+
this.logger.error('Failed to load users', { error });
|
|
71
|
+
return of([]);
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getUserById(id: string): Observable<User> {
|
|
77
|
+
return this.http.get<User>(`${this.apiUrl}/${id}`).pipe(
|
|
78
|
+
catchError(error => {
|
|
79
|
+
this.logger.error('Failed to load user', { id, error });
|
|
80
|
+
throw error;
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Barrel Exports
|
|
88
|
+
|
|
89
|
+
Every feature directory has an `index.ts` that exports the public API.
|
|
90
|
+
Internal implementation files are not exported.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// src/app/users/index.ts
|
|
94
|
+
export { UserListContainerComponent } from './user-list-container.component';
|
|
95
|
+
export { UserService } from './user.service';
|
|
96
|
+
export { User, UserRole, CreateUserRequest } from './user.model';
|
|
97
|
+
// Do NOT export internal components, helpers, or private types
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Error Handling Patterns
|
|
101
|
+
|
|
102
|
+
### HTTP Error Handling in Services
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// ✅ Typed error handling with logging
|
|
106
|
+
saveUser(user: CreateUserRequest): Observable<User> {
|
|
107
|
+
return this.http.post<User>(this.apiUrl, user).pipe(
|
|
108
|
+
catchError((error: unknown) => {
|
|
109
|
+
if (error instanceof HttpErrorResponse) {
|
|
110
|
+
switch (error.status) {
|
|
111
|
+
case 409:
|
|
112
|
+
this.logger.warn('User already exists', { email: user.email });
|
|
113
|
+
throw new UserAlreadyExistsError(user.email);
|
|
114
|
+
case 422:
|
|
115
|
+
this.logger.warn('Validation failed', { errors: error.error });
|
|
116
|
+
throw new ValidationError(error.error.errors);
|
|
117
|
+
default:
|
|
118
|
+
this.logger.error('Unexpected error saving user', { error });
|
|
119
|
+
throw new UnexpectedError('Failed to save user');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
throw error;
|
|
123
|
+
})
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Component Error Display
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// ✅ Component handles error state from service
|
|
132
|
+
@Component({
|
|
133
|
+
template: `
|
|
134
|
+
<app-error-banner *ngIf="error" [message]="error" />
|
|
135
|
+
<app-user-list *ngIf="users$ | async as users" [users]="users" />
|
|
136
|
+
<app-loading-spinner *ngIf="loading$ | async" />
|
|
137
|
+
`,
|
|
138
|
+
})
|
|
139
|
+
export class UserListContainerComponent {
|
|
140
|
+
error: string | null = null;
|
|
141
|
+
|
|
142
|
+
users$ = this.userService.getUsers().pipe(
|
|
143
|
+
catchError(error => {
|
|
144
|
+
this.error = error.message;
|
|
145
|
+
return of([]);
|
|
146
|
+
})
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Custom Error Types
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
// ✅ Domain-specific error classes
|
|
155
|
+
export class UserAlreadyExistsError extends Error {
|
|
156
|
+
constructor(public email: string) {
|
|
157
|
+
super(`User with email ${email} already exists`);
|
|
158
|
+
this.name = 'UserAlreadyExistsError';
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export class ValidationError extends Error {
|
|
163
|
+
constructor(public errors: Record<string, string[]>) {
|
|
164
|
+
super('Validation failed');
|
|
165
|
+
this.name = 'ValidationError';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Subscription Management
|
|
171
|
+
|
|
172
|
+
### Preferred: async Pipe
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
// ✅ Best — Angular handles subscription lifecycle
|
|
176
|
+
@Component({
|
|
177
|
+
template: `
|
|
178
|
+
<div *ngIf="user$ | async as user">
|
|
179
|
+
<h1>{{ user.name }}</h1>
|
|
180
|
+
</div>
|
|
181
|
+
`,
|
|
182
|
+
})
|
|
183
|
+
export class UserDetailComponent {
|
|
184
|
+
user$ = this.route.params.pipe(
|
|
185
|
+
switchMap(params => this.userService.getUserById(params['id']))
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### When You Need the Value in Code: takeUntilDestroyed
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// ✅ Angular 16+ — automatic cleanup
|
|
194
|
+
@Component({ ... })
|
|
195
|
+
export class DashboardComponent implements OnInit {
|
|
196
|
+
private destroyRef = inject(DestroyRef);
|
|
197
|
+
metrics: DashboardMetrics | null = null;
|
|
198
|
+
|
|
199
|
+
ngOnInit() {
|
|
200
|
+
this.metricsService.getMetrics().pipe(
|
|
201
|
+
takeUntilDestroyed(this.destroyRef)
|
|
202
|
+
).subscribe(metrics => {
|
|
203
|
+
this.metrics = metrics;
|
|
204
|
+
this.updateChart(metrics);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Never: Bare subscribe Without Cleanup
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
// ❌ Memory leak — no cleanup mechanism
|
|
214
|
+
ngOnInit() {
|
|
215
|
+
this.userService.getUsers().subscribe(users => this.users = users);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## File Organization
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
src/app/
|
|
223
|
+
├── users/ # Feature directory
|
|
224
|
+
│ ├── index.ts # Barrel exports (public API)
|
|
225
|
+
│ ├── user-list-container.component.ts # Smart component
|
|
226
|
+
│ ├── user-list.component.ts # Presentational component
|
|
227
|
+
│ ├── user-detail.component.ts
|
|
228
|
+
│ ├── user.service.ts # HTTP + business logic
|
|
229
|
+
│ ├── user.model.ts # Interfaces, types, enums
|
|
230
|
+
│ └── user.errors.ts # Domain error classes
|
|
231
|
+
├── shared/ # Cross-feature utilities
|
|
232
|
+
│ ├── index.ts
|
|
233
|
+
│ ├── logger.service.ts
|
|
234
|
+
│ └── error-banner.component.ts
|
|
235
|
+
└── core/ # App-wide singletons
|
|
236
|
+
├── index.ts
|
|
237
|
+
├── auth.service.ts
|
|
238
|
+
└── http-error.interceptor.ts
|
|
239
|
+
```
|