그림 1의 🎯 카드를 확대했다

Assessment를 연다

도메인 한 장에서 판정은 카드 하나였다. 그 카드를 열면 객체들이 나온다 — 전체 설계도 한 장을 먼저 보고, 누가 무엇을 하는지(협력), 무엇을 품는지(구조), 어떤 순서인지(라인), 마지막으로 실측 순서로 파고든다.

한 장 — 전체 설계도

판정 설계 전체를 한 장에

세 가지 분리가 한 그림에 있다 — 도메인 분리(세 개의 존: 빌려 쓰는 사실 / 요청 동안만 존재하는 공장 / 영속되는 답), 책임 분리(역할 4색: 재료·규칙·값·라인), 그리고 관계 문법(흐름은 실선으로 아래로, ID 참조는 점선으로 위로).

다른 애그리거트 — 빌려 쓴다영속 · ID로만 안다 · 도메인 한 장의 카드들
판정 공장요청 한 번 동안만 존재 — 아무것도 저장되지 않는다
재료
일급 컬렉션
📦ObservationWindow 관측창사진 여러 장 — 미래 차단 · 스파이크 제외
👉JudgedWindow 라벨된 창precedingOrderFor(순번) → 직전 버스
규칙
교체 가능
🏷️FullnessPolicy 만석의 정의judge(관측) → FULL·AVAILABLE·모름
🎰BoardingChanceModel 확률 카트리지estimate(봉투) → Estimate
🕳️episode · wait 빈 슬롯 둘unavailable@builtin — 정직한 "모델 없음"

스스로 지킨다
Probability만분율 정수만 존재 PassedStopMarkhasPassed()로만 비교 Estimate값 아니면 사유 DataState확률 칸에서만 파생
🔁 조립 라인 — 순서만 안다 · 판정 규칙 소유 금지 · 바깥 접촉은 수집까지, 이후는 전부 순수 함수
🎯 Assessment 애그리거트영속 — 같은 재료·같은 모델이면 언제든 같은 답으로 재생성
query노선(버전)+순번 judgedAt주입된 시각 탈 확률4660 = 46.6% 몇 대사유: 모델 없음 몇 분사유: 모델 없음 precedingBus직전 버스 요약 dataStateOK lineage모델 4 + 근거 범위
실선 흐름 — 사실이 재료가 되고, 불변식을 통과한 답만 나온다 점선 ID 참조 — 아래(답)가 위(지식·사실)를 이름으로만 안다 역할 — 재료 · 규칙 · 값 · 라인

확대 1 — 객체와 협력

객체는 필드가 아니라 메시지로 산다

실측 질문 하나 — "18:40, 농수산물시장(순번 61), 탈 수 있어?" — 가 네 번의 메시지로 답이 된다. 각 객체는 받는 메시지(메서드)가 명함이고, 판단에 필요한 규칙을 자기 안에 갖고 있다. 서비스의 if문이 아니다.

🏷️ FullnessPolicy 만석 정책 judge(잔여 0석) → FULL
👉 JudgedWindow 라벨된 관측창 precedingOrderFor(61) → v581
🔁 조립 라인 오케스트레이터 "탈 수 있어?"를 들고 순서대로 찾아간다 판정 규칙 소유 금지 — 순서만 안다
🎯 Assessment 판정 new Assessment(…) → 46.6% 탄생
🎰 BoardingChanceModel 확률 카트리지 estimate(봉투) → ℙ(5340).complement() = 4660
실선 화살표 라인이 보내는 메시지 (①→④ 순서) 초록 칩 객체의 응답 — 받는 메시지(메서드)가 객체의 명함
🏷️ 만석 정책 — 관측 1건 + 정원만 본다. 만석의 정의는 나만 안다 (정의가 바뀌면 학습 상수도 무효) 👉 관측창 — 좌석을 안 본다. 동률이면 명시 규칙(진행도→최신 바퀴→해시), 그래도 못 가르면 AMBIGUOUS 사유 🎰 확률 모델 — 재료는 봉투로만. 포트를 조회하는 순간 백테스트가 미래를 훔쳐본다 🎯 판정 — 세 칸 없이는, 계보 없이는 태어나지 못한다. 불량품은 생성자에서 거부

스스로를 지키는 값들 — 잘못된 값은 태어나지 못한다

우테코 문법 그대로다 — LottoNumber가 setter 없이 검증과 비교만 갖듯, 값이 자기 규칙을 독점한다.

🛡️
Probability

만분율 정수(0~10000)만 존재. 소수점 확률은 생성자에서 죽는다 — 같은 입력이면 비트까지 같은 답. 보수 계산(complement)도 자기 몫.

🛡️
PassedStopMark

통과 비교는 hasPassed(순번)로만. 맨정수를 노출하지 않아 "실수로 순번과 비교"가 컴파일되지 않는다.

