P05 - Remediate a checkpoint finding
Choose the commands you use
Operating system
CodeArbiter host
Know before you begin
P05 is a guided, runnable Academy lesson in this preview. Its shared action cards are the public course route.
P05 is the first Practitioner exercise that asks you to preserve a precise remediation history. It uses the Workshop Queue practice project that Academy prepares in your learner clone; it does not ask you to experiment in your own production repository. Complete P04 first. If you need to learn how to make a GitHub fork, clone it locally, install Academy, or distinguish your terminal from your harness, use the prerequisite action below and return after F01.
Keep two places open: a native terminal at the learner clone for Academy and Git commands, and one CodeArbiter harness at the same clone for agent and CodeArbiter actions. A native-terminal command is entered directly and never starts with !. A shell command sent through a harness starts with exactly one !; this lesson does not ask you to type one. CodeArbiter commands and agent messages belong in the harness and never begin with !.
Confirm the safe practice space
You · Browser · All operating systems
P05 is a Practitioner lab. Complete P04 in your own fork and Academy clone first. If you have not yet forked, cloned, installed Academy, and practiced the terminal boundary, return to F01 before continuing. P05 changes only the prepared Workshop Queue exercise, never the Academy source clone.
A known fork and clone keep the remediation attempt separate from the course source and give Academy a repository it can reset safely.
Reviewed resources for Confirm the safe practice space
You have a clean Academy learner clone, an installed Academy CLI from F01, and a CodeArbiter harness pointed at that clone.
If you are unsure which repository is your fork or where Academy is installed, stop and repeat F01. Do not run P05 in an unfamiliar checkout.
This is a prerequisite check by you. Academy Check does not authenticate how you created the fork or clone.
What you will prove
The prepared exercise can persist a terminal blocked ticket through its normal model and store, but its JSON report wrongly excludes that ticket from the unresolved count. You will preserve four linear commits after Academy Prepare:
- the checkpoint's generated dated report and baseline together with an exact finding record;
- a test-only RED regression that exposes the defect;
- a code-only GREEN repair that leaves the regression unchanged; and
- a canonical receipt that names the first three real commit IDs.
The repair is deliberately small: unresolved means every ticket that is not completed. P05 Check can reconstruct the fixture, commits, path roles, regression, repair, receipt, and clean worktree. It cannot prove who reviewed a result, whether a checkpoint command was run, or the chronology of commands that led to the final commits.
Prepare safely
Prepare the numbered remediation attempt
From the clean main branch at your Academy learner clone root, run Prepare in a native terminal. This command is entered directly in the terminal, so it never begins with !.
Prepare creates the verifier-owned attempt branch and stages the real blocked-ticket summary defect before any learner work begins.
You · Native terminal · Windows
$academy = "$env:LOCALAPPDATA\ArbiterAcademy\preview-0.30\Scripts\arbiter-academy.exe"
& $academy --repository (Get-Location).Path prepare P05-checkpoint-remediation
You · Native terminal · macOS
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" prepare P05-checkpoint-remediation
You · Native terminal · Linux
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" prepare P05-checkpoint-remediation
Academy prints academy/P05-checkpoint-remediation/ATTEMPT_NUMBER and prepares a blocked ticket whose summary count is intentionally wrong.
Preserve the exact error. Resolve only the named clean-worktree or branch condition; do not force-reset main or delete an earlier attempt.
The printed attempt branch and prepared commit are the baseline that Check later reconstructs.
ATTEMPT_NUMBER is a value Academy prints, such as 1; it is not text to type literally. Stay on that numbered branch. The prepared commit also adds ADR-0005 and its decision-log entry. Do not edit those decision records, and do not repair the deliberately stale CONTEXT.md reference: that is the starting condition for P06.
Verify the prepared branch before changing anything
In the same native terminal, inspect the prepared branch, commit, and worktree. Compare the branch with the value Prepare printed. These are terminal commands, not harness commands, so do not add !.
The four required commits count only when they descend from the prepared attempt, not from a look-alike local branch.
You · Native terminal · Windows
git branch --show-current
git rev-parse HEAD
git status --short
You · Native terminal · macOS
git branch --show-current
git rev-parse HEAD
git status --short
You · Native terminal · Linux
git branch --show-current
git rev-parse HEAD
git status --short
The branch begins academy/P05-checkpoint-remediation/, HEAD is the prepared commit, and status prints no changed paths.
If any value differs, preserve the output and use Reset. Do not rename a branch, rewrite history, or manually copy prepared files.
You confirmed the attempt identity before creating the finding, RED, GREEN, and receipt commits.
Ask the agent to read the prepared boundary
In your active CodeArbiter harness, send the copied message. This is a request to the agent, not a shell command, so it never begins with !. The agent reads; it must not edit or commit in this step.
The learner and agent need the domain, persistence, reporting, decision, and scenario boundaries before deciding what the finding proves.
Your agent · Claude Code harness · All operating systems
Open .codearbiter/decisions/0005-terminal-blocked-ticket-lifecycle.md, .codearbiter/decisions/decision-log.md, training_scenarios/P05-checkpoint-remediation.json, tests/test_cli.py, workshop_queue/model.py, workshop_queue/service.py, and workshop_queue/cli.py. Show the prepared blocked-ticket behavior and the summary expression that omits it. Do not edit, stage, run a host command, or commit.
Your agent · Codex harness · All operating systems
Open .codearbiter/decisions/0005-terminal-blocked-ticket-lifecycle.md, .codearbiter/decisions/decision-log.md, training_scenarios/P05-checkpoint-remediation.json, tests/test_cli.py, workshop_queue/model.py, workshop_queue/service.py, and workshop_queue/cli.py. Show the prepared blocked-ticket behavior and the summary expression that omits it. Do not edit, stage, run a host command, or commit.
Your agent · Pi harness · All operating systems
Open .codearbiter/decisions/0005-terminal-blocked-ticket-lifecycle.md, .codearbiter/decisions/decision-log.md, training_scenarios/P05-checkpoint-remediation.json, tests/test_cli.py, workshop_queue/model.py, workshop_queue/service.py, and workshop_queue/cli.py. Show the prepared blocked-ticket behavior and the summary expression that omits it. Do not edit, stage, run a host command, or commit.
The agent can identify that blocked tickets persist through the normal model and store, while the report's unresolved total counts only open and claimed tickets.
If a required file is missing or the branch is not the prepared attempt, stop. Preserve the attempt and Reset instead of substituting a similar source file.
This read establishes the repository boundary for your own inspection; it is not a verifier-authenticated review.
Practice
Ask CodeArbiter to surface the checkpoint finding
In the selected harness, send the host-native checkpoint command. This is a CodeArbiter command, not a shell command, so it never begins with !.
The checkpoint lane frames the observed product defect before the repair lane begins.
Your agent · Claude Code harness · All operating systems
/ca:checkpoint
Your agent · Codex harness · All operating systems
$ca-checkpoint
Your agent · Pi harness · All operating systems
/ca-checkpoint
Your agent · Pi harness · All operating systems
/skill:ca-checkpoint
The agent reports that the blocked Workshop Queue ticket is omitted from the unresolved summary and names the report/test boundary.
If the checkpoint reports another problem or cannot run, preserve its output and correct the named prerequisite or use Reset. Do not invent a checkpoint transcript.
The finding commit below, not a chat transcript, is the repository artifact Check can inspect.
Inspect the real defect before recording it
You · Active CodeArbiter harness · All operating systems
Read the checkpoint result next to the prepared summary boundary. Confirm the claim is narrow: RQ-105 is blocked, its reason is venue-access clearance, and the unresolved count excludes it. Do not ask the agent to repair the code yet.
A precise finding prevents a generic report or unrelated product change from masquerading as remediation.
You can state the observed defect in one sentence and identify tests/test_cli.py plus workshop_queue/cli.py as the later test and code boundaries.
If the result is not the prepared blocked-ticket defect, stop and Reset. Do not broaden the exercise to make a different finding fit.
This is your inspection. Check does not authenticate a checkpoint run or a person's review.
Ask the agent to record only the finding
After the selected checkpoint command writes its generated checkpoint report and .codearbiter/last-checkpoint, send this message in the selected harness. It asks the agent to make the first of four commits, carrying those real generated artifacts with the finding, and forbids the test or production repair in that commit.
The verifier requires an exact, standalone finding commit before the RED regression and GREEN repair.
Your agent · Claude Code harness · All operating systems
Create .codearbiter/reports/academy/P05-finding.md with exactly these UTF-8 bytes, including the final newline:
# P05 Finding: blocked tickets omitted from unresolved summary
Ticket `RQ-105` is blocked: `Venue access is awaiting facilities clearance`.
Affected paths: `tests/test_cli.py`, `workshop_queue/cli.py`.
Then identify the one dated .codearbiter/checkpoints/YYYY-MM-DD.md generated by the just-run checkpoint and confirm .codearbiter/last-checkpoint exists. Stage exactly that generated report, .codearbiter/last-checkpoint, and .codearbiter/reports/academy/P05-finding.md; show the staged path list and diff, then invoke the CodeArbiter commit gate. Do not edit tests or production code, create the receipt, amend, or rebase.
Your agent · Codex harness · All operating systems
Create .codearbiter/reports/academy/P05-finding.md with exactly these UTF-8 bytes, including the final newline:
# P05 Finding: blocked tickets omitted from unresolved summary
Ticket `RQ-105` is blocked: `Venue access is awaiting facilities clearance`.
Affected paths: `tests/test_cli.py`, `workshop_queue/cli.py`.
Then identify the one dated .codearbiter/checkpoints/YYYY-MM-DD.md generated by the just-run checkpoint and confirm .codearbiter/last-checkpoint exists. Stage exactly that generated report, .codearbiter/last-checkpoint, and .codearbiter/reports/academy/P05-finding.md; show the staged path list and diff, then invoke the CodeArbiter commit gate. Do not edit tests or production code, create the receipt, amend, or rebase.
Your agent · Pi harness · All operating systems
Create .codearbiter/reports/academy/P05-finding.md with exactly these UTF-8 bytes, including the final newline:
# P05 Finding: blocked tickets omitted from unresolved summary
Ticket `RQ-105` is blocked: `Venue access is awaiting facilities clearance`.
Affected paths: `tests/test_cli.py`, `workshop_queue/cli.py`.
Then identify the one dated .codearbiter/checkpoints/YYYY-MM-DD.md generated by the just-run checkpoint and confirm .codearbiter/last-checkpoint exists. Stage exactly that generated report, .codearbiter/last-checkpoint, and .codearbiter/reports/academy/P05-finding.md; show the staged path list and diff, then invoke the CodeArbiter commit gate. Do not edit tests or production code, create the receipt, amend, or rebase.
One new descendant commit changes the generated dated checkpoint report, .codearbiter/last-checkpoint, and .codearbiter/reports/academy/P05-finding.md; it changes no test or production path.
If a generated checkpoint artifact is absent, another path is staged, or the finding content differs, stop before committing. Preserve the attempt and Reset rather than amending a malformed evidence history.
The first descendant commit preserves the real checkpoint side effects and proves the finding was recorded before the regression and repair.
Verify the finding commit boundary
Use a native terminal to inspect only the latest commit path list. These are direct terminal commands and never begin with !.
A clean three-artifact commit gives the later history an unambiguous checkpoint-and-finding boundary.
You · Native terminal · Windows
git log -1 --format=%H
git diff-tree --no-commit-id --name-only -r HEAD
You · Native terminal · macOS
git log -1 --format=%H
git diff-tree --no-commit-id --name-only -r HEAD
You · Native terminal · Linux
git log -1 --format=%H
git diff-tree --no-commit-id --name-only -r HEAD
The path list contains the generated dated checkpoint report, .codearbiter/last-checkpoint, and .codearbiter/reports/academy/P05-finding.md only.
If the commit omits either checkpoint artifact or contains another path, preserve the attempt and Reset. Do not rewrite the commit with amend or rebase.
The commit ID is later written into the final receipt as finding_commit.
Ask the agent to add the test-only RED regression
Send this message in the selected harness. The agent must change only the test, run it, and stop at the meaningful failing assertion before any production edit.
The lesson proves that the prepared report is wrong with a real persisted blocked ticket rather than a synthetic JSON assertion.
Your agent · Claude Code harness · All operating systems
Change only tests/test_cli.py. The verifier does not accept an equivalent test. Insert this exact method in WorkshopQueueCliTests:
def test_report_json_counts_blocked_ticket_as_unresolved(self) -> None:
tickets = json.loads(self.fixture.read_text(encoding="utf-8"))
tickets[0]["id"] = "RQ-105"
self.fixture.write_text(json.dumps(tickets), encoding="utf-8")
claim_result = self.run_cli("claim", "RQ-105", "--volunteer", "Sam")
block_result = self.run_cli("block", "RQ-105", "--reason", "Venue access is awaiting facilities clearance")
report = self.run_cli("report", "--format", "json")
self.assertEqual(claim_result.returncode, 0, claim_result.stderr)
self.assertEqual(block_result.returncode, 0, block_result.stderr)
self.assertEqual(report.returncode, 0, report.stderr)
parsed = json.loads(report.stdout)
self.assertEqual(parsed["blocked"], 1)
self.assertEqual(parsed["unresolved"], 1)
Run only the exact focused test with python -m unittest tests.test_cli.WorkshopQueueCliTests.test_report_json_counts_blocked_ticket_as_unresolved -v and stop when it fails because unresolved is 0 instead of 1. Do not edit workshop_queue, stage, or commit yet.
Your agent · Codex harness · All operating systems
Change only tests/test_cli.py. The verifier does not accept an equivalent test. Insert this exact method in WorkshopQueueCliTests:
def test_report_json_counts_blocked_ticket_as_unresolved(self) -> None:
tickets = json.loads(self.fixture.read_text(encoding="utf-8"))
tickets[0]["id"] = "RQ-105"
self.fixture.write_text(json.dumps(tickets), encoding="utf-8")
claim_result = self.run_cli("claim", "RQ-105", "--volunteer", "Sam")
block_result = self.run_cli("block", "RQ-105", "--reason", "Venue access is awaiting facilities clearance")
report = self.run_cli("report", "--format", "json")
self.assertEqual(claim_result.returncode, 0, claim_result.stderr)
self.assertEqual(block_result.returncode, 0, block_result.stderr)
self.assertEqual(report.returncode, 0, report.stderr)
parsed = json.loads(report.stdout)
self.assertEqual(parsed["blocked"], 1)
self.assertEqual(parsed["unresolved"], 1)
Run only the exact focused test with python -m unittest tests.test_cli.WorkshopQueueCliTests.test_report_json_counts_blocked_ticket_as_unresolved -v and stop when it fails because unresolved is 0 instead of 1. Do not edit workshop_queue, stage, or commit yet.
Your agent · Pi harness · All operating systems
Change only tests/test_cli.py. The verifier does not accept an equivalent test. Insert this exact method in WorkshopQueueCliTests:
def test_report_json_counts_blocked_ticket_as_unresolved(self) -> None:
tickets = json.loads(self.fixture.read_text(encoding="utf-8"))
tickets[0]["id"] = "RQ-105"
self.fixture.write_text(json.dumps(tickets), encoding="utf-8")
claim_result = self.run_cli("claim", "RQ-105", "--volunteer", "Sam")
block_result = self.run_cli("block", "RQ-105", "--reason", "Venue access is awaiting facilities clearance")
report = self.run_cli("report", "--format", "json")
self.assertEqual(claim_result.returncode, 0, claim_result.stderr)
self.assertEqual(block_result.returncode, 0, block_result.stderr)
self.assertEqual(report.returncode, 0, report.stderr)
parsed = json.loads(report.stdout)
self.assertEqual(parsed["blocked"], 1)
self.assertEqual(parsed["unresolved"], 1)
Run only the exact focused test with python -m unittest tests.test_cli.WorkshopQueueCliTests.test_report_json_counts_blocked_ticket_as_unresolved -v and stop when it fails because unresolved is 0 instead of 1. Do not edit workshop_queue, stage, or commit yet.
Only tests/test_cli.py changes, and the focused test fails because the report says unresolved is 0 when the persisted blocked ticket makes it 1.
If the test fails for an import, file, fixture, or command error, fix neither production nor unrelated setup. Preserve the output and Reset for a new attempt.
The later RED commit contains only the unchanged regression method whose taught AST final Check requires exactly.
Recognize the meaningful RED result
You · Active CodeArbiter harness · All operating systems
Read the focused test result. The important failure is the unresolved assertion after a successful claim, block, and report, not a syntax, import, fixture, or command failure.
A failing test demonstrates the product defect before the repair changes the report expression.
The focused test reaches the JSON report and shows that blocked is 1 while unresolved is still counted incorrectly.
If the test did not reach the unresolved assertion, do not continue to GREEN. Preserve the attempt and Reset instead of repairing a different problem.
You observe this runtime result during the lesson. Final Check validates the committed test and repair, not command chronology.
Ask the agent to commit only the RED test
Send this message in the selected harness after you have observed the meaningful RED result.
The test-only commit preserves the regression before the production repair can make it pass.
Your agent · Claude Code harness · All operating systems
Stage only tests/test_cli.py. Show the staged path list and diff, confirm the file contains the unchanged failing blocked-ticket regression, then invoke the CodeArbiter commit gate. Do not edit workshop_queue, create the receipt, amend, or rebase.
Your agent · Codex harness · All operating systems
Stage only tests/test_cli.py. Show the staged path list and diff, confirm the file contains the unchanged failing blocked-ticket regression, then invoke the CodeArbiter commit gate. Do not edit workshop_queue, create the receipt, amend, or rebase.
Your agent · Pi harness · All operating systems
Stage only tests/test_cli.py. Show the staged path list and diff, confirm the file contains the unchanged failing blocked-ticket regression, then invoke the CodeArbiter commit gate. Do not edit workshop_queue, create the receipt, amend, or rebase.
A second descendant commit changes exactly tests/test_cli.py and retains the meaningful failing regression.
If another file is staged or the test was changed after the observed RED result, preserve the attempt and Reset. Do not combine RED and GREEN into one commit.
The final verifier requires this commit immediately after the finding and before the code-only repair.
Ask the agent to make the code-only GREEN repair
Send this message in the selected harness. It permits the smallest report repair only after the committed RED test exists.
The bounded repair changes the definition of unresolved from open plus claimed to every ticket that is not completed.
Your agent · Claude Code harness · All operating systems
Change only workshop_queue/cli.py so the unresolved total is sum(ticket.status is not TicketStatus.COMPLETED for ticket in tickets). Do not change tests. Run the exact focused blocked-ticket test and stop after it passes. Do not stage or commit yet.
Your agent · Codex harness · All operating systems
Change only workshop_queue/cli.py so the unresolved total is sum(ticket.status is not TicketStatus.COMPLETED for ticket in tickets). Do not change tests. Run the exact focused blocked-ticket test and stop after it passes. Do not stage or commit yet.
Your agent · Pi harness · All operating systems
Change only workshop_queue/cli.py so the unresolved total is sum(ticket.status is not TicketStatus.COMPLETED for ticket in tickets). Do not change tests. Run the exact focused blocked-ticket test and stop after it passes. Do not stage or commit yet.
The focused regression now passes, tests/test_cli.py remains byte-for-byte unchanged from RED, and only workshop_queue/cli.py is modified.
If the focused test remains red or another production path changes, stop. Preserve the result and Reset rather than broadening the repair.
The later GREEN commit must be a one-path descendant whose inverse recreates the prepared defect.
Ask the agent to commit only the GREEN repair
Send this message in the selected harness after the focused test passes.
A code-only GREEN commit lets Check prove that the repair followed and did not modify the regression.
Your agent · Claude Code harness · All operating systems
Stage only workshop_queue/cli.py. Show the staged path list and diff, confirm tests/test_cli.py is unchanged from the RED commit, then invoke the CodeArbiter commit gate. Do not create the receipt, amend, or rebase.
Your agent · Codex harness · All operating systems
Stage only workshop_queue/cli.py. Show the staged path list and diff, confirm tests/test_cli.py is unchanged from the RED commit, then invoke the CodeArbiter commit gate. Do not create the receipt, amend, or rebase.
Your agent · Pi harness · All operating systems
Stage only workshop_queue/cli.py. Show the staged path list and diff, confirm tests/test_cli.py is unchanged from the RED commit, then invoke the CodeArbiter commit gate. Do not create the receipt, amend, or rebase.
A third descendant commit changes exactly workshop_queue/cli.py and the focused test remains green.
If the staged boundary includes the test or another path, stop and Reset. Do not make the history look right by amending or rebasing it.
The receipt records this exact commit as remediation_commit.
Generate the exact receipt bytes last
Run the complete command for your operating system in the native terminal only after the finding, RED, and GREEN commits exist. It reads the three real commit IDs from Git, writes deterministic verifier-owned bytes, stages only the receipt, and shows the staged diff. Do not hand-edit the JSON.
The fixed generator sorts keys, uses compact separators and ASCII escaping, and appends exactly one LF so the final receipt matches Check byte for byte.
You · Native terminal · Windows
@'
import json
import pathlib
import subprocess
def git(*arguments):
return subprocess.run(["git", *arguments], check=True, stdout=subprocess.PIPE, text=True).stdout
if git("status", "--porcelain", "--untracked-files=all"):
raise SystemExit("P05 receipt requires a clean worktree after GREEN")
reference_oid = git("rev-parse", "HEAD").strip()
commits = git("rev-list", "--reverse", "HEAD~3..HEAD").splitlines()
hex_digits = "0123456789abcdef"
if (
not reference_oid
or any(character not in hex_digits for character in reference_oid)
or len(commits) != 3
or any(
len(commit) != len(reference_oid)
or any(character not in hex_digits for character in commit)
for commit in commits
)
):
raise SystemExit("P05 receipt requires exactly three commit IDs after Prepare")
payload = {
"affected_paths": ["tests/test_cli.py", "workshop_queue/cli.py"],
"finding_commit": commits[0],
"finding_id": "ACADEMY-P05-BLOCKED-UNRESOLVED",
"red_commit": commits[1],
"remediation_commit": commits[2],
"schema_version": 2,
"status": "remediated",
}
receipt = pathlib.Path(".codearbiter/checkpoints/P05-academy.json")
receipt.parent.mkdir(parents=True, exist_ok=True)
receipt.write_bytes(json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode("utf-8") + b"\n")
subprocess.run(["git", "add", "--", receipt.as_posix()], check=True)
subprocess.run(["git", "diff", "--cached", "--", receipt.as_posix()], check=True)
'@ | python -
You · Native terminal · macOS
python3 - <<'PY'
import json
import pathlib
import subprocess
def git(*arguments):
return subprocess.run(["git", *arguments], check=True, stdout=subprocess.PIPE, text=True).stdout
if git("status", "--porcelain", "--untracked-files=all"):
raise SystemExit("P05 receipt requires a clean worktree after GREEN")
reference_oid = git("rev-parse", "HEAD").strip()
commits = git("rev-list", "--reverse", "HEAD~3..HEAD").splitlines()
hex_digits = "0123456789abcdef"
if (
not reference_oid
or any(character not in hex_digits for character in reference_oid)
or len(commits) != 3
or any(
len(commit) != len(reference_oid)
or any(character not in hex_digits for character in commit)
for commit in commits
)
):
raise SystemExit("P05 receipt requires exactly three commit IDs after Prepare")
payload = {
"affected_paths": ["tests/test_cli.py", "workshop_queue/cli.py"],
"finding_commit": commits[0],
"finding_id": "ACADEMY-P05-BLOCKED-UNRESOLVED",
"red_commit": commits[1],
"remediation_commit": commits[2],
"schema_version": 2,
"status": "remediated",
}
receipt = pathlib.Path(".codearbiter/checkpoints/P05-academy.json")
receipt.parent.mkdir(parents=True, exist_ok=True)
receipt.write_bytes(json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode("utf-8") + b"\n")
subprocess.run(["git", "add", "--", receipt.as_posix()], check=True)
subprocess.run(["git", "diff", "--cached", "--", receipt.as_posix()], check=True)
PY
You · Native terminal · Linux
python3 - <<'PY'
import json
import pathlib
import subprocess
def git(*arguments):
return subprocess.run(["git", *arguments], check=True, stdout=subprocess.PIPE, text=True).stdout
if git("status", "--porcelain", "--untracked-files=all"):
raise SystemExit("P05 receipt requires a clean worktree after GREEN")
reference_oid = git("rev-parse", "HEAD").strip()
commits = git("rev-list", "--reverse", "HEAD~3..HEAD").splitlines()
hex_digits = "0123456789abcdef"
if (
not reference_oid
or any(character not in hex_digits for character in reference_oid)
or len(commits) != 3
or any(
len(commit) != len(reference_oid)
or any(character not in hex_digits for character in commit)
for commit in commits
)
):
raise SystemExit("P05 receipt requires exactly three commit IDs after Prepare")
payload = {
"affected_paths": ["tests/test_cli.py", "workshop_queue/cli.py"],
"finding_commit": commits[0],
"finding_id": "ACADEMY-P05-BLOCKED-UNRESOLVED",
"red_commit": commits[1],
"remediation_commit": commits[2],
"schema_version": 2,
"status": "remediated",
}
receipt = pathlib.Path(".codearbiter/checkpoints/P05-academy.json")
receipt.parent.mkdir(parents=True, exist_ok=True)
receipt.write_bytes(json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode("utf-8") + b"\n")
subprocess.run(["git", "add", "--", receipt.as_posix()], check=True)
subprocess.run(["git", "diff", "--cached", "--", receipt.as_posix()], check=True)
PY
The command shows only .codearbiter/checkpoints/P05-academy.json staged; its compact sorted-key JSON names the real finding, RED, and GREEN commit IDs and ends in exactly one LF.
If generation stops, an ID is missing, a path is extra, or GREEN is not clean, do not hand-write JSON or rewrite history. Preserve the attempt and Reset.
Check accepts only a canonical receipt in the fourth and final descendant commit.
Ask the agent to commit the final receipt
Send this message in the selected harness after reviewing the staged receipt.
The receipt must be last so it can bind the already-committed finding, RED, and GREEN evidence.
Your agent · Claude Code harness · All operating systems
Confirm the staged path list is exactly .codearbiter/checkpoints/P05-academy.json, then invoke the CodeArbiter commit gate. Do not add files, amend, rebase, or push.
Your agent · Codex harness · All operating systems
Confirm the staged path list is exactly .codearbiter/checkpoints/P05-academy.json, then invoke the CodeArbiter commit gate. Do not add files, amend, rebase, or push.
Your agent · Pi harness · All operating systems
Confirm the staged path list is exactly .codearbiter/checkpoints/P05-academy.json, then invoke the CodeArbiter commit gate. Do not add files, amend, rebase, or push.
The fourth and final descendant commit changes exactly .codearbiter/checkpoints/P05-academy.json.
If the commit gate reports a boundary problem, preserve the attempt and use Reset. Never force a receipt into an earlier commit.
The committed receipt is the only P05 artifact Academy Check reads as the final evidence binding.
Do not add a fifth evidence commit. Do not amend, rebase, force-reset, or use copied terminal output as a substitute for the required repository evidence. The point is not a plausible story about a repair; it is a reviewable history that makes the defect, regression, repair, and final receipt separable.
Recognize success
The completed attempt has exactly four descendant commits after Prepare and no pending worktree changes. The first changes the generated dated .codearbiter/checkpoints/YYYY-MM-DD.md, .codearbiter/last-checkpoint, and .codearbiter/reports/academy/P05-finding.md; the second changes only tests/test_cli.py; the third changes only workshop_queue/cli.py; and the fourth changes only .codearbiter/checkpoints/P05-academy.json.
The finding says that blocked RQ-105 is omitted from the unresolved summary. The RED action gives the agent the verifier's exact taught method; an equivalent replacement is not accepted. That test persists the fixture, reaches the real report, and fails because unresolved is wrong, not because the setup broke. The GREEN repair changes the unresolved predicate to every ticket that is not completed. Run the native-terminal action to generate the receipt last; its deterministic generator writes sorted keys, compact separators, ASCII escaping, and exactly one LF. The receipt contains schema_version, finding_id, finding_commit, red_commit, remediation_commit, and status. affected_paths is exactly, in order, tests/test_cli.py then workshop_queue/cli.py. A copied host command is guidance, not evidence that either command was invoked.
Confirm the completed attempt is clean
Before Check, inspect the worktree in a native terminal. This is a direct terminal command and never begins with !.
P05 Check rejects uncommitted or unrelated state so the committed four-step history is the whole claim.
You · Native terminal · Windows
git status --short --untracked-files=all
You · Native terminal · macOS
git status --short --untracked-files=all
You · Native terminal · Linux
git status --short --untracked-files=all
Git prints no changed or untracked paths.
If status is not empty, do not delete evidence or add unrelated files to a P05 commit. Preserve the attempt and Reset.
A clean worktree is a direct Check precondition.
Check
Run the external Academy Check
Run Check from the Academy learner clone root in a native terminal. This command is entered directly and never begins with !.
Check independently reconstructs the prepared fixture, commit ancestry, exact path roles, regression, repair, receipt, and live worktree.
You · Native terminal · Windows
$academy = "$env:LOCALAPPDATA\ArbiterAcademy\preview-0.30\Scripts\arbiter-academy.exe"
& $academy --repository (Get-Location).Path check P05-checkpoint-remediation
You · Native terminal · macOS
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" check P05-checkpoint-remediation
You · Native terminal · Linux
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" check P05-checkpoint-remediation
Check prints checkpoint P05-checkpoint-remediation: passed and records progress in .academy/progress.json.
If Check fails, preserve the committed attempt and read the failed predicate. Start a new numbered attempt with Reset instead of rewriting committed evidence.
Check validates Git artifacts and the final worktree. It does not authenticate a checkpoint run or a human review, and it does not prove command chronology.
A pass contains checkpoint P05-checkpoint-remediation: passed and records progress in .academy/progress.json. Check independently verifies the prepared ADR, decision log, blocked ticket lifecycle, staged defect, exact four-commit topology, path roles, RED regression, GREEN repair, canonical receipt, and clean worktree. Check does not authenticate a checkpoint run or a human review, and it does not prove command chronology. Treat the commands and inspection steps as the practice you observe, not as claims that a final-state verifier can honestly make.
Recover or continue
If the branch identity, finding boundary, RED result, code-only GREEN boundary, receipt shape, or Check result is wrong, preserve the attempt. Read the named failure and create a fresh numbered attempt rather than trying to make past commits look correct. A preserved failed attempt is useful evidence; a rewritten one teaches the wrong habit.
Create a preserved numbered retry
Use Reset only when P05 needs another attempt. Run it at the Academy learner clone root in a native terminal; the command never begins with !.
Reset preserves the failed or incomplete attempt for inspection before creating the next numbered baseline.
You · Native terminal · Windows
$academy = "$env:LOCALAPPDATA\ArbiterAcademy\preview-0.30\Scripts\arbiter-academy.exe"
& $academy --repository (Get-Location).Path reset P05-checkpoint-remediation
You · Native terminal · macOS
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" reset P05-checkpoint-remediation
You · Native terminal · Linux
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" reset P05-checkpoint-remediation
Academy preserves the earlier attempt and prints the next academy/P05-checkpoint-remediation/ATTEMPT_NUMBER branch.
If Reset stops, preserve its message and resolve only the named repository condition. Never force-reset or delete a prior attempt.
A new attempt begins from the clean fixture while the previous history remains inspectable.
Hint 1
When a path boundary is unclear, read the latest commit's path list before doing more work. The finding contains the dated checkpoint report, .codearbiter/last-checkpoint, and .codearbiter/reports/academy/P05-finding.md; RED is one test path; GREEN is one production path; and the receipt is one checkpoint path.
Hint 2
The prepared defect is already in workshop_queue/cli.py. The RED test must create the blocked ticket through the existing CLI boundary and show that blocked is 1 while unresolved is wrong. Do not create a second fixture or a second production change to make that assertion easier.
Hint 3
The receipt is not a progress note. It is the last commit and its three IDs must be the real finding, RED, and GREEN descendants in that order. If you cannot name those four one-path commits, use Reset rather than trying to repair the history.
P06 is the next public guided Academy lesson. Leave the completed P05 branch intact: the later recovery case is separate work, not a repair to fold into this remediation attempt.
Understand the mechanism
Checkpoint remediation is a chain of independently inspectable facts. The prepared fixture creates a real domain state; the finding narrows the observed defect; a direct test records the caller expectation before code changes; the production change is isolated; and the receipt binds those commits into one checkable statement. This makes a later reviewer able to distinguish a real remediation from an invented report, a generic event, a broad patch, or a history assembled after the fact.