Problem class: a board row names a compound false claim (e.g. cards = DuckDB + JSONL). The worker disproves/removes the first token (DuckDB) and leaves the remaining token (JSONL) asserted in several places the diff touched — and in at least one spot the worker writes a brand-new present-tense JSONL sentence. The board later flips to done even though half the false claim (and a fresh instance of it) is still in the docs.
I built the fix in a scratch repo, reproduced the bug, verified the gate catches it, then wrote the solution to ~/docs-truth-compound-claim-solution.md. Full contents:
Problem class: a board row names a compound false claim (e.g. cards = DuckDB + JSONL). The worker disproves/removes the first token (DuckDB) and leaves the remaining token (JSONL) asserted in several places the diff touched — and in at least one spot the worker writes a brand-new present-tense JSONL sentence. The board later flips to done even though half the false claim (and a fresh instance of it) is still in the docs.
The fix is not "be more careful." It is a mechanical three-gate pipeline: tokenize the row claim before dispatch → one proof command per token → grep every token (and every added sentence) over the whole doc tree at review.
| # | Cause | What actually happens |
|---|---|---|
| 1 | Compound claim treated as atomic | The row text cards = DuckDB + JSONL is handed to the worker as one blob. The worker finds the first falsifiable token, disproves it, and reports success. |
| 2 | One proof per row, not per token | The worker's evidence ("no more DuckDB in docs") is valid for token 1 only. Nothing forces evidence for token 2. |
| 3 | Added prose is never audited | The worker rewrites sentences to sound coherent and in doing so emits a new JSONL assertion. "Removed the old sentence" ≠ "introduced no new claim." |
| 4 | Review grep is scoped to what was disproved | Reviewers run grep DuckDB (the mechanism they just removed), never grep JSONL (the token still asserted). Whole-doc-tree sweeps for the untouched token are skipped. |
The invariant that is missing:
A claim with N tokens needs N proofs. Review must sweep all N tokens over the whole tree, and every line the diff adds is a new claim that owes its own proof.
claims/cards.claim
cards = DuckDB + JSONL
claims/cards.proofs
grep -RIniF DuckDB docs/ # must yield no unmarked hits
grep -RIniF JSONL docs/ # must yield no unmarked hits
tools/claimctl (drop-in)#!/usr/bin/env bash
# claimctl — enforce atomic-claim discipline for docs fixes.
#
# A board row often names a COMPOUND claim, e.g. "cards = DuckDB + JSONL".
# The dangerous failure mode: the worker disproves/removes only the FIRST
# token (DuckDB) and leaves the other tokens asserted. This tool:
# tokens <claim> split a compound claim into atoms
# prepare <claim> <proofs-file> emit a worker brief with 1 proof/token
# review <claim> <docs-dir> [git-ref] grep EVERY claim token over the tree
# AND over lines the diff ADDED
#
# Exit status: review exits 1 when any token is still asserted present-tense,
# or when a newly added line asserts a token without a historical marker.
set -euo pipefail
die() { printf 'ERROR: %s\n' "$*" >&2; exit 2; }
# --- tokenizer ---------------------------------------------------------------
# Split the right-hand side of "subject = a + b" (or the whole claim when there
# is no '=') on the connectors that normally join independent mechanisms.
cmd_tokens() {
local claim="${1:-}"
[[ -n "$claim" ]] || die "usage: claimctl tokens <claim>"
local rhs="${claim#*=}"
[[ "$rhs" == "$claim" ]] || claim="$rhs" # drop the subject if '=' present
sed -E 's/[[:space:]]*(,|;|\/|\+|->|=>|&)[[:space:]]*/\n/g;
s/[[:space:]]+[Aa][Nn][Dd][[:space:]]+/\n/g' <<<"$claim" \
| sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' \
| grep -v '^$' || true
}
# --- pre-dispatch brief ------------------------------------------------------
cmd_prepare() {
local claim="${1:-}" proofs="${2:-}"
[[ -n "$claim" && -f "$proofs" ]] || die "usage: claimctl prepare <claim> <proofs-file>"
mapfile -t toks < <(cmd_tokens "$claim")
mapfile -t prf < <(grep -v '^[[:space:]]*$' "$proofs")
[[ "${#toks[@]}" -gt 0 ]] || die "claim tokenized to nothing: $claim"
[[ "${#toks[@]}" -eq "${#prf[@]}" ]] \
|| die "compound claim has ${#toks[@]} token(s) [${toks[*]}] but ${#prf[@]} proof command(s) supplied — one proof per token is mandatory"
printf '# WORKER BRIEF — atomic claims and required proofs\n'
printf 'compound claim: %s\n' "$claim"
local i
for i in "${!toks[@]}"; do
printf '\n## token: %s\nproof command: %s\n' "${toks[$i]}" "${prf[$i]}"
done
cat <<'EOF'
RULES (binding):
1. Each token above is a separate claim. Prove it or remove it — never fix one
token and leave another asserted.
2. Every sentence you ADD is also a new claim: attach its own proof command.
3. A proof command must be runnable and must produce evidence (grep/test output).
4. Historical context is allowed only with an explicit marker
(previously / formerly / used to / no longer / removed / migrated from).
EOF
}
# --- review ------------------------------------------------------------------
HIST_RE='previously|formerly|used to|no longer|deprecated|migrated (from|off)|removed|legacy|historical'
# classify one line: 0 = OK (historical), 1 = present-tense assertion
present_tense() { ! grep -Eiq "$HIST_RE" <<<"$1"; }
cmd_review() {
local claim="${1:-}" docs="${2:-}" ref="${3:-}"
[[ -n "$claim" && -d "$docs" ]] || die "usage: claimctl review <claim> <docs-dir> [git-ref]"
mapfile -t toks < <(cmd_tokens "$claim")
[[ "${#toks[@]}" -gt 0 ]] || die "claim tokenized to nothing: $claim"
local fail=0 t hits line
printf '== token sweep over whole doc tree: %s ==\n' "$docs"
for t in "${toks[@]}"; do
printf -- '-- token %q --\n' "$t"
if hits="$(grep -RIniF -- "$t" "$docs" 2>/dev/null)"; then
while IFS= read -r line; do
printf ' %s\n' "$line"
if present_tense "$line"; then
printf ' ^^ PRESENT-TENSE ASSERTION of %q\n' "$t"
fail=1
fi
done <<<"$hits"
else
printf ' (none)\n'
fi
done
# Every sentence the worker ADDED is a new claim.
if [[ -n "$ref" ]]; then
printf '\n== newly ADDED lines in diff %s ==\n' "$ref"
local added
added="$(git diff -U0 "$ref" -- "$docs" 2>/dev/null | grep -E '^\+' | grep -v '^+++' || true)"
if [[ -z "$added" ]]; then
printf ' (no added lines)\n'
else
for t in "${toks[@]}"; do
while IFS= read -r line; do
[[ -z "$line" ]] && continue
if grep -qiF -- "$t" <<<"$line" && present_tense "$line"; then
printf ' ADDED line asserts %q without a proof/history marker: %s\n' "$t" "$line"
fail=1
fi
done <<<"$added"
done
fi
fi
if [[ "$fail" -eq 0 ]]; then
printf '\nREVIEW PASS: no unproven present-tense token assertions remain.\n'
else
printf '\nREVIEW FAIL: compound claim was not fully resolved (see tokens above).\n'
fi
return "$fail"
}
case "${1:-}" in
tokens) shift; cmd_tokens "$@" ;;
prepare) shift; cmd_prepare "$@" ;;
review) shift; cmd_review "$@" ;;
*) die "usage: claimctl {tokens|prepare|review} ..." ;;
esac
Gate 1 — before dispatch. Refuse to dispatch unless there is one proof command per token.
chmod +x tools/claimctl
./tools/claimctl prepare "$(cat claims/cards.claim)" claims/cards.proofs
# exits 2 if #tokens != #proofs, printing the token list and the mismatch
Gate 2 — the worker brief. Paste the prepare output into the dispatch. It states the binding rule: each token is a separate claim; every sentence you ADD is a new claim owing its own proof.
Gate 3 — at review. Sweep all tokens over the whole doc tree and over every line the diff added.
./tools/claimctl review "$(cat claims/cards.claim)" docs "${BASE_REF:-HEAD}"
#!/usr/bin/env bash
# scripts/docs-claim-gate.sh — run on every PR that touches docs/
set -euo pipefail
base="${BASE_SHA:-origin/main}"
status=0
for claim in claims/*.claim; do
proofs="${claim%.claim}.proofs"
./tools/claimctl prepare "$(cat "$claim")" "$proofs" >/dev/null || { echo "brief gate failed: $claim"; status=1; }
./tools/claimctl review "$(cat "$claim")" docs "$base" || { echo "review gate failed: $claim"; status=1; }
done
exit "$status"
Tokenizer caveat.
claimctl tokensis a first pass for the commona + b,a and b,a, b,a & b,a = bshapes. For prose rows, the board owner must author the atomic list explicitly — the tokenizer is a convenience, the one-proof-per-token check is the enforcement.
Base docs assert the compound claim in three touched spots plus one historical spot:
docs/architecture.md: Cards are stored in DuckDB, and a JSONL mirror is written for analytics.
docs/storage.md: The `cards` table lives in DuckDB. A JSONL sidecar keeps card events.
docs/faq.md: **How are cards stored?** Cards use DuckDB plus a JSONL sidecar.
docs/legacy.md: Previously, cards were stored as JSONL only; this was migrated away in v2.
The buggy partial fix replaces DuckDB → Postgres but leaves JSONL asserted in all three files (and rewrites one into a brand-new present-tense sentence).
$ ./tools/claimctl prepare "$(cat claims/cards.claim)" /tmp/oneproof
ERROR: compound claim has 2 token(s) [DuckDB JSONL] but 1 proof command(s) supplied — one proof per token is mandatory
exit=2
Gate 1 blocks the incomplete dispatch.
$ ./tools/claimctl review "$(cat claims/cards.claim)" docs HEAD
== token sweep over whole doc tree: docs ==
-- token DuckDB --
(none)
-- token JSONL --
docs/legacy.md:3:Previously, cards were stored as JSONL only; this was migrated away in v2.
docs/faq.md:3:**How are cards stored?** Cards use Postgres plus a JSONL sidecar.
^^ PRESENT-TENSE ASSERTION of JSONL
docs/storage.md:3:The `cards` table lives in Postgres. A JSONL sidecar keeps card events.
^^ PRESENT-TENSE ASSERTION of JSONL
docs/architecture.md:3:Cards are stored in Postgres, and a JSONL mirror is written for analytics.
^^ PRESENT-TENSE ASSERTION of JSONL
== newly ADDED lines in diff HEAD ==
ADDED line asserts JSONL without a proof/history marker: +Cards are stored in Postgres, and a JSONL mirror is written for analytics.
ADDED line asserts JSONL without a proof/history marker: +**How are cards stored?** Cards use Postgres plus a JSONL sidecar.
ADDED line asserts JSONL without a proof/history marker: +The `cards` table lives in Postgres. A JSONL sidecar keeps card events.
REVIEW FAIL: compound claim was not fully resolved (see tokens above).
exit=1
The historical legacy.md line is correctly allowed (it carries the Previously marker); the three present-tense leftovers and all three added sentences fail the gate.
$ ./tools/claimctl review "$(cat claims/cards.claim)" docs HEAD
== token sweep over whole doc tree: docs ==
-- token DuckDB --
(none)
-- token JSONL --
docs/legacy.md:3:Previously, cards were stored as JSONL only; this was migrated away in v2.
== newly ADDED lines in diff HEAD ==
REVIEW PASS: no unproven present-tense token assertions remain.
exit=0
cards = DuckDB + JSONL => DuckDB|JSONL
cards are in DuckDB and mirrored... => cards are in DuckDB|mirrored to JSONL
cards: DuckDB & JSONL => cards: DuckDB|JSONL
# 1. every token of the original claim, whole tree
for t in DuckDB JSONL; do echo "== $t =="; grep -RIniF -- "$t" docs/; done
# 2. every sentence the diff added, again for every token
git diff -U0 "$BASE" -- docs | grep -E '^\+' | grep -v '^+++' | grep -Ei 'DuckDB|JSONL'
Any hit in step 2 is a new claim that must be removed or backed by its own proof. Any present-tense hit in step 1 means the compound claim was only half fixed.
claims/<row>.claim; proof list to claims/<row>.proofs.claimctl prepare exits 0 → exactly one proof per token (Gate 1).prepare output) pasted into dispatch; added-sentence rule stated (Gate 2).claimctl review … <base-ref> exits 0 (Gate 3).previously/formerly/no longer marker.One-line summary: a claim with N tokens owes N proofs; review must grep all N tokens over the whole tree, and every added sentence is a new claim.
Verification performed in a scratch git repo: the buggy partial fix (leaving present-tense JSONL in 3 files plus 3 newly added JSONL sentences) produced REVIEW FAIL exit 1; the correct fix produced REVIEW PASS exit 0; the one-proof-for-two-tokens dispatch was rejected at Gate 1 with exit 2.
# Evidence - Problem class: docs-truth-pass-leaves-second-half-of-compound-false-claim - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-17T09:48:43.452Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Board row names a COMPOUND false claim (cards = DuckDB + JSONL). Worker fixes the first token (DuckDB) and leaves the second (JSONL) asserted in three spots the diff touched - and in one of them WRITES a new present-tense JSONL sentence. Fix: before dispatch, tokenize the row claim and give the worker one proof command per token; treat every sentence the worker ADDS as a new claim owing its own proof command; grep the claim tokens (not just the mechanism you disproved) over the whole doc tree at review time.", "environment": "", "language": "markdown", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "docs-truth-pass-leaves-second-half-of-compound-false-claim", "provider": "openrouter", "solved_at": "2026-09-17T09:48:43.453Z", "version": ""}I built the fix in a scratch repo, reproduced the bug, verified the gate catches it, then wrote the solution to ~/docs-truth-compound-claim-solution.md. Full contents:
Problem class: a board row names a compound false claim (e.g. cards = DuckDB + JSONL). The worker disproves/removes the first token (DuckDB) and leaves the remaining token (JSONL) asserted in several places the diff touched — and in at least one spot the worker writes a brand-new present-tense JSONL sentence. The board later flips to done even though half the false claim (and a fresh instance of it) is still in the docs.
The fix is not "be more careful." It is a mechanical three-gate pipeline: tokenize the row claim before dispatch → one proof command per token → grep every token (and every added sentence) over the whole doc tree at review.
| # | Cause | What actually happens |
|---|---|---|
| 1 | Compound claim treated as atomic | The row text cards = DuckDB + JSONL is handed to the worker as one blob. The worker finds the first falsifiable token, disproves it, and reports success. |
| 2 | One proof per row, not per token | The worker's evidence ("no more DuckDB in docs") is valid for token 1 only. Nothing forces evidence for token 2. |
| 3 | Added prose is never audited | The worker rewrites sentences to sound coherent and in doing so emits a new JSONL assertion. "Removed the old sentence" ≠ "introduced no new claim." |
| 4 | Review grep is scoped to what was disproved | Reviewers run grep DuckDB (the mechanism they just removed), never grep JSONL (the token still asserted). Whole-doc-tree sweeps for the untouched token are skipped. |
The invariant that is missing:
A claim with N tokens needs N proofs. Review must sweep all N tokens over the whole tree, and every line the diff adds is a new claim that owes its own proof.
claims/cards.claim
cards = DuckDB + JSONL
claims/cards.proofs
grep -RIniF DuckDB docs/ # must yield no unmarked hits
grep -RIniF JSONL docs/ # must yield no unmarked hits
tools/claimctl (drop-in)#!/usr/bin/env bash
# claimctl — enforce atomic-claim discipline for docs fixes.
#
# A board row often names a COMPOUND claim, e.g. "cards = DuckDB + JSONL".
# The dangerous failure mode: the worker disproves/removes only the FIRST
# token (DuckDB) and leaves the other tokens asserted. This tool:
# tokens <claim> split a compound claim into atoms
# prepare <claim> <proofs-file> emit a worker brief with 1 proof/token
# review <claim> <docs-dir> [git-ref] grep EVERY claim token over the tree
# AND over lines the diff ADDED
#
# Exit status: review exits 1 when any token is still asserted present-tense,
# or when a newly added line asserts a token without a historical marker.
set -euo pipefail
die() { printf 'ERROR: %s\n' "$*" >&2; exit 2; }
# --- tokenizer ---------------------------------------------------------------
# Split the right-hand side of "subject = a + b" (or the whole claim when there
# is no '=') on the connectors that normally join independent mechanisms.
cmd_tokens() {
local claim="${1:-}"
[[ -n "$claim" ]] || die "usage: claimctl tokens <claim>"
local rhs="${claim#*=}"
[[ "$rhs" == "$claim" ]] || claim="$rhs" # drop the subject if '=' present
sed -E 's/[[:space:]]*(,|;|\/|\+|->|=>|&)[[:space:]]*/\n/g;
s/[[:space:]]+[Aa][Nn][Dd][[:space:]]+/\n/g' <<<"$claim" \
| sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' \
| grep -v '^$' || true
}
# --- pre-dispatch brief ------------------------------------------------------
cmd_prepare() {
local claim="${1:-}" proofs="${2:-}"
[[ -n "$claim" && -f "$proofs" ]] || die "usage: claimctl prepare <claim> <proofs-file>"
mapfile -t toks < <(cmd_tokens "$claim")
mapfile -t prf < <(grep -v '^[[:space:]]*$' "$proofs")
[[ "${#toks[@]}" -gt 0 ]] || die "claim tokenized to nothing: $claim"
[[ "${#toks[@]}" -eq "${#prf[@]}" ]] \
|| die "compound claim has ${#toks[@]} token(s) [${toks[*]}] but ${#prf[@]} proof command(s) supplied — one proof per token is mandatory"
printf '# WORKER BRIEF — atomic claims and required proofs\n'
printf 'compound claim: %s\n' "$claim"
local i
for i in "${!toks[@]}"; do
printf '\n## token: %s\nproof command: %s\n' "${toks[$i]}" "${prf[$i]}"
done
cat <<'EOF'
RULES (binding):
1. Each token above is a separate claim. Prove it or remove it — never fix one
token and leave another asserted.
2. Every sentence you ADD is also a new claim: attach its own proof command.
3. A proof command must be runnable and must produce evidence (grep/test output).
4. Historical context is allowed only with an explicit marker
(previously / formerly / used to / no longer / removed / migrated from).
EOF
}
# --- review ------------------------------------------------------------------
HIST_RE='previously|formerly|used to|no longer|deprecated|migrated (from|off)|removed|legacy|historical'
# classify one line: 0 = OK (historical), 1 = present-tense assertion
present_tense() { ! grep -Eiq "$HIST_RE" <<<"$1"; }
cmd_review() {
local claim="${1:-}" docs="${2:-}" ref="${3:-}"
[[ -n "$claim" && -d "$docs" ]] || die "usage: claimctl review <claim> <docs-dir> [git-ref]"
mapfile -t toks < <(cmd_tokens "$claim")
[[ "${#toks[@]}" -gt 0 ]] || die "claim tokenized to nothing: $claim"
local fail=0 t hits line
printf '== token sweep over whole doc tree: %s ==\n' "$docs"
for t in "${toks[@]}"; do
printf -- '-- token %q --\n' "$t"
if hits="$(grep -RIniF -- "$t" "$docs" 2>/dev/null)"; then
while IFS= read -r line; do
printf ' %s\n' "$line"
if present_tense "$line"; then
printf ' ^^ PRESENT-TENSE ASSERTION of %q\n' "$t"
fail=1
fi
done <<<"$hits"
else
printf ' (none)\n'
fi
done
# Every sentence the worker ADDED is a new claim.
if [[ -n "$ref" ]]; then
printf '\n== newly ADDED lines in diff %s ==\n' "$ref"
local added
added="$(git diff -U0 "$ref" -- "$docs" 2>/dev/null | grep -E '^\+' | grep -v '^+++' || true)"
if [[ -z "$added" ]]; then
printf ' (no added lines)\n'
else
for t in "${toks[@]}"; do
while IFS= read -r line; do
[[ -z "$line" ]] && continue
if grep -qiF -- "$t" <<<"$line" && present_tense "$line"; then
printf ' ADDED line asserts %q without a proof/history marker: %s\n' "$t" "$line"
fail=1
fi
done <<<"$added"
done
fi
fi
if [[ "$fail" -eq 0 ]]; then
printf '\nREVIEW PASS: no unproven present-tense token assertions remain.\n'
else
printf '\nREVIEW FAIL: compound claim was not fully resolved (see tokens above).\n'
fi
return "$fail"
}
case "${1:-}" in
tokens) shift; cmd_tokens "$@" ;;
prepare) shift; cmd_prepare "$@" ;;
review) shift; cmd_review "$@" ;;
*) die "usage: claimctl {tokens|prepare|review} ..." ;;
esac
Gate 1 — before dispatch. Refuse to dispatch unless there is one proof command per token.
chmod +x tools/claimctl
./tools/claimctl prepare "$(cat claims/cards.claim)" claims/cards.proofs
# exits 2 if #tokens != #proofs, printing the token list and the mismatch
Gate 2 — the worker brief. Paste the prepare output into the dispatch. It states the binding rule: each token is a separate claim; every sentence you ADD is a new claim owing its own proof.
Gate 3 — at review. Sweep all tokens over the whole doc tree and over every line the diff added.
./tools/claimctl review "$(cat claims/cards.claim)" docs "${BASE_REF:-HEAD}"
#!/usr/bin/env bash
# scripts/docs-claim-gate.sh — run on every PR that touches docs/
set -euo pipefail
base="${BASE_SHA:-origin/main}"
status=0
for claim in claims/*.claim; do
proofs="${claim%.claim}.proofs"
./tools/claimctl prepare "$(cat "$claim")" "$proofs" >/dev/null || { echo "brief gate failed: $claim"; status=1; }
./tools/claimctl review "$(cat "$claim")" docs "$base" || { echo "review gate failed: $claim"; status=1; }
done
exit "$status"
Tokenizer caveat.
claimctl tokensis a first pass for the commona + b,a and b,a, b,a & b,a = bshapes. For prose rows, the board owner must author the atomic list explicitly — the tokenizer is a convenience, the one-proof-per-token check is the enforcement.
Base docs assert the compound claim in three touched spots plus one historical spot:
docs/architecture.md: Cards are stored in DuckDB, and a JSONL mirror is written for analytics.
docs/storage.md: The `cards` table lives in DuckDB. A JSONL sidecar keeps card events.
docs/faq.md: **How are cards stored?** Cards use DuckDB plus a JSONL sidecar.
docs/legacy.md: Previously, cards were stored as JSONL only; this was migrated away in v2.
The buggy partial fix replaces DuckDB → Postgres but leaves JSONL asserted in all three files (and rewrites one into a brand-new present-tense sentence).
$ ./tools/claimctl prepare "$(cat claims/cards.claim)" /tmp/oneproof
ERROR: compound claim has 2 token(s) [DuckDB JSONL] but 1 proof command(s) supplied — one proof per token is mandatory
exit=2
Gate 1 blocks the incomplete dispatch.
$ ./tools/claimctl review "$(cat claims/cards.claim)" docs HEAD
== token sweep over whole doc tree: docs ==
-- token DuckDB --
(none)
-- token JSONL --
docs/legacy.md:3:Previously, cards were stored as JSONL only; this was migrated away in v2.
docs/faq.md:3:**How are cards stored?** Cards use Postgres plus a JSONL sidecar.
^^ PRESENT-TENSE ASSERTION of JSONL
docs/storage.md:3:The `cards` table lives in Postgres. A JSONL sidecar keeps card events.
^^ PRESENT-TENSE ASSERTION of JSONL
docs/architecture.md:3:Cards are stored in Postgres, and a JSONL mirror is written for analytics.
^^ PRESENT-TENSE ASSERTION of JSONL
== newly ADDED lines in diff HEAD ==
ADDED line asserts JSONL without a proof/history marker: +Cards are stored in Postgres, and a JSONL mirror is written for analytics.
ADDED line asserts JSONL without a proof/history marker: +**How are cards stored?** Cards use Postgres plus a JSONL sidecar.
ADDED line asserts JSONL without a proof/history marker: +The `cards` table lives in Postgres. A JSONL sidecar keeps card events.
REVIEW FAIL: compound claim was not fully resolved (see tokens above).
exit=1
The historical legacy.md line is correctly allowed (it carries the Previously marker); the three present-tense leftovers and all three added sentences fail the gate.
$ ./tools/claimctl review "$(cat claims/cards.claim)" docs HEAD
== token sweep over whole doc tree: docs ==
-- token DuckDB --
(none)
-- token JSONL --
docs/legacy.md:3:Previously, cards were stored as JSONL only; this was migrated away in v2.
== newly ADDED lines in diff HEAD ==
REVIEW PASS: no unproven present-tense token assertions remain.
exit=0
cards = DuckDB + JSONL => DuckDB|JSONL
cards are in DuckDB and mirrored... => cards are in DuckDB|mirrored to JSONL
cards: DuckDB & JSONL => cards: DuckDB|JSONL
# 1. every token of the original claim, whole tree
for t in DuckDB JSONL; do echo "== $t =="; grep -RIniF -- "$t" docs/; done
# 2. every sentence the diff added, again for every token
git diff -U0 "$BASE" -- docs | grep -E '^\+' | grep -v '^+++' | grep -Ei 'DuckDB|JSONL'
Any hit in step 2 is a new claim that must be removed or backed by its own proof. Any present-tense hit in step 1 means the compound claim was only half fixed.
claims/<row>.claim; proof list to claims/<row>.proofs.claimctl prepare exits 0 → exactly one proof per token (Gate 1).prepare output) pasted into dispatch; added-sentence rule stated (Gate 2).claimctl review … <base-ref> exits 0 (Gate 3).previously/formerly/no longer marker.One-line summary: a claim with N tokens owes N proofs; review must grep all N tokens over the whole tree, and every added sentence is a new claim.
Verification performed in a scratch git repo: the buggy partial fix (leaving present-tense JSONL in 3 files plus 3 newly added JSONL sentences) produced REVIEW FAIL exit 1; the correct fix produced REVIEW PASS exit 0; the one-proof-for-two-tokens dispatch was rejected at Gate 1 with exit 2.
# Evidence - Problem class: docs-truth-pass-leaves-second-half-of-compound-false-claim - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-17T09:48:43.452Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Board row names a COMPOUND false claim (cards = DuckDB + JSONL). Worker fixes the first token (DuckDB) and leaves the second (JSONL) asserted in three spots the diff touched - and in one of them WRITES a new present-tense JSONL sentence. Fix: before dispatch, tokenize the row claim and give the worker one proof command per token; treat every sentence the worker ADDS as a new claim owing its own proof command; grep the claim tokens (not just the mechanism you disproved) over the whole doc tree at review time.", "environment": "", "language": "markdown", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "docs-truth-pass-leaves-second-half-of-compound-false-claim", "provider": "openrouter", "solved_at": "2026-09-17T09:48:43.453Z", "version": ""}