문서와 심볼

aidlc-docs 를 그대로 읽는다 · 읽기 전용
/home/sunny/enode-fixup-workshop2-visualizer연결 중
aidlc-state.md347 줄

AI-DLC 상태

Current Status

  • Project: enode — 기능 추가 (중앙 현황판 · 대기열 · drain · 호스트 제어판 · Mediator MCP)
  • Current Phase: CONSTRUCTION
  • Current Stage: U-대기열 Code Generation Part 2 — 계획 열아홉을 다 돌렸다. CP2 초록. 승인 대기
  • Last Completed: U-대기열 Code Generation Part 2 가 끝났다. 계획 construction/plans/u-queue-code-generation-plan.md 의 체크박스가 전부 [x] 다 — 신설 둘(internal/api/queue.go · internal/api/queue_test.go) · 수정 아홉 · 새 Go 의존 0 · 새 패키지 0 · 새 열 0 · 새 라우트 0. CP2 가 전부 초록이다 — 빌드 · vet · 테스트 스킵 0건 · glyphscan · lint 20건(기준선) · 커버리지 16개 패키지 전부 하한 통과 · 경계 검사기 2 checked, 2 skipped, 4 total(안 바뀌는 것이 맞다) · 장면 다섯 · 라우트 18개 회귀 0 · 기동 시 승격. 화면 S1 을 Playwright 로 따로 확인했다 — 승격 전에는 QUEUED 행이 어느 카드에도 없고, 승격 뒤에 같은 Run 이 칩에서 빠져 카드에 붙는다. 화면 코드는 한 줄도 안 고쳤다. 결과는 construction/u-queue/code/code-generation-summary.md
  • Next Step: 다음 세션은 U-drain (CP3) 과 U-MCP (CP5) 를 병렬로 돈다 — 진행자 결정 2026-09-05. 둘 다 Functional Design 부터다(실행 계획 3절이 U-drain 에, decisions.md 5.3 이 U-MCP 에 걸어 뒀다). 병렬이 되는 근거는 unit-of-work-dependency.md 1.1 의 상자 그림이다 — 두 기둥이 만지는 파일이 하나도 안 겹친다. U-제어판 (CP4) 은 그 뒤다 — policy.Read · policy.Write 의 모양을 U-drain 의 Functional Design 이 정하기 때문이고, 그것이 닫히는 순간부터 U-제어판도 병렬로 붙을 수 있다
  • Parallel Caveat: 병렬로 돌리면 aidlc-docs/aidlc-state.md 와 aidlc-docs/audit.md 가 부딪친다 — 각각 한 장이고 모든 유닛이 같은 파일에 쓴다 (START.md §8 · CONVENTIONS.md 3.2). 세션 둘이 동시에 그 둘에 쓰기 전에 규칙을 정해야 한다. CONVENTIONS.md 3.4 가 「상태 파일 둘은 마지막 커밋에」로 커밋 쪽 절반만 처리했다
  • Scope Change: 2026-09-05 — Mediator MCP 가 이월에서 범위로 들어왔다. 진행자 결정이고 근거는 requirements/decisions.md 5절이다 — 이월의 이유가 결합이 아니라 값 둘(전송 · 토큰 전달)이었고 5.2 가 그 둘을 닫았다. 유닛이 다섯에서 여섯, FR 이 25개에서 29개, 게이트가 CP0 ~ CP4 에서 CP0 ~ CP5 가 됐다. 화면은 안 는다

유닛 이름 — 디렉터리 슬러그

저장소의 파일 이름이 전부 라틴 문자라 그것을 따른다. 문서 본문은 계속
한국어 이름을 쓴다.

유닛 슬러그 게이트
U-바닥 u-foundation CP0
U-관측API u-observe-api CP1
U-대기열 u-queue CP2
U-drain u-drain CP3
U-제어판 u-panel CP4
U-MCP u-mcp CP5

Workspace State

  • Existing Code: Yes
  • Programming Languages: Go 1.26
  • Build System: Go modules (go.mod · github.com/taeels/enode)
  • Project Structure: 멀티 커맨드 단일 모듈 — cmd/ 다섯 · internal/ 열
  • Workspace Root: 이 저장소의 뿌리
  • Code Baseline: 1c290a6 (enode main, 2026-09-04)
  • Design Canon: enode-design/ 서브모듈 @ 0fd304b
  • brownfield: true

Phase Status

단계 상태 비고
Workspace Detection 완료 위 표
Reverse Engineering 완료 (이관) 산출물 아홉이 inception/reverse-engineering/ 에 있다. 기준선과의 차이는 reverse-engineering-timestamp.md 머리
Requirements Analysis 완료 inception/requirements/requirements.md. 질문 세 묶음이 다 A·A·A 로 닫혔다 — 첫 묶음은 3절, 화면 대조에서 나온 둘째 묶음은 8.4절. FR 이 25개가 됐고 §4.1 계약과 §4.3 라우트가 둘째 묶음의 값을 실었다
User Stories 건너뜀 scene-gates.md §1 이 이미 페르소나 둘의 장면이고 §2 · §2.1 이 수용 기준이다. 두 벌이 되면 갈린다
Workflow Planning 완료 (승인) 아래 「실행 계획」. 별도 계획 파일을 안 만든 근거는 그 절 머리
Application Design 건너뜀 실행 계획 3절
Units Generation 완료 (승인) · 2026-09-05 에 여섯째 추가 유닛 다섯으로 닫혔고 뒤에 U-MCP 가 더해져 여섯이다 (requirements/decisions.md 5절). 계획 inception/plans/unit-of-work-plan.md 는 체크박스 전부 [x]. 산출물 셋은 inception/application-design/ — unit-of-work.md · unit-of-work-dependency.md · unit-of-work-story-map.md. 질문 셋도 A·A·A 로 닫혔다
Functional Design U-바닥 완료 (승인) · U-관측API 건너뜀 · U-대기열 완료 (승인) · U-MCP 실행 예정 유닛 다섯에 돈다: U-바닥 · U-대기열 · U-drain · U-제어판 · U-MCP. U-관측API 는 건너뜀 — U-MCP 는 안 건너뛴다: 도구 일곱의 스키마와 오류 사상이 이 단계 몫이고, 여덟째 후보 run.get 도 거기서 닫는다 (decisions.md 5.3). U-바닥 산출물은 construction/u-foundation/functional-design/ 의 넷 — 질문 파일 · domain-entities.md · business-logic-model.md · business-rules.md. 질문 셋은 A·A·A 로 닫혔다. 계획 파일을 안 만들었다 — 사용자 지시가 계획 파일을 Units Generation 과 Code Generation 으로 한정한다. frontend-components.md 도 안 냈다 — U-바닥에 화면이 없다. U-대기열 질문 넷은 A·A·A·A 로 닫혔다 — 승격 층 · 깨우기 동기성 · 409 갈래 · Reap 자리. 산출물은 construction/u-queue/functional-design/ 의 넷(질문 파일 포함)이고 frontend-components.md 는 안 냈다 — 이 유닛에 화면이 없다 (S1 의 QUEUED 칩은 U-관측API 가 이미 그렸고 지금 빈 목록을 낸다). 사용자 입력 승인 으로 닫혔다 — 산출물 셋에 변경 요청이 없었다
NFR Requirements 건너뜀 실행 계획 3절
NFR Design 건너뜀 NFR Requirements 를 건너뛰므로
Infrastructure Design 건너뜀 실행 계획 3절
Code Generation U-바닥 완료 (승인) · U-관측API 완료 (승인) · U-대기열 Part 2 (승인 대기) 유닛마다 돈다. U-바닥 계획 construction/plans/u-foundation-code-generation-plan.md 는 체크박스가 전부 [x] 다 — 신설 여덟 · 수정 여섯 · CP0 초록 · 결과는 construction/u-foundation/code/code-generation-summary.md. U-관측API 계획 construction/plans/u-observe-api-code-generation-plan.md 도 체크박스 122개가 전부 [x] 다 — 단계 열여덟 · 신설 열하나 · 수정 하나 · CP1 초록 · 화면 검증 통과 · 결과는 construction/u-observe-api/code/code-generation-summary.md. 그 유닛은 Functional Design 을 건너뛰므로 계획이 설계도 졌다 — 3절이 응답 계약, 4절이 화면이다. U-대기열 계획 construction/plans/u-queue-code-generation-plan.md 도 체크박스 111개가 전부 [x] 다 — 단계 열아홉 · 신설 둘 · 수정 아홉 · 새 Go 의존 0 · 새 패키지 0 · 새 열 0 · 새 라우트 0 · CP2 초록 · 화면 검증 통과 · 결과는 construction/u-queue/code/code-generation-summary.md. 그 유닛은 Functional Design 을 돌았으므로 계획이 설계를 다시 안 적었다. 계획이 「수정 여덟」로 셌던 것은 미계수다 — 2절 행렬은 처음부터 아홉 줄이다. 나머지 셋(U-drain · U-제어판 · U-MCP)의 계획은 그 유닛 차례에 만든다
Build and Test 실행 CP4
Operations 자리만 v1 의 placeholder

