mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-18 16:13:29 +08:00
fix: P1 test state-file PID mismatch + P2 session key eviction
P1 (cubic-dev-ai): Test process PID differs from spawned hook PID, so test was seeding/clearing wrong state file. Fix: pass fixed CLAUDE_SESSION_ID='gateguard-test-session' to spawned hooks. P2 (cubic-dev-ai): Pruning checked array could evict __bash_session__ and other session keys, causing gates to re-fire mid-session. Fix: preserve __prefixed keys during pruning, only evict file-path entries. 9/9 tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,9 +59,12 @@ function loadState() {
|
|||||||
function saveState(state) {
|
function saveState(state) {
|
||||||
try {
|
try {
|
||||||
state.last_active = Date.now();
|
state.last_active = Date.now();
|
||||||
// Prune checked list if it exceeds the cap
|
// Prune checked list if it exceeds the cap.
|
||||||
|
// Preserve session keys (__prefixed) so gates like __bash_session__ don't re-fire.
|
||||||
if (state.checked.length > MAX_CHECKED_ENTRIES) {
|
if (state.checked.length > MAX_CHECKED_ENTRIES) {
|
||||||
state.checked = state.checked.slice(-MAX_CHECKED_ENTRIES);
|
const sessionKeys = state.checked.filter(k => k.startsWith('__'));
|
||||||
|
const fileKeys = state.checked.filter(k => !k.startsWith('__'));
|
||||||
|
state.checked = [...sessionKeys, ...fileKeys.slice(-(MAX_CHECKED_ENTRIES - sessionKeys.length))];
|
||||||
}
|
}
|
||||||
fs.mkdirSync(STATE_DIR, { recursive: true });
|
fs.mkdirSync(STATE_DIR, { recursive: true });
|
||||||
// Atomic write: temp file + rename prevents partial reads
|
// Atomic write: temp file + rename prevents partial reads
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ const { spawnSync } = require('child_process');
|
|||||||
|
|
||||||
const runner = path.join(__dirname, '..', '..', 'scripts', 'hooks', 'run-with-flags.js');
|
const runner = path.join(__dirname, '..', '..', 'scripts', 'hooks', 'run-with-flags.js');
|
||||||
const stateDir = process.env.GATEGUARD_STATE_DIR || path.join(process.env.HOME || process.env.USERPROFILE || '/tmp', '.gateguard-test-' + process.pid);
|
const stateDir = process.env.GATEGUARD_STATE_DIR || path.join(process.env.HOME || process.env.USERPROFILE || '/tmp', '.gateguard-test-' + process.pid);
|
||||||
// State files are per-session. In tests, falls back to pid-based name.
|
// Use a fixed session ID so test process and spawned hook process share the same state file
|
||||||
const sessionId = process.env.CLAUDE_SESSION_ID || process.env.ECC_SESSION_ID || `pid-${process.ppid || process.pid}`;
|
const TEST_SESSION_ID = 'gateguard-test-session';
|
||||||
const stateFile = path.join(stateDir, `state-${sessionId.replace(/[^a-zA-Z0-9_-]/g, '_')}.json`);
|
const stateFile = path.join(stateDir, `state-${TEST_SESSION_ID}.json`);
|
||||||
|
|
||||||
function test(name, fn) {
|
function test(name, fn) {
|
||||||
try {
|
try {
|
||||||
@@ -60,6 +60,7 @@ function runHook(input, env = {}) {
|
|||||||
...process.env,
|
...process.env,
|
||||||
ECC_HOOK_PROFILE: 'standard',
|
ECC_HOOK_PROFILE: 'standard',
|
||||||
GATEGUARD_STATE_DIR: stateDir,
|
GATEGUARD_STATE_DIR: stateDir,
|
||||||
|
CLAUDE_SESSION_ID: TEST_SESSION_ID,
|
||||||
...env
|
...env
|
||||||
},
|
},
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
@@ -87,6 +88,7 @@ function runBashHook(input, env = {}) {
|
|||||||
...process.env,
|
...process.env,
|
||||||
ECC_HOOK_PROFILE: 'standard',
|
ECC_HOOK_PROFILE: 'standard',
|
||||||
GATEGUARD_STATE_DIR: stateDir,
|
GATEGUARD_STATE_DIR: stateDir,
|
||||||
|
CLAUDE_SESSION_ID: TEST_SESSION_ID,
|
||||||
...env
|
...env
|
||||||
},
|
},
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
|
|||||||
Reference in New Issue
Block a user