Skip to content

feat(revise): verifiable evidence: quote and spot checks, one verdict per line, who ran a review - #122

Merged
mmaclay merged 5 commits into
mainfrom
feat/88-verifiable-evidence
Nov 7, 2026
Merged

mmaclay merged 5 commits into
mainfrom
feat/88-verifiable-evidence

Conversation

@mmaclay

@mmaclay mmaclay commented Nov 7, 2026

Copy link
Copy Markdown
Member

Closes #88

Origin: #88, tracked in #89. In the reference revision, much of the report's evidence reached the group unchecked:

  • proposals carried an analyst's paraphrase instead of a person's words;
  • one probe line gave two verdicts and was counted as a break;
  • 42 findings named no one as having run the review;
  • the write-up had eight figures that nobody re-derived.

Sandbox: Sonnet, --check, against the sandbox's widgets repository with synthetic data.

  • revise-prepare-evidence: 7 of 7 runs pass across three commits, 2 of 2 on the final one. Each run flagged the planted wrong item (slice-1#3) and put the spot check: 5 items · 1 wrong · error rate 20% line in the Head. Each also had quote_check.py refuse the altered quote, recopied the comment's words, and reran the check to a pass.
  • source-reader-page-excerpt: 2 of 2 runs return verbatim Excerpt: lines and say the version is not in the file. The first batch was marked as failing because the scenario's regex was double-escaped; the saved outputs pass the corrected regex.

Canary: the next /lasp-dev:revise prepare.

  • Its report's Head should carry a spot check: line, and .review/revision/spot-check.md should hold ten lines.
  • quote_check.py should run before the commit question, and pass.
  • Any record harvested after the merge should have reviewer: on every finding.

The failures to look for:

  • a said: line whose words aren't in the comment it cites;
  • a Head figure that no script printed.

What changes

Every kind of evidence the revision report rests on is now checked by a script, or by a reader who didn't produce it:

#88 asks What this does
Quotes scripts/quote_check.py finds every said: line in the report, drafted entries included, in the own words of the comment it cites (or the pasted note), 1–40 words, never cutting a word. prepare step 10 runs it before offering the commit, and the report isn't offered until it passes.
Schemas block_tally.py refuses a probe line with a second verdict, such as breaks · … · judged as follows, and an analyst ask line with a second · outcome: or · diff:. The probe is rerun, never counted. The line forms stay as they are (see Decisions).
Who ran the review Record contract 14 → 15: every finding, cited question and uncited (by: review) finding carries reviewer: <login>, the account that posted it, which is the one the attribution line names.
Spot checks scripts/spot_check.py sample picks ten extracted items at random, the same ten for the same window. The driver reads each against its comment and writes .review/revision/spot-check.md. Then tally prints spot check: <n> items · <n> wrong · error rate <n>% for the Head.
Pages source-reader's page block adds one or two verbatim Excerpt: lines. The context refresh and onboard's first rules cite the page's ID, version and excerpt; a summary no excerpt bears out goes to Questions.
Numbers prepare step 10: every count and time in the report is one a script printed in this run, copied as printed. A rate is written with its counts, as <n> of <n> (<pct>%). A figure no script prints is left out. The one exception is the list of files a proposal would change. The Head's cost: line now comes from the new scripts/window_cost.py, which reads the harvest's thread dumps: the median and longest open-to-merge time, and how many pull requests merged without a build.

Files:

  • Scripts:
    • scripts/quote_check.py, new;
    • scripts/spot_check.py, new;
    • scripts/window_cost.py, new;
    • scripts/block_tally.py;
    • scripts/record.py.
  • Skills and agents:
    • skills/revise/prepare.md (steps 1, 2 and 10);
    • outline.md (the Head line; every quote is a said: line);
    • context-refresh.md;
    • SKILL.md;
    • skills/onboard/first-rules.md;
    • agents/source-reader.md;
    • agents/diff-probe.md.
  • Docs:
    • docs/contracts.md: the record v15, analysis blocks v2 and sweep blocks v3, plus three new sections: "The report's quotes", "The spot check" and "The window's cost";
    • docs/design.md;
    • the README's .review/ table.
  • Tests:
    • tests/test_quote_check.py, tests/test_spot_check.py and tests/test_window_cost.py, new;
    • test_block_tally.py, test_record.py and test_sandbox.py;
    • the fixture pr-0042/expected.yaml, regenerated (contract line and reviewer: lines only).
  • Sandbox: the scenarios revise-prepare-evidence and source-reader-page-excerpt, and the fixture sandbox/fixture/evidence/, with synthetic comments only.
  • Versions: revise 2.25.0 and onboard 0.6.7.

Not changed: the guidance items and guidance_check.py, which already checked quotes and schema; pr-review, whose attribution line already names who posted; ratchet_counts.py; capture.py.

Review

Three rounds, each by a fresh adversarial reviewer:

  • Round 1: 3 blocking findings, all fixed.
    • Step 10's figures rule contradicted the Head's cost figures. The fix is window_cost.py.
    • The comment lists of earlier windows were never given to the check. The fix adds the capture directories.
    • A nested - said: line was skipped instead of checked. Such a line is now refused.
  • Round 2: 3 blocking findings, all fixed.
    • window_cost.py refused a pull request that had no record. It now reads body.md.
    • A quote could go unchecked just because its pull request's list was not given. A quote is now unchecked only when the ledger's held candidates carry it, and matching is by repository and number.
    • Rates were not tied to the counts they came from. A rate is now written with its counts.
  • Round 3: no blocking findings. Its two should-fix findings and one nit were fixed: held quotes match by words and URL, however the ledger lays them out; a missing threads directory is refused; a labelled second verdict, breaks: or breaks —, is caught.

Checks on the final commit: the unit suite (1,255 tests), the four shell tests, check_static.py and codespell all pass.

Decisions for the maintainer

  • Record contract 14 → 15, approved before the change. reviewer is read from the finding's poster rather than parsed from the attribution line, because the two are the same account. Records of earlier versions have none, and nothing reads the field yet.
  • Line forms, not JSON, for the probe and analyst blocks, approved before the change. A fixed line form that a script parses already works as a schema. Refusing a second verdict closes the diff-probe: turn limit too low, and a verdict that contradicts itself #50 gap without adding a format.
  • Who spot-checks: the driver, not a new agent. The driver didn't extract the items, so it has no stake in them, and a new agent would cost a launch for ten reads. The seed is the window, so a rerun checks the same ten items.
  • A held candidate's quote can go unchecked. It is unchecked only when no comment list given holds its pull request and the ledger's held candidates carry the same words and URL. The count shows in the Head. Its words were checked in the window that held it.
  • Only said: lines are checked. The outline now says every quote in the report is a said: line, so a person's words given any other way count as paraphrase. Proposals that rest only on agree rates (Dial rewordings, expiries) carry no quote and aren't required to.

🤖 Generated with Claude Code. AI assistance level: 5/5 (not read by a person).

mmaclay and others added 5 commits November 6, 2026 23:47
… per line, who ran a review

Every said: quote in the report is found in the comment it cites by
scripts/quote_check.py before the report is offered; ten extracted items
are spot-checked against their comments, the error rate in the Head; a
probe or analyst line holding a second verdict fails its block; each
finding records the login that posted it (record contract 15); page
summaries carry a verbatim excerpt; every figure is a script's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, own-verdict reasons, page excerpts for new entries

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…quotes, prose verdict words, rates with their counts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reads refused, labelled second verdicts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mmaclay
mmaclay marked this pull request as ready for review November 7, 2026 16:45
@mmaclay
mmaclay merged commit da350f4 into main Nov 7, 2026
1 check passed
@mmaclay
mmaclay deleted the feat/88-verifiable-evidence branch November 7, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

revise: verifiable evidence

1 participant