Files
GodopuandClaude Opus 5 387479732e release(v4.4.0): bump framework and eight skills to 4.4.0 in lockstep
Issue #5 (Python core migration, CAS state transitions, shadow watcher,
auto-completion gate, eager-import immutable runtime, B-13 freeze removal)
is complete and merged to main. This stamps the release.

SemVer: MINOR, not MAJOR. The change is large but breaks nothing. Across the
whole Issue #5 range there are zero file deletions and zero renames, the event
wire schema stays at SCHEMA_VERSION 1, all four literal script paths survive as
compatibility shims, the 968-line legacy shell loop is still in run_loop.sh,
and every default change reverts through a single environment variable
(MAM_DELEGATION_PY / MAM_ENGINE_CAS / MAM_LOOP_PY / MAM_LOOP_FREEZE). The
riskiest new feature, auto-completion, ships default-off. No operator has
anything to migrate, which is the decisive reason not to call it 5.0.0. The
reasoning is recorded in the VERSIONS.md release notes, not just here.

Close a gap in the lockstep guard. lib.sh exports MAM_VERSION and eager_load()
refuses to start the loop when it disagrees with FRAMEWORK_VERSION, so eager.py
is a load-bearing fourth leg — but test_version_consistency.py only checked
three, and the sole check on eager.py was a hardcoded literal in the phase 4
test that a release bump has to edit anyway. The lockstep test now covers
eager.py, a new test pins the fail-closed gate itself, and the phase 4 test no
longer carries a version literal.

Fix a latent test-isolation defect the bump exposed. The first full run failed
four tests with "MAM_VERSION mismatch: expected 4.4.0, got 4.3.0 in
environment" — 4.3.0 was not in the tree, it was inherited from the shell that
launched pytest and had sourced the pre-bump lib.sh. Those tests were measuring
the runner's shell rather than the tree under test, and only passed until now
because the two values always happened to agree. A session-scoped fixture drops
the ambient value. Production is unaffected: run_loop.sh:17 sources lib.sh
before anything else and lib.sh re-exports MAM_VERSION unconditionally, so a
stale inherited value is always overwritten before Python starts.

Full suite: 750 passed in 912.50s, 0 failed, 0 skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UrDNJkHmm18uu7n7JwV5Qd
2026-09-07 15:55:26 +09:00

4.0 KiB

📑 Issue #5 Phase 4 — 불변 런타임 검증 및 Freeze 제거 명세

  • 문서 버전: Rev.1
  • 상태: Phase 4 설계 및 실행 기준선 (Immutable Runtime & Freeze Removal Specification)
  • 대상 파일:
    • lib_py/loop/runner.py, lib_py/loop/eager.py
    • .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh
    • docs/contracts/issue-5/task.md
    • tests/test_issue5_phase4_runtime.py

1. 개요 및 한 문장 요약

Python 상주 프로세스의 메모리 불변성(Eager Import)을 통해 작업 중 코드 수정 크래시(B-13)를 원천 차단하고, 임시 비계였던 /tmp/mam-loop-freeze.XXXXXX 스냅샷 복사 우회책을 안전하게 제거한다.

Phase 3에서 run_loop.sh가 Python lib_py.loop로 위임됨에 따라, Bash가 실행 중 스크립트를 디스크 바이트 오프셋 단위로 재독해하면서 발생하던 크래시(B-13: unexpected EOF / 구문 파괴)의 원인이 근본적으로 해소되었습니다. Phase 4에서는 이를 엄밀히 검증하고 불필요한 I/O 복사 오버헤드를 철거합니다.


2. 핵심 설계 요소

2-1. Eager Import 상주 정책 (eager.py & runner.py)

  • 지연 로딩(Lazy Import) 금지:
    • 루프 실행 도중 디스크 상의 .py 파일이 편집되더라도 런타임에 영향을 주지 않도록, 프로세스 기동 시점에 모든 의존 모듈(delegation, loop, paho.mqtt 등)을 메모리에 상주시킵니다.
    • eager_load() 함수를 기동 최우선 단계에서 호출하여 sys.modules에 모든 바이트코드와 AST를 고정합니다.
  • 자식 프로세스 템플릿 격리:
    • 서브프로세스로 실행되는 도구 호출(delegate_job) 시 PYTHONDONTWRITEBYTECODE=1을 유지하여 디스크에 .pyc 파편이 남거나 작업 트리가 오염되는 것을 방지합니다.

2-2. B-13 Freeze 스냅샷 제거 및 경량화 (run_loop.sh)

  • 기본 동작 변경:
    • Python 루프 모드(MAM_LOOP_PY=1, 기본값)에서는 파일 복사 스냅샷(/tmp/mam-loop-freeze.XXXXXX)을 생성하지 않고 직접 실행합니다.
    • 디스크 I/O 절감: 턴당 수백 개 파일 복사 오버헤드(수십~수백 ms) 완전 제거.
  • 안전 롤백 경로 보존:
    • 환경변수 MAM_LOOP_FREEZE=1 또는 레거시 셸 루프 모드(MAM_LOOP_PY=0)가 명시된 경우에만 레거시 Freeze 스냅샷 로직이 활성화됩니다.
    • 기존 테스트의 락/가드 해제 계약(_mam_release_guard)은 외부 주입 스냅샷 디렉터리가 있을 경우 그대로 안전하게 정리합니다.

2-3. 라이브 헬퍼 버전 호환성 게이트 (MAM_VERSION)

  • lib.sh의 MAM_VERSION과 프로세스 런타임의 프로토콜 버전(eager.FRAMEWORK_VERSION, 현재 4.4.0)을 동기화하고, 불일치 발생 시 안전하게 fail-closed 거부합니다.
  • 이 게이트 때문에 프레임워크 트리는 부분 갱신이 불가능합니다. 두 상수 중 하나만 배포된 혼재 트리는 루프 기동 시점에 RuntimeError로 거부되므로, 배포는 항상 트리 단위로 수행합니다.

3. 검증 게이트 (P4-01 ~ P4-03)

📌 P4-01: Eager Import 상주 및 불변성 검증

  • 기동 시 전체 모듈이 메모리에 로드되어 런타임 중 추가 임포트 I/O가 발생하지 않음을 검증.
  • tests/test_issue5_phase4_runtime.py에 모듈 목록 및 바이트코드 상주 테스트 추가.

📌 P4-02: 작업 중 코드 수정(B-13) 내구성 스트레스 테스트

  • 루프가 실행되는 도중 디스크 상의 소스 코드가 수정되거나 임의의 내용으로 치환되더라도, 이미 상주한 파이썬 프로세스가 에러 없이 끝까지 작업을 완결함을 시뮬레이션 검증.

📌 P4-03: Freeze 우회책 제거, 전면 회귀 및 운영 문서 동기화

  • run_loop.sh의 기본 Freeze 복사 분기를 비활성화.
  • 전체 회귀 테스트(744개+) 0-Fail 확인.
  • task.md 및 마이그레이션 운영 문서 갱신 완료.