AI 에이전트 · AI Engineering

VibeMarshal 시리즈 검증 부록

고정 source에서 확인한 검사 환경과 기존 실패, 구현 단계 및 목표 조건 반례의 재현 명령과 결과를 기록해요.

AI AgentPythonSQLiteWorkflow

문제의 출발점

이 부록은 2026년 10월 7일 원고 작성 때의 표적 회귀 검사와, 보완 때 임시 복사본에서 실행한 공통 사례를 구분해 기록해요. 기준 코드는 32bb0f9dd9f024045d24487312b50f5b703573a3예요. 아래 재현 명령은 다시 확인하는 방법이며 이번 보완에서 기존 126개 검사를 재실행했다는 뜻은 아니에요.

원고와 재현 스크립트 및 검사 로그 다운로드

묶음에는 시리즈 5편과 부록, 두 재현 프로브 및 기존 검사 요약과 단계별 로그가 있어요. source checkout을 준비한 뒤 아래 명령으로 같은 fixture를 다시 확인할 수 있어요.

확인한 환경과 검사 범위

확인한 환경과 검사 범위 데이터 표
항목기록
실행 환경Windows, Python 3.12.14
제품 코드고정 커밋의 source, 패키지 정의는 flowmarshal-engine 0.2.0a1
Python 의존성pydantic 2.13.5, cryptography 50.0.1, openai-codex 0.147.0
기존 검사의 설치 방식번들 Python에 source를 PYTHONPATH로 연결하고 SDK는 별도 분석 폴더에 설치
공통 사례표준 라이브러리만 사용한 fixture 임시 복사본
실행하지 않은 범위실제 Codex·Claude 호출, GUI build/E2E, wheel clean install, 전체 1.0 qualification

Python과 의존성 버전은 보완 시 같은 환경에서 다시 조회했어요. 기존 검사는 제품 wheel을 깨끗하게 설치한 환경의 결과가 아니에요. 프로젝트의 의존성 고정값은 pyproject.toml에 있어요.

기존 표적 검사 결과

9개 모듈의 실제 테스트 126개 중 123개가 통과했고 시간 검사 3개가 실패했어요. 이 수치는 전체 suite나 제품 qualification 결과가 아니에요.

기존 표적 검사 결과 데이터 표
배치실제 테스트통과실패추가 상태
domain·ledger·planning·authorization·effect의 5개 모듈67670첫 호출에서 다른 두 모듈의 SDK import 오류 2개 발생
SDK 준비 뒤 runtime job·effect checkpoint의 2개 모듈44413import 오류 해결, timing assertion 실패 보존
execution/usage·validation obligations의 2개 모듈15150오류와 skip 없음
합계1261233초기 import 오류는 실제 테스트 수에서 제외

원래 첫 실행의 unittest 집계는 69개 항목에 import 오류 2개를 포함했어요. SDK를 준비한 뒤 그 두 모듈을 실행했으므로 실제 테스트 수는 67 + 44 + 15 = 126으로 계산해요. 다운로드 묶음의 verification.json, verification-runtime.json, verification-validation.json에는 당시 모듈 목록과 집계가 담겨 있어요. 이는 도구가 기록한 실행 요약이며 전체 원시 console 로그는 아니에요.

실패한 세 검사는 모두 엄격한 < 0.25초 조건이 있어요. 정확히 0.250초여도 통과하지 않아요.

기존 표적 검사 결과 데이터 표
검사관측 시간
test_slow_inventory_for_supplied_proposal_stays_in_execution_spec_job0.250초
test_slow_inventory_lookup_does_not_block_execution_spec_prepare_tick약 0.266초
test_slow_inventory_lookup_does_not_block_goal_semantic_validate_tick0.250초

원인은 확정하지 않았고 같은 timing 검사를 반복해 실패를 지우지 않았어요. 환경 잡음이나 flaky라고 판단하려면 추가 근거가 필요해요. 이 결과만으로 실환경의 시간 상한이 충족됐다고 주장하지 않아요. 시간 상한과 회귀 검사

기존 모듈을 다시 확인하는 명령

아래는 PowerShell에서 별도의 checkout과 개발 환경을 준비하는 방법이에요. 실제 모델을 호출하는 qualification 명령을 포함하지 않아요. 경로와 환경이 달라지면 시간 측정값도 달라질 수 있어요.

git -c core.longpaths=true clone https://github.com/jaeseongs95/vibemarshal.git
Set-Location vibemarshal
git -c core.longpaths=true checkout 32bb0f9dd9f024045d24487312b50f5b703573a3
python -m venv .venv
& .\.venv\Scripts\python.exe -m pip install -e .
$env:PYTHONPATH = (Resolve-Path .\src).Path

source와 tests를 읽는 위치는 checkout의 최상위 폴더예요. 아래 세 명령은 같은 9개 모듈을 배치별로 검사하며, 테스트 결과가 실패면 해당 Python process의 종료 코드도 0이 아니에요.

& .\.venv\Scripts\python.exe -c "import sys,unittest; sys.path.insert(0,'tests'); names=['test_engine_domain','test_engine_ledger_service','test_engine_planning','test_engine_authorization_freshness','test_engine_effect_authorization']; result=unittest.TextTestRunner(verbosity=2).run(unittest.defaultTestLoader.loadTestsFromNames(names)); sys.exit(not result.wasSuccessful())"

& .\.venv\Scripts\python.exe -c "import sys,unittest; sys.path.insert(0,'tests'); names=['test_engine_runtime_job_supervisor','test_engine_effect_checkpoint_recovery']; result=unittest.TextTestRunner(verbosity=2).run(unittest.defaultTestLoader.loadTestsFromNames(names)); sys.exit(not result.wasSuccessful())"

