feat: add ai-psychosis plugin to open marketplace
Meta-awareness tools for healthy AI interaction patterns. Detects reinforcement loops, scope escalation, and compulsive patterns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f93d6abdae
commit
297867f847
19 changed files with 1920 additions and 0 deletions
66
plugins/ai-psychosis/tests/session-end.test.mjs
Normal file
66
plugins/ai-psychosis/tests/session-end.test.mjs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { describe, it, afterEach } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { join } from 'path';
|
||||
import { existsSync } from 'fs';
|
||||
import { runHook, setupTestDir, cleanupTestDir, createStateFile, readJsonl } from './test-helper.mjs';
|
||||
|
||||
let dir;
|
||||
afterEach(() => { if (dir) cleanupTestDir(dir); });
|
||||
|
||||
describe('session-end', () => {
|
||||
it('finalizes session record and deletes state file', () => {
|
||||
dir = setupTestDir();
|
||||
const nowEpoch = Math.floor(Date.now() / 1000);
|
||||
createStateFile(dir, 's1', {
|
||||
start_epoch: nowEpoch - 300, start_iso: '2026-01-01T10:00:00Z',
|
||||
tool_count: 5, edit_count: 2,
|
||||
dep_flags: 1, esc_flags: 0, fatigue_flags: 0, val_flags: 1,
|
||||
last_event_epoch: 0, burst_count: 0, last_warning_epoch: 0,
|
||||
});
|
||||
runHook('session-end.mjs', { session_id: 's1', cwd: '/tmp' }, dir);
|
||||
const records = readJsonl(join(dir, 'sessions.jsonl'));
|
||||
const end = records.find(r => r.end);
|
||||
assert.ok(end);
|
||||
assert.equal(end.session_id, 's1');
|
||||
assert.equal(end.tool_count, 5);
|
||||
assert.equal(end.edit_count, 2);
|
||||
assert.ok(!existsSync(join(dir, 'state', 's1.json')));
|
||||
});
|
||||
|
||||
it('computes duration correctly', () => {
|
||||
dir = setupTestDir();
|
||||
const nowEpoch = Math.floor(Date.now() / 1000);
|
||||
createStateFile(dir, 's2', {
|
||||
start_epoch: nowEpoch - 3600, start_iso: '2026-01-01T10:00:00Z',
|
||||
tool_count: 10, edit_count: 3,
|
||||
dep_flags: 0, esc_flags: 0, fatigue_flags: 0, val_flags: 0,
|
||||
last_event_epoch: 0, burst_count: 0, last_warning_epoch: 0,
|
||||
});
|
||||
runHook('session-end.mjs', { session_id: 's2', cwd: '/tmp' }, dir);
|
||||
const records = readJsonl(join(dir, 'sessions.jsonl'));
|
||||
const end = records.find(r => r.end);
|
||||
assert.ok(end.duration_min >= 59 && end.duration_min <= 61);
|
||||
});
|
||||
|
||||
it('preserves flags in final record', () => {
|
||||
dir = setupTestDir();
|
||||
createStateFile(dir, 's3', {
|
||||
start_epoch: Math.floor(Date.now() / 1000) - 60, start_iso: '2026-01-01T10:00:00Z',
|
||||
tool_count: 1, edit_count: 0,
|
||||
dep_flags: 3, esc_flags: 1, fatigue_flags: 2, val_flags: 0,
|
||||
last_event_epoch: 0, burst_count: 0, last_warning_epoch: 0,
|
||||
});
|
||||
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 });
|
||||
});
|
||||
|
||||
it('handles missing state file gracefully', () => {
|
||||
dir = setupTestDir();
|
||||
runHook('session-end.mjs', { session_id: 'missing', cwd: '/tmp' }, dir);
|
||||
const records = readJsonl(join(dir, 'sessions.jsonl'));
|
||||
assert.equal(records.length, 1);
|
||||
assert.equal(records[0].note, 'no_state_file');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue