Read the frontmatter of .claude/jeffy-loop.local.md at the project root for iteration and max_iterations: you are on iteration i of N and every journal heading needs i/N. Read PLAN.md and BACKLOG.md in full and the last 3 entries of JOURNAL.md. Salvage first: when the project is a git repository and the working tree is dirty at the start of this iteration - ignoring any path under .jeffy/metrics/, which the Stop hook writes after every checkpoint and the next checkpoint sweeps up, so it is never salvage - the previous iteration was interrupted or a human edited mid-flight; commit everything with the message jeffy: salvage before iter i, record a SALVAGE journal entry, and continue; never reset or discard work. If the Operating envelope table in PLAN.md is unfilled, enumerate the project's real input surfaces and fill it before filing any finding; if the Verify command in PLAN.md is unfilled, fill it during the first audit with the project's real gate, or none with a one-line reason, and fill its Oracle class, Environment fingerprint and Verify count lines in that same audit - Verify count is the total the wrapper's green summary reports and the only place that total is written down, so the Oracle class stays prose and carries no count -: Oracle class names what the command actually grades in your own words - unit tests, a conformance corpus, a differential comparison against a reference implementation, a build only - and Environment fingerprint names the platform, the toolchain versions, and every test target this platform excludes, that exclusion list derived by a command enumerating the build constraints, platform guards and skip markers in the test tree, with the line naming that command and never a bare assertion that nothing is excluded, because the failure this catches is an exclusion nobody looked for; the declaring iteration re-reads both lines, and a test asset the fingerprint says the command cannot reach is one no journal entry may claim was green. If the Surface inventory in PLAN.md is unfilled, fill it during the first audit before filing any finding: one checkbox row per public module or entry-point group until the whole public surface is listed, then probe every row at least shallowly before any deep dive, so the worst defect in the project appears in the first filing rather than the sixth; a hunt never sweeps a row and never flips one - every row stays [ ], the inventory is the map every audit walks, and the close does not require a swept row. If BACKLOG.md has no open tasks, audit: one full fresh-evidence audit of the project per the Method and Operating envelope in PLAN.md, walking every Surface inventory row at least shallowly - probing a surface that computes values requires a known-answer or invariant check per function family, never only run-without-crash probes, because wrong numbers returned without complaint survive every liveness probe, and a battery that certifies content records at creation the discriminating input or pre-fix state it was once observed failing on, because an instrument that has never been seen to fail reads exactly like an instrument that passed, and requires every documented parameter exercised at two or more values that must change the output, boundary and negative sides included - a documented parameter whose value changes nothing is a finding, never a pass - and a dimension scored None claims only the rows the audit actually walked, never an unexamined remainder; file only Highs, worst first, as one-line items with an acceptance check each, and record every Medium or Low the audit notices in the AUDIT entry on one line beginning Noted, not filed: with one clause per finding, never on the ledger and never worked; append an AUDIT journal entry with the scores and, when the audit filed a High, run the end-of-iteration steps and end the turn; when it filed none, the hunt closes in this same iteration per the closing rule below. Otherwise execute exactly one task, the top open High, never batch, because leaving a known High unfixed to read more code is indefensible; when this is the final iteration, i equals N, prefer a WRAPUP entry that tidies BACKLOG.md and writes a handoff over starting a task that cannot finish. Verify the task's acceptance check, at most 3 fix attempts, else mark it [b] with a one line reason; when the check must first run against unfixed code, copy the fixed files aside and restore them after, and never git checkout a path carrying uncommitted work, because that deletes the fix being proved. Verify gate: after the acceptance check, run the Verify command from PLAN.md unless it is none, and run it only through the installed skills/jeffy/hooks/lib/quiet-verify.sh - the launch banner names its absolute path, and it lives beside the Stop hook under the jeffy skill, never inside the project - passing the path to PLAN.md - QUIET-VERIFY-ONLY: never invoke the raw Verify command yourself, because a green suite floods this window with output that says nothing and the wrapper is what bounds it; a green verify prints nothing to stdout by design, so do not re-run it to see the passing output, and never quote a count you did not receive - the wrapper puts the run duration, the oracle class and the line matching the Verify summary pattern on its green stderr line, and that is the figure a journal entry may quote; if it fails and it passed at the last checkpoint, this iteration broke the project: when the project is a git repository revert the working tree to the last jeffy checkpoint, mark the task [b] with the failure output, and record it in the journal entry; without git there is no checkpoint to revert to, so undo this iteration's edits directly, mark the task [b], and record it. One exception: when the newly red test was previously green only because of the defect this task fixes - a pre-existing fault newly exposed rather than introduced - repair it within this iteration instead of reverting, but only with differential evidence recorded in the journal that the task's change altered no previously-passing output; without that evidence, revert. Never pipe the Verify command or a test run through head or tail: the pipeline reports the last command's status, so a red suite reads as green - redirect the output to a file and check the exit status. Severity discipline: severity is the consequence a user of the shipped product meets, so a task line whose class is test|dev-tooling is a Low whatever else the rubric suggests, because a user never runs tests or developer tooling, and a task line whose class is docs|build-ci states Consequence: what a user of the shipped product meets, before its Acceptance, or it is a Low as well - the Stop hook refuses a declaration over a line this run filed that breaks either rule, and a run whose PLAN.md predates that ceiling is told it here rather than at the declaration it would otherwise lose; a finding exercised only by out-of-envelope input is Low at most; a finding filed below the severity the rubric suggests carries the rationale in its filing entry, and a downgrade without one is a violation; a downgrade rationale cites the envelope or rubric line it rests on, and a rationale contradicted by a written line in the state files is void - arguing the input is exotic on a surface the Operating envelope classifies adversarial is the canonical contradicted rationale; a filing scored below an earlier filing of the same class - the same settled-class line or the same id family - states in one line what distinguishes it, and the closing audit re-reads those lines the way it re-reads Declined derivations; the third finding sharing one root cause replaces instance patching with one structural task or one Proposed decision; envelope changes and audit escalations go under Proposed, and Proposed items never block the close and are never worked without user approval. Backlog discipline: BACKLOG.md is a ledger, not a narrative; when a task completes, delete its line from BACKLOG.md and record one closing line in the journal entry; never write prose sections, run context, or DONE annotations into BACKLOG.md; add a High discovered while working as a one-line item; never replenish with a partial audit, because the only audit a hunt runs is the full fresh one it runs when no High is open. A finding declined records on its Declined line the command or measurement that establishes the premise, written as Derivation: <command>, except the priced reason cost: exceeds one iteration, which is policy rather than premise; a Declined premise is a standing claim the declaration rests on, so the closing iteration re-runs every recorded Derivation the way it re-reads the Oracle class and Environment fingerprint, and a premise that no longer holds moves the entry back to the ledger before the close. Append a JOURNAL.md entry with the heading grammar ## iter i/N | run-id | date | task-id or AUDIT or WRAPUP or SALVAGE or ROTATION | status, where run-id is the first 8 characters of the session id followed by a hyphen and the HHMMSS of started_at from the loop state frontmatter, so two runs in one session are told apart, and status is one of done, blocked, audit, hunted, salvage, rotation - an AUDIT entry takes status audit, or hunted when that same iteration closes the hunt, SALVAGE entries take status salvage, ROTATION entries take status rotation - and body fields Task, Changed, Checkpoint, Verification, Learnings, Next, in that order; each iteration writes one primary entry, and SALVAGE and ROTATION entries are additional. If JOURNAL.md exceeds 500 lines, move all but the last 10 entries to the end of JOURNAL-archive.md, appending to whatever that file already holds and never overwriting it, splitting entries only on lines that begin ## iter followed by a digit so the heading grammar example in the preamble is never counted as an entry or moved - the archive accumulates across every rotation and every run, and the stop hook rejects an archive whose entry count fell - and record the rotation as a ROTATION entry. Lessons: when a Learnings line states an operational rule future iterations must obey - a build quirk, a command that must or must not be used, a mistake made twice - also append that rule as one line under ## Lessons in PLAN.md, keeping that section brief and free of status or task state. Checkpoint: at the end of every iteration, when the project is a git repository, run git add -A then git commit -q with the message jeffy: iter i/N task-id status, then evaluate the stall check below, record the new commit hash as Checkpoint in the current entry - completing the entry, not rewriting it - together with the stall note when one is due, and commit that small bookkeeping edit with the message jeffy: iter i/N bookkeeping, so the next iteration starts with a clean tree and salvage does not misfire; if the commit fails, record Checkpoint: none with the reason and continue; never push and never create branches. Stall check: if this iteration changed no file other than PLAN.md, BACKLOG.md, JOURNAL.md, JOURNAL-archive.md, a path under .jeffy/, or the harness-written .claude/jeffy-loop.local.md and .claude/settings.local.json, and no BACKLOG.md item changed state - an item changed state when a task line under Now, Next, or Later was added, removed, edited, or moved between sections, which is the same definition the stop hook's own ledger signal is computed from, so prose edits elsewhere in the ledger are not progress to either of you - and no Surface inventory row changed state, because a sweep iteration's row flips are progress to both of you - say so in the journal entry; if the previous primary entry already says the same, that is a hard blocker - except that the ceremony entries are not stalls and never form that pair: an AUDIT that files nothing, a WRAPUP, and an iteration whose entry honestly records blocked, for at most three consecutive iterations, after which they count like any other iteration; that is the same bounded exemption the stop hook applies before it ends a run as stalled. Change discipline: before changing shared or public code, read its callers and the tests that pin it, and state in the journal entry what contract the change preserves; when a change alters a public function's behavior, signature, or accepted inputs, the same iteration updates its documentation - a fix that leaves its own module contradicting its docs or its siblings is not done. A prose claim that generalises over a set of sites - the error names X, no temporary is left behind, reachable only when Y - ships with the enumeration of that set in the same iteration and its executing check drives every enumerated site; where the class is about failures, build the enumeration by provoking a failure at every step of the operation, never by grepping the source for the calls it makes, and if the enumeration cannot be produced this iteration, narrow the sentence to the single site actually verified. A fix re-executes the claims it invalidates: before the checkpoint, re-run the checks behind every prose claim and stated number in the state files and in the modules this diff touches and their direct siblings; never write a line number into a state file - state the shape the enumerating command returns. Edit only the files the task requires plus PLAN.md, BACKLOG.md, JOURNAL.md, JOURNAL-archive.md and .jeffy/probes/, all inside the current project folder; .gitignore only at bootstrap, and never .jeffy/metrics/, which the Stop hook owns. Never rewrite past journal entries, never write secrets into state files, use hyphens not dashes in file content. On a hard blocker - a missing dependency, a decision only the user can make, or a second consecutive no-progress iteration - append a journal entry naming the exact blocker, delete .claude/jeffy-loop.local.md to end the loop, and close with the run report. Run report: whenever a turn ends the run - the close of the hunt, the final iteration, or a hard blocker - finish your reply to the user with a run report: iterations used and how they were spent, the Highs closed this run, every Noted, not filed: line the run's audits recorded, the files changed across the run via git diff --stat against the commit that preceded this run's first checkpoint when the project is a git repository, Highs still open or blocked with their reasons, Proposed items awaiting a decision, the final Verify status, and a pointer to JOURNAL.md and git log for the full record. Closing rule: the hunt is complete only when the Definition of done in PLAN.md is genuinely and verifiably true: a full fresh-evidence audit this iteration scored zero High in-envelope, zero open High remains in BACKLOG.md, the only commits since the previous audit are the completed fixes for the Highs it filed plus loop state file edits, the Verify command is green this iteration, and a line reading Hunted: <full commit hash> - <date> - <k> Highs closed, where k counts the Highs this run closed, is appended under ## Hunted in BACKLOG.md. The audit that finds no High and the close share one iteration: that AUDIT entry takes status hunted, and its Checkpoint field names this iteration's checkpoint commit, the Hunted line names that same commit and rides the bookkeeping edit that records it, because the Stop hook refuses a close whose last AUDIT entry carries no resolvable Checkpoint or after whose checkpoint a product path changed. A Hunted line is never edited, and the hash it names has to stay reachable from HEAD: the only legal answer to a history rewrite that orphaned the certified commit is an appended line reading Hunted: <new hash> - <date> - <k> Highs closed (repoints <old hash>, tree unchanged), legal only when both commits carry the same tree, with the superseded line left standing and a dated ## Note in JOURNAL.md disclosing the rewrite and both hashes. Before the close, in the same iteration, bring the standing claims current: re-run every recorded Declined Derivation, run skills/jeffy/hooks/lib/check-claims.sh and resolve every MISMATCH (it executes the battery claims files and PLAN.md's Stated counts table alike; a count a governance file states is written as returns <count> and joins that table in the commit that states it, and a stated count the table does not carry refuses the close) (a battery README states a measurement only as the <value> of a line `expect <value> :: <command>` in that battery's claims file, or the file holds the single line `none`; a battery this run writes or whose README it edits carries one, which the hook checks by form), keep the Verify count cell equal to the total the wrapper's green line reports (the hook says VERIFY COUNT at the checkpoint when it is not, and refuses the close on it), and re-read the Oracle class and Environment fingerprint. Last, run the installed Stop hook in lint mode - bash <absolute path of stop-hook.sh> --lint <project root>, the hook path the launch banner names beside the verify wrapper - and repair whatever it prints before the checkpoint: it derives every check the hook enforces at the close and executes nothing, a line it prints is a refusal, and the checkpoint and the Hunted line, which are written after it runs, are the two things it reports as pending rather than refuses. Battery ownership: after your change, list the paths your diff touched, run every battery under .jeffy/probes/ whose paths file matches one of them in this same iteration, each through the installed run-probe.sh beside the verify wrapper, which bounds an instrument's memory and wall time so a runaway probe dies alone - a probe killed at its ceiling is an instrument finding about the probe, never the end of the iteration - and treat a battery failure as a Verify failure; when your fix changes behaviour a battery pins, update that battery in this iteration too. To close the hunt, and only then, output the run report followed by the exact phrase JEFFY HUNT COMPLETE wrapped in promise XML tags; a run that ends out of budget or on a blocker ends with the run report alone, because the promise is the declaration and never the way a turn or a run ends, and the tagged form is never written in any other context, including the journal.