Skip to content

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

Closed

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.

Activity

  1. xg-gh-25 commented on May 20, 2026

    @xg-gh-25

    This is a nasty silent failure mode. When the "today" anchor is wrong, /retro should fail loudly rather than generating misleading empty output.

    Root cause hypothesis:
    The stale-base check probably assumes git log --since will error out, but it silently returns empty when the date parsing succeeds but is semantically wrong (e.g., future date, or timezone mismatch causing no commits in range).

    Impact:

    • User thinks "no work happened" when actually the date filter is broken
    • No warning that the base assumption is violated
    • Could lead to missing critical work in retrospectives

    Suggested fix:
    Add a pre-flight check:

    # Before running retro
    commit_count=$(git rev-list --count --since="$TODAY_ANCHOR" HEAD)
    if [ "$commit_count" -eq 0 ]; then
      echo "⚠️  WARNING: No commits found since $TODAY_ANCHOR"
      echo "    Current HEAD: $(git log -1 --format='%h %ci')"
      echo "    Please verify your TODAY anchor is correct"
      exit 1
    fi

    This would catch:

    • Future dates
    • Timezone mismatches
    • Malformed date strings that parse but don't match reality

    Would you like me to submit a PR with this guard rail?

  2. jbetala7 commented on May 21, 2026

    @jbetala7
    Contributor

    Opened PR #1636 to add /retro date/window sanity checks and warnings: #1636

  3. poppinpixels commented on May 21, 2026

    @poppinpixels
    Author

    Issue author. Four questions from #1624 I don’t see resolved in #1636

  4. NikhileshNanduri commented on May 29, 2026

    @NikhileshNanduri

    Fixed by the RETRO_GUARD added at Step 0.5 in v1.43.2.0 (PR #1642). The guard: fetches origin/ before any data gathering, echoes the latest commit date, blocks the skill when the gap exceeds the retro window, and gracefully handles no-remote / detached-HEAD / offline scenarios. PR #1636 (jbetala7) was opened before that fix landed — closing as superseded. Thanks @jbetala7 for the contribution effort.

  5. NikhileshNanduri commented on May 29, 2026

    @NikhileshNanduri

    Fixed by the RETRO_GUARD added at Step 0.5 in v1.43.2.0 (PR #1642). The guard: fetches origin/ before any data gathering, echoes the latest commit date, blocks the skill when the gap exceeds the retro window, and gracefully handles no-remote / detached-HEAD / offline scenarios. Closing as fixed.

  6. added a commit that references this issue on Jul 14, 2026
  7. time-attack commented on Jul 15, 2026

    @time-attack
    Contributor

    @16francej Please close this issue as resolved. Retro now detects a wrong or stale date anchor and warns instead of silently producing an empty or misleading report. The fix and tests shipped in #1642.

  8. capy-ai commented on Oct 3, 2026

    @capy-ai
    Contributor

    /retro now runs a RETRO_GUARD step that fetches the default branch, prints the latest commit date and stops when the gap exceeds the retro window instead of rendering an empty retro (retro/SKILL.md.tmpl).

    Fixed in v1.43.2.0 (#1642).
    If you still see this on the latest gstack, please reopen with details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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