From 79a4249e0b3fc4c368230dfdd39d343c66a0a017 Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Fri, 1 May 2026 17:30:14 +0200 Subject: [PATCH] feat(ai-psychosis): persist pushback + domain in sessions.jsonl --- .../hooks/scripts/session-end.mjs | 6 ++- .../ai-psychosis/tests/session-end.test.mjs | 38 ++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/plugins/ai-psychosis/hooks/scripts/session-end.mjs b/plugins/ai-psychosis/hooks/scripts/session-end.mjs index 21fe57c..73c78be 100644 --- a/plugins/ai-psychosis/hooks/scripts/session-end.mjs +++ b/plugins/ai-psychosis/hooks/scripts/session-end.mjs @@ -38,6 +38,8 @@ const depFlags = Number(state.dep_flags) || 0; const escFlags = Number(state.esc_flags) || 0; const fatFlags = Number(state.fatigue_flags) || 0; const valFlags = Number(state.val_flags) || 0; +const pushbackCount = Number(state.pushback_count) || 0; +const domainContext = state.domain_context || null; const startIso = state.start_iso || ''; // Compute duration @@ -54,11 +56,13 @@ appendJsonl(SESSIONS_LOG, { duration_min: durationMin, tool_count: toolCount, edit_count: editCount, + domain_context: domainContext, flags: { dependency: depFlags, escalation: escFlags, fatigue: fatFlags, - validation: valFlags + validation: valFlags, + pushback: pushbackCount } }); diff --git a/plugins/ai-psychosis/tests/session-end.test.mjs b/plugins/ai-psychosis/tests/session-end.test.mjs index ed46fce..ed6c110 100644 --- a/plugins/ai-psychosis/tests/session-end.test.mjs +++ b/plugins/ai-psychosis/tests/session-end.test.mjs @@ -53,7 +53,7 @@ describe('session-end', () => { runHook('session-end.mjs', { session_id: 's3', cwd: '/tmp' }, dir); const records = readJsonl(join(dir, 'sessions.jsonl')); const end = records.find(r => r.end); - assert.deepEqual(end.flags, { dependency: 3, escalation: 1, fatigue: 2, validation: 0 }); + assert.deepEqual(end.flags, { dependency: 3, escalation: 1, fatigue: 2, validation: 0, pushback: 0 }); }); it('handles missing state file gracefully', () => { @@ -63,4 +63,40 @@ describe('session-end', () => { assert.equal(records.length, 1); assert.equal(records[0].note, 'no_state_file'); }); + + it('persists pushback_count and domain_context (v1.1.0)', () => { + dir = setupTestDir(); + createStateFile(dir, 's4', { + start_epoch: Math.floor(Date.now() / 1000) - 120, start_iso: '2026-01-01T10:00:00Z', + tool_count: 2, edit_count: 1, + dep_flags: 0, esc_flags: 0, fatigue_flags: 0, val_flags: 0, + pushback_count: 3, domain_context: 'relationship', + last_event_epoch: 0, burst_count: 0, last_warning_epoch: 0, + }); + runHook('session-end.mjs', { session_id: 's4', cwd: '/tmp' }, dir); + const records = readJsonl(join(dir, 'sessions.jsonl')); + const end = records.find(r => r.end); + assert.ok(end); + assert.equal(end.flags.pushback, 3); + assert.equal(end.domain_context, 'relationship'); + }); + + it('backward-compat: state without pushback_count yields flags.pushback === 0 (not NaN/undefined)', () => { + dir = setupTestDir(); + createStateFile(dir, 's5', { + start_epoch: Math.floor(Date.now() / 1000) - 60, start_iso: '2026-01-01T10:00:00Z', + tool_count: 1, edit_count: 0, + dep_flags: 0, esc_flags: 0, fatigue_flags: 0, val_flags: 0, + // pushback_count and domain_context intentionally absent (v1.0.0 state shape) + last_event_epoch: 0, burst_count: 0, last_warning_epoch: 0, + }); + runHook('session-end.mjs', { session_id: 's5', cwd: '/tmp' }, dir); + const records = readJsonl(join(dir, 'sessions.jsonl')); + const end = records.find(r => r.end); + assert.ok(end); + assert.equal(end.flags.pushback, 0); + assert.notEqual(end.flags.pushback, undefined); + assert.ok(!Number.isNaN(end.flags.pushback)); + assert.equal(end.domain_context, null); + }); });