이 Mac 의 opencode 가 1.x 에서 v2.0.32 로 올라갔다. MAM 의 opencode 지원(어댑터·create/resume·purge·화면 판독 픽스처)은 1.x(픽스처 기준 OpenCode 1.18.32)를 기준으로 만들어졌다. v2 에서 CLI 와 데이터 레이아웃이 바뀐 부분이 있어 호환성 확인과 수정이 필요하다.
아래 확인된 사실은 v2.0.32 의 --help 출력과 데이터 디렉터리를 읽기 전용으로 살펴본 결과다. 실제 세션 생성·재개·purge 는 아직 시험하지 않았다.
확인된 사실 (v2.0.32)
opencode db path 서브커맨드가 없다.
서브커맨드 목록에 db 가 없다. 호출하면 최상위 도움말을 출력하고 exit 0 으로 끝난다.
DB 경로는 이제 opencode debug paths 의 db 줄로 나온다(~/.local/share/opencode/opencode.db).
영향: adapters/opencode.py:62-115_resolve_db 의 1단계가 도움말 텍스트를 경로로 받는다. 경로로 존재하지 않아서 지금은 파일시스템 폴백(opencode.db)으로 우연히 맞는다.
auth.json 이 데이터 디렉터리에 없다.
~/.local/share/opencode/auth.json 이 없다. DB 에 credential·account·control_account 테이블이 생겼다.
영향:
adapters/opencode.py:205-210auth_ok 는 이 파일이나 provider 환경변수만 본다.
create_session.sh:145-151 도 같은 파일을 먼저 확인한다. 다만 거기서는 opencode --version 폴백으로 통과한다.
환경변수 없이 OAuth 로그인만 한 환경에서는 auth_ok 가 false 가 될 수 있다.
최상위 실행의 플래그가 바뀌었다.
opencode --help 의 FLAGS 는 다음 6개뿐이다: --standalone, --server, --auto, --continue/-c, --session/-s, --prompt.
--agent 가 없다.run 서브커맨드에는 --agent 가 있다.
MAM 은 생성·재개 모두 opencode --auto --agent build / opencode --session <id> --auto --agent build 로 띄운다. 해당 위치:
adapters/opencode.py:197-203
create_session.sh:216
resume_session.sh:181,193
v2 TUI 가 --agent 를 거부하는지, 무시하는지, 숨은 플래그로 받는지는 아직 확인하지 않았다.
--session 의 의미가 바뀌었다. 도움말은 "Session ID to continue, or to create if it does not exist" 다. 없는 id 로 재개하면 오류 대신 새 세션이 생길 수 있다. resume 의 materialized 판정과 tier-1 id 신뢰 전제를 다시 봐야 한다.
백그라운드 서비스 모델이 생겼다.
기본 실행은 "background service" 에 붙는다(--standalone 은 개별 서버, service 서브커맨드는 서비스 관리).
확인할 것: TUI 프로세스가 아니라 공유 서비스가 세션을 쥐고 DB 에 쓰는지, 그 결과가 다음 MAM 판단에 어떤 영향을 주는지.
pane 의 프로세스 판별(pane.cmd, agent 이름 해석)
stop 의 /exit·kill 체인 뒤 서비스 잔존
purge 가 서비스가 열어 둔 DB 행을 지울 때의 일관성
heartbeat 의 프로세스 이름 기반 판정
DB 스키마에 v2 테이블이 추가됐다.
기존 session·message·part 옆에 다음 테이블이 생겼다: session_v2(fork·suspend·idle 컬럼 추가), session_message, session_inbox, session_pending, event, event_sequence, todo, permission 등.
이 Mac 의 DB 는 session 과 session_v2 의 행 수가 같다(마이그레이션된 것으로 보임). 그러나 v2 가 새 세션을 어느 테이블에 쓰는지는 아직 확인하지 않았다.
영향: 어댑터의 다음 기능은 session 테이블만 조회한다.
discover(:212-)
verify_artifact(:117-)
재조정기의 opencode drift C
purge_artifacts(:169-196)는 message/messages/part/parts/session/sessions 만 지운다. 따라서 session_v2·session_message 등에 같은 세션의 데이터가 남을 수 있고, residual 보고에도 잡히지 않는다(#31 과 같은 계열).
확인 작업 (제안)
실제 홈을 건드리지 않도록, 가능한 한 HOME/XDG_DATA_HOME 를 임시 디렉터리로 두고 --standalone 으로 시험한다.
v2 TUI 기동: --auto --agent build 가 받아들여지는지, build 에이전트 지정 방법이 바뀌었는지
새 세션이 기록되는 테이블과 컬럼(session vs session_v2, directory, time_created 단위)과, discover/verify_artifact/drift C 가 v2 세션을 찾는지
opencode --session <id> 재개, 그리고 없는 id 일 때의 동작
백그라운드 서비스와 pane 프로세스의 관계: create 의 프로세스 판별, stop 뒤 잔존 프로세스, heartbeat 판정
purge: v2 테이블까지 지우는지, opencode session delete <id> 로 위임하는 편이 나은지, residual 보고
_resolve_db: db path 대신 debug paths 를 쓰거나 폴백만 쓰기, 그리고 exit 0 도움말 출력을 경로로 오인하지 않기
인증 판정: auth.json 대신 쓸 신호(opencode auth 계열 또는 credential 테이블)
화면 판독: ready_tokens·입력 프롬프트(┃ 블록)·input_stop_pattern(Build auto · <model> 줄)이 v2 TUI 에서도 맞는지, tests/fixtures/panes/opencode_idle.txt 를 v2 화면으로 갱신
1.x 지원 유지 여부 결정(두 버전 분기 또는 v2 전용) 및 문서(docs/NEW_AGENT_INTEGRATION_GUIDE.md 의 opencode db path·auth.json 서술, README 의 opencode --session) 정정
참고
관련 코드: .agents/skills/lib_py/agents/adapters/opencode.py, multi-agent-mux-create/scripts/create_session.sh, multi-agent-mux-resume/scripts/resume_session.sh, multi-agent-mux-monitor/scripts/reconcile.sh(drift C), multi-agent-mux-orc-onboard/scripts/orc_onboard.sh
관련 테스트: tests/test_a4_adapter_contract.py, tests/test_c1_tui_readiness.py, tests/test_issue10_13_purge.py 등 opencode 를 다루는 테스트
## 배경
이 Mac 의 opencode 가 1.x 에서 **v2.0.32** 로 올라갔다. MAM 의 opencode 지원(어댑터·create/resume·purge·화면 판독 픽스처)은 1.x(픽스처 기준 `OpenCode 1.18.32`)를 기준으로 만들어졌다. v2 에서 CLI 와 데이터 레이아웃이 바뀐 부분이 있어 호환성 확인과 수정이 필요하다.
아래 **확인된 사실**은 v2.0.32 의 `--help` 출력과 데이터 디렉터리를 읽기 전용으로 살펴본 결과다. 실제 세션 생성·재개·purge 는 아직 시험하지 않았다.
## 확인된 사실 (v2.0.32)
1. **`opencode db path` 서브커맨드가 없다.**
- 서브커맨드 목록에 `db` 가 없다. 호출하면 최상위 도움말을 출력하고 **exit 0** 으로 끝난다.
- DB 경로는 이제 `opencode debug paths` 의 `db` 줄로 나온다(`~/.local/share/opencode/opencode.db`).
- 영향: `adapters/opencode.py:62-115` `_resolve_db` 의 1단계가 도움말 텍스트를 경로로 받는다. 경로로 존재하지 않아서 지금은 파일시스템 폴백(`opencode.db`)으로 우연히 맞는다.
2. **`auth.json` 이 데이터 디렉터리에 없다.**
- `~/.local/share/opencode/auth.json` 이 없다. DB 에 `credential`·`account`·`control_account` 테이블이 생겼다.
- 영향:
- `adapters/opencode.py:205-210` `auth_ok` 는 이 파일이나 provider 환경변수만 본다.
- `create_session.sh:145-151` 도 같은 파일을 먼저 확인한다. 다만 거기서는 `opencode --version` 폴백으로 통과한다.
- 환경변수 없이 OAuth 로그인만 한 환경에서는 `auth_ok` 가 false 가 될 수 있다.
3. **최상위 실행의 플래그가 바뀌었다.**
- `opencode --help` 의 FLAGS 는 다음 6개뿐이다: `--standalone`, `--server`, `--auto`, `--continue/-c`, `--session/-s`, `--prompt`.
- **`--agent` 가 없다.** `run` 서브커맨드에는 `--agent` 가 있다.
- MAM 은 생성·재개 모두 `opencode --auto --agent build` / `opencode --session <id> --auto --agent build` 로 띄운다. 해당 위치:
- `adapters/opencode.py:197-203`
- `create_session.sh:216`
- `resume_session.sh:181,193`
- v2 TUI 가 `--agent` 를 거부하는지, 무시하는지, 숨은 플래그로 받는지는 아직 확인하지 않았다.
4. **`--session` 의 의미가 바뀌었다.** 도움말은 "Session ID to continue, **or to create if it does not exist**" 다. 없는 id 로 재개하면 오류 대신 새 세션이 생길 수 있다. resume 의 materialized 판정과 tier-1 id 신뢰 전제를 다시 봐야 한다.
5. **백그라운드 서비스 모델이 생겼다.**
- 기본 실행은 "background service" 에 붙는다(`--standalone` 은 개별 서버, `service` 서브커맨드는 서비스 관리).
- 확인할 것: TUI 프로세스가 아니라 공유 서비스가 세션을 쥐고 DB 에 쓰는지, 그 결과가 다음 MAM 판단에 어떤 영향을 주는지.
- pane 의 프로세스 판별(`pane.cmd`, agent 이름 해석)
- stop 의 `/exit`·kill 체인 뒤 서비스 잔존
- purge 가 서비스가 열어 둔 DB 행을 지울 때의 일관성
- heartbeat 의 프로세스 이름 기반 판정
6. **DB 스키마에 v2 테이블이 추가됐다.**
- 기존 `session`·`message`·`part` 옆에 다음 테이블이 생겼다: `session_v2`(fork·suspend·idle 컬럼 추가), `session_message`, `session_inbox`, `session_pending`, `event`, `event_sequence`, `todo`, `permission` 등.
- 이 Mac 의 DB 는 `session` 과 `session_v2` 의 행 수가 같다(마이그레이션된 것으로 보임). 그러나 v2 가 **새 세션을 어느 테이블에 쓰는지**는 아직 확인하지 않았다.
- 영향: 어댑터의 다음 기능은 `session` 테이블만 조회한다.
- `discover`(`:212-`)
- `verify_artifact`(`:117-`)
- 재조정기의 opencode drift C
- `purge_artifacts`(`:169-196`)는 `message`/`messages`/`part`/`parts`/`session`/`sessions` 만 지운다. 따라서 `session_v2`·`session_message` 등에 같은 세션의 데이터가 남을 수 있고, residual 보고에도 잡히지 않는다(#31 과 같은 계열).
## 확인 작업 (제안)
실제 홈을 건드리지 않도록, 가능한 한 `HOME`/`XDG_DATA_HOME` 를 임시 디렉터리로 두고 `--standalone` 으로 시험한다.
- [ ] v2 TUI 기동: `--auto --agent build` 가 받아들여지는지, `build` 에이전트 지정 방법이 바뀌었는지
- [ ] 새 세션이 기록되는 테이블과 컬럼(`session` vs `session_v2`, `directory`, `time_created` 단위)과, `discover`/`verify_artifact`/drift C 가 v2 세션을 찾는지
- [ ] `opencode --session <id>` 재개, 그리고 없는 id 일 때의 동작
- [ ] 백그라운드 서비스와 pane 프로세스의 관계: create 의 프로세스 판별, stop 뒤 잔존 프로세스, heartbeat 판정
- [ ] purge: v2 테이블까지 지우는지, `opencode session delete <id>` 로 위임하는 편이 나은지, residual 보고
- [ ] `_resolve_db`: `db path` 대신 `debug paths` 를 쓰거나 폴백만 쓰기, 그리고 exit 0 도움말 출력을 경로로 오인하지 않기
- [ ] 인증 판정: `auth.json` 대신 쓸 신호(`opencode auth` 계열 또는 `credential` 테이블)
- [ ] 화면 판독: `ready_tokens`·입력 프롬프트(`┃` 블록)·`input_stop_pattern`(`Build auto · <model>` 줄)이 v2 TUI 에서도 맞는지, `tests/fixtures/panes/opencode_idle.txt` 를 v2 화면으로 갱신
- [ ] 1.x 지원 유지 여부 결정(두 버전 분기 또는 v2 전용) 및 문서(`docs/NEW_AGENT_INTEGRATION_GUIDE.md` 의 `opencode db path`·`auth.json` 서술, README 의 `opencode --session`) 정정
## 참고
- 관련 코드: `.agents/skills/lib_py/agents/adapters/opencode.py`, `multi-agent-mux-create/scripts/create_session.sh`, `multi-agent-mux-resume/scripts/resume_session.sh`, `multi-agent-mux-monitor/scripts/reconcile.sh`(drift C), `multi-agent-mux-orc-onboard/scripts/orc_onboard.sh`
- 관련 테스트: `tests/test_a4_adapter_contract.py`, `tests/test_c1_tui_readiness.py`, `tests/test_issue10_13_purge.py` 등 opencode 를 다루는 테스트
이 이슈는 v4.9.4 기준으로 작성했습니다. 그 뒤 병합된 v4.9.5(PR #59, Issue #31)가 opencode 어댑터에 residual_artifacts 를 추가했고, 그래서 본문 일부가 현재 main 과 맞지 않습니다.
1. 확인된 사실 6번 — residual 보고 범위
본문에는 "session_v2·session_message 등에 같은 세션의 데이터가 남을 수 있고, residual 보고에도 잡히지 않는다" 라고 적었습니다. 이 중 residual 부분은 이제 일부만 맞습니다.
v4.9.5 부터 opencode purge 는 남은 행을 지우지 않고 보고합니다(adapters/opencode.py:197-202, base.db_rows_naming). 보고 대상은 session_id·aggregate_id 컬럼, 그리고 session.id 에 세션 id 가 있는 행입니다.
이 Mac 의 v2 DB 컬럼과 대조한 결과:
보고됨(삭제는 안 됨): session_message, session_inbox, session_pending, session_share, todo, event(aggregate_id)
삭제도 보고도 안 됨: session_v2 의 세션 행. id 컬럼만 있고 id_tables 에는 session 만 들어 있기 때문입니다.
purge 가 지우는 범위(message·part·session 등)는 그대로입니다.
2. 줄 번호 (adapters/opencode.py, residual_artifacts 추가로 7줄 밀림)
함수
본문
현재
spawn_spec·resume_spec
:197-203
:204-210
auth_ok
:205-210
:212-217
discover
:212-
:219-
_resolve_db(:62-115), verify_artifact(:117-), purge_artifacts(:169-196), create_session.sh:145-151,216, resume_session.sh:181,193 는 그대로입니다.
검증 계획
macOS(이 호스트)에서 먼저 호환성을 확인하고 수정한 뒤, Linux 환경에서 다시 호환성 테스트를 진행합니다. 그래서 수정과 테스트는 두 OS 모두를 전제로 합니다.
경로: 하드코딩 대신 opencode debug paths(data·db·state·tmp) 또는 XDG 규칙(XDG_DATA_HOME 등)을 따릅니다. macOS 의 tmp 는 /var/folders/.../T/opencode, Linux 는 다를 수 있습니다.
백그라운드 서비스: 서비스 등록 방식이 OS 마다 다를 수 있습니다(macOS launchd, Linux systemd 사용자 유닛 등). 서비스 잔존·프로세스 판별 검증은 두 OS 에서 각각 확인합니다.
프로세스 판별: ps 옵션 차이(BSD/procps)와 /proc 유무를 감안해 어느 한 OS 에만 기대지 않습니다.
테스트: 실제 홈을 건드리지 않도록 임시 HOME/XDG_* 와 --standalone 을 씁니다. 실제 opencode 바이너리가 필요한 시험은 없는 환경에서는 skip 되게 하고, 화면 판독 픽스처는 v2 화면으로 추가합니다.
## 정정 (v4.9.5 기준)
이 이슈는 v4.9.4 기준으로 작성했습니다. 그 뒤 병합된 v4.9.5(PR #59, Issue #31)가 opencode 어댑터에 `residual_artifacts` 를 추가했고, 그래서 본문 일부가 현재 `main` 과 맞지 않습니다.
**1. 확인된 사실 6번 — residual 보고 범위**
본문에는 "`session_v2`·`session_message` 등에 같은 세션의 데이터가 남을 수 있고, residual 보고에도 잡히지 않는다" 라고 적었습니다. 이 중 residual 부분은 이제 일부만 맞습니다.
- v4.9.5 부터 opencode purge 는 남은 행을 지우지 않고 보고합니다(`adapters/opencode.py:197-202`, `base.db_rows_naming`). 보고 대상은 `session_id`·`aggregate_id` 컬럼, 그리고 `session.id` 에 세션 id 가 있는 행입니다.
- 이 Mac 의 v2 DB 컬럼과 대조한 결과:
- **보고됨(삭제는 안 됨)**: `session_message`, `session_inbox`, `session_pending`, `session_share`, `todo`, `event`(`aggregate_id`)
- **삭제도 보고도 안 됨**: `session_v2` 의 세션 행. id 컬럼만 있고 `id_tables` 에는 `session` 만 들어 있기 때문입니다.
- purge 가 지우는 범위(`message`·`part`·`session` 등)는 그대로입니다.
**2. 줄 번호** (`adapters/opencode.py`, `residual_artifacts` 추가로 7줄 밀림)
| 함수 | 본문 | 현재 |
| --- | --- | --- |
| `spawn_spec`·`resume_spec` | `:197-203` | `:204-210` |
| `auth_ok` | `:205-210` | `:212-217` |
| `discover` | `:212-` | `:219-` |
`_resolve_db`(`:62-115`), `verify_artifact`(`:117-`), `purge_artifacts`(`:169-196`), `create_session.sh:145-151,216`, `resume_session.sh:181,193` 는 그대로입니다.
## 검증 계획
macOS(이 호스트)에서 먼저 호환성을 확인하고 수정한 뒤, Linux 환경에서 다시 호환성 테스트를 진행합니다. 그래서 수정과 테스트는 두 OS 모두를 전제로 합니다.
- **경로**: 하드코딩 대신 `opencode debug paths`(`data`·`db`·`state`·`tmp`) 또는 XDG 규칙(`XDG_DATA_HOME` 등)을 따릅니다. macOS 의 `tmp` 는 `/var/folders/.../T/opencode`, Linux 는 다를 수 있습니다.
- **백그라운드 서비스**: 서비스 등록 방식이 OS 마다 다를 수 있습니다(macOS launchd, Linux systemd 사용자 유닛 등). 서비스 잔존·프로세스 판별 검증은 두 OS 에서 각각 확인합니다.
- **프로세스 판별**: `ps` 옵션 차이(BSD/procps)와 `/proc` 유무를 감안해 어느 한 OS 에만 기대지 않습니다.
- **테스트**: 실제 홈을 건드리지 않도록 임시 `HOME`/`XDG_*` 와 `--standalone` 을 씁니다. 실제 opencode 바이너리가 필요한 시험은 없는 환경에서는 skip 되게 하고, 화면 판독 픽스처는 v2 화면으로 추가합니다.
전체 스위트 (특히 tests/test_issue60_opencode_v2.py, XDG_DATA_HOME 이 설정된 환경 포함)
설치된 opencode 2.x 로 실제 바이너리 계약 테스트 (test_real_opencode_2x_contract, 2.x 가 설치돼 있으면 임시 HOME 에서 자동 실행)
실제 2.x 화면 캡처로 입력 영역 fixture (opencode_idle.txt) 갱신
stop 의 /exit 정상 종료 (입력과 Enter 사이 간격 필요)
홈 화면 안내 문구가 입력된 글자로 읽히는지 (stall_watch)
auth_ok (auth.json, 현재 쓰이지 않음) 를 2.x 기준으로 바꿀지
Linux 확인이 끝날 때까지 이 이슈는 열어 둡니다.
## macOS 확인 결과 (PR #61, v4.9.6 으로 병합)
MAM 은 이제 opencode **2.x 만** 지원합니다. macOS 에서 opencode 2.0.32 를 임시 HOME 으로 실측한 사실을 바탕으로 고쳤습니다.
- 실행: `opencode --auto --standalone` (재개는 `--session <id>` 추가). 2.x TUI 는 `--agent`·`-m` 을 받지 않습니다.
- 세션: `session_v2` 기준 (자식 세션 제외). DB 경로는 `opencode debug paths`.
- purge: `opencode session delete` + 1.x 에서 이전된 DB 의 옛 행 정리. 실패 시 경고와 residual 보고.
- 사용 중 판정: 백그라운드 서비스(`serve --service`)가 DB 를 잡고 있는 것만으로는 사용 중으로 보지 않습니다.
- 검증: 리뷰 3회차 4/4 PASS, macOS 전체 스위트 1949 passed / 56 skipped.
## Linux 에서 확인할 항목
- [ ] 전체 스위트 (특히 `tests/test_issue60_opencode_v2.py`, `XDG_DATA_HOME` 이 설정된 환경 포함)
- [ ] 설치된 opencode 2.x 로 실제 바이너리 계약 테스트 (`test_real_opencode_2x_contract`, 2.x 가 설치돼 있으면 임시 HOME 에서 자동 실행)
- [ ] 실제 2.x 화면 캡처로 입력 영역 fixture (`opencode_idle.txt`) 갱신
- [ ] stop 의 `/exit` 정상 종료 (입력과 Enter 사이 간격 필요)
- [ ] 홈 화면 안내 문구가 입력된 글자로 읽히는지 (stall_watch)
- [ ] `auth_ok` (`auth.json`, 현재 쓰이지 않음) 를 2.x 기준으로 바꿀지
Linux 확인이 끝날 때까지 이 이슈는 열어 둡니다.
아래 내용을 Linux 쪽 에이전트에 그대로 전달해 확인을 진행합니다. 결과는 이 이슈에 댓글로 남깁니다.
# 작업: Issue #60 Linux 호환성 확인 (opencode 2.x, MAM v4.9.6)
macOS 확인은 끝났고 PR #61(v4.9.6)로 main 에 병합됐다. 이제 이 Linux 환경에서 같은 동작을 확인한다.
**확인과 보고만 한다.** 코드 수정, 커밋, push, PR, 이슈 상태 변경은 하지 않는다. 고칠 것이 있으면 보고서에 적는다.
## 안전 규칙 (반드시 지킬 것)
- 실제 opencode 데이터와 서비스를 건드리지 않는다.
- 대상: `~/.local/share/opencode`, `~/.local/state/opencode`, `~/.config/opencode`, `$XDG_DATA_HOME/opencode`, 실행 중인 `opencode serve --service`- 실제 경로는 `ls`, `stat`, 읽기 전용 sqlite(`file:...?mode=ro`)로만 본다.
- 금지 명령:
-`opencode service stop/start/restart/set`- 실제 DB 에 대한 `opencode session delete`·`opencode api`- 모델을 호출하는 프롬프트 전송(외부 네트워크 사용 금지)
- opencode 를 직접 실행할 때는 임시 HOME·TMPDIR, `XDG_*` 해제, `--standalone`(또는 `debug paths` 처럼 서버가 필요 없는 명령)으로만 실행한다. 띄운 프로세스는 직접 정리한다.
- 실제 herdr 서버와 이미 돌고 있는 에이전트 세션은 건드리지 않는다. 직접 띄우는 세션은 격리된 herdr 서버(`--herdr-session issue60-linux` 등)에서만 만든다.
-`.mam.env` 를 export 하지 않는다. 비밀값(MQTT_PASSWORD, 토큰)은 출력하지 않는다.
-`--purge-conversation` 은 실행하지 않는다.
## 0. 준비와 사전 기록
```bash
git fetch origin && git checkout main && git pull --ff-only
grep -n MAM_VERSION .agents/skills/lib.sh # 4.9.6
opencode --version # 2.x 여야 함
uname -a; python3 --version
```- 작업 전 실제 opencode 폴더의 상태를 기록해 둔다. 끝난 뒤 이것과 비교한다.
-`ls -la` 목록과 `opencode.db`·`log/` 파일의 mtime
- 읽기 전용으로 센 `session_v2` 행 수
-`pgrep -af opencode` 출력
## 1. 전체 스위트
- 스위트를 저장소 밖 임시 basetemp 로 돌린다.
-`PYTHONDONTWRITEBYTECODE=1 python -m pytest -p no:cacheprovider -q -rs --basetemp=<저장소 밖 임시 경로> tests`- HERDR_*, WORKSPACE_ROOT, MAM_ENV_FILE, MAM_JOBS_DIR, DELEGATE_JOB_LOGS_DIR, CLAUDE_CONFIG_DIR 는 해제한다.
-`XDG_DATA_HOME` 을 별도 임시 폴더로 설정하고 한 번 더 돌린다.
- 대상: `tests/test_issue60_opencode_v2.py`, `tests/test_a4_adapter_contract.py`, `tests/test_issue31_purge_residual.py`, `tests/test_issue55_agent_homes.py`, `tests/test_tier2_component.py`- 그 임시 폴더에 아무것도 생기지 않아야 한다.
- 실패와 건너뜀은 모두 사유와 함께 적는다. 특히 macOS 에서 건너뛰었던 Linux 전용 테스트를 따로 표시한다.
## 2. 실제 바이너리 계약 테스트
-`test_real_opencode_2x_contract` 는 PATH 에 opencode 2.x 가 있으면 자동으로 실행된다(임시 HOME, `--standalone`, 모델 호출 없음).
-`pytest -q -rs tests/test_issue60_opencode_v2.py -k real` 로 실행해 통과 여부를 확인한다.
- skip 됐다면 그 이유를 적는다.
- 직접 실측해서 macOS 와 같은지 확인한다(임시 HOME 에서).
-`opencode debug paths` 의 `db` 줄이 HOME·XDG_DATA_HOME 을 따르는지
-`opencode session delete --standalone -- <없는 id>` 가 "Session not found" + exit 1 인지
- TUI 가 `--agent`·`-m` 을 거부하는지
-`--standalone` 의 자식 `serve --stdio` 가 TUI 종료와 함께 끝나는지
## 3. 실제 세션 확인 (격리된 herdr 서버)
- 이 저장소의 `multi-agent-mux-create` 로 opencode 세션 하나를 격리된 herdr 서버에 만든다.
- 실행 명령이 `opencode --auto --standalone` 인지 확인한다.
- 메시지는 보내지 않는다(보내면 세션 행과 모델 호출이 생긴다).
- 화면에 "Getting started"(provider 없음) 패널이 뜨면 거기서 멈추고 보고한다. 실제 HOME 의 설정을 쓸지는 사용자가 정한다.
- 확인할 것:
1.**화면:**`herdr --session <격리 서버> agent read <세션> --source visible` 로 캡처해 `tests/fixtures/panes/opencode_idle.txt` 와 비교한다(입력 블록 `┃`, "Build auto · <model>", "ctrl+p commands" 등). 다르면 캡처 원문을 보고서에 붙인다(경로·사용자명은 가린다).
2.**입력 영역 판정:** 캡처 파일로 실행한다. 빈 입력 상태에서 결과가 빈 문자열이어야 한다. 홈 화면 안내 문구(`Ask anything… "Fix a TODO in the codebase"`)가 입력된 글자로 읽히면 그대로 적는다.
```bash
PYTHONPATH=.agents/skills python3 -c "from lib_py.agents.input_region import extract_input_region as f; print(repr(f(open('<캡처>').read(),'opencode')))"
```
3. **정상 종료:** `multi-agent-mux-stop` 의 기본(graceful) stop 으로 끝낸다.
- `/exit` 로 끝났는지, kill-session·SIGKILL 단계로 넘어갔는지 stop 출력으로 확인한다.
- 뒤에 남은 `opencode`·`serve --stdio` 프로세스가 없는지 확인한다.
4. **status / reconcile:** 세션이 살아 있는 동안 `multi-agent-mux-status` 결과가 이상 없는지 본다(오류, drift 오탐).
- 끝나면 격리 herdr 서버와 세션을 정리한다.
## 4. auth_ok 검토 (읽기만)
- 어댑터의 `auth_ok` 는 여전히 `auth.json` 을 본다(현재 실제 동작에는 쓰이지 않음).
- 2.x 에서 인증 정보가 어디에 어떤 형식으로 있는지 파일 이름과 키 이름만 확인한다. 값은 출력하지 않는다.
- 바꿔야 할지 의견을 적는다.
## 5. 사후 확인
- 0번 기록과 비교한다.
- 실제 opencode 폴더 목록과 mtime, `session_v2` 행 수
- opencode 프로세스(사용자 서비스 외에 남은 것이 없어야 함)
- 실제 herdr 서버의 pane 목록
- `git status`(저장소가 깨끗해야 함)
## 보고 형식
- 환경: OS·배포판, Python, opencode 버전, herdr 버전
- 1~5 항목마다 결과(PASS / FAIL / SKIP)와 근거(명령, 출력 요약)
- FAIL 마다 원인 추정과 수정 제안(파일:줄). 기존 Linux 전용 실패와 같은 원인인지 구분한다.
- 실제 환경 변화 여부(5번 결과)
- 마지막 줄에 단독으로 `[VERDICT: PASS]` 또는 `[VERDICT: NOT PASS]`
- 보고서와 캡처에는 절대 경로, 사용자명, 토큰, 다른 워크스페이스 이름을 넣지 않는다.
## Linux 확인용 에이전트 프롬프트
아래 내용을 Linux 쪽 에이전트에 그대로 전달해 확인을 진행합니다. 결과는 이 이슈에 댓글로 남깁니다.
````markdown
# 작업: Issue #60 Linux 호환성 확인 (opencode 2.x, MAM v4.9.6)
macOS 확인은 끝났고 PR #61(v4.9.6)로 main 에 병합됐다. 이제 이 Linux 환경에서 같은 동작을 확인한다.
**확인과 보고만 한다.** 코드 수정, 커밋, push, PR, 이슈 상태 변경은 하지 않는다. 고칠 것이 있으면 보고서에 적는다.
## 안전 규칙 (반드시 지킬 것)
- 실제 opencode 데이터와 서비스를 건드리지 않는다.
- 대상: `~/.local/share/opencode`, `~/.local/state/opencode`, `~/.config/opencode`, `$XDG_DATA_HOME/opencode`, 실행 중인 `opencode serve --service`
- 실제 경로는 `ls`, `stat`, 읽기 전용 sqlite(`file:...?mode=ro`)로만 본다.
- 금지 명령:
- `opencode service stop/start/restart/set`
- 실제 DB 에 대한 `opencode session delete`·`opencode api`
- 모델을 호출하는 프롬프트 전송(외부 네트워크 사용 금지)
- opencode 를 직접 실행할 때는 임시 HOME·TMPDIR, `XDG_*` 해제, `--standalone`(또는 `debug paths` 처럼 서버가 필요 없는 명령)으로만 실행한다. 띄운 프로세스는 직접 정리한다.
- 실제 herdr 서버와 이미 돌고 있는 에이전트 세션은 건드리지 않는다. 직접 띄우는 세션은 격리된 herdr 서버(`--herdr-session issue60-linux` 등)에서만 만든다.
- `.mam.env` 를 export 하지 않는다. 비밀값(MQTT_PASSWORD, 토큰)은 출력하지 않는다.
- `--purge-conversation` 은 실행하지 않는다.
## 0. 준비와 사전 기록
```bash
git fetch origin && git checkout main && git pull --ff-only
grep -n MAM_VERSION .agents/skills/lib.sh # 4.9.6
opencode --version # 2.x 여야 함
uname -a; python3 --version
```
- 작업 전 실제 opencode 폴더의 상태를 기록해 둔다. 끝난 뒤 이것과 비교한다.
- `ls -la` 목록과 `opencode.db`·`log/` 파일의 mtime
- 읽기 전용으로 센 `session_v2` 행 수
- `pgrep -af opencode` 출력
## 1. 전체 스위트
- 스위트를 저장소 밖 임시 basetemp 로 돌린다.
- `PYTHONDONTWRITEBYTECODE=1 python -m pytest -p no:cacheprovider -q -rs --basetemp=<저장소 밖 임시 경로> tests`
- HERDR_*, WORKSPACE_ROOT, MAM_ENV_FILE, MAM_JOBS_DIR, DELEGATE_JOB_LOGS_DIR, CLAUDE_CONFIG_DIR 는 해제한다.
- `XDG_DATA_HOME` 을 별도 임시 폴더로 설정하고 한 번 더 돌린다.
- 대상: `tests/test_issue60_opencode_v2.py`, `tests/test_a4_adapter_contract.py`, `tests/test_issue31_purge_residual.py`, `tests/test_issue55_agent_homes.py`, `tests/test_tier2_component.py`
- 그 임시 폴더에 아무것도 생기지 않아야 한다.
- 실패와 건너뜀은 모두 사유와 함께 적는다. 특히 macOS 에서 건너뛰었던 Linux 전용 테스트를 따로 표시한다.
## 2. 실제 바이너리 계약 테스트
- `test_real_opencode_2x_contract` 는 PATH 에 opencode 2.x 가 있으면 자동으로 실행된다(임시 HOME, `--standalone`, 모델 호출 없음).
- `pytest -q -rs tests/test_issue60_opencode_v2.py -k real` 로 실행해 통과 여부를 확인한다.
- skip 됐다면 그 이유를 적는다.
- 직접 실측해서 macOS 와 같은지 확인한다(임시 HOME 에서).
- `opencode debug paths` 의 `db` 줄이 HOME·XDG_DATA_HOME 을 따르는지
- `opencode session delete --standalone -- <없는 id>` 가 "Session not found" + exit 1 인지
- TUI 가 `--agent`·`-m` 을 거부하는지
- `--standalone` 의 자식 `serve --stdio` 가 TUI 종료와 함께 끝나는지
## 3. 실제 세션 확인 (격리된 herdr 서버)
- 이 저장소의 `multi-agent-mux-create` 로 opencode 세션 하나를 격리된 herdr 서버에 만든다.
- 실행 명령이 `opencode --auto --standalone` 인지 확인한다.
- 메시지는 보내지 않는다(보내면 세션 행과 모델 호출이 생긴다).
- 화면에 "Getting started"(provider 없음) 패널이 뜨면 거기서 멈추고 보고한다. 실제 HOME 의 설정을 쓸지는 사용자가 정한다.
- 확인할 것:
1. **화면:** `herdr --session <격리 서버> agent read <세션> --source visible` 로 캡처해 `tests/fixtures/panes/opencode_idle.txt` 와 비교한다(입력 블록 `┃`, "Build auto · <model>", "ctrl+p commands" 등). 다르면 캡처 원문을 보고서에 붙인다(경로·사용자명은 가린다).
2. **입력 영역 판정:** 캡처 파일로 실행한다. 빈 입력 상태에서 결과가 빈 문자열이어야 한다. 홈 화면 안내 문구(`Ask anything… "Fix a TODO in the codebase"`)가 입력된 글자로 읽히면 그대로 적는다.
```bash
PYTHONPATH=.agents/skills python3 -c "from lib_py.agents.input_region import extract_input_region as f; print(repr(f(open('<캡처>').read(),'opencode')))"
```
3. **정상 종료:** `multi-agent-mux-stop` 의 기본(graceful) stop 으로 끝낸다.
- `/exit` 로 끝났는지, kill-session·SIGKILL 단계로 넘어갔는지 stop 출력으로 확인한다.
- 뒤에 남은 `opencode`·`serve --stdio` 프로세스가 없는지 확인한다.
4. **status / reconcile:** 세션이 살아 있는 동안 `multi-agent-mux-status` 결과가 이상 없는지 본다(오류, drift 오탐).
- 끝나면 격리 herdr 서버와 세션을 정리한다.
## 4. auth_ok 검토 (읽기만)
- 어댑터의 `auth_ok` 는 여전히 `auth.json` 을 본다(현재 실제 동작에는 쓰이지 않음).
- 2.x 에서 인증 정보가 어디에 어떤 형식으로 있는지 파일 이름과 키 이름만 확인한다. 값은 출력하지 않는다.
- 바꿔야 할지 의견을 적는다.
## 5. 사후 확인
- 0번 기록과 비교한다.
- 실제 opencode 폴더 목록과 mtime, `session_v2` 행 수
- opencode 프로세스(사용자 서비스 외에 남은 것이 없어야 함)
- 실제 herdr 서버의 pane 목록
- `git status`(저장소가 깨끗해야 함)
## 보고 형식
- 환경: OS·배포판, Python, opencode 버전, herdr 버전
- 1~5 항목마다 결과(PASS / FAIL / SKIP)와 근거(명령, 출력 요약)
- FAIL 마다 원인 추정과 수정 제안(파일:줄). 기존 Linux 전용 실패와 같은 원인인지 구분한다.
- 실제 환경 변화 여부(5번 결과)
- 마지막 줄에 단독으로 `[VERDICT: PASS]` 또는 `[VERDICT: NOT PASS]`
- 보고서와 캡처에는 절대 경로, 사용자명, 토큰, 다른 워크스페이스 이름을 넣지 않는다.
````
Linux 확인에서 나온 수정(PR #62)을 macOS 에서 다시 검토하고 병합했습니다.
macOS 리뷰 1회차에서 추가로 고친 것:
새 테스트의 clean 상태: macOS SQLite 는 닫은 뒤에도 -wal·-shm 을 남기므로, 테스트에서 지워 Linux 와 같은 상태로 맞춤
안내 문구 패턴은 따옴표로 시작하는 예시가 있어야 함 (사용자가 친 Ask anything… 는 입력으로 읽음)
auth_ok 는 실행 가능한 ~/.opencode/bin/opencode 만 인정
status.sh·reconcile.sh 도 opencode DB 를 읽기 전용으로 엶
검증: 리뷰 2회차 4/4 PASS, macOS 전체 스위트 2001 passed / 56 skipped / 실패 0. Linux 결과는 PR #62 본문에 있습니다.
남은 비차단: immutable 읽기의 짧은 경쟁 창, debug paths 캐시의 프로세스 수명, 2.x 대화 화면 안내 문구 미캡처, agy(#28)·codex·hermes 의 쓰기 가능 DB 열기.
Linux·macOS 확인이 모두 끝나 이 이슈를 닫습니다.
## 마무리 (PR #62, v4.9.7 로 병합)
Linux 확인에서 나온 수정(PR #62)을 macOS 에서 다시 검토하고 병합했습니다.
- macOS 리뷰 1회차에서 추가로 고친 것:
- 새 테스트의 `clean` 상태: macOS SQLite 는 닫은 뒤에도 `-wal`·`-shm` 을 남기므로, 테스트에서 지워 Linux 와 같은 상태로 맞춤
- 안내 문구 패턴은 따옴표로 시작하는 예시가 있어야 함 (사용자가 친 `Ask anything…` 는 입력으로 읽음)
- `auth_ok` 는 실행 가능한 `~/.opencode/bin/opencode` 만 인정
- `status.sh`·`reconcile.sh` 도 opencode DB 를 읽기 전용으로 엶
- 검증: 리뷰 2회차 4/4 PASS, macOS 전체 스위트 2001 passed / 56 skipped / 실패 0. Linux 결과는 PR #62 본문에 있습니다.
- 남은 비차단: immutable 읽기의 짧은 경쟁 창, `debug paths` 캐시의 프로세스 수명, 2.x 대화 화면 안내 문구 미캡처, agy(#28)·codex·hermes 의 쓰기 가능 DB 열기.
Linux·macOS 확인이 모두 끝나 이 이슈를 닫습니다.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
배경
이 Mac 의 opencode 가 1.x 에서 v2.0.32 로 올라갔다. MAM 의 opencode 지원(어댑터·create/resume·purge·화면 판독 픽스처)은 1.x(픽스처 기준
OpenCode 1.18.32)를 기준으로 만들어졌다. v2 에서 CLI 와 데이터 레이아웃이 바뀐 부분이 있어 호환성 확인과 수정이 필요하다.아래 확인된 사실은 v2.0.32 의
--help출력과 데이터 디렉터리를 읽기 전용으로 살펴본 결과다. 실제 세션 생성·재개·purge 는 아직 시험하지 않았다.확인된 사실 (v2.0.32)
opencode db path서브커맨드가 없다.db가 없다. 호출하면 최상위 도움말을 출력하고 exit 0 으로 끝난다.opencode debug paths의db줄로 나온다(~/.local/share/opencode/opencode.db).adapters/opencode.py:62-115_resolve_db의 1단계가 도움말 텍스트를 경로로 받는다. 경로로 존재하지 않아서 지금은 파일시스템 폴백(opencode.db)으로 우연히 맞는다.auth.json이 데이터 디렉터리에 없다.~/.local/share/opencode/auth.json이 없다. DB 에credential·account·control_account테이블이 생겼다.adapters/opencode.py:205-210auth_ok는 이 파일이나 provider 환경변수만 본다.create_session.sh:145-151도 같은 파일을 먼저 확인한다. 다만 거기서는opencode --version폴백으로 통과한다.auth_ok가 false 가 될 수 있다.opencode --help의 FLAGS 는 다음 6개뿐이다:--standalone,--server,--auto,--continue/-c,--session/-s,--prompt.--agent가 없다.run서브커맨드에는--agent가 있다.opencode --auto --agent build/opencode --session <id> --auto --agent build로 띄운다. 해당 위치:adapters/opencode.py:197-203create_session.sh:216resume_session.sh:181,193--agent를 거부하는지, 무시하는지, 숨은 플래그로 받는지는 아직 확인하지 않았다.--session의 의미가 바뀌었다. 도움말은 "Session ID to continue, or to create if it does not exist" 다. 없는 id 로 재개하면 오류 대신 새 세션이 생길 수 있다. resume 의 materialized 판정과 tier-1 id 신뢰 전제를 다시 봐야 한다.--standalone은 개별 서버,service서브커맨드는 서비스 관리).pane.cmd, agent 이름 해석)/exit·kill 체인 뒤 서비스 잔존session·message·part옆에 다음 테이블이 생겼다:session_v2(fork·suspend·idle 컬럼 추가),session_message,session_inbox,session_pending,event,event_sequence,todo,permission등.session과session_v2의 행 수가 같다(마이그레이션된 것으로 보임). 그러나 v2 가 새 세션을 어느 테이블에 쓰는지는 아직 확인하지 않았다.session테이블만 조회한다.discover(:212-)verify_artifact(:117-)purge_artifacts(:169-196)는message/messages/part/parts/session/sessions만 지운다. 따라서session_v2·session_message등에 같은 세션의 데이터가 남을 수 있고, residual 보고에도 잡히지 않는다(#31 과 같은 계열).확인 작업 (제안)
실제 홈을 건드리지 않도록, 가능한 한
HOME/XDG_DATA_HOME를 임시 디렉터리로 두고--standalone으로 시험한다.--auto --agent build가 받아들여지는지,build에이전트 지정 방법이 바뀌었는지sessionvssession_v2,directory,time_created단위)과,discover/verify_artifact/drift C 가 v2 세션을 찾는지opencode --session <id>재개, 그리고 없는 id 일 때의 동작opencode session delete <id>로 위임하는 편이 나은지, residual 보고_resolve_db:db path대신debug paths를 쓰거나 폴백만 쓰기, 그리고 exit 0 도움말 출력을 경로로 오인하지 않기auth.json대신 쓸 신호(opencode auth계열 또는credential테이블)ready_tokens·입력 프롬프트(┃블록)·input_stop_pattern(Build auto · <model>줄)이 v2 TUI 에서도 맞는지,tests/fixtures/panes/opencode_idle.txt를 v2 화면으로 갱신docs/NEW_AGENT_INTEGRATION_GUIDE.md의opencode db path·auth.json서술, README 의opencode --session) 정정참고
.agents/skills/lib_py/agents/adapters/opencode.py,multi-agent-mux-create/scripts/create_session.sh,multi-agent-mux-resume/scripts/resume_session.sh,multi-agent-mux-monitor/scripts/reconcile.sh(drift C),multi-agent-mux-orc-onboard/scripts/orc_onboard.shtests/test_a4_adapter_contract.py,tests/test_c1_tui_readiness.py,tests/test_issue10_13_purge.py등 opencode 를 다루는 테스트정정 (v4.9.5 기준)
이 이슈는 v4.9.4 기준으로 작성했습니다. 그 뒤 병합된 v4.9.5(PR #59, Issue #31)가 opencode 어댑터에
residual_artifacts를 추가했고, 그래서 본문 일부가 현재main과 맞지 않습니다.1. 확인된 사실 6번 — residual 보고 범위
본문에는 "
session_v2·session_message등에 같은 세션의 데이터가 남을 수 있고, residual 보고에도 잡히지 않는다" 라고 적었습니다. 이 중 residual 부분은 이제 일부만 맞습니다.adapters/opencode.py:197-202,base.db_rows_naming). 보고 대상은session_id·aggregate_id컬럼, 그리고session.id에 세션 id 가 있는 행입니다.session_message,session_inbox,session_pending,session_share,todo,event(aggregate_id)session_v2의 세션 행. id 컬럼만 있고id_tables에는session만 들어 있기 때문입니다.message·part·session등)는 그대로입니다.2. 줄 번호 (
adapters/opencode.py,residual_artifacts추가로 7줄 밀림)spawn_spec·resume_spec:197-203:204-210auth_ok:205-210:212-217discover:212-:219-_resolve_db(:62-115),verify_artifact(:117-),purge_artifacts(:169-196),create_session.sh:145-151,216,resume_session.sh:181,193는 그대로입니다.검증 계획
macOS(이 호스트)에서 먼저 호환성을 확인하고 수정한 뒤, Linux 환경에서 다시 호환성 테스트를 진행합니다. 그래서 수정과 테스트는 두 OS 모두를 전제로 합니다.
opencode debug paths(data·db·state·tmp) 또는 XDG 규칙(XDG_DATA_HOME등)을 따릅니다. macOS 의tmp는/var/folders/.../T/opencode, Linux 는 다를 수 있습니다.ps옵션 차이(BSD/procps)와/proc유무를 감안해 어느 한 OS 에만 기대지 않습니다.HOME/XDG_*와--standalone을 씁니다. 실제 opencode 바이너리가 필요한 시험은 없는 환경에서는 skip 되게 하고, 화면 판독 픽스처는 v2 화면으로 추가합니다.macOS 확인 결과 (PR #61, v4.9.6 으로 병합)
MAM 은 이제 opencode 2.x 만 지원합니다. macOS 에서 opencode 2.0.32 를 임시 HOME 으로 실측한 사실을 바탕으로 고쳤습니다.
opencode --auto --standalone(재개는--session <id>추가). 2.x TUI 는--agent·-m을 받지 않습니다.session_v2기준 (자식 세션 제외). DB 경로는opencode debug paths.opencode session delete+ 1.x 에서 이전된 DB 의 옛 행 정리. 실패 시 경고와 residual 보고.serve --service)가 DB 를 잡고 있는 것만으로는 사용 중으로 보지 않습니다.Linux 에서 확인할 항목
tests/test_issue60_opencode_v2.py,XDG_DATA_HOME이 설정된 환경 포함)test_real_opencode_2x_contract, 2.x 가 설치돼 있으면 임시 HOME 에서 자동 실행)opencode_idle.txt) 갱신/exit정상 종료 (입력과 Enter 사이 간격 필요)auth_ok(auth.json, 현재 쓰이지 않음) 를 2.x 기준으로 바꿀지Linux 확인이 끝날 때까지 이 이슈는 열어 둡니다.
Linux 확인용 에이전트 프롬프트
아래 내용을 Linux 쪽 에이전트에 그대로 전달해 확인을 진행합니다. 결과는 이 이슈에 댓글로 남깁니다.
마무리 (PR #62, v4.9.7 로 병합)
Linux 확인에서 나온 수정(PR #62)을 macOS 에서 다시 검토하고 병합했습니다.
clean상태: macOS SQLite 는 닫은 뒤에도-wal·-shm을 남기므로, 테스트에서 지워 Linux 와 같은 상태로 맞춤Ask anything…는 입력으로 읽음)auth_ok는 실행 가능한~/.opencode/bin/opencode만 인정status.sh·reconcile.sh도 opencode DB 를 읽기 전용으로 엶debug paths캐시의 프로세스 수명, 2.x 대화 화면 안내 문구 미캡처, agy(#28)·codex·hermes 의 쓰기 가능 DB 열기.Linux·macOS 확인이 모두 끝나 이 이슈를 닫습니다.