문서 목차
이 페이지에서목차

단계별 실행 계약

`cc-product:pm`의 요구사항 분석을 사용한다. 입력 파일의 원래 이름·형식·메시지 ID·페이지/섹션을

1. PRD — 채팅/첨부 → 1차 HTML 요구사항#

cc-product:pm의 요구사항 분석을 사용한다. 입력 파일의 원래 이름·형식·메시지 ID·페이지/섹션을 보존해 source_id로 인용한다. 중복 요구는 병합하고 모순은 질문 또는 가정으로 표시한다. PDF/슬라이드/이미지의 표·주석도 확인한다. 읽지 못한 첨부는 source coverage 미통과다.

  1. templates/requirements.example.json을 따라 requirements.json 작성.
  2. 목표·사용자·범위·FR/NFR·AC·Site/App/Console 화면·역할·주요 동선·preview/live 경계·미결정과 제품 방향(direction — 대상·핵심 행동·톤)을 포함. 각 요구와 화면은 안정된 ID를 갖는다. 첨부 없는 순수 채팅도 메시지를 source로 기록한다. cc-writing이 설치됐다면 product-writing으로 주요 역할/화면별 사용자 행동·상태 문구를, content-writing으로 공개 페이지의 고객 질문·근거·CTA를 확인해 화면의 요구/AC에 반영한다. 확인되지 않은 기능·가격·효과는 홍보 문구로 확정하지 않는다.
  3. 중요한 미결정(거래/권한/개인정보 공개/배포 대상)은 사용자에게 모아 질문한다. 제품 방향이 출처에 없으면 같은 묶음에 넣는다(cc-blueprint 의 figma-direction §D1 — 톤은 '깔끔하고 모던' 같은 말이 아니라 구체적 이미지). 답이 없으면 출처에서 추론해 direction 에 적고 추론한 칸을 direction.inferred 에 남긴다 — 방향은 되돌릴 수 있는 디자인 판단이 아니라 제품의 관점이라, 추론보다 묻는 쪽이 먼저다. 색상·간격처럼 되돌릴 수 있는 디자인 판단은 design-decision으로 확정한다. 매 단계 승인 질문을 반복하지 않는다.
  4. render_prd.py --input requirements.json --html prd.html --markdown prd.md 실행. HTML은 읽기용 1차 문서, Markdown은 같은 JSON에서 생성한 Figma/cob 입력이다. 독립적으로 두 PRD를 편집하지 않는다. 스크린샷/브라우저로 HTML 표·인쇄·한글 확인.
  5. 두 화면 이상에 걸치는 AC(통화·로케일 설정, 인증/본인확인 상태, 차단 목록, 안전한 뒤로가기·딥링크, 탭 라벨 i18n, 아이콘 세트 등)는 요구 문장에 "공통"으로 드러나게 쓴다. 구현 단계의 공통 배선이 이 목록에서 공유 계약을 먼저 만든다(§4-1).
  6. 질문 답변이 오면 JSON부터 갱신해 다시 렌더. prd 완료는 분석/문서 확정이며 제품 구현 완료가 아니다.

2. 디자인 — CoUI Figma#

cc-blueprint:design --spec <prd.md> --file <url> 또는 --new-file <name>을 문서 절차로 수행한다. Site와 App, Console의 요구 화면을 모두 그린다. Widgetbook은 Flutter 화면의 컴포넌트/상태 전시장이다.

  • 방향은 prd.md 「방향」의 세 칸을 / 로 이어 --direction 으로 넘긴다. 무인 실행이므로 디자인의 Step 0.4(방향)·1.6(변주안)은 묻지 않고 정해진 기준으로 고른다. 「방향」의 '추론함' 칸은 디자인 보고 첫 줄의 출처로 그대로 옮긴다 — --direction 으로 넘겨도 추론은 추론이다.
  • 요청의 figma.ledger(조직의 다양성 장부 경로)가 있으면 --ledger 로 넘긴다. 장부 비교·갱신은 figma-direction §D4 를 따르고, 장부가 없으면 디자인 보고의 축 기록만 남긴다.
  • Figma 파일 생성 전 도구가 요구하는 figma-create-new-file guidance/plan 결정을 따른다. plan 여러 개일 때 임의 조직 선택 금지. 파일/노드 ID는 실제 응답을 저장한다.
  • CoUI 라이브러리 검색→인스턴스 임포트→variable 바인딩. coui.version.json과 실제 소비 CoUI 릴리스의 API 세대를 확인하고 라이브러리/fileKey/참조 SHA를 기록한다.
  • 화면 레지스트리는 figma-widgetbook-alignment의 현재 스키마를 사용. 조립 전에는 run-dir에 두고, 조립 성공 후 프로젝트 docs/figma-screen-registry.yaml로 인계한다. 그때 정본 경로를 전환하고 디자인 단계의 사본은 변경하지 않는 증거로 보존한다.
  • 시각 검토 계약에 따라 대표 화면 먼저 크리틱→수정→재검토한 뒤 전체를 확장한다.
  • self-check L0=0, 요구 화면 누락 0과 별도의 시각 검토 통과가 완료 조건. 미지원 썸네일 지정처럼 비필수 기능은 L2로 기록하며 지원되지 않는 API를 반복 호출하지 않는다.
  • 화면별 Loading/Empty/Error 필요 여부, 요소별 CoUI 부품 첫 후보, CoUI 결함 분류와 결함 이슈 중복 확인은 반사 판정에 먼저 묻는다(screen-states · coui-component · coui-defect · duplicate). 상태는 엄격화 전용이라 Jev 의 false 로 빼지 않는다.

