문서와 심볼

aidlc-docs 를 그대로 읽는다 · 읽기 전용
/home/sunny/enode-fixup-workshop2-visualizer연결 중
inception/reverse-engineering/business-overview.md160 줄

enode — 비즈니스 개요

리버스 엔지니어링 산출물. /home/sunny/enode-review/enode/ 를 f46e187 시점에
읽고 적었다. 설계 정본이 아니다 — 정본은
aidlc/spaces/default/knowledge/documents/enode-design/INVARIANTS.md 이고,
이 문서는 「구현에 무엇이 있는가」만 기술한다.

이 저장소가 무엇인가

AI-Native SDLC 실행 모델의 구현이다. Go 모듈 github.com/taeels/enode,
실행파일 다섯(mediator · enode · runctl · enodectl · iapadapter)과
라이브러리 열(internal/*)로 이루어진 단일 저장소다.

세 축이 시스템을 이룬다.

축 실행파일 하는 일
접수 runctl 사람이 Run 계약을 제출하고 상태 · Record · 취소를 본다. 무상태
중앙 mediator 계약을 검증하고 노드에 배정하고 상태를 소유한다. 추론을 하지 않는다
실행 enode 자원이 있는 기계에 상주하며 Mediator 로 연결을 걸어 단계를 당겨 실행한다

여기에 한 기계의 enode 인스턴스를 관리하는 enodectl 과, 바깥 이슈 트래커를
아는 유일한 부품인 iapadapter(ADR-040)가 붙는다.

해결하는 문제 — 자원이 추론 쪽으로 오지 않는다

식별된 자원은 개발보드와 개발자가 쌓아온 컨텍스트다. 둘 다 복제되지
않는다. 보드는 물리적으로 하나뿐이고, 컨텍스트는 그 사람의 기계와 머릿속에만
있다.

이 제품이 없으면 자원이 추론이 있는 곳으로 와야 한다. 기존에는 MCP 가 그
역할을 했고 세 가지가 걸렸다.

   관리      MCP 서버가 발산한다
   설치      사용자마다 깔아야 한다
   경직성    컨텍스트 입도(granularity)를 제어할 수 없다

enode 는 방향을 뒤집는다 — 추상화 · 자원 노출 · 임대. 추론이 자원 쪽으로
간다. 그 뒤집기가 코드에서 관측되는 자리는 다음 셋이다.

  • 노드가 연결을 건다. internal/enode/ 전체에 net.Listen 도 http.Server
    도 0건이다. 저장소 전체에서 서버를 여는 자리는 cmd/mediator/main.go:112
    하나뿐이다. 자원이 있는 기계는 포트를 열지 않는다
  • 노드끼리 만나지 않는다. internal/enode/claim.go 의 모든 HTTP 호출이
    c.Base(Mediator)로만 간다. 단계 사이의 산출물도 Mediator 를 경유한다
    (PUT .../blob/NAME 로 올리고 GET /v1/runs/RUN/blob/NAME 으로 내린다)
  • 자원 점유는 중앙이 소유한다. internal/store/schema.sql 의
    leases (node_id text PRIMARY KEY) 한 줄이 「노드 하나는 동시에 한 Run」을
    애플리케이션 로직이 아니라 데이터베이스 기본키로 강제한다

가치의 고정점 — dhseo 시나리오

dhseo 가 퇴근했다. 재현 환경이 그 자리에만 있다. candidate patch 를 거기서
검증해야 한다.

enode 는 부재중인 기능 담당자의 대리인 노릇을 한다. 오케스트레이터가
graphics 파트에서 병렬 실험이 필요할 때 자원을 획득하고(acquire), 실험을
설계하고(계약의 expands 로 계획을 위임), 진행하고(claim 워커가 하네스를
띄운다), 보고까지(Run Record 봉인 + GET record) 한다.

이 시나리오가 가치 논의의 고정점이다. 완결성을 판단하는 기준은 이 시나리오가
끝까지 도는가
이지 「돌아간다」가 아니다.

시나리오의 각 동작이 코드에서 사는 자리:

시나리오 동작 구현 위치
자원 획득 internal/store/acquire.go runAcquires · doAcquire · tryGrab
부재자 기계에 배정 internal/match/match.go:66 Match — 순수 함수, I/O 0
실험 설계 위임 internal/store/expand.go:52 applyExpands (계약이 실행 중에 자란다)
실험 진행 internal/enode/claim.go Worker.execute → internal/enode/runner.go:54 runHarness
사람에게 되묻기 internal/store/ask.go + GET /v1/asks · POST .../answer
보고 internal/record/record.go 봉인(0444/0555) + GET /v1/runs/{id}/record (tar)
자원 반납 internal/store/release.go · internal/store/reap.go SettleIfDone

핵심 기능 — 코드에 있는 것

Run 계약(Run Contract) 이 이 제품의 중심 개념이다. 사람이 JSON 하나를
제출하면 Mediator 가 그것을 단계의 방향 그래프로 펴서 노드에 나눠 준다.

  • 두 종류의 단계 — agent(하네스에 프롬프트를 주고 산출물을 받는다)와
    run(명령을 실행한다). 둘 다이거나 둘 다 아니면 400
    (internal/contract/contract.go:796 Kind())
  • 순서는 목록이 아니라 간선 — needs 로 의존을 적고, 기본값은 직전 단계다.
    게이트 술어가 internal/store/claim.go:277-289 에 있다
  • 계약이 실행 중에 자란다 — expands 로 계획을 위임하면 새 단계가 붙는다.
    계약은 하나가 아니라 열(version 열) 이고 Record 에 전부 남는다
  • 분기와 건너뜀 전파 — dispatch 로 갈래를 고르면 안 고른 갈래가 SKIPPED 로
    전파된다 (internal/store/dispatch.go:118 propagateSkips)
  • 구간 반복과 되먹임 재시도 — loop · validate_with
    (internal/store/rollback.go)
  • 실행 중 자원 증감 — acquire 로 늘리고 release 로 조기 반납한다
  • 되묻기 — 에이전트가 사람에게 물을 수 있다. 인박스(GET /v1/asks)가 정본이고
    웹훅 푸시는 보조다 (internal/store/ask.go:102 PushAsks)
  • 성공 판정은 기계적 조건만 — success_when 을 internal/store/verdict.go:98
    Verify 가 순수 함수로 판정한다. DB 도 시계도 안 본다. 코드가 종료코드를
    판정에 쓰지 않는다 (internal/enode/claim.go:585-593)
  • 봉인된 Run Record — 끝난 Run 의 기록은 파일 0444 · 디렉터리 0555 로 봉인되고
    그 뒤의 쓰기는 410 으로 거절된다

도메인 어휘

이 저장소를 읽으려면 다음 명사가 필요하다. 전부 internal/contract 가 소유하며
네 실행파일의 공통 어휘다.

용어 뜻 정의 위치
Run 계약 하나의 실행 인스턴스 internal/store/store.go:145-152 (상태 상수)
Contract 무엇을 어떤 순서로 어디서 할지 적은 JSON internal/contract/contract.go:59
Step 계약의 한 단계. agent 또는 run internal/contract/contract.go:441
Node 자원을 광고하는 실행 기계 internal/enode/identity.go (신원 유도)
Advert 노드가 자기 속성을 알리는 것 internal/enode/detect.go:20 Detect
Lease 어떤 Run 이 어떤 노드를 점유했다는 장부 internal/store/schema.sql leases
Claim 노드가 실행할 단계를 하나 집어오는 것 internal/store/claim.go:246 ClaimStep
Run Record 그 Run 에서 일어난 일의 봉인된 파일시스템 기록 internal/record/record.go
Ledger 시야의 세 축(발견 · 주입 · 축소) 기록 internal/store/observe.go:96
Ask 실행 중 사람에게 던지는 질문 internal/store/ask.go
Harness 실제 추론을 돌리는 바깥 프로그램(claude CLI) internal/enode/harness.go:217

완결성의 합격 기준 — 슬라이스 S1~S10

README.md:20-32 의 표가 이 저장소의 합격 기준이다. 「돌아간다」가 아니라
발표자료 §15 의 O1~O9 중 무엇이 켜지는가로 잰다. S1~S7 까지가 스켈레톤이다.

슬라이스 켜는 것
S1 계약 타입 + 매처 (순수 함수) I/O 0. 넷의 공통 어휘
S2 Mediator: DB 스키마 + POST /v1/runs I5 · I1(=O7)
S3 enode: 신원 + 로컬 잠금 + 광고 루프 O8 · O9
S4 두 연결 — 하트비트 + claim 롱폴 + 명령 실행 O6 · I2
S5 계약 조건 대조 — success_when O4
S6 Record 봉인 + GET record (tar) O1 · O2 · O3 · I4
S7 runctl — 제출 · 상태 · Record · 취소 O5 · O7
— 여기까지가 스켈레톤
S8 blob 별 모양 + 스키마 검증 I4
S9 agent 어댑터 + 되먹임 재시도 루프
S10 워크스페이스 준비 · GET /v1/capabilities

README.md:34 는 S4 가 최대 위험이라고 적는다 — ADR-016(하트비트가 임대를
나른다)은 설계만 있고 한 번도 안 돌았으며, 미정 값 셋(임대 기간 · 갱신 주기 ·
not_after_factor)이 전부 거기서 정해진다. 이 리뷰의 계측은 그 진술과 같은 곳을
가리킨다: 노드 쪽 임대 워치독이 사는 internal/enode/claim.go 가 이 저장소에서
가장 안 덮인 실행 경로다(24.8%). 자세한 것은 code-quality-assessment.md.

바깥과 닿는 유일한 자리

cmd/iapadapter 만이 저장소 바깥(It's a Plan 이슈 트래커)을 안다. 내부 패키지에
의존하지 않고 자기 안에서 HTTP 로 Mediator 와 말한다 — 어댑터를 갈아 끼워도
나머지가 안 흔들리게 하려는 배치다. 이슈를 읽어 Run 계약을 만들고, Run 의
진행과 결과를 이슈 코멘트로 되돌려 놓는다.

이 문서의 근거

  • 제품 의도와 dhseo 시나리오: aidlc/spaces/default/knowledge/aidlc-shared/product-intent.md
  • 슬라이스 표와 배치: enode/README.md:20-56
  • 정본 문서 6종: aidlc/spaces/default/knowledge/documents/enode-design/
  • 나머지 전부: enode/ 의 Go 소스 직접 독해 (f46e187)