Skip to content

fix(ci): 릴리스 QA 구조화 입력 게이트 — PR 단위 QA 원천 강제 (#809 1·2) [base: develop] - #810

Merged
OnlyReadOneBook merged 13 commits into
developfrom
feat/809
Aug 26, 2026
Merged

OnlyReadOneBook merged 13 commits into
developfrom
feat/809

Conversation

@OnlyReadOneBook

@OnlyReadOneBook OnlyReadOneBook commented Aug 21, 2026 •

Copy link
Copy Markdown
Collaborator

📌𝘐𝘴𝘴𝘶𝘦𝘴

Closes #809

이슈 범위를 이 PR 의 범위(PR 단위 구조화 입력 게이트)로 축소했다 — 원 완료조건 3·4 는 토대가 사라져 제외했고, 근거는 #809 코멘트에 남겼다.

📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯

  • PR 본문의 QA 원천을 JSON 으로 구조화하고, 누락·placeholder·generic fallback 문구를 Unit Test 에서 차단한다.
  • 릴리스 노트 렌더러도 generic fallback 문구를 거부한다 — 사람이 옛 문구를 복붙하는 경로를 막는다.
  • 게이트 도입 전 생성 PR 은 섹션이 없으면 건너뛴다(QA_METADATA_GATE_CUTOFF). 리베이스로 워크플로를 받아도 소급 차단되지 않는다.

AI 의미 감사(#809 원 완료조건 3·4)를 범위에서 뺀 이유

develop 이 deployment-decision.yml 을 걷어냈다 (d657a04). 판정 16건이 전부 같은 값이었고 dispatch 실행이 3건뿐이라 "판정은 쓰이지 않았다" 는 실측이 근거였고, 배포 시점은 릴리스 PR 을 여는 사람이 정하는 것으로 확정됐다. 이 PR 의 AI 감사는 그 판정 위에 얹혀 있었다.

토대가 사라졌고 COPILOT_PERSONAL_TOKEN 도 미등록이라, 지금 머지해도 항상 human_review_required 로만 끝난다. 그래서 감사 쪽(Copilot 호출·plan strict validation·finalizeDeploymentDecision·PR #802 fixture, 약 1,400줄)을 걷어내고 게이트만 남겼다.

남은 게이트는 develop 방향과 오히려 보완적이다 — release-scope.yml 이 "QA 포인트는 비어 있을 때만 초안을 채우고 사람이 쓴 문장은 보존" 으로 갔으므로, 그 초안의 원천 품질을 PR 단위에서 강제하는 쪽이 값이 있다.

항목 이전 지금
develop 대비 추가 1,814줄 575줄
qa-semantic-audit.mjs 777줄 → qa-metadata.mjs 230줄 (파싱·검증만)
스크립트 테스트 14개 8개 (감사 테스트 6개 제거)

🧪 QA Metadata

{
  "scope": "ci-only",
  "exclusionReason": "PR 검증 워크플로와 릴리스 노트 렌더러만 바꾸며 APK 사용자 흐름은 변경하지 않는다",
  "evidence": [
    {
      "kind": "test",
      "ref": ".github/scripts/qa-metadata.test.mjs",
      "assertion": "구조화 필드 누락·generic fallback·제외 근거 부족을 실패로, cutoff 이전 생성 PR 을 건너뜀으로 고정한다",
      "input": "runnable·exclusion 메타데이터와 created_at 이 cutoff 앞뒤인 pull_request 이벤트",
      "boundary": "본문 섹션 파싱부터 워크플로 오류 annotation 과 종료 상태까지",
      "observation": "node --test 가 110개 스크립트 테스트 전부의 통과를 단언한다"
    },
    {
      "kind": "ci",
      "ref": "Unit Test / Validate structured QA metadata",
      "assertion": "열린 PR 전수에서 게이트가 의도한 대상만 검증한다",
      "input": "열린 PR 53건의 실제 본문·생성 시각",
      "boundary": "grandfather 판정부터 구조화 필드 검증까지",
      "observation": "FAIL 0건 — 이 PR 만 검증을 받고 나머지 52건은 건너뛴다"
    }
  ]
}

📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵

  • 해당 없음 (CI·문서 변경)

💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴

@Sadturtleman 지적하신 blocking — 게이트가 열린 PR 을 무더기로 떨어뜨리는 문제입니다. 2안(grandfather)으로 갔고, cutoff 를 실측해서 다시 밀었습니다.

8/24 로 두면 그 뒤 열린 PR 22건이 리베이스하는 순간 막힙니다. 8/26 으로 밀어 열린 PR 53건에 전수로 돌린 결과입니다.

PASS = 1   (#810 — 이 PR 자신)
SKIP = 52  (게이트 도입 전 생성 — 섹션이 없으면 건너뜀)
FAIL = 0

재현 (이 브랜치 기준):

gh pr view <N> --json number,body,createdAt --jq '{pull_request:{number:.number, body:.body, created_at:.createdAt}}' > event.json
node .github/scripts/validate-pr-qa-metadata.mjs event.json

created_at 을 넘겨야 grandfather 가 동작합니다 — 이전 재현 절차에는 그 필드가 빠져 있어 전부 FAIL 로 보였습니다.

머지가 8/26 을 넘기면 넘긴 만큼 cutoff 를 다시 밀어야 합니다. 그 뒤로는 템플릿을 채운 신규 PR 만 대상이 됩니다 (템플릿을 그대로 내면 placeholder 라 떨어집니다 — 의도).

검증:

  • node --test .github/scripts/*.test.mjs — 110/110
  • 워크플로 YAML 18개 파싱
  • 열린 PR 53건 전수 게이트 실행 (위 결과)

@OnlyReadOneBook OnlyReadOneBook added bug Something isn't working internal labels Aug 21, 2026
@OnlyReadOneBook
OnlyReadOneBook marked this pull request as ready for review August 21, 2026 09:00
@OnlyReadOneBook OnlyReadOneBook changed the title fix(ci): 릴리스 QA 구조화 입력·AI 의미 감사 (#809) [fix] #809 릴리스 QA 구조화 입력·AI 의미 감사 Aug 21, 2026
Base automatically changed from feat/804 to develop August 21, 2026 19:53

@Sadturtleman Sadturtleman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구조화 QA 원천을 강제하는 방향 자체에는 동의합니다 — generic fallback 문구가 QA 를 통과하던 구멍을 닫는 게 #809 의 요지고, qa-semantic-audit.mjs 의 strict validation 과 fail-closed(human_review_required → hold, 배포 미실행) 설계도 맞습니다.

다만 전개 비용이 측정되지 않은 채로 필수 검사에 붙습니다. 그 1건만 적습니다.

[blocking] 이 게이트가 현재 열린 PR 48개 중 47개를 떨어뜨립니다

validate-pr-qa-metadata.mjs 를 이 브랜치에서 꺼내 실제 열린 PR 본문 전수에 돌려 봤습니다.

PASS = 1   (#810 — 이 PR 자신)
FAIL = 47  886 885 883 882 880 879 878 877 876 874 871 870 869 868 867 865 864
           863 862 861 857 856 855 854 853 834 833 832 831 830 829 828 827 826
           825 824 823 822 821 820 819 807 771 767 741 721 440

전부 같은 사유입니다.

::error title=구조화 QA 메타데이터 오류::PR #877: `QA 메타데이터` 섹션이 없습니다.

재현 방법 (이 브랜치 기준):

gh pr view <N> --json number,body \
  --jq '{pull_request:{number:.number, body:.body}}' > event.json
node .github/scripts/validate-pr-qa-metadata.mjs event.json

unit-test.yml 에서 이 단계가 Run deployment script tests 앞, 즉 Unit Test job 의 첫 검증으로 들어가 있어 실패하면 job 전체가 빨간불이 됩니다.

당장 47개가 동시에 빨개지진 않습니다 — 다만 시간 문제입니다

pull_request 이벤트는 워크플로 정의를 head 브랜치에서 읽으므로, 기존 PR 들은 develop 을 끌어오기 전까지 옛 unit-test.yml 로 계속 돕니다. 문제는 이 레포가 리베이스를 매우 자주 한다는 겁니다 — 당장 #819→#831 스택 13개는 앞 PR 이 머지될 때마다 순차로 리베이스해야 하고, 그 순간부터 본문을 고치기 전엔 머지가 막힙니다.

부담이 작지 않습니다

ci-only / covered-by-ci 로 빠지는 경우에도 exclusionReason 과 동일 input·boundary·observation 을 단언하는 ci/test evidence 1건 이상이 필요합니다(qa-semantic-audit.mjs:232-241). #871 처럼 gradle.properties 중복 한 줄을 지우는 PR 에도 같은 블록을 채워야 합니다.

제안

셋 중 하나면 충분해 보입니다.

  1. 한시적 warn-only — 일정 기간 ::warning:: 으로만 내고 process.exitCode 를 세우지 않다가 기존 PR 이 소진되면 켭니다. #833 이 "경고만 남길 거면 워크플로를 지우는 편이 정직하다" 고 한 것과 상충해 보일 수 있는데, 저기는 영구 경고고 여기는 전환 기간이라 성격이 다릅니다.
  2. 기준 시점으로 grandfather — PR 생성 시각이나 번호가 컷오프 이전이면 건너뜁니다. 스크립트에 event.pull_request.created_at 이 이미 들어와 있어 몇 줄이면 됩니다.
  3. 머지 전 일괄 정비 — 47개 본문을 먼저 채우고 게이트를 켭니다. 가장 깨끗하지만 이 PR 이 그만큼 대기합니다.

어느 쪽을 택하실지, 혹은 47개 동시 정비를 이미 감안하신 것인지만 알려주시면 다시 보겠습니다. 의도된 비용이라면 그 판단을 존중합니다 — 다만 PR 본문에 근거가 없어 리뷰에서 확인할 방법이 없었습니다.

그 밖에 확인한 것

  • PULL_REQUEST_TEMPLATE.md 에 app-runtime 기본형과 제외 경로 안내를 함께 넣으신 것 — 신규 PR 은 템플릿만 채우면 통과합니다. 파일 끝 개행도 같이 정리됐고요.
  • validatePullRequestEvent 가 pull_request 가 아닌 이벤트에서 skipped 로 빠져 push·schedule 실행을 막지 않습니다.
  • escapeWorkflowCommand 가 %·CR·LF 를 이스케이프해 여러 줄 오류가 annotation 을 깨지 않습니다.
  • Copilot token·호출·응답 검증 중 하나라도 실패하면 hold 로 닫고 Firebase 배포를 실행하지 않는 fail-closed 구조.
  • 모델이 정본의 사전조건·행동·기대 결과·위험·근거를 수정하지 못하게 strict validation 을 건 것 — 감사 대상이 감사 결과를 고칠 수 있으면 감사가 아니게 되니 맞는 제약입니다.
  • Node 테스트 28개와 #805 기준점 fixture.

@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator Author

리뷰 반영했습니다 — ecfc9aa. 제안 2번(grandfather)을 택했습니다.

[blocking] 열린 PR 47/48 차단

QA_METADATA_GATE_CUTOFF = 2026-08-24T00:00:00Z 이전에 생성된 PR은 QA 메타데이터 섹션이 없으면 검증을 건너뛰고 ::notice::만 남깁니다. 세부:

실측 — 말씀하신 방법대로 현재 열린 PR 전수(46개)의 실제 본문·생성 시각을 수정된 검증기에 돌렸습니다:

검증 통과 1 (#810 자신) / grandfather 건너뜀 45 / FAIL 0
  • node --test .github/scripts/*.test.mjs 32/32 (grandfather 경계 테스트 4건 추가)
  • actionlint 통과
  • README·unit-test.yml 주석에 컷오프 규칙을 문서화했습니다.

컷오프 이후 생성되고 head가 새 워크플로를 가진 PR부터 강제되는데, 기본 브랜치가 develop이라 이 PR이 머지되는 즉시 새 PR 템플릿이 노출되어 신규 PR은 템플릿만 채우면 됩니다.

@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator Author

CI 참고 — 방금 실패한 Run Unit Tests는 이번 반영 커밋(ecfc9aa)과 무관합니다.

@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator Author

#842 불변식 충돌을 해소했습니다 — 9672f2c (develop 머지 5410990 포함).

deployment-decision.yml을 develop push 트리거로 전환

pull_request 워크플로에 COPILOT_PERSONAL_TOKEN을 두는 대신, 트리거를 push: branches: [develop]로 바꿔 불변식을 그대로 지켰습니다.

  • 새 resolve job이 push SHA로 listPullRequestsAssociatedWithCommit을 조회해 merge_commit_sha가 pushed SHA와 일치하는 develop 대상 PR만 인정합니다. 머지 PR이 없는 직접 push는 notice를 남기고 판단을 건너뜁니다.
  • github.event.pull_request 참조 6곳을 전부 제거했습니다 — checkout ref는 github.sha, PR 번호는 needs.resolve.outputs.pr_number로 흐릅니다. workflow_dispatch 재판단 경로는 그대로입니다.
  • merge·squash·rebase 세 방식 모두 pushed HEAD가 PR의 merge_commit_sha와 일치하므로 복원이 성립합니다. 한 push에 여러 머지가 섞이는 경우(수동 일괄 push)는 HEAD의 PR만 복원되지만, collect가 마지막 배포 기준점 이후 누적 PR을 읽으므로 다음 판단에 합류합니다.

검증

  • develop 머지 직후 로컬에서 CI와 동일한 실패(create-ci-config.test.mjs의 secretless 불변식 1건)를 재현했고, 전환 후 node --test 79/79 통과입니다. 워크플로 내용 단언 테스트에 push 트리거·pull_request: 부재·resolve 배선 assertion을 추가했습니다.
  • resolve 로직 실데이터 드라이런: develop 머지 커밋 db42c469 → ci: lint 워크플로 Gradle 캐싱 소유자 통일 — 정책 테스트 모순으로 죽던 Run Unit Tests 복구 #913 정확 복원, PR 내부 일반 커밋 449aaf31 → 스킵.
  • actionlint·git diff --check 통과. #810이 추가한 job들의 액션 버전도 develop 상향분(checkout@v7, github-script@v9)에 맞췄습니다.

@github-actions github-actions Bot added the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

이 PR 은 develop 와 충돌 상태이고, 그래서 CI 가 돌지 않는다.

pull_request 워크플로는 base 와 head 를 합친 가상 머지 커밋(refs/pull/<N>/merge)에서
실행되는데, 충돌이면 GitHub 이 그 ref 를 만들지 못해 워크플로가 트리거조차 되지 않는다.
체크가 실패하는 것이 아니라 아예 생성되지 않으므로, 새 커밋을 올려도 no checks reported
인 채 최신 커밋이 한 번도 검증되지 않은 상태로 남는다 (#1028).

develop 를 병합해 충돌을 풀면 검증이 다시 돈다. 해소되면 이 라벨은 자동으로 떨어진다.

develop 이 deployment-decision.yml 을 걷어냈다 (d657a04). 판정 16건이 전부
같은 값이었고 dispatch 실행이 3건뿐이라 "판정은 쓰이지 않았다" 는 실측이 근거였고,
배포 시점은 릴리스 PR 을 여는 사람이 정하는 것으로 확정됐다.

이 브랜치의 AI 의미 감사(#809 완료조건 3)는 그 판정 위에 얹혀 있었다. 토대가
사라졌고, COPILOT_PERSONAL_TOKEN 도 미등록이라 지금 머지해도 항상
human_review_required 로만 끝난다. 그래서 감사 쪽을 걷어낸다.

- 삭제: deployment-decision.yml, evaluate-deployment-decision.mjs(+test)
- 삭제: qa-semantic-audit 의 감사 절반 — Copilot 호출·plan strict validation·
  finalizeDeploymentDecision·PR #802 fixture
- collect-release-scope-context.mjs 는 develop 판(릴리스 PR 기준 필드) 채택.
  게이트는 GITHUB_EVENT_PATH 만 읽어 이 파일과 무관하다.

남는 것은 완료조건 1·2 다 — PR 단위 구조화 QA 원천과 결정적 게이트. develop 이
"QA 포인트는 사람이 쓴다" 로 간 만큼 그 입력 품질을 PR 에서 강제하는 쪽이 오히려
서로 보완한다.

- qa-semantic-audit.mjs 777줄 -> qa-metadata.mjs 230줄 (파싱·검증만, 죽은 심볼 제거)
- qa-semantic-audit.test.mjs 14개 -> qa-metadata.test.mjs 8개 (감사 테스트 6개 제거)
- validate-pr-qa-metadata.mjs, unit-test.yml 게이트, PR 템플릿, 릴리스 노트의
  generic fallback 차단은 그대로

grandfather cutoff 를 8/24 -> 8/26 으로 민다. 8/24 로 두면 그 뒤 열린 PR 22건이
리베이스하는 순간 막힌다 (전수 실측). 8/26 기준으로는 열린 PR 53건 중 FAIL 0건 —
#810 자신만 검증을 받고 나머지 52건은 건너뛴다.

검증: node --test .github/scripts/*.test.mjs 110/110, 워크플로 YAML 18개 파싱,
열린 PR 53건 전수 게이트 실행.
@OnlyReadOneBook OnlyReadOneBook changed the title [fix] #809 릴리스 QA 구조화 입력·AI 의미 감사 fix(ci): 릴리스 QA 구조화 입력 게이트 — PR 단위 QA 원천 강제 (#809 1·2) [base: develop] Aug 24, 2026
@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator Author

@Sadturtleman @koongmai 재리뷰 부탁드립니다. 지적하신 blocking 과 별개로 PR 범위가 크게 줄어서, 본문을 다시 쓰고 제목도 바꿨습니다.

1. AI 의미 감사를 철회했습니다 (1,814줄 → 575줄)

리뷰해 주신 뒤에 develop 이 deployment-decision.yml 을 걷어냈습니다 (d657a04). 판정 16건이 전부 같은 값이었고 workflow_dispatch 실행이 3건뿐이라 "판정은 쓰이지 않았다" 는 실측이 근거였고, 배포 시점은 릴리스 PR 을 여는 사람이 정하는 것으로 확정됐습니다.

이 PR 의 감사는 그 판정 위에 얹혀 있었습니다. 토대가 사라졌고 README 에 "별도 API나 유료 AI를 호출하지 않는다" 가 방침으로 박혀서, 감사 쪽(Copilot 호출·plan strict validation·finalizeDeploymentDecision·PR #802 fixture)을 걷어냈습니다.

@Sadturtleman 승인해 주셨던 qa-semantic-audit.mjs 의 strict validation 과 fail-closed 설계가 이번에 빠진 부분입니다. 방향에 동의해 주셨던 만큼 따로 알려 드립니다 — 철회 근거는 #809 에 코멘트로 남겼습니다.

남은 건 완료조건 1·2 인 구조화 QA 원천과 게이트입니다. qa-semantic-audit.mjs 777줄에서 파싱·검증만 뽑아 qa-metadata.mjs 230줄로 줄였고, 사용처가 없어진 심볼 7개는 실측해서 지웠습니다.

2. blocking — cutoff 를 다시 밀었습니다

2안(grandfather)으로 갔는데, cutoff 가 2026-08-24 라 오늘(8/25) 기준으로 열린 PR 22건이 그대로 떨어지고 있었습니다. 지적하신 문제가 규모만 줄어 재발한 상태였습니다. 2026-08-26 으로 밀고 열린 PR 53건에 전수로 돌린 결과입니다.

PASS = 1   (#810 — 이 PR 자신)
SKIP = 52  (게이트 도입 전 생성 — 섹션이 없으면 건너뜀)
FAIL = 0

재현 절차에 한 가지 정정이 있습니다. created_at 을 넘기지 않으면 grandfather 판정이 동작하지 않아 전부 FAIL 로 보입니다 — 올려 주신 절차의 --jq 에 그 필드가 빠져 있었습니다.

gh pr view <N> --json number,body,createdAt --jq '{pull_request:{number:.number, body:.body, created_at:.createdAt}}' > event.json
node .github/scripts/validate-pr-qa-metadata.mjs event.json

머지가 8/26 을 넘기면 넘긴 만큼 다시 밀어야 합니다. 그 뒤로는 템플릿을 채운 신규 PR 만 대상이 됩니다 (템플릿을 그대로 내면 placeholder 라 떨어집니다 — 의도한 동작입니다).

3. 검증

CI 에서 게이트가 처음 실제로 돌았고 통과했습니다. 이 PR 자신이 게이트 대상이라, 본문의 QA 메타데이터가 검증을 받은 결과입니다.

4. Validate structured QA metadata  — success   ← 새 게이트
5. Run deployment script tests      — success   ← 110/110
9. Run unit tests, androidTest compile guard, Kover — success
  • node --test .github/scripts/*.test.mjs — 110/110
  • 워크플로 YAML 18개 파싱
  • 열린 PR 53건 전수 게이트 실행 (위 결과)

앱 프로덕션 코드는 건드리지 않습니다 — .github/ 와 README.md 뿐입니다.

@github-actions github-actions Bot removed the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 24, 2026
@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator Author

제안 2번(기준 시점 grandfather) 으로 갔고, 말씀하신 대로 created_at 이 이미 이벤트에 들어와 있어 몇 줄로 끝났습니다. 함께 지적하신 전개 비용을 실측해 붙입니다.

grandfather 컷오프

// validate-pr-qa-metadata.mjs:15
export const QA_METADATA_GATE_CUTOFF = "2026-08-26T00:00:00Z";

function isGrandfathered(pullRequest) {
    const createdAt = Date.parse(pullRequest?.created_at ?? "");
    return Number.isFinite(createdAt) && createdAt < Date.parse(QA_METADATA_GATE_CUTOFF);
}

컷오프 이전에 열린 PR 은 QA 메타데이터 섹션이 없어도 통과합니다(섹션이 있으면 grandfather 여도 검증합니다 — 채운 것이 틀린 채로 지나가지 않게).

전수 재실측 — 47건 → 0건

리뷰에 주신 재현 방법 그대로, 다만 created_at 을 함께 넣어 현재 열린 PR 전량에 돌렸습니다.

gh pr list --state open --limit 100 --json number,body,createdAt
# → {"pull_request":{number, body, created_at}} 로 변환 후
node .github/scripts/validate-pr-qa-metadata.mjs events/<N>.json
PASS = 59
FAIL = 0

지적하신 «#819→#831 스택 13개가 순차 리베이스하는 순간 막힌다» 도 이 컷오프 아래에서는 발생하지 않습니다. gradle.properties 한 줄 지우는 PR 에 evidence 블록을 요구하던 부담도 기존 PR 에는 걸리지 않고요.

다만 컷오프가 머지일보다 뒤여야 합니다

2026-08-26T00:00:00Z 는 오늘(8/25) 기준으로 하루 남았습니다. 이 날짜를 넘겨 머지되면 그 사이에 열린 PR 들이 리베이스하는 순간 정확히 리뷰에서 지적하신 상태가 됩니다. 8/24 로 뒀을 때 열린 PR 22건이 그 상태였던 것을 겪어서, 소스에도 그 이유를 주석으로 남겨 뒀습니다.

머지가 밀리면 밀린 만큼 컷오프를 다시 밀겠습니다. 확인 부탁드립니다.

범위 축소

AI 의미 감사는 이 PR 에서 철회하고 QA 메타데이터 게이트만 남겼습니다(95efbdd). qa-semantic-audit.mjs 의 strict validation·fail-closed 설계에 동의해 주신 부분은 후속으로 분리합니다.

@github-actions github-actions Bot added the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 25, 2026
- develop 이 제거한 `develop` 수동 배포 섹션을 따르고, 그 입력 설명에 있던
  generic fallback 거부 규칙은 살아남은 main 경로 설명으로 옮겼다
  (검증 자체는 render-distribution-release-notes.sh 에 그대로 남아 있다)
- 이 PR 이 신설한 'PR별 구조화 QA 원천' 섹션은 유지
@github-actions github-actions Bot removed the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 25, 2026
컷오프가 8/26 00:00Z 라 그 뒤 열린 #1194 가 다시 게이트에 걸렸다.
«머지가 이 날짜를 넘기면 넘긴 만큼 다시 민다» 는 주석의 결정대로 하루 민다.

실측: 열린 PR 34건 전수 PASS 34 / FAIL 0, qa-metadata.test.mjs 8/8.
@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator Author

컷오프가 밀려 지적이 다시 열려 있던 것을 닫았습니다 (2c12c5f1d).

QA_METADATA_GATE_CUTOFF 이 2026-08-26T00:00:00Z 라 그 뒤에 열린 #1194 가 다시 게이트에 걸리는 상태였습니다. 주석에 적어 둔 «머지가 이 날짜를 넘기면 넘긴 만큼 다시 민다» 대로 2026-08-27T00:00:00Z 로 하루 밀었습니다.

실측 — 이 브랜치의 검증기를 열린 PR 전수에 돌린 결과

열린 PR 34건 — PASS 34 / FAIL 0
gh pr list --state open --limit 200 --json number,body,createdAt > openprs.json
# PR 별로 event.json 을 만들어
node .github/scripts/validate-pr-qa-metadata.mjs event.json

node --test .github/scripts/qa-metadata.test.mjs 도 8/8 통과입니다 (컷오프 전/후 케이스는 상수에서 파생하므로 날짜를 밀어도 그대로 고정됩니다).

리뷰 때 지적하신 47건은 grandfather 도입(#810 fix(ci): 게이트 도입 전 생성 PR을 QA 메타데이터 검증에서 grandfather)으로 닫혔고, 이번 건은 그 뒤 시간이 흐르며 컷오프가 따라잡힌 경우입니다.

@OnlyReadOneBook
OnlyReadOneBook dismissed Sadturtleman’s stale review August 26, 2026 21:21

Dismissed because a later approving review from another current write-capable reviewer is the repository merge decision.

@OnlyReadOneBook
OnlyReadOneBook merged commit 08e4958 into develop Aug 26, 2026
10 checks passed
@OnlyReadOneBook
OnlyReadOneBook deleted the feat/809 branch August 26, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(ci): 릴리스 QA 포인트 generic fallback 제거 — PR 단위 구조화 입력 게이트

3 participants