CHA

CHA — 순환형 적대적 하네싱 코딩 에이전트를 위한 배포 문턱 루프. Claude Code 플러그인.

CHA — Cyclic Hostile Adversarial Harnessing A release-gate loop for coding agents. A Claude Code plugin.

린터도 아니고 프롬프트 모음도 아닙니다. 이슈가 0 이 될 때까지 안 멈추고, 자기가 돌려 보지 않은 것은 믿지 않는 절차입니다.

Not a linter, not a prompt pack — a process that keeps running until the issue count is zero, and that refuses to believe anything it has not executed.

나머지를 다 떠받치는 규칙 하나: 돌려 보기 전에는 결함이 아니다.

The one rule that makes the rest work: a claim is not a defect until you have run it.

왜 이게 필요한가Why this exists

코딩 에이전트가 제 코드를 스스로 검토하는 것은, 고를 수 있는 검토자 중 제일 못 믿을 검토자를 고르는 일입니다. 그 코드를 제가 썼고, 같은 주석을 읽었고, 같은 자리가 안 보입니다. 그리고 확신이 없을 때 매끄럽고 자신 있는 틀린 답을 냅니다.

A coding agent reviewing its own work is the least reliable reviewer you can pick. It wrote the code, it read the same comments, it shares the same blind spots — and when it is unsure, it produces a fluent, confident, wrong answer.

흔한 처방은 안 듣습니다.

The usual patches don't hold.

「네 diff 를 검토해 봐」
“Review your own diff”
같은 모델 · 같은 맥락 · 같은 사각지대.
Same model, same context, same blind spot.
같은 모델로 한 번 더
A second pass from the same model
오류가 상관되어 있습니다. 자기 말에 동의합니다.
Correlated errors. It agrees with itself.
더 센 린터
A stricter linter
모양은 보지만 거짓말은 못 봅니다. 코드와 어긋난 주석은 초록입니다.
Finds shapes, not lies. A comment that contradicts its code is green.
검사를 더
More tests
아무것도 안 재는 검사도 초록입니다. 아무도 모릅니다.
A test that asserts nothing is also green. Nobody notices.

CHA 는 역할을 플랫폼째 가르고, 안 돌려 본 주장은 통과시키지 않는 것으로 이걸 막습니다.

CHA fixes this by splitting the roles across platforms and never letting a claim through unexecuted.

쓰면 얻는 것What you get

이점 하나하나를 루프의 장치 하나가 값을 치르고 얻어 오고, 그 장치가 실제로 일한 숫자가 같이 붙어 있습니다. 약속이 아니라 잰 것입니다.

Each benefit is bought by one device in the loop, and each comes with the number that showed the device working. Measured, not promised.