3. 조립 — 초기 생성물의 빌드 가능성#

cc-bricks:project-init과 donor-registry를 읽고 설치된 cob의 실제 CLI를 확인한다. 카탈로그에 없는 이름, 동명 common/auth compose, 도너 SCC, console 기본 모드를 확인한다. PRD의 기능은 capability/recipe/atomic compose로 매핑하고 FR별 지원/미지원 이유를 남긴다. 이름이 비슷하다고 도너 도서스토어를 환전 서비스에 넣지 않는다. FR마다 브릭 대응과 책 도메인 필요 여부는 반사 판정의 feature-brick 세트에 먼저 묻는다 — Jev 는 도너 브릭을 빼는 쪽으로만 움직인다. 생성물에 남은 도너 문구는 donor-trace 로 문자열마다 판정한다.

  1. PRD→proposals→plan 경로가 제공되면 cob의 prd-ingest 계약을 따르고 project.yaml 직접 작성 금지 규약을 보존한다. 단순 명시 spec 경로는 설치된 cob schema/도움말이 허용한 것만 사용.
  2. generate --dry-run 후 실제 생성. --no-safety-check, 실패 무시, 임의 force로 우회하지 않는다.
  3. project.enable_website: true, project.enable_admin: true, project.console_skeleton: true가 spec의 project:에 들어 있는지 확인한다. has_web은 Flutter 배포 게이트일 뿐 웹사이트 생성 플래그가 아니다. 선택된 application/console feature, web/_site · app/console/widgetbook 셸, workspace 멤버(사이트는 멤버가 아니다 — 독립 pub 워크스페이스), pubspec, router·DI·widgetbook registry가 같은 선택 집합인지 검사한다. 미등록 패키지를 무조건 지우는 후처리 대신 조립 계약 오류를 고친다. enable_admin: true만으로 도너 콘솔이 허용되지는 않는다.
  4. 고정 Flutter/Dart·cob·bricks SHA/버전과 원래 생성 로그/스냅샷을 저장한다. CoUI는 원격 최신 stable Flutter/Web 릴리스를 포함하는 SHA로 맞추고 모든 pub 루트의 manifest/lock 일치 및 최신성 검사 결과를 저장한다(재개 작업에도 동일). 스캐폴드가 데이터·백엔드를 생성했다면 설치→서버 프로토콜 생성→클라이언트/Slang/Freezed 등 프로젝트 제공 codegen을 의존 순서대로 실행한다. 전역 serverpod 버전과 생성물 버전 일치 확인.
  5. 화면 수정 전 Serverpod generate/analyze와 각 셸 analyze, 사이트 dart pub get + bash scripts/ci.sh (Jaspr static build · 산출물 검증 포함) + Flutter release web build. 기본 엔트리 경로/허용된 flavor는 실제 프로젝트에서 찾는다. 지원 범위 내 테스트도 실행. 이 결과가 baseline_builds 증거다.
  6. CI를 지금 설치한다 — 배포 단계까지 미루지 않는다. pages.json·build_pages.py·jaspr_ci.py· prepare.sh(예시를 실제 melos scripts/Makefile 명령으로 교체)와 templates/product-pages.yml을 pages 계약대로 설치하고 화면 수정 전 베이스라인을 브랜치/PR로 push한다. 그 run이 completed/success가 될 때까지 고친 뒤 gh run view <id> --json headSha,status,conclusion,url,event 응답을 ci_baseline 증거로 남긴다. PR run은 배포하지 않는다. 러너 전용 결함(.fvm 부재로 melos SDK 경로 실패, macOS에서 만든 골든의 Linux 비교, 메모리 부족, 빌드 옵션 과다)은 여기서 드러나야 하며, 구현 단계와 병렬로 고친다 — CI 대기가 구현을 막지 않도록 run을 띄워 두고 §4를 시작해도 된다. 단 scaffold pass는 green run을 받은 뒤에만 한다.

