Files
llm-wiki/raw/branch-notes/feature-frontend-ci-quality-gates-contract.md
T

308 lines
36 KiB
Markdown

---
title: branch / feature-frontend-ci-quality-gates-contract
source_type: branch-note
status: raw
id: BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-027
kind: project-work-item
project: ca-skeleton-frontend-operational-contract
work_item: WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-027
inherits: [DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TEST-STACK-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SUPPLY-CHAIN-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-DEPLOYMENT-001@1]
refines: []
overrides: []
depends_on: [WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-017, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-020, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-024, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-025, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-026]
contract_packet: 1
branch: feature-frontend-ci-quality-gates-contract
parent_branch:
related_projects: [ca-skeleton-frontend, ca-skeleton]
governing_docs: [raw/project-notes/ca-skeleton-frontend-operational-contract]
tags: [branch, ca-skeleton, frontend, ci-cd, build-tooling, static-analysis, supply-chain]
created: 2026-07-18
target_merge:
status_label: in-progress
contract_packet_sha256: 642f71eb6bed0e706b19f3c814c85a626371ec65a0fc08eef602c9185b13e6dd
imports: [FE-GATE-001@1, FE-GATE-002@1, FE-GATE-004@1, FE-GATE-012@1, FE-GATE-014@1, FE-GATE-016@1, FE-GATE-018@1, FE-GATE-021@1, FE-OC-016@1, FE-OC-017@1, FE-OC-018@1, FE-OC-019@1, FE-OC-020@1, FE-OC-021@1, FE-OC-022@1, FE-OC-023@1, FE-OC-025@1]
---
# branch: feature-frontend-ci-quality-gates-contract
> Layer: `raw/branch-notes/` — TODO·결정·진행 기록. 현재는 `/branch-spec` 로 spec 을 채운 `planned` 단계다(frontend 코드 저장소 미생성). 구현 결과는 검증 뒤 `/ingest`로만 추출한다.
<!-- section-id: branch-parent -->
## 부모 (필수)
[[raw/project-notes/ca-skeleton-frontend-operational-contract]]
<!-- GENERATED: branch-contract:start -->
<!-- section-id: branch-contract-packet -->
## 브랜치 계약 패킷
- **생성 시 프로젝트 개정**: `1`
- **패킷 스키마**: `contract_packet: 1`
- **완료 조건**: blocking gate가 분리되고 dependency graph와 artifact retention이 검증된다
<!-- section-id: inherited-project-decisions -->
### 상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
| `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TEST-STACK-001@1` | test stack default는 Vitest, RTL, MSW, Playwright, axe다 | test gate 결과의 CI stage orchestration에 적용 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] |
| `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SUPPLY-CHAIN-001@1` | dependency lock, secret scan, vulnerability scan, license inventory, dependency review를 merge/release gate로 분리한다 | supply-chain gate의 blocking·artifact retention 배선에 적용 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] |
| `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-DEPLOYMENT-001@1` | static release는 immutable release directory와 atomic active pointer로 배포한다 | release·production-promotion stage와 rollback artifact retention에 적용 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] |
<!-- section-id: branch-local-decisions -->
### 브랜치 지역 결정
> 기존 branch-local 결정은 아래 `## Decision Evidence Map / 결정-근거 매핑`의 D-row가 소유하며 이 packet에서 복제하지 않는다.
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|---|---|---|---|
<!-- section-id: declared-overrides -->
### 선언한 예외
| Override ID | Overrides | Reason | Approval | Status |
|---|---|---|---|---|
<!-- GENERATED: branch-contract:end -->
<!-- section-id: branch-goal -->
## 목표
이 branch 는 **어느 `FE-OC-*` 의 single owner 도 아니다.** 대신 `FE-OC-020`·`FE-OC-021`·`FE-OC-022`·`FE-OC-023`·`FE-OC-024`·`FE-OC-025` 의 acceptance gate 들을 **하나의 실행 가능한 CI orchestration** 으로 묶는 contribution branch 다([[raw/project-notes/ca-skeleton-frontend-operational-contract]] §20 Branch Decomposition — Primary contract IDs `—`, Measurable completion = "separate blocking gates, dependency graph, artifact retention"). 구체적으로 [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.1 의 26-gate acceptance matrix 와 §15.3 promotion formula(MERGE_READY → RELEASE_READY → PROD_PROMOTION_READY → FIELD_SLO_READY)를 CI pipeline 의 **stage dependency graph + blocking-check 배선 + evidence artifact retention 정책** 으로 내린다. gate 의 *정의*(blocking scope·Covered FE-OC·pass condition·evidence artifact)와 promotion formula 는 [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.1·§15.3 이 소유하고, gate 별 Owner 는 §2.1.1 이 확정한다. gate → **test level / fixture KIND** taxonomy 와 `artifacts/` 트리 taxonomy 는 [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] (`FE-OC-020`) 가, gate 의 *fixture 본문* 은 각 contract owner 가 소유한다. 이 branch 는 그 gate 들이 **어떤 순서로 / 어떤 blocking 의미로 / 어떤 의존 관계로 실행되고, 그 증거가 어떻게 보관되는지** 만 명세한다. 모든 진술 등급은 `planned` — frontend repository 와 CI 설정이 아직 없다.
- 이슈: 없음 (repository·CI 미생성)
- PR: 없음
<!-- section-id: branch-scope -->
## 범위
### 포함 범위
이 branch 가 소유하는 CI orchestration 레이어(gate 정의가 아니라 gate 의 *실행/배선/보관*):
- **Gate stage dependency graph** — [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.3 promotion formula 를 CI pipeline 의 4 stage(merge / release / prod-promotion / field-SLO)로 매핑하고, downstream stage 가 upstream stage 의 gate 집합 전부 PASS 없이는 실행/승격되지 않는 AND 의존을 배선.
- **Blocking-check 배선 + no-downgrade 집행** — §15.1 Blocking scope 열의 각 gate 를 독립 required check 로 wiring 하고, gate 실패를 warning / soft-fail / `continue-on-error` 로 낮추지 못하게 강제(`FE-OC-020` normative summary).
- **Evidence artifact retention 정책** — 각 gate 가 §14.3 / §15.1 이 정한 evidence artifact 를 공유 `artifacts/` 트리에 산출하도록 upload/retention 을 배선하고, rollback target(§12.5)·drill record(`FE-GATE-016`/`FE-GATE-021`~`025`)가 승격 감사에 필요한 기간 동안 남도록 retention class 를 정의.
- **Gate → CI trigger 매핑** — 각 gate 가 어느 event(merge PR / release / production promotion / field-window)에서 실행되는지의 배선.
### 제외 범위
> 의도적으로 제외 — 다른 owner 소유. 여기서는 이름만 가리키고 detail 을 재명세하지 않는다(CLAUDE.md §15.5 R3).
- **Gate 정의와 promotion formula**(blocking scope·Covered FE-OC·pass condition·evidence artifact·tier→gate 집합) → [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.1·§15.3, gate 별 Owner 는 §2.1.1.
- **Gate taxonomy**(gate → test level / fixture KIND 열거·negative-fixture-per-gate 규칙·`artifacts/` 트리 taxonomy) → [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] (`FE-OC-020`). 이 branch 는 둘 다 *consume* 만 하고 재정의하지 않는다.
- **각 gate 의 fixture 본문·pass-condition** → contract owner 위임: build/bundle/security → [[raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract]] (`FE-OC-018`); release-coherence/config-compat/rollback/hosting-header → [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] (`FE-OC-016`, `FE-OC-017`, `FE-OC-019` — hosting-header gate 의 security 축); bundle/lab/field performance → [[raw/branch-notes/feature-web-vitals-performance-budget-contract]] (`FE-OC-021`); runbook drill(`FE-RB-001`~`005`) → [[raw/branch-notes/feature-frontend-operational-runbook-contract]] (`FE-OC-025`); registry diff → [[raw/branch-notes/feature-frontend-contract-registry-governance]] (`FE-OC-022`); compatibility fixture → [[raw/branch-notes/feature-frontend-contract-compatibility-governance]] (`FE-OC-023`); sample-removal → [[raw/branch-notes/feature-sample-feature-slice-contract-fixture]] (`FE-OC-024`); merge-tier test gate 본문 → 각 test/arch owner.
- **구체 CI provider workflow syntax + 실제 merge protection / required-check 설정** — provider 미확정([[raw/project-notes/ca-skeleton-frontend-operational-contract]] §14.1 CI runner 미확정, `FE-Q-002`/`FE-Q-003`/`FE-Q-007`/`FE-Q-010`). 이 branch 는 provider-agnostic orchestration contract 만 정의(D6).
- **NFR 임계값·gate pass-condition 수치**(timeout 10s / retry ≤2 / bundle KiB / axe 0 / p75 등) → 각 NFR owner. orchestration 은 gate 결과만 소비.
## 근거 (필수, 최소 1개+)
| Source | 정당화하는 결정 |
|---|---|
| [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.3 promotion formula | D1 stage dependency graph(4 tier AND 의존)의 1차 근거. |
| [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.1 gate matrix (Blocking scope · Evidence artifact 열) | D2 blocking-check 배선 + D3 artifact→gate 매핑의 근거(26-row acceptance gate registry). |
| [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-020` normative summary | D2 no-downgrade 불변식("실패를 warning 으로 낮추면 안 됨")의 근거. |
| [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §14.3 planned commands (artifact 열) + §4.6 `artifacts/` blueprint | D3 evidence artifact retention 트리(script→artifact 매핑)의 근거. |
| [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §12.5 rollback invariant + §15.1 `FE-GATE-016`(prior release pair) | D3/D4 retention 하한(rollback target·drill record 가 다음 release 승격까지 생존)의 근거. |
| [[raw/official-docs/supply-chain-slsa-provenance-framework]] `SLSA-FW-C6`, `SLSA-FW-C4` | D3 rationale — release/security evidence 는 machine-readable provenance(in-toto attestation = "authenticated, machine-readable statement about a software artifact")이므로 CI 가 retain/traceable 하게 보관해야 함. **범위 한정**: SLSA 는 build provenance *artifact* 의 machine-readability/traceability 만 근거하고, gate ordering·blocking 정책은 근거하지 않음(그건 hub §15.3 project decision). SLSA gate/fixture 본문은 [[raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract]] (`FE-OC-018`) 소유. |
## TODO
- [ ] §15.3 promotion formula 를 CI 4-stage dependency graph(merge → release → prod-promotion → field-SLO)로 배선 + stage 간 AND gating 명세 — 등급: `planned`
- [ ] §15.1 각 gate 를 독립 required check 로 wiring + no-downgrade(`continue-on-error` 금지) 집행 규칙 정의 — 등급: `planned`
- [ ] evidence artifact upload + retention class(merge/release/prod-drill) 정의; rollback target·drill record 가 다음 release 승격까지 생존하도록 하한 고정 — 등급: `planned`
- [ ] artifact retention **기간 수치**(day/count) 확정 — 등급: `needs-confirmation` (`UNSUPPORTED_DECISION` — hub 미규정, D4)
- [ ] provider 선택 후 required-check 이름 + branch-protection 을 이 orchestration contract 에 바인딩 — 등급: `planned` (provider 미정, out of scope)
## 진행 중 메모
- `/branch-spec` self-map 완료(2026-07-19): 이 branch 는 no-primary-owner contribution branch. SSOT = hub §15.1 gate matrix + §15.3 promotion formula + §14.3 artifact 열 + §12.5 rollback invariant. gate 정의(blocking scope·Covered FE-OC·pass condition·evidence artifact)는 hub §15.1 소유이고 gate → test level / fixture KIND taxonomy 는 [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] 소유이므로 26-row 표를 복제하지 않고 **stage 레벨**로만 orchestration 을 명세(RESTATED_FOREIGN_DECISION 회피).
- 4개 dependency sibling(build-supply-chain / release-cache / web-vitals / operational-runbook)이 모두 자기 Out of scope 에서 "CI gate orchestration · 실행 순서 · artifact retention" 을 이 branch 로 위임 확인 — 방향 일관.
- 외부 web research 불필요(모든 orchestration 결정 hub-grounded). SLSA 는 seeded source 를 artifact-provenance-retention rationale 로만 범위 한정 인용. frontend 코드·CI 부재 → 전부 `planned`.
## 결정 사항
> 각 결정의 근거는 아래 Sources 및 Decision Evidence Map 참조.
- 2026-07-19: **CI pipeline = §15.3 promotion formula 를 그대로 반영한 4-stage dependency graph** (merge → release → prod-promotion → field-SLO); downstream stage 는 upstream stage gate 전부 PASS 전에는 실행/승격 불가(AND) / 검토한 대안: 단일 flat gate 집합(stage 없음) / 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.3.
- 2026-07-19: **각 gate 는 독립 blocking required check**; 선언된 Blocking scope 내에서 실패는 warning/soft-fail/`continue-on-error` 로 낮출 수 없음 / 검토한 대안: 비핵심 gate 를 non-blocking advisory 로 강등 / 근거: `FE-OC-020` normative summary + §15.1 Blocking scope 열 + §15.3.
- 2026-07-19: **각 gate 는 evidence artifact 를 공유 `artifacts/` 트리에 산출하고 CI 가 이를 retain**(승격 감사 trail); rollback target·drill record 는 최소한 다음 release 가 승격될 때까지 생존 / 근거: §14.3 artifact 열 + §12.5 rollback invariant + `SLSA-FW-C6`.
- 2026-07-19: **artifact retention 기간(day/count)·storage backend 는 미결정**`UNSUPPORTED_DECISION`; hub 는 *어떤* artifact 를 남기는지만 규정하고 *얼마나* 보관하는지는 규정 안 함. 하한만 rollback invariant 로 grounding, 수치는 provider/조직 정책 확정 후 채움.
- 2026-07-19: **fixture 본문·gate pass-condition 은 CI 가 정의하지 않고 owner branch 에 위임**(R3); orchestration 은 gate 결과·artifact·blocking 만 배선 / 근거: §20 dependency 열 + §15.1 Covered-FE-OC.
- 2026-07-19: **provider-agnostic orchestration contract**; 구체 workflow syntax·required-check 이름·branch-protection 은 provider 선택 시 바인딩(deferred) / 근거: §14.1 CI runner 미확정 + `FE-Q-002`/`FE-Q-003`/`FE-Q-010`.
## 결정-근거 매핑
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|---|
| D1 | CI pipeline 을 §15.3 promotion formula 와 동형인 4-stage dependency graph(merge → release → prod-promotion → field-SLO)로 배선; downstream stage 는 upstream gate 전부 PASS 전 실행/승격 불가(AND) | 이 조건: gate 들이 §15.3 의 4 promotion tier 로 분류될 때. 대안(flat 배선): 새 blocking scope 가 추가되면 §15.1 gate 수와 promotion formula 를 함께 갱신하고 stage graph 도 재도출(§15.1 "이 수와 promotion formula 를 함께 갱신") | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.3 promotion formula; §15.1 Blocking scope 열 | `project-decision` (hub formula 도출) | stage 내 fail-fast vs full-fan-out, stage 간 부분 재실행 정책을 hub 가 규정하지 않음 |
| D2 | 각 gate = 독립 blocking required check; 선언된 Blocking scope 내 실패를 warning/soft-fail/`continue-on-error` 로 낮출 수 없음 | 불변식(분기 N/A) — `FE-OC-020` 이 downgrade 를 금지하고 각 promotion tier 가 지정 gate 집합의 AND 로 고정돼 우회 여지가 없으므로 항상 blocking | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-020` normative summary; §15.1 Blocking scope 열; §15.3 formula | `accepted-documented-only` (invariant) | downgrade 를 실제로 막는 지점은 provider 의 branch-protection/required-check 설정 — provider 미확정(D6) |
| D3 | 각 gate 는 §14.3/§15.1 이 정한 evidence artifact 를 공유 `artifacts/` 트리에 산출하고 CI 가 retain; rollback target(§12.5 coherent set)·drill record 는 다음 release 승격까지 생존 | 이 조건: gate 가 machine-readable evidence 를 남길 때(전 gate). 대안: script rename 시 gate+artifact 매핑을 동시 갱신해야 함(§14.3 말미) — 매핑 갱신 없는 rename 금지 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §14.3 artifact 열, §4.6 `artifacts/` blueprint, §12.5 rollback invariant, §15.1 `FE-GATE-016`(prior release pair); `raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C6`, `#SLSA-FW-C4` (machine-readable provenance retention rationale, 범위 한정) | `project-decision` (경로/트리) + `official-standard` (provenance-artifact retention rationale) | artifact 포맷(JUnit XML/SARIF/JSON)이 실제 CI reporter/artifact store 와 호환되는지 미검증 |
| D4 | **UNSUPPORTED_DECISION** — artifact retention 기간(day/count)·storage backend·tier 별 차등 보관은 hub 미규정. 하한(rollback target·drill record 는 다음 release 승격까지 보관)만 §12.5 로 grounding, 구체 수치는 미결정 | 이 조건: rollback/drill evidence 는 다음 release pair 검증 전 삭제 금지(§12.5, `FE-GATE-016` "prior release pair"). 대안: merge-tier lint/test artifact 는 1 build cycle 후 만료 허용 — **수치 자체는 근거 없음**(trade-off: 짧으면 rollback/audit 증거 유실, 길면 storage 팽창) | 없음 — hub §14/§15 는 *어떤* artifact 인지만 규정, retention 기간 미규정. `FE-Q-010`(security), `FE-Q-003`(provider)도 retention 수치 미포함 | `UNSUPPORTED` | 잘못된 retention → `FE-GATE-016` rollback drill 이 prior release pair 를 잃어 실행 불가; 값은 provider/조직 정책 확정 후 결정 필요 |
| D5 | fixture 본문·gate pass-condition 은 CI orchestration 이 정의하지 않고 각 FE-OC owner branch 에 위임; orchestration 은 gate 결과·artifact·blocking 배선만 소유(R3) | 이 조건: gate 가 단일 FE-OC owner 로 매핑될 때. 대안: 한 gate 가 다수 owner fixture 를 요구하면(예 `FE-GATE-004`/`005`/`007`) 모든 owner fixture 를 실행하도록 wiring 하되 test-level taxonomy owner([[raw/branch-notes/feature-frontend-test-taxonomy-contract]] `FE-OC-020`)가 조정 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §20 dependency 열; §15.1 Covered-FE-OC 열 | `project-decision` (R3 경계) | 없음 material — 위임 대상은 §엣지·실패·의존 참조 |
| D6 | provider-agnostic orchestration contract; 구체 workflow syntax·required-check 이름·branch-protection 은 provider 선택 시 바인딩(deferred) | 이 조건: provider 미확정 동안은 stage graph + blocking 불변식 + retention 정책만 정의. 대안: provider 확정 시 required-check 이름을 이 contract 의 gate 에 1:1 바인딩하고 branch-protection 을 stage graph 에 맞춤 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §14.1 (CI runner 미확정); `FE-Q-002`/`FE-Q-003`/`FE-Q-010` (open questions) | `deferred` / `conditional-default` | provider primitive 가 4-tier 를 독립 required check 로 표현 못 할 수 있음(예: 단일 job 강제) |
## 구현 가이드
> 전 항목 `planned` — frontend repository·CI 미생성. stage/artifact/경로는 hub §15.1(gate matrix)·§15.3(promotion formula)·§14.3(planned commands)·§4.6(directory blueprint)에서 도출한 blueprint 이며 repo·provider 확정 시 변경 가능. gate *정의* 는 재명세하지 않고 [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] taxonomy 를 consume(R3).
### 1. Stage dependency graph (promotion formula → CI stage)
> **Trace**: D1 · [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §15.3 / §15.1 Blocking scope 열
>
> - **UNSUPPORTED_IMPL_DECISION**: stage 내 gate 병렬 실행 시 **fail-fast(첫 실패에서 stage 중단) vs full-fan-out(전 gate 실행 후 집계)** 은 hub 미규정 → default 로 full-fan-out 제안(trade-off: full-fan-out 은 CI 시간↑ 이나 한 push 에서 여러 gate 실패를 한 번에 보고해 되돌이 횟수↓).
CI pipeline 은 §15.3 promotion formula 와 동형의 stage graph 다. downstream stage 는 upstream stage 의 gate 집합이 **전부 PASS** 이기 전에는 실행/승격되지 않는다(formula 의 `AND` 배선).
각 stage 의 **gate 집합은 hub §15.3 promotion formula 소유**이며 여기에 열거하지 않는다 — hub 가 gate 를 추가·supersede 하면 복제한 ID 목록만 조용히 낡는다. 본 표는 stage ↔ trigger ↔ 통과 의미의 배선만 정의한다.
| Stage | Trigger event | Gate 집합 | 의존(upstream stage) | 통과 의미 |
|---|---|---|---|---|
| S1 merge | PR → protected branch merge | hub §15.3 `MERGE_READY` 집합 | — | `MERGE_READY` |
| S2 release | release cut | S1 + hub §15.3 `RELEASE_READY` 추가분 | S1 (`MERGE_READY`) | `RELEASE_READY` |
| S3 prod-promotion | production promotion | S2 + hub §15.3 `PROD_PROMOTION_READY` 추가분 | S2 (`RELEASE_READY`) | `PROD_PROMOTION_READY` |
| S4 field-SLO | 28-day field window 후 | S3 + hub §15.3 `FIELD_SLO_READY` 추가분 | S3 (`PROD_PROMOTION_READY`) | `FIELD_SLO_READY` |
**Off-chain gate**(선형 승격 chain 밖 — §15.1 Blocking scope 열 그대로):
- `FE-GATE-017`(scoped diagram review, Blocking scope = documentation readiness, 현재 `PASS_SCOPED`) — 선형 merge→release chain 에 넣지 않고 문서 준비 gate 로 독립 배선.
- `FE-GATE-018` 은 위 S4 로, 다른 gate 와 달리 field window 종속이라 별 stage.
> 참고: `FE-GATE-008`(e2e)·`FE-GATE-009`(a11y)·`FE-GATE-011`(build)·`FE-GATE-013`(security) 등은 Blocking scope 가 "merge + release" 이므로 S1·S2 양쪽 required. 이 branch 는 gate 를 stage 에 배정만 하고, 각 gate 의 fixture/pass-condition 은 owner 소유(D5).
### 2. Blocking-check 배선 + no-downgrade 집행
> **Trace**: D2 · [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-020` / §15.1 Blocking scope 열 / §15.3
>
> - **UNSUPPORTED_IMPL_DECISION**: 없음 — blocking 규칙은 `FE-OC-020`("실패를 warning 으로 낮추면 안 됨") + §15.3 formula verbatim.
- 각 gate 는 §15.1 Blocking scope 열이 지정한 stage 에서 **독립 required check** 로 실행된다(통합 test job 으로 합치지 않음 — gate KIND 분리는 taxonomy owner 소유이나, CI 는 그 KIND 를 별 check 로 배선).
- gate 실패 → 해당 Blocking scope 의 promotion tier 를 `NOT_READY` 로 고정. **warning / soft-fail / `continue-on-error: true` / manual override 로 승격을 통과시키는 배선 금지**(`FE-OC-020` 위반).
- promotion 판정은 §15.3 formula 를 그대로 계산:
- `MERGE_READY` = S1 gate 전부 PASS
- `RELEASE_READY` = `MERGE_READY` AND S2 추가 gate 전부 PASS
- `PROD_PROMOTION_READY` = `RELEASE_READY` AND S3 추가 gate 전부 PASS
- `FIELD_SLO_READY` = `PROD_PROMOTION_READY` AND `FE-GATE-018` PASS
- exception/override 가 조직 정책상 필요하면 그 승인 owner·audit 기록을 **별도 결정 row 로** 등재해야 하며(§2.2 Q4 "허용되는 예외와 승인 owner"), 무기록 override 는 금지.
### 3. Evidence artifact retention
> **Trace**: D3 + D4 · [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §14.3 artifact 열 / §4.6 / §12.5 rollback invariant / §15.1 `FE-GATE-016` · `raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C6`
>
> - **UNSUPPORTED_IMPL_DECISION**: (a) retention **기간 수치**(아래 표 "보관 하한" 의 day/count) 전부 — hub 미규정(D4). rollback/drill 은 §12.5 로 "다음 release 승격까지" 라는 *상대적* 하한만 grounding, 절대 수치는 provider/조직 정책 확정 후. (b) storage backend(CI artifact store vs 별도 object store) 미규정 — default 로 CI 기본 artifact store 제안(trade-off: 기본 store 는 무료·간단하나 보관기간 상한/용량 제약이 provider 종속).
각 gate 는 §14.3/§15.1 이 정한 artifact 를 공유 `artifacts/` 트리(§4.6)에 산출하고 CI 가 upload/retain 한다. gate 는 자체 트리를 만들지 않는다(taxonomy owner 의 `artifacts/` SSOT 를 consume).
```text
artifacts/
quality/ install.txt · lint.txt · check-types.txt # S1
tests/ runtime-schema.xml · unit.xml · component.xml · integration.xml · a11y.json · sample-removal.xml · e2e/ # S1(+e2e S1/S2)
performance/ bundle.json · lab.json · field-web-vitals.json # bundle/lab S2, field S4
security/ scan.sarif # S1/S2
release/ build-manifest.json · verification.json · hosting-headers.json · dependency-inventory.* · checksums.txt # S2 (§12.1)
runbooks/ FE-RB-00N/<release-id>/record.json # S3 drill (FE-GATE-021~025)
```
| Retention class | 대상 artifact | 보관 하한(상대) | 근거 |
|---|---|---|---|
| merge-cycle | `quality/*`, `tests/{unit,component,integration,runtime-schema,a11y,sample-removal}` | `UNSUPPORTED` (수치 미정; 최소 해당 PR 승격 판정까지) | §14.3 artifact 열 |
| release-coherence | `release/*`, `performance/{bundle,lab}`, `security/scan.sarif` | **다음 release 가 승격될 때까지**(rollback target coherent set 생존) | §12.5 rollback invariant + `FE-GATE-016` prior release pair |
| prod-drill | `runbooks/FE-RB-00N/<release-id>/record.json` | **다음 production promotion 승격 판정까지**(drill evidence 는 승격 gate 입력) | §15.1 `FE-GATE-016`/`021`~`025` |
| field | `performance/field-web-vitals.json` | **28-day field window + 집계 완료까지** | §14.2 `FE-NFR-013`~`015`, `FE-GATE-018` |
- artifact 는 machine-readable(§14.3 확장자 `.xml`/`.sarif`/`.json`) 이어야 하고, release/security artifact 는 provenance 성격이므로 traceable 하게 보관(`SLSA-FW-C6`: in-toto attestation = machine-readable statement about artifact digests). **단** SLSA gate/fixture(build provenance attestation 생성 자체)는 [[raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract]] (`FE-OC-018`) 소유 — 이 branch 는 산출된 artifact 의 upload/retention 만 배선.
- script rename 은 gate+artifact 매핑 동시 갱신 조건으로만 허용(§14.3 말미) — retention 배선도 함께 갱신.
### 4. Fixture-content 위임 경계 (R3)
> **Trace**: D5 · [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §20 dependency 열 / §15.1 Covered-FE-OC
>
> - **UNSUPPORTED_IMPL_DECISION**: 없음 — 순수 위임 표. 이 branch 는 아래 gate 의 실행/blocking/retention 만 배선하고 fixture 본문은 owner 소유.
> - **owner 열 회수(2026-07-21)**: 이전 판은 gate 별 fixture-content owner 를 이 표에 복제했는데, 그 사본이 실제로 낡아 있었다 — `FE-GATE-001` 을 build-bundle 로 적었으나 hub §2.1.1 owner 는 `feature-frontend-project-bootstrap-toolchain-contract` 이고, `FE-GATE-014` 를 release-cache-rollback 으로 적었으나 hub owner 는 `feature-frontend-contract-compatibility-governance` 이며 지목된 branch 는 그 gate 를 한 번도 언급하지 않는다. 같은 문서의 §가져온 프로젝트 계약 표(아래)는 두 gate 모두 hub 와 같게 적고 있어 문서가 자기모순 상태였다. [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] 가 이미 같은 함정에서 회수한 선례를 따라 **owner 열을 삭제하고 hub §2.1.1 포인터만 남긴다.**
> gate 별 **Owner 는 hub §2.1.1 이 SSOT** 다. 이 표는 owner 를 재진술하지 않고, *이 branch 가 CI 에서 무엇을 배선하는가* 만 소유한다.
| Gate 군 | 이 branch 가 배선하는 것 |
|---|---|
| `FE-GATE-001,011,012,013` (install/build/bundle/security) | stage 배정 + required check + artifact retention |
| `FE-GATE-014,015,016,019` (config-compat/release-coherence/rollback/hosting-header) | stage 배정 + blocking + drill artifact 보관 |
| `FE-GATE-018,026` (field/lab performance) | stage 배정 + field window retention |
| `FE-GATE-021,022,023,024,025` (`FE-RB-001`~`005` drill) | prod-promotion stage 배정 + drill record retention |
| `FE-GATE-002,003,004,005,006,007,008,009,010,020` (test/arch/sample) | S1 배선 + required check |
| registry diff / compatibility gate | gate 결과 소비 |
## 엣지·실패·의존
- **실패·엣지 경로**:
- gate 실패가 `continue-on-error`/warning 으로 downgrade → `FE-OC-020` 위반(기대: promotion formula 가 해당 tier 를 `NOT_READY` 로 유지, 승격 차단).
- upstream stage 미완인데 downstream stage 실행 → dependency graph 위반(기대: S2/S3/S4 는 upstream gate 전부 PASS 전 skip).
- retention 만료로 rollback target/drill record 소실 → `FE-GATE-016` 이 prior release pair 를 잃어 실행 불가(기대: release-coherence/prod-drill retention class 가 다음 승격까지 보관, §12.5).
- script rename 후 gate+artifact 매핑 미갱신 → §14.3 위반(기대: drift check 가 매핑 불일치 검출, retention 배선도 함께 갱신).
- provider 가 4-tier 를 독립 required check 로 표현 못 함 → D6 open risk(기대: equivalent primitive + 그 rollback/blocking semantics 를 결정 row 로 기록, §12.4 유사 절차).
- flaky gate(e2e/perf) → deterministic fixture(fake clock §15.1 `FE-GATE-005`, recorded context metadata §14.1) 요구는 taxonomy/owner 소유; orchestration 은 flaky 결과를 PASS 로 취급하지 않도록 retry-suppression(무한 retry 로 통과 금지) 배선.
- **다른 계약 의존** (§20 dependency 열 + §4.3):
- [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] (`FE-OC-020`) — gate → test level / fixture KIND taxonomy 와 `artifacts/` 트리 taxonomy 를 이 branch 가 consume. 그 taxonomy 가 바뀌면 stage graph·retention 배선 재도출. (gate→FE-OC mapping 과 promotion formula 는 hub §15.1·§15.3 소유.)
- [[raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract]] (`FE-OC-018`) — install/build/bundle/security gate fixture·SLSA provenance artifact 제공. 산출 artifact 경로가 바뀌면 retention 배선 갱신.
- [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] (`FE-OC-016`, `FE-OC-017`, `FE-OC-019`) — release-coherence/rollback drill + hosting-header(cache·security) fixture 제공. rollback target coherent set(§12.5)이 retention 하한을 규정.
- [[raw/branch-notes/feature-web-vitals-performance-budget-contract]] (`FE-OC-021`) — bundle/lab/field gate pass-condition 제공. field window 가 S4 retention 을 규정.
- [[raw/branch-notes/feature-frontend-operational-runbook-contract]] (`FE-OC-025`) — `FE-RB-001`~`005` drill 본문 제공. drill record 가 prod-promotion 승격 gate 입력.
- [[raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract]] (`FE-OC-003`) — `pnpm test:*` script host / engine 없이는 어떤 gate 도 실행 불가(간접 의존; taxonomy 경유).
## 검증해야 할 주장
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
| required gate 실패가 merge/release/promotion 을 실제로 막는다 | CI·branch-protection 설정 없음 | provider 확정 후 negative fixture(§15.2)로 gate 를 고의 실패시켜 해당 tier 가 `NOT_READY` 로 승격 차단되는지 확인 | `needs-confirmation` |
| 4-stage dependency graph 가 §15.3 formula 와 정합(downstream 이 upstream AND 없이 승격 안 됨) | CI 미배선 | stage 별 gate 집합을 §15.3 verbatim 과 대조하고, upstream gate 1개 실패 시 downstream stage skip 을 e2e 로 확인 | `needs-confirmation` |
| gate 실패가 warning/`continue-on-error` 로 downgrade 되지 않음 | CI wiring·override 정책 미구현 | workflow 에 `continue-on-error` 부재 grep + override 감사 로그 확인 | `planned` |
| rollback target·drill record 가 다음 release/promotion 승격까지 생존 | retention 배선·수치 미정(D4) | release pair 를 만들어 `FE-GATE-016` 이 prior release artifact 를 실제로 사용할 수 있는지 drill(§12.5) | `needs-confirmation` |
| artifact 포맷(XML/SARIF/JSON)이 CI reporter/artifact store 와 호환 | reporter 미선택 | 각 gate reporter 산출물을 CI artifact upload + 재파싱으로 검증 | `planned` |
| retention 기간 수치가 조직/provider 정책에 부합 | hub 미규정(`UNSUPPORTED_DECISION`) | `FE-Q-010`/`FE-Q-003` resolution 으로 retention day/count 확정 후 배선 | `needs-confirmation` |
## 관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
- 스캐폴딩 단계: `/coverage` 실행 전 수동 행을 만들지 않는다.
## 마주친 문제
- 없음 — 구현 착수 전(`planned`).
## 묶음 (이 branch에서 파생된 자료)
<!-- GENERATED: project-contract-imports:start -->
## 가져온 프로젝트 계약
| Ref | Owner | 요약 | Branch 적용 |
|---|---|---|---|
| `FE-GATE-001@1` | [[raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract]] | lockfile 이 manifest 와 어긋나면 merge·release 를 MUST 차단 | import 참조로 적용 |
| `FE-GATE-002@1` | [[raw/branch-notes/feature-frontend-architecture-enforcement-lint-contract]] | 금지된 API·import 가 남아 있으면 merge 를 MUST 차단 | import 참조로 적용 |
| `FE-GATE-004@1` | [[raw/branch-notes/feature-runtime-schema-validation-contract]] | invalid fixture 가 예상 kind 로 거부되지 않으면 merge 를 MUST 차단 | import 참조로 적용 |
| `FE-GATE-012@1` | [[raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract]] | 번들 NFR threshold 초과면 release 를 MUST 차단 | import 참조로 적용 |
| `FE-GATE-014@1` | [[raw/branch-notes/feature-frontend-contract-compatibility-governance]] | 지원 대상 config 버전이 boot 에 실패하면 release 를 MUST 차단 | import 참조로 적용 |
| `FE-GATE-016@1` | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | rollback 과 smoke 증거가 없으면 production promotion 을 MUST 차단 | import 참조로 적용 |
| `FE-GATE-018@1` | [[raw/branch-notes/feature-web-vitals-performance-budget-contract]] | p75 목표 미달이거나 표본 임계가 미해결이면 field readiness 를 MUST 차단 | import 참조로 적용 |
| `FE-GATE-021@1` | [[raw/branch-notes/feature-frontend-operational-runbook-contract]] | `FE-RB-001` 의 containment·escalation·recovery 단언이 실패하면 production promotion 을 MUST 차단 | import 참조로 적용 |
| `FE-OC-016@1` | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | HTML, asset, runtime config, release manifest cache policy를 MUST 구분 | import 참조로 적용 |
| `FE-OC-017@1` | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | rollback은 immutable prior release로 수행하고 build/config/API compatibility를 MUST 검증 | import 참조로 적용 |
| `FE-OC-018@1` | [[raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract]] | frozen lockfile, dependency review, secret scan, SBOM 또는 dependency inventory를 release gate에 MUST 포함 | import 참조로 적용 |
| `FE-OC-019@1` | [[raw/branch-notes/feature-frontend-browser-security-boundary-contract]] | browser bundle에 secret을 넣지 않고 untrusted HTML injection을 기본 금지 | import 참조로 적용 |
| `FE-OC-020@1` | [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] | gate 종류별 책임·fixture·artifact를 분리하고 실패를 warning으로 낮추면 안 됨 | import 참조로 적용 |
| `FE-OC-021@1` | [[raw/branch-notes/feature-web-vitals-performance-budget-contract]] | NFR은 device/network/cache/build context와 함께 MUST 측정 | import 참조로 적용 |
| `FE-OC-022@1` | [[raw/branch-notes/feature-frontend-contract-registry-governance]] | 8개 registry는 single primary owner와 compatibility impact를 MUST 기록 | import 참조로 적용 |
| `FE-OC-023@1` | [[raw/branch-notes/feature-frontend-contract-compatibility-governance]] | API/config/storage/release schema의 breaking change는 migration 또는 version bump 없이 배포하면 안 됨 | import 참조로 적용 |
| `FE-OC-025@1` | [[raw/branch-notes/feature-frontend-operational-runbook-contract]] | boot, chunk mismatch, API degradation, telemetry failure, rollback runbook을 MUST 유지 | import 참조로 적용 |
<!-- GENERATED: project-contract-imports:end -->
- 없음 — 자식 자료는 생성 후 controller가 parent Cluster와 함께 등록한다.
## 관련 일일 노트
- 없음 — daily note는 이 작업에서 수정하지 않는다.
## 완료 후 정리
- PR 링크: 없음
- 리뷰 메모: 없음
- 머지 결과 / 배포 환경: `planned`
- **wiki 추출 대상** (verified만): 없음 — 구현 착수 전(전부 `planned`).
- **추출하지 않을 항목** (planned / documented-only / abandoned): 현재 전체 — verified evidence 확보 전까지 추출 금지.