CHA — what you get Seven benefits, each read left to right: the failure it stops, the device in the loop that stops it, and the number that measured it. Confident wrong review claims are stopped by a second eye on another platform plus adjudication by execution: 57 claims to 22 true on deel, 67 settled to 22 true on a Luau game. A fix that never showed the bug is stopped by the red test first: 10 fail and 2 pass before a line was touched on CHA itself. A fix nobody guards is stopped by a mutant per fix: 20 of 92 leaked on their first run in the game. A green build that measures nothing is stopped by counting unmeasurable as failure: 24 hidden behind a green build on deel. A refusal filed as an answer is stopped by classifying every run: the game record said lost 0 and it was lost 2. Half-applied fixes are stopped by one writer and a read-only reviewer: the shape was found 3 times. Falling for the same false claim again is stopped by an append-only record: 2,745 lines on deel, none deleted. 쓰면 얻는 것 · what you get the failure it stops → the device that stops it → the number that measured it 막는 실패/ the failure it stops 루프의 장치/ the device 잰 것/ measured 그럴듯하지만 틀린 리뷰 지적confident review claims that are wrong 2차 눈 + 실행으로 판정another platform reviews · execution decides 57 → 22 · 67 → 22주장 → 참 · deel 과 게임claims → true · the rest never touched code 무엇을 고쳤는지 모르는 고침a fix that never showed the bug 빨간 검사 먼저watch it fail before the fix, keep the output 10 fail / 2 passCHA 자기 검수, 한 줄 고치기 전CHA on itself, before a line was touched 아무도 안 지키는 고침a fix nobody guards, deleted later 고친 자리마다 어긋break the fixed line, a test must go red 20 / 92게임: 처음 돌 때 샌 어긋game: mutants that leaked on their first run 아무것도 안 재는 초록a green build that measures nothing 못 잼은 실패로 센다unmeasurable fails the sweep 24deel: 초록 뒤에 숨어 있던 어긋deel: 2 leaked + 22 drifted anchors 거절 문구가 답으로 저장됨a refusal filed as a clean answer 끝난 모양마다 이름을 붙인다every run classified: quota, refusal, empty… lost 0 → lost 2게임: 거절 문구가 답으로 저장된 둘game: two refusals saved as answers 두 손이 고쳐 반만 붙은 고침two writers, a half-applied fix 쓰는 곳 하나 · 2차 눈은 읽기 전용one writer · read-only reviewer, enforced 3deel: 반만 붙은 고침, 모두 한 모양deel: half-applied fixes, one shape each time 같은 거짓 지적에 또 속음the same false claim, back in new words 반증까지 적는 덧붙임 기록append-only record, counter-evidence kept 2,745deel: 한 줄도 안 지운 기록deel: lines of record, none deleted 모두 잰 숫자다 — deel 관문 39 · Luau 게임 2026-09-22 · CHA 자기 검수. 벤치마크가 아니라, 루프가 실제 결함을 찾는다는 증거다. Every number was measured: deel at gate 39, a Luau game on 2026-09-22, CHA on itself. Evidence the loop finds real things, not a benchmark.

그림은 옆으로 밀어서 볼 수 있습니다.

The diagram scrolls sideways.

왼쪽부터 막는 실패, 그것을 막는 장치, 그 장치가 일한 숫자. deel 은 관문 39, 게임은 2026-09-22, CHA 는 자기 자신에게 돌린 회차의 값입니다.
Left to right: the failure it stops, the device that stops it, the number that measured it. deel at gate 39, the game on 2026-09-22, CHA in its own rounds.
AI 리뷰를 믿지 않고도 쓸 수 있습니다
An AI reviewer you can use without trusting it
2차 눈은 다른 플랫폼에서 읽기만 하고, 지적은 하나하나 돌려 봐서 가릅니다. deel 에서 57건 중 참 22건, 게임에서 결론 난 67건 중 참 22건. 거짓은 코드에 손대지 않았습니다.
It reviews from another platform, read-only, and every claim is settled by running it. On deel 22 of 57 were true; on the game, 22 of 67 settled. The false ones never touched the code.
고침마다 무엇을 고쳤는지 증거가 남습니다
Proof of what each fix fixed
빨간 검사가 먼저입니다. CHA 를 자기 자신에게 돌렸을 때, 한 줄 고치기 전 검사는 10 실패 / 2 통과 였습니다.
The red test comes first. On CHA itself the suite read 10 fail / 2 pass before a line was touched.
나중에 누가 고침을 지우면 검사가 빨개집니다
A test that goes red if a fix is deleted later
고칠 때마다 어긋을 박습니다. 게임에서는 어긋 92개 중 20개가 처음 돌 때 샜습니다. 결함에서 빨갛고 고침에서 초록인데 아무것도 안 지키던 검사였습니다.
Every fix gets a mutant. On the game, 20 of 92 leaked on their first run: checks that went red on the defect and green on the fix, and guarded nothing.
초록이 「뭔가를 쟀다」는 뜻이 됩니다
A green that means something was measured
못 잼은 실패로 세고, 관문은 「통과」가 아니라 숫자로 적습니다. deel 의 초록 빌드 뒤에 어긋 24개가 숨어 있었습니다. 샌 것 2, 아무것도 안 재던 것 22.
Unmeasurable counts as failure, and the gate reports numbers, never the word “pass”. Behind deel’s green build were 24 mutants: 2 leaked, 22 measuring nothing.
조용히 잃는 것이 없습니다
Nothing lost quietly
2차 눈의 실행마다 끝난 모양에 이름을 붙입니다. 잘림 · 쿼터 · 도구 막힘 · 빈 답. 게임 기록의 「잃음 0」은 잃음 2 였고, 둘 다 거절 문구가 답으로 저장된 것이었습니다.
Every second-eye run is classified: truncated, quota, blocked on a tool, empty. The game’s record said “lost 0”. It was lost 2, both refusals saved as answers.
반만 붙은 고침이 안 나옵니다
No half-applied fixes
쓰는 곳은 하나이고, 2차 눈의 읽기 전용은 선언이 아니라 검사됩니다. deel 에서 나온 반만 붙은 고침 3건은 전부 쓰는 곳이 둘일 때의 모양이었습니다.
One writer, and the reviewer’s read-only boundary is checked rather than declared. The three half-applied fixes on deel all had the two-writer shape.
같은 거짓 지적에 값을 한 번만 치릅니다
The same false claim costs you once
기록은 덧붙이기만 하고, 거짓 판정에는 반증을 같이 적습니다. 같은 지적이 몇 회차 뒤에 다른 말로 돌아오기 때문입니다. deel 의 기록은 2,745줄, 한 줄도 안 지웠습니다.
The record is append-only, and a false verdict is filed with its counter-evidence, because the same claim comes back a few rounds later in different words. deel’s record: 2,745 lines, none deleted.

