문서와 심볼

aidlc-docs 를 그대로 읽는다 · 읽기 전용
/home/sunny/enode-fixup-workshop2-visualizer연결 중
inception/application-design/unit-of-work-story-map.md198 줄

유닛 맵 — 요구사항 · 화면 · 게이트가 어느 유닛에 걸리나

여기 스토리는 없다. 파일 이름은 v1 의 것을 그대로 썼고(경로를 바꾸면 뒤
단계가 읽는 자리와 갈린다), 안에 들어간 것은 셋이다.

   FR-1 ~ FR-29      requirements.md 4절의 추적표
   화면 일곱          S0 · S0b · S1 · S1b · S2 · S3 · S5
   조각 게이트 여섯    CP0 ~ CP5

FR-26 ~ FR-29 와 CP5 는 2026-09-05 에 들어왔다 — Mediator MCP 의 이월을
진행자가 되돌렸다 (requirements/decisions.md 5절). 화면은 안 는다: MCP 가
화면을 안 만든다.

User Stories 를 건너뛴 근거는 aidlc-state.md 실행 계획 3절이다 — 요약하면
scene-gates.md §1 이 이미 페르소나 둘(dhseo · taeels)의 장면이고 §2 가
조각마다 수용 기준을, §2.1 이 화면 검증을 갖고 있다. 스토리를 새로 내면
같은 것의 두 번째 정본이 생긴다.
그래서 묶는 축이 스토리가 아니라 장면이다.


1. 장면 -> 조각 -> 유닛

dhseo 장면 하나를 다섯 조각으로 자른 것이 scene-gates.md 이고, 조각마다
그것을 초록으로 만드는 유닛이 있다.

   장면의 순간                                    조각    유닛
   ──────────────────────────────────────────────  ────    ────────────
   (기동이 안 깨졌다 — 장면 밖의 바닥)               CP0     U-바닥
   ①  보드가 함대에 있다.  현황판에 보인다            CP1     U-관측API
   ②  계약이 온다.  보드가 잡힌다                     CP1     U-관측API
   ③  둘째 계약이 QUEUED.  둘 다 보인다               CP2     U-대기열
   ④  제어판에서 at-boundary 로 drain 을 건다         CP3/CP4 U-drain / U-제어판
   ⑤  경계에서 임대가 풀린다.  draining 이 보인다      CP3     U-drain
   ⑥  dhseo 가 보드를 쓴다.  LED 가 새 패턴이다        CP4     전부
   ⑦  drain 을 푼다.  둘째 계약이 보드를 집는다        CP3/CP4 U-drain / U-제어판

④ 와 ⑦ 이 조각 둘에 걸치는 것은 같은 일을 두 표면이 한다는 뜻이다.
CP3 은 정책 파일로 걸고 풀고, CP4 는 같은 것을 제어판 버튼으로 한다.
scene-gates.md §2.1 이 CP3 을 「화면 없음」으로 둔 이유가 이것이다.


2. FR -> 유닛

requirements.md §4 의 추적표를 유닛 쪽으로 뒤집었다. FR-1 ~ FR-25 가
빠짐없이 어느 유닛엔가 걸린다.

U-바닥 (CP0)

   FR-1   GET /v1/nodes 의 저장 쪽 — ListNodes
   FR-2   GET /v1/runs 의 저장 쪽 — ListRuns
   FR-3   StepView.chosen.  DB 에 있고 뷰에 없었다
   FR-6   runs.state 어휘에 QUEUED (상수와 자리)
   FR-13  정책 자리 — nodes 열과 UpsertAdvert 시그니처

U-관측API (CP1)

   FR-1   GET /v1/nodes 라우트
   FR-2   GET /v1/runs 라우트 + current[] + reject
   FR-4   임대는 GET /v1/nodes 에 내장.  별도 표면 없음
   FR-5   중앙 현황판 정적 파일 — S0 · S0b · S1 · S1b · S2
   FR-16  화면 몫 — draining 배지 두 국면

U-대기열 (CP2)

   FR-6   409 -> QUEUED, 제출 응답 202.  422 는 그대로 FAILED
   FR-7   QUEUED Run 의 steps 를 제출 시점에 만든다
   FR-8   승격 — WakeQueued 가 도착 순서로 전부 훑는다
   FR-9   깨우기 다섯 지점 (여섯째는 U-drain)
   FR-10  기동 시 WakeQueued 한 번
   FR-11  중앙 쪽 — submit 이 busy 에 DrainingNodes 를 합친다

U-drain (CP3)

   FR-9   여섯째 깨우기 — drain 해제를 받은 광고 처리
   FR-11  노드 쪽 — 매칭에서 draining 노드 제외
   FR-12  정책 자리.  정본은 노드의 파일.  위치와 형식은 Functional Design
   FR-13  경로 — 읽기 · 싣기 · 복사 · 되돌리기 · Worker 에 넘기기
   FR-14  두 모드.  graceful 과 at-boundary
   FR-15  해제는 소유자 명시
   FR-16  drain 중에도 광고를 계속 보낸다

U-제어판 (CP4)

   FR-17  enodectl serve [name].  이 기계의 노드를 전부 서브한다
   FR-18  프로세스 제어 — status · start · stop · logs
   FR-19  신원 — node_id · label · principal · instance
   FR-20  탐지 능력 읽기 전용
   FR-21  현재 작업.  출처는 Mediator 조회
   FR-22  drain 토글 — 걸기 · 모드 고르기 · 풀기
   FR-23  Mediator 연결 상태와 마지막 응답 시각
   FR-24  호스트 화면 S3 · S5
   FR-25  마지막 관측 캐시.  observed 와 stale

