Skip to content

v0.24.0

Choose a tag to compare

@sol5288 sol5288 released this 16 Aug 18:00
· 559 commits to main since this release

업그레이드해도 새 명령이 설치본에 생기지 않던 문제를 고칩니다 — 그리고 그 사실을 아무도 말하지
않던 것을 고칩니다.

🔴 0.23.0 이전에 설치한 프로젝트라면(= init 을 0.22.x 이하로 돌린 곳) 업그레이드 후 아래 한 줄을
실행하십시오. req:repolicy·req:delegatepackage.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 의 C6req: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 --scriptspackage.jsonscripts없는 req:* 키만
    삽입합니다. --persona·--gitignore 와 같은 opt-in 축이라, 플래그가 없으면 package.json
    열지도 않습니다(공표된 "sync 는 package.json 을 건드리지 않는다"가 기본 동작으로 그대로 유지됩니다).

    • 기존 키는 값이 무엇이든 미변경입니다. req:new 를 자기 래퍼로 바꿔 두었다면 그대로 남습니다.
    • 🔴 원문을 재직렬화하지 않습니다. JSON.stringify 왕복은 기존 값의 표현을 바꿉니다
      ("node .\/build""node ./build" · 1e+01). 원문에 텍스트로 끼워 넣어 들여쓰기 · 키 순서 ·
      말미 공백과 빈 줄 · BOM · 개행 형태
      를 보존하므로, diff 가 삽입한 키로 한정됩니다.
    • 계획과 적용이 같은 판정을 씁니다: 존재 판정(k in scripts — 값이 null 이어도 부재가 아닙니다) ·
      키를 JSON 의미로 디코드("scripts"scripts) · 중복 최상위 scriptsJSON.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

  • 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-proof series-terminal). 판정에서 빼는 것만으로는 부정확한 lifecycle
    레코드가 영원히 남아 해소할 수 없는 경고가 되기 때문입니다.

    • 🔴 승인 문장을 요구하지 않습니다. --resolve replace 는 사람 판단이라 --confirm 이 필요하지만,
      이쪽은 "그 phase 가 phases[] 에 없다"도구가 검증하는 사실입니다. --reason 은 요구합니다.
    • 🔴 살아 있는 phase 의 series 는 거부합니다 — 닫아 주면 필요한 리뷰를 건너뛰는 길이 됩니다.
    • 🔴 orphaned 는 티켓 종결이 아닙니다 — 그러지 않으면 진행 중인 티켓이 series-terminal 로 판정되어
      req:doctor 의 종결 면제(D2·D3·D11)가 잘못 붙습니다. 기존 replace·human-resolution 의 의미는 그대로입니다.
    • 재실행은 수렴합니다(이미 닫혔으면 쓰지 않고 그 사실을 말합니다).
  • feat: req:doctor D34 — 열린 orphan series 를 통합 전에 WARN 으로 알리고 해소 명령을 냅니다
    (통합은 막지 않습니다). 실측에서 이 사실은 통합 시점에야 드러났습니다.

    • 🔴 해소 명령의 인자는 커밋된 state 에서 오므로 셸 안전 관문을 통과할 때만 렌더링합니다 —
      안전하지 않으면 명령 대신 값을 보여 줍니다(명령 주입 방지).
  • docs: 업그레이드 절차에 명령 표면 축 추가 — 요약이
    설치 → sync --apply --scripts → quickstart --apply → check 로 바뀝니다(한/영).