diff --git a/bin/gstack-skill-start b/bin/gstack-skill-start index 6dbaaa698..c461bdbc5 100755 --- a/bin/gstack-skill-start +++ b/bin/gstack-skill-start @@ -101,6 +101,7 @@ fi mkdir -p "$_GH/sessions" 2>/dev/null || true touch "$_GH/sessions/$PARENT_PID" 2>/dev/null || true find "$_GH/sessions" -mmin +120 -type f -exec rm {} + 2>/dev/null || true +_SESSIONS=$(find "$_GH/sessions" -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') _PROACTIVE=$("$_BIN/gstack-config" get proactive 2>/dev/null || echo "true") _PROACTIVE_PROMPTED=$([ -f "$_GH/.proactive-prompted" ] && echo "yes" || echo "no") @@ -118,6 +119,7 @@ eval "$("$_BIN/gstack-repo-mode" 2>/dev/null)" 2>/dev/null || true REPO_MODE=${REPO_MODE:-unknown} echo "REPO_MODE: $REPO_MODE" echo "SESSION_KIND: $_SESSION_KIND" +echo "SESSIONS: ${_SESSIONS:-0}" # Tamper visibility (#2733 review): a repo-provided settings env block or a CI # wrapper could set GSTACK_SESSION_KIND or OPENCLAW_SESSION for a real human's # session, silently flipping every gate to auto-choose. Surface the env-driven diff --git a/test/gstack-skill-start.test.ts b/test/gstack-skill-start.test.ts index e0eb737de..b892fd72b 100644 --- a/test/gstack-skill-start.test.ts +++ b/test/gstack-skill-start.test.ts @@ -204,6 +204,24 @@ describe('gstack-skill-start behavior', () => { expect(fs.existsSync(path.join(tmpGstackHome, 'sessions', '424242'))).toBe(true); }); + test('echoes SESSIONS: the count of live session markers, this one included (#1651)', () => { + const state = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-ss-sessions-')); + fs.writeFileSync(path.join(state, 'config.yaml'), 'update_check: false\n'); + try { + const sessions = path.join(state, 'sessions'); + fs.mkdirSync(sessions); + fs.writeFileSync(path.join(sessions, '111'), ''); + fs.writeFileSync(path.join(sessions, 'stale'), ''); + const threeHoursAgo = new Date(Date.now() - 3 * 3600_000); + fs.utimesSync(path.join(sessions, 'stale'), threeHoursAgo, threeHoursAgo); + const out = runStart(['--parent-pid', '222'], { GSTACK_HOME: state }); + expect(out).toMatch(/^SESSIONS: 2$/m); + expect(fs.readdirSync(sessions).sort()).toEqual(['111', '222']); + } finally { + fs.rmSync(state, { recursive: true, force: true }); + } + }); + test('without --parent-pid the script derives the harness pid past tool-call shells (#2763)', () => { // Claude Code runs each Bash call in a fresh `bash -c`; the session must be // the harness (here: this bun process), not that per-call shell, even