// 宗师顶(B·职业层)单测 —— 2026-07-21 立。 // 守:①double-witness 自检(done 必双证) ②归类有限集 ③唐学者→国子祭酒双证在 ④noTrack 诚实 ⑤查不实标待补不编。 // 跑:node --test test/zongshi.test.js import test from 'node:test'; import assert from 'node:assert/strict'; import { GUDAI_LEI, MODERN_TO_GUDAI, classifyProfession, zongshiFor, assertZongshi, ZONGSHI } from '../src/zongshi.js'; test('①宗师顶双证自检 CLEAN(done 的每条都两证齐全)', () => { assert.deepEqual(assertZongshi(), [], 'done:true 的宗师顶必须双证齐全'); }); test('②归类:预设类走映射、自由文本走关键词、命不中返 null(不硬猜)', () => { assert.equal(classifyProfession('中医大夫', 'health').lei, 'yi', '预设 health→医'); assert.equal(classifyProfession('国画家', 'art').lei, 'yishu', '预设 art→艺'); assert.equal(classifyProfession('针灸推拿').lei, 'yi', '自由文本关键词→医'); assert.equal(classifyProfession('书法老师').lei, 'yishu', '自由文本→艺'); assert.equal(classifyProfession('高中语文老师').lei, 'wen', '自由文本→文'); assert.equal(classifyProfession('外卖调度不知道啥').lei, null, '归不了 → null,交给 AI/用户,不硬猜'); }); test('③唐·学者宗师顶=国子监祭酒·从三品,两史互证', () => { const z = zongshiFor('wen', 'tang'); assert.ok(z?.done, '唐学者宗师顶已双证上线'); assert.equal(z.title, '国子监祭酒'); assert.equal(z.grade, '从三品'); assert.match(z.source, /新唐书/); assert.match(z.source2, /旧唐书/); assert.ok(z.quote.includes('從三品') && z.quote2.includes('從三品'), '两证都逐字含「從三品」'); }); test('④noTrack 诚实:商无正经仕途巅峰,不编假官', () => { const z = zongshiFor('shang', 'tang'); assert.ok(z?.noTrack, '商→noTrack'); assert.ok(!z.title, 'noTrack 绝不带 title(不编假官)'); }); test('⑤查不实标待补:唐·医宗师顶未双证 ⇒ done:false,不当真数据发', () => { const z = zongshiFor('yi', 'tang'); assert.equal(z?.done, false, '未双证的必须 done:false'); assert.ok(z.note, '待补条必须写明为什么待补'); }); test('⑥有限集:古代类是有限的几类,现代类全映射到其中(other 除外)', () => { const leiIds = new Set(GUDAI_LEI.map((l) => l.id)); for (const [modern, lei] of Object.entries(MODERN_TO_GUDAI)) { if (lei === null) continue; // other 待分类 assert.ok(leiIds.has(lei), `现代类 ${modern} 映到的 ${lei} 必须是有限古代类之一`); } });