드는 값. 판정은 지적 수에, 전수 어긋내기는 어긋 수 × 검사 한 판의 시간에 비례합니다. 시계로 잰 것은 deel 의 전수 한 번(1,149개 · 2시간 46분)뿐이고, 나머지는 저장소마다 다릅니다.

What it costs. Adjudication grows with the number of claims, and the full sweep with mutants × one test run. The only wall-clock figure measured is deel’s full sweep, 1,149 mutants in 2h46m; the rest depends on the repository.

루프 — 아홉 걸음The loop — nine steps

순서대로 돕니다. 하나를 건너뛴다고 빨라지지 않습니다. 값이 더 안 보이는 자리로 옮겨 갈 뿐입니다.

They run in order. Skipping one does not speed the loop up — it moves the cost to a place where it is harder to see.

CHA — the nine-step loop Nine steps in a closed cycle: hunt, brief, second eye, adjudicate, red test, fix, mutant, gate, record. Step three runs on another platform and is read-only. While the open issue count is above zero the loop returns to step one. CHA — 순환형 적대적 하네싱 Cyclic Hostile Adversarial Harnessing · the nine-step loop 다른 플랫폼 · 읽기 전용 another platform · read-only 1 사냥hunt first eye reads a slice, writes suspicions 2 브리핑brief cut to ≤20KB + the promises 3 2차 눈second eye another platform, read-only 4 판정adjudicate run it: 참 / 거짓 / 못 잼 5 빨간 검사red test prove the failure first 6 고침fix one writer, one defect 7 어긋mutant break it on purpose 8 관문gate real numbers, not "pass" 9 기록record append, never delete 이슈 > 0 ? / issues > 0 ? 관문이 초록이고 열린 항목이 0 일 때만 멈춘다. 배포는 사람이 허락한 뒤에만. It stops only when the gate is green and the open count is zero. Nothing ships without an explicit human go-ahead.

그림은 옆으로 밀어서 볼 수 있습니다.

The diagram scrolls sideways.

