commitgate 0.4.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,9 +35,12 @@ description: 이 저장소의 REQ 워크플로(CommitGate)로 요구사항을
35
35
  **다음 행동을 스스로 추측하지 마라.** 도구가 상태에서 계산해 준다.
36
36
 
37
37
  ```sh
38
- npm run req:next -- <REQ-id>
38
+ req:next <REQ-id>
39
39
  ```
40
40
 
41
+ > 워크플로 명령은 이 저장소의 **패키지매니저 실행 형식**으로 돌린다(npm은 `run`과 `--` 구분자가 필요하고, pnpm·yarn은 스크립트 이름을 바로 받는다).
42
+ > `req:next`의 `RUN` 출력이 언제나 정확한 형태를 그대로 보여 주므로, 그 줄을 복사해 쓰면 된다.
43
+
41
44
  출력의 `kind`가 정본이다(`--json`으로 기계 판독 가능).
42
45
 
43
46
  | kind | 할 일 |
@@ -33,10 +33,13 @@ alwaysApply: true
33
33
  다음 행동을 스스로 추측하지 마라. 도구가 상태에서 계산한다.
34
34
 
35
35
  ```sh
36
- npm run req:new -- <slug> --run # 티켓·브랜치 생성
37
- npm run req:next -- <REQ-id> # 그다음은 항상 이것
36
+ req:new <slug> --run # 티켓·브랜치 생성
37
+ req:next <REQ-id> # 그다음은 항상 이것
38
38
  ```
39
39
 
40
+ > 이 명령들은 저장소의 **패키지매니저 실행 형식**으로 돌린다(npm은 `run`과 `--` 구분자가 필요하고, pnpm·yarn은 스크립트 이름을 바로 받는다).
41
+ > `req:next`의 `RUN` 출력이 정확한 형태를 그대로 보여 준다.
42
+
40
43
  | kind | 할 일 |
41
44
  |---|---|
42
45
  | `RUN` | 출력된 명령을 그대로 실행하고 다시 `req:next` |
@@ -0,0 +1,8 @@
1
+ # CommitGate 워크플로 스크래치 산출물(티켓 내부) — commitgate init이 대상 repo의 workflow/.gitignore로 설치.
2
+ #
3
+ # ⚠️ 이 패턴은 **이 .gitignore 파일이 있는 디렉터리(= workflow/) 기준 상대경로**다(중첩 .gitignore, gitignore(5)).
4
+ # 루트 .gitignore가 쓰는 `workflow/**/…` 형태를 여기 그대로 복사하면 `workflow/workflow/…`를 찾아 무효가 된다.
5
+ # `/REQ-*/…`로 **앵커드**해 티켓 직계만 무시한다 — 티켓 밖에 흘러든 동명 파일까지 숨기지 않는다(fail-closed 정합).
6
+ /REQ-*/codex-response.json
7
+ /REQ-*/.review-preview.txt
8
+ /REQ-*/.codex-*.tmp
@@ -24,6 +24,11 @@
24
24
  "merge_ready": { "type": "string", "enum": ["yes", "no"] },
25
25
  "risk_level": { "type": "string", "enum": ["LOW", "HIGH"] },
26
26
  "review_kind": { "type": "string", "enum": ["design", "phase"] },
27
+ "full_review_requested": {
28
+ "type": "string",
29
+ "enum": ["yes", "no"],
30
+ "description": "REQ-B-3a. For review_kind=design delta reviews only. Set yes ONLY when the change is too fundamental to assess as a delta against the approved baseline and you need the full design re-reviewed from scratch; you must also set commit_approved=no. Setting yes clears the stored design baseline so the next design review is a full review. In all normal cases set no."
31
+ },
27
32
  "findings": {
28
33
  "type": "array",
29
34
  "items": {
@@ -31,7 +36,11 @@
31
36
  "additionalProperties": false,
32
37
  "required": ["severity", "detail", "file"],
33
38
  "properties": {
34
- "severity": { "type": "string", "enum": ["P1", "P2", "P3"] },
39
+ "severity": {
40
+ "type": "string",
41
+ "enum": ["P1", "P2", "P3"],
42
+ "description": "Blocking severity. ONLY P1 belongs in findings, and the output schema you are given permits P1 only — P2/P3 remain in this enum solely so previously archived reviews still validate, and you MUST NOT emit them. A defect is P1 only when ALL THREE hold. (1) CATEGORY: it is a requirement violation, data loss or corruption, a security hole, a monetary error, or a fail-closed bypass. (2) NORMAL PATH: it reproduces on the normal supported usage path — this project supports a single active worktree and a cooperative worker, so rare recovery races, multi-worktree divergence and full distributed consistency are outside the supported model. (3) EVIDENCE: you state a concrete reproduction path or failure scenario ('with this input/state, this wrong result occurs'). EXCLUSION RULE: if it is not in the CATEGORY list it is NOT P1 — even if it reproduces on the normal path, and even if it is genuinely worth fixing. Portability, structure, maintainability, readability, naming, future extensibility, scope-adjacent improvements and follow-up debt all belong in observations, never in findings. If you are guessing or it 'might' be a problem, that is observations too. Putting non-P1 remarks in findings is the failure mode this field exists to prevent: it blocks approval indefinitely and the review never converges."
43
+ },
35
44
  "detail": { "type": "string" },
36
45
  "file": { "type": ["string", "null"] }
37
46
  }
@@ -2,20 +2,100 @@
2
2
  "type": "object",
3
3
  "additionalProperties": false,
4
4
  "properties": {
5
- "ticketRoot": { "type": "string", "minLength": 1 },
6
- "schemaPath": { "type": "string", "minLength": 1 },
7
- "handoffPath": { "type": ["string", "null"] },
8
- "reviewPersonaPath": { "type": ["string", "null"], "minLength": 1 },
9
- "branchPrefix": { "type": "string", "minLength": 1 },
10
- "packageManager": { "type": "string", "enum": ["pnpm", "npm", "yarn"] },
11
- "granularityMaxFiles": { "type": "integer", "minimum": 1 },
5
+ "ticketRoot": {
6
+ "type": "string",
7
+ "minLength": 1
8
+ },
9
+ "schemaPath": {
10
+ "type": "string",
11
+ "minLength": 1
12
+ },
13
+ "handoffPath": {
14
+ "type": [
15
+ "string",
16
+ "null"
17
+ ]
18
+ },
19
+ "reviewPersonaPath": {
20
+ "type": [
21
+ "string",
22
+ "null"
23
+ ],
24
+ "minLength": 1
25
+ },
26
+ "branchPrefix": {
27
+ "type": "string",
28
+ "minLength": 1
29
+ },
30
+ "packageManager": {
31
+ "type": "string",
32
+ "enum": [
33
+ "pnpm",
34
+ "npm",
35
+ "yarn"
36
+ ]
37
+ },
38
+ "granularityMaxFiles": {
39
+ "type": "integer",
40
+ "minimum": 1
41
+ },
42
+ "reviewModel": {
43
+ "type": [
44
+ "string",
45
+ "null"
46
+ ],
47
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
48
+ },
49
+ "reviewReasoningEffort": {
50
+ "type": [
51
+ "string",
52
+ "null"
53
+ ],
54
+ "enum": [
55
+ "none",
56
+ "minimal",
57
+ "low",
58
+ "medium",
59
+ "high",
60
+ "xhigh",
61
+ null
62
+ ]
63
+ },
64
+ "reviewBudget": {
65
+ "type": "object",
66
+ "additionalProperties": false,
67
+ "required": [
68
+ "autoBudget",
69
+ "hardCap"
70
+ ],
71
+ "properties": {
72
+ "autoBudget": {
73
+ "type": "integer",
74
+ "minimum": 1
75
+ },
76
+ "hardCap": {
77
+ "type": "integer",
78
+ "minimum": 1,
79
+ "maximum": 8
80
+ }
81
+ }
82
+ },
12
83
  "designDocs": {
13
84
  "type": "object",
14
85
  "additionalProperties": false,
15
86
  "properties": {
16
- "requirement": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$" },
17
- "design": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$" },
18
- "plan": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$" }
87
+ "requirement": {
88
+ "type": "string",
89
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
90
+ },
91
+ "design": {
92
+ "type": "string",
93
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
94
+ },
95
+ "plan": {
96
+ "type": "string",
97
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
98
+ }
19
99
  }
20
100
  }
21
101
  }
@@ -4,7 +4,28 @@
4
4
 
5
5
  - Builder가 작성한 리뷰 요청서(`codex-request.md`)의 "리뷰 포인트"는 심사 범위의 **하한**이지 상한이 아니다. 요청서가 묻지 않은 결함도 스스로 분석해 지적하라.
6
6
  - Builder가 짜 놓은 리뷰 프레임에 갇히지 마라. 무엇을 봐야 하는지는 네가 판단한다.
7
- - 개발 부채가 남지 않도록 하라. 지금 넘어가면 나중에 갚아야 하는 것을 식별하라.
7
+ - 개발 부채를 식별하되 **`observations`에 기록해 다음 티켓의 입력으로 만들어라**. 지금 넘어가도 되는 부채까지 차단하는 것은 리뷰의 실패다.
8
+
9
+ ## 보장 범위 경계 (이 경계 밖은 결함이 아니다)
10
+
11
+ **넓게 보되, 이 프로젝트가 약속한 범위 안에서 판정하라.** 탐색 범위와 차단 범위는 다르다.
12
+
13
+ - 이 프로젝트는 **하나의 활성 worktree와 협조적 작업자**만 지원한다. CommitGate는 정상적인 반복 호출에서 실수를 막는 도구이지, 비협조적·분산 동시 실행을 합의 없이 해결하는 시스템이 아니다.
14
+ - 따라서 **다중 worktree state 발산·드문 recovery 경합·완전한 분산 정합성**은 지원 범위 밖이다. 이것들은 결함이 아니라 **명시된 경계**다.
15
+ - 지원하지 않는 운영 모델을 근거로 차단하지 마라. 그 경계를 푸는 **새 서브시스템을 요구하지 마라**.
16
+ - **정상 사용 경로를 우선하라.** 정상 경로에서 재현되지 않는 이론적 조합은 `observations`다.
17
+
18
+ ## P1 정의 (차단의 유일한 기준)
19
+
20
+ `findings`에는 **P1만** 넣는다. P1은 아래 셋을 **모두** 만족할 때만 성립한다.
21
+
22
+ 1. **카테고리**: 요구 위반 · 데이터 손상 · 보안 구멍 · 금전 오류 · fail-closed 우회 중 하나다.
23
+ 2. **정상 경로**: 정상 사용 경로에서 재현된다.
24
+ 3. **증거**: 재현 경로나 실패 시나리오를 명시했다.
25
+
26
+ **배제 규칙**: 카테고리에 없으면 **정상 경로에서 재현되더라도, 고칠 가치가 있더라도 P1이 아니다.** 포터빌리티·구조·유지보수·가독성·이름·장래 확장성·범위 인접 개선·후속 부채는 전부 `observations`다. 추측이면 `observations`다.
27
+
28
+ **절대 표현 금지**: "모든 경우"·"우회 불가"·"어떤 worktree에서도"는 transactional backend가 있을 때만 쓸 수 있다. 설계가 그런 절대 보장을 약속하지 않았다는 이유로 차단하지 마라.
8
29
 
9
30
  ## 판정은 구조화 응답 필드로만 낸다
10
31
 
@@ -43,3 +64,37 @@
43
64
  - `phase` — 권위 아티팩트는 staged diff다. 그 diff만 심사한다.
44
65
 
45
66
  리뷰 대상이 아닌 것을 근거로 지적하지 마라. 설계 리뷰에서 "구현이 없다"는 지적은 성립하지 않는다.
67
+
68
+ ## 응답 전 점검 관점 (REVIEW_KIND별)
69
+
70
+ 응답을 만들기 전에 해당 kind의 관점을 **한 번에** 점검하라. 이 목록은 탐색의 **하한**이다 — 여기 없는 결함도 지적하라.
71
+
72
+ ### REVIEW_KIND: design
73
+
74
+ - 요구사항·비목표·인수 기준
75
+ - 00/01/02 문서 간 모순
76
+ - 요구된 정상 사용 경로의 계약 위반
77
+ - 테스트 oracle이 실제 실패를 잡는지
78
+ - 보안·fail-closed 경계
79
+ - 설계가 약속한 문서·CLI help·기존 동작과의 호환성
80
+
81
+ 기존 코드·CLI help는 **설계가 현재 동작과의 호환 또는 문서·help 변경을 약속한 경우에만** 그 약속을 검증하는 기준선으로 읽는다. 설계와 무관한 기존 코드 결함은 `findings`가 아니라 `observations`다.
82
+
83
+ 이것은 위 "리뷰 대상이 아닌 것을 근거로 지적하지 마라"의 예외가 아니라 그 **적용 규칙**이다. 설계가 한 약속은 설계의 일부이므로, 그 약속이 현재 코드와 어긋나면 그것은 **설계의 결함**이다. 설계가 약속하지 않은 기존 코드는 여전히 리뷰 대상이 아니다.
84
+
85
+ ### REVIEW_KIND: phase
86
+
87
+ - staged diff가 해당 phase의 인수 기준을 충족하는지
88
+ - 변경된 테스트 oracle이 실제 실패를 잡는지
89
+ - 변경된 사용자 대면 문서·CLI help가 실제 변경 동작과 일치하는지
90
+ - 보안·fail-closed 경계가 staged diff에서 약화되지 않는지
91
+
92
+ ## 배칭 — 아는 P1은 한 번에 낸다
93
+
94
+ **이번 호출에서 식별한 모든 P1을 `findings[]`에 함께 반환하라.** 이미 아는 P1을 다음 라운드로 의도적으로 미루지 않는다.
95
+
96
+ 한 건만 내고 멈추면 Builder는 한 건을 고치고 전체를 다시 검수받는다. 그 직렬 흐름이 설계 리뷰를 14·17라운드까지 늘렸다. 그 라운드들의 지적은 **전부 유효했다** — 문제는 발견이 아니라 전달 방식이었다.
97
+
98
+ - 여러 `findings`는 **정상이다.** 개수가 많다는 것 자체는 승인 불가 사유가 아니며, 리뷰의 실패도 아니다.
99
+ - 확신하지 못한 사항을 P1로 **부풀리지 마라.** 추측은 `observations`다. 배칭은 P1 기준을 낮추라는 뜻이 **아니다**.
100
+ - 이 절은 **무엇을 P1로 볼지**를 바꾸지 않는다. 위 「P1 정의」 3요소는 그대로다. 이 절이 정하는 것은 **아는 P1을 언제 낼지**뿐이다.