Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ This repository intentionally ships no `AGENTS.md` / `CLAUDE.md`. If you work wi

## Layout

- `src/` — CLI (`cli.mjs`), floors (`floor-tmux.mjs`, `floor-rottie.mjs`), ledger/storage, watch, dashboards.
- `src/` — CLI (`cli.mjs`), floors (`floor-tmux.mjs`, `floor-herdr.mjs`), ledger/storage, watch, dashboards.
- `tests/` — run with `npm test` (`tests/run.mjs` sets an isolated tmux socket, no window, notifications off, then runs `node --test`). Do not run `node --test` bare. Tests that need tmux skip when it is absent.
- `scripts/watch-judge.sh` — example judge command for `kadan watch`; requires `KADAN_JUDGE_MODEL`.
- `skills/` — agent skills that drive Kadan (conductor, supervisor, secretary).
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ kadan attach 비서 # 비서 터미널에 들어가 대화 시작
| 개념 | 한 줄 설명 |
|---|---|
| **역할** | `kadan-<이름>` tmux 세션 하나. 예: `비서`, `감독`, `작업자-a` |
| **바닥(floor)** | 역할이 실제로 사는 터미널 층. 기본은 `tmux`, macOS 앱인 `rottie`도 지원. `herdr`는 명시적으로 선택하는 시험 기능 |
| **바닥(floor)** | 역할이 실제로 사는 터미널 층. 기본은 `tmux`. `herdr`는 명시적으로 선택하는 시험 기능. macOS 앱 `rottie`는 바닥이 아니라 창(`KADAN_WINDOW=rottie`)으로만 쓴다 |
| **원장(ledger)** | 시작·발령·우편·완료 같은 사건을 뒤에 덧붙이기만 하는 기록. 고치거나 지우지 않음 |
| **완료 마커** | 에이전트가 직접 출력하는 `KADAN:DONE <카드id> <ok\|failed>` 한 줄. 카단은 출력을 보고 완료를 짐작하지 않음 |
| **워크 / 카드** | 워크 = 약속한 결과 한 건, 카드 = 그 결과를 위해 한 담당에게 맡긴 일 한 건 |
Expand Down Expand Up @@ -117,7 +117,7 @@ kadan stop worker-a # 카단이 만든 세션만 끌 수
| 변수 | 뜻 | 기본값 |
|---|---|---|
| `KADAN_HOME` | 데이터 폴더 | `~/.kadan` |
| `KADAN_FLOOR` | 실행 바닥 (`tmux` \| `rottie` \| 시험 기능 `herdr`) | `tmux` |
| `KADAN_FLOOR` | 실행 바닥 (`tmux` \| 시험 기능 `herdr`) | `tmux` |
| `KADAN_HERDR_SOCKET` | herdr 시험 서버의 절대 소켓 경로. 별도 `KADAN_HOME`과 함께 지정 | 없음 |
| `KADAN_WINDOW` | 시작할 때 열 창 (`none` \| `rottie` \| `orca`). 비우면 `kadan window set`으로 고정한 기계 설정을 따른다 | `none` |
| `KADAN_SOCKET` | tmux 구획 이름 | `kadan` |
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ flowchart TB
USER[사용자와 감독] --> CLI[카단 CLI]
CLI --> WORK[업무 카드와 실행 카드]
CLI --> MAIL[우편과 역할별 inbox]
CLI --> FLOOR[실행 바닥: tmux 또는 rottie]
CLI --> FLOOR[실행 바닥: tmux, 시험용 herdr]
FLOOR --> ROLE[대화형 AI 역할 세션]
WORK --> STORE[(같은 SQLite: 사건과 상태 이력)]
MAIL --> STORE
Expand Down Expand Up @@ -43,7 +43,7 @@ flowchart TB
| 우편 | 누구에게 무슨 말을 했고 읽음·답변은 어떤 상태인가? | `mail/events.jsonl`과 본문 파일 |
| 역할별 우편함(inbox) | 내가 받은 편지·보낸 편지·답할 질문은 무엇인가? | 우편 원장의 역할별 조회. 역할마다 새 DB를 만들지 않음 |
| 시스템 사건 원장 | 어떤 세션이 시작·종료됐고 감시가 무엇을 했는가? | `system/events.jsonl` |
| 실행 바닥 | 어느 터미널에 입력하고 화면을 읽는가? | tmux 또는 rottie의 실제 세션과 PID |
| 실행 바닥 | 어느 터미널에 입력하고 화면을 읽는가? | tmux(시험용은 herdr)의 실제 세션과 PID |

