@mcgrapeng/ccg 3.1.0 → 4.1.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.
- package/.claude/settings.local.json +110 -0
- package/.idea/MypyPlugin.xml +7 -0
- package/.idea/ccg.iml +8 -0
- package/.idea/inspectionProfiles/Project_Default.xml +23 -0
- package/.idea/inspectionProfiles/profiles_settings.xml +6 -0
- package/.idea/misc.xml +7 -0
- package/.idea/modules.xml +8 -0
- package/.idea/ruff.xml +6 -0
- package/.idea/vcs.xml +6 -0
- package/.plan.md +62 -0
- package/README.md +637 -140
- package/a.txt +9 -0
- package/asym_test.sh +18 -0
- package/bin/ccg-precommit.bat +22 -0
- package/bin/ccg.js +12 -10
- package/ccg +15 -0
- package/ccg-bailian-integration.sh +210 -0
- package/ccg-bailian-models.sh +123 -0
- package/ccg-multi-provider.sh +491 -0
- package/ccg-workflow.sh +1108 -0
- package/ccg.md +290 -50
- package/ccg.sh +2964 -114
- package/docs/ARCHITECTURE.ja.md +463 -0
- package/docs/ARCHITECTURE.ko.md +463 -0
- package/docs/ARCHITECTURE.md +490 -0
- package/docs/ARCHITECTURE.zh-CN.md +469 -0
- package/docs/CAPABILITIES.md +206 -0
- package/docs/CHANGELOG.md +252 -0
- package/docs/README.ja.md +443 -0
- package/docs/README.ko.md +442 -0
- package/docs/README.zh-CN.md +512 -0
- package/package.json +13 -20
- package/scripts/curl-install.sh +100 -27
- package/scripts/install.sh +21 -5
- package/test-bailian-full.sh +90 -0
- package/test-bailian.sh +49 -0
- package/CHANGELOG.md +0 -119
- package/README.ja.md +0 -220
- package/README.ko.md +0 -219
- package/README.zh-CN.md +0 -219
package/README.ja.md
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
# ccg — Code Divergence Detector
|
|
2
|
-
|
|
3
|
-
> Claude Code のスラッシュコマンド。一度インストールして、diff の上で `/ccg` と入力するだけ。
|
|
4
|
-
|
|
5
|
-
[]()
|
|
6
|
-
[](https://www.npmjs.com/package/@mcgrapeng/ccg)
|
|
7
|
-
[](LICENSE)
|
|
8
|
-
|
|
9
|
-
[English](README.md) | [简体中文](README.zh-CN.md) | **日本語** | [한국어](README.ko.md) · [アーキテクチャ →](docs/ARCHITECTURE.ja.md)
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## ccg とは
|
|
14
|
-
|
|
15
|
-
あなたは `auth/login.go` を編集し終え、マージしようとしています。念のため確認したい。今の選択肢は 3 つしかなく、全て欠点があります:
|
|
16
|
-
|
|
17
|
-
- **単一モデルのレビュー**(Copilot、Cursor `/review`、Aider)は **1 つの視点** しか提供しません。Claude が timing attack を見逃せば、あなたも一緒に見逃します。
|
|
18
|
-
- **複数モデル集約ツール**(zen-mcp-server 等)は意見を **平均化** してしまい、優秀なモデル同士が意見を異にした箇所——人間が本当に助けを必要とする箇所——を覆い隠してしまいます。
|
|
19
|
-
- **手動の二重チェック** は時間が無限にあればやりますが、ありませんね。
|
|
20
|
-
|
|
21
|
-
ccg は Claude Code 用の `/ccg` スラッシュコマンドで、この 3 つを本当に解決します。任意の diff に対して:
|
|
22
|
-
|
|
23
|
-
1. 同じ prompt を **Codex(OpenAI)** と **Gemini(Google)** に並列で送信
|
|
24
|
-
2. **Claude** に両方のレポートを読ませ、**両者が意見を異にした箇所を浮かび上がらせる**——そこが人間の判断が必要な場所
|
|
25
|
-
3. コストを記録、リスクに応じて最安充足モデルを自動選択、過去のレビュー履歴を保持
|
|
26
|
-
|
|
27
|
-
**例え話**:別チームの 2 人のシニアエンジニアに同じ PR をレビューさせ、テックリードに統合させる:「ここは両方同意、ここは意見が分かれた——あなたが決めて、私の見解は以下」。
|
|
28
|
-
|
|
29
|
-
## いつ ccg を使うか
|
|
30
|
-
|
|
31
|
-
トリガーは **領域** ではなく **感覚** です。書き終えた自分の diff を見ながら、心の中で次のように考えていたら、ccg の場面です:
|
|
32
|
-
|
|
33
|
-
| 心の中の独り言 | ccg を使う? |
|
|
34
|
-
|---|---|
|
|
35
|
-
| 「これを間違えたら午前 3 時に呼び出される」 | ✅ Yes |
|
|
36
|
-
| 「これは判断問題 — 明らかに正しい答えはない」 | ✅ Yes |
|
|
37
|
-
| 「誰か他に先に見てほしい」 | ✅ Yes |
|
|
38
|
-
| 「変数の名前を変えただけ」 | ❌ No |
|
|
39
|
-
| 「ドキュメント変更だけ」 | ❌ No |
|
|
40
|
-
| 「単一モデルとストリーミング対話したい」 | ❌ No(CLI を直接使う) |
|
|
41
|
-
|
|
42
|
-
**ドメイン横断の実例** —— auth / 暗号ではないが、すべて「シニア 2 人が意見を異にしうる」瞬間:
|
|
43
|
-
|
|
44
|
-
- **ソーシャルプラットフォーム** —— フィードに新エンゲージメントシグナルを追加して再ランキング · コメントツリー fan-out 戦略 · A/B テストバケッティングロジック · 反スパムレート制限ポリシー · フォロー関係のグラフ DB スキーマ
|
|
45
|
-
- **データ / AI インフラ** —— embedding モデル切替(再インデックスする?) · chunking 戦略変更 · RAG 検索スコアリング · prompt injection 防御レイヤリング
|
|
46
|
-
- **フロントエンド** —— 新ページに SSR vs ISR vs RSC · キャッシュ無効化戦略 · 状態管理リファクタリング · アクセシビリティのトレードオフ
|
|
47
|
-
- **API 設計** —— cursor vs offset ページング · エラーレスポンスモデル · バージョニング方式 · 冪等性キーの扱い
|
|
48
|
-
- **分散システム** —— タイムアウト / 再試行ポリシー · cache TTL vs イベント駆動無効化 · partition tolerance トレードオフ · leader election のセマンティクス
|
|
49
|
-
- **データベース** —— マルチステップマイグレーションの順序 · ホットパスのインデックス選択 · トランザクション分離レベル · 論理削除 vs 物理削除
|
|
50
|
-
- **セキュリティ** —— ええ、auth / 暗号 / 決済もここ —— ただし多くのドメインの 1 つに過ぎない
|
|
51
|
-
|
|
52
|
-
**パターン**:「妥当なエンジニアが選択肢 A を選ぶこともあれば、別の妥当なエンジニアが B を選ぶこともある」変更 —— これが分岐検出が $0.04 を稼ぐ瞬間。
|
|
53
|
-
|
|
54
|
-
## なぜ ccg なのか(他ツールとの比較)
|
|
55
|
-
|
|
56
|
-
**1. 意見の相違こそがシグナル、ノイズではない。**
|
|
57
|
-
Codex が「`subtle.ConstantTimeCompare` を使え」と言い、Gemini が「bcrypt は既に恒定時間、それは cargo-cult」と言った時、**そここそ考える必要がある場所**。他のツールはこれを「timing attack に注意」とぼやかして混ぜます。ccg は両者の生の言葉を見せます。
|
|
58
|
-
|
|
59
|
-
**2. コスト可視化が組み込み。**
|
|
60
|
-
Codex / Gemini CLI は支出を教えません。ccg は全呼び出しを記録、リスクに応じて最安充足モデルを自動選択(リスクルーティング)、同一プロンプトは 24h キャッシュでゼロコスト。`ccg_usage --this-month` が「今月いくら使った?」に即答。
|
|
61
|
-
|
|
62
|
-
**3. セッションを跨いで残るレビュー履歴。**
|
|
63
|
-
「2 週間前、モデルは `src/auth.ts` について何と言ったか?」——ccg の追記専用台帳がこれに答えます。ステートレスなツールには不可能です。
|
|
64
|
-
|
|
65
|
-
## インストール
|
|
66
|
-
|
|
67
|
-
どちらかを選択:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# npm (推奨)
|
|
71
|
-
npx @mcgrapeng/ccg install
|
|
72
|
-
|
|
73
|
-
# または curl ワンライナー、Node 不要
|
|
74
|
-
curl -fsSL https://raw.githubusercontent.com/mcgrapeng/ccg/main/scripts/curl-install.sh | bash
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
次に AI CLI を一度だけインストール:
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
npm i -g @openai/codex @google/gemini-cli
|
|
81
|
-
echo 'export GEMINI_API_KEY="<your-key>"' >> ~/.zshenv
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
確認:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npx @mcgrapeng/ccg doctor # Codex / Gemini / API key をチェック
|
|
88
|
-
npx @mcgrapeng/ccg about # 7 層の機能と現在の環境状態を表示
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## 使い方の完全な例
|
|
92
|
-
|
|
93
|
-
`auth/login.go` を編集したとします:
|
|
94
|
-
|
|
95
|
-
```go
|
|
96
|
-
// before // after
|
|
97
|
-
func Login(user, pw string) bool { func Login(user, pw string) bool {
|
|
98
|
-
u := lookupUser(user) u := lookupUser(user)
|
|
99
|
-
- return u.Hash == sha256.Sum256([]byte(pw)) hashed, err := bcrypt.GenerateFromPassword([]byte(pw), 12)
|
|
100
|
-
+ if err != nil { return false }
|
|
101
|
-
+ return subtle.ConstantTimeCompare(u.Hash, hashed) == 1
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Claude Code を開いて入力:
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
/ccg
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
約 30 秒後に表示されるもの——**実際の出力例**、プレースホルダーではない:
|
|
112
|
-
|
|
113
|
-
```
|
|
114
|
-
📍 範囲:worktree · 1 ファイル · +4 -1 行
|
|
115
|
-
🎯 モード:quality (risk=65 · auth+35 size>0+5 crypto-mention+25)
|
|
116
|
-
🩺 両レビュアー正常:Codex ✓ · Gemini ✓
|
|
117
|
-
💰 コスト:$0.041
|
|
118
|
-
|
|
119
|
-
═══ AGREEMENT (2) — 両方が指摘、低シグナル ═══
|
|
120
|
-
• auth/login.go:3 — sha256 はパスワードハッシュでない;bcrypt が正しい
|
|
121
|
-
• auth/login.go:5 — bcrypt エラーは明示的に処理(やっている)
|
|
122
|
-
|
|
123
|
-
═══ DIVERGENCE (1) — 両モデルが意見不一致 ★ あなたが決定 ═══
|
|
124
|
-
|
|
125
|
-
▸ auth/login.go:6 — bcrypt ハッシュの比較方法
|
|
126
|
-
🔵 Codex: 「bcrypt を使っても timing attack を防ぐため
|
|
127
|
-
subtle.ConstantTimeCompare でラップせよ」
|
|
128
|
-
🟢 Gemini:「bcrypt.CompareHashAndPassword は既に恒定時間。
|
|
129
|
-
ラッピングは cargo-cult、長さ不一致 panic を生み得る」
|
|
130
|
-
⚖️ Claude: Gemini が正しい。bcrypt.CompareHashAndPassword が標準的な
|
|
131
|
-
比較方法;その生の出力に対する ConstantTimeCompare は
|
|
132
|
-
カテゴリ誤り——「ハッシュした pw」と「保存されたハッシュ」を
|
|
133
|
-
比較しているが、bcrypt は毎回新しいソルトを使うので
|
|
134
|
-
直接比較は常に false を返す。
|
|
135
|
-
➡️ アクション:ConstantTimeCompare 行を以下に置換:
|
|
136
|
-
`err := bcrypt.CompareHashAndPassword(u.Hash, []byte(pw))`
|
|
137
|
-
`return err == nil`
|
|
138
|
-
|
|
139
|
-
═══ BLINDSPOT (1) — どちらも見ていないが Claude が疑う ═══
|
|
140
|
-
• エラーパス:bcrypt エラー時に false を返すのは呼び出し側には正しいが、
|
|
141
|
-
インフラエラー(bcrypt OOM 等)を静かに飲み込む。ログを追加せよ。
|
|
142
|
-
|
|
143
|
-
═══ VERDICT: fix-required ═══
|
|
144
|
-
現在の比較ロジックは正しいパスワードを常に拒否する。DIVERGENCE の
|
|
145
|
-
アクションを適用 + エラーログ追加で、マージ可能。
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### この出力をどう読むか
|
|
149
|
-
|
|
150
|
-
| セクション | 意味 | 何をすべきか |
|
|
151
|
-
|---|---|---|
|
|
152
|
-
| **AGREEMENT** | Codex と Gemini の両方が同じ問題を指摘。単一の Claude でも見つかる可能性が高い——**新規情報量低**。 | 流し読み、未修正なら修正。 |
|
|
153
|
-
| **DIVERGENCE** ★ | 両モデルが意見不一致。**これが ccg の存在意義**。Claude の「アクション」行が推奨をくれるが、最終判断はあなた。 | 注意深く読む、Claude の判断を受け入れるかオーバーライド。 |
|
|
154
|
-
| **BLINDSPOT** | どちらのモデルも気付かなかったが Claude が合成時に疑った。**控えめに**——1 回あたり最大 2 件。 | ヒントとして扱う、聖典ではない。 |
|
|
155
|
-
| **VERDICT** | `merge` / `fix-required` / `discuss`。1 行サマリー。 | マージゲートとして使用。 |
|
|
156
|
-
|
|
157
|
-
レビュー後、`ccg_ledger_record` が JSONL 1 行を台帳に書きます。2 週間後:
|
|
158
|
-
|
|
159
|
-
```bash
|
|
160
|
-
source ~/.claude/commands/ccg.sh
|
|
161
|
-
ccg_ledger_query "auth/login.go"
|
|
162
|
-
# → "auth/login.go: 3 レビュー · 最新 2026-05-23 (fix-required) · 2026-05-09 (merge) · 2026-04-28 (discuss)"
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## 設定(デフォルトで通常は十分)
|
|
166
|
-
|
|
167
|
-
モードとモデルの選択は自動です。必要なときだけ上書き:
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
CCG_MODE=quality /ccg # 任意の diff で quality モデルを強制
|
|
171
|
-
CCG_CODEX_MODEL=o3 /ccg # 1 つのモデルだけ上書き
|
|
172
|
-
CCG_NO_CACHE=1 /ccg # この呼び出しのみ 24h キャッシュをスキップ
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
よく使うもの(全部は [アーキテクチャ §5](docs/ARCHITECTURE.ja.md#5-拡張ポイント)):
|
|
176
|
-
|
|
177
|
-
| 変数 | デフォルト | 用途 |
|
|
178
|
-
|---|---|---|
|
|
179
|
-
| `CCG_MODE` | `auto` | `auto` / `cost` / `balanced` / `quality` |
|
|
180
|
-
| `CCG_CACHE_TTL_HOURS` | `24` | キャッシュ TTL |
|
|
181
|
-
| `CCG_MAX_PROMPT_KB` | `100` | 1 回あたりのプロンプトサイズ上限 |
|
|
182
|
-
|
|
183
|
-
コスト目安(USD / 呼び出し、キャッシュヒット後):
|
|
184
|
-
|
|
185
|
-
| モード | Codex | Gemini | 標準コスト |
|
|
186
|
-
|---|---|---|---|
|
|
187
|
-
| `cost` | gpt-5-nano | gemini-2.5-flash-lite | ~$0.0007 |
|
|
188
|
-
| `balanced` | gpt-5-mini | gemini-2.5-flash | ~$0.0046 |
|
|
189
|
-
| `quality` | gpt-5 | gemini-2.5-pro | ~$0.0440 |
|
|
190
|
-
|
|
191
|
-
累計支出はいつでも確認可能:
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
source ~/.claude/commands/ccg.sh
|
|
195
|
-
ccg_usage --this-month
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
## 適さない用途
|
|
199
|
-
|
|
200
|
-
- Claude Code 以外の IDE([zen-mcp-server](https://github.com/BeehiveInnovations/zen-mcp-server) を試してください)
|
|
201
|
-
- 静的解析の置き換え(Semgrep / CodeQL と併用してください)
|
|
202
|
-
- 全 PR で自動実行(ccg はトリアージツール、ボットではありません)
|
|
203
|
-
- ストリーミング出力やマルチターン会話
|
|
204
|
-
|
|
205
|
-
## アーキテクチャとコントリビュート
|
|
206
|
-
|
|
207
|
-
ccg は **7 層** で構成されており、「分岐検出」は最上位 1 層にすぎません。下の 6 層(キャッシュ、台帳、使用量、リスクルーティング、スマート diff、安全な CLI スケジューリング)はそれぞれ独立して実問題を解決します。`ccg.sh` を変更する前に [docs/ARCHITECTURE.ja.md](docs/ARCHITECTURE.ja.md) を読んでください。
|
|
208
|
-
|
|
209
|
-
テスト:
|
|
210
|
-
|
|
211
|
-
```bash
|
|
212
|
-
bash tests/test_ccg.sh # 99 個の回帰テスト、~31s
|
|
213
|
-
REAL_CLI=1 bash tests/test_ccg.sh # +2 個のライブ API テスト(課金あり)
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## ライセンスと謝辞
|
|
217
|
-
|
|
218
|
-
MIT —— [LICENSE](LICENSE) を参照。
|
|
219
|
-
|
|
220
|
-
[oh-my-claudecode](https://github.com/Yeachan-Heo/oh-my-claudecode) の元々の `/ccg` コンセプト · Claude Code · OpenAI Codex CLI · Google Gemini CLI を基に構築。
|
package/README.ko.md
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
# ccg — Code Divergence Detector
|
|
2
|
-
|
|
3
|
-
> Claude Code 슬래시 명령. 한 번 설치하고 diff 위에서 `/ccg`를 입력하세요.
|
|
4
|
-
|
|
5
|
-
[]()
|
|
6
|
-
[](https://www.npmjs.com/package/@mcgrapeng/ccg)
|
|
7
|
-
[](LICENSE)
|
|
8
|
-
|
|
9
|
-
[English](README.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | **한국어** · [아키텍처 →](docs/ARCHITECTURE.ko.md)
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## ccg란
|
|
14
|
-
|
|
15
|
-
`auth/login.go` 변경 후 머지하려고 합니다. 안전 점검을 하고 싶습니다. 오늘 선택지는 세 가지뿐이고, 모두 결함이 있습니다:
|
|
16
|
-
|
|
17
|
-
- **단일 모델 리뷰**(Copilot, Cursor `/review`, Aider)는 **한 가지 관점**만 제공합니다. Claude가 timing attack을 놓치면 당신도 함께 놓칩니다.
|
|
18
|
-
- **다중 모델 게이트웨이**(zen-mcp-server 등)는 의견을 **평균화**하여, 똑똑한 모델들이 의견을 달리한 곳 — 인간이 정말로 도움이 필요한 유일한 곳 — 을 정확히 가립니다.
|
|
19
|
-
- **수동 교차 검증**은 시간이 무한하다면 할 일. 당신에겐 없습니다.
|
|
20
|
-
|
|
21
|
-
ccg는 Claude Code용 `/ccg` 슬래시 명령으로, 이 세 가지 모두를 진짜로 해결합니다. 임의의 diff에 대해:
|
|
22
|
-
|
|
23
|
-
1. 같은 prompt를 **Codex(OpenAI)** 와 **Gemini(Google)** 에 병렬 전송
|
|
24
|
-
2. **Claude** 가 두 보고서를 읽고 **그들이 의견을 달리하는 곳을 부각** —— 인간 판단이 필요한 곳
|
|
25
|
-
3. 비용 추적, 위험 수준에 적합한 가장 저렴한 모델 자동 선택, 과거 리뷰 기억
|
|
26
|
-
|
|
27
|
-
**비유**: 다른 팀의 시니어 엔지니어 두 명에게 같은 PR을 리뷰시키고, 테크 리드가 종합: "이건 둘 다 동의, 이건 의견이 갈렸음 — 당신이 결정, 내 견해는 다음".
|
|
28
|
-
|
|
29
|
-
## 언제 ccg를 사용할까
|
|
30
|
-
|
|
31
|
-
트리거는 **도메인**이 아니라 **느낌**입니다. 방금 작성한 diff를 보면서 마음속으로 다음과 같이 생각하고 있다면 — ccg의 순간입니다:
|
|
32
|
-
|
|
33
|
-
| 마음속 독백 | ccg 사용? |
|
|
34
|
-
|---|---|
|
|
35
|
-
| "이걸 잘못하면 새벽 3시에 호출됨." | ✅ 예 |
|
|
36
|
-
| "이건 판단의 문제 — 명백히 정답이 있는 게 아님." | ✅ 예 |
|
|
37
|
-
| "누가 먼저 봐줬으면 좋겠다." | ✅ 예 |
|
|
38
|
-
| "변수 이름만 바꿨다." | ❌ 아니요 |
|
|
39
|
-
| "문서만 편집." | ❌ 아니요 |
|
|
40
|
-
| "단일 모델과 스트리밍 대화하고 싶음." | ❌ 아니요 (CLI 직접 사용) |
|
|
41
|
-
|
|
42
|
-
**도메인 횡단 실제 예시** — 모두 auth/암호화가 아니지만, 모두 "시니어 엔지니어 두 명이 의견이 갈릴" 순간입니다:
|
|
43
|
-
|
|
44
|
-
- **소셜 플랫폼** — 새 참여 신호로 피드 재정렬 · 댓글 트리 fan-out 전략 · A/B 테스트 버킷팅 로직 · 어뷰즈 방지 레이트 리밋 정책 · 팔로우 관계의 그래프 DB 스키마
|
|
45
|
-
- **데이터 / AI 인프라** — embedding 모델 교체(재인덱싱?) · 청킹 전략 변경 · RAG 검색 점수 · 프롬프트 인젝션 방어 레이어링
|
|
46
|
-
- **프론트엔드** — 새 페이지에 SSR vs ISR vs RSC · 캐시 무효화 전략 · 상태 관리 리팩토링 · 접근성 트레이드오프
|
|
47
|
-
- **API 설계** — 페이지네이션 cursor vs offset · 에러 응답 모델 · 버전 관리 방식 · 멱등성 키 처리
|
|
48
|
-
- **분산 시스템** — 타임아웃 / 재시도 정책 · cache TTL vs 이벤트 기반 무효화 · 분할 내성 트레이드오프 · 리더 선출 의미론
|
|
49
|
-
- **데이터베이스** — 다단계 마이그레이션 순서 · 핫 패스 인덱스 선택 · 트랜잭션 격리 수준 · 소프트 삭제 vs 하드 삭제
|
|
50
|
-
- **보안** — 네, auth / 암호화 / 결제도 여기 — 하지만 많은 도메인 중 하나일 뿐
|
|
51
|
-
|
|
52
|
-
**패턴**: 합리적인 엔지니어 한 명은 A를 선택하고 다른 합리적인 엔지니어는 B를 선택할 수 있는 모든 변경 — 그게 분기 검출이 $0.04를 회수하는 순간.
|
|
53
|
-
|
|
54
|
-
## 왜 ccg인가 (다른 도구와의 비교)
|
|
55
|
-
|
|
56
|
-
**1. 의견 불일치가 신호, 잡음이 아님.**
|
|
57
|
-
Codex가 "`subtle.ConstantTimeCompare`를 사용하라"고 하고 Gemini가 "bcrypt는 이미 constant-time, 그건 cargo-cult"라고 할 때, *그곳이* 당신이 생각해야 할 곳입니다. 다른 도구는 이런 충돌을 모호한 "timing attack 주의"로 섞어버립니다. ccg는 양쪽의 말을 그대로 보여줍니다.
|
|
58
|
-
|
|
59
|
-
**2. 내장 비용 텔레메트리.**
|
|
60
|
-
Codex / Gemini CLI는 지출을 알려주지 않습니다. ccg는 모든 호출을 기록하고, 위험에 따라 가장 저렴하고 충분한 모델을 자동 선택(위험 라우팅)하며, 같은 prompt는 24h 캐시로 비용 0. `ccg_usage --this-month`가 "지금까지 얼마 썼지?"에 답합니다.
|
|
61
|
-
|
|
62
|
-
**3. 세션 간에 살아남는 리뷰 이력.**
|
|
63
|
-
"2주 전에 모델이 `src/auth.ts`에 대해 뭐라고 했지?" —— ccg의 추가 전용 원장이 답합니다. 어떤 무상태 도구도 못 합니다.
|
|
64
|
-
|
|
65
|
-
## 설치
|
|
66
|
-
|
|
67
|
-
둘 중 선택:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# npm (권장)
|
|
71
|
-
npx @mcgrapeng/ccg install
|
|
72
|
-
|
|
73
|
-
# 또는 curl 한 줄 설치, Node 불필요
|
|
74
|
-
curl -fsSL https://raw.githubusercontent.com/mcgrapeng/ccg/main/scripts/curl-install.sh | bash
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
그다음 AI CLI를 한 번 설치:
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
npm i -g @openai/codex @google/gemini-cli
|
|
81
|
-
echo 'export GEMINI_API_KEY="<your-key>"' >> ~/.zshenv
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
확인:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npx @mcgrapeng/ccg doctor # Codex / Gemini / API key 점검
|
|
88
|
-
npx @mcgrapeng/ccg about # 7개 계층의 기능과 현재 환경 상태 확인
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## 사용법 — 완전한 예제
|
|
92
|
-
|
|
93
|
-
`auth/login.go`를 막 편집했다고 해봅시다:
|
|
94
|
-
|
|
95
|
-
```go
|
|
96
|
-
// before // after
|
|
97
|
-
func Login(user, pw string) bool { func Login(user, pw string) bool {
|
|
98
|
-
u := lookupUser(user) u := lookupUser(user)
|
|
99
|
-
- return u.Hash == sha256.Sum256([]byte(pw)) hashed, err := bcrypt.GenerateFromPassword([]byte(pw), 12)
|
|
100
|
-
+ if err != nil { return false }
|
|
101
|
-
+ return subtle.ConstantTimeCompare(u.Hash, hashed) == 1
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Claude Code를 열고 입력:
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
/ccg
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
약 30초 후 다음과 같은 출력 —— **실제 출력**, 플레이스홀더 아님:
|
|
112
|
-
|
|
113
|
-
```
|
|
114
|
-
📍 범위: worktree · 1 파일 · +4 -1 줄
|
|
115
|
-
🎯 모드: quality (risk=65 · auth+35 size>0+5 crypto-mention+25)
|
|
116
|
-
🩺 두 리뷰어 정상: Codex ✓ · Gemini ✓
|
|
117
|
-
💰 비용: $0.041
|
|
118
|
-
|
|
119
|
-
═══ AGREEMENT (2) — 양쪽 모두 지적, 낮은 신호 ═══
|
|
120
|
-
• auth/login.go:3 — sha256은 비밀번호 해시 아님; bcrypt가 맞음
|
|
121
|
-
• auth/login.go:5 — bcrypt 에러 명시적 처리 (당신이 했음)
|
|
122
|
-
|
|
123
|
-
═══ DIVERGENCE (1) — 두 모델이 의견 불일치 ★ 당신이 결정 ═══
|
|
124
|
-
|
|
125
|
-
▸ auth/login.go:6 — bcrypt 해시 비교 방법
|
|
126
|
-
🔵 Codex: "bcrypt를 사용해도 timing attack 방지를 위해
|
|
127
|
-
subtle.ConstantTimeCompare로 감싸라."
|
|
128
|
-
🟢 Gemini: "bcrypt.CompareHashAndPassword는 이미 constant-time.
|
|
129
|
-
감싸는 것은 cargo-cult이고 길이 불일치 panic을 유발할 수 있다."
|
|
130
|
-
⚖️ Claude: Gemini가 맞다. bcrypt.CompareHashAndPassword가 표준 비교
|
|
131
|
-
방법; 그 원시 출력에 ConstantTimeCompare는 카테고리 오류 ——
|
|
132
|
-
"막 해시한 pw"와 "저장된 해시"를 비교하지만 bcrypt는
|
|
133
|
-
매번 새 솔트를 쓰므로 직접 비교는 항상 false 반환.
|
|
134
|
-
➡️ 액션: ConstantTimeCompare 줄을 다음으로 교체:
|
|
135
|
-
`err := bcrypt.CompareHashAndPassword(u.Hash, []byte(pw))`
|
|
136
|
-
`return err == nil`
|
|
137
|
-
|
|
138
|
-
═══ BLINDSPOT (1) — 둘 다 못 봤지만 Claude 의심 ═══
|
|
139
|
-
• 에러 경로: bcrypt 오류 시 false 반환은 호출자에겐 맞지만,
|
|
140
|
-
인프라 오류(bcrypt OOM 등)를 조용히 삼킴. 로그를 추가하라.
|
|
141
|
-
|
|
142
|
-
═══ VERDICT: fix-required ═══
|
|
143
|
-
현재 비교 로직은 유효한 비밀번호도 항상 거부한다. DIVERGENCE 액션
|
|
144
|
-
적용 + 오류 로깅 추가 후 머지 가능.
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### 이 출력을 어떻게 읽는가
|
|
148
|
-
|
|
149
|
-
| 섹션 | 의미 | 무엇을 할까 |
|
|
150
|
-
|---|---|---|
|
|
151
|
-
| **AGREEMENT** | Codex와 Gemini 둘 다 같은 것을 지적. 단일 소스 Claude도 잡을 가능성 높음 —— **새로운 정보량 낮음**. | 훑어보고, 미수정 시 수정. |
|
|
152
|
-
| **DIVERGENCE** ★ | 두 모델이 의견 불일치. **ccg가 존재하는 진짜 이유**. Claude의 "액션" 줄이 추천을 주지만 최종 결정자는 당신. | 주의 깊게 읽고, Claude 판단 수용 또는 재정의. |
|
|
153
|
-
| **BLINDSPOT** | 어떤 모델도 제기하지 않았지만 Claude가 합성하면서 의심. **신중히 사용** —— 호출당 최대 2건. | 힌트로 다루고, 절대 진리 아님. |
|
|
154
|
-
| **VERDICT** | `merge` / `fix-required` / `discuss`. 한 줄 요약. | 머지 게이트로 사용. |
|
|
155
|
-
|
|
156
|
-
리뷰 후 `ccg_ledger_record`가 원장에 JSONL 한 줄 기록. 2주 후:
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
source ~/.claude/commands/ccg.sh
|
|
160
|
-
ccg_ledger_query "auth/login.go"
|
|
161
|
-
# → "auth/login.go: 3 리뷰 · 최신 2026-05-23 (fix-required) · 2026-05-09 (merge) · 2026-04-28 (discuss)"
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## 설정 (기본값으로 보통 충분)
|
|
165
|
-
|
|
166
|
-
모드와 모델 선택은 자동입니다. 필요할 때만 재정의:
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
CCG_MODE=quality /ccg # 모든 diff에 quality 모델 강제
|
|
170
|
-
CCG_CODEX_MODEL=o3 /ccg # 단일 모델만 재정의
|
|
171
|
-
CCG_NO_CACHE=1 /ccg # 이번 호출만 24h 캐시 우회
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
자주 쓰는 것 (전체는 [아키텍처 §5](docs/ARCHITECTURE.ko.md#5-확장-지점)):
|
|
175
|
-
|
|
176
|
-
| 변수 | 기본값 | 용도 |
|
|
177
|
-
|---|---|---|
|
|
178
|
-
| `CCG_MODE` | `auto` | `auto` / `cost` / `balanced` / `quality` |
|
|
179
|
-
| `CCG_CACHE_TTL_HOURS` | `24` | 캐시 TTL |
|
|
180
|
-
| `CCG_MAX_PROMPT_KB` | `100` | 호출당 프롬프트 크기 상한 |
|
|
181
|
-
|
|
182
|
-
비용 참고 (USD / 호출, 캐시 적중 후):
|
|
183
|
-
|
|
184
|
-
| 모드 | Codex | Gemini | 표준 비용 |
|
|
185
|
-
|---|---|---|---|
|
|
186
|
-
| `cost` | gpt-5-nano | gemini-2.5-flash-lite | ~$0.0007 |
|
|
187
|
-
| `balanced` | gpt-5-mini | gemini-2.5-flash | ~$0.0046 |
|
|
188
|
-
| `quality` | gpt-5 | gemini-2.5-pro | ~$0.0440 |
|
|
189
|
-
|
|
190
|
-
누적 지출은 언제든:
|
|
191
|
-
|
|
192
|
-
```bash
|
|
193
|
-
source ~/.claude/commands/ccg.sh
|
|
194
|
-
ccg_usage --this-month
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
## 적합하지 않은 경우
|
|
198
|
-
|
|
199
|
-
- Claude Code 이외의 IDE ([zen-mcp-server](https://github.com/BeehiveInnovations/zen-mcp-server) 시도)
|
|
200
|
-
- 정적 분석 대체 (Semgrep / CodeQL과 함께 사용)
|
|
201
|
-
- 모든 PR에 자동 실행 (ccg는 트리아지 도구, 봇이 아닙니다)
|
|
202
|
-
- 스트리밍 출력 또는 멀티턴 대화
|
|
203
|
-
|
|
204
|
-
## 아키텍처 및 기여
|
|
205
|
-
|
|
206
|
-
ccg는 **7개 계층**으로 구성되며, "분기 검출"은 최상위 1개 계층일 뿐입니다. 아래 6개 계층(캐시, 원장, 사용량, 위험 라우팅, 스마트 diff, 안전한 CLI 스케줄링)은 각각 독립적으로 실제 문제를 해결합니다. `ccg.sh`를 변경하기 전에 [docs/ARCHITECTURE.ko.md](docs/ARCHITECTURE.ko.md)를 읽어주세요.
|
|
207
|
-
|
|
208
|
-
테스트:
|
|
209
|
-
|
|
210
|
-
```bash
|
|
211
|
-
bash tests/test_ccg.sh # 99개 회귀 테스트, ~31s
|
|
212
|
-
REAL_CLI=1 bash tests/test_ccg.sh # +2개 실제 API 테스트 (비용 발생)
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## 라이선스 및 감사의 말
|
|
216
|
-
|
|
217
|
-
MIT —— [LICENSE](LICENSE) 참조.
|
|
218
|
-
|
|
219
|
-
[oh-my-claudecode](https://github.com/Yeachan-Heo/oh-my-claudecode)의 원래 `/ccg` 컨셉 · Claude Code · OpenAI Codex CLI · Google Gemini CLI 기반.
|
package/README.zh-CN.md
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
# ccg — 代码分歧检测器
|
|
2
|
-
|
|
3
|
-
> Claude Code 的 slash command。装一次,在 diff 上输入 `/ccg`。
|
|
4
|
-
|
|
5
|
-
[]()
|
|
6
|
-
[](https://www.npmjs.com/package/@mcgrapeng/ccg)
|
|
7
|
-
[](LICENSE)
|
|
8
|
-
|
|
9
|
-
[English](README.md) | **简体中文** | [日本語](README.ja.md) | [한국어](README.ko.md) · [架构文档 →](docs/ARCHITECTURE.zh-CN.md)
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## ccg 是什么
|
|
14
|
-
|
|
15
|
-
你刚改完 `auth/login.go`,准备 merge。你想"保险一下"再走。今天你只有三种选择,每种都有硬伤:
|
|
16
|
-
|
|
17
|
-
- **单模型 review**(Copilot、Cursor `/review`、Aider)只给**一种视角**。如果 Claude 漏看了 timing attack,你也会一起漏。
|
|
18
|
-
- **多模型聚合工具**(zen-mcp-server 等)把多个模型的意见**平均化**,恰好遮盖了它们意见分歧的地方——而那才是你真正需要思考的位置。
|
|
19
|
-
- **手工双查**理论上最稳,但你没那个时间。
|
|
20
|
-
|
|
21
|
-
ccg 是 Claude Code 的 `/ccg` slash command,针对这三件事都做了真正的解决:
|
|
22
|
-
|
|
23
|
-
1. 把同一个 prompt **并行**发给 **Codex(OpenAI)** 和 **Gemini(Google)**
|
|
24
|
-
2. 让 **Claude** 读完两份报告,**聚焦它们意见不一致的地方**——人需要拍板的就在那里
|
|
25
|
-
3. 自动按代码风险选最便宜够用的模型、记录每次调用成本、保留历史评审账本
|
|
26
|
-
|
|
27
|
-
**类比理解**:就像让两个不同团队的 senior 工程师 review 同一份 PR,再让一个 tech lead 综合:"这几点他们都同意,这一点他们意见不一致——你来定,下面是我的看法。"
|
|
28
|
-
|
|
29
|
-
## 什么时候用 ccg
|
|
30
|
-
|
|
31
|
-
触发条件不是**领域**,而是**感觉**。当你看着自己刚写完的 diff,心里冒出下面这种念头,就是 ccg 的场景:
|
|
32
|
-
|
|
33
|
-
| 你心里在想 | 用 ccg? |
|
|
34
|
-
|---|---|
|
|
35
|
-
| "这个改错了,我凌晨会被叫起来" | ✅ 用 |
|
|
36
|
-
| "这是个判断题,没有一定对的答案" | ✅ 用 |
|
|
37
|
-
| "我希望有第二个人帮我看一眼" | ✅ 用 |
|
|
38
|
-
| "我就是改了个变量名" | ❌ 不用 |
|
|
39
|
-
| "只改了文档" | ❌ 不用 |
|
|
40
|
-
| "我想跟单个模型流式对话" | ❌ 不用(直接用 CLI) |
|
|
41
|
-
|
|
42
|
-
**跨领域真实例子** —— 都不是 auth / 加密的场景,但都是"两个资深工程师真会吵起来"的瞬间:
|
|
43
|
-
|
|
44
|
-
- **社交平台** —— feed 排序换了新的互动信号 · 评论树 fan-out 策略 · A/B 实验分桶逻辑 · 反滥用限流策略 · 关注关系的图数据库 schema
|
|
45
|
-
- **数据 / AI 基建** —— 换 embedding 模型(向量库要不要重建?) · 改 chunking 策略 · RAG 检索打分 · prompt injection 防御分层
|
|
46
|
-
- **前端** —— 新页面用 SSR 还是 ISR 还是 RSC · 缓存失效策略 · 状态管理重构 · 可访问性取舍
|
|
47
|
-
- **API 设计** —— 分页用 cursor 还是 offset · 错误响应模型 · 版本管理策略 · 幂等性 key 处理
|
|
48
|
-
- **分布式系统** —— 超时 / 重试策略 · cache TTL vs 事件驱动失效 · 分区容忍度取舍 · leader election 语义
|
|
49
|
-
- **数据库** —— 多步迁移的拆分顺序 · 热点路径的索引选择 · 事务隔离级别 · 软删 vs 硬删
|
|
50
|
-
- **安全** —— 对,auth / 加密 / 支付也属于这类 —— 但只是众多领域之一
|
|
51
|
-
|
|
52
|
-
**判断标准**:任何一个"合理的工程师可能选 A、另一个合理的工程师可能选 B"的改动,就是分歧检测赚回 $0.04 的时刻。
|
|
53
|
-
|
|
54
|
-
## 为什么是 ccg(和其他工具的对比)
|
|
55
|
-
|
|
56
|
-
**1. 分歧才是信号,不是噪音。**
|
|
57
|
-
当 Codex 说"加上 `subtle.ConstantTimeCompare` 防 timing attack",而 Gemini 说"bcrypt 自己就是恒定时间的,加包装是 cargo-cult"——**这才是你需要思考的地方**。别的工具会把这种冲突糊成一句模糊的"注意 timing 攻击"。ccg 把两边原话端给你。
|
|
58
|
-
|
|
59
|
-
**2. 内置成本可见性。**
|
|
60
|
-
Codex / Gemini CLI 都不告诉你花了多少钱。ccg 记录每次调用,按风险自动选最便宜够用的模型(risk-aware routing),相同 prompt 24h 内命中缓存零成本。`ccg_usage --this-month` 立刻回答"这个月我花了多少?"。
|
|
61
|
-
|
|
62
|
-
**3. 跨会话保留的评审历史。**
|
|
63
|
-
"两周前模型对 `src/auth.ts` 说了什么?"——ccg 的 append-only 账本能回答。任何无状态工具都做不到。
|
|
64
|
-
|
|
65
|
-
## 怎么安装
|
|
66
|
-
|
|
67
|
-
二选一:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# npm(推荐)
|
|
71
|
-
npx @mcgrapeng/ccg install
|
|
72
|
-
|
|
73
|
-
# 或 curl 一行装,无需 Node
|
|
74
|
-
curl -fsSL https://raw.githubusercontent.com/mcgrapeng/ccg/main/scripts/curl-install.sh | bash
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
再装两个 AI CLI(一次性):
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
npm i -g @openai/codex @google/gemini-cli
|
|
81
|
-
echo 'export GEMINI_API_KEY="<你的-key>"' >> ~/.zshenv
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
验证:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npx @mcgrapeng/ccg doctor # 检查 Codex / Gemini / API key
|
|
88
|
-
npx @mcgrapeng/ccg about # 看 7 层能力 + 当前环境状态
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## 完整使用示例
|
|
92
|
-
|
|
93
|
-
假设你刚改了 `auth/login.go`:
|
|
94
|
-
|
|
95
|
-
```go
|
|
96
|
-
// 改前 // 改后
|
|
97
|
-
func Login(user, pw string) bool { func Login(user, pw string) bool {
|
|
98
|
-
u := lookupUser(user) u := lookupUser(user)
|
|
99
|
-
- return u.Hash == sha256.Sum256([]byte(pw)) hashed, err := bcrypt.GenerateFromPassword([]byte(pw), 12)
|
|
100
|
-
+ if err != nil { return false }
|
|
101
|
-
+ return subtle.ConstantTimeCompare(u.Hash, hashed) == 1
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
你在 Claude Code 输入:
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
/ccg
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
约 30 秒后你会看到——**真实输出示例**,不是占位符:
|
|
112
|
-
|
|
113
|
-
```
|
|
114
|
-
📍 范围:worktree · 1 个文件 · +4 -1 行
|
|
115
|
-
🎯 模式:quality (风险=65 · auth+35 size>0+5 crypto-mention+25)
|
|
116
|
-
🩺 两个评审者都正常:Codex ✓ · Gemini ✓
|
|
117
|
-
💰 成本:$0.041
|
|
118
|
-
|
|
119
|
-
═══ AGREEMENT (2) — 两边都标记,信号弱 ═══
|
|
120
|
-
• auth/login.go:3 — sha256 不是密码哈希;换成 bcrypt 是对的
|
|
121
|
-
• auth/login.go:5 — bcrypt 错误要显式处理(你做了)
|
|
122
|
-
|
|
123
|
-
═══ DIVERGENCE (1) — 两个模型不一致 ★ 你来决定 ═══
|
|
124
|
-
|
|
125
|
-
▸ auth/login.go:6 — 怎么比较 bcrypt 哈希
|
|
126
|
-
🔵 Codex 说: "外包一层 subtle.ConstantTimeCompare 防 timing 攻击,
|
|
127
|
-
即使用了 bcrypt 也要加。"
|
|
128
|
-
🟢 Gemini 说:"bcrypt.CompareHashAndPassword 自身就是恒定时间的。
|
|
129
|
-
外包一层是 cargo-cult,反而可能因为长度不一致 panic。"
|
|
130
|
-
⚖️ Claude 综合:Gemini 是对的。bcrypt.CompareHashAndPassword 才是
|
|
131
|
-
标准比较方式;对它的原始输出做 ConstantTimeCompare 是
|
|
132
|
-
根本性错误——你比较的是"刚 hash 的 pw"和"存储的 hash",
|
|
133
|
-
而 bcrypt 每次 hash 都用新的盐,所以直接比较永远返回 false。
|
|
134
|
-
➡️ 建议动作: 把 ConstantTimeCompare 那行替换为:
|
|
135
|
-
`err := bcrypt.CompareHashAndPassword(u.Hash, []byte(pw))`
|
|
136
|
-
`return err == nil`
|
|
137
|
-
|
|
138
|
-
═══ BLINDSPOT (1) — 两边都没看到 Claude 怀疑 ═══
|
|
139
|
-
• 错误处理路径:bcrypt 出错时返回 false 对调用方是对的,但是会静默吞掉
|
|
140
|
-
基础设施错误(比如 bcrypt OOM)。建议加日志。
|
|
141
|
-
|
|
142
|
-
═══ VERDICT: fix-required ═══
|
|
143
|
-
当前比较逻辑会永远拒绝合法密码。按 DIVERGENCE 的建议改完 + 加错误日志,
|
|
144
|
-
就可以 merge 了。
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### 怎么看懂这份输出
|
|
148
|
-
|
|
149
|
-
| 段落 | 是什么意思 | 你该怎么办 |
|
|
150
|
-
|---|---|---|
|
|
151
|
-
| **AGREEMENT** | Codex 和 Gemini 都标记的同一个问题。你单源用 Claude 也大概率能发现——**新信息量低**。 | 扫一眼,没改的就改。 |
|
|
152
|
-
| **DIVERGENCE** ★ | 两个模型意见不一致。**这才是 ccg 存在的真正原因。** Claude 的"建议动作"给你推荐,但你是最终拍板的人。 | 仔细读,接受 Claude 判断或自己覆盖。 |
|
|
153
|
-
| **BLINDSPOT** | 两个模型都没看到,但 Claude 综合时怀疑。**慎用**——每次最多 2 条。 | 当提示看,不是金科玉律。 |
|
|
154
|
-
| **VERDICT** | `merge` / `fix-required` / `discuss`。一句话结论。 | 当 merge 门禁用。 |
|
|
155
|
-
|
|
156
|
-
评审完,`ccg_ledger_record` 会写一行 JSONL 到账本。两周后你可以:
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
source ~/.claude/commands/ccg.sh
|
|
160
|
-
ccg_ledger_query "auth/login.go"
|
|
161
|
-
# → "auth/login.go: 3 次评审 · 最近 2026-05-23 (fix-required) · 2026-05-09 (merge) · 2026-04-28 (discuss)"
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## 配置(默认值通常够用)
|
|
165
|
-
|
|
166
|
-
模式和模型都是自动的。需要时再覆盖:
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
CCG_MODE=quality /ccg # 任意 diff 都强制 quality 模型
|
|
170
|
-
CCG_CODEX_MODEL=o3 /ccg # 单独换某个模型
|
|
171
|
-
CCG_NO_CACHE=1 /ccg # 本次跳过 24h 缓存
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
常用配置(全部在 [架构文档 § 5](docs/ARCHITECTURE.zh-CN.md#5-扩展点)):
|
|
175
|
-
|
|
176
|
-
| 变量 | 默认 | 用途 |
|
|
177
|
-
|---|---|---|
|
|
178
|
-
| `CCG_MODE` | `auto` | `auto` / `cost` / `balanced` / `quality` |
|
|
179
|
-
| `CCG_CACHE_TTL_HOURS` | `24` | 缓存 TTL |
|
|
180
|
-
| `CCG_MAX_PROMPT_KB` | `100` | 单次 prompt 大小硬上限 |
|
|
181
|
-
|
|
182
|
-
成本参考(USD / 次,缓存命中 $0):
|
|
183
|
-
|
|
184
|
-
| 模式 | Codex | Gemini | 单次典型 |
|
|
185
|
-
|---|---|---|---|
|
|
186
|
-
| `cost` | gpt-5-nano | gemini-2.5-flash-lite | ~$0.0007 |
|
|
187
|
-
| `balanced` | gpt-5-mini | gemini-2.5-flash | ~$0.0046 |
|
|
188
|
-
| `quality` | gpt-5 | gemini-2.5-pro | ~$0.0440 |
|
|
189
|
-
|
|
190
|
-
随时查累计:
|
|
191
|
-
|
|
192
|
-
```bash
|
|
193
|
-
source ~/.claude/commands/ccg.sh
|
|
194
|
-
ccg_usage --this-month
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
## 不适合的场景
|
|
198
|
-
|
|
199
|
-
- Claude Code 之外的 IDE(试试 [zen-mcp-server](https://github.com/BeehiveInnovations/zen-mcp-server))
|
|
200
|
-
- 替代静态分析(要配合 Semgrep / CodeQL 用)
|
|
201
|
-
- 每个 PR 自动跑(ccg 是分诊工具,不是机器人)
|
|
202
|
-
- 流式输出或多轮对话
|
|
203
|
-
|
|
204
|
-
## 架构与贡献
|
|
205
|
-
|
|
206
|
-
ccg 一共 **7 层**,"分歧检测"只是最上面一层。下面 6 层(缓存、账本、用量、风险路由、智能 diff、安全 CLI 调度)各自独立解决真问题。改 `ccg.sh` 之前先读 [docs/ARCHITECTURE.zh-CN.md](docs/ARCHITECTURE.zh-CN.md)。
|
|
207
|
-
|
|
208
|
-
测试:
|
|
209
|
-
|
|
210
|
-
```bash
|
|
211
|
-
bash tests/test_ccg.sh # 99 个回归测试,~31s
|
|
212
|
-
REAL_CLI=1 bash tests/test_ccg.sh # +2 个真实 API 测试(会扣费)
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## 许可证与致谢
|
|
216
|
-
|
|
217
|
-
MIT —— 见 [LICENSE](LICENSE)。
|
|
218
|
-
|
|
219
|
-
基于 [oh-my-claudecode](https://github.com/Yeachan-Heo/oh-my-claudecode) 最初的 `/ccg` 概念 · Claude Code · OpenAI Codex CLI · Google Gemini CLI。
|