조립 단계는 API 서버 가동 없이도 빌드 가능해야 한다. preview 프로필이 필요하면 공급 템플릿에 선언된 프로필을 사용한다. 없는 프로필을 생성물에서 손으로 발명한 뒤 깨끗한 조립이라고 기록하지 않는다. 공급 결함을 고쳤으면 이전 실패 트리를 실행별 snapshot으로 보존한 뒤 같은 project.root를 빈 상태로 재생성하고 다시 게이트를 통과시킨다. 다른 root로 바꾸려면 새 job으로 시작한다. 도너 monorepo는 serverpod_cli 4.1.0-beta.1과 서버·클라이언트·인증 계열의 동일 핀으로 첫 serverpod generate를 통과해야 한다. generated/future_calls.dart 미생성·getter 누락이 다시 나오면 반복 실행이나 생성 파일 스텁 대신, FutureCall 구현에서 생성 dispatcher 직접 참조가 재도입됐는지 브릭을 고치고 빈 root에서 재생성한다(bricks#353 회귀).

4. 구현 — 초기 프로젝트를 기반으로 화면 개발#

세 하위 단계로 진행하고 각각의 시작/끝을 evidence/implement-timing.md에 적는다.

4-1 공통 배선(fan-out 전). PRD의 공통 AC(§1-5)에서 여러 화면이 같이 쓰는 계약을 먼저 한 곳에 정의·등록한다: 통화/로케일 설정 상태, 인증·본인확인 상태와 가드, 차단 목록, 안전한 내비게이션 (뒤로가기·딥링크 복귀 규칙), 탭/메뉴 라벨 i18n 키, 아이콘 매핑. 그룹 에이전트는 이 계약을 가져다 쓰기만 하고 같은 개념을 따로 만들지 않는다. 실측 한 건에서 통합 단계 74분 중 23분이 그룹별로 중복 생성된 설정·상태·라벨을 합치는 데 쓰였다.

4-2 화면 그룹 fan-out. 대표 구현을 Figma와 같은 viewport/상태/데이터로 비교해 구조·위계 차이를 고친 뒤 그룹을 확장한다. 한 그룹은 화면 3–4개로 나눈다(실측 가장 긴 그룹이 53–55분이었다). 같은 feature 패키지를 두 그룹이 동시에 고치지 않게 나눈다. 그룹 안의 analyze/test는 변경한 패키지만 돌린다(예: melos exec --diff=<base-ref> -- dart analyze ., 해당 패키지의 flutter test). 전체 melos run analyze(실측 9분)는 4-3에서 한 번, 그리고 PR CI의 full prepare가 맡는다.

4-3 통합. 라우트·DI·widgetbook 등록을 합치고 전체 analyze/test를 한 번 돌린 뒤, 런타임 스모크로 화면 도달성을 확인한다. 화면 커버리지 표의 라우트마다 기대 문구를 적은 스펙(예시)을 만들고, 로컬 build_pages.py 출력에 대해 runtime_smoke.py --serve <out> --base-path /<repo>/로 실행한다. 브라우저를 손으로 클릭하며 도는 대신 이 보고서와 스크린샷을 검토한다. 같은 스펙을 배포 단계에서 재사용한다.

화면별로 cc-blueprint:build를 사용하되 기존 모듈에 통합한다. 사이트는 web/<name>_site 워크스페이스의 페이지별 기능 패키지(feature/<page>)와 매니페스트(packages/core SitePage)에 구현하고(사이트 README 의 페이지 추가 절차), 링크 · 자산은 SiteLocation 상대 경로로 둔다 — <base>·절대 경로를 쓰지 않는다. SSG 결과는 bash scripts/ci.sh 로 확인한다. 새 형제 *_screens 앱을 만들어 정상 엔트리 대신 배포하지 않는다. 생성된 entity/UseCase/Repository 계약·routes/DI와 연계한다. 화면의 소유 패키지(병렬 그룹)와 그룹이 올린 공유 요청의 행선지(core 공유 계약 · 그룹 내부 · 실서버 전 보류)는 반사 판정의 screen-owner · shared-request 에 먼저 묻는다.

  • blueprint의 프레젠테이션 온리 규약은 이번에 추가하는 화면 코드 범위에 적용한다. cob이 이미 만든 data/backend를 삭제하거나 "data 0" 체크를 위해 스텁하지 않는다.
  • 기존 데이터 계약이 시안과 다르면 요구/계약 차이를 기록해 적절한 소유 레이어에서 정합시킨다. preview일 때 mock은 DI 경계에서 주입하고 앱/콘솔 정상 엔트리의 선언된 preview 모드를 사용. live일 때 cc-serverpod/실제 backend 스킬로 API를 연결하고 no-op 처리로 성공을 만들지 않는다.
  • feature 소유 nested widgetbook 패키지, 1 Page=1 use_case, 상태 Knob, this.bloc 주입, designLink, 상태별 골든은 widgetbook-conventions/widgetbook-wiring 계약 그대로.
  • app·console에서 라우트로 화면에 도달 가능한지 검사(4-3 런타임 스모크 보고서). 이름만 등록하고 실제 메뉴/동선에서 열 수 없으면 screen_coverage 미통과. 중요 FR별 테스트·행동 확인과 mock/live 분류표를 남김.
  • cc-writing이 설치됐다면 product-writing으로 default/loading/empty/error/success의 실제 동작과 문구를 대조하고, 공개 콘텐츠는 content-writing으로 출처·링크·제목/헤딩을 검수한다. 구현 문자열은 프로젝트 i18n 계약으로 인계하며 검증되지 않은 성공/성과를 주장하지 않는다.
  • /cc-blueprint:sync L0=0 + 범위 내 섹션 누락 0, 단위/위젯/필요 E2E 통과. UI 변경 후 실행 앱에 hot reload/restart하고 웹은 release 브라우저 검증 사용. 연결 불가를 검증 완료로 표현하지 않는다.

5. 배포 — 네 웹 surface를 하나의 GitHub Pages 사이트로#

cc-aws:cicd-pipeline과 pages 배포 절차를 수행한다.

  1. 소스 저장소는 정상 기본 브랜치에 유지. build/web/.git을 만들거나 소스 없는 gh-pages를 기본 브랜치로 쓰지 않는다. 빌드 출력은 CI에서만 묶는다.
  2. 프로젝트에 schema 2 templates/pages.example.json을 채워 tool/product_auto/pages.json으로 저장하고 scripts/build_pages.py와 scripts/jaspr_ci.py를 동일 폴더에 복사. 이것은 배포 어댑터이며 앱 코드 패치가 아니다.
  3. 워크플로·prepare.sh는 조립 단계(§3-6)에서 이미 설치되어 베이스라인 green을 받았다. 여기서는 구현 중 바뀐 codegen/엔트리만 반영한다. 사이트 빌드와 Flutter 세 빌드가 모두 성공해야 upload-pages-artifact를 한 번 실행하고 deploy-pages도 한 번 실행.
  4. GitHub가 반환한 실제 Pages base URL 아래 /site/, /app/, /console/, /widgetbook/을 확인. live는 Pages 외부의 Serverpod API 상태·실제 요청도 확인한다. 정적 Pages 배포만으로 백엔드 배포 완료라고 기록하지 않는다.
  5. 4-3의 스모크 스펙으로 runtime_smoke.py --base-url <pages_url>을 실행해 배포 URL의 도달성·딥링크 새로고침·콘솔 오류를 확인하고 스크린샷을 검토한다. 핵심 동선의 행동(입력·전송)은 브라우저 검증으로 보탠다.
  6. 배포 run/head SHA, 서빙된 build.json, 스모크 보고서·브라우저 증거를 남긴 후 완료 처리.

단계 5가 실패하면 마지막 정상 사이트를 유지한다. 성공한 widgetbook만 먼저 발행해 전체 성공으로 표시하지 않는다. 부분 산출물은 작업 디렉토리에서 확인 가능하다.

조립·구현·배포 중 CI·빌드가 실패하면 원인 분류와 직전 실패와 같은지를 반사 판정의 ci-failure · same-failure 에 먼저 묻는다. 원인은 수정 위치만 고르고, 게이트 판정은 바꾸지 않는다.

검색어를 입력하면 문서를 찾습니다.

↑ ↓ 이동 · Enter 열기Esc 닫기