실행 계획 (Workflow Planning)

별도 계획 파일을 만들지 않았다. 규칙은 inception/plans/execution-plan.md
를 요구하지만, 사용자 지시가 「계획 파일은 Units Generation 과 Code Generation
에서만 만든다」이다. 이 단계의 산출은 어느 단계를 돌리고 어느 것을 건너뛰는가와
그 근거인데, 그것은 상태 파일이 이미 지고 있는 짐이다. 파일을 하나 더 만들면
같은 표가 두 벌이 되고, 두 벌이 되면 갈린다.

1. 범위와 영향

축 값
변환 유형 단일 컴포넌트가 아니다. 여러 패키지에 걸친 기능 추가이고 아키텍처 변환은 아니다
사용자 표면 변화 있다. 화면 여덟 장 중 일곱, 새 CLI 하위 명령 enodectl serve
구조 변화 있다. 새 패키지 둘 — internal/panel · internal/api/ui. 노드에 HTTP 서버가 처음 선다
데이터 모델 변화 있다. nodes 에 정책 열이 는다. runs.state 어휘에 QUEUED 가 는다. StepView 에 chosen
API 변화 있다. 라우트 15 -> 18 (GET /v1/nodes · GET /v1/runs · GET /ui/). POST /v1/runs 가 202 를 낼 수 있다. 광고 응답에 policy
NFR 영향 있다. 보안 확장이 새 표면 넷에 걸린다 (requirements.md §5.1)
배포 모델 변화 없다. 새 실행파일 없음 · packaging/ 안 건드림 · 클라우드 자원 없음

2. 위험

위험 수준 — Medium.

   낮은 것        스키마 변경이 전부 ADD COLUMN IF NOT EXISTS 로 가산이다.
                  runs.state 에 CHECK 가 없어 QUEUED 가 마이그레이션 없이 들어간다.
                  새 패키지 둘은 격리돼 있고 기존 코드가 임포트하지 않는다

   높은 것 둘      둘 다 internal/api/api.go 이고 둘 다 기존 뜨거운 경로다
                  submit      매칭 거절 처리에 QUEUED 분기가 든다.  모든 제출이 지난다
                  postResult  끝에 at-boundary 종료가 든다.  모든 단계 보고가 지난다

   되돌리기        Moderate.  가산 열과 새 파일은 그냥 두면 되고,
                  api.go 의 등록 줄과 위 두 블록만 되돌리면 기존 동작으로 돌아간다

   테스트          Moderate.  store 를 부르는 유닛은 ENODE_TEST_DATABASE_URL 이 필요하고
                  internal/panel · internal/api/ui 는 DB 없이 돈다 (NFR-Q2)

코드 대조로 지운 위험 하나 — Reap 이 QUEUED Run 을 쓸어가지 않는다.
reap.go 의 회수 UPDATE 가 run_id IN (SELECT run_id FROM leases WHERE not_after <= now()) 로 걸러지는데 QUEUED 는 임대를 안 쥐므로 그 부분질의에
안 들어온다. 뒤이은 두 문장도 state='FAILED' 또는 종료 상태만 본다.
무기한 대기가 reaper 에 안 잡힌다 — decisions.md 1절의 「대기 상한 없음」이
코드에서 이미 참이다.

3. 단계 판정

건너뛰는 것