& .\.venv\Scripts\python.exe -c "import sys,unittest; sys.path.insert(0,'tests'); names=['test_engine_execution_usage_separation','test_engine_validation_obligations']; result=unittest.TextTestRunner(verbosity=2).run(unittest.defaultTestLoader.loadTestsFromNames(names)); sys.exit(not result.wasSuccessful())"

원고 작성 때는 첫 배치에서 SDK가 없어 두 모듈이 import되지 않았고, 별도 폴더에 SDK를 준비한 뒤 두 번째 배치를 실행했어요. 위 절차는 시작할 때 의존성을 준비하므로 그 초기 import 오류를 재현하려는 명령은 아니에요. 테스트 목록과 본래 코드 경계를 다시 확인하는 절차예요.

공통 사례에서 새로 실행한 검사

사례의 입력은 project-e2e-multi-task fixture예요. 네 파일을 임시 폴더에 복사하고 테스트 파일과 함수 이름·인자를 유지했어요. cents와 total의 구현만 단계별로 바꿨어요.

# money.py의 예제 구현
from decimal import Decimal

def cents(amount: str) -> int:
    return int(Decimal(amount) * 100)

# invoice.py의 예제 구현
from money import cents

def total(prices: list[str]) -> int:
    return sum(cents(price) for price in prices)

성공 범위는 fixture가 제시한 입력과 기대값이에요. 이 예제 코드를 모든 금액 입력의 처리 규칙으로 평가하지 않았어요. 세 단계마다 별도의 Python process에서 전체 6개 검사를 실행했어요.

공통 사례에서 새로 실행한 검사 데이터 표
단계process 종료 코드실행한 검사통과ERROR
원본의 미구현 함수 두 개1606
cents만 구현1633
cents와 total 모두 구현0660

여기서 ERROR는 함수의 NotImplementedError 때문에 검사가 오류로 끝났다는 뜻이에요. 검사를 실행했어도 아직 구현하지 않은 기능이 있으면 전체 요청을 완료할 근거가 생기지 않아요. 총 18개 테스트 실행은 세 상태의 같은 6개 사례를 관측한 것이며 독립적인 18개 기능 사례가 아니에요.

다운로드 묶음의 example-probe.py와 evidence/example/에는 프로브와 결과 JSON 및 단계별 검사 로그가 있어요. 공개용 로그는 임시 폴더의 절대 경로만 <temporary-example-project>로 바꿨으며 그 사실을 JSON에 기록했어요. 원본 fixture와 테스트 파일의 바이트가 바뀌지 않았는지도 SHA-256으로 대조했어요.

# 압축을 푼 원고 폴더에서 실행한다.
# SourceRoot에는 위에서 준비한 source checkout의 절대 경로를 준다.
$SourceRoot = (Resolve-Path C:\work\vibemarshal).Path
python .\example-probe.py --source-root $SourceRoot --output .\example-run

example-run은 새 출력 폴더여야 해요. 프로브는 그 아래의 임시 복사본만 수정하고 원본 source를 고치지 않아요. 기존 파일을 덮어쓰지 않으며 실행 후 결과 JSON과 로그를 남겨요. 실제 provider 실행, Core 완료 판정이나 1.0 제품 검증을 재현하는 명령은 아니에요.

반환값이 맞아도 재사용 조건을 어기는 반례

시리즈를 재구성하며 같은 fixture의 다른 구현 경로를 추가로 검사했어요. cents는 Decimal로 구현하고, total도 금액을 직접 Decimal로 변환하도록 바꿨어요. 이때 반환값 검사만 선택하면 통과하지만 기존 함수 재사용 조건은 어길 수 있어요.

반환값이 맞아도 재사용 조건을 어기는 반례 데이터 표
단계실행한 검사통과실패process 종료 코드
직접 변환하는 total, 반환값 검사만 선택5500
같은 구현, 원래의 전체 검사6511
cents 재사용으로 수정, 같은 전체 검사6600

첫 단계는 불완전한 검사 범위의 반례를 관측하기 위한 실행이며 완료 판정의 근거로 채택하지 않았어요. 두 번째 단계의 test_reuses_money_cents는 invoice.cents를 감시해 기대 호출 2회와 실제 0회를 비교했고 AssertionError: 2 != 0으로 실패했어요. 테스트 파일의 내용과 원본 fixture의 네 파일은 바꾸지 않았어요.

원고 묶음의 goal-path-counterexample.py와 evidence/counterexample/에 프로브, 단계별 원시 검사 로그와 결과 JSON을 담았어요. 로그에서는 실행 복사본의 절대 경로를 <isolated-fixture>로 치환했어요. 새 프로브는 기존 source 바깥의 새 출력 폴더에 fixture-copy를 만들고, 그 복사본의 구현 두 개만 수정해요. 검사 선택 항목과 원본 SHA-256은 JSON에 기록하며 원본과 검사 파일의 바이트가 유지됐는지도 확인해요.

python .\goal-path-counterexample.py --source-root $SourceRoot --output .\counterexample-run

counterexample-run은 새 폴더여야 해요. 프로브의 세 검사 실행은 별도의 Python process에서 진행돼요. 합계 17회 실행은 동일한 fixture를 서로 다른 구현과 검사 범위에서 확인한 수이며, 독립적인 17개 기능 사례가 아니에요. 실제 Engine의 Plan 선택이나 승인·완료 전이, provider 실행을 재현한 결과도 아니에요.

이 반례는 모든 작업이 실제 Core의 완료 조건을 충족했는데도 Goal이 잘못 승인됐다는 주장이 아니에요. 반환값만 확인하는 작업별 검사를 전체 목표의 근거로 확대했을 때 놓칠 수 있는 조건을 보여줘요. Goal·Task·integration 검사의 범위를 함께 설계해야 하는 이유로 읽어야 해요.