397777089e
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
145 lines
5.6 KiB
JavaScript
145 lines
5.6 KiB
JavaScript
// tools/missed-activations.test.mjs
|
|
import { describe, it, expect } from 'vitest';
|
|
import { detectMissedActivations } from './missed-activations.mjs';
|
|
|
|
const map = {
|
|
refactor: ['#11', '#12', '#43'],
|
|
bugfix: ['#18', '#34'],
|
|
feature: ['#19'],
|
|
other: [],
|
|
};
|
|
const dormancy = { '#11': false, '#12': false, '#43': false, '#18': false, '#34': false, '#19': false };
|
|
|
|
function ep(classification, node_chosen) {
|
|
return {
|
|
schema_version: 2,
|
|
primary_rationale: { task_classification: classification, node_chosen },
|
|
};
|
|
}
|
|
|
|
describe('detectMissedActivations', () => {
|
|
it('counts an episode with profile classification + node_chosen=direct as missed', () => {
|
|
const result = detectMissedActivations([ep('refactor', 'direct')], map, dormancy);
|
|
expect(result.totalMissed).toBe(1);
|
|
expect(result.byNode).toEqual({ '#11': 1, '#12': 1, '#43': 1 });
|
|
});
|
|
|
|
it('does NOT count episode when the recommended node IS chosen', () => {
|
|
const result = detectMissedActivations([ep('refactor', '#11')], map, dormancy);
|
|
expect(result.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('does NOT count episode when classification=other (empty list)', () => {
|
|
const result = detectMissedActivations([ep('other', 'direct')], map, dormancy);
|
|
expect(result.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('excludes dormant (DEFERRED) nodes from recommendations', () => {
|
|
const dorm = { ...dormancy, '#43': true };
|
|
const result = detectMissedActivations([ep('refactor', 'direct')], map, dorm);
|
|
expect(result.byNode).toEqual({ '#11': 1, '#12': 1 });
|
|
expect(result.totalMissed).toBe(1);
|
|
});
|
|
|
|
it('returns totalMissed=0 when ALL recommended nodes are dormant', () => {
|
|
const dorm = { '#11': true, '#12': true, '#43': true };
|
|
const result = detectMissedActivations([ep('refactor', 'direct')], map, dorm);
|
|
expect(result.totalMissed).toBe(0);
|
|
expect(result.byNode).toEqual({});
|
|
});
|
|
|
|
it('ignores schema v1 episodes (no factor analysis)', () => {
|
|
const v1 = { schema_version: 1, primary_rationale: { task_classification: 'refactor', node_chosen: 'direct' } };
|
|
const result = detectMissedActivations([v1], map, dormancy);
|
|
expect(result.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('ignores observer_error markers', () => {
|
|
const err = { observer_error: true };
|
|
const result = detectMissedActivations([err], map, dormancy);
|
|
expect(result.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('ignores unknown classification (not in map)', () => {
|
|
const result = detectMissedActivations([ep('unknown-bucket', 'direct')], map, dormancy);
|
|
expect(result.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('aggregates byClassification breakdown for the report', () => {
|
|
const eps = [
|
|
ep('refactor', 'direct'),
|
|
ep('refactor', 'direct'),
|
|
ep('bugfix', 'direct'),
|
|
];
|
|
const result = detectMissedActivations(eps, map, dormancy);
|
|
expect(result.byClassification).toEqual({ refactor: 2, bugfix: 1 });
|
|
expect(result.totalMissed).toBe(3);
|
|
});
|
|
|
|
it('detects missed activation on v3 episode', () => {
|
|
const v3 = { schema_version: 3, primary_rationale: { node_chosen: 'direct', task_classification: 'feature', recommended_node: '#19' } };
|
|
const result = detectMissedActivations([v3], { feature: ['#19'] }, { '#19': false });
|
|
expect(result.totalMissed).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe('detectMissedActivations — §17 v4 path (Phase 2 Task 11)', () => {
|
|
it('flags direct on non-conversation v4 episode with recommended_node', () => {
|
|
const r = detectMissedActivations([{
|
|
schema_version: 4,
|
|
classifier_output: { task_type: 'feature', recommended_node: '#19', no_skill_found: false },
|
|
execution_trace: { actual_node_invoked_first: 'direct' },
|
|
}]);
|
|
expect(r.totalMissed).toBe(1);
|
|
expect(r.byNode).toEqual({ '#19': 1 });
|
|
expect(r.byClassification).toEqual({ feature: 1 });
|
|
});
|
|
|
|
it('does not flag conversation task_type (§17 exempt)', () => {
|
|
const r = detectMissedActivations([{
|
|
schema_version: 4,
|
|
classifier_output: { task_type: 'conversation', recommended_node: null },
|
|
}]);
|
|
expect(r.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('does not flag micro / manual_override (§17 exempt)', () => {
|
|
const r = detectMissedActivations([
|
|
{ schema_version: 4, classifier_output: { task_type: 'micro', recommended_node: null }, execution_trace: { actual_node_invoked_first: 'direct' } },
|
|
{ schema_version: 4, classifier_output: { task_type: 'manual_override', recommended_node: 'tdd' }, execution_trace: { actual_node_invoked_first: 'direct' } },
|
|
]);
|
|
expect(r.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('does not flag when no_skill_found=true (classifier honestly admits no match)', () => {
|
|
const r = detectMissedActivations([{
|
|
schema_version: 4,
|
|
classifier_output: { task_type: 'feature', recommended_node: null, no_skill_found: true },
|
|
execution_trace: { actual_node_invoked_first: 'direct' },
|
|
}]);
|
|
expect(r.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('does not flag when a real node fired (not direct)', () => {
|
|
const r = detectMissedActivations([{
|
|
schema_version: 4,
|
|
classifier_output: { task_type: 'feature', recommended_node: '#19', no_skill_found: false },
|
|
execution_trace: { actual_node_invoked_first: 'superpowers:test-driven-development' },
|
|
}]);
|
|
expect(r.totalMissed).toBe(0);
|
|
});
|
|
|
|
it('does not flag when recommended_node is dormant', () => {
|
|
const r = detectMissedActivations(
|
|
[{
|
|
schema_version: 4,
|
|
classifier_output: { task_type: 'feature', recommended_node: '#50', no_skill_found: false },
|
|
execution_trace: { actual_node_invoked_first: 'direct' },
|
|
}],
|
|
{},
|
|
{ '#50': true },
|
|
);
|
|
expect(r.totalMissed).toBe(0);
|
|
});
|
|
});
|