단계 근거
User Stories scene-gates.md §1 이 이미 페르소나 둘(dhseo · taeels)의 장면이고, §2 가 조각마다 수용 기준을, §2.1 이 화면 검증을 갖고 있다. design/README.md §1 이 표면별 책임을 갈랐다. 스토리를 새로 내면 같은 것의 두 번째 정본이 생긴다
Application Design 이 단계가 낼 것을 팩이 이미 갖고 있다 — 컴포넌트 목록은 RE 산출물, 새 패키지 경계와 겹침 처리와 접점 여덟은 unit-boundaries.md §2 ~ §4, 계약은 requirements.md §4.1 ~ §4.3 이 고정했다. 메서드 수준 설계는 유닛마다의 Functional Design 이 그 유닛의 자리에서 낸다. 컴포넌트 문서를 하나 더 만들면 권위가 둘로 갈린다
NFR Requirements 기술 스택에 고를 것이 없다 — Go 1.26 · 표준 라이브러리 ServeMux · PostgreSQL 이 이미 정해져 있고 새 의존이 없다. NFR 은 requirements.md §5 가 33개로 이미 적었고 값은 전부 decisions.md 가 닫았다. 건너뛴다고 보안 확장이 꺼지지 않는다 — 강제는 단계마다 따로 돈다
NFR Design 위를 건너뛰므로
Infrastructure Design 매핑할 인프라가 없다. 새 실행파일 없음 · 클라우드 자원 없음 · 배포 모델 그대로 · 리버스 프록시와 TLS 는 constraints.md §6

실행하는 것

단계 근거
Units Generation 사용자 지시이자 필요다. 패키지 여럿 · 새 라우트 셋 · 스키마 변경 · 상태 어휘 변경이 전부 판정 조건에 걸린다
Functional Design (유닛 넷) U-바닥(새 스키마 · 새 상태 · 정책 타입) · U-대기열(승격 트랜잭션 · 깨우기 여섯 지점 · 크래시 복구) · U-drain(정책 파일 형식이 명시적으로 이 단계 몫이다 — decisions.md 1절) · U-제어판(노드에 서는 첫 HTTP 서버 · 화면 둘). U-관측API 는 건너뛴다 — 응답 모양이 decisions.md 2절과 ADR-065 로 이미 확정이고 기존 행을 투영하는 것뿐이다
Code Generation 항상. 유닛마다 계획에 그 조각의 게이트 명령을 실제로 돌리는 단계를 박는다
Build and Test 항상. 끝에서 CP4

4. 유닛 — 여섯에서 다섯으로

권장은 여섯이고 다섯으로 간다. 근거를 적는다.

unit-boundaries.md §1 이 U-화면을 「SKIP 가능 축」으로 두고 「폭이 있으면
따로 가르고, 없으면 U-관측API 와 U-제어판에 각각 합친다. 합칠 때도 파일은
ui/ 아래로 분리한다」고 적었다. 이 실행은 폭이 1 이다 — 병합 순서가 착수
순서로 직렬이고(START.md §5) 유닛을 나눠 맡을 사람이 없다.

합치지 않으면 CP1 이 초록이 될 수 없다. scene-gates.md §2 는 CP1 이
딛는 유닛을 U-관측API 로 두는데, §2.1 은 같은 CP1 에 화면 검증 S1 · S1b 를
건다. U-화면이 여섯째로 오면 CP1 시점에 화면이 없다. §4 의 보류는 「빨간 이유가
그 유닛 밖」일 때만 쓰는 것이라 여기 안 맞는다. CP3 행이 「(U-제어판은 뒤에
온다)」로 순서를 이미 인정한 것과 달리 CP1 · CP2 행은 그 각주가 없다 — 팩
안의 어긋남이고, 합치는 것이 팩 자신이 준 해법이다.

   U-바닥        스키마 · 상태 상수 · 조회 메서드 · 정책 자리 · 경계 검사 테스트     CP0
   U-관측API     GET /v1/runs · GET /v1/nodes · StepView.chosen
                 + 중앙 화면 S0 · S0b · S1 · S1b · S2  (internal/api/ui/)          CP1
   U-대기열      409 -> QUEUED · FIFO · WakeQueued · 202 · 기동 시 깨우기            CP2
   U-drain       정책 파일 · 광고에 싣기 · 후보 제외 · 응답 통보 · 두 모드 · 해제     CP3
   U-제어판      enodectl serve · 프로세스 제어 · 신원 · 탐지 능력 · 현재 작업
                 · drain 토글 + 호스트 화면 S3 · S5  (internal/panel/ui/)           CP4
   U-MCP         runctl mcp — stdio JSON-RPC · 도구 일곱  (internal/mcp/)           CP5

