Skip to content

Two defects in _SESSIONS concurrent-session detection — value never echoed + marker TTL doesn't reflect 'currently active' #1651

@TJ-NomoAI

Description

@TJ-NomoAI

Context

Built a CLAUDE.md-level concurrent-agent detection rule on top of gstack's _SESSIONS mechanism (so a session-start step can force the operator into a separate git worktree when another Claude Code agent is active in the same repo). Two defects surfaced during the ship + dogfooding.

Defect A — _SESSIONS is computed but never echoed

Every skill preamble does:

mkdir -p ~/.gstack/sessions
touch ~/.gstack/sessions/"$PPID"
_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')

The variable is computed but only consumed by an internal check inside the preamble. The preamble echoes many other state values to stdout for the calling agent to read (BRANCH:, PROACTIVE:, PROACTIVE_PROMPTED:, SKILL_PREFIX:, REPO_MODE:, LAKE_INTRO:, TELEMETRY:, TEL_PROMPTED:, EXPLAIN_LEVEL:, QUESTION_TUNING:, ARTIFACTS_SYNC:, LEARNINGS:, HAS_ROUTING:, ROUTING_DECLINED:, VENDORED_GSTACK:, MODEL_OVERLAY:, CHECKPOINT_MODE:, CHECKPOINT_PUSH:) — but never _SESSIONS:. Any CLAUDE.md rule that tells the agent to "read the preamble's session count" has no value to read.

Cost: my v1 CLAUDE.md rule said exactly that and shipped non-functional. Caught on post-ship audit when I re-read my own /ship preamble output adversarially. Worked around by inlining the bash command (find ~/.gstack/sessions -mmin -120 -type f | wc -l) into the rule itself.

Fix shape (cheap): add echo "SESSIONS: $_SESSIONS" to the preamble's existing echo block. ~1 line. Backwards-compatible.

Defect B — Marker TTL doesn't reflect "currently active"

The touch ~/.gstack/sessions/$PPID runs once per skill preamble invocation. The find -mmin -120 finds markers touched within 2h. A long-running Claude Code session that doesn't invoke a gstack skill for >2h has its marker mtime stay frozen; eventually it falls outside the window and the session reports SESSIONS=0 despite being active.

Reproduced live in my own session post-ship:

$ ls -la ~/.gstack/sessions/
-rw-r--r--  1 user staff  0 May 21 12:28 65834   ← last skill invocation 10h+ ago

$ find ~/.gstack/sessions -mmin -120 -type f
(empty)                                          ← marker outside the 2h window

$ # but my Claude Code session is still active and editing files

If two long-running sessions hit this state simultaneously, both register SESSIONS=0 and both "proceed normally" while actively colliding — the exact failure mode the marker was designed to prevent.

Fix shapes (pick one):

  1. Refresh the marker via a PreToolUse hook (gstack already uses these heavily). touch ~/.gstack/sessions/$PPID on every tool call. Marker mtime tracks "actively using tools," not "ran a skill in the last 2h."
  2. Shorter TTL + periodic refresh hook. More moving parts.
  3. Switch to a different detection signal entirely (e.g., ps). Platform-dependent, brittle.

Recommendation: option 1. Reuses existing hook infrastructure, minimal added complexity, gives accurate "is this session active" signal.

Why this matters beyond my repo

Any gstack consumer building concurrent-agent safety on top of _SESSIONS will hit both gaps. Filing now so the design conversation happens once at the right layer instead of every consumer rolling their own workaround.

Reference

Full forensic detail (with the multi-month context of the worktree-warfare failure mode this detection was meant to prevent) lives in my local repo at: docs/upstream-issues/gstack-sessions-detection-gaps.md (will be on main once PR Nomo-AI-Labs/nomo-ai#2843 merges).

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