Skip to content
Conduit

skill

CHA

CHA (Cyclic Hostile Adversarial Harnessing) — Cross-checking LLM pipeline for deep code debugging

jysvai/CHAcommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/jysvai/CHA itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 21, 2026

CHA — Cyclic Hostile Adversarial Harnessing

한국어 문서: README.ko.md

A release-gate loop for coding agents. 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:

PatchWhy it fails
"Review your own diff"Same model, same context, same blind spot.
A second pass from the same modelCorrelated errors. It agrees with itself.
A stricter linterFinds shapes, not lies. A comment that contradicts its code is green.
More testsA test that asserts nothing is also green. Nobody notices.

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

  • A different platform reviews (Gemini, Codex, GPT — any second eye). Different training, different failure modes, uncorrelated hallucinations.
  • Only one agent writes code (Claude). Edits stay serialized, so a fix is never half-applied by two writers.
  • Every claim is adjudicated by execution. In the measured run, 57 claims → 22 true. Roughly 6 in 10 confident findings were wrong, and reading alone would not have told you which.
  • Every fix is proved red first, then green.
  • Every fix gets a mutant: break the fixed line on purpose and confirm a test goes red. If it stays green, the fix is unguarded and someone will delete it.
  • A false warning is a defect. Code that cries wolf costs the same as code that is silent.

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.

You getBecauseMeasured
An AI reviewer you can use without trusting it.It reviews from another platform, read-only, and every claim is settled by running it.deel 57 → 22 true · the game 67 settled → 22 true. The false ones never touched the code.
Proof of what each fix fixed.The red test comes first, and its output is kept.CHA on itself: 10 fail / 2 pass before a line was touched.
A test that goes red if a fix is deleted later.Every fix gets a mutant: the fixed line, broken on purpose.The game: 20 of 92 mutants leaked on their first run, each a check that guarded nothing.
A green that means something was measured.Unmeasurable counts as failure, and the gate reports numbers, never the word "pass".deel: 24 mutants hiding behind a green build: 2 leaked, 22 measuring nothing.
Nothing lost quietly.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.One writer, and the reviewer's read-only boundary is checked, not declared.deel: 3 half-applied fixes, every one the two-writer shape.
The same false claim costs you once.An append-only record that files every false verdict with its counter-evidence.deel: 2,745 lines of record, none deleted.

What it costs is in the FAQ: adjudication grows with the number of claims, and the full sweep with mutants × test time.


Measured on a real codebase

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

Source under review171 files · 77,607 lines
Tests154 files · 75,499 lines
Test results at the last gate12,596 pass · 0 fail · 1 skip · 156/156 files exit clean
Mutants registered1,179 across 138 source files / 119 test files
Last full mutation sweep1,149 mutants · 2h46m · 1,125 caught · 2 leaked · 22 unmeasurable — all 24 resolved
Gates run39
Second-eye briefings in the last round39
Claims raised → confirmed by execution57 → 22
Fixes landed in that round19
Cumulative record2,745 lines, never deleted
Commits434

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 that the green build was hiding. 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 last category is the dangerous one: it is invisible in both a red run and a green run.


Measured on a second domain: a Roblox game

The loop was run on something with 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 only thing that could run was a static check over the source. The game is private, so its code is not quoted, only the numbers and the shapes of the defects.

Source under review58 Luau files · 24,401 lines
Gate at the end23 checks green (4 static · 18 red tests · 1 rig geometry), re-run 2026-09-22
Defects recorded21 in logic, security and lifecycle · 7 in the character model
Mutants92, all caught at the end · 20 leaked the first time they ran
Second eyegemini-3.8-flash-high via agy, read-only · 30 briefings → 27 answered · 3 lost
Claims raised → settled by execution128 → 67 settled → 22 true · 45 false (58 never adjudicated)

The false rate held across domains. 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 what the defects looked like, not their classes. 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. The engine's respawn path skipped the cleanup that the ending path ran. A cylinder mesh rendered a disc because the engine forces width equal to length, which no amount of reading the source shows.

