Skip to content

release: 0.5.12 — 상태 파일을 쓰는 SKILL.md 인라인 jq 가 무락이던 것 (update-task.sh · update-state.sh --skill · goax_help) - #14

Merged
bluecheat merged 5 commits into
mainfrom
feat/update-task-script
Sep 11, 2026
Merged

bluecheat merged 5 commits into
mainfrom
feat/update-task-script

Conversation

@bluecheat

@bluecheat bluecheat commented Sep 11, 2026 •

Copy link
Copy Markdown
Owner

왜

0.5.11 이 인계 노트를 current-task.json 의 handoff 로 옮기면서 남긴 비용 (1) — status-note.sh 는 락을 잡고 쓰는데 phase 를 바꾸는 SKILL.md 인라인 jq 5곳 8군데는 무락이라, 두 세션이 같은 리포를 쓰면 handoff 항목이 lost-update 로 사라지는 창이 남아 있었어요. 리뷰에서 같은 결함이 state.json 에도 있는 게 드러났어요 — update-state.sh · tasks-gate.sh(task_seal) 는 락을 잡는데 skill 마무리의 last_skill·skill_calls 인라인 jq 12곳은 무락.

무엇이 바뀌나

  • update-task.sh (신규, 37번째) — current-task.json task 필드를 락 안에서 in-place. --phase · --set k=v · --blocked-by · --merge-intent · --start · --json · --dry-run. enum(phase·size·risk·spec_tier) 검증 실패, 빈 값, 옵션 토큰이면 아무것도 안 쓰고 exit 1. 락 문자열은 status-note.sh · tier-from-state.sh --reset 과 바이트 동일.
  • update-state.sh --skill <name> [--last-mistake <file>] — last_skill·skill_calls+=1·last_mistake_file 을 derived 와 같은 락·같은 쓰기 안에서. --json/--dry 와 같이 주면 경고.
  • SKILL.md 인라인 jq 20군데 (current-task 8 · state 12) 가 전부 스크립트 호출 한 줄로.
  • tier-from-state.sh --reset — current-task.json.template 복사 fallback 제거 (설치본엔 없는 파일). 파일 없으면 exit 1 · jq 없으면 exit 2 (예전엔 둘 다 조용히 ok).
  • goax_help — 출고 스크립트 36개의 --help 가 sed -n '2,NNp'(큰따옴표 1곳 · 사설 awk 2곳 포함)로 줄 번호를 손으로 들고 있었고 실측 19개가 어긋나 있었어요 (Exit: 계약 잘림 / set -euo 누출). 헬퍼 하나로 통일, reset-task.sh --help 는 자기 헤더.
  • smoke writer_contract — 상태 파일 둘 × (skills/agents 전면 금지, 스크립트 허용 목록), 변수 경로(F=…; > "$F.tmp", FILE=…; REL=…, X=… # 주석) 검출 포함. 호출 엣지 8+12곳 고정. --help 줄 범위(따옴표 양쪽)·사설 awk 0개 + 36개 헤더 끝까지 일치.

검증

  • bash tests/smoke.sh — 592 통과 / 0 실패 (0.5.11 기준선 572 → +20)
  • 새 컨텍스트 code-reviewer(opus) 리뷰 3회전 — 1차 8건 · 2차 3건 · 3차 3건 전부 반영, 최종 verdict: 진행
  • 심은 위반 6종(변수 경로 3꼴 · 직접 경로 · SKILL.md 인라인 · 읽기 전용 오탐 없음)이 writer_contract 에 의도대로 판정되는 것 확인

후속

없음.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LDjdeZ7Tjc5fhXGDpopXC6

bluecheat and others added 5 commits September 11, 2026 23:18
….sh)

0.5.11 이 인계 노트를 current-task.json 의 handoff 로 옮기면서 남긴 비용 — 같은 파일을 status-note.sh 는
락을 잡고 쓰는데 phase 를 바꾸는 SKILL.md 인라인 jq 5곳 8군데는 무락이라, 두 세션이 같은 리포를 쓰면
handoff 항목이 lost-update 로 사라지는 창이 남아 있었어요.

- update-task.sh 신설 — current-task.json 의 task 필드를 락 안에서 in-place 갱신. --phase · --set k=v ·
  --blocked-by · --merge-intent · --start · --json · --dry-run. enum(phase·size·risk·spec_tier) 은 case 로
  검증하고 틀리면 아무것도 안 써요. 락 문자열은 status-note.sh · tier-from-state.sh --reset 과 바이트 동일.
- triage · spec · spec-validate · spec-tasks · spec-implement 의 인라인 jq 8군데 → update-task.sh 호출.
- tier-from-state.sh --reset — current-task.json.template 복사 fallback 제거 (설치본엔 없는 파일).
  파일 없으면 exit 1 · jq 없으면 exit 2 (예전엔 둘 다 조용히 ok).
