WhatsApp 上 8 月 23 日 17:30 到 8 月 25 日 00:08 之间一共 84 条消息,其中 33 条是语音和图片。语音全部下载转录后,才拿到完整要求——有一条只存在于语音里,文字消息完全没提。
她截图里那份考卷长得像老式打字机打出来的,字与字之间空隙忽大忽小。看起来像 AI 排版差。其实不是。
问题出在渲染管线选错了一个模板文件。那份模板是给教材用的,不是给考卷用的,里面写死了两件事:
| 模板里写的 | 在她 Mac 上的实际后果 |
|---|---|
字体 Source Serif 4 | Mac 上没装这个字体 → Word 自动换成一个等宽的备用字体 → 打字机效果 |
段落 JUSTIFY(两端对齐) | 短行被强行撑满 → 字间大空隙 → 她说的「跳来跳去」 |
| 表格用 pandoc 默认样式 | 样式里边框直接写死是「无」→ 所有表格都没有框线 |
换句话说:那个打字机效果根本不在源文件里,是字体在她电脑上回退造成的。这也解释了为什么我们这边看着还行、她那边看着一塌糊涂。
这不是 AI 偷懒,是钟表不答应。一个实操工位现实上要 ~48 分钟,加上口试 30 分钟、交卷整理 10 分钟:
_engine/ppa/worksheet.py 的时间容量模型;实际时间预算表已印在 FB-018-3 SET B 考卷第 1 页 A. TEMPOH 节。所以给 Jennifer 的不是一句「不行」,是一份表格:每个 NOSS 一张「Borang Pemilihan Unit Kompetensi」,列出全部 CU 加上各自的工作活动数和评估准则数(= 占时间的诚实指标),让她自己勾。表格上直接写着容量提示。
校验器指向 FB-018-3 现有的 8 份文件,自动扫出的结果——这些正是 Jennifer 用眼睛一条条挑出来的东西:
uv run python -m _engine.ppa.cli validate 首次运行,报告存于 _engine/reports/validate-20260825T040446Z.json。| 检查 | 数量 | 抓到的是什么 |
|---|---|---|
| V05 语言 | 335 | 中英马混排(Tinjauan Pasaran / Market Survey 式对照 + 整段英文) |
| V04 已排除单元 | 20 | E01 说好不考,却出现在封面、TUGASAN C、评分表、口试题 5.11–5.12 |
| V06 封面清单 | 4 | 四份文件封面都还列着 E01 |
| V02 实操覆盖 | 3 | C01/C04/C05 定为实操,TUGASAN 段落却没提到 |
| V03 口试覆盖 | 2 | C02 没有对应口试题;某份出了 12 题(要求 10 题) |
| V07 时长 | 2 | 一份没有卷级时长声明;一份写「3 HOURS」(英文单位) |
| V08 页数 | 4 | 页数是硬写的(29/30/24/13),没经过渲染核对 |
页数这条值得单独说:JPK 考卷封面要声明印刷页数,用来防止有人从密封考卷里抽走一页。Jennifer 自己那两份参考样本这里都写错了(soalan 写 13 实际 14,skema 写 14 实际 11)。页数只有排版完才知道,所以现在文件里先写占位符,渲染完由程序回填真实数字,再重新排版确认数字没把行数撑爆——反复到稳定为止。
把同一套东西套到剩下的科目上。NOSS 原文逐条转录成机器可读的能力图谱:
那 20 处是标准文件自己的问题,不是我们的。照录不改,全部记进 source_notes。举两个例子:
转录时「顺手改对」听起来负责,实际上会让这份图谱不再能追溯回标准原文——PPL 拿标准来对,对不上。所以照录 + 标注。
其余 5 个 NOSS 的 CU 该怎么选,是 Jennifer 的决定,我不能替她定。但不需要她决定的部分(语言、分数、页数)可以先量化出来:
uv run python -m _engine.ppa.cli lint,扫描 output/jennifer-ppa-soalan/ 下 44 份考卷文件。合计 44 份文件、799 个待修问题,其中 775 个是语言混排。FB-018-3 已经是 0。
她 00:08 那句「有这种可能吗」——有。它现在是一个叫 noss-ppa-generator 的技能,七个步骤:
| # | 步骤 | 谁做 |
|---|---|---|
| 1 | NOSS PDF → 能力图谱(逐条转录,错漏照录并标注) | 机器 |
| 2 | 生成 CU 选择表,附时间容量提示 | 机器 |
| 3 | 填表:每个 CU 标实操 / 口试 / 不考 | Jennifer |
| 4 | 写成机器可读的 profile + 给写手的规格书 | 机器 |
| 5 | 生成 SOALAN / SKEMA / ANSWER SHEET / EQUIPMENT | 机器 |
| 6 | V01–V10 校验,0 错才放行 | 机器 |
| 7 | 渲染 → 数页数 → 回填 → 出 PDF → 人眼复核两页 | 机器 + 人 |
第 3 步是整套东西的心脏。没有它,就回到 AI 自己挑 CU 的老路。
她的权威版是 马来文标题 + 英文正文——A. TEMPOH MASA 配 : 3 HOURS,C. TUGASAN 配 The candidate is required to…,两者从不出现在同一句里。
她说的「only one language」指的是一句话里中英马对照那种混排,不是要求整份改成马来文。上午照「全马来文」改,如果拿这套规则去校验她自己已通过的卷,会误报几百条——这本身就说明规则当时定错了。
把她的 PDF 按字体逐个 span 抽出来:
BOLD C01 MARKET & PRODUCT SURVEY [Arial-BoldMT]
C02 DIRECT / RETAIL SALES [ArialMT]
C03 AFTER SALES SERVICE [ArialMT]
BOLD C04 SELF SALES PERFORMANCE ASSESSMENT [Arial-BoldMT]
BOLD C05 ONLINE SALES [Arial-BoldMT]
C06 PRODUCT MARKETING [ArialMT]
raw/jennifer-authoritative-fb018-3/jen-skema-setA.pdf 第 1 页,本次 session 用 pymupdf 按 span 字体名抽取。C01、C04、C05——正是她 8 月 25 日 00:02 才用文字讲清楚的那三个。文本抽取会把粗体丢掉,所以 AI 看到的是六个一模一样的单元。对应昨晚那段:
你 23:17:「你这边加粗的意思是选那些加粗的 cu 对吗?可能 ai 误会了」
她 23:17:「对」
结论:决策如果只靠视觉格式承载,就过不了管线。必须以数据形式携带。这正是 profile 文件存在的理由。
核对答案范本时发现,Appendix 2 里的「已核实汇总表」和同一附录的 20 行原始数据对不上——而考生的任务恰恰是「分析原始数据」:
| 项目 | 汇总表说 | 20 行原始数据实际是 |
|---|---|---|
| Married + Children | 10 | 11 |
| Air-Conditioner | 7 | 6 |
| 有购买意向 Yes | 15 | 16 |
后果:老老实实数那 20 行的考生,会被评分表判错。
而且这条串了一整条链——答案范本跟着汇总表走,评分表跟着答案范本走,所以从里往外看每一层都「一致」,唯独跟考生手上真正要分析的那张表不一致。三个 agent、十四个校验器,全部漏过。
已修,并加了 V15 数据对账校验器。而且验证过它真的会响——把修好的数字改回错的,立刻报两条。一个不会响的校验器,通过了等于没查,还买了个假的安心。
| 文件 | 她的实际结构 | 我们之前 |
|---|---|---|
| ASSESSMENT ANSWER SHEET | 8 页,红笔填好的答案范本 | 3 页空白答题栏 另一种文件 |
| EQUIPMENT VERIFICATION | 单页 JPK 表单 JPK/PPA-PPT/SP/1:2022 | 3 页自创结构 格式错 |
这两份在 8 月 21 日那次审计里就被标注为「未审」——搁着没看的东西,往往正是错得最离谱的。
已上传 Jennifer 的 Drive(档名前缀 [fb3 B 25.08]),并发了 WhatsApp + 4 张改动前后对照图给她核对。她已读。
把同一套格式套到 Office Admin、Digital Marketing、Retail Outlet、S&M L4/L5 —— 22 份 soalan + skema 全部重做。写了个批量迁移脚本,40 个文件不可能靠手改。
页眉参考码的正则是照 FB-018-3 写的,认不出 N821-001-3 这种「字母+数字」开头的代码。后果:
两处都修了。这是今天第二次遇到同一类失败——V15 那次也是「链条内部处处一致,唯独与外部真相不一致」。
| 问题 | 怎么发现的 |
|---|---|
| FB-018-45 的 CU 代码是编的 — 考卷写 M01–M08,我的图谱写 C01–C08,原文 PDF 的 CU Code 栏整栏空白,连 NOSS 编号都没印 | 查证时抽全文,两种代码一个字都搜不到 |
L4 和 L5 撞号 — 两份不同考卷都印 FB-018-45:2012/2026/A/01,PPL 签字栏也一样 | 跨文件查重(第一版写太粗,把同一份卷的四件套也误报——她的原件也是四件共码,那是对的) |
| 5 个文件渲染失败 — 加页眉后版式多一页,声明页数不再准 | 新加的「声明 vs 实际」终检拦下的。这正是它存在的理由 |
上午我说「N821 的标准自相矛盾,正文写 Staff、图表写 Office」。实际读原文的 agent 报告:§6 p.6、CPC p.11、CoCU 15.7 p.71 三处全写 Staff。是 8 月 21 日那份审计搞错,我照抄了它没有复核。考卷上的 C07 STAFF ADMINISTRATION SUPERVISION 是对的。
上午那条「其余科目共 799 个待修问题」——换成正确的语言规则后是 140。其中 659 条是我上午那条做过头的规则造成的误报。一个规则定错,它产生的「发现」全都是噪音,还会误导下一步该修什么。
今天的批量迁移只覆盖了 soalan 和 skema。结果:10 份设备核对表全部还是自创格式,10 份答案范本全部是空白表格式。
而这两类正是 8 月 21 日那次审计标注为「未审」的文件。搁置未读之物,往往错得最彻底。
设备核对表改成了从考卷 §D+§E 直接推导而非人写——这样它在结构上就不可能和考卷不一致。跨文档「考卷清单 vs 核对表清单」不符从 10 处降到 0。
答案范本是考官的对照钥匙。抓到 4 处引用了考卷没有的附录编号:
| 文件 | 引用 | 考卷实际 |
|---|---|---|
| G471 ×2 | Appendix 3A / 3B / 5A / 5B | APPENDIX 3 内含 ### A. ### B. |
| FB-018-45 L4 ×2 | Appendix 2B | APPENDIX 2 内含 **B. …** |
内容理解正确,标签自己造。考官拿着卷子搜那个字串会一无所获。
没有采信 agent 的报告——自己算:
G471 2,350.00 = 备用金 200.00 + 现金销售 2,150.00 ✓
28 = 货架容量 40 − 现有 12 ✓
N821 105.00 = 3 × 35.00 85.00 = 10 × 8.50 ✓
60.00 = 5 × 12.00 90.00 = 6 × 15.00 ✓
61.50 = 期初 287.00 − 报销合计 225.50 ✓
*-answer-sheet.md 的粗体数字与其配对 *-soalan.md 附录中印出的原始数据。单价 35.00 / 12.00 / 8.50 / 15.00 全部印在考卷里。上一次跳过这一步的后果,就是本页前面那条 V15——汇总表与原始数据打架,照实算的考生会被判错。
| 发生了什么 | 教训 |
|---|---|
| V05 语言检查连续三次「修好一个、打破另一个」:只查右边 → 加词表 → 要求左边有虚词 | 最后改成正面判据,并建 7 个探针固定行为。没有探针的规则调整是盲改 |
| 把设备表专用的字号/页边距参数误套到 soalan/skema 上 | 参数写进代码按文件类型自动选,不再靠人记 |
| 修签名孤儿页 → 改成表格行 → 反而撑坏了列宽 | 真因在上游一个从没出过问题的函数。改动影响范围永远比预期大一格 |
格式全部做完了,但它们的 CU 结构仍然是错的——Office Admin 还是 7 个 CU 全在里面,正是 Jennifer 点名的问题。等她填完 CU 选择表才能定案。
此刻上传会让它们看起来像完成品。已上传的只有 FB-018-3 四件。
VIZTECH TRADING SDN. BHD.——那是别家中心的名字,从参考样本抄来的,而且同一个名字还被当成场景里的虚构公司在用。我已改成 CHARACTER INTERNATIONAL ACADEMY SDN. BHD.,场景公司另起名 Sinar Elektronik。考卷是以谁的 pentauliahan 递交就必须是谁,这个你要拍板。① 中心名称是推断的 — 下午已确证:她自己那份原件封面写的就是 CHARACTER INTERNATIONAL ACADEMY SDN. BHD.,VIZTECH 只出现在我们上传的文件里。仍已发消息请她书面确认一次。
② 其余 5 个 NOSS 的考卷还没改——因为 CU 选择必须她先定。已量化的 799 个问题里,语言和分数部分可以先改,但 CU 结构不动。
③ Jennifer 那两份参考样本里的另外两件(ASSESSMENT ANSWER SHEET、EQUIPMENT VERIFICATION 原件)至今没审过,我方的是照结构自己做的。
④ 「三个 CU 只用口试验证是否满足 JPK 对实作评估的要求」——这条要 PPL 确认,不是我能判断的。Jennifer 的原始样本就是这个结构,但它是不是被 JPK 正式接受过,没有证据。
图谱结构:NOSS → CU → WorkActivity → PerformanceCriterion,CU 上挂一个 mode 属性(practical / oral / excluded),这个属性只能来自 profile,永不由模型推断。
十个校验器:V01 profile 覆盖全部 CU · V02 实操 CU 出现在 TUGASAN · V03 口试 CU 有题且题数对 · V04 排除的 CU 不出现在任何地方 · V05 单语 · V06 封面清单 = 实际评估集合 · V07 时长在窗口内且单位是 JAM · V08 页数不是占位符 · V09 权重合计 100% · V10 评分表逐节对账。
代码位置:_engine/ppa/(图谱 + 校验 + 工作表 + CLI)、_engine/render/(docx 渲染 + 页数回填 + PDF)、_engine/graph/(6 份 NOSS 图谱)、_engine/profiles/(选择档)、.claude/skills/noss-ppa-generator/(操作手册)。
渲染修的具体项:Arial 强制(含 eastAsia / cs 字形槽,python-docx 默认只设 ascii)· 全局左对齐 · 直接写 w:tblBorders(改 table.style 无效,pandoc 的直接格式会覆盖样式)· Jata Negara 徽章插入正文首行 · w:tblHeader 表头跨页重复 · w:cantSplit 行不跨页断开 · 页脚参考编号 + 页码 · 表头判定排除含填空下划线的行。