**공통 실행 원장은 실행 카드에 연결되는 사건 이력이다.** 별도의 업무 관리 체계를 하나 더 만드는 것이 아니다. 카드 상태 이력은 약속과 진행을, 공통 사건은 발령·실행 종료를 맡는다. 카드에 연결된 일반 질문도 새 실행은 아니다.

Expand Down
2 changes: 1 addition & 1 deletion docs/card-center.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,6 @@ kadan card update 저장소/카드 --revision 4 --status-reason '검색 방식

### 터미널 출력 로그

새 tmux 세션은 원문 바이트를 빠른 gzip 압축으로 `out/<세션>.log.gz`에 뒤이어 보존한다. 같은 역할의 후속 세션은 gzip 멤버를 추가하며 `gzip -dc <절대경로>.log.gz`로 순서대로 복원한다. 실행 중에는 마지막 멤버가 아직 닫히지 않아 복원 명령이 종료부 부족을 표시할 수 있으므로, 완전한 검증은 해당 세션 종료 뒤 한다. gzip이 없으면 경고와 함께 기존 `.log` 기록을 유지한다. SQLite·로티 바닥의 기록 방식과 화면에서 DONE을 판정하는 경로는 바꾸지 않는다.
새 tmux 세션은 원문 바이트를 빠른 gzip 압축으로 `out/<세션>.log.gz`에 뒤이어 보존한다. 같은 역할의 후속 세션은 gzip 멤버를 추가하며 `gzip -dc <절대경로>.log.gz`로 순서대로 복원한다. 실행 중에는 마지막 멤버가 아직 닫히지 않아 복원 명령이 종료부 부족을 표시할 수 있으므로, 완전한 검증은 해당 세션 종료 뒤 한다. gzip이 없으면 경고와 함께 기존 `.log` 기록을 유지한다. SQLite·herdr 바닥의 기록 방식과 화면에서 DONE을 판정하는 경로는 바꾸지 않는다.

기존 `.log`·카드 근거·동결 JSONL은 이동하거나 삭제하지 않는다. 이 변경은 앞으로의 증가량을 줄이며 기존 공간을 회수한 것은 아니다.
2 changes: 1 addition & 1 deletion docs/card-worktime.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
| `restarted` | 같은 세대 안에서 다른 모델·강도로 다시 시작됐다. 시각만으로 어느 쪽인지 단정하지 않는다. **모델·강도가 같으면 실행 도구(omo·codex 등) 이름만 달라도 재시작으로 보지 않고 알려진 모델로 판정한다** |
| `no-model` | 실행 명령에서 모델을 읽을 수 없다 |

- 아직 살아 있는 세대(stop 없음)는 옛 세션 발령 막기와 같이 "지금 pane PID와 같은 start만" 본다. 읽기 전용 계산에서 바닥(tmux·rottie)을 조회하지 않으므로, 세대의 마지막 실행 명령 기록의 PID를 지금 PID로 본다.
- 아직 살아 있는 세대(stop 없음)는 옛 세션 발령 막기와 같이 "지금 pane PID와 같은 start만" 본다. 읽기 전용 계산에서 바닥(tmux)을 조회하지 않으므로, 세대의 마지막 실행 명령 기록의 PID를 지금 PID로 본다.
- **한계**: 원장이 아는 것은 세션을 띄울 때의 명령뿐이다. 세션 안에서 나중에 바꾼 모델(`/model` 등)은 알 수 없다.
- 역할 프로필(작업자·검수자)은 start 기록의 `roleProfile`이 기준이고, 없으면 카드 단계로 추론한다(review는 검수자, 그 밖은 작업자).

