fix(v2): AI_FALLBACK replaces the ACTIONABLE_NOW-with-confidence-0 lie, normalize null-like strings
Fallback (ai_disabled, ai_error, invalid_json, ai_max_candidates_cap -- any candidate the AI never actually analyzed) now produces classification 'AI_FALLBACK', an explicit technical state that is never part of the 11-class enum sent to OpenAI (the AI itself can never legitimately return it). Previously it silently claimed ACTIONABLE_NOW with confidence 0, which made unanalyzed tickets indistinguishable from genuinely confirmed ones at the classification-label level. Also normalizes blocker_type/waiting_for when the model returns the literal string "null"/"none"/"n/a"/"" instead of JSON null -- done once, in the validation layer (logic/classification.js), not scattered around the workflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
db7a261a10
commit
00a42db269
+31
-2
@@ -1,12 +1,41 @@
|
||||
const { test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const { buildFallbackClassification } = require('./fallback');
|
||||
const { buildFallbackClassification, AI_FALLBACK_CLASSIFICATION } = require('./fallback');
|
||||
const { VALID_CLASSIFICATIONS } = require('./classification');
|
||||
|
||||
test('fallback e sempre seguro e marcado como tal', () => {
|
||||
const result = buildFallbackClassification('ai_timeout');
|
||||
assert.equal(result.is_fallback, true);
|
||||
assert.equal(result.fallback_reason, 'ai_timeout');
|
||||
assert.equal(result.confidence, 0);
|
||||
assert.equal(result.classification, 'ACTIONABLE_NOW');
|
||||
assert.ok(result.reason.includes('Fallback'));
|
||||
});
|
||||
|
||||
test('fallback NUNCA finge ser ACTIONABLE_NOW -- usa AI_FALLBACK, um estado tecnico explicito', () => {
|
||||
const result = buildFallbackClassification('ai_error');
|
||||
assert.equal(result.classification, AI_FALLBACK_CLASSIFICATION);
|
||||
assert.notEqual(result.classification, 'ACTIONABLE_NOW');
|
||||
assert.equal(result.actionable_today, false);
|
||||
});
|
||||
|
||||
test('AI_FALLBACK nunca e uma classe que a propria IA pode retornar (fica fora do schema enviado a OpenAI)', () => {
|
||||
assert.ok(!VALID_CLASSIFICATIONS.includes(AI_FALLBACK_CLASSIFICATION));
|
||||
});
|
||||
|
||||
test('AI_MAX_CANDIDATES gera AI_FALLBACK, nao ACTIONABLE_NOW', () => {
|
||||
const result = buildFallbackClassification('ai_max_candidates_cap');
|
||||
assert.equal(result.classification, AI_FALLBACK_CLASSIFICATION);
|
||||
assert.equal(result.fallback_reason, 'ai_max_candidates_cap');
|
||||
});
|
||||
|
||||
test('erro de IA gera AI_FALLBACK', () => {
|
||||
assert.equal(buildFallbackClassification('ai_error').classification, AI_FALLBACK_CLASSIFICATION);
|
||||
});
|
||||
|
||||
test('IA desligada gera AI_FALLBACK', () => {
|
||||
assert.equal(buildFallbackClassification('ai_disabled').classification, AI_FALLBACK_CLASSIFICATION);
|
||||
});
|
||||
|
||||
test('JSON invalido gera AI_FALLBACK', () => {
|
||||
assert.equal(buildFallbackClassification('invalid_json').classification, AI_FALLBACK_CLASSIFICATION);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user