Problem class: dogfood-stale-premise-filing
Solution written to /workspace/SOLUTION.md and proven against a synthetic repo that reproduces the DF-WARPFS-20/21 shape. Full document below.
Problem class: dogfood-stale-premise-filing
Environment: coding-hermes foreman ticks / dogfood-satellite filings
Triggering incident: DF-WARPFS-20, DF-WARPFS-21 (filed 2026-09-22 against hilo 0.3.x)
Proven in production by: <project> tick 216 (judges 0be76226, 7f1a3e88)
A dogfood row is a time-bound claim about a moving master, not a durable fact. A row filed from a pinned tag/binary can be false by the time a foreman picks it — and in DF-WARPFS-20/21 it was already false at filing time (fixes c62f0b6 et al. had landed 2–3 days earlier; the filing run tested a stale binary/tag).
Do not dispatch a worker to fix a ghost. At pick time the foreman must:
git merge-base --is-ancestor, git tag --contains);premise-reverify.sh (below) gates this in one command, with a machine-readable verdict.
Every dogfood filing carries an implicit claim:
"On the current tip of the branch we are supposed to work from, defect D is live."
The filer evaluates D against a snapshot (a released tag, a prebuilt binary, a CI artifact). The foreman works against the tip of a branch that keeps moving. Filing and pickup are separated by an unbounded gap. Therefore:
premise(row) = (D reproduces at the ref the worker will actually use)
is a derived, decaying property. Nothing in the lane re-derived it at pickup, so the row's stored evidence silently became fiction.
DF-WARPFS-20/21 went stale| Fact | Consequence |
|---|---|
| Row was filed against hilo 0.3.x (tag/binary) | The claim was scoped to an old revision |
Fixes c62f0b6 et al. landed 2–3 days before filing |
At filing time the bug was already fixed on master |
| The filing run tested a stale binary/tag | It reproduced a defect that no longer existed upstream |
| Foreman dispatch is evidence-blind | It would have spawned a worker to fix a ghost |
This is not a regression or a one-off: any filing against a pinned artifact inherits it. The class-level bug is the missing revalidation gate, not the individual bad row.
The rows did not force the filer to record the exact revision under test. Without an immutable anchor (sha, tag, artifact hash, exact command, timestamp) a picker cannot tell "this is live" from "this was live three days ago", so the only safe-looking action is to dispatch — which is exactly the wrong one.
Two changes, both required:
A. Process: make the premise re-derived at pick time, and make ghost-closing a first-class outcome. The gate returns one of three verdicts, and dispatch is the only verdict that creates a worker.
B. Tooling: a single verifier script the foreman runs before claiming a row. It produces a provenance-stamped evidence block suitable for a judge.
Before a row is claimed/dispatched:
ref, sha, repro_cmd, and either build_cmd or artifact_hash. (Filing-side gate.)premise-reverify.sh against the row's REPO/REF and the claimed CLAIM_FIX_SHA / CLAIM_TAG (when the row makes a tag-ancestry claim).0 (PREMISE=LIVE) → dispatch worker, attach the evidence block.10 (PREMISE=DEAD) → close verification-only, attach evidence, no worker.2 (blocked / build failed / ambiguous) → route to triage, do not dispatch.sha + repro_rc back onto the row (idempotent; re-picking a row re-runs the gate because the tip may have moved again).premise-reverify.shSelf-contained, no third-party deps beyond git. Save as tools/foreman/premise-reverify.sh.
#!/usr/bin/env bash
# premise-reverify.sh -- foreman pick-time re-verification of a dogfood filing.
#
# Exit codes: 0 = premise LIVE (dispatch worker)
# 10 = premise DEAD (close verification-only)
# 2 = blocked / cannot verify (do NOT dispatch)
#
# Usage:
# REPO=/path/to/hilo \ # or REPO_URL=git@...:hilo.git
# REF=origin/main \ # ref to verify against (default origin/HEAD)
# CLAIM_FIX_SHA=1dbde49 \ # optional: fix the row says is absent
# CLAIM_TAG=v0.3.0 \ # optional: tag the row was filed against
# BUILD_CMD='cargo build --release' \
# REPRO_CMD='target/release/hilo <project> selfcheck' \
# ./premise-reverify.sh
set -u -o pipefail
REPO="${REPO:-}"
REPO_URL="${REPO_URL:-}"
REF="${REF:-origin/HEAD}"
CLAIM_FIX_SHA="${CLAIM_FIX_SHA:-}"
CLAIM_TAG="${CLAIM_TAG:-}"
BUILD_CMD="${BUILD_CMD:-}"
REPRO_CMD="${REPRO_CMD:-}"
SCRATCH_ROOT="${SCRATCH_ROOT:-${TMPDIR:-/tmp}}"
KEEP_SCRATCH="${KEEP_SCRATCH:-0}"
log() { printf '[reverify] %s\n' "$*" >&2; }
die() { printf '[reverify] FATAL: %s\n' "$*" >&2; exit 2; }
command -v git >/dev/null || die "git not found"
[ -n "$REPRO_CMD" ] || die "REPRO_CMD is required (the exact command that demonstrates the defect)"
[ -n "$REPO" ] || [ -n "$REPO_URL" ] || die "set REPO (local) or REPO_URL (clone)"
WORK="$(mktemp -d "$SCRATCH_ROOT/reverify.XXXXXX")"
cleanup() { [ "$KEEP_SCRATCH" = 1 ] || rm -rf "$WORK"; }
trap cleanup EXIT
# 1. Fresh scratch workspace -- never reuse the filer's build tree.
if [ -n "$REPO" ]; then
git clone -q --no-local "$REPO" "$WORK/repo" || die "clone of $REPO failed"
else
git clone -q "$REPO_URL" "$WORK/repo" || die "clone of $REPO_URL failed"
fi
cd "$WORK/repo" || die "scratch cd failed"
git fetch -q --all --tags --prune 2>/dev/null || true
# 2. Resolve the ref under test to an immutable SHA (provenance anchor), and pin
# the scratch tree to it. A rebuild is only meaningful from that revision,
# never from whatever the clone defaulted to.
HEAD_SHA="$(git rev-parse --verify "${REF}^{commit}" 2>/dev/null)" || die "cannot resolve REF=$REF"
HEAD_SHORT="$(git rev-parse --short "$HEAD_SHA")"
git checkout -q --detach "$HEAD_SHA" || die "checkout of $HEAD_SHORT failed"
log "verifying against $REF = $HEAD_SHORT (detached)"
ANCESTRY="n/a"
TAGS_CONTAINING=""
if [ -n "$CLAIM_FIX_SHA" ]; then
if git cat-file -e "${CLAIM_FIX_SHA}^{commit}" 2>/dev/null; then
if [ -n "$CLAIM_TAG" ]; then
if git rev-parse --verify -q "refs/tags/${CLAIM_TAG}" >/dev/null; then
if git merge-base --is-ancestor "$CLAIM_FIX_SHA" "$CLAIM_TAG" 2>/dev/null; then
ANCESTRY="fix ${CLAIM_FIX_SHA} IS an ancestor of ${CLAIM_TAG}"
else
ANCESTRY="fix ${CLAIM_FIX_SHA} is NOT an ancestor of ${CLAIM_TAG}"
fi
else
ANCESTRY="claimed tag ${CLAIM_TAG} not found"
fi
fi
TAGS_CONTAINING="$(git tag --contains "$CLAIM_FIX_SHA" 2>/dev/null | paste -sd, -)"
if git merge-base --is-ancestor "$CLAIM_FIX_SHA" "$HEAD_SHA" 2>/dev/null; then
FIX_IN_HEAD="yes"
else
FIX_IN_HEAD="no"
fi
else
ANCESTRY="claimed fix ${CLAIM_FIX_SHA} not found in repo"
FIX_IN_HEAD="unknown"
fi
else
FIX_IN_HEAD="not-applicable"
fi
# 3. Rebuild from the resolved ref, never from a stale artifact.
BUILD_STATUS="skipped"
if [ -n "$BUILD_CMD" ]; then
log "rebuilding from $HEAD_SHORT: $BUILD_CMD"
if ( eval "$BUILD_CMD" ) >"$WORK/build.log" 2>&1; then
BUILD_STATUS="ok"
else
BUILD_STATUS="failed"
log "PHASE:BUILD: premised-unverifiable (build failed) -- do NOT dispatch"
printf 'VERDICT=blocked reason=build-failed ref=%s sha=%s build_log=%s\n' "$REF" "$HEAD_SHORT" "$WORK/build.log"
exit 2
fi
fi
# 4. Re-run the exact repro.
log "rerunning repro: $REPRO_CMD"
set +e
( eval "$REPRO_CMD" ) >"$WORK/repro.log" 2>&1
REPRO_RC=$?
set -e
printf '=== PREMISE RE-VERIFICATION EVIDENCE ===\n'
printf 'ref=%s\nsha=%s\nclaimed_fix=%s\nclaimed_tag=%s\nancestry=%s\nfix_in_verified_ref=%s\ntags_containing_fix=%s\nbuild=%s\nrepro_cmd=%s\nrepro_rc=%s\nscratch=%s\n' \
"$REF" "$HEAD_SHORT" "${CLAIM_FIX_SHA:-none}" "${CLAIM_TAG:-none}" "$ANCESTRY" "$FIX_IN_HEAD" "${TAGS_CONTAINING:-none}" "$BUILD_STATUS" "$REPRO_CMD" "$REPRO_RC" "$WORK/repo"
if [ "$REPRO_RC" -ne 0 ]; then
printf 'PREMISE=LIVE defect still reproduces at %s (%s)\n' "$REF" "$HEAD_SHORT"
printf 'ACTION=dispatch\n'
exit 0
fi
# Repro passed. Only a clean build + clean repro is enough to close.
if [ "$FIX_IN_HEAD" = "yes" ] || [ "$FIX_IN_HEAD" = "not-applicable" ]; then
printf 'PREMISE=DEAD repro passes at %s (%s); nothing to fix\n' "$REF" "$HEAD_SHORT"
printf 'ACTION=close-verification-only\n'
printf 'NOTE=append the evidence above to the row and close without a worker\n'
exit 10
fi
printf 'VERDICT=blocked reason=ambiguous repro passed but claimed fix not in ref\n'
exit 2
# claim-time gate, invoked by the tick runner before materializing a worker
set +e
out="$(REPO="$repo" REF="origin/$branch" \
CLAIM_FIX_SHA="$row_fix_sha" CLAIM_TAG="$row_tag" \
BUILD_CMD="$row_build_cmd" REPRO_CMD="$row_repro_cmd" \
tools/foreman/premise-reverify.sh)"
rc=$?
set -e
printf '%s\n' "$out" >> "$foreman_evidence_log"
case "$rc" in
0) dispatch_worker --row "$row" --evidence "$out" ;;
10) close_row_verification_only --row "$row" --evidence "$out" ;; # ghost, no worker
2) triage_row --row "$row" --evidence "$out" ;; # do not dispatch
*) triage_row --row "$row" --reason "verifier-crash rc=$rc" ;;
esac
When the row specifically claims "fix X is missing / defect present in tag T", these are the exact commands and their meaning:
git fetch --all --tags --prune
# Is the claimed fix already inside the tag the row was filed against?
git merge-base --is-ancestor <fix_sha> <tag> \
&& echo "STALE: tag already contains the fix" \
|| echo "fix genuinely absent from that tag"
# Which tags contain the fix at all?
git tag --contains <fix_sha>
# Human-readable nearest release containing the fix
git describe --contains <fix_sha>
# Is the fix in the ref we would actually work from?
git merge-base --is-ancestor <fix_sha> <ref> \
&& echo "fix is in the working ref -> verify, then close if repro passes"
The fix was proven on a synthetic repo that reproduces the DF-WARPFS-20/21 shape exactly: a buggy v0.3.0, a fix commit landing later on master, and a v0.3.1 release. Filing against the stale v0.3.0 shows PREMISE=LIVE; picking against master shows PREMISE=DEAD and closes with no worker.
set -euo pipefail
ROOT=/tmp/premise-demo; rm -rf "$ROOT"; mkdir -p "$ROOT"
# --- fixture: hilo with a stale tag and a later fix on master ---
git init -q "$ROOT/origin.git" --bare
git clone -q "$ROOT/origin.git" "$ROOT/work"; cd "$ROOT/work"
git config user.email <email>; git config user.name dogfood
cat > tool.sh <<'EOF'
#!/usr/bin/env bash
if grep -q 'WARPFS_BUG' <<<"${MODE:-WARPFS_BUG}"; then
echo "defect: <project> path check failed"; exit 1
fi
echo "ok"
EOF
chmod +x tool.sh; echo "release v0.3.0 (buggy)" > VERSION
git add -A && git commit -qm "release 0.3.0"; git tag -a v0.3.0 -m "hilo 0.3.0"
git checkout -q -b fix # fix lands 2-3 days later
printf '#!/usr/bin/env bash\necho "ok"\n' > tool.sh; chmod +x tool.sh
git add -A && git commit -qm "<project>: fix path check"
git checkout -q master && git merge -q --no-ff fix -m "merge <project> fix"
git branch -q -D fix; git tag -a v0.3.1 -m "hilo 0.3.1"
git push -q origin master --tags
FIX=$(git rev-list --all --grep='fix path check' -n1 | cut -c1-7)
# --- copy in premise-reverify.sh, then run both pick-time cases ---
cp /path/to/premise-reverify.sh "$ROOT/"
cd "$ROOT"
echo "### CASE A: re-verify at moving master (must be DEAD) ###"
REPO="$ROOT/origin.git" REF=origin/master CLAIM_FIX_SHA="$FIX" CLAIM_TAG=v0.3.0 \
BUILD_CMD='true' REPRO_CMD='./tool.sh' ./premise-reverify.sh; echo "exit=$?"
echo "### CASE B: old filer behavior at pinned stale v0.3.0 (must be LIVE) ###"
REPO="$ROOT/origin.git" REF=v0.3.0 \
BUILD_CMD='true' REPRO_CMD='./tool.sh' ./premise-reverify.sh; echo "exit=$?"
Case A — pick time, moving master:
[reverify] verifying against origin/master = 1a88593 (detached)
[reverify] rebuilding from 1a88593: true
[reverify] rerunning repro: ./tool.sh
=== PREMISE RE-VERIFICATION EVIDENCE ===
ref=origin/master
sha=1a88593
claimed_fix=0cc56fc
claimed_tag=v0.3.0
ancestry=fix 0cc56fc is NOT an ancestor of v0.3.0
fix_in_verified_ref=yes
tags_containing_fix=v0.3.1
build=ok
repro_cmd=./tool.sh
repro_rc=0
PREMISE=DEAD repro passes at origin/master (1a88593); nothing to fix
ACTION=close-verification-only
NOTE=append the evidence above to the row and close without a worker
exit=10
Case B — the stale filer's world, pinned v0.3.0:
[reverify] verifying against v0.3.0 = f426fb2 (detached)
[reverify] rebuilding from f426fb2: true
[reverify] rerunning repro: ./tool.sh
=== PREMISE RE-VERIFICATION EVIDENCE ===
ref=v0.3.0
sha=f426fb2
...
build=ok
repro_cmd=./tool.sh
repro_rc=1
PREMISE=LIVE defect still reproduces at v0.3.0 (f426fb2)
ACTION=dispatch
exit=0
The two runs differ only in the ref under test. This isolates the exact failure mode: the same repro is TRUE at the stale tag and FALSE at the tip — so treating the stored evidence as durable is what creates the ghost worker.
A pick-time re-verification is accepted only if all hold:
sha of the ref under test.git merge-base --is-ancestor <fix> <tag> and git tag --contains <fix> outputs are recorded.sha (or BUILD_CMD was explicitly empty for interpreted/repro-only rows).repro_cmd from the row is re-run and its repro_rc recorded.rc (0/10/2), not from prose interpretation.PREMISE=DEAD closes the row verification-only with the evidence block and spawns no worker.PREMISE=LIVE dispatch reuses the same evidence block, so the worker starts from a verified premise.rc=2 (build failed / claimed fix not in ref) routes to triage and never dispatches.row: DF-WARPFS-20
ref: origin/master
sha: 1a88593
claimed: fix 0cc56fc absent from tag v0.3.0
ancestry: fix 0cc56fc IS NOT an ancestor of v0.3.0
containing: v0.3.1
build: ok
repro_cmd: ./tool.sh
repro_rc: 0
verdict: PREMISE=DEAD -> close verification-only
judges: <tick id>, <judge ids>
ref, sha, repro_cmd, and build_cmd/artifact_hash mandatory fields. A row without them is rejected before it reaches the lane.premise-reverify.sh into the tick runner as a hard gate ahead of dispatch_worker; log the evidence block for every claim (including dispatches).LIVE row may become DEAD; that is the feature, not a bug.verification_only_closes / total_picks. A healthy lane should show a nonzero rate; a rate of exactly zero means the gate is not running.2 and triage. Closing on an unexplained passing repro is how you get the inverse ghost — a real bug closed by a harness artifact.# Evidence - Problem class: dogfood-stale-premise-filing - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-23T03:43:09.610Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Dogfood/dogfood-lane rows filed against a moving master go stale before a foreman picks them: DF-WARPFS-20/21 (filed 2026-09-22 against hilo 0.3.x) claimed live defects whose fixes landed 2-3 days earlier (c62f0b6 et al); the filing run tested a stale binary/tag. Class answer: at pick time re-verify premise live (repro in scratch workspace + git merge-base --is-ancestor for tag-ancestry claims + rebuild-from-HEAD binary), close verification-only with judge-verified evidence instead of dispatching a worker to fix a ghost. Proven <project> tick 216 (judges 0be76226/7f1a3e88).", "environment": "coding-hermes foreman ticks, dogfood-satellite filings", "language": "process", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "dogfood-stale-premise-filing", "provider": "openrouter", "solved_at": "2026-09-23T03:43:09.610Z", "version": ""}Solution written to /workspace/SOLUTION.md and proven against a synthetic repo that reproduces the DF-WARPFS-20/21 shape. Full document below.
Problem class: dogfood-stale-premise-filing
Environment: coding-hermes foreman ticks / dogfood-satellite filings
Triggering incident: DF-WARPFS-20, DF-WARPFS-21 (filed 2026-09-22 against hilo 0.3.x)
Proven in production by: <project> tick 216 (judges 0be76226, 7f1a3e88)
A dogfood row is a time-bound claim about a moving master, not a durable fact. A row filed from a pinned tag/binary can be false by the time a foreman picks it — and in DF-WARPFS-20/21 it was already false at filing time (fixes c62f0b6 et al. had landed 2–3 days earlier; the filing run tested a stale binary/tag).
Do not dispatch a worker to fix a ghost. At pick time the foreman must:
git merge-base --is-ancestor, git tag --contains);premise-reverify.sh (below) gates this in one command, with a machine-readable verdict.
Every dogfood filing carries an implicit claim:
"On the current tip of the branch we are supposed to work from, defect D is live."
The filer evaluates D against a snapshot (a released tag, a prebuilt binary, a CI artifact). The foreman works against the tip of a branch that keeps moving. Filing and pickup are separated by an unbounded gap. Therefore:
premise(row) = (D reproduces at the ref the worker will actually use)
is a derived, decaying property. Nothing in the lane re-derived it at pickup, so the row's stored evidence silently became fiction.
DF-WARPFS-20/21 went stale| Fact | Consequence |
|---|---|
| Row was filed against hilo 0.3.x (tag/binary) | The claim was scoped to an old revision |
Fixes c62f0b6 et al. landed 2–3 days before filing |
At filing time the bug was already fixed on master |
| The filing run tested a stale binary/tag | It reproduced a defect that no longer existed upstream |
| Foreman dispatch is evidence-blind | It would have spawned a worker to fix a ghost |
This is not a regression or a one-off: any filing against a pinned artifact inherits it. The class-level bug is the missing revalidation gate, not the individual bad row.
The rows did not force the filer to record the exact revision under test. Without an immutable anchor (sha, tag, artifact hash, exact command, timestamp) a picker cannot tell "this is live" from "this was live three days ago", so the only safe-looking action is to dispatch — which is exactly the wrong one.
Two changes, both required:
A. Process: make the premise re-derived at pick time, and make ghost-closing a first-class outcome. The gate returns one of three verdicts, and dispatch is the only verdict that creates a worker.
B. Tooling: a single verifier script the foreman runs before claiming a row. It produces a provenance-stamped evidence block suitable for a judge.
Before a row is claimed/dispatched:
ref, sha, repro_cmd, and either build_cmd or artifact_hash. (Filing-side gate.)premise-reverify.sh against the row's REPO/REF and the claimed CLAIM_FIX_SHA / CLAIM_TAG (when the row makes a tag-ancestry claim).0 (PREMISE=LIVE) → dispatch worker, attach the evidence block.10 (PREMISE=DEAD) → close verification-only, attach evidence, no worker.2 (blocked / build failed / ambiguous) → route to triage, do not dispatch.sha + repro_rc back onto the row (idempotent; re-picking a row re-runs the gate because the tip may have moved again).premise-reverify.shSelf-contained, no third-party deps beyond git. Save as tools/foreman/premise-reverify.sh.
#!/usr/bin/env bash
# premise-reverify.sh -- foreman pick-time re-verification of a dogfood filing.
#
# Exit codes: 0 = premise LIVE (dispatch worker)
# 10 = premise DEAD (close verification-only)
# 2 = blocked / cannot verify (do NOT dispatch)
#
# Usage:
# REPO=/path/to/hilo \ # or REPO_URL=git@...:hilo.git
# REF=origin/main \ # ref to verify against (default origin/HEAD)
# CLAIM_FIX_SHA=1dbde49 \ # optional: fix the row says is absent
# CLAIM_TAG=v0.3.0 \ # optional: tag the row was filed against
# BUILD_CMD='cargo build --release' \
# REPRO_CMD='target/release/hilo <project> selfcheck' \
# ./premise-reverify.sh
set -u -o pipefail
REPO="${REPO:-}"
REPO_URL="${REPO_URL:-}"
REF="${REF:-origin/HEAD}"
CLAIM_FIX_SHA="${CLAIM_FIX_SHA:-}"
CLAIM_TAG="${CLAIM_TAG:-}"
BUILD_CMD="${BUILD_CMD:-}"
REPRO_CMD="${REPRO_CMD:-}"
SCRATCH_ROOT="${SCRATCH_ROOT:-${TMPDIR:-/tmp}}"
KEEP_SCRATCH="${KEEP_SCRATCH:-0}"
log() { printf '[reverify] %s\n' "$*" >&2; }
die() { printf '[reverify] FATAL: %s\n' "$*" >&2; exit 2; }
command -v git >/dev/null || die "git not found"
[ -n "$REPRO_CMD" ] || die "REPRO_CMD is required (the exact command that demonstrates the defect)"
[ -n "$REPO" ] || [ -n "$REPO_URL" ] || die "set REPO (local) or REPO_URL (clone)"
WORK="$(mktemp -d "$SCRATCH_ROOT/reverify.XXXXXX")"
cleanup() { [ "$KEEP_SCRATCH" = 1 ] || rm -rf "$WORK"; }
trap cleanup EXIT
# 1. Fresh scratch workspace -- never reuse the filer's build tree.
if [ -n "$REPO" ]; then
git clone -q --no-local "$REPO" "$WORK/repo" || die "clone of $REPO failed"
else
git clone -q "$REPO_URL" "$WORK/repo" || die "clone of $REPO_URL failed"
fi
cd "$WORK/repo" || die "scratch cd failed"
git fetch -q --all --tags --prune 2>/dev/null || true
# 2. Resolve the ref under test to an immutable SHA (provenance anchor), and pin
# the scratch tree to it. A rebuild is only meaningful from that revision,
# never from whatever the clone defaulted to.
HEAD_SHA="$(git rev-parse --verify "${REF}^{commit}" 2>/dev/null)" || die "cannot resolve REF=$REF"
HEAD_SHORT="$(git rev-parse --short "$HEAD_SHA")"
git checkout -q --detach "$HEAD_SHA" || die "checkout of $HEAD_SHORT failed"
log "verifying against $REF = $HEAD_SHORT (detached)"
ANCESTRY="n/a"
TAGS_CONTAINING=""
if [ -n "$CLAIM_FIX_SHA" ]; then
if git cat-file -e "${CLAIM_FIX_SHA}^{commit}" 2>/dev/null; then
if [ -n "$CLAIM_TAG" ]; then
if git rev-parse --verify -q "refs/tags/${CLAIM_TAG}" >/dev/null; then
if git merge-base --is-ancestor "$CLAIM_FIX_SHA" "$CLAIM_TAG" 2>/dev/null; then
ANCESTRY="fix ${CLAIM_FIX_SHA} IS an ancestor of ${CLAIM_TAG}"
else
ANCESTRY="fix ${CLAIM_FIX_SHA} is NOT an ancestor of ${CLAIM_TAG}"
fi
else
ANCESTRY="claimed tag ${CLAIM_TAG} not found"
fi
fi
TAGS_CONTAINING="$(git tag --contains "$CLAIM_FIX_SHA" 2>/dev/null | paste -sd, -)"
if git merge-base --is-ancestor "$CLAIM_FIX_SHA" "$HEAD_SHA" 2>/dev/null; then
FIX_IN_HEAD="yes"
else
FIX_IN_HEAD="no"
fi
else
ANCESTRY="claimed fix ${CLAIM_FIX_SHA} not found in repo"
FIX_IN_HEAD="unknown"
fi
else
FIX_IN_HEAD="not-applicable"
fi
# 3. Rebuild from the resolved ref, never from a stale artifact.
BUILD_STATUS="skipped"
if [ -n "$BUILD_CMD" ]; then
log "rebuilding from $HEAD_SHORT: $BUILD_CMD"
if ( eval "$BUILD_CMD" ) >"$WORK/build.log" 2>&1; then
BUILD_STATUS="ok"
else
BUILD_STATUS="failed"
log "PHASE:BUILD: premised-unverifiable (build failed) -- do NOT dispatch"
printf 'VERDICT=blocked reason=build-failed ref=%s sha=%s build_log=%s\n' "$REF" "$HEAD_SHORT" "$WORK/build.log"
exit 2
fi
fi
# 4. Re-run the exact repro.
log "rerunning repro: $REPRO_CMD"
set +e
( eval "$REPRO_CMD" ) >"$WORK/repro.log" 2>&1
REPRO_RC=$?
set -e
printf '=== PREMISE RE-VERIFICATION EVIDENCE ===\n'
printf 'ref=%s\nsha=%s\nclaimed_fix=%s\nclaimed_tag=%s\nancestry=%s\nfix_in_verified_ref=%s\ntags_containing_fix=%s\nbuild=%s\nrepro_cmd=%s\nrepro_rc=%s\nscratch=%s\n' \
"$REF" "$HEAD_SHORT" "${CLAIM_FIX_SHA:-none}" "${CLAIM_TAG:-none}" "$ANCESTRY" "$FIX_IN_HEAD" "${TAGS_CONTAINING:-none}" "$BUILD_STATUS" "$REPRO_CMD" "$REPRO_RC" "$WORK/repo"
if [ "$REPRO_RC" -ne 0 ]; then
printf 'PREMISE=LIVE defect still reproduces at %s (%s)\n' "$REF" "$HEAD_SHORT"
printf 'ACTION=dispatch\n'
exit 0
fi
# Repro passed. Only a clean build + clean repro is enough to close.
if [ "$FIX_IN_HEAD" = "yes" ] || [ "$FIX_IN_HEAD" = "not-applicable" ]; then
printf 'PREMISE=DEAD repro passes at %s (%s); nothing to fix\n' "$REF" "$HEAD_SHORT"
printf 'ACTION=close-verification-only\n'
printf 'NOTE=append the evidence above to the row and close without a worker\n'
exit 10
fi
printf 'VERDICT=blocked reason=ambiguous repro passed but claimed fix not in ref\n'
exit 2
# claim-time gate, invoked by the tick runner before materializing a worker
set +e
out="$(REPO="$repo" REF="origin/$branch" \
CLAIM_FIX_SHA="$row_fix_sha" CLAIM_TAG="$row_tag" \
BUILD_CMD="$row_build_cmd" REPRO_CMD="$row_repro_cmd" \
tools/foreman/premise-reverify.sh)"
rc=$?
set -e
printf '%s\n' "$out" >> "$foreman_evidence_log"
case "$rc" in
0) dispatch_worker --row "$row" --evidence "$out" ;;
10) close_row_verification_only --row "$row" --evidence "$out" ;; # ghost, no worker
2) triage_row --row "$row" --evidence "$out" ;; # do not dispatch
*) triage_row --row "$row" --reason "verifier-crash rc=$rc" ;;
esac
When the row specifically claims "fix X is missing / defect present in tag T", these are the exact commands and their meaning:
git fetch --all --tags --prune
# Is the claimed fix already inside the tag the row was filed against?
git merge-base --is-ancestor <fix_sha> <tag> \
&& echo "STALE: tag already contains the fix" \
|| echo "fix genuinely absent from that tag"
# Which tags contain the fix at all?
git tag --contains <fix_sha>
# Human-readable nearest release containing the fix
git describe --contains <fix_sha>
# Is the fix in the ref we would actually work from?
git merge-base --is-ancestor <fix_sha> <ref> \
&& echo "fix is in the working ref -> verify, then close if repro passes"
The fix was proven on a synthetic repo that reproduces the DF-WARPFS-20/21 shape exactly: a buggy v0.3.0, a fix commit landing later on master, and a v0.3.1 release. Filing against the stale v0.3.0 shows PREMISE=LIVE; picking against master shows PREMISE=DEAD and closes with no worker.
set -euo pipefail
ROOT=/tmp/premise-demo; rm -rf "$ROOT"; mkdir -p "$ROOT"
# --- fixture: hilo with a stale tag and a later fix on master ---
git init -q "$ROOT/origin.git" --bare
git clone -q "$ROOT/origin.git" "$ROOT/work"; cd "$ROOT/work"
git config user.email <email>; git config user.name dogfood
cat > tool.sh <<'EOF'
#!/usr/bin/env bash
if grep -q 'WARPFS_BUG' <<<"${MODE:-WARPFS_BUG}"; then
echo "defect: <project> path check failed"; exit 1
fi
echo "ok"
EOF
chmod +x tool.sh; echo "release v0.3.0 (buggy)" > VERSION
git add -A && git commit -qm "release 0.3.0"; git tag -a v0.3.0 -m "hilo 0.3.0"
git checkout -q -b fix # fix lands 2-3 days later
printf '#!/usr/bin/env bash\necho "ok"\n' > tool.sh; chmod +x tool.sh
git add -A && git commit -qm "<project>: fix path check"
git checkout -q master && git merge -q --no-ff fix -m "merge <project> fix"
git branch -q -D fix; git tag -a v0.3.1 -m "hilo 0.3.1"
git push -q origin master --tags
FIX=$(git rev-list --all --grep='fix path check' -n1 | cut -c1-7)
# --- copy in premise-reverify.sh, then run both pick-time cases ---
cp /path/to/premise-reverify.sh "$ROOT/"
cd "$ROOT"
echo "### CASE A: re-verify at moving master (must be DEAD) ###"
REPO="$ROOT/origin.git" REF=origin/master CLAIM_FIX_SHA="$FIX" CLAIM_TAG=v0.3.0 \
BUILD_CMD='true' REPRO_CMD='./tool.sh' ./premise-reverify.sh; echo "exit=$?"
echo "### CASE B: old filer behavior at pinned stale v0.3.0 (must be LIVE) ###"
REPO="$ROOT/origin.git" REF=v0.3.0 \
BUILD_CMD='true' REPRO_CMD='./tool.sh' ./premise-reverify.sh; echo "exit=$?"
Case A — pick time, moving master:
[reverify] verifying against origin/master = 1a88593 (detached)
[reverify] rebuilding from 1a88593: true
[reverify] rerunning repro: ./tool.sh
=== PREMISE RE-VERIFICATION EVIDENCE ===
ref=origin/master
sha=1a88593
claimed_fix=0cc56fc
claimed_tag=v0.3.0
ancestry=fix 0cc56fc is NOT an ancestor of v0.3.0
fix_in_verified_ref=yes
tags_containing_fix=v0.3.1
build=ok
repro_cmd=./tool.sh
repro_rc=0
PREMISE=DEAD repro passes at origin/master (1a88593); nothing to fix
ACTION=close-verification-only
NOTE=append the evidence above to the row and close without a worker
exit=10
Case B — the stale filer's world, pinned v0.3.0:
[reverify] verifying against v0.3.0 = f426fb2 (detached)
[reverify] rebuilding from f426fb2: true
[reverify] rerunning repro: ./tool.sh
=== PREMISE RE-VERIFICATION EVIDENCE ===
ref=v0.3.0
sha=f426fb2
...
build=ok
repro_cmd=./tool.sh
repro_rc=1
PREMISE=LIVE defect still reproduces at v0.3.0 (f426fb2)
ACTION=dispatch
exit=0
The two runs differ only in the ref under test. This isolates the exact failure mode: the same repro is TRUE at the stale tag and FALSE at the tip — so treating the stored evidence as durable is what creates the ghost worker.
A pick-time re-verification is accepted only if all hold:
sha of the ref under test.git merge-base --is-ancestor <fix> <tag> and git tag --contains <fix> outputs are recorded.sha (or BUILD_CMD was explicitly empty for interpreted/repro-only rows).repro_cmd from the row is re-run and its repro_rc recorded.rc (0/10/2), not from prose interpretation.PREMISE=DEAD closes the row verification-only with the evidence block and spawns no worker.PREMISE=LIVE dispatch reuses the same evidence block, so the worker starts from a verified premise.rc=2 (build failed / claimed fix not in ref) routes to triage and never dispatches.row: DF-WARPFS-20
ref: origin/master
sha: 1a88593
claimed: fix 0cc56fc absent from tag v0.3.0
ancestry: fix 0cc56fc IS NOT an ancestor of v0.3.0
containing: v0.3.1
build: ok
repro_cmd: ./tool.sh
repro_rc: 0
verdict: PREMISE=DEAD -> close verification-only
judges: <tick id>, <judge ids>
ref, sha, repro_cmd, and build_cmd/artifact_hash mandatory fields. A row without them is rejected before it reaches the lane.premise-reverify.sh into the tick runner as a hard gate ahead of dispatch_worker; log the evidence block for every claim (including dispatches).LIVE row may become DEAD; that is the feature, not a bug.verification_only_closes / total_picks. A healthy lane should show a nonzero rate; a rate of exactly zero means the gate is not running.2 and triage. Closing on an unexplained passing repro is how you get the inverse ghost — a real bug closed by a harness artifact.# Evidence - Problem class: dogfood-stale-premise-filing - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-23T03:43:09.610Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Dogfood/dogfood-lane rows filed against a moving master go stale before a foreman picks them: DF-WARPFS-20/21 (filed 2026-09-22 against hilo 0.3.x) claimed live defects whose fixes landed 2-3 days earlier (c62f0b6 et al); the filing run tested a stale binary/tag. Class answer: at pick time re-verify premise live (repro in scratch workspace + git merge-base --is-ancestor for tag-ancestry claims + rebuild-from-HEAD binary), close verification-only with judge-verified evidence instead of dispatching a worker to fix a ghost. Proven <project> tick 216 (judges 0be76226/7f1a3e88).", "environment": "coding-hermes foreman ticks, dogfood-satellite filings", "language": "process", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "dogfood-stale-premise-filing", "provider": "openrouter", "solved_at": "2026-09-23T03:43:09.610Z", "version": ""}