여섯째는 2026-09-05 에 들어왔다. 위 다섯을 정할 때는 Mediator MCP 가
이월이었다. 진행자가 그것을 되돌렸고 근거는 requirements/decisions.md
5절이다 — 이월의 이유가 결합이 아니라 값 둘이었다.

파일은 여전히 ui/ 아래로 분리한다 — 합친 것은 계획 단위이지 파일 경계가
아니다.

5. 착수 순서와 접점

   순서    U-바닥 -> U-관측API -> U-대기열 -> U-drain -> U-제어판
   게이트   CP0       CP1          CP2         CP3        CP4

           U-관측API -> U-MCP                              장면 밖 · 병렬
                        CP5

U-MCP 만 이 사슬 밖이다. U-관측API 의 라우트 둘만 딛으므로 CP1 이 초록인
지금 이미 착수 가능하고, 만지는 파일 넷(internal/mcp/ 신설 ·
internal/runctl/client.go · cmd/runctl/main.go)을 다른 유닛이 아무도
안 만져 병합 순서에 자리를 안 잡는다.

U-바닥이 늦으면 전원이 선다. 다른 넷이 전부 이것을 딛는다. CP0 가
초록이어야 다음이 시작된다.

직렬로 받아야 하는 자리 — internal/api/api.go 의 등록 줄. 관측 둘 · 정적
파일 하나 · 대기열의 submit 분기 · drain 의 광고 응답 한 줄과 postResult
끝 블록이 전부 이 파일이다. unit-boundaries.md §3 이 처리를 적었다.

의존이 실제로 걸리는 자리 넷:

   U-대기열  -> U-바닥       DrainingNodes · ListQueued · QUEUED 상수 · steps 제출 시 생성
   U-drain   -> U-대기열     해제를 감지한 광고 처리가 WakeQueued 를 부른다
   U-제어판  -> U-관측API    현재 작업을 GET /v1/nodes · GET /v1/runs/{id} 로 조립한다
   U-제어판  -> U-drain      policy.Read · policy.Write 를 쓴다.  자기 파서를 안 만든다
   U-MCP     -> U-관측API    GET /v1/nodes · GET /v1/runs.  HTTP 의존이고 임포트가 아니다

6. 흐름

flowchart TD
    Start(["User Request"])

    subgraph INCEPTION["INCEPTION PHASE"]
        WD["Workspace Detection<br/><b>COMPLETED</b>"]
        RE["Reverse Engineering<br/><b>COMPLETED</b>"]
        RA["Requirements Analysis<br/><b>COMPLETED</b>"]
        US["User Stories<br/><b>SKIP</b>"]
        WP["Workflow Planning<br/><b>COMPLETED</b>"]
        AD["Application Design<br/><b>SKIP</b>"]
        UG["Units Generation<br/>6 units<br/><b>EXECUTE</b>"]
    end

    subgraph CONSTRUCTION["CONSTRUCTION PHASE"]
        FD["Functional Design<br/>5 of 6 units<br/><b>EXECUTE</b>"]
        NFRA["NFR Requirements<br/><b>SKIP</b>"]
        NFRD["NFR Design<br/><b>SKIP</b>"]
        ID["Infrastructure Design<br/><b>SKIP</b>"]
        CG["Code Generation<br/>per unit + scene gate<br/><b>EXECUTE</b>"]
        BT["Build and Test<br/>CP4<br/><b>EXECUTE</b>"]
    end

    subgraph OPERATIONS["OPERATIONS PHASE"]
        OPS["Operations<br/><b>PLACEHOLDER</b>"]
    end

    Start --> WD
    WD --> RE
    RE --> RA
    RA --> US
    US --> WP
    WP --> AD
    AD --> UG
    UG --> FD
    FD --> NFRA
    NFRA --> NFRD
    NFRD --> ID
    ID --> CG
    CG --> BT
    BT --> OPS
    BT --> End(["Complete"])

    style WD fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style RE fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style RA fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style WP fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style CG fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style BT fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style UG fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style FD fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style US fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
    style AD fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
    style NFRA fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
    style NFRD fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
    style ID fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
    style OPS fill:#BDBDBD,stroke:#424242,stroke-width:2px,stroke-dasharray: 5 5,color:#000
    style INCEPTION fill:#BBDEFB,stroke:#1565C0,stroke-width:3px,color:#000
    style CONSTRUCTION fill:#C8E6C9,stroke:#2E7D32,stroke-width:3px,color:#000
    style OPERATIONS fill:#FFF59D,stroke:#F57F17,stroke-width:3px,color:#000
    style Start fill:#CE93D8,stroke:#6A1B9A,stroke-width:3px,color:#000
    style End fill:#CE93D8,stroke:#6A1B9A,stroke-width:3px,color:#000

    linkStyle default stroke:#333,stroke-width:2px

같은 것을 글로 적은 것:

   INCEPTION      Workspace Detection   완료
                  Reverse Engineering   완료 (이관)
                  Requirements Analysis 완료
                  User Stories          건너뜀
                  Workflow Planning     완료
                  Application Design    건너뜀
                  Units Generation      실행 -> 유닛 여섯 (MCP 는 2026-09-05 추가)

   CONSTRUCTION   유닛마다 Functional Design (다섯) -> Code Generation -> 조각 게이트
                  NFR Requirements · NFR Design · Infrastructure Design   건너뜀
                  Build and Test        실행.  CP4

   OPERATIONS     자리만

7. 성공 기준

   1차 목표     scene-gates.md §1 의 dhseo 장면이 ① ~ ⑦ 끝까지 돈다.
                LED 가 새 패턴으로 깜빡인다

   산출         GET /v1/runs · GET /v1/nodes · GET /ui/ 셋과 화면 일곱
                QUEUED 와 승격
                정책 파일 · 광고 왕복 · 두 모드 · 해제
                enodectl serve
                runctl mcp — 도구 일곱 (장면 밖.  CP5)

   품질 게이트   CP0 ~ CP4.  조각이 초록이 아니면 다음 유닛에 안 들어간다
                CP5 는 사슬 밖이다 — 빨개도 CP4 를 안 막는다
                go test · go vet · golangci-lint · glyphscan · 커버리지 계약
                경계 검사 테스트 (unit-boundaries.md §5)
                기존 라우트 15개 회귀

8. 남는 조건 — 이 저장소 밖

canon.md §3 의 선행 조건 셋은 enode-design 의 PR 이고 이 저장소가 하지
않는다. 착지 전이라도 이 팩은 개정된 문장을 따른다 (requirements.md §7.1).


Reverse Engineering 산출물

aidlc-docs/inception/reverse-engineering/ 에 아홉이 있다.

   api-documentation      architecture       business-overview
   code-quality-assessment code-structure    component-inventory
   dependencies           technology-stack   reverse-engineering-timestamp

출처가 v2 다. 2.1 스테이지가 기준선 f46e187 에서 낸 것을 파일 그대로
옮겼고, v2 가 v1 의 산출물 어휘를 유지해 아홉 이름이 v1 요구와 일치한다.
이 저장소의 코드는 1c290a6 이고 구조 차이는 reverse-engineering-timestamp.md
머리에 있다. code-quality-assessment.md · code-structure.md 가 낡았다.

설계 중 나온 정정 여섯

U-바닥 Functional Design 이 코드와 CI 설정을 대조하면서 앞 단계의 문장 셋을
바로잡았고, Code Generation 이 실측으로 넷째를 더했고, U-대기열 Functional
Design 이 다섯째를, U-대기열 Code Generation 이 여섯째를 더했다. 근거는
construction/u-foundation/functional-design/ 과 .../code/ 와
construction/u-queue/functional-design/ 과 construction/plans/ 에 있다.

무엇 어디에 있던 문장 바로잡은 것
runs.state 의 어휘 requirements.md §5.2 NFR-I2 — 「저장되는 어휘는 RUNNING · SUCCEEDED · FAILED 와 새로 오는 QUEUED 넷」 다섯이다. internal/store/reap.go:279 의 SettleIfDone 이 RUNNING -> VERIFYING 을 따로 커밋하고 그 뒤에 대조가 이어져, 폴링이 VERIFYING 행을 실제로 본다. RESOLVING · ALLOCATING 은 상수만 있고 저장되지 않는다. business-rules.md 3절
api.go 를 만지는 유닛 unit-boundaries.md §2 · unit-of-work-dependency.md §3 — U-바닥 열에 api.go 가 없다 한 줄 만진다. UpsertAdvert 의 반환이 둘이 되므로 internal/api/api.go:208 이 바뀐다. 등록 줄도 핸들러 로직도 아니다. business-logic-model.md §2.2
경계 검사기의 「건너뜀」 unit-of-work.md — 「없으면 통과가 아니라 건너뛴다를 검사기가 구분해서 적는다」 t.Skip 으로 구현하면 안 된다. .ci-allowed-skips 가 「CI 로 갖출 수 없는 조건」만 받고, 목록에 없는 t.Skip 은 CI 의 스킵 감시가 위반으로 센다. t.Logf 로 적고 CP0 에 go test -v ./internal/boundary 를 더한다. business-rules.md R18 · R19
Advert.Policy 의 json 태그 domain-entities.md §2.2 — `json:"policy,omitempty"` omitzero 다. Go 의 omitempty 는 구조체 필드에 안 듣고 제로값을 "policy":{} 로 내보낸다 — 실측했다. 같은 문서가 요구한 「제로값이면 policy 키가 빠진다」를 내는 것은 omitzero (Go 1.24+, 이 저장소는 1.26) 하나다. 빈 객체가 나가면 R4 가 같게 읽으라고 정한 둘을 읽는 쪽이 가르려 든다. code-generation-summary.md 3절
「부분 반납 뒤 깨우기」의 자리 unit-of-work.md U-대기열 파일 행렬 — internal/store/release.go o 「부분 반납 뒤 깨우기」 그 자리에서는 못 깨운다. applyRelease 가 ReportStep 의 트랜잭션 안에서 돈다 (claim.go:773 로 열고 :843 -> :863 으로 부르고 :823 에서 커밋). 거기서 깨우면 아직 커밋 안 된 임대 해제를 보고 승격하려 들고 승격의 트랜잭션이 같은 행을 기다린다. 자리는 커밋 뒤 — 즉 postResult 이고, 그 한 번이 「완료」와 「부분 반납」 둘을 덮는다. 딸린 조건은 SettleIfDone 이 빈 문자열을 내도 깨워야 한다는 것. 파급은 release.go 를 안 고치는 것 — 만지는 파일이 여섯에서 다섯으로 준다. 깨우기 지점은 여전히 여섯이고 호출 자리가 다섯이다. functional-design-questions.md 4절
nonce 를 옮기는가 U-대기열 Functional Design 요약 — 「label 과 nonce 를 internal/api 에서 internal/store 로 옮긴다」 nonce 는 옮길 것이 없다. internal/store/acquire.go:243 에 같은 구현이 이미 있고 획득 경로가 그것을 쓴다. 승격은 같은 패키지의 그 함수를 그대로 부르고, internal/api/api.go 의 nonce() 는 제자리에 둔다 — 지우려면 store 쪽을 내보내야 하고 그러면 안 지어도 될 공개 표면이 하나 는다. 따라서 api.go 에서 crypto/rand · encoding/hex 임포트가 안 빠졌다. domain-entities.md §3.2 의 제목 「옮기는 함수 하나」와 일치한다. u-queue-code-generation-plan.md 3.1절

Extension Configuration

사용자 결정 2026-09-04. Requirements Analysis 에서 확인했다.

Extension Enabled Decided At 비고
security-baseline Yes Requirements Analysis 새 표면에만 건다. 지침 줄은 requirements/decisions.md 3절. SECURITY-04 의 취급은 requirements.md §3.3
resiliency-baseline No Requirements Analysis 규칙 전문을 싣지 않았다
property-based-testing No Requirements Analysis 규칙 전문을 싣지 않았다