release: 0.5.11 — 인계 노트가 세 번째 상태 파일이던 것 (STATUS.md → current-task.json handoff) - #13
Merged
Merged
Conversation
`.ax/docs/STATUS.md` 는 어느 리포에도 커밋된 적 없는 세션 상태인데 `.gitignore.template` 에 없었고, 커밋되는 `.ax/docs/` 트리 한가운데 있었어요. 리포 계약(CLAUDE.md)은 "상태 파일은 state.json · current-task.json 둘, 새로 만들지 않아요" 인데 STATUS.md 가 그걸 어겼어요. - 인계 노트를 `.ax/current-task.json` 의 `handoff` 객체로 옮겨요 — now · now_at · next · open · renamed. writer 는 그대로 `status-note.sh` 하나 (CLI 불변, `--show --json` 의 sections/counts/over_cap 불변, `lines` → `items`, `now_at` 추가). 줄 끝 `(YYYY-MM-DDTHH:MMZ)` 스탬프는 `now_at` 필드로 올라와요. - Stop 게이트(`spec-gate.sh`)는 이미 열어 둔 current-task.json 의 `handoff.now` + `now_at` 으로 24시간을 봐요. `harness-pointer.sh` 는 handoff 에 항목이 있으면 경로만 한 줄, `build-memory.sh` 포인터도 같은 조건. - `tier-from-state.sh --reset` 이 `current-task.json.lock` 을 잡아요 — 같은 파일을 쓰는 두 스크립트가 같은 락 문자열을 갖게. reset 은 `handoff` 를 지우지 않아요 (next·open·renamed 는 task 를 넘어 살아요). jq 가 죽으면 원본을 두고 tmp 만 치우고 error 로 답해요. - doctor 가 남은 `.ax/docs/STATUS.md` 를 마이그레이션 잔재(`stale_status_md`)로 알려요 — 자동 삭제·import 없음. - `.ax/MEMORY.md` 는 그대로 — 고유 정보가 없는 재생성 캐시고 이미 gitignore 돼 있어요. 포인터 한 줄만 바뀌어요. - smoke: §34·§35·§41·§43 을 JSON 저장소 기준으로 재작성 + writer in-place 가드 · reset 보존 · 선점 락 7종. 571 통과 / 0 실패 (기준선 559). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XgYfK9moXVF9YCRPvfg8tH
- changelog/0.5.11.md: "A 의 정직한 비용" 의 "A" 는 플래닝 세션의 옵션 라벨이라 독자에게 정의가 없었어요 — "current-task.json 에 두는 것의 정직한 비용" 으로. - tests/smoke.sh: current-task.json writer in-place 가드가 skills/ 만 훑었어요 — agents/ · templates/default/.ax/scripts/bash/ 까지. 후속 update-task.sh 같은 writer 스크립트가 자동으로 계약 아래 들어와요. - tier-from-state.sh --help: 헤더 주석이 27행까지인데 2,23p 로 잘라 Output 4줄이 안 나왔어요 (기존 결함). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LDjdeZ7Tjc5fhXGDpopXC6
bluecheat
force-pushed
the
feature/handoff-in-current-task-json
branch
from
September 11, 2026 13:58
272de55 to
3d33e4a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
왜
.ax/docs/STATUS.md(세션 인계 노트)는 어느 사용자 리포에도 커밋된 적 없는 세션 상태인데,.gitignore.template에는 없고(state.json·current-task.json·MEMORY.md는 있어요) 커밋되는.ax/docs/트리 한가운데 놓여 있었어요 —git add -A한 번이면 새는 자리예요. 리포 계약(CLAUDE.md"Skills update.ax/state.json… and.ax/current-task.json… do not invent new state files")을 하네스 자신이 어긴 세 번째 상태 파일이었어요.실사용에서 발견: commerce 리포 세션에서 Stop 게이트가 "인계 노트를 적어라" 고 해서
status-note.sh가STATUS.md를 만들었는데, 팀은 그 파일을 쓴 적이 없었고 리뷰에서 "이건 왜 만들었어" 로 잡혔어요.무엇이 바뀌나
status-note.sh)은 그대로, 저장 위치가.ax/current-task.json의handoff객체로 바뀌어요.status-note.sh— CLI 표면 동일(--show|--init|--add|--done|--set|--clear <절>,--json,--dry-run,--cap).--show --json의sections/counts/over_cap/exists/path불변,lines→items(네 절 항목 합),now_at추가. 줄 끝(YYYY-MM-DDTHH:MMZ)스탬프가now_at필드로 올라와요 —--set now만 갱신하고--add now는 건드리지 않아요 (게이트 침묵 창 불변).current-task.json이 없으면 변이 모드는 exit 1 로 거절해요 — 최소 파일을 만들면 MANIFEST->seed 가 영원히 막혀서요. jq 필수(없으면 exit 2).stop/spec-gate.sh— 이미 열어 둔current-task.json의handoff.now에 spec 이름 +now_at24시간으로 판정 (파일 read 하나 줄어요).subagent-start/harness-pointer.sh— handoff 에 항목이 있으면 경로만 한 줄.build-memory.sh포인터도 같은 조건(HAS_JQ가드 안).tier-from-state.sh --reset—current-task.json을 쓰는 유일한 다른 스크립트라 같은 락 문자열(goax_normalize_path(…/.ax/current-task.json).lock)을 잡아요. 필드별 null 대입 그대로라handoff는 살아남아요 (next·open·renamed 는 task 를 넘어 살아야 해요). jq 가 죽으면 원본을 두고 tmp 만 치우고 error 로 답해요.doctor-scan.sh— 인계 노트 기한(- [ ] YYYY-MM-DD)을 handoff 네 절에서 읽고, 남은.ax/docs/STATUS.md를 마이그레이션 잔재(migration.stale_status_md)로 알려요. 자동 import·삭제 없음 — 이 파일은 per-machine 상태고 내용이 설계상 일시적이라(끝난 항목은 지움,now는 24h 지나면 무효) 손으로 고친 마크다운을 파싱해 신선도까지 판정하는 코드는 새 실패 모드만 들고 와요. 필요한 줄은status-note.sh --add로 옮기고rm.changelog/0.5.11.md. 문서(CLAUDE.md · skill-routing · scripts/hooks README · triage/spec-implement/lane/zero/up/onboarding/doctor SKILL.md · templates/zero) 전부 새 저장소 기준..ax/MEMORY.md는 그대로 두는 이유STATUS.md 의 문제는 "고유 정보가 상태 파일이 아닌 곳에, gitignore 도 없이" 있었던 거예요. MEMORY.md 는 셋 다 해당하지 않아요 — 고유 정보가 없고(
build-memory.sh가 마크다운·상태에서 결정론 재생성), 이미 gitignore 돼 있고, 소비자는triage§1.0 하나예요.state.json.hud가update-state.sh의 렌더 캐시인 것과 같은 지위예요. state.json 에 접으면 수 KB 마크다운이 HUD JSON 에 들어가 3-way 동기화 규칙에 걸리고, 파일 없이 stdout 을 읽으면 재열람이 안 돼요. 이번 결정에 필요한 변경은 인계 노트 포인터 한 줄뿐이라 그것만 했어요.왜
current-task.json이고state.json이 아닌가 · 그 비용state.json은 "사용자가 편집하지 않는 렌더 캐시 SSOT"(docs/state-ownership.md)라 고유 정보를 넣으면 캐시가 아니게 되고,template + statusline.sh + ownership 표3-way 동기화에 걸리고, writer 트래픽(update-state.sh 매 skill 종료 · tasks-gate 봉인 · 인라인 jq 9곳)이 훨씬 많아요.current-task.json은 "triage→spec→audit 컨텍스트 인계" 파일이라 세션 간 인계와 같은 축이고, 읽는 훅 4곳이 이미 여는 파일이에요..ax/handoff.json별도 파일이면 셋 다 없지만 "새 상태 파일 금지" 정면 위반이라 기각): (1) 같은 파일 동시 쓰기 노출 — 스크립트 writer 둘은 같은 락으로 직렬화되지만 SKILL.md 인라인 jq 5곳은 무락이에요 (두 세션이 같은 리포를 동시에 쓸 때만, 인라인 jq 끼리는 오늘도 같은 노출 — 후속:update-task.sh로 흡수). (2) writer 가 객체를 통째로 재조립하면handoff가 조용히 사라져요 — smoke 에 "current-task.json 으로 곧장 리다이렉트 금지(in-place jq 만)" 구조 가드를 계약으로 넣었어요. (3)current-task.json이 task 를 넘어 사는 하위 객체를 하나 갖게 돼요 —reset-task.sh가handoff를 남기는 걸 문서와 smoke 로 고정했어요.행동 변화 (업그레이드하는 쪽)
status-note.sh변이 모드는current-task.json없으면 exit 1 (/up먼저). jq 없으면 exit 2 —zero-ablation.sh --on의 기한 체크박스 기록(|| true)도 조용히 같이 건너뛰어요 (예전 텍스트 모드는 awk 라 jq 없이도 됐어요).STATUS.md는 자동으로 옮기지 않아요.doctor가 잔재로 알려요.검증
bash tests/smoke.sh— 571 통과 / 0 실패 / exit 0 (main 기준선 559, +12). 재작성: §34 status-note 픽스처, §35 stop 게이트·doctor-scan·zero-ablation·SubagentStart, §41now_at신선도, §43 락 동시성(--init ×5·--add ‖ --add ×10유실 0 ·--add ‖ tier-from-state --reset ×5둘 다 생존 · dry-run 은 락도handoff도 안 만듦 · 선점current-task.json.lock앞 exit 1 — 7종). 추가: writer in-place 가드, reset 이 handoff 를 안 지움, doctorstale_status_mdfindings +1, harness-pointer 경로만·600자 미만.--set now직후 spec-gate 통과(출력 없음) →now_at을 2020 으로 바꾸면decision:block→--set now ""뒤now==[]·now_at==null.now_at이 깨진 값 7종·now가 문자열·handoff 부재 → 전부 block 으로 fall through(크래시 없음). 깨진 JSON 에서--reset→ exit 1, 원본·락 그대로.docs/state-ownership.md변경 없음, 락 문자열 두 스크립트 바이트 동일,[a-z]범위 0, 버전 마커 0, 남은STATUS.md참조는 doctor 잔재 통지(doctor-scan.sh · doctor/SKILL.md · scripts README 행 · smoke 픽스처)만.<<EOF·"$ROOT/…"리다이렉트 포착),--resetjq 실패 처리, 선점 락 7종.후속 (이 PR 밖)
current-task.json인라인 jq 5곳(triage·spec·spec-validate·spec-tasks·spec-implement)을 락 있는update-task.sh --phase <p> [--set k=v]로 흡수 — 결정론 경계 룰과 위 비용 (1) 을 같이 닫아요.tier-from-state.sh의.ax/current-task.json.template복사 fallback 정리 (설치본엔 그 파일이 없어요).🤖 Generated with Claude Code
https://claude.ai/code/session_01XgYfK9moXVF9YCRPvfg8tH