3c3bdc2d3d
Phase 2 Task 11 of LLM-first router overhaul. Spec §17 — extends
detectMissedActivations() to recognise the new v4 episode schema while keeping
the v2/v3 conditional rule (Pravila §16.4 v1.36) unchanged for legacy episodes
still flowing in the log.
- tools/missed-activations.mjs:
+ V4_EXEMPT_TASK_TYPES = {conversation, micro, manual_override} (§17 exempt
set; continuation deliberately not in this list per spec §6 / D1).
+ v4 branch: uses classifier_output.task_type +
classifier_output.recommended_node + classifier_output.no_skill_found +
execution_trace.actual_node_invoked_first. classificationMap is ignored
on this path (recommended_node is inline). Dormancy still respected.
+ v2/v3 legacy branch unchanged.
+ signature kept positional (episodes, classificationMap?, dormancy?) —
brain-retro-analyzer.mjs:229 and observer-coverage-checker.mjs:124
untouched; their tests still pass.
- tools/missed-activations.test.mjs: +6 v4-path tests (flagged miss / 3 §17
exempt cases / no_skill_found honest / real node fired / recommended dormant).
Tests: 16 missed-activations + 35 brain-retro-analyzer + 10 observer-coverage-
checker = 61 PASS, 0 regressions.
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);
|
|
});
|
|
});
|