아홉 걸음. 3번만 다른 플랫폼에서 돌고, 나머지는 전부 쓰는 곳 한 군데에서 돕니다.
Nine steps. Only step 3 runs on another platform; everything else runs where the one writer is.
  1. 1 사냥 / hunt 1차 눈이 한 조각을 읽고 「의심」을 적는다. 판정은 안 한다. The first eye reads a slice and writes down suspicions. No verdicts.
  2. 2 브리핑 / brief 소스를 20KB 이하로 자르고, 코드가 스스로 한 「약속」을 붙인다. Cut the source into chunks of at most 20KB, with the promises the code makes attached.
  3. 3 2차 눈 / second eye 다른 플랫폼 · 고정된 모델 id · 읽기 전용 · 결함만. Another platform, a pinned model id, read-only, defects only.
  4. 4 판정 / adjudicate 돌려 본다. 참 / 거짓 / 못 잼. Run it. 참 true / 거짓 false / 못 잼 unmeasurable.
  5. 5 빨간 검사 / red test 소스를 건드리기 전에 실패를 증명한다. 빨개지는 것을 눈으로 본다. Prove the failure before touching the source. Watch it go red, and keep the output.
  6. 6 고침 / fix 쓰는 곳은 한 군데. 커밋 하나에 결함 하나. One writer. One defect per commit.
  7. 7 어긋 / mutant 고친 줄을 일부러 망가뜨리고, 검사가 알아채는지 본다. Break the fix on purpose and confirm a test notices.
  8. 8 관문 / gate 검사 + 검사기 + 문서. 「통과」가 아니라 실제 숫자로 적는다. Tests, lint, docs — reported as real numbers, not as the word “pass”.
  9. 9 기록 / record 끝에 보탠다. 영영 안 지운다. Append forever. Never delete.

이슈 > 0 ? ──► 1번으로 issues > 0 ? ──► back to 1

숫자가 0 위에 있는 동안에는 아무것도 안 나갑니다. 끝나는 조건은 「알려진 버그 없음」이 아니라 「답 못 한 질문 없음」입니다 — 안 가른 지적 0, 샌 어긋 0, 못 잰 어긋 0, 초록 관문, 기록 보탬. 둘은 다르고, 확인할 수 있는 쪽은 뒤엣것뿐입니다.

Nothing ships while the count is above zero. The termination condition is not “no known bugs” but “no unanswered questions” — zero open claims, zero leaked mutants, zero unmeasurable mutants, a green gate, and the round appended to the record. Those are different, and only the second one can be checked.

조각들이 어떻게 붙나How the pieces connect

그림에서 제일 중요한 선은 가운데 점선입니다. 코드를 쓰는 곳은 왼쪽 하나뿐이고, 오른쪽 2차 눈은 브리핑 글을 받아 지적 글을 돌려줄 뿐 저장소에 손을 못 댑니다.

The important line in this diagram is the dashed one down the middle. Only the left side writes code. The second eye on the right receives briefing text and returns claim text; it never touches the repository.

믿고 안 믿고의 문제가 아닙니다. 쓰는 곳이 둘이면 둘이 만나는 자리를 아무도 안 읽습니다 — 한쪽이 봉인을 옮기고 다른 쪽이 그 봉인이 지키던 것을 옮기면, 각자 검사는 따로 초록이고 결함은 그 사이에 삽니다. 실제로 나온 꼴은 언제나 「머리말은 옳은 행동을 적고 있고, 코드는 두 부르는 자리 중 한 군데만 그렇게 하고 있다」 였습니다. 세 번 나왔습니다.

This is not about trust. With two writers, nobody reads the place where the two edits meet — one moves a guard, the other moves the thing it guarded, each suite is green separately, and the defect lives in between. The shape it actually took was always the same: the header describes the correct behaviour and only one of two call sites implements it. Found three times.