Expand Down
4 changes: 2 additions & 2 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
| 변수 | 뜻 |
|---|---|
| `KADAN_HOME` | 원장·카드·설정이 사는 폴더. 기본 `~/.kadan` (옛 이름 `KADAN_LITE_HOME`도 읽음) |
| `KADAN_FLOOR` | 에이전트가 사는 바닥. `tmux`(기본) 또는 `rottie`. 시험 기능 `herdr`는 별도 `KADAN_HOME`으로 명시 선택하며, 실행 중 전환·자동 폴백 없음 |
| `KADAN_FLOOR` | 에이전트가 사는 바닥. `tmux`(기본). 로티는 바닥이 아니라 창(`KADAN_WINDOW=rottie`)이라 `rottie`를 주면 `KADAN_FLOOR_INVALID`다. 시험 기능 `herdr`는 별도 `KADAN_HOME`으로 명시 선택하며, 실행 중 전환·자동 폴백 없음 |
| `KADAN_HERDR_SOCKET` | herdr 시험 기능의 named server 절대 소켓 경로. `KADAN_HOME`과 함께 필수. 서버 자동 기동·훅 설치 없음. [실행 방법](experiments/herdr-roundtrip.md) |
| `KADAN_WINDOW` | tmux 바닥에서 시작할 때 여는 창. `none`(기본) · `rottie` · `orca`. 있으면 기계 설정(`kadan window`)보다 먼저다 |
| `KADAN_ROTTIE_BIN` | `KADAN_WINDOW=rottie`일 때 말 걸 로티 CLI의 절대경로. 있으면 기계 설정의 경로보다 먼저다 |
Expand Down Expand Up @@ -89,7 +89,7 @@ tmux 세션을 종료한 뒤 원장의 최신 탭 ID를 조회하고, `terminal

로티 데몬을 다시 켜면 tmux 세션(에이전트)은 살고, 그 세션을 보여 주던 로티 탭만 끊긴다. `restore`는 탭만 다시 붙인다.

- 바닥이 tmux이고 `KADAN_WINDOW=rottie`일 때만 쓴다. 로티 바닥은 데몬과 함께 에이전트도 끝나므로 되살릴 것이 없다.
- 바닥이 tmux이고 `KADAN_WINDOW=rottie`일 때만 쓴다.
- 세션마다 원장에 적힌 로티 탭 상태를 로티에 묻는다. `running`·`created`면 건너뛰고, `unknown`·`closed`·`exited`이거나 탭이 없으면 새 탭을 붙인다.
- 마지막 `start`에 로티 탭이 없는 세션(숨김으로 띄운 watch·대시보드)은 건너뛴다.
- 탭 조회가 하나라도 실패하면 아무것도 하지 않고 이유를 보고한다.
Expand Down
28 changes: 11 additions & 17 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
## 정체성

- 이 저장소는 카단(kadan)의 심플 코어다. 이전 카단 구현(관제층)은 동결 보존하며 이 저장소가 대체하려는 것이 아니다.
- **tmux는 지금의 바닥이지, 영원한 바닥이 아니다.** 나중에 로티 같은 다른 바닥으로
이동할 수 있다. 중요한 것은 바닥이 아니라 코어다 — 원장·안전장치·명령 인터페이스
- **tmux는 지금의 바닥이지, 영원한 바닥이 아니다.** 나중에 다른 바닥으로
이동할 수 있다. 로티는 바닥이 아니라 창(`KADAN_WINDOW=rottie`)으로만 쓴다. 중요한 것은 바닥이 아니라 코어다 — 원장·안전장치·명령 인터페이스
(`start/send/done/wait/read/status/log/attach/stop`)·DONE 마커 규약은 바닥과 분리해
유지하고, 바닥을 바꿀 때 코어는 그대로 갖고 간다.
- 실행 도구(provider) 어댑터를 만들지 않는다. 어떤 CLI든 바닥의 세션 안에 띄우면
Expand All @@ -44,26 +44,20 @@

tmux는 (a)(b)(c)를 충족했고 (d)는 Mac에서 통과했다(서버 왕복은 서버가 생기면).

**제품판 바닥(rottie)** — GUI 제품이라 (a)(b)(c)는 설계상 해당 없다. 자격은
(d) 12장 왕복 + 아래 전제를 문서에 명시하는 것이다.
**로티는 바닥이 아니다(2026-10-17 제거).** 로티 바닥(`KADAN_FLOOR=rottie`)은 쓰지 않아 코드·시험을
없앴고, `KADAN_FLOOR=rottie`는 `KADAN_FLOOR_INVALID`로 거절한다. 로티는 tmux 역할을 보여 주는
창으로만 쓴다(`KADAN_WINDOW=rottie`, 시니어 탭, adopt 탭). 9/15 이전 원장의 `floor:"rottie"` 시작 줄은
그대로 읽힌다.

- 앱이 떠 있어야 한다(`ROTTIE_APP_NOT_RUNNING`은 typed로 그대로 보고, 자동 기동 없음).
- 빌드마다 소켓·데이터·데몬이 따로다. 실측 대상은
Rottie dev 빌드 실행 파일(`KADAN_ROTTIE_BIN`)이고, start 원장에 create 응답의
`runtime.build`를 `rottieBuild`로 적으며, 빌드가 다른 앱을 한 원장에 섞지 않는다.
- Cmd+Q는 종료 팝업대로 터미널을 닫는다. 데몬 PTY 생존은 강제 종료·안전 재시작 경로에서만
성립한다(card-18 11번).

**등록 현황(2026-08-30 관리자 등록):** tmux(명세·서버), rottie(제품판). rottie 등록
근거는 2026-08-30 12장 왕복 표(Local build `8938ad06`, 관리자 작업장 기록)다. dev 빌드 재검증(card-19)과 일회성 `ROTTIE_INTERNAL` 재현은 남은 과제다.
**등록 현황:** tmux(명세·서버). herdr은 시험 바닥이다.

### 바닥 병존 조건 (4개)

- 바닥 = 파일 하나 + 함수 7개 + 선택 1개. 기계당 하나, `KADAN_FLOOR`로 설치 때
고정한다.
- 런타임 전환·자동 폴백·capability 등급은 만들지 않는다.
- 두 바닥이 병존하려면 둘 다 같은 12장 왕복을 통과해야 한다.
- 정식 등록 바닥은 tmux·rottie 둘이다. 2026-10-11 사용자 승인으로 [herdr 시험 바닥](experiments/herdr-roundtrip.md)을 선택 기능으로 제공한다. 별도 데이터 폴더와 named server 소켓을 명시하며, 정식 등록·기계 기본값 변경을 뜻하지 않는다.
- 바닥이 둘 이상 병존하려면 둘 다 같은 12장 왕복을 통과해야 한다.
- 정식 등록 바닥은 tmux 하나다. 2026-10-11 사용자 승인으로 [herdr 시험 바닥](experiments/herdr-roundtrip.md)을 선택 기능으로 제공한다. 별도 데이터 폴더와 named server 소켓을 명시하며, 정식 등록·기계 기본값 변경을 뜻하지 않는다.

## 잠긴 최소 규칙 (이것만은 지킨다)

Expand Down Expand Up @@ -96,7 +90,7 @@ tmux는 (a)(b)(c)를 충족했고 (d)는 Mac에서 통과했다(서버 왕복은
그래서 활동이 붙은 시각보다 뒤일 때(`activity > created`)만 사람 입력으로 센다. 로티 탭이 시작과 동시에 붙어도 첫 안내·발령이 막히지 않는다.
한계: 붙은 바로 그 초 안에 누른 키는 놓친다. 반대로 붙은 뒤 터미널 응답 같은 입력으로 활동이 바뀌면 그 창은 30초 보류된다(막히는 것은 시작 첫 안내뿐이고 start는 성공).
이는 화면에 보이는 확인이 아니며 AI 인증·모델 응답 성공을 증명하지 않는다. 복사모드 검사는 기존 공통 전송 경계를 재사용한다.
이 tmux 프로세스·입력 검증은 Rottie 바닥의 실측을 대신하지 않는다.
이 tmux 프로세스·입력 검증은 다른 바닥의 실측을 대신하지 않는다.
실제 전경 AI 프로세스의 명시 모델도 시작 기록과 대조한다. 불일치·미확인이면 거부한다.
빈 셸·비AI 명령·모델 미지정·이전 세대 신원만 남은 pane에는 카드를 붙여넣지
않는다 — 일반 우편·질문·답장은 이 경계를 거치지 않는다(2026-09-21 --profile
Expand Down Expand Up @@ -177,7 +171,7 @@ tmux는 (a)(b)(c)를 충족했고 (d)는 Mac에서 통과했다(서버 왕복은
- 코어(core): 바닥이 바뀌어도 갖고 가는 것 — 원장, 안전장치(생존 확인·모호하면 판정 금지·
자기 것만 종료), 명령 인터페이스(start/send/done/wait/read/status/log/attach/stop),
DONE 마커 규약.
- 바닥(bottom): 에이전트가 사는 곳. 지금은 tmux 구획(`-L kadan`). 로티 같은 다른 바닥으로
- 바닥(bottom): 에이전트가 사는 곳. 지금은 tmux 구획(`-L kadan`). 다른 바닥으로
이동할 수 있다.
- 역할(role): 슈퍼감독·일반감독·작업자 등 바닥의 세션 하나로 띄우는 단위.
- 원장(ledger): 무엇을 했는지 뒤에만 추가하는 사건 기록. 현재 실제 저장은 SQLite다.
Expand Down
12 changes: 6 additions & 6 deletions docs/kadan-guide.html
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,9 @@ <h2>"다 했어요"를 어떻게 믿을까요?</h2>
<section class="scene" id="s5">
<span class="num">장면 5 · 비교</span>
<h2>바닥이 바뀌면 카단도 바뀔까요?</h2>
<p class="claim">AI가 사는 곳(바닥)은 tmux에서 로티(rottie) 같은 다른 곳으로 바뀔 수 있어요. 하지만 원장·검문소·DONE 마커·명령(<b>코어</b>)은 그대로 두고 <b>바닥 조각만 갈아끼워요</b>.</p>
<p class="claim">AI가 사는 곳(바닥)은 tmux에서 herdr(시험용) 같은 다른 곳으로 바뀔 수 있어요. 하지만 원장·검문소·DONE 마커·명령(<b>코어</b>)은 그대로 두고 <b>바닥 조각만 갈아끼워요</b>.</p>
<figure>
<svg viewBox="0 0 960 430" role="img" aria-label="같은 코어 상자가 두 번 있고 아래 바닥 조각만 tmux에서 rottie로 바뀐다 — 코어는 그대로다">
<svg viewBox="0 0 960 430" role="img" aria-label="같은 코어 상자가 두 번 있고 아래 바닥 조각만 tmux에서 herdr로 바뀐다 — 코어는 그대로다">
<defs>
<marker id="m-warn-5" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" class="t-warn"/></marker>
</defs>
Expand All @@ -375,7 +375,7 @@ <h2>바닥이 바뀌면 카단도 바뀔까요?</h2>
<line x1="392" y1="332" x2="566" y2="332" class="st-warn" stroke-width="2.5" marker-end="url(#m-warn-5)"/>
<line x1="566" y1="344" x2="392" y2="344" class="st-warn" stroke-width="2.5" marker-end="url(#m-warn-5)"/>
<text x="479" y="316" text-anchor="middle" font-size="13" font-weight="700" class="t-warn">바닥만 갈아끼운다</text>
<text x="479" y="376" text-anchor="middle" font-size="11.5" class="t-muted mono">KADAN_FLOOR=tmux | rottie (floor.mjs:4)</text>
<text x="479" y="376" text-anchor="middle" font-size="11.5" class="t-muted mono">KADAN_FLOOR=tmux | herdr (floor.mjs:4)</text>
<rect x="580" y="56" width="340" height="224" rx="14" class="f-panel st-accent" stroke-width="2"/>
<text x="600" y="88" font-size="15" font-weight="800" class="t-ink">코어 — 바뀌지 않는 것</text>
<rect x="600" y="104" width="146" height="44" rx="8" class="f-soft"/><text x="673" y="131" text-anchor="middle" font-size="13" class="t-accent">원장(ledger)</text>
Expand All @@ -385,11 +385,11 @@ <h2>바닥이 바뀌면 카단도 바뀔까요?</h2>
<text x="600" y="238" font-size="12" class="t-muted">start · send · done · wait · read ·</text>
<text x="600" y="258" font-size="12" class="t-muted">status · log · attach · stop</text>
<rect x="580" y="300" width="340" height="64" rx="10" class="f-warnf st-warn" stroke-width="2"/>
<text x="750" y="328" text-anchor="middle" font-size="14" font-weight="800" class="t-warn">바닥 조각: rottie</text>
<text x="750" y="350" text-anchor="middle" font-size="12" class="t-muted">제품 창 — 앱이 떠 있어야 한다</text>
<text x="750" y="328" text-anchor="middle" font-size="14" font-weight="800" class="t-warn">바닥 조각: herdr</text>
<text x="750" y="350" text-anchor="middle" font-size="12" class="t-muted">시험 바닥 — 별도 소켓·데이터 폴더</text>
<text x="480" y="408" text-anchor="middle" font-size="12.5" class="t-muted">바닥이 해 주는 일은 같다: 만들기·살아있나·PID·밀어넣기·읽기·종료·목록 (+변화 대기) — floor-tmux.mjs:596</text>
</svg>
<figcaption>코어(원장·검문소·DONE 마커·명령)는 같은 색 그대로, 바닥 조각만 tmux에서 rottie로 바뀐다. (출처: src/floor.mjs:4, src/floor-tmux.mjs:596)</figcaption>
<figcaption>코어(원장·검문소·DONE 마커·명령)는 같은 색 그대로, 바닥 조각만 tmux에서 herdr로 바뀐다. (출처: src/floor.mjs:4, src/floor-tmux.mjs:596)</figcaption>
</figure>
</section>

Expand Down
Loading
Loading