- smoke — skills·agents 의 current-task.json 쓰기 전면 금지, 출고 writer 셋 고정, 호출 엣지 8곳,
  update-task ‖ status-note 동시 5회, 선점 락 8종, dry-run 8종. 581 통과 / 0 실패 (기준선 572).
- bump-version.sh 가 result.files.VERSION 에 쓰기 전 값을 찍던 것 정정 (메인테이너 스킬).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LDjdeZ7Tjc5fhXGDpopXC6
출고 스크립트 32개가 `sed -n '2,NNp'` 로 헤더 범위를 하드코딩했고, 헤더가 자라면 `Exit:` 계약 줄이 잘리고
줄면 `set -euo pipefail` 까지 --help 에 찍혔어요. common.sh 에 goax_help(헤더 주석 블록을 첫 비-# 행
전까지 그대로) 를 두고 전부 바꿨어요. smoke 가 (1) 줄 범위 방식 0개 (2) 스크립트마다 --help 마지막 줄 ==
헤더 마지막 줄을 검사해요. 583 통과 / 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LDjdeZ7Tjc5fhXGDpopXC6
…값·옵션 토큰 거절, writer 가드 변수 경로

리뷰어(새 컨텍스트 opus) 지적 8건 전부:
- update-state.sh --skill <name> [--last-mistake <file>] — last_skill·skill_calls·last_mistake_file 을 derived 와
  같은 락·같은 쓰기 안에서. SKILL.md 12곳의 `jq '.last_skill = …' state.json > tmp && mv` 를 전부 한 줄로.
  update-state.sh 를 먼저 부르고 메타만 따로 쓰던 곳은 호출 두 번이 한 번으로.
- update-task.sh — --phase/--set/--blocked-by/--merge-intent 값이 비었거나 다음 토큰이 옵션이면 exit 1
  (예전엔 updated_at 만 조용히 쓰고 ok; spec-validate 가 BLOCKED 비워 보내면 phase 만 넘어갔어요).
  옵션 토큰을 값으로 안 삼켜 `--set --json` 도 봉투. --phase idle 거절. --merge-intent '{}' 는 changed 에 안 뜸.
- smoke writer_contract — 파일 둘(current-task.json · state.json) × (skills/agents 전면 금지, 스크립트 허용 목록)
  + 변수 경로(`F=…; > "$F.tmp"`) 검출. 심은 위반 3종(변수 경로·직접 경로·SKILL.md 인라인) 전부 잡히는 것 확인.
- §8 jq 문법 검사 → update-state.sh --skill 호출 엣지 12곳. CONCEPTS.md 36 → 37.
smoke 592 통과 / 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LDjdeZ7Tjc5fhXGDpopXC6
…헤더, 가드 정규식 확장

리뷰어 2차 지적: check-spec-clarity.sh 가 `sed -n "2,33p"`(큰따옴표)라 가드가 못 봤고, build-memory.sh 는
같은 awk 를 사설로 들고 있어 per-script 검사 밖이었어요. 둘 다 goax_help 로. reset-task.sh --help 는 exec 로
넘어가 tier-from-state 헤더를 찍던 것 → 자기 헤더. goax_help 정의가 goax_normalize_path 문서 블록 안에
끼어 있던 것 → goax_error 옆으로. smoke 가드는 따옴표 양쪽 + 사설 awk 복사본까지 막아요. 36/37 (common.sh 제외 전부).
smoke 592 통과 / 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LDjdeZ7Tjc5fhXGDpopXC6
…--json+--skill 경고

- writer_contract 의 변수 대입 정규식이 줄 끝 앵커라 `FILE=…; REL=…` · `TASK_FILE=… # 주석` · `CT=…; OUT=…` 꼴이
  빠져나갔어요 (update-task.sh 의 정확한 모양이라 새 스크립트로 복사되면 가드가 못 봤어요). 뒤에 `;`·`#`·공백이
  와도 대입으로 봐요. `(` 는 빼서 `X=$(jq … .json)` 읽기는 안 잡아요. 심은 3꼴 전부 잡히고 읽기 전용은 안 잡혀요.
- 새로 쓴 `[A-Za-z_][A-Za-z0-9_]*` → `[[:alpha:]_][[:alnum:]_]*` (CLAUDE.md 브래킷 범위 금지).
- update-state.sh — `--json`/`--dry` 는 파일을 안 쓰는 모드라 `--skill` 을 같이 주면 조용히 안 찍혔어요. goax_warn.
smoke 592 통과 / 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LDjdeZ7Tjc5fhXGDpopXC6
@bluecheat
bluecheat merged commit 7309a57 into main Sep 11, 2026
@bluecheat
bluecheat deleted the feat/update-task-script branch September 11, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant