23 KiB
S2_00 request 생성·검증·저장 선행 task 신설 계획
Objective
Stage_2_S2_00.yml의 맨 앞에 Task_S2_00_prepare_request를 신설하여 외부 실행 인자를 검증하고 stage2_control/s2_00_request.json을 저장·read-back한 뒤, 성공한 동일 실행만 기존 Task_S2_00_deterministic_ingress로 진행하도록 한다. workspace 단위 동시 실행 통제, 두 task 간 request identity 결속, 빌드·배포·hash 계약 갱신을 하나의 변경으로 다룬다.
작성일: 2026-09-30. 상태: 구현 전 계획. 이 문서 작성 과정에서는 실행 YAML·runtime·배포 자산을 변경하지 않았다.
Deliverables
| 산출물 | 내용 |
|---|---|
| 외부 실행 인자·host 계약 | 인자 전달 방식, workspace 권한·경로 결속, 직렬화, task 실패 차단, receipt 전달 |
| 2-task authoring 및 배포 YAML | prepare → ingress 순서와 success-only 실행 |
| prepare 구현 및 runtime mirror | 입력 검증, request 생성, write/read-back, 준비 receipt |
| ingress 보강 | host가 전달한 준비 receipt의 request hash·실행 identity와 실제 입력 대조 |
| workflow/schema/binding/builder 갱신 | task별 쓰기 권한, 2-task 추출·검증·receipt·mirror 계약 |
| 회귀·통합 검증 증거 | mock, 동시 실행, 실제 backend를 구분한 결과 |
| 분석·IO 문서 개정 | 새로운 선행 단계, 외부 인자 및 실패·잠금 수명 반영 |
Scope and Non-Scope
- 범위: request 준비와 기존 ingress를 연결하는 구조 및 이를 배포 가능한 상태로 검증하는 데 필요한 계약 변경.
- 유지: request 파일의 기존 6필드, 고정 경로, 기존 C00/C05/C10/C15의 업무 책임, 정상/diagnostic 산출물 집합.
- 제외: Stage 1 사건 데이터 수정, S2_10 이후 업무 로직 변경, 기존 DEV release의 자동 production 승격, 기존 보존·projection 결함의 일괄 수정.
- 계획 작성이 구현 또는 live 배포 승인을 뜻하지 않는다. 실행 제한 해제는 request 생성 구현과 별개의 작업이다.
Known Inputs
M = Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/, R = M/Default_Agent/Stage_2_Clean/, W = localdocs가 결속한 논리 workspace root.
| 확인한 현 상태 | 근거 |
|---|---|
| 현재 IN → ingress → OUT, 단일 task | R/agent_scripts/Stage_2_S2_00.yml: 17–43, 6230–6248 |
| request는 읽기 입력이며 6필드 폐쇄형 검증 | 같은 YAML: 5548–5591, 5757 이후 |
| 입력 closure를 두 번 읽고 bytes 비교 후 temp hydration | 같은 YAML: 5825–5893 |
| 빌더가 정확히 1 task·1 run_code·고정 DAG를 강제 | R/offline_build/build_s2_00_inline_projection.py: 283–378 |
authoring 정본은 M/Stage_2_S2_00_v.2.yml; 배포 YAML과 mirror는 파생본 |
같은 builder: 30–38, 680–755 |
| 단일 code pointer와 code hash·mirror를 receipt에 기록 | 같은 builder: 680–755 |
현재 S2_00 쓰기 root는 stage2_runs/by-binding/<run_binding_digest>/ |
R/deployment/stage2_code_executor_binding.yml: 47–66 |
| localdocs 계약상 허용 도구는 read_binary_doc/write_binary_file | 같은 binding: 47–66. CAS·분산 잠금 기능이 있다는 근거는 없음 |
| 외부 인자 주입 및 성공 receipt의 task 간 전달에 필요한 backend 구체 API | 현재 확인 범위에서 미확정. 구현 1단계에서 확인해야 함 |
사용자 지정 기존 분석 자료: Stage_2_00_Analysis_v1.md, Stage_2_00_IO_info.md.
Material Assumptions
- request는 LLM이 추론하거나 폴더를 scan해서 만드는 값이 아니다. host가 확정한 네 값과 코드상 두 상수로 생성한다.
- task 프로세스·임시 디렉터리·메모리는 서로 공유된다고 가정하지 않는다. backend가 인증된 실행 context와 선행 receipt를 후행 task에 전달해야 한다.
wait_until은 실행 순서를 기술하지만, 실패한 선행 task의 후속 실행까지 자동 차단한다는 보장은 별도로 검증한다.- 파일 읽기→없으면 lock 파일 쓰기는 원자적 잠금이 아니다. read-back·hash 비교도 상호 배제를 대신하지 않는다.
- 권고 기본안은 host가 같은 user/workspace의 전체 S2_00 실행을 직렬화하는 것이다. 최소 요구 구간인 request 저장 전부터 hydration 완료까지보다 길게 잠금을 유지하여, 초기 구현에서 중간 해제 프로토콜을 추가하지 않는다.
Questions That Could Change the Outcome
구현 착수 시 아래를 backend 문서·코드·시험으로 먼저 확인한다. 답을 추측해 YAML 문법이나 도구 기능을 만들지 않는다.
| 확인 사항 | 결정 기준·미지원 시 처리 |
|---|---|
| 외부 structured 인자 전달 방식 | 실제 지원하는 executor 입력 채널 사용. 고정된 템플릿 문법·미지원 run_code parameter를 임의 추가하지 않음 |
| 선행 stdout receipt를 후행 입력으로 전달하는 방식 | backend가 실행 identity에 결속해 전달해야 함. 동일 고정 파일에 별도 receipt를 쓴다는 방식만으로 신뢰 경계를 대신하지 않음 |
| task 성공 판정 | transport 성공뿐 아니라 exit code·receipt schema·ok·실행 ID 일치 확인 가능해야 함 |
| workspace 직렬화와 취소·worker 종료 보장 | 여러 backend worker에 걸친 전역 보장 필요. 한 프로세스의 mutex만 있으면 불충분 |
| 저장 권한 강제 | prepare에 정확한 request 경로만 쓰기 허용; ingress 결과 쓰기 권한과 분리 가능한지 확인 |
미지원 항목이 있으면 해당 backend 기능을 선행 구현 대상으로 기록한다. 로컬/mock 작업은 계속할 수 있으나 backend 증거 없이 live-ready로 표시하지 않는다.
Workstreams and Dependencies
1. 기준선 및 변경 영향 확정
- 관련 authoring·배포 YAML, runtime mirror, workflow, schema, binding, builder·tests의 hash와 Git 변경 상태를 기록한다. 기존 사용자 변경은 보존한다.
- 문자열뿐 아니라 task ID·code pointer·code hash를 참조하는 소비자를 찾아 변경 목록을 닫는다.
- 기존 검사 결과를 기준선으로 기록하여 이번 변경의 회귀와 기존 실패를 구분한다.
- 위 backend 확인 사항을 검증하고 실제 인자·receipt 주입 방식 및 잠금 구현 위치를 확정한다.
완료 기준: 정확한 변경 파일 목록, backend 연동 계약, 기존 실패 목록이 기록되어야 한다.
2. 외부 인자 및 request 계약 확정
request 출력은 다음 6필드로 고정한다.
| 필드 | 공급자·형식 | 검증 |
|---|---|---|
schema_version |
prepare 코드 상수 | stage2_s2_00_execution_request.v1 |
workflow_id |
prepare 코드 상수 | S2_00 |
request_id |
host 문자열 | [A-Za-z0-9][A-Za-z0-9._-]{0,127} |
attempt_id |
host 문자열 | 위와 동일. 재시도 정책에 따라 새 시도 식별자 부여 |
stage1_run_root_ref |
host 문자열 | W 아래 승인된 Stage 1 사건 root에 결속한 canonical 상대경로 |
stage1_deployment_root_ref |
host 문자열 | W 아래 승인된 Stage 1 배포 root에 결속한 canonical 상대경로 |
- 누락·추가 필드, 빈 값, 잘못된 타입, absolute path,
.., 역슬래시, NUL, 비정규 NFC 경로 등을 거절한다. 기존_inline_relative_path와 검증 의미를 맞춘다. - 문법적으로 올바른 경로라는 사실과 해당 실행이 접근할 권한이 있다는 사실을 구별한다. host가 승인한 user/workspace 및 Stage 1 완료 실행과 두 root를 결속한다.
- request 값은 다른 업무 run에서 남은 파일, 작업 디렉터리 추측, LLM 판단으로 채우지 않는다.
- user/workspace·host execution ID·lock ownership·준비 receipt는 별도의 실행 envelope에 담는다. 기존 request JSON에 7번째 필드를 추가하지 않는다.
- structured 전달을 우선한다. 코드 템플릿에 전달해야 하는 환경이라면 검증된 직렬화·안전한 encoding을 사용하고, 입력 문자열을 Python source에 직접 삽입하지 않는다.
완료 기준: 허용·거절 예제와 인자 전달 계약이 양쪽 task 및 backend 검증에서 일치한다.
3. host 직렬화 및 실패 수명 구현
잠금 key는 인증된 (user, workspace, S2_00 request 고정 경로)로 정한다. 서로 다른 request_id라도 동일 workspace의 고정 파일을 공유하면 같은 key를 사용한다.
host admission → workspace 실행 소유권 획득
→ prepare 시작 → request 저장/read-back
→ 성공 receipt를 동일 실행 ingress에 전달
→ ingress request 1차/2차 읽기 → temp hydration
→ core 실행·원격 출력 발행 → 종료/취소 정리
→ 두 task와 미완료 I/O의 종료 확인 → 소유권 해제
- 기본안은 전체 S2_00 종료까지 직렬화한다. 따라서 최소 보호 구간인 hydration 완료까지는 확실히 포함된다.
- prepare에서 획득한 프로세스 로컬 lock을 task 종료 때 해제하는 구조는 금지한다. 소유권은 host 실행 전체에 귀속된다.
- 모든 request writer와 재시도 경로가 같은 통제에 참여해야 한다. 통제 밖 writer는 권한으로 차단한다.
- timeout·취소·host 재시작 시 오래된 worker와 진행 중 쓰기가 끝났는지 확인한 후 다음 실행을 허용한다. TTL 만료만으로 새 소유자를 실행하지 않는다.
- lease 방식이 불가피하다면 stale owner의 쓰기/읽기를 실제로 거절하는 fencing 또는 동등한 host 보장을 구현한다. JSON에 token만 넣는 것은 fencing이 아니다.
- 이후 성능 최적화로 hydration 직후 해제하려면 authenticated hydration-complete 신호, 이후 request 재읽기 없음, 원본 Stage 1 run의 불변성 등을 별도 입증한다. 초기 버전에는 적용하지 않는다.
완료 기준: 두 host worker의 경쟁·지연·취소 시험에서도 request 교차 소비가 없어야 한다.
4. 선행 task 구현
신규 task ID: Task_S2_00_prepare_request.
- 인증된 host envelope, 실행 소유권, 네 외부 인자를 검증한다.
- 고정 두 상수를 추가하여 6필드 request 객체를 만든다.
- strict JSON/schema 및 경로·ID 검증을 수행한다. schema 자산을 읽는 경우 release/module manifest의 hash 결속된 정확한 closure를 사용한다.
- 기존 canonical JSON 규칙(UTF-8, 정렬 key, 고정 구분자, NaN 금지, 종료 newline)으로 직렬화하고 raw SHA-256을 계산한다.
- 소유권을 유지한 상태에서
W/stage2_control/s2_00_request.json에 binary write를 수행한다. 현재 계약에 없는 원격 rename·원자적 파일 교체 기능을 가정하지 않는다. - 같은 경로를 binary read-back하여 bytes가 동일한지 확인하고, 다시 parse/schema 검증한다.
- 성공일 때만 stdout 준비 receipt를 반환한다. 권고 schema는 신규
stage2_s2_00_prepare_request_receipt.v1이며ok, request path/hash/byte length, request_id/attempt_id, host execution binding을 포함한다. 이것은 신규 설계이며 기존 파일이라고 표현하지 않는다. - 오류·write 응답 유실·read-back 불일치·close 실패 등은 성공 receipt로 취급하지 않는다. ingress는 실행하지 않는다. 부분 파일이 남아 있어도 성공한 것으로 간주하지 않는다.
동일 시도 재실행은 같은 bytes 및 host identity가 확인되면 재사용 가능하다. 새 시도/다른 request로 교체할 때에는 이전 실행 종료 및 새 소유권이 먼저 확인되어야 한다. 성공 후 무조건 request를 삭제하는 정리 코드는 두지 않는다.
완료 기준: 실제 저장 bytes와 receipt hash가 일치하고, 모든 실패 경로가 후행 실행을 차단한다.
5. ingress 결속 및 DAG 변경
IN
→ Task_S2_00_prepare_request
→ [host: exit=0 + 유효한 ok:true receipt + 동일 실행 binding 확인]
→ Task_S2_00_deterministic_ingress
→ OUT
- YAML
task_procedure에 prepare의wait_until: [IN], ingress의wait_until: [Task_S2_00_prepare_request]를 설정하고 nexts를 대응시킨다. stage prevs/nexts는 기존 독립 stage 구조를 유지한다. - host의 success-only 조건은 YAML edge와 별도로 계약 및 시험에 포함한다. 실패한 prepare가 '완료'되었다는 이유로 ingress를 시작하지 않는다.
- ingress는 host가 제공한 준비 receipt가 없거나 잘못되면 시작을 거절한다. 최초 request bytes와 expected hash, request_id/attempt_id를 대조한다.
- 기존 두 read-pass의 동등성 검사를 유지한다. 두 번째 request bytes도 준비 receipt hash와 일치해야 한다. 동일하게 바뀐 다른 request를 두 번 읽어 통과하는 상황까지 차단한다.
- 신뢰할 수 없는 stale receipt·다른 workspace receipt·다른 attempt의 receipt를 거절한다.
- 기존 C00–C15, output barrier·route 계약은 유지한다. wrapper 실패와 core diagnostic 분기를 혼동하지 않는다.
완료 기준: prepare와 ingress가 같은 request를 사용했다는 검증 가능한 연결이 생긴다.
6. authoring·빌드·배포 계약 갱신
| 파일·영역 | 작업 |
|---|---|
M/Stage_2_S2_00_v.2.yml |
authoring 정본에서 2-task 구조·설명·version·inline source 갱신 |
R/agent_scripts/Stage_2_S2_00.yml |
수정한 builder로 배포본 생성. 배포본만 수작업 수정하지 않음 |
R/offline_build/build_s2_00_inline_projection.py/.txt |
'정확히 1개' 검증을 정확히 두 개의 지정 task와 지정 순서로 변경; 추가 임의 task는 거절 |
| 같은 builder의 code 검사 | 공통 보안·endpoint·import 검사는 유지; ingress 전용 token과 prepare 전용 token을 분리 |
R/runtime/s2_00_ingress.py/.txt |
ingress task code의 파생 mirror로 유지 |
신규 R/runtime/s2_00_prepare_request.py/.txt |
prepare code의 파생 mirror 제안. 두 task를 결합한 실행 파일로 만들지 않음 |
R/manifest/s2_00_inline_code_receipt.json |
task별 code pointer·hash·mirror, 전체 task semantics hash로 확장; schema version/소비자 동시 갱신 |
R/workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml |
선행 단계, 외부 인자, receipt·success gate·직렬화 계약 반영 |
R/deployment/stage2_code_executor_binding.yml |
task별 executor 및 권한: prepare는 request 고정 경로, ingress는 기존 결과 root. schema/release 읽기 경로도 task별 명시 |
R/schemas/ingress.schema.json |
기존 6필드 execution_request 유지, 신규 prepare/envelope receipt 검증 정의 |
R/schemas/deployment.schema.json 및 관련 schema |
두 task·task별 code binding·receipt 계약과 실제 소비자 호환성 반영 |
R/manifest/module_manifest.json, stage2_release.json, release validator |
변경 자산의 등록·hash와 추가된 계약 검증 반영 |
M/Stage_2_00_Analysis_v1.md, Stage_2_00_IO_info.md |
구현 완료 후 실제 구조·IO·검증 상태로 개정 |
task index=0에 ingress가 있다고 가정하는 코드를 모두 확인한다. task_name으로 추출하고 receipt에는 실제 YAML pointer도 남긴다. version 값은 관련 schema와 소비자 호환성을 확인해 함께 올린다.
7. hash 재결속 및 패키지 확정
- 변경 자산 → module/release → inline release pin → authoring projection/mirror/receipt → executor binding/detached admission의 실제 참조 그래프를 먼저 만든다.
- 현재 builder는 projection 이후 binding 재결속을 전제로 한다. 기존 detached 설계를 유지하고, parent release에 자신을 포함한 code hash를 되먹이는 순환 의존을 새로 만들지 않는다.
- 참조 그래프의 위상 순서대로 재생성한다. 순환이 발견되면 hash를 반복 덮어쓰는 대신 detached boundary를 설계·검증한다.
- 현재
expected_release_sha256, task별 code hash, Agent raw hash, workflow/schema/module hash와 receipt pointer를 함께 대조한다. - 재생성 뒤 빌더
--check, release validator, mirror parity를 실행한다. 두 번째 빌드에서 bytes 차이가 없어야 한다. - 테스트용 release와 실제 배포 release를 분리한다. DEV guard를 삭제하거나 production 표기를 붙여 검사를 통과시키지 않는다.
완료 기준: 참조된 변경 자산의 hash가 모두 일치하고, 반복 빌드가 추가 변경을 만들지 않는다.
Source and Tool Plan
로컬 authoring·builder·runtime·tests를 우선 읽는다. backend 관련 문서·코드는 필요한 범위에서 확인하고 지원 여부를 증거로 남긴다. 신규 의존성 설치나 서비스 호출은 이 계획 작성에 포함하지 않는다. 구현 시 기존 도구·검증 runner를 확인해 사용하고, 라이브 시험은 별도 격리 workspace와 비실사건 fixture로 수행한다.
Validation Plan
| 시험 | 통과 기준 |
|---|---|
| 유효한 인자 | request 정확히 6필드, canonical bytes/hash/read-back 일치 |
| 누락·추가·타입·ID·경로 오류 | 저장 전 거절, ingress 호출 0회 |
| 권한 밖 경로·다른 workspace | host 결속 검증 실패, 업무 입력 읽기 불가 |
| 저장 실패·응답 유실·read-back mismatch | 성공 receipt 없음, ingress 호출 0회 |
| 선행 task exit 0이나 ok:false/깨진 receipt | host가 후행 task를 실행하지 않음 |
| 준비 후 request 변조 | 첫 읽기 expected hash 검증 또는 두 pass 비교에서 거절 |
| 두 pass 모두 동일한 타 요청으로 교체 | 준비 receipt hash/identity 검증에서 거절 |
| 같은 workspace 두 요청·두 worker | 단일 소유자만 진입, 다른 요청 bytes를 소비하지 않음 |
| 다른 workspace 병렬 실행 | 불필요한 전역 직렬화 없이 독립 진행 |
| cancel·timeout·host crash·오래된 worker 재개 | 이전 쓰기 가능성이 사라지기 전 새 owner 쓰기 금지; stale owner 차단 |
| 동일 시도 retry / 새 attempt | 정의한 재사용/교체 정책 준수, 기존 output idempotency 계약 유지 |
| task shape / builder | 지정 두 task와 순서만 허용; task 누락·추가·우회 edge 거절 |
| 두 code mirror·receipt pointer·hash | authoring에서 추출한 bytes와 정확히 일치 |
| 기존 core 정상·diagnostic 회귀 | fixture 기준 11+E/5 출력 및 barrier 계약 보존 |
| 실제 backend 통합 | 인자 주입·receipt 전달·failure gate·workspace 격리를 실제 환경에서 확인 |
mock 통과는 실제 host 잠금·권한 강제 증거가 아니다. STATIC_PASS, OFFLINE_TEST_PASS, BACKEND_INTEGRATION_PASS, LIVE_ADMISSION_PENDING을 구분해 보고한다. 현재 DEV release로 정상 core 성공을 주장하지 않는다.
Approval Boundaries
현재 요청은 작업 계획 작성이다. 이 단계에서는 계획 문서만 생성한다. 이후 구현 요청 시 범위 내 로컬 수정·시험을 수행하고, 실제 서비스 배포·외부 쓰기·live activation은 그때의 승인 범위를 확인한다. backend 기능 미지원은 기술적 미완료 조건으로 기록하며 이를 단순 승인 문제로 대체하지 않는다.
Progress
- 현재 단일 task·request read·builder 제약 확인
- 현재 write root와 localdocs 도구 계약 확인
- 작업 순서·의존성·동시 실행·검증 계획 작성
- backend 전달·직렬화 기능 확인 및 연동 방식 확정
- schema·prepare·ingress·DAG 구현
- builder·binding·hash 재결속
- offline·동시 실행·backend 통합 검증
- 분석·IO 문서 갱신 및 배포 적격성 판정
Decision Log
| 날짜 | 결정 | 근거 | 결과 |
|---|---|---|---|
| 2026-09-30 | request의 기존 6필드 유지 | 현재 strict validator와 사용자 요구 | 실행 보조 정보는 host envelope로 분리 |
| 2026-09-30 | 첫 버전은 전체 S2_00 host 직렬화 | 두 독립 task 사이 lock 수명 및 고정 request 경로 | hydration 완료 전 해제 위험과 중간 callback 의존 감소 |
| 2026-09-30 | 준비 receipt hash를 ingress에 전달 | 두 read-pass 비교만으로 다른 요청 교체를 모두 검출할 수 없음 | 소비할 request를 선행 실행에 결속 |
| 2026-09-30 | authoring부터 재생성 | builder가 정본 및 mirror parity를 관리 | 배포 YAML 단독 변경 방지 |
Evidence Ledger
| 명제 | 확인 근거 | 상태 |
|---|---|---|
| 기존 builder는 두 task를 거절한다 | extract_run_code_task의 EXACTLY_ONE_TASK_REQUIRED·EXACTLY_ONE_RUN_CODE_REQUIRED | 확인 |
| 현재 request 저장은 쓰기 허용 root 밖이다 | S2_00 binding의 write_root_rule | 계약에서 확인; live 강제 여부는 미확인 |
| localdocs 원자적 lock/CAS 지원 | 현재 allowlist에 read/write만 있음 | 지원 근거 없음, 사용 가능하다고 가정하지 않음 |
| 선행 task를 현재 backend가 어떻게 인자 결속하는가 | 구체 backend 구현을 아직 확인하지 않음 | 미확정 |
| request writer의 생성 필요 | 현재 소비 코드 및 이전 폴더 전체 검색 결과 | 현 패키지에 실사용 writer 없음 |
Risks and Failure Modes
- YAML만 바꾸면 builder·code pointer·권한·hash 계약에서 실패한다.
wait_until만 추가하면 prepare 실패 후 ingress가 진행될 수 있다.- 고정 request 파일에 write/read-back만 구현하면 동시 요청이 서로 덮어쓸 수 있다.
- lock TTL 이후 오래된 writer가 살아 있으면 새 요청을 오염시킬 수 있다.
- 기존 release 제한을 이번 변경의 실패로 혼동하거나, 이를 제거해 정상 실행을 과장할 수 있다.
- 다른 request가 같은 run binding으로 귀결될 때 기존 status bytes 일치 요건은 여전히 적용된다. 기존 출력 충돌을 자동 덮어쓰기로 해소하지 않는다.
롤백은 두 task 실행을 먼저 정지하고 진행 중 I/O 종료를 확인한 뒤, authoring·배포본·mirror·schema·binding·receipt를 검증된 동일 버전 묶음으로 복원한다. 이전 버전도 외부 request 공급 없이는 실행되지 않으므로 롤백 자체를 서비스 정상화로 보지 않는다. 사건 입력·이미 발행된 결과는 일괄 삭제하지 않는다.
Results and Residual Uncertainty
계획은 작성 완료하였고, 구현은 미착수다. 가장 중요한 미확정 항목은 backend의 structured 인자/receipt 전달과 workspace 단위 직렬화·worker 종료 통제이다. 이 기능이 확인되거나 구현되어야 안전한 2-task 실행이 완성된다. 완료 판정은 request 생성 성공뿐 아니라 동일 요청의 후행 소비, 실패 시 차단, 동시 실행 안전성, 빌드·hash 일치를 모두 통과하는 것으로 한다. 실제 backend 시험 전에는 live-ready로 판정하지 않는다.