Mutation mattered more where nothing runs. One in five mutants leaked the first time it ran. Each leak was a check that went red on the defect and green on the fix and still guarded nothing.

The run's own record miscounted twice, in both directions. "Lost 0" was really 2 lost: a tool refusal saved as the answer. A round's "82% false" was really 68%: sixteen claims counted twice. What CHA took back from it is 1.3.0: Lua support, a call-site index in every briefing, refusal files read as not answered, and a declared reviewer. Details: docs/en/09-results.md.


Run against itself

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.

Rounds3 · 2026-09-18 (1.1.0) · 2026-09-20 (1.2.0) · 2026-09-22 (1.3.0)
Claims settled by execution49 → 33 참 · 4 거짓 · 12 못 잼
Fixes landed30, red test first
Mutants registered49 · last full sweep 49 잡음 · 0 샜음 · 0 못 잼, 25m32s
Tool tests67 checks · round 1 started from 12, the first this repository had

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

Round 1 found eight defects in its own tools. Before a line was touched, the suite went 10 fail / 2 pass. The ones worth naming: a mutation whose test was killed at the timeout was scored 잡음, so an unmeasured line sat on the healthy side of the table. A mutant list written the way the FAQ offers lost its entries while still showing them in the file. secondEye.maxRetries: "six" made the queue send nothing and report success. --max 20kb removed the cap and shipped a 41.9KB briefing under the line cap NaNKB. All four are this repository's own defect classes, living in the tools built to find them.

Breaking the fixes on purpose found two more: a test that could not tell two reasons apart, and a control flaky one run in four — invisible until the timeout fix stopped scoring slowness as success.

Round 2 ported the four devices the live deel loop had and this repository did not, and found eleven defects doing it. Four were one shape: something the repository said about itself that no code made true. secondEye.mode: "read-only" and writer: "claude-only" were read by nothing, while the architecture diagram drew them as a boundary. One more was found only by looking at the machine: the sweep had leaked 76 runaway processes, and the timings it printed were measured inside load it was creating.

Round 3 brought back what the game run taught: 14 claims → 11 참 · 3 거짓. All three false ones came from this side. One of them, a plausible agy command line already written into the draft of the setup docs, would have shipped. Only a live run told it apart from the working one.

The rounds, with the command next to every number: .cha/record.md.


The loop

Nothing ships while the count is above zero, and nothing ships without an explicit human go-ahead.

Step by step, with each one's entry and exit condition: docs/en/02-loop.md.


How the pieces connect

Everything that can write is on one side of a line: the plugin, the tools, the .cha/ files, and the single agent that edits code. The second eye is on the other side, on another platform, with a pinned model id and no write tools, no shell, and no repository access. Briefing text crosses one way, claim text crosses back, and nothing else crosses at all.

That line is not about trust. Two writers produce edits whose interaction nobody has read — one moves a guard, the other moves the thing it guarded, both test suites pass separately, and the defect lives in between. Every half-applied fix in the measured rounds had that shape: a header describing behaviour that only one of two call sites implemented. It happened three times.


Install

# 1. Add this repo as a plugin marketplace
/plugin marketplace add jysvai/CHA

# 2. Install
/plugin install cha@cha

Or point Claude Code at a local clone:

git clone https://github.com/jysvai/CHA ~/cha
/plugin marketplace add ~/cha
/plugin install cha@cha

Then, in the repo you want to review:

/cha-init

That writes .cha/ (config, cumulative record, mutant list) and tells you what your second eye needs.

Full setup — including the second-eye CLI, quota handling, and what to do when you have no second platform — is in docs/en/01-setup.md.


Commands

CommandWhat it does
/cha-initScaffold .cha/ in the current repo and detect the gate commands.
/cha-hunt <path>First-eye pass over a slice. Produces suspicions, not verdicts.
/cha-brief <path>Cut a file into ≤20KB briefings with the five defect classes and .cha/house.md attached.
/cha-review2Send every pending briefing to the second eye, one at a time, quota-aware.
/cha-gauge <briefing>Run one briefing N times and report how often the second eye actually answers.
/cha-judge <tag>Adjudicate one answer by execution. Writes true/false/unmeasurable with evidence.
/cha-fix <id>Red test first, then the fix, then the mutant. Refuses to reorder.
/cha-mutate [filter]Run the mutant sweep — all of them, or one file.
/cha-gateRun the full gate and refuse to report green on anything unmeasured.
/cha-recordAppend this round to the cumulative record.
/cha-statusWhere the loop is: pending briefings, unjudged answers, unguarded fixes.

Skills

Skills load automatically when the work matches. You can also invoke them by name.

SkillLoaded when
cha-loopRunning or resuming the loop; deciding what step is next.
cha-briefingCutting source into second-eye briefings.
cha-adjudicationJudging a claim — the execution-first rules and the verdict format.
cha-mutationWriting, repairing, and sweeping mutants.
cha-red-testProving a failure before fixing it.
cha-recordThe cumulative record format and what must never be dropped.

Agents

AgentRole
cha-hunterRead-only first eye. Produces suspicions with file:line, never fixes.
cha-adjudicatorRuns the claim. Returns a verdict with the command and its output.
cha-mutant-smithLifts the exact source line, builds the mutant, verifies it is caught.

Where the claims went

Every claim is split by execution, not by reading — and the split is not close.


The five defect classes

Every briefing carries these. They are the classes that survived every 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)/ marked qwen2.5-coder:32b — a 32B model — as "too small", because 32b contains 2b.
  2. Silent failure. 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. Named "rejects non-numeric counts", asked only about 'many', and let '3', null, true and [] straight through.
  4. Comment contradicts code. 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 was checked after the connection had already knocked on the external address three times, with the key attached.

Details and the real diffs: docs/en/09-results.md.


What CHA refuses to do

  • It does not fix what it could not measure. Four findings in the last round were platform-locked (Unix-only, or needed Excel installed). They were recorded as unmeasurable, not guessed at. Inventing a fix for an unrun claim is the same failure mode CHA exists to stop.
  • It does not let the reviewer write code. The second eye is read-only and one writer holds the pen — and both are checked rather than declared. A command carrying a permission-skipping flag stops the run; a patch that comes back in an answer is removed before the answer is filed, and the removal is written into the answer.
  • It does not let an empty answer look like a clean file. Every second-eye run is classified — truncated, blocked on a tool, quota, disconnected, empty — and the kind decides the next move. A truncated answer is re-asked smaller, never re-asked identically.
  • It does not report green on anything it did not run. An unmeasurable mutant fails the sweep. Silence is not success.
  • It does not ship on its own. Tag and push happen after a human says so, with the review scope reported first.

Portfolio page

A single self-contained page in Korean and English: what you get, the loop, the numbers from all three runs, and the defect classes.

jysvai.github.io/CHA · the source is site/index.html, published as it is by every push that touches it.


Documentation

00 — WhyThe failure mode this exists to stop.
01 — SetupInstall, second-eye CLI, quota, no-second-platform fallback.
02 — The loopEach step, its entry and exit condition.
03 — Harness tuningWhat actually had to be tuned, and what broke first.
04 — BriefingWhy 20KB, what goes in, .cha/house.md, what must never go in.
05 — Second eyeSerialization, quota backoff, model pinning, the enforced read-only boundary, the failure kinds, and measuring the reviewer itself.
06 — AdjudicationExecution-first rules, verdict format, the 57→22 number.
07 — MutationAnchors, drift, the unmeasurable category.
08 — Gate & recordWhat the gate covers and why the record is never deleted.
09 — ResultsThe measured run, with the actual defects.
10 — FAQCost, time, small repos, CI.

Korean documentation lives in docs/ko/.


License

Apache-2.0 — see LICENSE and NOTICE.

↑↓ navigate openesc close