Skip to content

/retro silently produces empty/misleading output when 'today' anchor is wrong (no stale-base warning) #1624

@poppinpixels

Description

@poppinpixels

Failure mode

When /retro runs on a worktree-style setup (Conductor, etc.) and the agent's understanding of "today" is off by enough days, the skill silently produces a clean-looking retro that misses recent reality. The git log --since="<midnight-aligned-start>" window quietly returns zero or near-zero commits, but nothing in the output flags that the window is wrong.

Both inputs to the window can be wrong:

  1. "today" anchor drift — the agent computes today from session-context cues that don't match the actual system date (model error, session-reminder mismatch, etc.).
  2. Stale worktree base — the Conductor/claude/... branch is days/weeks behind origin/<default>, and although the skill does git fetch origin <default> --quiet, nothing surfaces that the latest commit is materially older than "today" would suggest.

Either way, the retro renders successfully, the metrics table looks legitimate, and the user gets a confidently-wrong report.

Reproducer

I hit this on a real project today:

  • today per system date: 2026-05-20
  • Agent computed today (incorrectly): 2026-05-15
  • /retro (default 7d): analyzed --since="2026-05-08T00:00:00", returned 18 commits (all from May 8-11), missed 4 commits on origin/main from May 19-20 including the latest version bump
  • Output: a clean retro narrative ending "Streak: 0d (4-day burst May 8-11)" — looks coherent, completely missed v0.21.0 → v0.22.0 work that had already shipped

The user caught it only when version-bumping for the next PR: "version number is way old."

Why it's silent

Step 1: Gather Raw Data runs git fetch origin <default> --quiet and then immediately starts gathering commits via git log origin/<default> --since="<window>". There's no sanity-check on the gap between "today" and origin/<default>'s latest commit. If the gap exceeds the window length, the window is empty — but the retro keeps going and the model fills in narrative from whatever (possibly zero) commits it found.

Suggested fix (sketch)

Inject a stale-base sanity check right after the fetch, before the data-gathering. Always echo the latest commit date + gap so the agent has the data point; escalate to an explicit warning when the gap is suspect:

git fetch origin <default> --quiet

_LATEST_COMMIT_TS=$(git log origin/<default> -1 --format="%at" 2>/dev/null || echo 0)
_LATEST_COMMIT_DATE=$(git log origin/<default> -1 --format="%ad" --date=short 2>/dev/null || echo unknown)
_GAP_DAYS=$(( ($(date +%s) - _LATEST_COMMIT_TS) / 86400 ))
echo "ORIGIN_<default>_LATEST: $_LATEST_COMMIT_DATE (${_GAP_DAYS}d before today)"
if [ "$_GAP_DAYS" -gt 3 ]; then
  echo "⚠ STALE-BASE WARNING: latest commit is ${_GAP_DAYS} days before today."
  echo "  If your window is shorter than ${_GAP_DAYS}d, the retro will contain few or zero commits."
  echo "  Sanity-check the 'today' anchor against the actual system date before proceeding —"
  echo "  a clean-looking retro on the wrong window silently misses recent reality."
fi

Plus a prose follow-up after the bash block: "If the stale-base warning fires: confirm that today matches the system date, and that origin/<default> actually has the recent activity you expect. If the gap exceeds the window length, the retro will report empty or near-empty results — that's evidence the anchor or fetch is wrong, not that the team didn't ship."

Always echoing the data point (even when no warning fires) gives the agent a fact to cross-check against. The 3-day threshold is comfortably above typical weekly cadence (so weekend gaps don't false-positive) but low enough to catch the 9-day case I hit. The threshold is debatable — could be window-aware (e.g., gap > window_days) if the skill exposes the parsed window length as a bash var.

Why I'm filing an issue instead of a PR

I have a working local patch (tested against the repo where the bug surfaced) but want to confirm with you whether:

  • The 3-day threshold is right, or whether it should be window-aware
  • The warning text matches gstack's voice/conventions
  • This belongs in Step 1: Gather Raw Data or as its own pre-flight step before Step 1
  • The fix should also apply to /retro compare and /retro global (the global mode has its own multi-repo discovery — the same failure mode could occur there)

Happy to send a PR shaped however you'd prefer. Context: hit while running /retro from a Claude Code (Conductor) worktree branch that was 4 commits behind origin/main.


If helpful: the lesson also landed in my local project memory as "high-confidence 'obviously fine' moments are exactly when the second pair of eyes catches the thing that isn't" — same pattern across the stale-base miss, a self-judged bug diagnosis, and a /ship declaring-done gate where I skipped the advisor. The /retro skill is the most fixable of these because the check is mechanical.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions