Problem
jig sessions can start on a worktree/branch that has silently drifted behind
its upstream. When that happens, the agent forms its whole premise — "what's
built", spec/slice STATUS, file contents — from stale state, before any guard
runs. In practice this bites (real incident: a local origin/main was already
18 commits ahead of the working branch at session start).
Gap in existing hooks
jig already has freshness-adjacent signals, but none covers git branch
staleness at time-zero:
jig-context-check.sh → context freshness (fill %, MCP count)
jig-project-orient.sh → orientation headline from jig artifacts
- spec-workflow
last_verified → spec/ADR staleness
transition and slice-land do a fresh fetch at command time — but that's
later, and only if you reach those commands. There's no earlier tripwire that
fires before the agent trusts repo state.
Proposed shape
A SessionStart hook that is fetch-free (compares HEAD against the
already-known remote ref — instant, no network, can't hang), silent when
up-to-date or not in a repo, and never blocks (always exits 0). Same
soft/never-block philosophy as jig-context-check.sh.
Working prototype (running in my global config today, fired the 18-behind warning):
upstream = @{upstream}, else fall back to origin/main | origin/master
behind = git rev-list --count HEAD..$upstream
if behind > 0: print a ⚠️ warning pointing at `git fetch && git log HEAD..$upstream --oneline`
Full script attached below.
Open questions for maintainer
- In scope for jig? It's pointedly relevant to the merge-main→v2 branch
discipline, where branches silently drift.
- Warn-only, or nudge toward an action? (e.g. suggest a fetch/merge, or
just inform.)
- Opt-out env var — assume
JIG_GIT_FRESHNESS=0 to match the other hooks?
- Threshold — warn at any N>0 behind, or only past a floor?
- Fetch-free vs. optional fresh fetch — keep it strictly local (my bias:
yes, so it can never hang a session), or offer an opt-in fetch mode?
If the shape's agreeable I'll open a PR with the hook + a test
(test_jig_git_freshness.py) matching the existing hook-test pattern.
Prototype script
#!/usr/bin/env bash
# SessionStart hook — warn if this git worktree/branch is behind its upstream,
# BEFORE any file is read or premise formed. Fetch-free, silent when fresh,
# never blocks.
set +e
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{upstream}' 2>/dev/null)
if [ -z "$upstream" ]; then
for cand in origin/main origin/master; do
if git rev-parse --verify -q "$cand" >/dev/null 2>&1; then upstream="$cand"; break; fi
done
fi
[ -z "$upstream" ] && exit 0
behind=$(git rev-list --count "HEAD..$upstream" 2>/dev/null)
[ -z "$behind" ] && exit 0
if [ "$behind" -gt 0 ]; then
echo "⚠️ GIT FRESHNESS: HEAD is $behind commit(s) behind $upstream."
echo " Verify against $upstream before trusting repo state: git fetch && git log HEAD..$upstream --oneline"
fi
exit 0
Problem
jig sessions can start on a worktree/branch that has silently drifted behind
its upstream. When that happens, the agent forms its whole premise — "what's
built", spec/slice STATUS, file contents — from stale state, before any guard
runs. In practice this bites (real incident: a local
origin/mainwas already18 commits ahead of the working branch at session start).
Gap in existing hooks
jig already has freshness-adjacent signals, but none covers git branch
staleness at time-zero:
jig-context-check.sh→ context freshness (fill %, MCP count)jig-project-orient.sh→ orientation headline from jig artifactslast_verified→ spec/ADR stalenesstransitionandslice-landdo a fresh fetch at command time — but that'slater, and only if you reach those commands. There's no earlier tripwire that
fires before the agent trusts repo state.
Proposed shape
A
SessionStarthook that is fetch-free (comparesHEADagainst thealready-known remote ref — instant, no network, can't hang), silent when
up-to-date or not in a repo, and never blocks (always exits 0). Same
soft/never-block philosophy as
jig-context-check.sh.Working prototype (running in my global config today, fired the 18-behind warning):
Full script attached below.
Open questions for maintainer
discipline, where branches silently drift.
just inform.)
JIG_GIT_FRESHNESS=0to match the other hooks?yes, so it can never hang a session), or offer an opt-in fetch mode?
If the shape's agreeable I'll open a PR with the hook + a test
(
test_jig_git_freshness.py) matching the existing hook-test pattern.Prototype script