Visible tests drive the loop. Hidden tests measure overfitting.
Source runs full-1, rep-2 and rep-1 at tdd-experiment c3dd988
Contents
Search and validation
What it changes: The check. Hidden tests score milestones.
BronzeMost cost effectiveM 519,499, M_io 443,244
One method of the study, from runs full-1 and rep-2. The survey build is the method's single build in run full-1. A replicate is one of its builds in run rep-2, which ran in a different batch. Claims carry a tag. Recomputed means redone from source data. Verified means checked against a primary source. Unchecked means written or judged by an agent and not checked.
How it builds code
The procedure supplied to the agents. Indented lines run under the line above them.
Family: Search and validation. Idea: Visible tests drive the loop. Hidden tests measure overfitting. What it changes in the search: The check. Hidden tests score milestones.
once:1. Pin the public interface first such as the CLI or the noun-verb verbs.2. A human or separate agent writes several black-box cases per requirement.3. Move about a third of each requirement's cases into a hidden set.the harness does:4. Keep hidden tests in a private repo that only CI checks out. Keep its CI token out of the agent environment.5. Clone it outside the agent workspace. Add a permissions deny entry for that path in the assistant settings.repeat per requirement until none is open:6. Drive TDD and AI loops with the visible set alone.7. On each merge CI prints hidden pass counts per requirement. Log the gap.8. On a hidden failure write a fresh visible test. Replace that hidden case.if hidden failure, once:with Held-out TDD step 2. A human or separate agent writes several black-box cases per requirement.with Held-out TDD step 8. On a hidden failure write a fresh visible test. Replace that hidden case.if hidden failure, once:with Held-out TDD step 3. Move about a third of each requirement's cases into a hidden set.with Held-out TDD step 8. On a hidden failure write a fresh visible test. Replace that hidden case.
Once means one agent runs the steps. Repeat per unit means one agent per unit until no unit is open. Throughout means the rule joins every prompt. For up to n starts means separate attempts with the best kept. The harness does means the harness runs the step without an agent. If names the event that starts a stage, and with adds a rule borrowed from another method. Steps are quoted from args.json with their numbers. Tag: verified.
Figure 21.1
Stage flow of Held-out TDD
Once: step 1.Lane: Agent.
Next: Once: step 2.
Once: step 2.Lane: Agent.
Next: Once: step 3.
Once: step 3.Lane: Agent.
Next: Steps 4 and 5.
Steps 4 and 5.Lane: Harness.
Next: Steps 6 to 8.
Steps 6 to 8. Returns hiddenFail. Lane: Agent.
Next: With held-out steps 2 and 8 (on fail).
Loop: repeat per requirement, back to Steps 6 to 8.
With held-out steps 2 and 8.Lane: When hidden failure.
Next: With held-out steps 3 and 8.
With held-out steps 3 and 8.Lane: When hidden failure.
7 stages from the run facts, each checked against its block of the steps above. Details and notes are in the stage table. Tag: recomputed.
Loop: repeat per requirement, back to Steps 6 to 8.
With held-out steps 2 and 8.Lane: When hidden failure.
Next: With held-out steps 3 and 8.
With held-out steps 3 and 8.Lane: When hidden failure.
Stages
Each stage as the run facts list it. Runs as and Note are quoted verbatim and Steps repeats the steps above. Tag: verified.
Stage
Runs as
Steps
Details
Note
Once: step 1
once:
1. Pin the public interface first such as the CLI or the noun-verb verbs.
none
none
Once: step 2
once:
2. A human or separate agent writes several black-box cases per requirement.
none
You are the separate agent. Return blocked if {cases} holds anything. Write at least 3 black-box cases per requirement as {cases}/<requirement>/<variant>/caseNN.txt, where <requirement> names a noun and <variant> is a variant folder name from examples/EXAMPLES.md, in the spec format of examples/specs. Keep generators and other scratch files in {scratch}, never in the clone, which the method agents read. Log counts only in LOG.md and commit LOG.md.
Once: step 3
once:
3. Move about a third of each requirement's cases into a hidden set.
none
Run {split} {cases} {visible}, which keeps two thirds visible, and commit visible/. Log only the line it prints.
Steps 4 and 5
the harness does:
4. Keep hidden tests in a private repo that only CI checks out. Keep its CI token out of the agent environment. 5. Clone it outside the agent workspace. Add a permissions deny entry for that path in the assistant settings.
none
none
Steps 6 to 8
repeat per requirement until none is open:
6. Drive TDD and AI loops with the visible set alone. 7. On each merge CI prints hidden pass counts per requirement. Log the gap. 8. On a hidden failure write a fresh visible test. Replace that hidden case.
unit requirement; returns hiddenFail
Drive with ./run.sh specs visible and ./run.sh test. Once the unit is green run ./run.sh hidden once and append a GAP.md row: time, label, requirement, visible pass/total, hidden pass/total and gap. Write a fresh visible test for each requirement ticked in UNITS.md that fails hidden. Write each fresh visible test under test/, never under visible/, which the harness re-splits. A spec file there goes in a variant folder, so ./run.sh specs test plays it. The harness does the rest of step 8 after this loop and replaces the hidden cases through separate agents, so leave the hidden set alone. Return in failing only the requirements ticked in UNITS.md that fail hidden, because the others are not built yet.
With held-out steps 2 and 8
if hidden failure, once:
with Held-out TDD step 2. A human or separate agent writes several black-box cases per requirement. with Held-out TDD step 8. On a hidden failure write a fresh visible test. Replace that hidden case.
when hidden_failure; with held-out steps 2 and 8
You are the separate agent. Add fresh cases to {cases} for each requirement the facts below list as failing hidden, in the layout of {cases}. Keep generators and other scratch files in {scratch}, never in the clone, which the method agents read. Log counts only in LOG.md and commit LOG.md.
With held-out steps 3 and 8
if hidden failure, once:
with Held-out TDD step 3. Move about a third of each requirement's cases into a hidden set. with Held-out TDD step 8. On a hidden failure write a fresh visible test. Replace that hidden case.
when hidden_failure; with held-out steps 3 and 8
Run {split} {cases} {visible} again and commit visible/. Log the line it prints and the count of earlier cases it moved into visible/. Then run ./run.sh specs visible and ./run.sh hidden once and append a closing GAP.md row.
Survey build
One build in run full-1.
15/15Functional mark
33E
801,898Cost to completion
519,499M
443,244M_io
4PMD findings
noAlignment
Replicates
Repeat builds: 5 in run rep-2.
0.777Median adjusted mutation, over 5 replicates in rep-2
3Median classes, over 5 replicates in rep-2
973,901Median cost to completion, over 5 replicates in rep-2
17Median CQP, over 5 replicates in rep-2
M against Classic greedy TDD: U 11, Holm p 1.000; adjusted mutation against Classic greedy TDD: U 0, Holm p 0.024Planned contrast, exact, Holm, rep-2
0.96Consistency score C, exploratory over rep-1 and rep-2, lower is more consistent
Verdict
One survey build and 5 replicates in rep-2. The survey build passed the largest share of hidden tests at 500000 weighted tokens, 0.42, and had the lowest adjusted mutation score of the survey, 0.794. The M test did not detect a difference from Classic greedy TDD (U 11 and Holm p 1.000). The replicates' median share at 500000 weighted tokens was 0.00 in a different batch from the survey build. Their median adjusted mutation of 0.777 was lower than Classic greedy TDD's 1.000, Holm p 0.024, in line with the survey build. Its 9 survey and 46 rep-2 high audit flags were each judged a false positive. Tag: recomputed.
Report summary
The report's class diagram for this design is identical to Figure 21.2 below, so it is shown once. Tag: recomputed.
Functional mark /15
15/15
Hidden pass /76
76/76
Unseen pass /69
69/69
Strict PMD compliance
fail (4 violations)
Mutation score
112/149, 0 not run, adjusted 112/141 (29 of 37 survivors fail hidden tests)
Classes
5
Simple Constructs /5
4
Minimal Duplication /5
4
Modular Structure /5
5
Problem Alignment (tentative) /5
4
Weighted tokens
844,959
Bench median ms
606
Score card
Survey tiles place the survey build among the single survey builds. One build per method describes that build and does not rank the methods. Contrast tiles are medians over the replicates. Tag: recomputed.
Adjusted mutation0.79411th highest of 11 single survey builds, one per method
Classes54th highest of 11 single survey builds, one per method
Cost to completion801,8982nd lowest of 11 single survey builds, one per method
Strict PMD violations45th lowest of 11 single survey builds, one per method
Median adjusted mutation0.777over 5 replicates in rep-2
Median classes3over 5 replicates in rep-2
Median cost to completion973,901over 5 replicates in rep-2
Median CQP17over 5 replicates in rep-2
Planned contrastM against Classic greedy TDD: U 11, Holm p 1.000; adjusted mutation against Classic greedy TDD: U 0, Holm p 0.024exact, Holm, rep-2
Consistency score C0.96exploratory over rep-1 and rep-2, lower is more consistent
Builds
Best, median and worst order a method's replicates by adjusted mutation, highest first, then lower cost to completion. The median build is the representative. Tag: recomputed.
Same family comes from the methods doc. Nearest and farthest average the rank differences over adjusted mutation, classes and cost to completion of the survey builds, over the metrics both methods have. Anchor Engineering has no survey build, so the replicate medians of adjusted mutation and classes stand in. Cost to completion leaves out such a method, since costs of a different batch do not compare. Tag: recomputed.
Branch method/held-out. Claims carry a tag. Recomputed means redone from source data. Verified means checked against a primary source. Unchecked means written or judged by an agent and not checked.
Headline
Functional mark /15
15/15
Hidden pass /76
76/76
Unseen pass /69
69/69
Acceptance pass /6
6/6
Strict PMD compliance
fail (4 violations)
Recomputed from the grader's grade.tsv and summary.json and from metrics.json. The functional mark follows A02-RUBRIC.md: 2 for the original set with no failure, 3 per other set less one per failure, and 4 when every test passes. A02 is the course assignment whose spec and rubric the experiment uses. STA means anticlockwise and STC clockwise sowing. 6-4 and 7-5 are houses and seeds. A02-RUBRIC.md names the original set "Clockwise 6 Houses 4 Seeds". This page names each set by the spec folder its tests play, so the original set reads STA 6-4. Strict PMD compliance passes when PMD with the starter's kalah_pmd.xml finds no violation in src/ and otherwise fails with the count of distinct violations. The lint sets no minimum priority, so rules of every priority count. It covers src/ only, the scope of the starter's ./run.sh lint. A02-RUBRIC.md awards no marks for PMD, so the functional mark leaves it out.
Rubric set
Tests
Failures
Marks
Original set, STA 6-4
testST64SKHHSH_
0
2/2
STC 6-4
testSTC64SKHHSH_
0
3/3
STA 7-5
testST75SKHHSH_
0
3/3
STC 7-5
testSTC75SKHHSH_
0
3/3
All requirements
all tests
0
4/4
Summary metrics
Metric
Value
Tag
Total lines
417 (src 269, own tests 148)
recomputed
Lines of code
331 (src 210, own tests 121)
recomputed
Classes
5
recomputed
Methods
26
recomputed
Fields
13
recomputed
Bench median ms
606
recomputed
Bench volume
100614 inputs, 40083576 output chars
recomputed
Own tests leave out the starter's two Example tests and their ExampleSpec helper. Classes count top-level, nested and anonymous classes in src/.
Quality, costs and audit
Metric
Value
Tag
Mutation score
112/149, 0 not run, adjusted 112/141 (29 of 37 survivors fail hidden tests)
recomputed
PMD lines
4 (4 violations)
recomputed
Dependency edges
7
recomputed
Review scores (superseded)
Alterability 5, Code quality principles 4.1, Test quality 3
PMD lines count violations once per file and line. Agent time sums each agent's first to last timestamp, so agents that ran side by side add up. Weighted tokens count input 1, cache creation 1.25, cache read 0.05 and output 5 per token. These are claude-opus-5-5 prices relative to an input token and state no dollar cost. Costs, times and agent calls cover this clone only. The comparison row covers every clone of the method as its count basis states.
Review scores
A blind reviewer agent scored src/ and test/ from 1, worst, to 5, best, so the scores are unchecked. Reasons are the reviewer's own words, verbatim. This review is superseded by the blind rating of three raters in rating.json, whose medians fill the comparison's principle columns.
Reason: Direction is a pure view concern here: Board sows the same way in every variant and only BoardView's clockwise branch picks the row layout, so the change touches one small conditional.
Alterability. Item: Change Case 2: 7 houses with 5 seeds. Score /5: 5.
Reason: House count and seed count are constructor parameters used throughout Board and BoardView, so the variant is a single ternary in Kalah.play and all four combinations work without other edits.
Reason: The files are small and well formatted, with a clear order and related helpers next to each other. The sow loop's side/pit state is dense to scan.
Reason: Names and class Javadocs state intent well, and CANCELLED and the Protocol constants give literals meaning. The magic expressions 3 - side, 2 - player and player - 1 are never named.
Reason: Players and houses are 1-based throughout and Protocol handles every message the same way. Opponent indexing switches between 3 - side and 2 - player, which is an inconsistent idiom.
Code quality principles. Item: 4. Used Content. Score /5: 5.
Reason: Every class, method and constant is used. The stub output was removed and nothing dead remains.
Reason: Game.run is a simple loop. Board.sow, though, encodes the last-seed-in-store case through the side flip and pit reset, and needs a comment to explain its return tests.
Reason: Row rendering shares a houses helper with an ascending flag, and draw is factored out. Game over plus draw appears in two branches of run, and pit and pitEnd nearly duplicate each other.
Reason: The responsibilities split cleanly into Board as the model, BoardView for rendering, Protocol for text and Game for the turn loop. Classes are package-private with narrow interfaces.
Code quality principles. Item: 8. Problem Alignment. Score /5: 4.
Reason: Board, house, store, sow and capture follow the domain vocabulary, and the variants map directly to constructor args and the view. The integer side/pit cursor is a lower-level encoding than the domain suggests.
Test quality. Item: Test quality. Score /5: 3.
Reason: BoardTest pins sowing, an extra turn, capture and scoring with clear names, and BoardViewTest covers two variant layouts. No own test exercises Game flow such as quit, empty house or end of game. ProtocolTest and PublicInterfaceTest mostly restate constants and signatures.
Audit flags
9 high and 4 low flags from agent tool calls and the method's commits. Only audit.json lists the low flags.
Channel
Agent or commit
Tool
Path
ho_reflection
held-out:s1
Write
test/kalah/PublicInterfaceTest.java
ho_reflection
held-out:s1
Write
test/kalah/PublicInterfaceTest.java
ho_reflection
held-out:s1
Write
test/kalah/PublicInterfaceTest.java
hidden
held-out:s2
Bash
$CLONES_DIR/_heldout
hidden
held-out:s2
Bash
$CLONES_DIR/_heldout
ho_reflection
9640df5925beb1dca6dded74b969b49f64fd7fad
-
test/kalah/PublicInterfaceTest.java:3
ho_reflection
9640df5925beb1dca6dded74b969b49f64fd7fad
-
test/kalah/PublicInterfaceTest.java:4
ho_reflection
9640df5925beb1dca6dded74b969b49f64fd7fad
-
test/kalah/PublicInterfaceTest.java:13
ho_reflection
9640df5925beb1dca6dded74b969b49f64fd7fad
-
test/kalah/PublicInterfaceTest.java:17
Channel
Marker
Disposition
ho_reflection
java.lang.reflect
false positive
ho_reflection
getConstructor(
false positive
ho_reflection
getMethod(
false positive
hidden
_heldout
false positive
hidden
_heldout
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
getConstructor(
false positive
ho_reflection
getMethod(
false positive
ho_reflection.
Definition: Held-out only. Added code or a tool write that uses reflection.
hidden.
Definition: A path named /hidden or a _heldout path outside the agent's allowed _heldout folders. The held-out method's own case folders live under _heldout.
Dispositions from the run's findings.json judge every high flag of their channel.
hidden. Verdict: false positive. Tag: verified.
Evidence: Both flags are held-out:s2 naming _heldout itself. One Bash call lists _heldout and _heldout/cases and one changes into _heldout to write cases with its scratch generator. Neither reads _heldout/hidden, and s2 may use _heldout/cases and _heldout/scratch.
Evidence: 3 flags mark held-out:s1's Write of test/kalah/PublicInterfaceTest.java and 4 mark its lines in commit 9640df5. The test reflects only on Kalah to check a public no-argument constructor and a public play(IO, boolean, boolean). It reads no spec and no MockIO state.
Step log
Method agents wrote the LOG.md cells. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC. Agent, tokens and seconds are recomputed from transcripts by row time. A dash in Agent means no agent run spans the row.
Step log, 10 rows and 10 columns
2026-10-15T23:54:08Z. Step: s1: 1 pin public interface. Unit: public interface: play(IO, boolean, boolean) and CLI protocol. Tests added: 8. Cycles: 1. Sha: 9640df5. Agent: held-out:s1. Tokens: 375190. Seconds: 63.417.
Actions: Added PublicInterfaceTest (reflection pin of public constructor and play signature, green on stub as a pin of the given contract). Added ProtocolTest red (no Protocol class) then src/kalah/Protocol.java green with the quit verb, prompt, empty-house, game-over, score, winner and tie texts from examples/specs. "Player 1 wins!" inferred by symmetry. Ran ./run.sh test ProtocolTest and PublicInterfaceTest only. Conflict logged: the step names no checks while standing guidance asks for static checks and related tests, so only the two new test classes ran. Full ./run.sh test stays red on the six example tests by design of the starter.
Actions: Wrote 84 spec-format cases outside the clone: 7 requirements, 3 cases per requirement per variant, 12 per requirement. Generated and checked outside the clone. The generator replays all 6 example specs exactly. No ./run.sh call because the step names no checks. Conflict logged: standing guidance asks to commit each work group, while the step keeps cases out of the clone, so only LOG.md is committed.
2026-10-15T23:57:58Z. Step: s3: 3 move a third of each requirement into a hidden set. Unit: held-out split: 7 requirements. Tests added: 0. Cycles: 0. Sha: ab6140f. Agent: held-out:s3. Tokens: 94348. Seconds: 11.044.
Actions: Wrote UNITS.md (7 requirements) and committed it. Red-green: BoardViewTest (board drawing both directions), BoardTest sowing, BoardTest capture. Added Board, BoardView, Game and wired Kalah.play. Visible quit 8/8 needed capture because quit STC 7-5 case03 ends a move with a capture, so capture was built in this unit; logged as a deviation from one requirement per iteration. ./run.sh test: 4 own classes green, example tests still red for later units (empty house, full games). ./run.sh hidden once: quit 4/4, gap 0, so no fresh visible test. Conflict logged: standing guidance asks for static checks and full CI green, while the step names only specs, test and hidden, so lint was not run and CI stays red on later-unit examples.
Actions: Visible sowing was 4/8: each case03 ends a move in the own store and expects another turn. Red BoardTest.testLastSeedInOwnStoreGivesAnotherTurn, then Board.sow returns the same player when the last seed lands in the own store. Visible sowing 8/8; store and lap visible also turned 8/8 from the same rule. ./run.sh test: 4 own classes green, example tests still red on empty house and full games for later units. ./run.sh hidden once: sowing 4/4, gap 0, quit still 4/4, so no fresh visible test. Conflict logged: standing guidance asks for static checks and green CI, while the step names only specs, test and hidden, so lint was not run and CI stays red on later-unit examples.
Actions: ./run.sh specs visible: store already 8/8 from the iteration 2 another-turn rule, so the visible set gave no red case and no code or test changed (0 cycles). ./run.sh test: 4 own classes green, example tests still red on empty house and full games for later units. ./run.sh hidden once: store 4/4, gap 0, quit and sowing still 4/4, so no fresh visible test. Ticked store. Conflict logged: standing guidance asks for new tests per change and static checks, while the step drives only from the visible set and names only specs, test and hidden, so no test was added and lint was not run.
Actions: ./run.sh specs visible: capture already 8/8 because iteration 1 built capture for a quit case, so the visible set gave no red case and no code or test changed (0 cycles). Specs ran twice to filter output, with the same result. ./run.sh test: 4 own classes green, example tests still red on empty house and full games for later units. ./run.sh hidden once: capture 4/4, gap 0, quit sowing and store still 4/4, so no fresh visible test. Ticked capture. Conflict logged: standing guidance asks for new tests per change and static checks, while the step drives only from the visible set and names only specs, test and hidden, so no test was added and lint was not run.
Actions: ./run.sh specs visible: emptyhouse 0/8, all other built requirements 8/8. Red BoardTest.testHouseIsEmptyOnlyAfterItIsSown (no Board.isEmpty), then Board.isEmpty and Game prints Protocol.EMPTY_HOUSE and reprompts without sowing. Visible emptyhouse 8/8. ./run.sh test: BoardTest, BoardViewTest, ProtocolTest and PublicInterfaceTest green, example full-game tests still red on game end for a later unit. ./run.sh hidden once: emptyhouse 4/4, gap 0, quit sowing store capture lap 4/4, gameend 0/4 (not built), so no fresh visible test. Ticked emptyhouse. Conflict logged: standing guidance asks for static checks and green CI, while the step names only specs, test and hidden, so lint was not run and CI stays red on game-end examples.
Actions: ./run.sh specs visible: lap already 8/8 from the iteration 2 another-turn rule and sowing across the opponent store skip, so the visible set gave no red case and no code or test changed (0 cycles). Specs ran twice to filter output, with the same result. ./run.sh test: own classes green, example full-game tests still red on game end for a later unit. ./run.sh hidden once: lap 4/4, gap 0, other built requirements 4/4, gameend 0/4 (not built), so no fresh visible test. Ticked lap. Conflict logged: standing guidance asks for new tests per change and static checks, while the step drives only from the visible set and names only specs, test and hidden, so no test was added and lint was not run.
Actions: ./run.sh test red: BoardTest.testNoMovesOnceEveryOwnHouseIsEmptyAndScoreAddsHousesToStore did not compile (no Board.hasMoves or Board.score). Added both, and Game now prints Game over, the board, both score lines and the winner or a tie when the player to move has no seeds. ./run.sh test: 6 classes green, example full-game tests now pass. ./run.sh specs visible: 56/56, gameend 8/8. ./run.sh hidden once: every requirement 4/4, gameend gap 0, so no fresh visible test. Ticked gameend, UNITS.md has no open lines. Conflict logged: standing guidance asks for static checks, while the step names only specs, test and hidden, so lint was not run.
Raw inputs
metrics.json
summary.json
grade.tsv
costs.json
steps.csv
audit.json
review.json
LOG.md
MEASURE.md
classdiagram.uml
classdiagram.png
classdiagram.svg
collect.tsv
rating.json
MEASURE.md
The method's measure agent answered its Measure line from LOG.md and git. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC.
# Measure
Measure: visible and hidden pass rate per merge. Gap per noun. Hidden cases replaced after disclosure.
Sources: LOG.md, GAP.md and git log. ATTEMPTS.md does not exist. Credits and time are measured by the harness and are not recorded here.
The run has no merge commits. Each held-out iteration lands as one tick commit on the work branch, so each tick commit counts as one merge.
## Pass rate per merge
Case set: 84 cases over 7 requirements. 56 visible (8 per requirement) and 28 hidden (4 per requirement).
| merge | sha | unit | unit visible | unit hidden | all visible | all hidden |
|---|---|---|---|---|---|---|
| iter1 | e30c970 | quit | 8/8 | 4/4 | not recorded | not recorded |
| iter2 | 3aa6c9d | sowing | 8/8 | 4/4 | not recorded | not recorded |
| iter3 | 984a0be | store | 8/8 | 4/4 | not recorded | not recorded |
| iter4 | 0017295 | capture | 8/8 | 4/4 | not recorded | not recorded |
| iter5 | 47cffd9 | emptyhouse | 8/8 | 4/4 | 48/56 | 24/28 |
| iter6 | 657940a | lap | 8/8 | 4/4 | 48/56 | 24/28 |
| iter7 | 0232958 | gameend | 8/8 | 4/4 | 56/56 | 28/28 |
Unit columns come from GAP.md. All-set columns come from LOG.md. Iterations 1 to 4 logged only the built requirements, so their all-set totals are not recorded. At iterations 5 and 6 LOG.md states every requirement except gameend at 8/8 visible and 4/4 hidden, and gameend 0/4 hidden. Gameend visible 0/8 at those merges is inferred from it being unbuilt.
## Gap per noun
Gap is visible pass rate minus hidden pass rate for the iteration's requirement.
| noun | visible | hidden | gap |
|---|---|---|---|
| quit | 8/8 | 4/4 | 0 |
| sowing | 8/8 | 4/4 | 0 |
| store | 8/8 | 4/4 | 0 |
| capture | 8/8 | 4/4 | 0 |
| emptyhouse | 8/8 | 4/4 | 0 |
| lap | 8/8 | 4/4 | 0 |
| gameend | 8/8 | 4/4 | 0 |
Every noun closed with a gap of 0 at its first hidden run.
## Hidden cases replaced after disclosure
0. No hidden run showed a gap, so no hidden case was disclosed and none was moved to the visible set or replaced. Each iteration ran ./run.sh hidden once.
## Other counts
- Red-green cycles: 7 (s1 1, iter1 3, iter2 1, iter5 1, iter7 1). Iterations 3, 4 and 6 ran 0 cycles because earlier rules already passed their visible cases.
- Tests added per LOG.md: 8 in s1 and 8 over the iterations. The 84 held-out spec cases live outside the clone.
- Deviation: capture was built in iteration 1 because a visible quit case ends with a capture.
Branch method/rep-2-r04. Claims carry a tag. Recomputed means redone from source data. Verified means checked against a primary source. Unchecked means written or judged by an agent and not checked.
Headline
Functional mark /15
15/15
Hidden pass /76
76/76
Unseen pass /69
69/69
Acceptance pass /6
6/6
Strict PMD compliance
fail (12 violations)
Recomputed from the grader's grade.tsv and summary.json and from metrics.json. The functional mark follows A02-RUBRIC.md: 2 for the original set with no failure, 3 per other set less one per failure, and 4 when every test passes. A02 is the course assignment whose spec and rubric the experiment uses. STA means anticlockwise and STC clockwise sowing. 6-4 and 7-5 are houses and seeds. A02-RUBRIC.md names the original set "Clockwise 6 Houses 4 Seeds". This page names each set by the spec folder its tests play, so the original set reads STA 6-4. Strict PMD compliance passes when PMD with the starter's kalah_pmd.xml finds no violation in src/ and otherwise fails with the count of distinct violations. The lint sets no minimum priority, so rules of every priority count. It covers src/ only, the scope of the starter's ./run.sh lint. A02-RUBRIC.md awards no marks for PMD, so the functional mark leaves it out.
Rubric set
Tests
Failures
Marks
Original set, STA 6-4
testST64SKHHSH_
0
2/2
STC 6-4
testSTC64SKHHSH_
0
3/3
STA 7-5
testST75SKHHSH_
0
3/3
STC 7-5
testSTC75SKHHSH_
0
3/3
All requirements
all tests
0
4/4
Summary metrics
Metric
Value
Tag
Total lines
305 (src 188, own tests 117)
recomputed
Lines of code
248 (src 148, own tests 100)
recomputed
Classes
3
recomputed
Methods
18
recomputed
Fields
6
recomputed
Bench median ms
571
recomputed
Bench volume
100614 inputs, 40083576 output chars
recomputed
Own tests leave out the starter's two Example tests and their ExampleSpec helper. Classes count top-level, nested and anonymous classes in src/.
Quality, costs and audit
Metric
Value
Tag
Mutation score
87/120, 0 not run, adjusted 87/112 (25 of 33 survivors fail hidden tests)
recomputed
PMD lines
12 (12 violations)
recomputed
Dependency edges
3
recomputed
Review scores (superseded)
Alterability 5, Code quality principles 4.2, Test quality 3
PMD lines count violations once per file and line. Agent time sums each agent's first to last timestamp, so agents that ran side by side add up. Weighted tokens count input 1, cache creation 1.25, cache read 0.05 and output 5 per token. These are claude-opus-5-5 prices relative to an input token and state no dollar cost. Costs, times and agent calls cover this clone only. The comparison row covers every clone of the method as its count basis states.
Review scores
A blind reviewer agent scored src/ and test/ from 1, worst, to 5, best, so the scores are unchecked. Reasons are the reviewer's own words, verbatim. This review is superseded by the blind rating of three raters in rating.json, whose medians fill the comparison's principle columns.
Reason: Direction lives only in BoardPrinter as one boolean, because sowing in rising house order is the same for both variants and only the drawn layout mirrors. Board and the game loop never read the flag.
Alterability. Item: Change Case 2: 7 houses with 5 seeds. Score /5: 5.
Reason: The variant is a single constructor choice in play(). Board, printer borders and the input range all come from houseCount(), so nothing else changes.
Reason: Formatting is tidy and the three classes are small and easy to scan. The QUIT constant sits at the bottom of Kalah, away from where it is used, and the clockwise and anticlockwise print branches are dense string concatenations.
Reason: Names such as sow, captureAt, isEmpty and score match the domain, and the javadoc explains why direction affects only drawing. P1, P2 and QUIT are symbolic, but Kalah still uses bare 0, 1 and 1 - player for players.
Reason: Style is mostly uniform. Players are named constants in BoardPrinter but literals in Kalah and Board, and java.util.Arrays is written fully qualified three times where an import would do.
Code quality principles. Item: 4. Used Content. Score /5: 4.
Reason: The production code has no dead elements. Two added transcript files, emptyhouse/p2_empty.txt and quit/p1_quit_after_extra_move.txt, are referenced by no test and so never run.
Reason: The control flow is short and readable. sow() nests a store check inside a wrap check inside the loop with an early return, which is the hardest part to follow.
Reason: Board holds the state and rules, BoardPrinter handles rendering and Kalah handles the turn loop and I/O. Each class has one clear job and package-private scope.
Code quality principles. Item: 8. Problem Alignment. Score /5: 5.
Reason: The classes and methods match Kalah concepts directly: houses, stores, sowing, capture, extra move, empty house and score. Seeing that direction is only a display mirror keeps the rules in one model.
Test quality. Item: Test quality. Score /5: 3.
Reason: BoardTest covers sowing, extra moves, skipping the opponent store, captures and laps with independent cases, and InterfaceTest pins quit for all four variants. Empty-house and game-over transcripts are not run, the added spec files are never referenced, and some capture setups are opaque move sequences.
Audit flags
9 high and 5 low flags from agent tool calls and the method's commits. Only audit.json lists the low flags.
Channel
Agent or commit
Tool
Path
ho_reflection
rep-2-r04:s1
Write
test/kalah/InterfaceTest.java
ho_reflection
rep-2-r04:s1
Write
test/kalah/InterfaceTest.java
ho_reflection
rep-2-r04:s1
Write
test/kalah/InterfaceTest.java
hidden
rep-2-r04:s2
Bash
$CLONES_DIR/_heldout/rep-2-r04
hidden
rep-2-r04:s2
Bash
$CLONES_DIR/_heldout/rep-2-r04
ho_reflection
1362bccab8a7ddf9f3c4f4bd28623610fce8245f
-
test/kalah/InterfaceTest.java:4
ho_reflection
1362bccab8a7ddf9f3c4f4bd28623610fce8245f
-
test/kalah/InterfaceTest.java:5
ho_reflection
1362bccab8a7ddf9f3c4f4bd28623610fce8245f
-
test/kalah/InterfaceTest.java:11
ho_reflection
1362bccab8a7ddf9f3c4f4bd28623610fce8245f
-
test/kalah/InterfaceTest.java:14
Channel
Marker
Disposition
ho_reflection
java.lang.reflect
false positive
ho_reflection
getMethod(
false positive
ho_reflection
getConstructor(
false positive
hidden
_heldout
false positive
hidden
_heldout
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
getMethod(
false positive
ho_reflection
getConstructor(
false positive
ho_reflection.
Definition: Held-out only. Added code or a tool write that uses reflection.
hidden.
Definition: A path named /hidden or a _heldout path outside the agent's allowed _heldout folders. The held-out method's own case folders live under _heldout.
Dispositions from the run's findings.json judge every high flag of their channel.
hidden. Verdict: false positive. Tag: verified.
Evidence: Both flags are rep-2-r04:s2 in agent-ab883340dd8047793.jsonl. At line 14 it lists its own _heldout/rep-2-r04 and its cases before writing, and at line 96 it copies scratch/out into cases. It names no hidden path and no other build's dir.
Evidence: All 7 flags mark rep-2-r04:s1's InterfaceTest, 3 as a Write and 4 in commit 1362bcc. It reflects only on Kalah to check its public constructor and play. None reads a spec or MockIO state.
Step log
Method agents wrote the LOG.md cells. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC. Agent, tokens and seconds are recomputed from transcripts by row time. A dash in Agent means no agent run spans the row.
Step log, 11 rows and 10 columns
2026-10-30T06:01:56Z. Step: s1. Unit: public interface: play(IO, boolean, boolean) and quit CLI per variant. Tests added: 5. Cycles: 1. Sha: 1362bcc. Agent: rep-2-r04:s1. Tokens: 762474. Seconds: 131.446.
Actions: Pinned play() signature by reflection and the start board, prompt, 'q' and Game over transcript for all four variants (3 new specs under test/pin plus example quit.txt). Added Board and BoardPrinter for the start board. Ran ./run.sh test InterfaceTest only: red 4 errors then green 5/5. Conflict: Write and Edit strip trailing spaces, so the prompt's trailing space in the 3 spec files was restored with one sed call against the no-scripted-edits rule.
Actions: Wrote 100 held-out cases outside the clone: 8 requirements x 4 variants, 3 per variant (gameend 4). Counts per requirement: board 12, sowing 12, store 12, capture 12, emptyhouse 12, quit 12, lap 12, gameend 16. No ./run.sh call; this step names no check.
Actions: Wrote UNITS.md with 8 requirements. Red: ./run.sh specs visible/board 0/8. Added Board.sow (rising house order, skip opponent store, extra move on store, capture) and turn alternation in Kalah. Green: visible board 8/8. Added BoardTest (3 tests). First capture test used an invented move list and failed, fixed to the case03 sequence. ./run.sh test: BoardTest and InterfaceTest green, Example tests still red on empty-house and game-end units not built yet. ./run.sh hidden once: specs 0, so the runner has no hidden set and the gap is not measurable. Conflict: used sed for the UNITS.md tick and printf for GAP.md against the no-scripted-edits rule.
Actions: ./run.sh specs visible/sowing was already 8/8 from iteration 1, so no code change and no red phase. Added BoardTest.testSowDropsOneSeedPerFollowingHouse (7 houses, 5 seeds) as a characterization test. ./run.sh test: BoardTest 4/4 and InterfaceTest green, Example tests still red on units not built yet. ./run.sh hidden once: specs 0, so the gap is not measurable. Ticked sowing and logged GAP.md.
Actions: ./run.sh specs visible/store was already 8/8 from iteration 1, so no code change and no red phase. Added BoardTest.testSecondPlayerStoreCollectsSeedAndGrantsAnotherMove as a characterization test. ./run.sh test: BoardTest 5/5 and InterfaceTest green, Example tests still red on empty-house and game-end units not built yet. ./run.sh hidden once: specs 0, so the gap is not measurable. Ticked store and logged GAP.md. Conflict: used sed for the UNITS.md tick and echo for GAP.md and LOG.md against the no-scripted-edits rule.
Actions: ./run.sh specs visible/capture was already 8/8 from iteration 1, so no code change and no red phase. Added BoardTest.testLastSeedInEmptyOpponentHouseCapturesNothing as a characterization test of the own-side capture guard. ./run.sh test: BoardTest 6/6 and InterfaceTest green, Example tests still red on empty-house and game-end units not built yet. ./run.sh hidden once: specs 0, so the gap is not measurable. Ticked capture and logged GAP.md.
Actions: Red: ./run.sh specs visible/emptyhouse 0/8. Kalah.play now prints House is empty. Move again. and reprompts the same player when the chosen house is empty. Green: visible emptyhouse 8/8. Added spec test/emptyhouse/test_STA_6_4_SK_H_H_SH/p2_empty.txt (P2 empty choice after an extra move), first failed on trailing prompt spaces stripped by Write, then passed in ./run.sh specs test 1/1. ./run.sh test: BoardTest and InterfaceTest green, one Example test per direction still red on game end not built yet. ./run.sh hidden once: specs 0, so the gap is not measurable. Conflict: used sed for the prompt trailing spaces because Edit and Write strip them, plus sed for the UNITS.md tick and echo for GAP.md and LOG.md against the no-scripted-edits rule.
Actions: ./run.sh specs visible/quit was already 8/8 from earlier iterations, so no code change and no red phase. Added spec test/quit/test_STA_6_4_SK_H_H_SH/p1_quit_after_extra_move.txt (P1 quits during its extra move). It first failed on a wrong expected store cell in the test, fixed the test, then ./run.sh specs test 2/2. ./run.sh test: BoardTest and InterfaceTest green, one Example test per direction still red on game end not built yet. ./run.sh hidden once: specs 0, so the gap is not measurable. Ticked quit and logged GAP.md. Conflict: used echo, sed and awk to write the spec, tick UNITS.md and append GAP.md and LOG.md against the no-scripted-edits rule, because Write strips the prompt trailing spaces.
Actions: ./run.sh specs visible/lap was already 8/8 from earlier iterations, so no code change and no red phase. Added BoardTest.testFullLapRefillsEmptiedOriginHouseAndCaptures (6 houses, 13 seeds wrap past the P2 store into the emptied origin house and capture). ./run.sh test: BoardTest 7/7 and InterfaceTest green, one Example test per direction still red on game end not built yet. ./run.sh hidden once: specs 0, so the gap is not measurable. Ticked lap and logged GAP.md. Conflict: used sed for the UNITS.md tick and echo for GAP.md and LOG.md against the no-scripted-edits rule.
Actions: Red: ./run.sh specs visible/gameend 0/11. Kalah.play now ends the game when the player to move has all houses empty, printing Game over, the board, both scores (houses plus store) and the winner or A tie!. Board gained isEmpty and score. Green: visible/gameend 11/11, ./run.sh specs visible 67/67, ./run.sh specs test 2/2, ./run.sh test all 4 classes green including Example tests. Added BoardTest.testScoreCountsHousesAndStoreAndEmptySideEndsGame. ./run.sh hidden once: specs 0, so the gap is not measurable. Ticked gameend and logged GAP.md. Conflict: used a python script for the source edits, sed for the UNITS.md tick and echo for GAP.md and LOG.md against the no-scripted-edits rule.
Raw inputs
metrics.json
summary.json
grade.tsv
costs.json
steps.csv
audit.json
review.json
LOG.md
MEASURE.md
classdiagram.uml
classdiagram.png
classdiagram.svg
collect.tsv
rating.json
MEASURE.md
The method's measure agent answered its Measure line from LOG.md and git. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC.
# Measure
Method: Held-out TDD. Sources are LOG.md, GAP.md and git log. ATTEMPTS.md does not exist.
## Answer
Every merge point reached 100 percent of its visible cases. The hidden pass rate was never measured. `./run.sh hidden` played 0 specs at every iteration, so the gap per noun is not measurable and no hidden case was disclosed or replaced.
## Pass rate per merge
The branch has no merge commits. Each L6-8 iteration commit is taken as the merge point for its requirement.
| iteration | requirement (noun) | commit | visible pass/total | hidden pass/total | gap |
|---|---|---|---|---|---|
| 1 | board | 36b4161 | 8/8 | 0/0 played | not measurable |
| 2 | sowing | 549b964 | 8/8 | 0/0 played | not measurable |
| 3 | store | c839451 | 8/8 | 0/0 played | not measurable |
| 4 | capture | f2091ca | 8/8 | 0/0 played | not measurable |
| 5 | emptyhouse | 5ba64fb | 8/8 | 0/0 played | not measurable |
| 6 | quit | d0e6622 | 8/8 | 0/0 played | not measurable |
| 7 | lap | 38509cd | 8/8 | 0/0 played | not measurable |
| 8 | gameend | 62476fa | 11/11 | 0/0 played | not measurable |
At the final commit 62476fa `./run.sh specs visible` passed 67/67 and `./run.sh test` was green (LOG.md iteration 8).
## Gap per noun
The split in stage s3 held out 33 of 100 cases. From the s2 counts per requirement that is 4 hidden cases for each of the seven 12-case nouns and 5 for gameend. None of them ran. The gap for every noun is therefore unknown. It is not zero.
## Hidden cases replaced after disclosure
Zero. No hidden result was ever shown, so nothing was disclosed and no case needed replacing.
## Credits and time
Credits and wall time are measured by the harness. LOG.md timestamps span 06:01:56Z to 06:16:24Z for stages s1 to iteration 8.
## Cycles and tests
From LOG.md. Red-green cycles total 6. Tests added total 15 (5 in s1 interface pins, 8 BoardTest cases, 2 specs under test).
Branch method/rep-2-r08. Claims carry a tag. Recomputed means redone from source data. Verified means checked against a primary source. Unchecked means written or judged by an agent and not checked.
Headline
Functional mark /15
15/15
Hidden pass /76
76/76
Unseen pass /69
69/69
Acceptance pass /6
6/6
Strict PMD compliance
fail (6 violations)
Recomputed from the grader's grade.tsv and summary.json and from metrics.json. The functional mark follows A02-RUBRIC.md: 2 for the original set with no failure, 3 per other set less one per failure, and 4 when every test passes. A02 is the course assignment whose spec and rubric the experiment uses. STA means anticlockwise and STC clockwise sowing. 6-4 and 7-5 are houses and seeds. A02-RUBRIC.md names the original set "Clockwise 6 Houses 4 Seeds". This page names each set by the spec folder its tests play, so the original set reads STA 6-4. Strict PMD compliance passes when PMD with the starter's kalah_pmd.xml finds no violation in src/ and otherwise fails with the count of distinct violations. The lint sets no minimum priority, so rules of every priority count. It covers src/ only, the scope of the starter's ./run.sh lint. A02-RUBRIC.md awards no marks for PMD, so the functional mark leaves it out.
Rubric set
Tests
Failures
Marks
Original set, STA 6-4
testST64SKHHSH_
0
2/2
STC 6-4
testSTC64SKHHSH_
0
3/3
STA 7-5
testST75SKHHSH_
0
3/3
STC 7-5
testSTC75SKHHSH_
0
3/3
All requirements
all tests
0
4/4
Summary metrics
Metric
Value
Tag
Total lines
445 (src 283, own tests 162)
recomputed
Lines of code
366 (src 227, own tests 139)
recomputed
Classes
5
recomputed
Methods
34
recomputed
Fields
9
recomputed
Bench median ms
497
recomputed
Bench volume
100614 inputs, 40083576 output chars
recomputed
Own tests leave out the starter's two Example tests and their ExampleSpec helper. Classes count top-level, nested and anonymous classes in src/.
Quality, costs and audit
Metric
Value
Tag
Mutation score
94/128, 0 not run, adjusted 94/121 (27 of 34 survivors fail hidden tests)
recomputed
PMD lines
6 (6 violations)
recomputed
Dependency edges
7
recomputed
Review scores (superseded)
Alterability 5, Code quality principles 4.4, Test quality 4
PMD lines count violations once per file and line. Agent time sums each agent's first to last timestamp, so agents that ran side by side add up. Weighted tokens count input 1, cache creation 1.25, cache read 0.05 and output 5 per token. These are claude-opus-5-5 prices relative to an input token and state no dollar cost. Costs, times and agent calls cover this clone only. The comparison row covers every clone of the method as its count basis states.
Review scores
A blind reviewer agent scored src/ and test/ from 1, worst, to 5, best, so the scores are unchecked. Reasons are the reviewer's own words, verbatim. This review is superseded by the blind rating of three raters in rating.json, whose medians fill the comparison's principle columns.
Reason: Sowing order is the same in both directions. Direction lives only in BoardPrinter, where one if/else picks the row order and store placement, so the change touches one small branch.
Alterability. Item: Change Case 2: 7 houses with 5 seeds. Score /5: 5.
Reason: House and seed counts come in through the Board constructor from one ternary in Kalah.play. Printing, sowing and capture all derive from board.houses(), so nothing else changes.
Reason: The names are domain terms such as sow, capture, store and opponent. The encodings 3 - player and house 0 as the store are only partly explained, by the Pit comment.
Reason: The constructs are plain loops, ints and a small value class. The magic 3 - x arithmetic and the continue that skips the opponent store are slightly terse.
Reason: The opponent formula 3 - x appears in both Board and Game. The 'Game over' plus print sequence is repeated on the quit path and the normal end path.
Reason: Responsibilities are cleanly split. Board holds pits and sowing, Game holds turns and capture, BoardPrinter holds the layout and Kalah handles I/O.
Code quality principles. Item: 8. Problem Alignment. Score /5: 4.
Reason: Board, Pit, sow and capture map directly to the rules. Players are bare ints, and sowing direction exists only as a display mirror, so that concept is implicit in the model.
Test quality. Item: Test quality. Score /5: 4.
Reason: Focused, independent and well-named tests cover sowing, wrap-around with the opponent store skipped, extra turns, capture, no capture, game end and both printer layouts. Nothing exercises play() end to end, the quit or empty-house paths, or a clockwise seven-house game.
Audit flags
9 high and 10 low flags from agent tool calls and the method's commits. Only audit.json lists the low flags.
Channel
Agent or commit
Tool
Path
ho_reflection
rep-2-r08:s1
Write
test/kalah/KalahInterfaceTest.java
ho_reflection
rep-2-r08:s1
Write
test/kalah/KalahInterfaceTest.java
ho_reflection
rep-2-r08:s1
Write
test/kalah/KalahInterfaceTest.java
hidden
rep-2-r08:s2
Bash
$CLONES_DIR/_heldout/rep-2-r08
hidden
rep-2-r08:s2
Bash
$CLONES_DIR/_heldout/rep-2-r08
ho_reflection
5ab4469ce9a6706d60cdda381ff5aa14bc5bd2e4
-
test/kalah/KalahInterfaceTest.java:3
ho_reflection
5ab4469ce9a6706d60cdda381ff5aa14bc5bd2e4
-
test/kalah/KalahInterfaceTest.java:4
ho_reflection
5ab4469ce9a6706d60cdda381ff5aa14bc5bd2e4
-
test/kalah/KalahInterfaceTest.java:13
ho_reflection
5ab4469ce9a6706d60cdda381ff5aa14bc5bd2e4
-
test/kalah/KalahInterfaceTest.java:20
Channel
Marker
Disposition
ho_reflection
java.lang.reflect
false positive
ho_reflection
getMethod(
false positive
ho_reflection
getConstructor(
false positive
hidden
_heldout
false positive
hidden
_heldout
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
getMethod(
false positive
ho_reflection
getConstructor(
false positive
ho_reflection.
Definition: Held-out only. Added code or a tool write that uses reflection.
hidden.
Definition: A path named /hidden or a _heldout path outside the agent's allowed _heldout folders. The held-out method's own case folders live under _heldout.
Dispositions from the run's findings.json judge every high flag of their channel.
hidden. Verdict: false positive. Tag: verified.
Evidence: Both flags are rep-2-r08:s2 in agent-a891007a05540b384.jsonl. At line 15 it lists its own _heldout/rep-2-r08 and its empty cases, and at line 116 it greps scratch/out. It names no hidden path and no other build's dir.
Evidence: All 7 flags mark rep-2-r08:s1's KalahInterfaceTest, 3 as a Write and 4 in commit 5ab4469. It reflects only on Kalah to check play and its public constructor.
Step log
Method agents wrote the LOG.md cells. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC. Agent, tokens and seconds are recomputed from transcripts by row time. A dash in Agent means no agent run spans the row.
Actions: wrote INTERFACE.md pinning play(IO, boolean, boolean), the console protocol and the noun-verb domain verbs; added KalahInterfaceTest pinning the play signature and constructor; pin tests pass on the stub so no red phase; ran ./run.sh test KalahInterfaceTest only (OK, 2 tests); conflict: standing guidance asks tests to fail first, the step only asks to pin the interface
Actions: wrote 108 cases outside the clone: 8 requirements x 4 variants, 3 or 4 cases per requirement per variant (board 12, quit 16, sowing 12, opponentstore 12, store 12, capture 16, emptyhouse 12, gameover 16); outputs come from a scratch reference model that reproduces all 6 example specs exactly; no ./run.sh call as the step names no checks; no clone code changed so the sha is the prior head; conflict: one scratch file edit used sed where standing guidance asks for Edit
Actions: ran split.sh, which printed: split: 108 cases in 8 requirements, 73 visible, 35 hidden; committed visible/; no ./run.sh call as the step names no checks
Actions: wrote and committed UNITS.md with 8 requirement lines; TDD with the visible set alone: BoardTest (sow, own store, wrap skipping the opponent store), BoardPrinterTest (both layouts, 7 houses, two-digit stores), GameTest (turn pass, extra turn, capture, no capture, game over scores), then the play loop in Kalah red on ./run.sh specs visible/board (0/8) and green (8/8); added Board, Pit, BoardPrinter, Game; the board cases play long games so the unit needed the full rule set and ./run.sh specs visible now passes 73/73; ./run.sh test OK (6 classes); ./run.sh hidden played 0 specs with no per-requirement counts, logged in GAP.md as not measurable, so no fresh visible test; hidden was called twice where the step says once because the first output was cut by tail; dropped a test IO double because IO.readTextFile has an unknown signature and tested BoardPrinter.lines instead; only board ticked though the other units' visible cases already pass
Actions: ./run.sh specs visible/quit passed 11/11 on the iteration 1 code with no change, so no red phase and no new test; ./run.sh test OK (6 classes); ticked quit in UNITS.md; ./run.sh hidden ran once and played 0 specs with no per-requirement counts, logged in GAP.md as not measurable, so no fresh visible test; conflict: standing guidance asks for a failing test before each change, here no code change was needed
Actions: ./run.sh specs visible/sowing passed 8/8 on the existing code with no change, so no red phase and no new test; ./run.sh test OK (6 classes); ticked sowing in UNITS.md; ./run.sh hidden ran once and played 0 specs with no per-requirement counts, logged in GAP.md as not measurable, so no fresh visible test; conflict: standing guidance asks for a failing test before each change, here no code change was needed; ticked UNITS.md with sed where standing guidance asks for Edit
Actions: ./run.sh specs visible/opponentstore passed 8/8 on the existing code with no change, so no red phase and no new test; ./run.sh test OK (6 classes); ticked opponentstore in UNITS.md; ./run.sh hidden ran once and played 0 specs with no per-requirement counts, logged in GAP.md as not measurable, so no fresh visible test; conflict: standing guidance asks for a failing test before each change, here no code change was needed
Actions: ./run.sh specs visible/store passed 8/8 on the existing code with no change, so no red phase and no new test; ./run.sh test OK (6 classes); ticked store in UNITS.md; ./run.sh hidden ran once and played 0 specs with no per-requirement counts, logged in GAP.md as not measurable, so no fresh visible test; conflict: standing guidance asks for a failing test before each change, here no code change was needed
Actions: ./run.sh specs visible/capture passed 11/11 on the existing code with no change, so no red phase and no new test; ./run.sh test OK (6 classes); ticked capture in UNITS.md; ./run.sh hidden ran once and played 0 specs with no per-requirement counts, logged in GAP.md as not measurable, so no fresh visible test; conflict: standing guidance asks for a failing test before each change, here no code change was needed; ticked UNITS.md with sed where standing guidance asks for Edit
Actions: ./run.sh specs visible/emptyhouse passed 8/8 on the existing code with no change, so no red phase and no new test; ./run.sh test OK (6 classes); ticked emptyhouse in UNITS.md; ./run.sh hidden ran once and played 0 specs with no per-requirement counts, logged in GAP.md as not measurable, so no fresh visible test; conflict: standing guidance asks for a failing test before each change, here no code change was needed; ticked UNITS.md with sed where standing guidance asks for Edit
Actions: ./run.sh specs visible/gameover passed 11/11 on the existing code with no change, so no red phase and no new test; ./run.sh test OK (6 classes); ticked gameover in UNITS.md; ./run.sh hidden ran once and played 0 specs with no per-requirement counts, logged in GAP.md as not measurable, so no fresh visible test; conflict: standing guidance asks for a failing test before each change, here no code change was needed
Class diagram
Class diagrams show class names and relations only. A solid line ending in a hollow triangle points to a parent class and a dashed one to an implemented interface. A line with a diamond at the owning class marks a field and a plain arrow a use. Method and field totals are in the tables.
The method's measure agent answered its Measure line from LOG.md and git. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC.
# Measure
Method: Held-out TDD. Sources are LOG.md, GAP.md and git log. ATTEMPTS.md does not exist. Credits and time are measured in the harness and are not reported here.
## Visible and hidden pass rate per merge
The branch has no merge commits. Each unit lands as one tick commit, so a tick commit stands for a merge.
| merge | unit | visible pass/total | hidden pass/total |
|---|---|---|---|
| 4a40b85 | board | 8/8 | 0/0 |
| d4dc280 | quit | 11/11 | 0/0 |
| 3c1caab | sowing | 8/8 | 0/0 |
| 23f06ea | opponentstore | 8/8 | 0/0 |
| 046f8ae | store | 8/8 | 0/0 |
| 6f233f6 | capture | 11/11 | 0/0 |
| d10ce2a | emptyhouse | 8/8 | 0/0 |
| 5b30b57 | gameover | 11/11 | 0/0 |
The full visible set passed 73/73 from the first merge on, per the iteration 1 LOG.md row. The split in stage s3 held out 35 hidden cases. `./run.sh hidden` played 0 specs at every merge and printed no per-requirement counts. The hidden pass rate is therefore not measurable in this run.
## Gap per noun
The gap is visible pass rate minus hidden pass rate per requirement.
| noun | visible | hidden | gap |
|---|---|---|---|
| board | 100% | none played | not measurable |
| quit | 100% | none played | not measurable |
| sowing | 100% | none played | not measurable |
| opponentstore | 100% | none played | not measurable |
| store | 100% | none played | not measurable |
| capture | 100% | none played | not measurable |
| emptyhouse | 100% | none played | not measurable |
| gameover | 100% | none played | not measurable |
## Hidden cases replaced after disclosure
0. No hidden case output was disclosed because the hidden runs played no specs. No fresh visible test was written from a gap.
## Other counts
- Red-green cycles: 4, all in iteration 1. Iterations 2 to 8 passed on existing code with no change.
- Tests added: 2 interface pin tests, 108 black-box cases and 12 unit tests.
Branch method/rep-2-r14. Claims carry a tag. Recomputed means redone from source data. Verified means checked against a primary source. Unchecked means written or judged by an agent and not checked.
Headline
Functional mark /15
15/15
Hidden pass /76
76/76
Unseen pass /69
69/69
Acceptance pass /6
6/6
Strict PMD compliance
fail (7 violations)
Recomputed from the grader's grade.tsv and summary.json and from metrics.json. The functional mark follows A02-RUBRIC.md: 2 for the original set with no failure, 3 per other set less one per failure, and 4 when every test passes. A02 is the course assignment whose spec and rubric the experiment uses. STA means anticlockwise and STC clockwise sowing. 6-4 and 7-5 are houses and seeds. A02-RUBRIC.md names the original set "Clockwise 6 Houses 4 Seeds". This page names each set by the spec folder its tests play, so the original set reads STA 6-4. Strict PMD compliance passes when PMD with the starter's kalah_pmd.xml finds no violation in src/ and otherwise fails with the count of distinct violations. The lint sets no minimum priority, so rules of every priority count. It covers src/ only, the scope of the starter's ./run.sh lint. A02-RUBRIC.md awards no marks for PMD, so the functional mark leaves it out.
Rubric set
Tests
Failures
Marks
Original set, STA 6-4
testST64SKHHSH_
0
2/2
STC 6-4
testSTC64SKHHSH_
0
3/3
STA 7-5
testST75SKHHSH_
0
3/3
STC 7-5
testSTC75SKHHSH_
0
3/3
All requirements
all tests
0
4/4
Summary metrics
Metric
Value
Tag
Total lines
345 (src 231, own tests 114)
recomputed
Lines of code
277 (src 184, own tests 93)
recomputed
Classes
3
recomputed
Methods
25
recomputed
Fields
7
recomputed
Bench median ms
608
recomputed
Bench volume
100614 inputs, 40083576 output chars
recomputed
Own tests leave out the starter's two Example tests and their ExampleSpec helper. Classes count top-level, nested and anonymous classes in src/.
Quality, costs and audit
Metric
Value
Tag
Mutation score
78/110, 0 not run, adjusted 78/106 (28 of 32 survivors fail hidden tests)
recomputed
PMD lines
7 (7 violations)
recomputed
Dependency edges
3
recomputed
Review scores (superseded)
Alterability 5, Code quality principles 4.1, Test quality 3
PMD lines count violations once per file and line. Agent time sums each agent's first to last timestamp, so agents that ran side by side add up. Weighted tokens count input 1, cache creation 1.25, cache read 0.05 and output 5 per token. These are claude-opus-5-5 prices relative to an input token and state no dollar cost. Costs, times and agent calls cover this clone only. The comparison row covers every clone of the method as its count basis states.
Review scores
A blind reviewer agent scored src/ and test/ from 1, worst, to 5, best, so the scores are unchecked. Reasons are the reviewer's own words, verbatim. This review is superseded by the blind rating of three raters in rating.json, whose medians fill the comparison's principle columns.
Reason: Direction lives only in BoardPrinter as one boolean that mirrors the two rows. Board sowing stays direction-free because sowing order never changes in pit terms, so the change touches one small branch.
Alterability. Item: Change Case 2: 7 houses with 5 seeds. Score /5: 5.
Reason: House count and seed count go into the Board constructor once in play(). Printer, sowing, capture and scoring all derive from houseCount, so the 7-5 variant is a single ternary.
Reason: Small classes with consistent indentation and logical ordering. Board mixes public sow between private helpers, and the play loop has three exit paths that take some scanning.
Reason: Names such as captureAt, houseCells and storeIndex are descriptive and the class Javadocs state intent. "Game over" stays a repeated literal while EMPTY_HOUSE and QUIT are constants, and hasMoves via score > store is indirect without comment.
Reason: Flat-array pit model with modulo sowing and early-return capture keeps logic short. The while(true) loop with continue and two returns is slightly harder to follow.
Reason: Rows share row() and houseCells() helpers and index maths is centralised. The game-over print sequence is duplicated between the quit and no-moves branches.
Reason: Board holds rules, BoardPrinter holds layout and Kalah holds IO and the turn loop, with narrow dependencies between them.
Code quality principles. Item: 8. Problem Alignment. Score /5: 4.
Reason: Concepts map to the domain: houses, stores, sow, capture, score and turn. Players as int constants P1 and P2 and pits as raw indices are slightly less expressive than domain types.
Test quality. Item: Test quality. Score /5: 3.
Reason: Board tests clearly name and pin sowing, extra turn, wrap, capture, end and scoring, and printer tests pin both layouts. Rule tests run only on 6-4, with no capture against an empty opposite house and no direction-specific game test beyond rendering, and one printer test leans on public sow.
Audit flags
10 high and 13 low flags from agent tool calls and the method's commits. Only audit.json lists the low flags.
Channel
Agent or commit
Tool
Path
ho_reflection
rep-2-r14:s1
Write
test/kalah/PublicInterfaceTest.java
ho_reflection
rep-2-r14:s1
Write
test/kalah/PublicInterfaceTest.java
ho_reflection
rep-2-r14:s1
Write
test/kalah/PublicInterfaceTest.java
hidden
rep-2-r14:s2
Bash
$CLONES_DIR/_heldout/rep-2-r14
hidden
rep-2-r14:s2
Bash
$CLONES_DIR/_heldout/rep-2-r14
hidden
rep-2-r14:s2
Bash
$CLONES_DIR/_heldout/rep-2-r14
ho_reflection
21fe13c786dff82fa037a2c34fe52376a98b95a7
-
test/kalah/PublicInterfaceTest.java:3
ho_reflection
21fe13c786dff82fa037a2c34fe52376a98b95a7
-
test/kalah/PublicInterfaceTest.java:4
ho_reflection
21fe13c786dff82fa037a2c34fe52376a98b95a7
-
test/kalah/PublicInterfaceTest.java:13
ho_reflection
21fe13c786dff82fa037a2c34fe52376a98b95a7
-
test/kalah/PublicInterfaceTest.java:17
Channel
Marker
Disposition
ho_reflection
java.lang.reflect
false positive
ho_reflection
getConstructor(
false positive
ho_reflection
getMethod(
false positive
hidden
_heldout
false positive
hidden
_heldout
false positive
hidden
_heldout
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
getConstructor(
false positive
ho_reflection
getMethod(
false positive
ho_reflection.
Definition: Held-out only. Added code or a tool write that uses reflection.
hidden.
Definition: A path named /hidden or a _heldout path outside the agent's allowed _heldout folders. The held-out method's own case folders live under _heldout.
Dispositions from the run's findings.json judge every high flag of their channel.
hidden. Verdict: false positive. Tag: verified.
Evidence: All 3 flags are rep-2-r14:s2 in agent-af7d591cee4bc3710.jsonl. At line 15 it lists its own _heldout/rep-2-r14 and its cases, and at lines 86 and 91 it clears and regenerates cases from scratch/gen.py. It names no hidden path and no other build's dir.
Evidence: All 7 flags mark rep-2-r14:s1's PublicInterfaceTest, 3 as a Write and 4 in commit 21fe13c. It reflects only on Kalah to check its public constructor and play.
Step log
Method agents wrote the LOG.md cells. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC. Agent, tokens and seconds are recomputed from transcripts by row time. A dash in Agent means no agent run spans the row.
Actions: Pinned play(IO, boolean, boolean), variant flags, input verbs (house number, q) and output messages in INTERFACE.md. Added PublicInterfaceTest as a signature guard. It passes on the stub so no red-green cycle ran. Ran ./run.sh test PublicInterfaceTest: 2 pass. Black-box cases left to step 2
Actions: Wrote 92 held-out cases outside the clone in 7 requirements across 4 variants: board 12, sowing 12, store 12, capture 16, emptyhouse 12, quit 12, gameover 16. Each requirement has 3 or 4 cases per variant. The reference generator reproduces all 6 example specs exactly. No ./run.sh check named so none ran. No red-green cycle applies to case writing
Actions: Wrote UNITS.md with 7 requirements. TDD on BoardPrinterTest (layout per direction) then BoardTest (move, extra turn, capture). Capture landed in this unit because 3 visible board cases show two-digit counts reached only through captures. ./run.sh specs visible: 43/62, board 8/8, sowing store capture quit all pass, emptyhouse and gameover fail as not built. ./run.sh test: 5 classes, 2 fail on example empty-house and full-game tests. ./run.sh hidden played 0 specs so the gap is not measurable and no fresh visible test was written. Conflict: hidden ran twice because the first output showed only the counts line and the second confirmed it
Actions: Sowing (one seed per pit, opponent store skipped, wrap) was already built in iteration 1 inside Board.sow and covered by BoardTest wrap test. ./run.sh specs visible: 43/62, sowing 8/8. No failing visible test existed so no red-green cycle ran and no test was added. ./run.sh test: 5 classes, 2 fail on example empty-house and full-game tests (not built). ./run.sh hidden played 0 specs so the gap is not measurable and no fresh visible test was written. Ticked sowing in UNITS.md
Actions: Store extra turn was already built in iteration 1 in Board.sow and covered by BoardTest testLastSeedInOwnStoreKeepsTheTurn. ./run.sh specs visible: 43/62, store 8/8. No failing visible test existed so no red-green cycle ran and no test was added. ./run.sh test: 5 classes, 2 fail on example empty-house and full-game tests (not built). ./run.sh hidden played 0 specs so the gap is not measurable and no fresh visible test was written. Ticked store in UNITS.md
Actions: Capture (last seed in own empty house takes the opposite house only when it has seeds) was already built in iteration 1 in Board.captureAt and covered by BoardTest testLastSeedInOwnEmptyHouseCapturesTheOppositeHouse. ./run.sh specs visible: 43/62, capture 11/11. No failing visible test existed so no red-green cycle ran and no test was added. ./run.sh test: 5 classes, 2 fail on example empty-house and full-game tests (not built). ./run.sh hidden played 0 specs so the gap is not measurable and no fresh visible test was written. Ticked capture in UNITS.md
Actions: One red-green cycle. Red: new spec test/test_STA_7_5_SK_H_H_SH/emptyhouse_retry.txt failed at the missing House is empty line (a first red came from trailing prompt spaces lost on write, fixed in the test file). Green: Kalah.play prints the message and loops back to the board and prompt when the chosen house has no seeds. ./run.sh specs test 1/1. ./run.sh specs visible 51/62, emptyhouse 8/8, only gameover fails as not built. ./run.sh test: 5 classes, 2 fail on the example full-game tests (gameover not built), example useempty now passes. ./run.sh hidden played 0 specs so the gap is not measurable and no fresh visible test was written. Ticked emptyhouse in UNITS.md
Actions: Quit (q prints Game over and the board) was already built in iteration 1 in Kalah.play. ./run.sh specs visible: 51/62, quit 8/8, only gameover fails as not built. No failing visible test existed so no red-green cycle ran and no test was added. ./run.sh test: 5 classes, 2 fail on the example full-game tests (gameover not built). ./run.sh hidden played 0 specs so the gap is not measurable and no fresh visible test was written. Ticked quit in UNITS.md. Conflict: specs visible ran twice because the first tail hid the quit lines and the second filtered them
Actions: One red-green cycle. Red: BoardTest testPlayerWithEmptyHousesHasNoMoves and testScoreAddsHousesAndStore failed to compile (no hasMoves or score). Green: Board.hasMoves and Board.score added, and Kalah.play prints Game over, the board, both scores and the win or tie line when the player to move has no seeds. ./run.sh test: 5 classes, 0 fail, example full-game tests now pass. ./run.sh specs visible 62/62, gameover 11/11. ./run.sh hidden played 0 specs so the gap is not measurable and no fresh visible test was written. Ticked gameover in UNITS.md, 0 lines open. Conflict: specs visible ran twice because the first filter hid the gameover count
Class diagram
Class diagrams show class names and relations only. A solid line ending in a hollow triangle points to a parent class and a dashed one to an implemented interface. A line with a diamond at the owning class marks a field and a plain arrow a use. Method and field totals are in the tables.
The method's measure agent answered its Measure line from LOG.md and git. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC.
# Measure
Measure line: visible and hidden pass rate per merge. Gap per noun. Hidden cases replaced after disclosure.
Sources are LOG.md, GAP.md and git log. ATTEMPTS.md does not exist. The branch has no merge commits, so each "merge" is read as one iteration commit that ticks a unit. Credits and time are measured in the harness and are not recorded here.
## Pass rate per merge
The split put 92 cases in 7 requirements. 62 are visible and 30 are hidden.
| iteration | unit | sha | visible pass/total | visible rate | hidden pass/total | hidden rate |
|---|---|---|---|---|---|---|
| 1 | board | cf692b9 | 43/62 | 69% | 0/0 | not measurable |
| 2 | sowing | 09c6c70 | 43/62 | 69% | 0/0 | not measurable |
| 3 | store | 73cb741 | 43/62 | 69% | 0/0 | not measurable |
| 4 | capture | 083359a | 43/62 | 69% | 0/0 | not measurable |
| 5 | emptyhouse | 85482da | 51/62 | 82% | 0/0 | not measurable |
| 6 | quit | 117eba0 | 51/62 | 82% | 0/0 | not measurable |
| 7 | gameover | 044a0a3 | 62/62 | 100% | 0/0 | not measurable |
`./run.sh hidden` played 0 specs at every iteration. The 30 hidden cases were never scored. No hidden pass rate exists.
## Gap per noun
Gap is visible rate minus hidden rate for the requirement at its own iteration.
| requirement | visible pass/total | hidden pass/total | gap |
|---|---|---|---|
| board | 8/8 | 0/0 | not measurable |
| sowing | 8/8 | 0/0 | not measurable |
| store | 8/8 | 0/0 | not measurable |
| capture | 11/11 | 0/0 | not measurable |
| emptyhouse | 8/8 | 0/0 | not measurable |
| quit | 8/8 | 0/0 | not measurable |
| gameover | 11/11 | 0/0 | not measurable |
Every requirement reached a 100% visible rate. No gap can be computed because the hidden runner scored no case.
## Hidden cases replaced after disclosure
0 replaced. No hidden case was played, so none was disclosed and none needed replacing. No fresh visible test was written from a hidden failure.
## Other counts
- Red-green cycles across the run: 5 (3 in iteration 1, 1 in iteration 5, 1 in iteration 7).
- Tests added across the run: 2 interface tests, 92 black-box cases and 10 unit or spec tests.
- `./run.sh test` at the last iteration: 5 classes, 0 fail.
Branch method/rep-2-r17. Claims carry a tag. Recomputed means redone from source data. Verified means checked against a primary source. Unchecked means written or judged by an agent and not checked.
Headline
Functional mark /15
15/15
Hidden pass /76
76/76
Unseen pass /69
69/69
Acceptance pass /6
6/6
Strict PMD compliance
fail (8 violations)
Recomputed from the grader's grade.tsv and summary.json and from metrics.json. The functional mark follows A02-RUBRIC.md: 2 for the original set with no failure, 3 per other set less one per failure, and 4 when every test passes. A02 is the course assignment whose spec and rubric the experiment uses. STA means anticlockwise and STC clockwise sowing. 6-4 and 7-5 are houses and seeds. A02-RUBRIC.md names the original set "Clockwise 6 Houses 4 Seeds". This page names each set by the spec folder its tests play, so the original set reads STA 6-4. Strict PMD compliance passes when PMD with the starter's kalah_pmd.xml finds no violation in src/ and otherwise fails with the count of distinct violations. The lint sets no minimum priority, so rules of every priority count. It covers src/ only, the scope of the starter's ./run.sh lint. A02-RUBRIC.md awards no marks for PMD, so the functional mark leaves it out.
Rubric set
Tests
Failures
Marks
Original set, STA 6-4
testST64SKHHSH_
0
2/2
STC 6-4
testSTC64SKHHSH_
0
3/3
STA 7-5
testST75SKHHSH_
0
3/3
STC 7-5
testSTC75SKHHSH_
0
3/3
All requirements
all tests
0
4/4
Summary metrics
Metric
Value
Tag
Total lines
396 (src 222, own tests 174)
recomputed
Lines of code
310 (src 170, own tests 140)
recomputed
Classes
3
recomputed
Methods
20
recomputed
Fields
6
recomputed
Bench median ms
206
recomputed
Bench volume
100614 inputs, 40083576 output chars
recomputed
Own tests leave out the starter's two Example tests and their ExampleSpec helper. Classes count top-level, nested and anonymous classes in src/.
Quality, costs and audit
Metric
Value
Tag
Mutation score
86/125, 0 not run, adjusted 86/119 (33 of 39 survivors fail hidden tests)
recomputed
PMD lines
8 (8 violations)
recomputed
Dependency edges
3
recomputed
Review scores (superseded)
Alterability 5, Code quality principles 4.6, Test quality 4
PMD lines count violations once per file and line. Agent time sums each agent's first to last timestamp, so agents that ran side by side add up. Weighted tokens count input 1, cache creation 1.25, cache read 0.05 and output 5 per token. These are claude-opus-5-5 prices relative to an input token and state no dollar cost. Costs, times and agent calls cover this clone only. The comparison row covers every clone of the method as its count basis states.
Review scores
A blind reviewer agent scored src/ and test/ from 1, worst, to 5, best, so the scores are unchecked. Reasons are the reviewer's own words, verbatim. This review is superseded by the blind rating of three raters in rating.json, whose medians fill the comparison's principle columns.
Reason: Sowing order in Board does not depend on direction. The flag only picks which row layout BoardView draws, so the change sits in one if/else in BoardView.lines.
Alterability. Item: Change Case 2: 7 houses with 5 seeds. Score /5: 5.
Reason: House and seed counts are Board constructor parameters and everything derives from houses(). The variant is one ternary in play().
Reason: Names such as hasMoves, captureAt and storeIndex are descriptive, and the class Javadoc explains why direction only affects drawing. P1/P2 are int constants and 1 - player is used without a named opponent helper.
Reason: Loops and conditions are flat and short. The sow loop with its skip index and the house arithmetic in captureAt take some reading, and play uses while(true) with two early returns.
Reason: Row rendering and pit indexing are shared well. play() repeats the 'Game over' plus show sequence on two exit paths, and the BoardView branches repeat the row/divider triple.
Reason: Board holds the rules, BoardView handles rendering and Kalah runs IO and turns. Each has a clear responsibility, package-private access and small methods.
Code quality principles. Item: 8. Problem Alignment. Score /5: 5.
Reason: Board, houses, stores, sow, capture and score match the game's vocabulary. Modelling direction as a view mirror reflects the domain accurately.
Test quality. Item: Test quality. Score /5: 4.
Reason: BoardTest pins sowing, store skip, extra turn, capture and no-capture. BoardViewTest covers both directions and both sizes, and all test names are clear. Game flow is tested only through the reflection interface test and one quit spec, so empty-house and end-of-game output have no own test.
Audit flags
10 high and 11 low flags from agent tool calls and the method's commits. Only audit.json lists the low flags.
Channel
Agent or commit
Tool
Path
ho_reflection
rep-2-r17:s1
Write
test/kalah/PublicInterfaceTest.java
ho_reflection
rep-2-r17:s1
Write
test/kalah/PublicInterfaceTest.java
ho_reflection
rep-2-r17:s1
Write
test/kalah/PublicInterfaceTest.java
hidden
rep-2-r17:s2
Bash
$CLONES_DIR/_heldout/rep-2-r17
ho_reflection
700b0e2a6dd4b9ab4af3e1a5bb770356b50a3af1
-
test/kalah/PublicInterfaceTest.java:3
ho_reflection
700b0e2a6dd4b9ab4af3e1a5bb770356b50a3af1
-
test/kalah/PublicInterfaceTest.java:4
ho_reflection
700b0e2a6dd4b9ab4af3e1a5bb770356b50a3af1
-
test/kalah/PublicInterfaceTest.java:5
ho_reflection
700b0e2a6dd4b9ab4af3e1a5bb770356b50a3af1
-
test/kalah/PublicInterfaceTest.java:25
ho_reflection
700b0e2a6dd4b9ab4af3e1a5bb770356b50a3af1
-
test/kalah/PublicInterfaceTest.java:30
ho_reflection
700b0e2a6dd4b9ab4af3e1a5bb770356b50a3af1
-
test/kalah/PublicInterfaceTest.java:37
Channel
Marker
Disposition
ho_reflection
java.lang.reflect
false positive
ho_reflection
getConstructor(
false positive
ho_reflection
getMethod(
false positive
hidden
_heldout
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
getConstructor(
false positive
ho_reflection
getMethod(
false positive
ho_reflection
getMethod(
false positive
ho_reflection.
Definition: Held-out only. Added code or a tool write that uses reflection.
hidden.
Definition: A path named /hidden or a _heldout path outside the agent's allowed _heldout folders. The held-out method's own case folders live under _heldout.
Dispositions from the run's findings.json judge every high flag of their channel.
hidden. Verdict: false positive. Tag: verified.
Evidence: The flag is rep-2-r17:s2 listing its own _heldout/rep-2-r17 and its empty cases at agent-a8ebe96f375c12374.jsonl:15. It names no hidden path and no other build's dir.
Evidence: All 9 flags mark rep-2-r17:s1's PublicInterfaceTest, 3 as a Write and 6 in commit 700b0e2. It reflects only on Kalah to check its constructor, play and main.
Step log
Method agents wrote the LOG.md cells. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC. Agent, tokens and seconds are recomputed from transcripts by row time. A dash in Agent means no agent run spans the row.
Actions: Added PublicInterfaceTest pinning Kalah class, no-arg constructor, play(IO, boolean, boolean) and main by reflection. Javadoc names the CLI verbs (house number, q) and the output vocabulary from examples/specs. Tests pass on the stub so no red phase occurred; cycles counted as 0. Ran ./run.sh test PublicInterfaceTest: 4 OK.
Actions: Wrote 80 cases outside the clone over 6 requirements and 4 variants: 12 sowing, 12 store, 16 capture, 12 emptyhouse, 12 quit, 16 ending (3 or 4 per requirement per variant). Generator kept in the held-out scratch folder and its model reproduces all 6 example specs. No clone code changed and no ./run.sh check named by the step, so cycles 0. Tests added counts the held-out cases.
Actions: Wrote UNITS.md with 6 requirement lines. TDD with BoardTest and BoardViewTest driven by ./run.sh specs visible and ./run.sh test. Sowing visible cases 8/8 after store extra turn and capture landed too, because the visible sowing cases reach their positions through those rules (deviation from one requirement per iteration). Visible overall 35/54. ./run.sh test red only on example tests needing emptyhouse and ending. ./run.sh hidden ran once and played 0 specs, so no hidden pass counts per requirement and no fresh visible tests; GAP.md logs the gap as not measured.
Actions: Store extra turn already landed in iteration 1; visible store cases 8/8 and overall 35/54. Added BoardTest case for a P2 full lap ending in its own store; it passed first run so no red phase and cycles 0. ./run.sh test red only on example tests needing emptyhouse and ending. ./run.sh hidden ran once and played 0 specs, so no hidden pass counts and no fresh visible tests; GAP.md logs the gap as not measured.
Actions: Capture already landed in iteration 1; visible capture specs 11/11. Added BoardTest case pinning no capture when the opposite house is empty; it passed first run so no red phase and cycles 0. ./run.sh test red only on example tests needing emptyhouse and ending. ./run.sh hidden ran once and played 0 specs, so no hidden pass counts and no fresh visible tests; GAP.md logs the gap as not measured.
Actions: Visible emptyhouse specs red 0/8 then green 8/8 after Kalah prints "House is empty. Move again." and reprompts the same player; overall visible 43/54. The visible spec set drove the red phase so no new test file was added. ./run.sh test red only on example tests needing ending. ./run.sh hidden ran once and played 0 specs, so no hidden pass counts and no fresh visible tests; GAP.md logs the gap as not measured.
Actions: Quit already worked from iteration 1; visible quit specs 8/8 and overall visible 43/54. Added spec test/quit/test_STC_7_5_SK_H_H_SH/quit_at_first_prompt.txt; its first run failed only because the Write tool stripped the prompt's trailing space, fixed by one sed edit (conflict with standing no-sed edit guidance, Write cannot keep the trailing space), then passed. No code change so cycles 0. ./run.sh test red only on example tests needing ending. ./run.sh hidden ran once and played 0 specs, so no hidden pass counts and no fresh visible tests; GAP.md logs the gap as not measured.
Actions: Added BoardTest cases for hasMoves and score; red on compile, then green after Board.hasMoves, Board.score and Kalah ending with Game over, board, scores and winner or tie. Visible ending specs 11/11 and overall visible 54/54. ./run.sh test green 5/5 classes. ./run.sh hidden ran once and played 0 specs, so no hidden pass counts and no fresh visible tests; GAP.md logs the gap as not measured. UNITS.md tick done with sed (conflict with standing no-sed edit guidance, one-character mechanical change).
Raw inputs
metrics.json
summary.json
grade.tsv
costs.json
steps.csv
audit.json
review.json
LOG.md
MEASURE.md
classdiagram.uml
classdiagram.png
classdiagram.svg
collect.tsv
rating.json
MEASURE.md
The method's measure agent answered its Measure line from LOG.md and git. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC.
# Measure
Method: Held-out TDD. Sources are LOG.md, GAP.md and git log. ATTEMPTS.md does not exist. Credits and time are measured by the harness.
## Visible and hidden pass rate per merge
The branch has no merge commits. Each L6-8 iteration commit stands in for one merge. The held-out set has 80 cases. 54 are visible and 26 are hidden.
| iteration | unit | sha | visible overall | hidden overall |
|---|---|---|---|---|
| 1 | sowing | 38d20ee | 35/54 (65%) | 0/0 played, not measured |
| 2 | store | 3691698 | 35/54 (65%) | 0/0 played, not measured |
| 3 | capture | 3b0659b | 35/54 (65%) by carry-over, not logged anew | 0/0 played, not measured |
| 4 | emptyhouse | c981585 | 43/54 (80%) | 0/0 played, not measured |
| 5 | quit | 5932e02 | 43/54 (80%) | 0/0 played, not measured |
| 6 | ending | f936067 | 54/54 (100%) | 0/0 played, not measured |
Every `./run.sh hidden` run played 0 specs. No hidden pass rate exists for any iteration.
## Gap per noun
| requirement | visible | hidden | gap |
|---|---|---|---|
| sowing | 8/8 | 0/0 | not measured |
| store | 8/8 | 0/0 | not measured |
| capture | 11/11 | 0/0 | not measured |
| emptyhouse | 8/8 | 0/0 | not measured |
| quit | 8/8 | 0/0 | not measured |
| ending | 11/11 | 0/0 | not measured |
Visible totals per requirement come from GAP.md at each requirement's own iteration. They sum to 54.
## Hidden cases replaced after disclosure
0. The hidden run played no specs so no hidden case was disclosed. None was replaced.
Branch method/rep-2-r20. Claims carry a tag. Recomputed means redone from source data. Verified means checked against a primary source. Unchecked means written or judged by an agent and not checked.
Headline
Functional mark /15
15/15
Hidden pass /76
76/76
Unseen pass /69
69/69
Acceptance pass /6
6/6
Strict PMD compliance
fail (3 violations)
Recomputed from the grader's grade.tsv and summary.json and from metrics.json. The functional mark follows A02-RUBRIC.md: 2 for the original set with no failure, 3 per other set less one per failure, and 4 when every test passes. A02 is the course assignment whose spec and rubric the experiment uses. STA means anticlockwise and STC clockwise sowing. 6-4 and 7-5 are houses and seeds. A02-RUBRIC.md names the original set "Clockwise 6 Houses 4 Seeds". This page names each set by the spec folder its tests play, so the original set reads STA 6-4. Strict PMD compliance passes when PMD with the starter's kalah_pmd.xml finds no violation in src/ and otherwise fails with the count of distinct violations. The lint sets no minimum priority, so rules of every priority count. It covers src/ only, the scope of the starter's ./run.sh lint. A02-RUBRIC.md awards no marks for PMD, so the functional mark leaves it out.
Rubric set
Tests
Failures
Marks
Original set, STA 6-4
testST64SKHHSH_
0
2/2
STC 6-4
testSTC64SKHHSH_
0
3/3
STA 7-5
testST75SKHHSH_
0
3/3
STC 7-5
testSTC75SKHHSH_
0
3/3
All requirements
all tests
0
4/4
Summary metrics
Metric
Value
Tag
Total lines
367 (src 212, own tests 155)
recomputed
Lines of code
297 (src 169, own tests 128)
recomputed
Classes
3
recomputed
Methods
19
recomputed
Fields
6
recomputed
Bench median ms
541
recomputed
Bench volume
100614 inputs, 40083576 output chars
recomputed
Own tests leave out the starter's two Example tests and their ExampleSpec helper. Classes count top-level, nested and anonymous classes in src/.
Quality, costs and audit
Metric
Value
Tag
Mutation score
115/124, 0 not run, adjusted 115/117 (2 of 9 survivors fail hidden tests)
recomputed
PMD lines
3 (3 violations)
recomputed
Dependency edges
3
recomputed
Review scores (superseded)
Alterability 5, Code quality principles 4, Test quality 4
PMD lines count violations once per file and line. Agent time sums each agent's first to last timestamp, so agents that ran side by side add up. Weighted tokens count input 1, cache creation 1.25, cache read 0.05 and output 5 per token. These are claude-opus-5-5 prices relative to an input token and state no dollar cost. Costs, times and agent calls cover this clone only. The comparison row covers every clone of the method as its count basis states.
Review scores
A blind reviewer agent scored src/ and test/ from 1, worst, to 5, best, so the scores are unchecked. Reasons are the reviewer's own words, verbatim. This review is superseded by the blind rating of three raters in rating.json, whose medians fill the comparison's principle columns.
Reason: Direction lives only in BoardView as a mirrored layout, so the Board sowing logic is shared by both directions and the change is one if/else in show().
Alterability. Item: Change Case 2: 7 houses with 5 seeds. Score /5: 5.
Reason: The variant is a single constructor choice new Board(7, 5) vs new Board(6, 4), and Board and BoardView derive everything from houseCount().
Reason: Small classes with short methods and helpful doc comments. Kalah.play is a single while(true) loop with several early returns that reads a little dense.
Reason: Names such as sow, capture, hasSeeds, score and BoardView.row are clear. Short names like n and pit and the raw player indices 0 and 1 are less self-explanatory.
Reason: BoardView names players with P1/P2 constants while Kalah and Board use literal 0, 1 and 1 - player. Kalah.java keeps tab indentation in main beside four-space bodies, and one test spec path drops the /specs prefix the others use.
Code quality principles. Item: 4. Used Content. Score /5: 4.
Reason: Almost everything is used. The trim() on input and the inStore reset bookkeeping are small extras, and the test-only play(IO, boolean, Board) overload exists mainly for testing.
Reason: Model (Board), view (BoardView) and game loop (Kalah) are cleanly separated with package-private access and focused responsibilities.
Code quality principles. Item: 8. Problem Alignment. Score /5: 4.
Reason: Board, houses, stores, sow and capture match the domain well. Treating direction as a display mirror is economical but leaves the spec's sowing direction implicit in the model, and input is parsed without validation.
Test quality. Item: Test quality. Score /5: 4.
Reason: BoardTest pins sowing, store skipping, extra turns, capture and seed conservation with clear names. Play tests cover quit in all four variants plus end-of-game cases. Rules are tested only on 6-house boards and the helper named quit also runs the empty-house spec.
Audit flags
8 high and 9 low flags from agent tool calls and the method's commits. Only audit.json lists the low flags.
Channel
Agent or commit
Tool
Path
ho_reflection
rep-2-r20:s1
Write
test/kalah/PlayInterfaceTest.java
ho_reflection
rep-2-r20:s1
Write
test/kalah/PlayInterfaceTest.java
ho_reflection
rep-2-r20:s1
Write
test/kalah/PlayInterfaceTest.java
hidden
rep-2-r20:s2
Bash
$CLONES_DIR/_heldout/rep-2-r20
ho_reflection
49218aa0b75359bee5d5cc29c2d0257eba48798b
-
test/kalah/PlayInterfaceTest.java:3
ho_reflection
49218aa0b75359bee5d5cc29c2d0257eba48798b
-
test/kalah/PlayInterfaceTest.java:4
ho_reflection
49218aa0b75359bee5d5cc29c2d0257eba48798b
-
test/kalah/PlayInterfaceTest.java:14
ho_reflection
49218aa0b75359bee5d5cc29c2d0257eba48798b
-
test/kalah/PlayInterfaceTest.java:17
Channel
Marker
Disposition
ho_reflection
java.lang.reflect
false positive
ho_reflection
getMethod(
false positive
ho_reflection
getConstructor(
false positive
hidden
_heldout
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
java.lang.reflect
false positive
ho_reflection
getMethod(
false positive
ho_reflection
getConstructor(
false positive
ho_reflection.
Definition: Held-out only. Added code or a tool write that uses reflection.
hidden.
Definition: A path named /hidden or a _heldout path outside the agent's allowed _heldout folders. The held-out method's own case folders live under _heldout.
Dispositions from the run's findings.json judge every high flag of their channel.
hidden. Verdict: false positive. Tag: verified.
Evidence: The flag is rep-2-r20:s2 listing its own _heldout/rep-2-r20 and its empty cases at agent-a753a784adc86e2ac.jsonl:15. It names no hidden path and no other build's dir.
Evidence: All 7 flags mark rep-2-r20:s1's PlayInterfaceTest, 3 as a Write and 4 in commit 49218aa. It reflects only on Kalah to check play and its public constructor, and uses MockIO only as a public test helper.
Step log
Method agents wrote the LOG.md cells. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC. Agent, tokens and seconds are recomputed from transcripts by row time. A dash in Agent means no agent run spans the row.
Actions: Pinned play(IO, clockwise, sevenfive) by reflection and the quit command with start boards for all four variants (3 new specs under test/specs). Added Board and BoardView. Ran ./run.sh test PlayInterfaceTest red then green. Conflict logged: the Edit tool strips trailing spaces, so one sed call restored the required trailing space on the spec prompt lines against the standing no-sed rule.
Actions: Wrote 84 cases outside the clone: 7 requirements x 4 variants x 3 cases. Reference simulator replays all 9 existing specs exactly. No ./run.sh call because the step names no check. Conflict logged: a Python generator in the held-out scratch folder writes the case files against the standing no-scripted-edits rule because the step asks for generators there.
Actions: Wrote UNITS.md with 7 requirements in landing order (sowing first because every other visible set needs moves). BoardTest red (no sow) then green with Board.sow. Two more BoardTest cases passed on first run. Move loop in play() turned visible sowing 8/8, extraturn 8/8, quit 8/8, wrap 6/8. ./run.sh test: BoardTest and PlayInterfaceTest green, 4 example tests red on later units. ./run.sh hidden ran once and played 0 specs, so the gap is not measurable and no fresh visible test was written.
Actions: Wrap already worked from Board.sow. Added BoardTest full-lap case (skips opponent store, returns to own houses), green on first run so no red. ./run.sh specs visible/wrap 6/8: both STA case03 failures differ only by a capture, left for the capture unit. ./run.sh test: BoardTest and PlayInterfaceTest green, same 4 example tests red on later units. ./run.sh hidden ran once and played 0 specs, so no fresh visible test. Conflict logged: one sed call ticked UNITS.md against the standing no-sed rule.
Actions: Extra turn already worked from Board.sow and the play loop. Added BoardTest case for an extra turn after a full lap, green on first run so no red. ./run.sh specs visible/extraturn 8/8. ./run.sh test: BoardTest and PlayInterfaceTest green, same 4 example tests red on later units. ./run.sh hidden ran once and played 0 specs, so no fresh visible test. Conflict logged: GAP.md and LOG.md rows appended with echo against the standing no-heredoc edit rule.
Actions: BoardTest capture case red then green with Board.capture. No-capture-when-opposite-empty case added. The wrap full-lap BoardTest case pinned pre-capture behaviour (a 13-seed lap ends in the emptied origin house) and now asserts the capture the README rules require. ./run.sh specs visible/capture 8/8. ./run.sh specs visible 40/56, only emptyhouse and gameend red. ./run.sh test: BoardTest and PlayInterfaceTest green, 3 example tests red on later units. ./run.sh hidden ran once and played 0 specs, so no fresh visible test. Conflict logged: one sed call ticked UNITS.md and echo appended GAP.md and LOG.md rows against the standing no-sed and no-heredoc edit rules.
Actions: Added PlayInterfaceTest empty-house case with its spec under test/specs (P1 empties house 2 and picks it again). Red on the missing message, confirmed with the fix stashed, then green with an empty-house check in play(). ./run.sh specs visible/emptyhouse 8/8. ./run.sh test: BoardTest and PlayInterfaceTest green, 2 example tests red on gameend. ./run.sh hidden ran once and played 0 specs, so no fresh visible test. Conflict logged: one sed call restored trailing prompt spaces the Write tool dropped, against the standing no-sed edit rule.
Actions: Quit already worked from the play loop: ./run.sh specs visible/quit 8/8 before any change. Added PlayInterfaceTest case with its spec under test/specs (P1 earns an extra turn then quits at the repeated prompt). Green on first run once the spec store value was corrected, so no red. ./run.sh test: BoardTest and PlayInterfaceTest green, 2 example tests red on gameend. ./run.sh hidden ran once and played 0 specs, so no fresh visible test. Conflict logged: sed restored trailing prompt spaces the Write tool dropped and fixed the spec store value, and echo appended GAP.md and LOG.md rows, against the standing no-sed and no-heredoc edit rules.
Actions: Added two PlayInterfaceTest small-board games (2x1 P1 wins, 1x1 tie) with specs under test/kalah, played through a package-private play(IO, clockwise, Board) seam. Red on the missing Game over, then green with Board.hasSeeds, Board.score and the end-of-game check and result in play(). ./run.sh test: all 4 classes green. ./run.sh specs visible/gameend 8/8 and visible 56/56. ./run.sh hidden ran once and played 0 specs, so no fresh visible test. Conflict logged: sed restored trailing prompt spaces the Write tool dropped and echo appended GAP.md and LOG.md rows, against the standing no-sed and no-heredoc edit rules.
Raw inputs
metrics.json
summary.json
grade.tsv
costs.json
steps.csv
audit.json
review.json
LOG.md
MEASURE.md
classdiagram.uml
classdiagram.png
classdiagram.svg
collect.tsv
rating.json
MEASURE.md
The method's measure agent answered its Measure line from LOG.md and git. Agent-written text is shown verbatim and unchecked. Words such as recomputed inside it are the agent's own and are not tags of this page. Its Measure lines describe measurement during the run. Harness scores were measured separately after the run. Agent text may quote git commit times in the host's local zone. Harness times are UTC.
# Measure
Method: Held-out TDD. Sources: LOG.md, GAP.md and git log. ATTEMPTS.md does not exist.
The branch has no merge commits. Each unit commit (the "Tick the unit" commit) counts as one merge below.
## Visible and hidden pass rate per merge
Visible counts come from `./run.sh specs visible/<unit>` and hidden counts from `./run.sh hidden` as logged in GAP.md.
| merge | sha | unit | visible unit | visible all | hidden |
|---|---|---|---|---|---|
| 1 | 57ec7d0 | sowing | 8/8 | not logged | 0/0 |
| 2 | f2c0c37 | wrap | 6/8 | not logged | 0/0 |
| 3 | e45e5db | extraturn | 8/8 | not logged | 0/0 |
| 4 | 47b68d0 | capture | 8/8 | 40/56 | 0/0 |
| 5 | aabbd8c | emptyhouse | 8/8 | not logged | 0/0 |
| 6 | f457624 | quit | 8/8 | not logged | 0/0 |
| 7 | e70a6d1 | gameend | 8/8 | 56/56 | 0/0 |
At merge 4 visible/wrap reached 8/8. Its two failures at merge 2 were capture outcomes. The hidden pass rate is undefined at every merge because `./run.sh hidden` played 0 specs each time. The s3 split put 28 of 84 cases in the hidden set, so they existed but the runner never reached them.
## Gap per noun
Gap means visible pass rate minus hidden pass rate per requirement.
| noun | visible | hidden | gap |
|---|---|---|---|
| sowing | 8/8 | 0/0 | not measurable |
| wrap | 6/8 then 8/8 | 0/0 | not measurable |
| extraturn | 8/8 | 0/0 | not measurable |
| capture | 8/8 | 0/0 | not measurable |
| emptyhouse | 8/8 | 0/0 | not measurable |
| quit | 8/8 | 0/0 | not measurable |
| gameend | 8/8 | 0/0 | not measurable |
## Hidden cases replaced after disclosure
0. No hidden result was ever disclosed because the hidden run played 0 specs. No fresh visible test was written in response and no hidden case was replaced.
## Credits and time
Credits and time are measured by the harness.