Skip to content

feat(#63): SessionStart drift banner — show when fork is behind upstream#64

Merged
atlas-apex merged 1 commit into
mainfrom
feature/#63-drift-banner
Apr 17, 2026
Merged

feat(#63): SessionStart drift banner — show when fork is behind upstream#64
atlas-apex merged 1 commit into
mainfrom
feature/#63-drift-banner

Conversation

@atlas-apex

Copy link
Copy Markdown
Collaborator

Summary

SessionStart hook that prints a one-line banner when the fork is behind upstream me2resh/apexstack. Silent on network failure, silent if no upstream remote, silent when up-to-date. Runs once per 10 minutes via a session cache.

Ships PRD-0002 change #2. Compounds with #58 (/update): banner tells you when to sync, skill does the sync.

What changed

  • .claude/hooks/check-upstream-drift.sh — new hook (2.5 KB). Handles remote detection, fetch caching, default-branch resolution (main/master), and singular/plural output.
  • .claude/settings.json — wires the hook into SessionStart alongside onboarding-check.sh.
  • CLAUDE.md — hook count 15 → 16, brief reference.
  • docs/multi-project.md — new "How you know it's time" subsection in the Upgrades section.
  • .claude/hooks/README.md — hook documented as section 4a.

Testing

Verified end-to-end:

  • Runs in the upstream apexstack repo (no upstream remote) → exits silent, no output
  • Runs in the ops fork at ~/apexstack (has upstream, 1 commit behind after [Feature] /update command to sync ApexStack fork from upstream #58 merged) → prints:
    ApexStack: 1 commit behind upstream/main. Run /update to sync.
    
  • Second run in same directory within 10 min → no re-fetch (cache hit), still prints correct count
  • Cache file at .claude/session/last-upstream-fetch is a single timestamp, gitignored

Glossary

Term Definition
upstream drift Ops fork lagging behind me2resh/apexstack in commits. Problem #1 in PRD-0002.
fetch cache .claude/session/last-upstream-fetch holds a Unix timestamp so the hook skips the network call if run within the last 10 minutes. Session state, gitignored.
SessionStart Claude Code hook event that fires on every new session start. Used for setup reminders and status banners.
default branch The repo's conventional integration branch, resolved from refs/remotes/origin/HEAD. Usually main, sometimes master.

Related

PRD-0002 change #2. Compounds with /update (#58): banner tells you
when to sync, skill does the sync.

What the hook does:
- SessionStart: runs `git fetch upstream --quiet` (timeout 5s)
- Caches last-fetch time in .claude/session/last-upstream-fetch,
  skips re-fetch if within 10 minutes
- Counts `git rev-list main..upstream/main`
- If behind, prints one line to stdout; silent otherwise

Silent exit paths (no output, no startup noise):
- Not a git repo
- No `upstream` remote (upstream repo itself, or fork that hasn't
  configured one yet)
- Fetch fails (offline / hosting down / auth)
- Fork is up-to-date

Banner:

    ApexStack: 12 commits behind upstream/main. Run /update to sync.

Singular/plural ("1 commit" vs "N commits") handled inline.

Verified end-to-end against the ops fork (workspace/apexstack/ here
has no upstream → silent; ops repo at project root has upstream and
is 1 commit behind after #58 merged → banner fires correctly).

Also:
- .claude/settings.json: hook wired into SessionStart alongside
  onboarding-check.sh
- CLAUDE.md: hook count 15 → 16
- docs/multi-project.md: new "How you know it's time" subsection in
  the Upgrades section
- .claude/hooks/README.md: hook documented as 4a

Closes #63

@atlas-apex atlas-apex left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #64

Commit: 9cdad01573726175c71a9dde8fa9649b3766f59b

Summary

Adds SessionStart hook check-upstream-drift.sh that prints a one-line banner when the fork is behind upstream/<default-branch>. Companion to /update (#61). Silent on network failure, no upstream remote, or up-to-date. 10-min fetch cache.

Checklist

  • Architecture & Design: Pass — clean bail-out ladder, single responsibility
  • Code Quality: Pass — defensive shell (2>/dev/null, || exit 0), timeout 5 caps worst case, singular/plural correct
  • Testing: Pass — PR body documents three verified scenarios (no upstream / behind / cache hit)
  • Security: Pass — no secrets, no command-injection surface
  • Performance: Pass — cache keeps cold-path < 200ms; worst case bounded at ~5s
  • PR Description & Glossary: Pass — 4 terms (upstream drift, fetch cache, SessionStart, default branch)
  • AgDR: N/A — mechanical implementation of PRD-0002 change #2, no new tech decisions

Notes (non-blocking)

  • Default-branch fallback to main if origin/HEAD unset is reasonable; a master repo without origin/HEAD set would silently compare wrong refs and rev-list exits → silent. Acceptable for v1.
  • Settings.json ordering correct: onboarding reminder fires first (fresh clones have no upstream → drift hook silent).
  • Hook count bumped 15→16 in CLAUDE.md, consistent with README section 4a.

Verdict

APPROVED (submitted as comment — cannot self-approve)

Rex marker written at .claude/session/reviews/64-rex.approved (41 bytes, matches #61 format).


Reviewed by Rex (Code Reviewer Agent)
Reviewed commit: 9cdad01573726175c71a9dde8fa9649b3766f59b

@atlas-apex atlas-apex merged commit e23c1ab into main Apr 17, 2026
4 checks passed
@atlas-apex atlas-apex deleted the feature/#63-drift-banner branch April 17, 2026 08:09
osama-abu-baker pushed a commit to osama-abu-baker/apexyard that referenced this pull request Jun 3, 2026
…d upstream (me2resh#64)

PRD-0002 change #2. Compounds with /update (me2resh#58): banner tells you
when to sync, skill does the sync.

What the hook does:
- SessionStart: runs `git fetch upstream --quiet` (timeout 5s)
- Caches last-fetch time in .claude/session/last-upstream-fetch,
  skips re-fetch if within 10 minutes
- Counts `git rev-list main..upstream/main`
- If behind, prints one line to stdout; silent otherwise

Silent exit paths (no output, no startup noise):
- Not a git repo
- No `upstream` remote (upstream repo itself, or fork that hasn't
  configured one yet)
- Fetch fails (offline / hosting down / auth)
- Fork is up-to-date

Banner:

    ApexStack: 12 commits behind upstream/main. Run /update to sync.

Singular/plural ("1 commit" vs "N commits") handled inline.

Verified end-to-end against the ops fork (workspace/apexstack/ here
has no upstream → silent; ops repo at project root has upstream and
is 1 commit behind after me2resh#58 merged → banner fires correctly).

Also:
- .claude/settings.json: hook wired into SessionStart alongside
  onboarding-check.sh
- CLAUDE.md: hook count 15 → 16
- docs/multi-project.md: new "How you know it's time" subsection in
  the Upgrades section
- .claude/hooks/README.md: hook documented as 4a

Closes me2resh#63

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
mosta7il pushed a commit to mosta7il/apexyard that referenced this pull request Jun 8, 2026
…d upstream (me2resh#64)

PRD-0002 change me2resh#2. Compounds with /update (me2resh#58): banner tells you
when to sync, skill does the sync.

What the hook does:
- SessionStart: runs `git fetch upstream --quiet` (timeout 5s)
- Caches last-fetch time in .claude/session/last-upstream-fetch,
  skips re-fetch if within 10 minutes
- Counts `git rev-list main..upstream/main`
- If behind, prints one line to stdout; silent otherwise

Silent exit paths (no output, no startup noise):
- Not a git repo
- No `upstream` remote (upstream repo itself, or fork that hasn't
  configured one yet)
- Fetch fails (offline / hosting down / auth)
- Fork is up-to-date

Banner:

    ApexStack: 12 commits behind upstream/main. Run /update to sync.

Singular/plural ("1 commit" vs "N commits") handled inline.

Verified end-to-end against the ops fork (workspace/apexstack/ here
has no upstream → silent; ops repo at project root has upstream and
is 1 commit behind after me2resh#58 merged → banner fires correctly).

Also:
- .claude/settings.json: hook wired into SessionStart alongside
  onboarding-check.sh
- CLAUDE.md: hook count 15 → 16
- docs/multi-project.md: new "How you know it's time" subsection in
  the Upgrades section
- .claude/hooks/README.md: hook documented as 4a

Closes me2resh#63

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] SessionStart drift banner — show when fork is behind upstream

2 participants