From 66e21dcd5ccf7293a5abce06d604457c54d546b0 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Tue, 3 Nov 2026 17:36:40 +0100 Subject: [PATCH] fix(council): let the Claude Code session id win over --session A claim made with --session stored the name, but the PreToolUse gate compares the hook payload's session_id, so the gate refused every edit of the claiming session and a later release without the flag exited 3. caller() now takes CLAUDE_CODE_SESSION_ID whenever it is set and falls back to --session only for other runtimes. test_council covers a claim and release with --session under a Claude Code session (negative control against the old caller fails). Claims made with --session before this fix go stale after an hour without a heartbeat and can then be taken over. Co-Authored-By: Claude Opus 5.5 --- skills/kvb-org-organize/scripts/council.py | 7 ++++--- tests/test_council.py | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/skills/kvb-org-organize/scripts/council.py b/skills/kvb-org-organize/scripts/council.py index 94c0ade..91fe50f 100755 --- a/skills/kvb-org-organize/scripts/council.py +++ b/skills/kvb-org-organize/scripts/council.py @@ -4,7 +4,8 @@ Environment: AGENTS_COUNCIL_ROOT: council directory shared by every agent on the host; /tmp/agents-council unless set, because all agents must agree on it. - CLAUDE_CODE_SESSION_ID: the caller's session; other runtimes pass --session. + CLAUDE_CODE_SESSION_ID: the caller's session, taken over --session; other + runtimes pass --session. Exit codes: 0 done, 2 usage error, 3 office held by a live session, @@ -46,11 +47,11 @@ def live_sessions() -> dict[str, str | None]: def caller(session: str | None) -> tuple[str, str]: - if session: - return session, "other" env = os.environ.get("CLAUDE_CODE_SESSION_ID") if env: return env, "claude-code" + if session: + return session, "other" print("council: no session id; pass --session", file=sys.stderr) sys.exit(2) diff --git a/tests/test_council.py b/tests/test_council.py index 7205155..2ad28c0 100644 --- a/tests/test_council.py +++ b/tests/test_council.py @@ -62,6 +62,11 @@ class TestCouncil(unittest.TestCase): self._run("s1", "claim", "work/x", "--work", "w") self.assertEqual(self._run("s2", "takeover", "work/x", "--work", "w").returncode, 3) + def test_session_flag_cannot_hide_the_claude_code_session(self): + self._run("s1", "claim", "work/x", "--work", "w", "--session", "One") + self.assertIn('"session": "s1"', (self.root / "work/x/claim.json").read_text()) + self.assertEqual(self._run("s1", "release", "work/x", "--session", "One").returncode, 0) + def test_only_the_holder_releases(self): self._run("s1", "claim", "work/x", "--work", "w") self.assertEqual(self._run("s2", "release", "work/x").returncode, 3)