v0.24.0
업그레이드해도 새 명령이 설치본에 생기지 않던 문제를 고칩니다 — 그리고 그 사실을 아무도 말하지
않던 것을 고칩니다.🔴 0.23.0 이전에 설치한 프로젝트라면(=
init을 0.22.x 이하로 돌린 곳) 업그레이드 후 아래 한 줄을
실행하십시오.req:repolicy·req:delegate가package.json에 없습니다.npx commitgate sync --apply --scripts
-
fix: 릴리스가 추가한
req:*명령이 기존 설치본에 생기지 않던 문제 —req:*스크립트는init이
설치 시점에 주입합니다. 그래서 새 verb(req:repolicy·req:delegate— 둘 다 0.23.0 도입)가 추가돼도
기존 프로젝트의package.json에는 그 키가 없었고, 문서화된 업그레이드 절차
(설치 → sync --apply → quickstart --apply → migrate)에는init재실행이 없어 절차를 정확히 따라도
도달할 수 없었습니다.- 드러나는 방식이 문제였습니다.
req:next가 통합 통제점에서 정확히 그 명령을 안내하는데:사람 승인을 받은 직후, 통제점을 통과시키는 바로 그 명령이 실패했습니다.승인 후 실행: $ pnpm req:delegate --scope ticket:REQ-2026-242 … --run → ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command "req:delegate" not found - 🔴 어떤 진단도 말하지 않았습니다:
commitgate check는 C1~C5 PASS,req:doctor는
OK D19: 설치 모드: Stage B,commitgate sync는변경 없음이었습니다. - 이제
commitgate check의 C6 와req:doctor의 D33 이 부족한 verb 를 이름으로 말하고
해소 명령을 안내합니다(둘 다 WARN — 커밋을 막지 않습니다). 개발 저장소(dogfood)는 점검하지 않습니다. - 🔴 D19 는 이 축을 판정할 수 없습니다. D19 는 설치 모드(Stage A/B)를 5개 표본 키의 값 형태로
보고 부재 키는 걸러내므로,req:delegate가 없어도OK D19: Stage B입니다. 질문이 다릅니다 —
그래서 D19 를 고치지 않고 별도 체크를 뒀습니다(한 체크에 두 질문을 섞으면 한쪽 답이 다른 쪽을 가립니다). - 🔴 0.23.1 이 이 상태를 만들지 않았습니다. 0.23.0 이 verb 둘을 추가했고, 그 이전에
init을 돌린
설치본은 그때부터 부족했습니다. 이번 릴리스가 하는 일은 그 사실을 말하고 채울 수단을 주는 것입니다.
확인할 파일:
scripts/req/lib/command-surface.ts(판정·입력 획득·안내의 정본) ·
bin/check.ts(C6) ·scripts/req/req-doctor.ts(D33) ·
tests/unit/doctor-command-surface-wiring.test.ts(배선 e2e — 순수 테스트가 못 잡는 축) - 드러나는 방식이 문제였습니다.
-
feat:
commitgate sync --apply --scripts—package.json의scripts에 없는req:*키만
삽입합니다.--persona·--gitignore와 같은 opt-in 축이라, 플래그가 없으면package.json을
열지도 않습니다(공표된 "sync 는 package.json 을 건드리지 않는다"가 기본 동작으로 그대로 유지됩니다).- 기존 키는 값이 무엇이든 미변경입니다.
req:new를 자기 래퍼로 바꿔 두었다면 그대로 남습니다. - 🔴 원문을 재직렬화하지 않습니다.
JSON.stringify왕복은 기존 값의 표현을 바꿉니다
("node .\/build"→"node ./build"·1e+0→1). 원문에 텍스트로 끼워 넣어 들여쓰기 · 키 순서 ·
말미 공백과 빈 줄 · BOM · 개행 형태를 보존하므로, diff 가 삽입한 키로 한정됩니다. - 계획과 적용이 같은 판정을 씁니다: 존재 판정(
k in scripts— 값이null이어도 부재가 아닙니다) ·
키를 JSON 의미로 디코드("scripts"도scripts) · 중복 최상위scripts는JSON.parse가
채택하는 마지막 것.
- 기존 키는 값이 무엇이든 미변경입니다.
-
docs:
commitgate delivery묶음이stopGate: "merge"전용인 것처럼 적혀 있던 문제 — 코드의 정본은
defersToIntegration('merge' | 'auto')이고auto도 커밋 단계·종단 판정이 같습니다. 그래서auto
사용자는 정지 횟수를 가장 크게 줄이는 조합(묶음)을 문서에서 볼 수 없었습니다.- 티켓마다 개별 통합하면 사람이 멈추는 자리가 티켓 수만큼이지만, 묶음은 3회로 고정입니다 —
seal확인 ·approve확인 · 통합 승인(I1/I2또는B1). 멤버 수와 무관하고merge·auto가
같습니다. 티켓·phase 크기를 바꾸지 않으므로 리뷰 면적은 그대로입니다. - 🔴 HIGH member 는 예외입니다:
delivery integrate전에 그 티켓의req:confirm --scope delivery
가 따로 필요하며--high-risk위임으로도 대체되지 않습니다 → 3 + HIGH member 수. - 🔴 묶음의 마지막 병합은
auto여도 사람이 합니다.commitgate integrate는 feature→trunk 명령이라
기본branchPrefix(feat/req-)에서delivery/<slug>는 전제에서 걸러집니다. - 회귀 가드가 문자열만 보지 않습니다 —
planIntegration에 delivery 브랜치를 넣어 전제가 실제로
거부함을 확인하고 그 사실과 문서 서술을 함께 묶습니다.
확인할 파일:
docs/workflow.md·docs/workflow.en.md(delivery 절) ·bin/delivery.ts(help) ·
tests/unit/delivery-stopgate-docs.test.ts - 티켓마다 개별 통합하면 사람이 멈추는 자리가 티켓 수만큼이지만, 묶음은 3회로 고정입니다 —
-
fix: phase 를 개명·재정렬하면
stopGate: "auto"자율 통합이 영구 차단되던 문제 — 리뷰 지적을 따라
mid-ticket 으로 phase 이름을 바꾸면state.json의 옛 series 레코드가closed_reason: null로 남습니다.
attempt 는 전부 닫혔는데 series 레코드만 열려 있고,commitgate integrate가 그것을
reviewInconclusive로 세어 위임이 있어도 거부했습니다:사전 위임이 이 통합을 허용하지 않습니다 (review-inconclusive)- 🔴 나가는 길이 없었습니다.
--close-stale은 열린 attempt 축이라버릴 열린 attempt 가 없다로
거부하고,--resolve replace는 "successor REQ 로 대체" 라는 다른 의미입니다. - 게이트가 옳게 거부한 것이 아닙니다.
phases[]에 없는 phase 의 열린 series 는 현재 phase 들이
검수됐는지에 대해 아무것도 말하지 않습니다 — 존재하지 않는 phase 에는 소비될 승인이 없습니다.
그래서 사람 승인 탈출구를 만드는 대신 판정에서 제외했습니다(정상 행위마다 통제점을 늘리지 않습니다). - 🔴 우회가 열리지 않습니다: 승인 증거는 phase 별이라 새 이름의 phase 는 자기 승인을 새로 받아야 하고,
리뷰 예산 축(hardCap)은 orphan 도 그대로 셉니다 — 개명으로 예산이 리셋되지 않습니다.
- 🔴 나가는 길이 없었습니다.
-
feat:
req:review-exception --close-orphan— 사라진 phase 의 series 를 기록으로 종결합니다
(closed_reason: 'orphaned'+ close-proofseries-terminal). 판정에서 빼는 것만으로는 부정확한 lifecycle
레코드가 영원히 남아 해소할 수 없는 경고가 되기 때문입니다.- 🔴 승인 문장을 요구하지 않습니다.
--resolve replace는 사람 판단이라--confirm이 필요하지만,
이쪽은 "그 phase 가phases[]에 없다" 는 도구가 검증하는 사실입니다.--reason은 요구합니다. - 🔴 살아 있는 phase 의 series 는 거부합니다 — 닫아 주면 필요한 리뷰를 건너뛰는 길이 됩니다.
- 🔴
orphaned는 티켓 종결이 아닙니다 — 그러지 않으면 진행 중인 티켓이series-terminal로 판정되어
req:doctor의 종결 면제(D2·D3·D11)가 잘못 붙습니다. 기존replace·human-resolution의 의미는 그대로입니다. - 재실행은 수렴합니다(이미 닫혔으면 쓰지 않고 그 사실을 말합니다).
- 🔴 승인 문장을 요구하지 않습니다.
-
feat:
req:doctorD34 — 열린 orphan series 를 통합 전에 WARN 으로 알리고 해소 명령을 냅니다
(통합은 막지 않습니다). 실측에서 이 사실은 통합 시점에야 드러났습니다.- 🔴 해소 명령의 인자는 커밋된
state에서 오므로 셸 안전 관문을 통과할 때만 렌더링합니다 —
안전하지 않으면 명령 대신 값을 보여 줍니다(명령 주입 방지).
- 🔴 해소 명령의 인자는 커밋된
-
docs: 업그레이드 절차에 명령 표면 축 추가 — 요약이
설치 → sync --apply --scripts → quickstart --apply → check로 바뀝니다(한/영).