U-MCP (CP5)

   FR-26  runctl mcp — stdio JSON-RPC 하나.  새 실행파일 없음
   FR-27  토큰은 환경변수.  도구 인자로 안 받는다
   FR-28  도구 일곱.  전부 기존 REST 를 감싼다
   FR-29  runctl.Client 에 Nodes · Runs 두 메서드

셈

   유닛에 한 번 이상 걸린 FR      29
   어느 유닛에도 안 걸린 FR        0
   유닛 둘에 걸린 FR               FR-1 · FR-2 · FR-6 · FR-9 · FR-11 · FR-13 · FR-16
                                  일곱.  전부 저장 쪽과 표면 쪽으로 갈린 것이다
   유닛 하나에만 걸린 새 넷         FR-26 ~ FR-29 는 전부 U-MCP 다.  저장 쪽이 없다 —
                                  이 유닛이 DB 도 Mediator 도 안 건드리기 때문이다

3. NFR -> 유닛

기능이 아닌 요구는 완료 조건으로 걸린다. unit-of-work.md 의 유닛마다
완료 조건에 번호가 박혀 있고, 여기는 그 반대 방향의 색인이다.

묶음 유닛
NFR-S1 · S2 · S3 · S7 · S8 (바인딩 · 토큰 · 파일 권한) U-제어판
NFR-S4 · S5 (라우트 토큰 · 입력 검증) U-관측API
NFR-S6 (HTML 표면 헤더 넷) U-관측API · U-제어판
NFR-S9 (오류 문구) U-관측API · U-제어판
NFR-I1 · I2 (불변식 · READY 안 만들기) U-바닥 · U-대기열
NFR-I3 (중앙 drain 라우트 없음) U-drain
NFR-I4 (match.Match 안 고침) U-바닥 · U-대기열
NFR-I5 (단계 도중에 안 끊음) U-drain
NFR-I6 (dry-run 응답 불변) U-대기열 · U-drain
NFR-I7 (재제출 200) U-대기열
NFR-P1 ~ P6 (패키지 경계) U-바닥이 검사기를 내고 U-제어판 · U-관측API 가 지킨다
NFR-O1 ~ O6 (폴링 · 갱신 · 배지) U-관측API · U-제어판
NFR-Q1 ~ Q5 (품질 게이트) 전부. CP0 ~ CP4 마다 돈다

4. 화면 -> 유닛 -> 게이트

화면이 있는 유닛의 완료 조건은 그 화면의 버튼을 전부 나열한다
(scene-gates.md §2.1 · design/README.md §7). 목록은 unit-of-work.md
안에 있고 여기는 어느 화면이 어디에 속하는지만 적는다.

화면 무엇 유닛 파일 검증 게이트
S0 토큰 입력 U-관측API internal/api/ui/ CP1
S0b 토큰 거절 (401 인라인) U-관측API internal/api/ui/ CP1
S1 함대 격자 + Run 목록 U-관측API internal/api/ui/ CP1 · CP2 · CP4
S1b 갱신 실패 U-관측API internal/api/ui/ CP1
S2 Run 상세 · 작업 그래프 U-관측API internal/api/ui/ CP1
S3 호스트 제어판 (도는 노드) U-제어판 internal/panel/ui/ CP4
S5 호스트 제어판 (멈춘 노드) U-제어판 internal/panel/ui/ CP4
S4 트랜스크립트 없음 — —

S4 는 자리만이다 — constraints.md §5 가 범위 밖으로 뒀고 S3 의 트랜스크립트
카드는 비활성으로 그린다.

S1 이 게이트 셋에 걸리는 것이 이 표의 요점이다. CP1 이 카드와 임대를,
CP2 가 QUEUED 행을, CP4 가 draining 배지 두 국면을 본다. 화면을 U-관측API
에 합쳤어도 검증은 세 조각에 흩어진 채로 남는다.


5. 게이트 -> 유닛 요약

조각 무엇을 확인하나 딛는 유닛 화면 검증
CP0 기동이 안 깨졌다. 경계 검사 초록 U-바닥 없음
CP1 보인다. 두 라우트가 실데이터 JSON U-관측API S0 · S0b · S1 · S1b · S2
CP2 기다린다. 202 · QUEUED · 승격 U-대기열 S1 의 QUEUED 행
CP3 돌려받는다. 경계에서 놓고 풀면 돌아온다 U-drain 없음 — 정책 파일과 GET /v1/nodes 로 닫는다
CP4 한 장면. ① ~ ⑦ 을 끝까지. LED 가 새 패턴 전부 S3 · S5 · S1 의 배지
CP5 감싼다. tools/list 가 일곱. 같은 자료가 MCP 로 나간다 U-MCP 없음 — MCP 가 화면을 안 만든다

CP5 는 CP4 의 조건이 아니다. dhseo 장면에 MCP 가 안 나오므로 CP5 가
빨개도 CP4 는 초록일 수 있고, 반대로 CP5 는 CP1 만 초록이면 언제든 돈다.
게이트 사슬에 안 들어가는 유일한 조각이다.

CP4 는 유닛 하나의 게이트가 아니다. U-제어판이 마지막에 오지만 초록으로
만드는 것은 다섯 전부이고, 그래서 앞의 넷 중 하나라도 보류면 CP4 가 못 닫힌다
(scene-gates.md §4).