CHA — how the pieces connect A left-to-right data flow. Everything with write access is on the left of a dashed read-only boundary: the plugin tools, the .cha files and the one writer. On the right is the second eye, on another platform with a pinned model id and no write tools, no shell and no repository access. It receives briefing text and returns claim text, and nothing else crosses. The boundary is enforced by tools/readonly.mjs from the mode and writer keys, not merely declared. 조각들이 어떻게 붙나 · how the pieces connect one writer on the left · a read-only second eye on the right · every artefact under .cha/ 쓰는 곳 하나 / one writer Claude Code + this plugin — the only thing with write access to the repo 읽기 전용 경계 / read-only boundary tools/readonly.mjs · mode + writer .cha/config.jsongate · secondEye · briefing.maxBytes · mutate · writer모든 도구가 읽는다 / every tool reads this src/**the source under review tools/brief.mjs≤20480 bytes · + .cha/house.md .cha/briefings/*.md tools/queue.mjsserial · kind-aware · asks smaller .cha/answers/*.md 판정 / adjudicate돌려 본다 / by execution 빨간 검사 / red testwatch it fail first 고침 / fixone writer, one defect tools/add-mutant.mjsanchor lifted, never retyped .cha/mutants.json tools/mutate.mjsrestore in a finally 잡음 / 샜음 / 못 잼caught / leaked / unmeasurable 관문 / gatetests · check · docs tools/record.mjsappend grows · --set holds .cha/record.md보태기만 · append-only · never edited downward 2차 눈 / second eye 다른 플랫폼another platform 모델 id 못박음pinned model id 받는 것: 브리핑 글만receives: briefing text only 보내는 것: 지적 글만returns: claim text only 쓰기 도구 · 셸 · 저장소 접근 없음no writes · no shell · no repo 파일 / file 도구 / tool (tools/*.mjs) 단계 / step 쓰는 곳이 둘이면 두 수정이 만나는 자리를 아무도 안 읽는다. 반만 붙은 고침이 나오는 자리가 거기다 — 세 번 나왔다. Two writers produce edits whose interaction nobody read. That is where half-applied fixes come from — found three times.

그림은 옆으로 밀어서 볼 수 있습니다.

The diagram scrolls sideways.

왼쪽은 쓰는 곳 하나, 오른쪽은 읽기만 하는 2차 눈. 가운데 점선이 읽기 전용 경계입니다. 아래쪽은 .cha/ 의 파일들과 그것을 만드는 도구들.
One writer on the left, a read-only second eye on the right, the read-only boundary down the middle. Below: the files in .cha/ and the tools that produce them.

실제로 잰 숫자Measured on a real codebase

CHA 는 책상에서 설계한 것이 아니라, 의존성 0 짜리 Node CLI 코딩 에이전트의 배포 검수에서 뽑아낸 절차입니다.

CHA was not designed on a whiteboard. It was extracted from the release review of a zero-dependency Node CLI coding agent.

검수 대상Source under review
171 files · 77,607 lines
검사Tests
154 files · 75,499 lines
마지막 관문Last gate
12,596 pass · 0 fail · 1 skip · 156 of 156 files exited cleanly
검사기Style check
OK across 167 files · 170 shipped files all LF
문서 검사Docs check
62 pages · 0 broken links
등록된 어긋Mutants registered
1,179 · across 138 source files / 119 test files
마지막 전수 어긋내기Last full mutation sweep
1,149 in 2h46m → 1,125 caught · 2 leaked · 22 unmeasurable
돌린 관문Gates run
39
2차 눈 브리핑Briefings sent
39
올라온 지적 → 참Claims received → true
57 → 22
실제로 고친 자리Fixes landed
19
못 잼으로 적은 지적Claims recorded unmeasurable
4
누적 기록Cumulative record
2,745 lines · 한 번도 안 지움2,745 lines · append-only
커밋Commits
434

관문 39(2026-09-16) 시점의 값입니다. 회차가 돌면 바뀝니다 — 누적 합계가 아니라 한 번 잰 그 순간의 사진입니다. 루프는 아직 안 멈췄습니다.

Every figure above is the state at gate 39 (2026-09-16). Later rounds move them — this is a snapshot of one measured moment, not a running total. The loop has not stopped.

초록 뒤에 숨어 있던 스물넷The 24 the green build was hiding

전수 어긋내기가 찾아낸 것은 「아무 검사도 안 잡는 어긋 2개」와 「앵커가 낡아 아무것도 안 재고 있던 어긋 22개」였습니다. 뒤엣것이 더 위험합니다 — 목록에 이름이 있고, 개수에 세어지고, 빨강으로도 초록으로도 안 보입니다.

The full sweep found 2 mutants that no test caught, and 22 whose anchors had drifted — they were in the list, named, counted as present, and measuring nothing. That second category is the dangerous one: it is invisible in a red run and in a green run alike.

이 숫자가 아닌 것. 저장소 하나 · 검토자 짝 하나 · 사람 하나에서 나온 숫자입니다. 루프가 실제 결함을 찾아낸다는 증거이지, 벤치마크가 아닙니다. 다른 저장소에서 같은 비율이 나온다는 뜻도 아니고, 여기 있는 어떤 숫자도 다른 방법과 견준 적이 없습니다.

What these numbers are not. They come from one codebase, one reviewer pairing, one person. They are evidence that the loop finds real things — not a benchmark. They do not claim the same ratios hold elsewhere, and none of them has been compared against another method.

두 번째 도메인: Roblox 게임A second domain: a Roblox game

deel 과 공통점이 없는 대상입니다. Luau 로 쓴, 당시 공개 전이던 Roblox 멀티플레이 호러 게임이고, 기계에는 Luau 런타임이 없었습니다. 게임은 비공개라서 코드는 인용하지 않고 숫자와 결함의 모양만 적습니다.

Nothing in common with deel: a multiplayer Roblox horror game written in Luau, unreleased at the time, on a machine with no Luau runtime. The game is private, so its code is not quoted, only the numbers and the shapes of the defects.

검수 대상Source under review
58 Luau files · 24,401 lines
마지막 관문Gate at the end
23 checks green · 4 static · 18 red tests · 1 rig geometry
기록된 결함Defects recorded
21 logic · security · lifecycle · 7 character model
어긋Mutants
92, all caught at the end · 20 leaked on their first run
2차 눈Second eye
gemini-3.8-flash-high via agy, read-only · 30 sent → 27 answered · 3 lost
올라온 지적 → 실행으로 가른 것Claims → settled by execution
128 → 67 settled → 22 true · 45 false · 58 never adjudicated

거짓 비율은 도메인이 바뀌어도 유지됐습니다The false rate held across domains

결론 난 지적의 67% 가 거짓이었고, deel 에서는 61% 였습니다. 언어도 리뷰어도 프로그램 종류도 다른데, 확신에 찬 지적 열에 여섯에서 일곱은 읽어서는 드러나지 않는 방식으로 틀렸습니다.

67% of the settled claims were false; on deel it was 61%. Different language, different reviewer, different kind of program, and still six or seven confident findings in ten were wrong in ways reading could not reveal.

도메인이 바꾼 것은 갈래가 아니라 생김새The domain changed the look of the defects, not their classes

Luau 표의 nil 구멍이 레이캐스트 필터에서 플레이어 자기 몸을 빼 버렸습니다. 클라이언트가 보낸 NaN 이 형 검사와 math.clamp 를 통과해 그 플레이어의 저장을 영구히 망가뜨렸습니다. 실린더 메시는 엔진이 가로와 세로를 같게 강제하는 탓에 원반으로 그려졌고, 소스를 아무리 읽어도 그건 안 보입니다.

A nil hole in a Luau table dropped the player’s own body out of a raycast filter. A NaN sent from the client passed a type check and math.clamp and permanently broke that player’s saves. A cylinder mesh rendered a disc because the engine forces width equal to length, which no amount of reading the source shows.

그 실행의 기록도 양쪽으로 한 번씩 잘못 셌습니다. 「잃음 0」은 잃음 2 였고, 한 회차의 「거짓 82%」는 지적 16건을 두 번 센 것이라 실제로 68% 였습니다. 게임 하나 · 리뷰어 하나 · 하루의 숫자이고, 128건 중 58건은 판정하지 못했습니다. CHA 가 거기서 가져온 것이 1.3.0 입니다.

The run’s own record miscounted twice, in both directions. “Lost 0” was lost 2, and one round’s “82% false” was 68% once sixteen double-counted claims were counted once. One game, one reviewer, one day, and 58 of the 128 claims were never adjudicated. What CHA took back from it is 1.3.0.

자기 자신에게 돌려 봤습니다Run against itself

CHA 를 제 저장소에 세 회차 돌렸습니다. 1.1.0 부터 배포마다 한 회차이고, 모든 지적은 아무것도 고치기 전에 돌려서 갈랐습니다.

CHA has been pointed at its own repository for three rounds, one per release since 1.1.0. Every claim was settled by running it before anything was edited.

회차Rounds
3 · 2026-09-18 (1.1.0) · 2026-09-20 (1.2.0) · 2026-09-22 (1.3.0)
돌려서 가른 지적Claims settled by execution
49 → 33 참 · 4 거짓 · 12 못 잼
고침Fixes landed
30 · 빨간 검사 먼저30 · red test first
어긋Mutants registered
49 · last sweep 49 잡음 · 0 샜음 · 0 못 잼 in 25m32s
도구 검사Tool tests
67 · 1회차는 12 에서 시작67 · round 1 started from 12

관문 4(2026-09-22) 시점의 값입니다. 도구 검사는 2026-10-07 에 다시 돌렸습니다: 67 통과 / 0 실패 / 0 건너뜀.

The state at gate 4 (2026-09-22). The tool tests were re-run on 2026-10-07: 67 pass / 0 fail / 0 skip.

찾으라고 만든 도구 안에 있던 결함The defect classes, inside the tools built to find them

1회차: 제한시간에 죽은 검사가 잡음 으로 셌습니다. 아무것도 못 잰 줄이 건강한 쪽에 앉아 있었습니다. 2회차: secondEye.mode: "read-only" 와 writer: "claude-only" 는 어느 코드도 읽지 않았는데, 구조 그림은 그 둘을 경계로 그리고 있었습니다. 3회차: 거짓 지적 셋이 전부 이쪽에서 나왔고, 그중 하나인 그럴듯한 agy 명령줄은 설치 문서 초안에 들어가 그대로 나갈 뻔했습니다. 그걸 가른 것은 실제 실행 하나뿐이었습니다.

Round 1: a mutation whose test was killed at the timeout was scored 잡음, so an unmeasured line sat on the healthy side of the table. Round 2: secondEye.mode: "read-only" and writer: "claude-only" were read by nothing, while the architecture diagram drew them as a boundary. Round 3: all three false claims came from this side, and one, a plausible agy command line in the draft of the setup docs, would have shipped. Only a live run told it apart from the working one.

다섯 갈래 결함The five defect classes

브리핑마다 이 다섯을 붙입니다. 회차를 거듭하며 살아남은 갈래이고, 린터가 못 보고 같은 모델이 이름 붙이지 못하는 것들입니다.

Every briefing carries these. They are the classes that survived round after round — the ones a linter cannot see and a same-model review will not name.

  1. 실제 입력에 절대 안 맞는 규칙A rule that never matches real input

    /(1b|2b|3b)/ 가 qwen2.5-coder:32b — 32B 모델 — 을 「작은 모델」로 셌습니다. 32b 안에 2b 가 들어 있어서요.

    /(1b|2b|3b)/ marked qwen2.5-coder:32b — a 32B model — as “too small”, because 32b contains 2b.

  2. 조용한 실패Silent failure

    못 읽은 시트를 catch { continue; } 로 건너뛰고, 결과는 「다 읽었습니다」 였습니다.

    A sheet that could not be read was skipped with catch { continue; } and the result still said “read everything”.

  3. 안 지키는 검사A test that does not guard

    이름은 「셈이 숫자가 아니면 안 받는다」 인데 'many' 하나만 물어봐서, '3' · null · true · [] 가 전부 그냥 지났습니다.

    Named “rejects non-numeric counts”, it asked only about 'many', and let '3', null, true and [] straight through.

  4. 주석과 코드의 모순Comment contradicts code

    머리말은 「ok 없는 줄은 성공으로 안 친다」 인데 코드는 성공으로 셌고, 실패율이 실제보다 낮게 나왔습니다.

    The header said “a line with no ok is not counted as a success”; the code counted it as one, and the failure rate came out lower than reality.

  5. 신뢰 경계 누수Trust-boundary leak

    --offline 봉인을 바깥 주소를 세 번 두드린 뒤에 — 열쇠까지 실어 보낸 뒤에 — 봤습니다.

    --offline was checked after the connection had already knocked on the external address three times, with the key attached.

판정은 셋 — 그리고 셋째가 핵심Three verdicts — and the third one is the point

주장이 참이 되는 조건 하나: 거짓이었다면 다르게 굴었을 무언가를 실제로 돌려 봤을 때.

A claim is true when you have run something that would have behaved differently if it were false.

참 / true
돌려 봤고, 잘못된 동작이 나왔다. 명령과 그 출력을 같이 적는다.
Ran it, saw the wrong behaviour. The command and its output go into the record.
거짓 / false
돌려 봤고, 그런 동작이 안 나왔다. 「아니오」가 아니라 반증을 적는다. 같은 지적이 몇 회차 뒤에 다른 말로 다시 올라오기 때문입니다.
Ran it, did not see it. Record the counter-evidence, not just “no” — the same claim comes back a few rounds later in different words.
못 잼 / unmeasurable
여기서는 못 돌린다, 또는 주장이 양쪽으로 읽힌다. 절대 거짓으로 적지 않습니다. 깨끗한 성적표를 위해 못 잰 것을 거짓으로 미는 순간, 숫자 전체가 뜻을 잃습니다.
Cannot be run here, or the claim reads both ways. Never recorded as false. The moment an unmeasurable claim is filed as false to keep the sheet clean, every other number on the sheet stops meaning anything.

어긋내기에서도 같습니다. 못 잼은 실패로 셉니다. 조용히 안 맞는 앵커는 「돌아가고, 아무것도 안 재고, 총계는 건강해 보이는」 줄이고 — 그게 바로 이 루프가 잡으려는 결함이 도구 안쪽에 들어앉은 모양입니다.

The same holds in the mutation sweep. Unmeasurable counts as failure. An anchor that silently stops matching is a line that runs, measures nothing, and keeps the total looking healthy — which is precisely the defect class this loop hunts, living inside the tool meant to find it.

CHA — 57 claims, split by execution Fifty-seven second-eye claims enter and are split by execution, not by reading. Twenty-two were true and nineteen fixes landed. The false ones were recorded with counter-evidence and no code was edited. Four were unmeasurable and were recorded as unmeasurable, never as false. 주장 57건, 실행으로 가른다 57 claims · split by execution, never by plausibility 실행으로 가른다 / split by execution a claim is true when you have run something that would behave differently if it were false 주장 5757 claims received39 briefings · 39 rounds 참true 22 고침 1919 fixes landed빨간 검사 먼저 · 어긋으로 지킴 / guarded 거짓false 반증을 기록counter-evidence recorded코드는 안 건드림 / no code edited 못 잼unmeasurable 4 기록. 거짓 아님recorded, never as false하네스의 지도 / a map of the harness 실행이 아니라 그럴듯함으로 움직였으면, 멀쩡한 코드에 35번 손을 댔을 것이다. Acting on plausibility instead of execution would have meant 35 edits to working code. 57 − 22 = 35. 잰 숫자다, 어림이 아니다 / measured, not estimated.

그림은 옆으로 밀어서 볼 수 있습니다.

The diagram scrolls sideways.

지적 57건이 실행으로 셋으로 갈립니다. 그럴듯함으로 움직였으면 멀쩡한 코드에 35번 손을 댔을 것입니다.
Fifty-seven claims split three ways by execution. Acting on plausibility instead would have meant 35 edits to working code.

CHA 가 안 하는 것What CHA refuses to do

설치Install

Claude Code 안에서:

Inside Claude Code:

/plugin marketplace add jysvai/CHA
/plugin install cha@cha

그다음, 검수할 저장소에서:

Then, in the repo you want to review:

/cha-init

.cha/(설정 · 누적 기록 · 어긋 목록)를 깔고, 관문 명령을 알아내고, 2차 눈에 무엇이 필요한지 알려 줍니다. 명령 열한 개 · 스킬 여섯 개 · 에이전트 세 개 · 의존성 0.

That writes .cha/ — config, cumulative record, mutant list — detects the gate commands, and tells you what your second eye needs. Eleven commands, six skills, three agents, zero dependencies.