第 1 卷(人物主线):第 1–3 集 + 人物表

主角线:Guspu Frillyknots / Ral Fastenhatchets / Alath Blottedmine
由线索挖掘器自动选定,按因果链切集,经 5 维度自评闸门(≥12 分)后入库。
This commit is contained in:
Chen Yi
2026-10-05 19:28:49 +08:00
parent 594cf48a1a
commit e0073e90bd
24 changed files with 2070 additions and 79 deletions
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# 管道启动器:把命令交给一个真正装了依赖的解释器。
#
# 背景(实测踩过的坑):会话里 PATH 上的 python3 可能不是系统解释器,
# 而是编辑器工具链自建的 venv(例如 ~/.pi-lens/pip-tools)。
# 那种 venv 里没有 defusedxml,而且关闭了 user site,于是
# `python3 -m dfannals.cli` 会突然报 ModuleNotFoundError。
# 这里主动挑一个能 import defusedxml 的解释器,避免依赖 PATH 的偶然性。
#
# scripts/dfannals status|plan|threads|episodes|cast|index|next|run ...
# DFANNALS_PYTHON=/path/to/python3 scripts/dfannals status # 也可显式指定
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
pick_python() {
local cand
for cand in "${DFANNALS_PYTHON:-}" /usr/bin/python3 python3; do
[ -n "$cand" ] || continue
command -v "$cand" >/dev/null 2>&1 || continue
if "$cand" -c "import defusedxml" >/dev/null 2>&1; then
printf '%s' "$cand"
return 0
fi
done
return 1
}
PY="$(pick_python)" || {
echo "找不到可用解释器:需要一个能 import defusedxml 的 python3。" >&2
echo "装依赖:sudo apt install -y python3-defusedxml" >&2
exit 1
}
cd "$HERE"
exec "$PY" -m dfannals.cli "$@"
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""闸门自检:证明 5 维度自评真的能把"流水账"判成不合格。
这是 t4 契约要求的可复现证据。它跑两次真实模型自评:
平淡稿:纯事件罗列,主角全程被动,没有任何抉择、转折或具体对手
有戏剧本:主角有目标、冲突逐级升级、有立场翻转、对手具体
然后断言 平淡稿 < 阈值 ≤ 有戏剧本。若两者都低,说明评分尺度太严(会误杀好稿);
若两者都高,说明闸门形同虚设。
"""
from __future__ import annotations
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from dfannals import gate # noqa: E402
DULL = """# 第二十三章:大事记
元年,甲死了。甲是精灵。三年,乙死了。乙是精灵。
五年,甲和乙的部族打了一仗。七年,又打了一仗。九年,再打了一仗。
十一年,丙死了。十三年,丁死了。十五年,戊死了。十七年,又打了一仗。
十九年,己死了。二十一年,庚死了。二十三年,辛死了。二十五年,壬死了。
史书到此中断。以上均有据可查。
"""
VIVID = """# 第二十三章:他等那口井塌了十七年
Ngalak 站在井台边数桶。第七桶,他想,今天必须到第十桶。
"粮行的水,先紧着粮行用。"他对排队的人说。队伍里有人骂了一句,他没回头。他要的不是水。
水他买得起;他买不起的是 Minkot 每天清晨把钥匙挂在腰间走过集市时,那种不必向任何人解释的从容。
第三年冬天,井边塌了一角,压死了两个挑水的孩子。Ngalak 第一个到场。他跪在泥水里哭,
哭得比孩子的母亲还大声,哭完站起来,把外袍脱下来盖在尸首上。人群里有人说:这才是管事的人。
Minkot 站在后面,手里还握着一把钥匙,一句话没说。
"你那是哭吗?"当晚 Minkot 在酒馆里问他,把酒碗撞在桌上,酒溅出来一半,"你那是敲锣。"
"我敲了,"Ngalak 把溅出来的酒擦干,"你听见了?"
第十年,Minkot 的妻子在集市上指着 Ngalak 的鼻子说:是你挖的地基。三天后她改口,说自己 grief 昏了头。
Ngalak 送了她一头牛。她把牛牵走的那天,Minkot 站在门口看着,门没关,他也没让妻子进屋。
"你到底要什么?"第十七年,Minkot 终于开口。集市上的人都停下来听。
"我要你不必再解释的资格。"Ngalak 说。
Minkot 把钥匙从腰上解下来,放在井台上,然后回身把自己家里的水缸砸了。陶片溅了一地。
"这口井,我不要了。"他说,"记住,今天不是他赢了——是我不要了。"
Ngalak 站在原地。他等这一天等了十七年,真等到手的时候,发现钥匙比他想的要重。
他把它握了很久,才发觉自己在数桶:第八桶,第九桶,第十桶。
"""
def main() -> int:
print("跑真实模型自评(两次调用)…\n")
dull = gate.evaluate(DULL)
print("平淡稿:", dull.render())
vivid = gate.evaluate(VIVID)
print("有戏剧本:", vivid.render())
print(f"\n阈值 = {gate.THRESHOLD}(满分 {len(gate.DIMENSIONS) * gate.MAX_SCORE})")
ok = dull.total < gate.THRESHOLD <= vivid.total
print(f"平淡稿 {dull.total} < 阈值 ≤ 有戏剧本 {vivid.total} → {'通过' if ok else '不通过'}")
if not ok:
if vivid.total < gate.THRESHOLD:
print("问题:评分尺度太严,好稿也会被误杀。")
else:
print("问题:闸门形同虚设,平淡稿也能通过。")
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())