🛡️
Estimate

값이거나, 사유 있는 미추정이거나 — 둘뿐. "그냥 없음"은 표현 자체가 불가능하다 (블랙잭 Bust 문법).

🛡️
DataState

from(확률 칸) 단일 인자 — 다른 칸을 보는 구현이 시그니처에서 막힌다. 파생 규칙이 타입에 박제.

규칙마다 집이 있다 — 서비스 if문이 아니라
도메인 규칙소유 객체 (받는 메시지)
나를 지난 차 중 누가 직전인가 + 동률이면 누구JudgedWindow.precedingOrderFor(순번)
이 관측은 만석인가FullnessPolicy.judge(관측)
만석일 때 탈 확률Probability.complement()
이 차가 내 정류장을 지났나PassedStopMark.hasPassed(순번)
화면에 어떤 배지를 다나DataState.from(확률 칸)
사유 없는 미추정 금지NotEstimated 생성자
불완전한 답 금지 (세 칸·계보)Assessment 생성자 — 불변식 28개 중 12개가 생성자 검증
흐름의 순서 (규칙 아님)조립 라인 — 판정 규칙 소유 금지가 라인의 계약

행동이 적은 객체도 둘 있다 — Lineage와 PrecedingBusView. 의도다: 영수증은 계산하지 않는다. 계산은 값객체가 하고, 기록은 그 결과가 완전한지만 보증한다.

확대 2 — 카드 속 구조

판정 한 장에 무엇이 들었나

질문 — 무엇을 물었나
답 세 칸 — 항상 존재한다
근거와 계보 — 답의 신분증
카드 안의 칸품고 있다 (같이 저장·같이 삭제) 점선 이름(ID)만 안다 회색 카드는 이 페이지 밖 — 도메인 한 장의 애그리거트

확대 3 — 답이 만들어지는 길

답은 조립 라인에서 나온다

질문 하나가 일곱 단계를 지나 위의 카드가 된다. 각 단계는 자기가 안 하는 일이 명확하다 — 그래서 모델을 갈아 끼워도, 백테스트를 돌려도 라인의 모양이 안 바뀐다.

🧭1 해석질문을 도메인 좌표로
노선 버전·정류장 순번
관측을 안 본다
📡2 수집위치 API 1콜
유일한 바깥 접촉
해석을 안 한다 — 실패도 사실
🧹3 성형스파이크 걸러내고
바퀴(trip) 나누기
판정을 안 한다
🏷️4 라벨관측마다 만석 라벨
FULL·AVAILABLE·모름
창 전체를 안 본다
👉5 선택직전 버스 고르기
동률이면 명시 규칙
좌석을 안 본다
🎰6 모델슬롯의 카트리지 실행
재료 부족이면 라인이 접음
포트 조회 금지 — 봉투로만
📦7 조립Assessment 생성
계보와 함께
추정을 안 한다 — 항상 실행
바깥과 닿는 구간 — 시계·API·쿼터 순수 구간 — 같은 입력 = 같은 답. 백테스트가 이 코드를 그대로 탄다

모델은 카트리지다 — 슬롯 4개

계약은 두 가지뿐 — 라벨링(관측 1건 → 라벨)과 추정(봉투 → 답). 빈 슬롯에도 이름이 있어서, v1의 "몇 대·몇 분" 칸은 0이 아니라 사유 있는 안 함이 된다.

fullness · 라벨링만석의 정의zero-seat@builtin잔여 0석 = 만석. 학습·서빙·채점이 같은 함수를 쓴다 — 정의가 바뀌면 상수도 무효
chance · 추정탈 확률const4@ps-2026-08-13상수 4개 lookup (학습 구간 ~08-07). 앞차 만석 46.6% · 여유 94.7%
episode · 추정몇 대 보내나unavailable@builtinv1엔 없다 — 그래서 답이 "모델 없음". 조용한 0이 아니다
wait · 추정몇 분 기다리나unavailable@builtinv2에서 카트리지만 꽂으면 된다 — 라인은 그대로

확대 4 — 실측으로 본 판정

2분 만에 답이 뒤집힌다

8/13 저녁, 3330 농수산물시장. 실제 관측으로 조립한 판정 두 장 — 직전 버스를 고르는 규칙 한 줄이 답을 지배한다. 그래서 규칙이 코드 구석이 아니라 도메인에 박제되고, 계보가 어느 규칙이었는지 기록한다.

18:40:31 판정

46.6%

직전 버스 v581 — 내 정류장 지나 두 정거장 앞 · 잔여 0석 → FULL

몇 대·몇 분: 모델 없음(사유 기록) · dataState OK

2분 뒤
직전 버스가
바뀌었다 →
18:42:55 판정

94.7%

직전 버스 v167 — 내 정류장을 막 출발 · 잔여 31석 → AVAILABLE

