Files
llm-wiki/raw/branch-notes/chore-harness-policy-engine-alignment.md

250 lines
14 KiB
Markdown

---
title: branch / chore-harness-policy-engine-alignment
source_type: branch-note
status: raw
id: BR-CA-SKELETON-CHILD-7869EDB8
kind: branch-child
project: ca-skeleton-operational-contract
work_item: WI-CA-SKELETON-OPERATIONAL-CONTRACT-033
inherits: [DEC-CA-SKELETON-OPERATIONAL-CONTRACT-BOOTSTRAP-001@1, DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-BUILD-001@1]
refines: []
overrides: []
depends_on: []
contract_packet: 1
branch: chore-harness-policy-engine-alignment
parent_branch: feature-developer-experience-contract
related_projects: [ca-skeleton]
tags: [branch, ca-skeleton, architecture, testing, build-tooling, code-generation, multi-module]
created: 2026-07-20
target_merge:
status_label: review
contract_packet_sha256: 2e26526393b48c4063a84c2593debc3f8aa4858aab480aeae9f9167bf49b778c
---
# branch: chore-harness-policy-engine-alignment
> Layer: `raw/branch-notes/` — ca-tmpl 개발 하네스를 registry-driven policy engine으로 정합한 작업 기록. Git은 detached HEAD `e68dd67a26d4579a070f10ee386213d3c23e6957`에서 작업했고, 사용자 소유 human-only commit 정책에 따라 commit/staging하지 않았다.
<!-- section-id: branch-parent -->
## 부모 (필수)
- [[raw/branch-notes/feature-developer-experience-contract]] — 개발 하네스와 단일 진입 검증 경험의 parent Work Item.
<!-- GENERATED: branch-contract:start -->
<!-- section-id: branch-contract-packet -->
## 브랜치 계약 패킷
- **생성 시 프로젝트 개정**: `1`
- **패킷 스키마**: `contract_packet: 1`
- **완료 조건**: fresh environment에서 ./gradlew bootstrap이 성공한다
<!-- section-id: inherited-project-decisions -->
### 상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-BOOTSTRAP-001@1` | 신규 환경의 default 진입 명령은 ./gradlew bootstrap이다 | harness validator와 Gradle verification command를 저장소 안에 둔다. | [[raw/project-notes/ca-skeleton-operational-contract]] |
| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-BUILD-001@1` | build tool은 Gradle Groovy DSL이다 | registry를 `settings.gradle`과 dependency verifier가 소비한다. | [[raw/project-notes/ca-skeleton-operational-contract]] |
<!-- section-id: branch-local-decisions -->
### 브랜치 지역 결정
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|---|---|---|---|
| D1 | 19개 leaf module의 topology·dependency·test command는 `.harness/project/modules.yaml` 하나가 소유한다. | `local` | `UNSUPPORTED_DECISION` | `implemented` |
| D2 | verdict/evidence는 필수 필드·산식·revision/rule hash·실제 upstream artifact를 fail-closed로 검증한다. | `local` | `UNSUPPORTED_DECISION` | `implemented` |
| D3 | canonical agent 5개에서 Claude/Codex/Antigravity/plugin 산출물을 생성하고, platform hook adapter만 공식 이벤트 계약을 번역한다. | `local` | `raw/official-docs/google-antigravity-hooks.md#GOOGLE-ANTIGRAVITY-HOOKS-C1`, `#GOOGLE-ANTIGRAVITY-HOOKS-C2` | `implemented` |
| D4 | review/report 의식은 file count가 아니라 risk와 evidence profile로 선택한다. | `local` | `UNSUPPORTED_DECISION` | `implemented` |
| D5 | agent는 stage/commit하지 않고 사람이 working tree를 검토·commit한다. | `local` | `UNSUPPORTED_DECISION` | `implemented` |
<!-- section-id: declared-overrides -->
### 선언한 예외
| Override ID | Overrides | Reason | Approval | Status |
|---|---|---|---|---|
| (없음) | - | 상속 결정 override 없음 | - | - |
<!-- section-id: branch-goal -->
<!-- GENERATED: branch-contract:end -->
## 목표
- 중첩 module topology와 flat-path 기반 훅·agent·Gradle verifier의 drift를 제거한다.
- 판단 결과와 테스트 증거를 서로 다른 플랫폼에서도 같은 schema와 revision identity로 검증한다.
- 과도한 전수 인용·N! 순열·file-count 보고 분할을 risk/evidence profile로 바꾼다.
- 이슈: 사용자 제공 `개발 하네스 분석·리뷰` 감사 보고서
- PR: 없음 — human-only commit handoff
<!-- section-id: branch-scope -->
## 범위
### 포함 범위
- `.harness/` module registry, task packet, profiles, risk/review/report/evidence policy.
- import mutation gate, verdict/evidence schema, revision and rule hashes.
- Claude/Codex/Antigravity/plugin agent renderer와 정적 parity snapshot.
- `src/settings.gradle`, `src/build.gradle`의 registry projection.
- root/plugin/module guidance의 Spring Boot 4.0.0·nested topology 정합.
### 제외 범위
- 인증된 세 외부 제품에서의 end-to-end golden 실행.
- 기존 production Java의 ArchUnit·Checkstyle 위반 수정.
- commit, staging, PR 생성.
## 근거 (필수, 최소 1개+)
| Source | 정당화하는 결정 |
|---|---|
| [[raw/official-docs/google-antigravity-hooks]] | D3 — Antigravity adapter의 JSON/camelCase/PreToolUse/Stop decision 계약 |
## TODO
- [x] 19개 leaf module registry와 nearest owner resolution — 등급: `locally-verified`
- [x] nested import mutation과 fail-closed shell/file write gate — 등급: `locally-verified`
- [x] strict verdict/evidence/revision/rule-hash validation — 등급: `locally-verified`
- [x] canonical renderer와 네 플랫폼 static parity — 등급: `locally-verified`
- [x] risk/profile 기반 orchestration·reporting·citation guidance — 등급: `locally-verified`
- [ ] 인증된 Claude/Codex/Antigravity 실제 golden execution — 등급: `planned`
- [ ] 기존 production ArchUnit·Checkstyle baseline 위반 정리 — 등급: `planned`, 본 branch 범위 밖
## 진행 중 메모
- 최초 import gate는 실제 `src/adapter/inbound|outbound/...` 중첩 경로를 production으로 인식하지 못했다.
- review chain은 ignored physical guidance의 revision hash 누락, production `Fake*.java` risk 오분류, command evidence 총계 불일치까지 추가로 발견했고 mutation test로 고정했다.
- 전체 Gradle check는 하네스 변경과 무관한 기존 production 위반으로 green이 아니다.
## 결정 사항
- 2026-07-20: registry를 Gradle settings/dependency verifier/import gate/agent runner의 공통 topology SSOT로 사용한다. 대안인 각 consumer별 allowlist는 drift가 이미 재현되어 폐기했다. 근거: D1 `UNSUPPORTED_DECISION` — 저장소 내부 trade-off.
- 2026-07-20: physical ignored guidance도 revision identity 선언에 포함한다. 대안인 tracked diff-only hash는 upstream review artifact가 stale guidance 변경을 놓쳤다. 근거: D2 `UNSUPPORTED_DECISION`.
- 2026-07-20: Antigravity는 shared validator를 호출하고 공식 hook event만 번역한다. 근거: D3, `GOOGLE-ANTIGRAVITY-HOOKS-C1/C2`.
- 2026-07-20: low/medium/high risk와 review-lite/standard/audit-deep/regulated profile을 사용한다. file count 자체는 risk classifier가 아니다. 근거: D4 `UNSUPPORTED_DECISION`.
- 2026-07-20: commit은 사람만 수행한다. 근거: D5 `UNSUPPORTED_DECISION` — review 전 immutable commit을 강제하지 않고 working-tree identity를 사용하기 위한 운영 선택.
## 결정-근거 매핑
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|---|
| D1 | 중앙 module registry | 동일 topology를 2개 이상 consumer가 사용하면 registry; 단일 독립 script면 local declaration 가능 | `UNSUPPORTED_DECISION` | repository-local verified | registry schema 변경 시 모든 projection test 필요 |
| D2 | strict verdict/evidence/revision/rule hash | review chain 결과를 재사용하면 strict artifact; 단발 로컬 메모는 간단 결과 가능 | `UNSUPPORTED_DECISION` | mutation-tested | external platform lifecycle E2E 미검증 |
| D3 | canonical render + thin platform adapter | 플랫폼 body 의미가 같고 wrapper 문법만 다를 때; 플랫폼 고유 agent는 explicit exception | `raw/official-docs/google-antigravity-hooks.md#GOOGLE-ANTIGRAVITY-HOOKS-C1`, `#GOOGLE-ANTIGRAVITY-HOOKS-C2` | `official-vendor-doc + locally-verified` | 실제 authenticated Antigravity run 필요 |
| D4 | risk/evidence profile | high-risk면 full chain; low-risk면 focused inline; 규제 요구면 regulated profile | `UNSUPPORTED_DECISION` | repository-local verified | 분류 flag를 호출자가 정직하게 제공해야 함 |
| D5 | human-only commit | 사용자가 working tree를 소유하는 collaborative workflow; 자동 release bot은 별도 policy 필요 | `UNSUPPORTED_DECISION` | documented + enforced in generated prompts | 사람이 commit 전 변경을 검토해야 함 |
## 구현 가이드
### 1. Topology와 task packet
> **Trace**: D1 (`UNSUPPORTED_DECISION`).
- `.harness/project/modules.yaml`: 19 leaf의 source/Gradle/package/dependency/test/instruction owner.
- `.harness/lib/module_registry.py`: longest filesystem boundary owner resolution.
- `.harness/lib/task_resolver.py`: risk, selected profiles, focused command, immutable packet·rule hashes.
- `src/settings.gradle``src/build.gradle`: registry를 parse해 project와 dependency verification을 투영한다.
### 2. Enforcement와 evidence
> **Trace**: D2 (`UNSUPPORTED_DECISION`).
- `.harness/lib/import_policy.py`, `import_hook.py`: platform-neutral import/write policy.
- `.harness/lib/verdict.py`: schema-level 필수값, nonnegative counts, 산식, command row reconciliation, upstream artifact hash, revision identity.
- `.harness/project/revision-surfaces.yaml`: ignored physical harness input과 transient exclusion.
### 3. Platform generation
> **Trace**: D3 (`GOOGLE-ANTIGRAVITY-HOOKS-C1/C2`).
- `.harness/agents/*.md`: 5개 canonical body.
- `.harness/generators/render_agents.py`: Claude/Codex/Antigravity/plugin physical output와 tracked snapshot 생성.
- `.harness/adapters/antigravity_import_hook.py`, `antigravity_hook.py`: 공식 event/decision 번역만 소유한다.
- **UNSUPPORTED_IMPL_DECISION**: source hash metadata와 physical/snapshot 이중 출력은 clean clone parity와 local installed surface를 함께 검사하기 위한 선택이다.
### 4. Risk와 reporting
> **Trace**: D4·D5 (`UNSUPPORTED_DECISION`).
- low: docs/comments/test fixture 또는 characterization으로 보호된 local refactor; high/medium trigger가 우선한다.
- medium: behavior/cross-module/external integration.
- high: security/migration/public contract/build/dependency/architecture/CI/deployment/transaction/concurrency.
- evidence matrix, quote verification, durable report는 selected profile에 비례한다.
## 엣지·실패·의존
- **실패·엣지 경로**: unknown production path는 medium; malformed write/verdict는 fail-closed; ignored guidance mutation은 revision을 바꾸고 transient evidence/cache/marker는 바꾸지 않는다.
- **다른 계약 의존**: parent D3/D4의 bootstrap·entrypoint 계약을 consume한다. production architecture baseline 정리는 `feature-architecture-enforcement-rules` owner 범위다.
## 검증해야 할 주장
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
| 세 외부 제품에서 같은 seeded task가 같은 verdict/evidence를 만든다 | repository-local static test는 인증 제품 lifecycle을 실행하지 않음 | Claude/Codex/Antigravity 각각에서 golden task를 실행하고 evidence JSON 비교 | `needs-confirmation` |
| module registry 변경이 모든 consumer를 invalidation한다 | 새 consumer가 registry 밖 local map을 만들 수 있음 | policy parity와 forbidden legacy token scan을 CI에서 유지 | `locally-verified` |
| production 전체 check가 green이다 | 기존 HEAD에도 architecture/checkstyle 위반 존재 | 별도 production-fix branch 후 `./gradlew check --console=plain` | `needs-confirmation` |
## 마주친 문제
- nested adapter 경로가 legacy regex를 우회함 — registry mutation test로 해결.
- ignored physical guidance가 revision identity에서 빠짐 — `revision-surfaces.yaml`과 mutation test로 해결.
- 기존 production baseline 실패 — [[raw/errors/ca-tmpl-preexisting-check-baseline-failures-2026-07-20]]로 분리, 미해결.
## 검증 결과
- `PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s .harness/tests -v` → 106/106 PASS.
- `PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s .claude/hooks -p 'test_*.py' -v` → 74/74 PASS.
- module validator → 19 leaf PASS; policy parity와 renderer `--check` PASS; `git diff --check` PASS.
- `./gradlew projects verifyCleanArchitectureDependencies --console=plain` → PASS.
- focused `CleanArchitectureTest`와 전체 `check` → 기존 `IdempotencyRecordEntity.requestHash columnDefinition='char(64)'` 위반으로 FAIL.
- `./gradlew check -x :app-bootstrap:test --console=plain` → 기존 domain `NeedBraces` 3건으로 FAIL.
- CA spec review → 11/11 PASS.
- CA architecture review → diff-specific blocking 0; repository verdict는 위 기존 ArchUnit 1건 때문에 FAIL.
- CA quality review → architecture upstream이 ready가 아니므로 미실행.
## 묶음 (이 branch에서 파생된 자료)
<!-- GENERATED: sources:start -->
- [[raw/official-docs/google-antigravity-hooks]]
<!-- GENERATED: sources:end -->
<!-- GENERATED: interviews:start -->
- [[raw/interviews/manifest-driven-multi-platform-agent-harness]]
<!-- GENERATED: interviews:end -->
<!-- GENERATED: errors:start -->
- [[raw/errors/ca-tmpl-preexisting-check-baseline-failures-2026-07-20]]
<!-- GENERATED: errors:end -->
<!-- GENERATED: blog-topics:start -->
- [[raw/blog-topics/manifest-driven-agent-harness-policy-engine]]
<!-- GENERATED: blog-topics:end -->
### Sub-branches
- 없음.
### 오류 기록
- [[raw/errors/ca-tmpl-preexisting-check-baseline-failures-2026-07-20]] — 하네스 변경과 무관한 ArchUnit·Checkstyle baseline 실패.
### 면접 준비
- [[raw/interviews/manifest-driven-multi-platform-agent-harness]] — registry, renderer, evidence identity 설계 질문.
### 강의
- 없음.
### blog-topics
- [[raw/blog-topics/manifest-driven-agent-harness-policy-engine]] — 중복 prompt를 policy engine으로 바꾼 과정.
## 관련 일일 노트
- 없음 — 이번 캡처에서는 branch-note와 파생 raw 자료만 생성했다.
## 완료 후 정리
- merge/commit: 사용자 handoff, 아직 없음.
- canonical 추출: 요청되지 않아 `wiki/*` 직접 생성 없음.