| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| Invoke | /product:scaffold |
| Category | pipeline |
| Complexity | moderate |
/product:scaffold โ ์ฝ๋ ๋ผ๋ "์๋ ์์ฑ" ๋จ๊ณ#
ํ์ดํ๋ผ์ธ 4.5๋จ๊ณ(Scaffold). ์ค๊ณ ๋ฌธ์๋ฅผ ๋ฐํ์ผ๋ก ๊ธฐ๋ฅ๋ณ ์ฝ๋ ๋ผ๋์ ํ ์คํธ ํ์ผ์ ์๋์ผ๋ก ๋ง๋ค์ด, ๊ฐ๋ฐ์๊ฐ ๊ณง๋ฐ๋ก ์ด์ ๋ถ์ผ ์ ์๊ฒ ์ค๋นํฉ๋๋ค.
ํ๋ง๋๋ก#
์ค๊ณ๋๊ฐ ๋์จ ๋ค, ๊ฑด๋ฌผ์ ๊ณจ์กฐ์ ๋ฐฐ๊ด์ ๋ฏธ๋ฆฌ ์ธ์๋๋ ๋จ๊ณ์ ๋๋ค. ๋ฐฉ๋ง๋ค ๋ฒฝยท๋ฌธยท์ฐฝํ์ ๋จผ์ ์๋์ผ๋ก ์ธ์๋๋ฉด, ์ฌ๋์ ์ธํ ๋ฆฌ์ด(์ค์ ๊ธฐ๋ฅ ๊ตฌํ)๋ง ์ฑ์ ๋ฃ์ผ๋ฉด ๋๋ ๊ฒ๊ณผ ๊ฐ์์.
๋๊ฐยท์ธ์ ์ฐ๋์#
- ์ค๊ณ(Design)๊ฐ ๋๋ ์ด์ ์ค์ ์ฝ๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ธฐ ์์ํ ๋
- ์ ๊ธฐ๋ฅ ๋ชจ๋์ Clean Architecture ํํ๋ก ํ ๋ฒ์ ๊น๋ํ๊ฒ ์ธํ ํ๊ณ ์ถ์ ๋
- ๊ธฐํ์์ ์๊ตฌ์ฌํญ(Acceptance Criteria)์ BDD ํ ์คํธ ๋ผ๋๋ก ๋ฐ๊ฟ๋๊ณ ์ถ์ ๋
๐ ๊ฑด๋๋ฐ์ด๋ ๋๋ ๊ฒฝ์ฐ: ์ด๋ฏธ ์ฝ๋ ๊ตฌ์กฐ๊ฐ ์กํ ์๊ฑฐ๋, BDD ํ
์คํธ ์์ฑ์ด ํ์ ์๋ ์์
์ด๋ผ๋ฉด --skip-bddยท--skip-tests
์ต์
์ผ๋ก ์ผ๋ถ ๋จ๊ณ๋ฅผ ์๋ตํ ์ ์์ต๋๋ค.
๋ฌด์์ ํด์ฃผ๋์#
๊ธฐ๋ฅ๋ง๋ค ์ฝ๋ ๋ผ๋์ ํ ์คํธ ํ์ผ์ด ์๋์ผ๋ก ๋ง๋ค์ด์ง๋๋ค. ์ฃผ์ ๊ฒฐ๊ณผ๋ฌผ์:
feature/application/(๊ธฐ๋ฅ์ด๋ฆ)/โ ํ๋ก ํธ์๋ ๊ธฐ๋ฅ ์ฝ๋ ๋ผ๋ (๊ธฐ๋ฅ๋ณ)backend/(ํ๋ก์ ํธ)_server/feature/(๊ธฐ๋ฅ์ด๋ฆ)/โ ๋ฐฑ์๋ ์ฝ๋ ๋ผ๋ (๊ธฐ๋ฅ๋ณ)test/src/bdd/(๊ธฐ๋ฅ).featureโ BDD ์๋๋ฆฌ์ค ํ์ผ (์ฌ๋์ด ์ฝ๋ ์๊ตฌ์ฌํญ ๋ช ์ธ)test/src/bdd/(๊ธฐ๋ฅ).widget_test.dartโ ์๋ ์์ฑ๋ ์์ ฏ ํ ์คํธtest/src/bdd/(๊ธฐ๋ฅ).patrol_test.dartโ ์๋ ์์ฑ๋ patrol ํ ์คํธtest/src/bdd/step/โ ๋จ๊ณ๋ณ ํจ์ ๋ผ๋ (๊ฐ๋ฐ ๋จ๊ณ์์ ์ฑ์ ๋ฃ์ ๋น์นธ)
์ด๋ป๊ฒ ์ฐ๋์#
# ๊ธฐ๋ณธ (์ค๊ณ ๋ฌธ์์์ ๊ธฐ๋ฅยท์ํฐํฐ๋ฅผ ์๋์ผ๋ก ์์๋)
/product:scaffold
# ํน์ ๊ธฐ๋ฅยท์ํฐํฐ๋ฅผ ์ง์ ์ง์
/product:scaffold --feature community --entity Post
# BDD .feature ํ์ผ ์์ฑ์ ๊ฑด๋๋ฐ๊ธฐ
/product:scaffold --skip-bdd
# ํ
์คํธ ํ์ผ ์์ฑ์ ๊ฑด๋๋ฐ๊ธฐ
/product:scaffold --skip-tests
์๋ ๋งค์นญ๋ brick์ด ํ๋ ธ์ ๋๋ --brick์ผ๋ก ํน์ brick์ ๊ฐ์ ๋ก ์ง์ ํ ์ ์์ต๋๋ค.
์์์ ๋ฌด์จ ์ผ์ด ๋ฒ์ด์ง๋์#
ํฌ๊ฒ ๋ค ๋จ๊ณ๋ก ์งํ๋ฉ๋๋ค.
- ๊ธฐ๋ฅ ์ ๋ฆฌ โ ์ค๊ณ ๋ฌธ์(์ํคํ ์ฒยทUXยท๊ธฐํ์)๋ฅผ ์ฝ์ด, ์ด๋ค ๊ธฐ๋ฅ์ด ์๊ณ ๊ฐ ๊ธฐ๋ฅ์ ์ด๋ค ํ๋ฉดยท์ํฐํฐยท์๊ตฌ์ฌํญ์ด ํ์ํ์ง ๋ชฉ๋ก์ผ๋ก ์ ๋ฆฌํฉ๋๋ค.
- ์ฝ๋ ๋ผ๋ ์์ฑ โ ์ ๋ฆฌ๋ ๊ธฐ๋ฅ๋ง๋ค Mason brick(๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋ ์ฝ๋ ํ)์ ๊ณจ๋ผ, ํ๋ก ํธ์๋ยท๋ฐฑ์๋ ํด๋ ๊ตฌ์กฐ์ ํ์ผ์ ์๋์ผ๋ก ์ฐ์ด๋ ๋๋ค.
-
BDD ํ
์คํธ ๋ผ๋ ์์ฑ โ ๊ธฐํ์์ ์๊ตฌ์ฌํญ์
.feature์๋๋ฆฌ์ค๋ก ๋ฐ๊พธ๊ณ , ์์ ฏยทpatrol ํ ์คํธ ํ์ผ๊ณผ ๋น ๋จ๊ณ ํจ์๋ค์ ์๋์ผ๋ก ๋ง๋ค์ด ๋ก๋๋ค. - ๊ฒ์(Scaffold Gate) โ ๋ผ๋ ํด๋ยท์๋๋ฆฌ์ค ํ์ผยทํ ์คํธ ํ์ผยท๋จ๊ณ ํจ์๊ฐ ๋น ์ง์์ด ๋ง๋ค์ด์ก๋์ง ํ์ธํ๊ณ , ๋น ์ง ๊ฒ ์์ผ๋ฉด ๋ณด์ํฉ๋๋ค.
โ๏ธ ์์ธ ์ต์ ยท์คํ ๋ช ์ธ (๊ฐ๋ฐ์ / AI ์์ด์ ํธ์ฉ)
Triggers#
- When scaffolding full-stack code structure after Design stage completion
- When generating BDD test scaffolding from PRD Acceptance Criteria
- When bootstrapping a new feature module with Clean Architecture layers
Usage#
/product:scaffold
/product:scaffold --feature community --entity Post
/product:scaffold --skip-bdd
/product:scaffold --skip-testsOptions#
| Option | Default | Description |
|---|---|---|
--feature | Auto-inferred from architecture doc | Feature name (snake_case) |
--entity | Auto-inferred from architecture doc | Primary entity name (PascalCase) |
--skip-bdd | false | Skip BDD .feature file generation |
--skip-tests | false | Skip build_runner test file generation |
--brick | Auto-matched | Force specific brick name |
Prerequisites#
- Design stage completed (Solutioning Gate passed)
- Architecture Doc (
docs/architecture-{slug}.md) exists - UX Spec (
docs/ux-spec-{slug}.md) exists - PRD (
docs/prd-{slug}.md) with Acceptance Criteria exists
Execution Flow#
Phase 1: Feature Extraction#
Source: cc-product (internal)
Parse Architecture Doc (
docs/architecture-{slug}.md)- Extract feature list from architecture layer definitions
- Identify primary/secondary entity per feature
- Map feature โ Clean Architecture layers (domain, data, presentation)
Parse UX Spec (
docs/ux-spec-{slug}.md)- Extract screen list per feature (list, detail, form, etc.)
- Identify screen-to-feature mapping
Parse PRD (
docs/prd-{slug}.md)- Extract Acceptance Criteria per feature
- Map AC โ Gherkin-ready scenario descriptions
Build Feature Manifest
features: - name: community # snake_case primary_entity: Post # PascalCase secondary_entity: Comment # PascalCase (optional) screens: [list, detail, form] acceptance_criteria: - " User can view post list " - " User can create new post " - " User can add comment to post " brick_match: feature-store # cc-bricks-feature ์ ์ค์ 11๊ฐ feature-* ๋ชจ๋์์ ๋งค์นญ
Phase 2: Brick Scaffolding#
Source: cc-bricks-feature
For each feature in the manifest:
Brick matching โ Match feature name to the closest brick among cc-bricks-feature ์ ์ค์ 11๊ฐ
feature-*๋ชจ๋ (skills/ ์ฐธ์กฐ; console brick ์์)- Exact match:
storeโfeature-store - Keyword match:
messagingโfeature-chat - Fallback: use generic feature structure
- Exact match:
Run Mason brick per feature
mason make feature-{brick_name} \ --project_name {project_name} \ --org_name {org_name} \ --org_tld {org_tld} \ --feature_name {feature_name}Verify scaffolded output
feature/application/{feature_name}/ โโโ lib/src/ โ โโโ domain/ # Entity, UseCase, Repository Interface โ โโโ data/ # Repository impl, Cache, OpenAPI Mixin โ โโโ presentation/ # BLoC, Page, Widgets โ โโโ route/ # GoRouter TypedRoute โ โโโ di/ # Dependency Injection โโโ test/src/ # Test directory structure backend/{project}_server/feature/{feature_name}/ โโโ model/ # .spy.yaml models โโโ endpoint/ # CRUD handlers โโโ service/ # Business logic โโโ exception/ # Domain exceptions โโโ validation/ # Input validationCommit:
"feat({scope}): scaffold {feature_name} via mason brick"
Phase 3: BDD Scenario Generation#
Source: cc-flutter-dev (bdd-scenario-agent)
For each feature with screens:
Generate .feature files from PRD Acceptance Criteria
/bdd:generate {feature_name} \ --entity-name {PrimaryEntity} \ --screens " {screen_list} " \ --builder dual \ --run-build trueco-test-gen build_runner generates dual test files
dart run build_runner build --delete-conflicting-outputsOutput per feature:
test/src/bdd/{feature}.featureโ Gherkin scenariostest/src/bdd/{feature}.widget_test.dartโ Auto-generated (DO NOT MODIFY)test/src/bdd/{feature}.patrol_test.dartโ Auto-generated (DO NOT MODIFY)test/src/bdd/step/โ Step function stubs (to be implemented in Development)
Step stub generation โ Create skeleton step functions with TestDriver API
/// Usage: Given I am on the post list page /// Purpose: Navigate to post list page Future<void> iAmOnThePostListPage(TestDriver driver) async { // TODO: Implement step - scaffold generated stub throw UnimplementedError('Step not yet implemented'); }Commit:
"test({scope}): generate BDD scenarios and test stubs for {feature_name}"
Phase 4: Scaffold Gate#
Scaffold Gate verification per feature:
| Check | Criteria |
|---|---|
| Brick output | feature/application/{feature_name}/lib/src/ directory exists with domain, data, presentation layers |
| Feature files | .feature file exists in test/src/bdd/ for each screen feature |
| Widget test gen | .widget_test.dart generated by co-test-gen build_runner |
| Patrol test gen | .patrol_test.dart generated by co-test-gen build_runner |
| Step stubs | All Gherkin steps have corresponding step function stubs in step/ folder |
Gate fails if any check does not pass. Scaffold is revised with feedback.
Artifacts#
feature/application/{feature_name}/ # Scaffolded feature code (per feature)
backend/{project}_server/feature/{name}/ # Scaffolded backend code (per feature)
test/src/bdd/{feature}.feature # BDD feature files
test/src/bdd/{feature}.widget_test.dart # Auto-generated widget tests
test/src/bdd/{feature}.patrol_test.dart # Auto-generated patrol tests
test/src/bdd/step/ # Step function stubsAfter Completion#
- Verify Scaffold Gate passed
- Update
.pipeline/{slug}.yamlstate - Present context-clear handoff:
โ
Scaffold stage complete (Scaffold Gate PASSED).
- {N} features scaffolded via Mason bricks
- {M} .feature files generated
- {K} widget + patrol test files auto-generated
- {S} step function stubs created (to be implemented in Development)
**Option 1 (Recommended)**: Clear context and continue to Epic Creation
/clear
Then run: /product:epic
**Option 2**: Continue in current context
Proceed directly to /product:epicNotes#
- Step function stubs are intentionally unimplemented (
throw UnimplementedError) โ they become the DoD for each Story in the Development stage - The BDD Coverage Gate (Step 8.3 in /dev:run) will enforce that all step stubs are implemented before PR creation
- Brick selection uses a best-match heuristic; use
--brickto override if the auto-match is incorrect - For features without a matching brick, the scaffold phase creates a minimal Clean Architecture directory structure