같은 라인, 같은 모델 — 바뀐 것은 관측뿐

실패도 답이다 — 미추정 사유 7종

미추정은 예외(throw)가 아니라 사유를 품은 값 — 블랙잭 Bust와 같은 문법. 어느 단계가 접었는지가 화면 배지(dataState)까지 그대로 이어진다.

NO_OBSERVATION — 관측 자체가 없다 NO_PRECEDING_BUS — 지나간 차가 없다 실측 3.6~7.1% FULLNESS_UNKNOWN — 좌석 미제공 0.067% STALE_OBSERVATION — 관측이 낡았다 AMBIGUOUS_PRECEDING — 동률 미해소 <1% ROUTE_NOT_SUPPORTED — 지원 밖 노선 MODEL_ABSENT — 모델 없음 v1 몇대·몇분
실패 경로 전수 — 어느 단계가 접고, 화면엔 뭐가 남나
사유접히는 단계모델 호출화면 상태(dataState)
ROUTE_NOT_SUPPORTED1.5 지원 게이트 — 수집을 아예 안 함(쿼터 방어)안 함MODEL_UNAVAILABLE
NO_OBSERVATION3 성형 — 빈 창. "장애"를 "앞차 없음"으로 말하지 않도록 먼저 접는다안 함UNAVAILABLE
FULLNESS_UNKNOWN4 라벨 → 5 앵커에서 드러남안 함SEAT_DATA_UNAVAILABLE
NO_PRECEDING_BUS5 선택 — 후보 없음안 함NO_PRECEDING_BUS
AMBIGUOUS_PRECEDING5 선택 — 해시까지 간 동률 + 후보 라벨 불일치일 때만안 함AMBIGUOUS
STALE_OBSERVATION5→6 경계 — 앵커 나이 > 임계(잠정 10분)안 함STALE
MODEL_ABSENT6 모델 — 빈 카트리지가 정직하게 답함확률 칸이면 MODEL_UNAVAILABLE, 아니면 무영향

규칙: 접혀도 7 조립은 예외 없이 실행돼 계보를 남긴다. dataState는 확률 칸에서만 파생 — v1에서 몇 대·몇 분이 "모델 없음"이어도 화면은 OK.

전체 필드표 펼쳐 보기 (판정 스키마의 원형)
필드관계근거
질문 🙋query품는다노선(버전 포함) + 정류장 순번 — 개편돼도 과거 질문의 의미가 안 흔들린다
judgedAt주입된 판정 시각. 시계 직접 조회 금지 — 백테스트가 과거 시각을 넣는 자리
답 세 칸 🎲boardingChance품는다Estimate — 만분율 정수(4660 = 46.6%). 부동소수 금지: 같은 입력이면 비트까지 같은 답
busesToSend품는다v1은 NotEstimated(MODEL_ABSENT) — 조용한 0 금지
expectedWait품는다
직전 버스 👉precedingBus품는다 + 이름만차량 가명 · 몇 정거장 앞(beyond) · 라벨 · 근거 시각 · 동률이면 어느 규칙으로 갈랐는지
화면 배지 🚦dataState품는다(파생)확률 칸에서만 파생한 7값 — 몇대·몇분이 "모델 없음"이어도 OK
계보 🧾modelRefs ×4품는다fullness·chance·episode·wait — 라벨 정책이 바뀌면 상수가 무효라 넷 다 기록
evidenceRef이름만Stored(사진 범위 ID) 또는 Ephemeral(즉석 해시) — 무저장 v1도 거짓 ID를 안 만든다
digests · trainedThrough품는다재현·비교 좌표. 학습 기준일 2026-08-07(코퍼스 실물로 확정)
보류 목록 — 실측·팀 결정으로 닫을 항목 10
항목닫는 방법
신선도 임계 구체값 (잠정 10분)가동 3일 judgedAt−observedAt 분포로 확정
좌석 앵커 정책 (최신 vs 통과시점)20일 아카이브로 두 정책 라벨 대조
직전 버스 거리 상한 K정차 소요 실측 후 결정 — 그때까진 기록만
동률 미해소의 실제 비용첫 주 판정 로그 집계 (상한 1% 확정)
dataState 값과 프런트 계약 일치Client API 명세의 enum과 대조
공휴일 달력 출처·버전v2 진입 시 결정 (v1은 안 읽음)
STALE 도달 실증 (소스 시각 정지)장애 구간 응답 1건 포착 시 확인
백테스트 채점 구간 부재 (학습이 8/07까지 전 구간)팀 결정 — 신규 수집 채점 vs 학습 구간 분할 재산출
상수의 구간 승격 (점 추정 → 신뢰구간)코퍼스 재집계로 즉시 가능
즉석(Ephemeral) 판정의 채점 제외 방식저장 도입 시점에 결정