<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>分支叙事 on PlumePHP</title><link>https://plumephp.com/tags/%E5%88%86%E6%94%AF%E5%8F%99%E4%BA%8B/</link><description>Recent content in 分支叙事 on PlumePHP</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Fri, 16 Oct 2026 23:00:00 +0800</lastBuildDate><atom:link href="https://plumephp.com/tags/%E5%88%86%E6%94%AF%E5%8F%99%E4%BA%8B/index.xml" rel="self" type="application/rss+xml"/><item><title>15.3 规模告警</title><link>https://plumephp.com/narr-sys-15-3-scale-warning/</link><pubDate>Fri, 16 Oct 2026 23:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-15-3-scale-warning/</guid><description>给规模定四条软告警阈值：可达状态数 &gt; 1e7、单次 BFS &gt; 120 秒、峰值内存 &gt; 4 GB、单条路径步数 &gt; 40。当前规格四条全未越（9895423 状态、58.6 秒、2147.1 MB、31 步）；把 flag 放大到 30 后越过三条，而内存那条在两次复跑里一次越一次未越，脚本恒 exit 0。</description></item><item><title>15.2 求值与遍历的开销</title><link>https://plumephp.com/narr-sys-15-2-eval-traversal-cost/</link><pubDate>Fri, 16 Oct 2026 22:30:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-15-2-eval-traversal-cost/</guid><description>量叙事引擎的单位成本：单次 eval_cond 求值中位数 169.9 ns，一次完整 BFS 32 层 9895423 状态、峰值 frontier 2498621、19121205 次求值、60.8 秒、峰值内存 2153 MB。给出求值次数与规格规模的比值，并声明所有耗时都是本机 proxy，只做相对比较。</description></item><item><title>15.1 规格规模的增长</title><link>https://plumephp.com/narr-sys-15-1-spec-scale-growth/</link><pubDate>Fri, 16 Oct 2026 22:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-15-1-spec-scale-growth/</guid><description>把同一份规格沿 flag、好感度、物品、节点四条轴分别放大一档，量 20 层内可达状态数与枚举耗时的增长：flag 18→30 时声明空间上界涨 4096 倍，实测可达只涨 2.096 倍；好感度轴单位倍率最高也只有 1.1285，远低于声明域的 101。给出规模表、增长阶与一张纯 xml.etree 生成的 SVG 曲线。</description></item><item><title>《叙事策划与叙事工艺》卷三《叙事体验与路径度量》· 全书目录与章节索引（50 篇）</title><link>https://plumephp.com/posts/books/%E5%8F%99%E4%BA%8B%E4%BD%93%E9%AA%8C%E4%B8%8E%E8%B7%AF%E5%BE%84%E5%BA%A6%E9%87%8F/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/posts/books/%E5%8F%99%E4%BA%8B%E4%BD%93%E9%AA%8C%E4%B8%8E%E8%B7%AF%E5%BE%84%E5%BA%A6%E9%87%8F/</guid><description>《叙事策划与叙事工艺》卷三《叙事体验与路径度量》全 50 篇，也是三卷本的收官卷。卷一回答「一个故事能不能先被写成一份规格」，卷二回答「这份规格能不能被一台机器确定性地执行」，卷三回答「执行出来的那些路径能不能被度量，而且度量得诚实」。全书围绕虚构的三夜悬疑叙事《雾港夜航》与工具链 inkwell 展开，只读卷二交付的真源与内核、不新造字段：config/story_spec.json 的 beats（16 个节拍与整数张力）与 metrics（目标张力曲线、覆盖率目标 850‰、结局熵下限 1500 毫比特、两个 MAE 阈值）是本卷两个新的度量输入。第一部分（第 1–4 章）做路径、覆盖与平衡：一次通关的轨迹怎么编码成可回放的路径、随机/贪心/穷举三种采样策略、分支覆盖率的千分比口径与缺口定位、结局分布熵与分支偏斜、结局可达性的回归、后果可见性与假选择检测、选择密度与节奏；第二部分（第 5–9 章）做曲线、张力与一致性：张力从哪里来（叙事节拍而非机制动力学）、张力与释放的节拍计算、情感曲线的构造与目标曲线 MAE、代理指标的口径声明、叙事节奏与密度、节奏冲突检测、好感度随路径的变化与阈值触达分布、关系曲线形状分类、一致性残差与设定-行为对齐回归、失调告警阈值；第三部分（第 10–12 章）做可视化、模拟与测试：纯 xml.etree 出张力曲线、分支图与路径热力图、模拟玩家的路径策略与它对分布的影响、W 层 Playwright 路径批跑与断言、从测试到决策；第四部分（第 13–16 章）做反推、演化与收官：曲线异常点定位、参数到曲线的反推与其稳健性、规格演化的影响面与指标回归、叙事质量代理指标总表与「指标不能声称什么」，最后把三卷装配成一份规格三种消费的完整链路。按章节提供仿真、逻辑内核与原型；当前试点阶段已有复核记录，完整项目的配置、共享模块和交付验收仍在补齐。全书数字均来自本机实跑：单条确定性路径覆盖对话边 446‰、覆盖场景 9/14、覆盖节拍 11/16、只到达 1/5 结局，而 BFS 口径下 115 条对话边全部可达（1000‰），可达状态 9895423 个；全部指标均为 proxy，只做相对比较。</description></item><item><title>《叙事策划与叙事工艺》卷三《叙事体验与路径度量》目录</title><link>https://plumephp.com/narr-metric-toc/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-toc/</guid><description>《叙事策划与叙事工艺》卷三《叙事体验与路径度量》目录：16 章 48 节，把玩家路径变成可度量的对象——路径的表示与采样、分支覆盖率与缺口、结局分布熵、张力曲线与 MAE、后果可见性、节奏密度、好感度曲线形状、一致性残差，以及反推与演化回归。本页给出分工说明、六档可运行性口径与全书 16 章 48 节完整清单。</description></item><item><title>1.1 一次通关的轨迹</title><link>https://plumephp.com/narr-metric-01-1-playthrough-trajectory/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-01-1-playthrough-trajectory/</guid><description>一次通关可以被拆成三种表示：玩家按下的选择序列、引擎走出的节点序列、以及每一步之后的完整状态轨迹。本节用《雾港夜航》的首选项确定性策略走完一条 25 步路径，逐步骤打印好感度、置位 flag、持有物品与 FNV-1a 状态摘要，并给出节点数等于选择数加一的整数不变量。</description></item><item><title>1.2 路径的表示与编码</title><link>https://plumephp.com/narr-metric-01-2-path-representation-encoding/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-01-2-path-representation-encoding/</guid><description>同一条路径可以写成三种编码：人可读的规范串、机器可比的紧凑整数元组、以及只对状态算的 FNV-1a 摘要。本节给出三种编码的构造规则，并用 Python 与 TypeScript 两侧对同一条路径算出逐位一致的结果，说明摘要绑定的是编码串而不是文本。</description></item><item><title>1.3 路径的回放与复现</title><link>https://plumephp.com/narr-metric-01-3-path-replay-reproduce/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-01-3-path-replay-reproduce/</guid><description>同一条选择序列推进两次，走出的状态必须逐位一致。本节用三条证据钉死这件事：确定性序列回放两次摘要相同、每个前缀从零重放等于全程记录、500 条采样序列各自回放两次逐条一致，并说明「回放无隐藏状态」到底在保证什么、为什么它是本卷所有度量的前提。</description></item><item><title>10.1 纯 xml.etree 出曲线</title><link>https://plumephp.com/narr-metric-10-1-xml-etree-curve/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-10-1-xml-etree-curve/</guid><description>把前几章算出的张力曲线用纯 xml.etree 手写成 SVG：ET.Element / ET.SubElement 建树、ET.tostring 落盘，再用 ET.fromstring 回读校验合法性并断言元素计数。16 个节拍里一条确定性路径命中 11 个、跳过 5 个，全程整数、无浮点、不依赖任何第三方绘图库。</description></item><item><title>10.2 分支图的可视化</title><link>https://plumephp.com/narr-metric-10-2-branch-graph-visualization/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-10-2-branch-graph-visualization/</guid><description>把 48 个对话节点 / 56 条去重对话边按场景分层画成一张 SVG 分支图，边按是否被一条确定性路径走过着色：走过 25 条（446‰），未走过 31 条；随机采样 200 条即可铺满 56/56。布局坐标由场景序号与场景内序号直接算出，纯 xml.etree 建树、回读校验。</description></item><item><title>10.3 路径热力图</title><link>https://plumephp.com/narr-metric-10-3-path-heatmap/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-10-3-path-heatmap/</guid><description>把 96 条采样路径在各场景上的经过次数画成 14×96 的矩阵热力图，cell 为整数、颜色按整数档位查表（档位定义在 config/nm_10_3_heatmap.json，全程无浮点调色）。矩阵元素之和 2544 恰等于所有路径的节点数之和；按结局排序后同结局的路径聚成一块。</description></item><item><title>11.1 模拟玩家的策略</title><link>https://plumephp.com/narr-metric-11-1-simulated-player-strategy/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-11-1-simulated-player-strategy/</guid><description>给采样装上「策略」这个旋钮：随机（可播种 PRNG 选可用选项）、贪心（总是最大化好感度增量）、覆盖导向（优先走尚未覆盖的边）三种模拟玩家策略，在同一份规格下各走 10 与 200 条路径，对照覆盖率、结局数与路径长度区间。全部指标都是 proxy。</description></item><item><title>11.2 策略对路径分布的影响</title><link>https://plumephp.com/narr-metric-11-2-strategy-effect-on-path-distribution/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-11-2-strategy-effect-on-path-distribution/</guid><description>同一份规格、同一个种子，只换「怎么选」这一条规则：随机、贪心、覆盖导向各跑 5000 条路径，量结局分布、结局分布熵与路径长度分布。实测贪心 5000 条里一次都没走到「真相」，而随机与覆盖导向都到达全部 5 个结局；再把三种策略按 7 档混合比扫描，只有纯贪心丢结局。全部指标都是 proxy。</description></item><item><title>11.3 与玩家动因模型的分工</title><link>https://plumephp.com/narr-metric-11-3-motivation-model-division/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-11-3-motivation-model-division/</guid><description>本章的「模拟玩家」是采样器，不是玩家模型：它只做路径选择策略（随机 / 贪心 / 覆盖导向），不建模动因、不做玩家分型。本节把这条分工写成一份可 lint 的 D 层声明表，再用 S 层脚本做硬断言，并与 11.1、11.2 真跑产物交叉核对，证明声明与脚本做的是同一件事。</description></item><item><title>12.1 目标与假设</title><link>https://plumephp.com/narr-metric-12-1-goal-and-hypothesis/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-12-1-goal-and-hypothesis/</guid><description>一次可玩性测试如果没有假设，就只是点着玩。本节把《雾港夜航》这次测试要验的东西落成四条可证伪的命题——覆盖率、结局覆盖、跨宿主一致、分布熵，每条都给出可测整数、判据与证伪条件，并算出零假设基线 446‰。真人玩家测试需真实业务环境，命令行不可复现，标 X。</description></item><item><title>12.2 W 层路径批跑与断言</title><link>https://plumephp.com/narr-metric-12-2-w-layer-path-batch-run-assert/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-12-2-w-layer-path-batch-run-assert/</guid><description>把规格与内核内联进单文件 HTML，用 Playwright 无头注入 24 条选择序列真玩：逐条断言终局节点、结局与状态摘要与 Python 侧一致，两遍确定性 24/24，覆盖率 982‰，截图与批跑 JSON 落盘。真人玩家测试标 X。</description></item><item><title>12.3 从测试到决策</title><link>https://plumephp.com/narr-metric-12-3-test-to-decision/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-12-3-test-to-decision/</guid><description>假设被证伪之后必须二选一：改规格还是改假设。用样本量扫描 N=24/100/500/2000/8000 诊断 H4（结局分布熵）——熵在 N=100 起越过 1500 毫比特、N≥500 稳定在 1718–1747，判定为测试设计缺陷、改假设而非改规格，story_spec.json 一行不改；真人测试标 X。</description></item><item><title>13.1 曲线的异常点定位</title><link>https://plumephp.com/narr-metric-13-1-curve-anomaly-localization/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-13-1-curve-anomaly-localization/</guid><description>曲线偏离目标时，怎么把它落到具体的节拍下标与场景？本节用残差向量做定位，造三个漂移场景：在路径上的单点、两个异常点，以及离路径的隐藏点。实测发现路径口径看不见没经过的节拍——b10 从 5 降到 4 时路径 MAE 仍为 0 毫，全曲线 MAE 才抬到 62 毫。可观测性决定了可识别性。</description></item><item><title>13.2 参数到曲线的反推</title><link>https://plumephp.com/narr-metric-13-2-parameter-to-curve-inversion/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-13-2-parameter-to-curve-inversion/</guid><description>给定一条目标张力曲线，反过来能求出哪些节拍标注？本节把「MAE 不超阈值」化成 sum 绝对值不超过 16 的整数约束，用逐位 DP 精确计数：达标解集有 6072047140 个，占全空间 5 的 16 次方的 39.8 千分。随机搜索 200000 次的经验命中率与精确比例吻合，而收紧到 62 毫时随机搜索一次都命不中。</description></item><item><title>13.3 反推的稳健性</title><link>https://plumephp.com/narr-metric-13-3-inversion-robustness/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-13-3-inversion-robustness/</guid><description>解集有多大是一回事，稳不稳是另一回事。本节用两条轴量反推的稳健性：把目标曲线的 b10 从 5 挪到 4，在可枚举的预算上精确求新旧解集的交集与 Jaccard 千分；再把 MAE 阈值从 0 毫扫到 2000 毫看解集规模的相变。结论是解集近稳但规模巨大，曲线达标推不出唯一标注。</description></item><item><title>14.1 规格演化的影响面</title><link>https://plumephp.com/narr-metric-14-1-spec-evolution-impact/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-14-1-spec-evolution-impact/</guid><description>改一处规格，哪些路径与指标会变？本节用集合差回答：拿卷二 4.3 的 500 条采样序列当基线，在改动后的规格上重放，逐项量被阻断路径数、终局状态集差、结局集差与边/节点/场景/节拍集差。五处小改动各自给出实测数字，并说明为什么影响面不能靠重跑穷举来算。</description></item><item><title>14.2 路径与指标的回归</title><link>https://plumephp.com/narr-metric-14-2-path-metric-regression/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-14-2-path-metric-regression/</guid><description>上一节算出了影响面，这一节把「改动前 / 改动后」做成一张回归对照表：分支覆盖率、结局分布熵、张力 MAE、一致性残差各一列，增量各一行，并对着写在 metrics 里的声明阈值逐格判越阈。五处改动全是「变了但未越阈」，表同时落成 JSON 与 CSV，供后续每次演化重跑比对。</description></item><item><title>14.3 演化的告警</title><link>https://plumephp.com/narr-metric-14-3-evolution-warning/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-14-3-evolution-warning/</guid><description>指标变了不等于指标变坏了。本节把 14.2 的增量按三级分类：OK（没变）、DRIFT（变了但未越声明阈值）、CROSS（越过阈值才判得动方向）。再以 B 层把两处规格参数连续扫一遍，扫出相变点，全程只发软告警、始终 exit 0——扰动不该让构建硬失败。</description></item><item><title>15.1 指标的定义与口径</title><link>https://plumephp.com/narr-metric-15-1-metric-definition-caliber/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-15-1-metric-definition-caliber/</guid><description>全卷七条代理指标第一次被收成一张总表：分支覆盖率、结局分布熵、张力曲线 MAE、好感度曲线 MAE、一致性残差、节奏密度偏差、整数不变量残差，每条给全定义、量纲、真源字段、实测值与首见小节。脚本从规格重算六条并与各章产物逐条对账，落 out/nm_15_1_metric_catalog.json。</description></item><item><title>15.2 指标的可比性与局限</title><link>https://plumephp.com/narr-metric-15-2-metric-comparability-limitation/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-15-2-metric-comparability-limitation/</guid><description>同一张指标表里的数不能随便比：量纲不同的指标不能相加，七条指标合成不出一个总分；同一份规格加删一条选项，覆盖率就从 446 漂到 438 / 454；熵对样本量敏感，n=50 缺最稀有结局反而算出更高的熵。本节用三个可复现实验把可比性的边界钉死。</description></item><item><title>15.3 指标不能声称什么</title><link>https://plumephp.com/narr-metric-15-3-what-metric-cannot-claim/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-15-3-what-metric-cannot-claim/</guid><description>命令行量不出玩家情绪，本卷七条指标全是 proxy。本节把「不能声称什么」写成可执行的 lint：八类禁声称（更感人、更好玩、玩家满意度、更优秀、玩家实际、读起来、绝对达标、提升 N 倍）、五条正面清单，以及 12 条候选结论的逐条判定与改写。指标能声称的只有相对变化与结构量。</description></item><item><title>16.1 三卷的装配检查表</title><link>https://plumephp.com/narr-metric-16-1-three-volume-assembly-checklist/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-16-1-three-volume-assembly-checklist/</guid><description>三卷共用一份真源。本节把「装起来能不能用」拆成四组共 17 条断言：真源字段齐、卷一结构过、卷二引擎三处消费一致（跨语言锚点摘要 4162796975 逐位相等）、卷三六项代理指标量得出。每条都给出本机实跑值与可重跑命令，任一 FAIL 即非零退出。</description></item><item><title>16.2 三种消费的总联调</title><link>https://plumephp.com/narr-metric-16-2-three-consumption-full-chain-integration/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-16-2-three-consumption-full-chain-integration/</guid><description>让穷举、执行、度量三种消费跑同一份规格并断言彼此不矛盾：BFS 穷举的可达集（9895423 个状态）包含全部采样路径，同一条选择序列在 Python / TS / 浏览器三处推进出逐位相同的状态摘要 4162796975。含 Playwright 无头真玩。</description></item><item><title>16.3 交付与后续</title><link>https://plumephp.com/narr-metric-16-3-deliverable-and-next/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-16-3-deliverable-and-next/</guid><description>本卷交付四类东西：真源与内核、度量工具链（S/P/W/B 共九件脚本）、可复算产物、六项代理指标口径。给出接手五步与「本套不做」清单——真人玩家测试、真实配音成本等需真实业务环境，命令行不可复现，逐处标 X，并列出后续可做的三个方向（多规格回归 / 度量反演 / 真人数据接入）。</description></item><item><title>2.1 采样策略：随机、贪心、穷举</title><link>https://plumephp.com/narr-metric-02-1-sampling-strategy-random-greedy-exhaustive/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-02-1-sampling-strategy-random-greedy-exhaustive/</guid><description>一张 48 节点、115 个选项的故事图，一条确定性路径只走 25 条边（446‰），远低于 850‰ 的目标。本节把随机、贪心、穷举三种采样策略放进同一路径预算对照，量出各自覆盖多少条对话边、到达几个结局，并解释为什么穷举是覆盖率的基准而不是一种采样。</description></item><item><title>2.2 分支覆盖率的度量</title><link>https://plumephp.com/narr-metric-02-2-branch-coverage-metric/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-02-2-branch-coverage-metric/</guid><description>分支覆盖率是一个整数千分比：走过的对话边 × 1000 整除全部对话边。本节先声明两层分母口径（去重边 56 与选项 115），再把单条确定性路径、采样 N 条、BFS 穷举三个来源放进同一张表，量出边、节点、场景三层覆盖，并给出 446‰ 与 1000‰ 的口径来源。</description></item><item><title>2.3 覆盖的缺口与告警</title><link>https://plumephp.com/narr-metric-02-3-coverage-gap-warning/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-02-3-coverage-gap-warning/</guid><description>覆盖率给一个总数，缺口给一张名单。本节对随机采样 N=100 条路径逐边计数，定位那条从未被走过的边——门条件为 bell_rung 的真相结局入口，源节点访问了 100 次却没选中它；再用采样规模与种子的参数扰动给出软告警口径，低于 850‰ 只记 WARN、恒 exit 0。</description></item><item><title>3.1 结局分布的熵</title><link>https://plumephp.com/narr-metric-03-1-ending-distribution-entropy/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-03-1-ending-distribution-entropy/</guid><description>结局熵有四个数，混在一起就错。本节把上界 2321 毫比特、单路径 0 毫比特、路径采样 1714 毫比特、状态枚举 1888 毫比特分开报，并讲清「上界不是实测值」——一条路径只到一个结局，它的熵恒为 0。全部整数、毫比特取整，seed=20261016 可复现。</description></item><item><title>3.2 分支的平衡与偏斜</title><link>https://plumephp.com/narr-metric-03-2-branch-balance-skew/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-03-2-branch-balance-skew/</guid><description>20000 条路径逐边计数，把「分支被走得均不均匀」变成整数：分支覆盖率 1000‰、进入次数中位 4173、偏斜度 gini 373‰、头部集中度 29‰。再用偏置强度 b 从 0 扫到 1000 看相变——覆盖先掉、偏斜先抬、稀有结局先消失，软告警恒 exit 0。</description></item><item><title>3.3 结局可达性的回归</title><link>https://plumephp.com/narr-metric-03-3-ending-reachability-regression/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-03-3-ending-reachability-regression/</guid><description>回归的精确含义是「基线可达、改动后不可达」。本节用 BFS 精确口径枚举基线可达的 5 个结局，掐断真相的唯一入边后静态死条件分析报出回归；再把灯守的阈值门从 0 扫到 101，用 Y*=100 定位它由可达变不可达的临界点，软告警恒 exit 0。</description></item><item><title>4.1 后果可见性</title><link>https://plumephp.com/narr-metric-04-1-consequence-visibility/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-04-1-consequence-visibility/</guid><description>后果可见性量的是：一个选项写下的状态差量，要隔几步才被下游的条件读到。本节把 115 个选项逐个算成整数距离——34 个立即可见、37 个延迟、28 个写进状态却永不被读到，另有 16 个根本没有差量；平均 2.42 步、最远 12 步。全程结构 BFS，不出现浮点，也不预测玩家感受。</description></item><item><title>4.2 假选择的检测</title><link>https://plumephp.com/narr-metric-04-2-fake-choice-detection/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-04-2-fake-choice-detection/</guid><description>两个不同选项在同一状态下推进出的状态逐字段相等，就是一对假选择。本节用完整 BFS 精确枚举 9895423 个可达 (节点,状态) 对，检出 3 对静态假与 10 对状态级假；其中 d_fg_3 的一对在全部 1036900 个可用状态下都相等，静态判据会漏掉它。再用三个合成规格证明检测器会开火。</description></item><item><title>4.3 选择密度与节奏</title><link>https://plumephp.com/narr-metric-04-3-choice-density-rhythm/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-04-3-choice-density-rhythm/</guid><description>选择密度量的是：一条路径上每隔多少节点出现一次有分量的选择。采样 500 条路径实测——选择密度 962 千分，有分量选择占 917 千分，相邻有分量选择的间隔均值 1.094 步、最大 3 步；三幕占比 433 / 296 / 270，第一夜最密。全程定点整数，与第 7 章的节奏度量共用同一套口径。</description></item><item><title>5.1 张力从哪里来：叙事节拍</title><link>https://plumephp.com/narr-metric-05-1-tension-source-narrative-beat/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-05-1-tension-source-narrative-beat/</guid><description>张力在本卷里不是从机制里长出来的，而是作者在规格里标注的：真源的 beats 是 16 个节拍，每个带一个整数 1 到 5 的 tension。本节只读这份标注，不跑任何仿真，就把它按幕切开、算出分布直方图与峰值位置，并给出 beats 字段表与三条整数不变量，全部数字来自本机实跑。</description></item><item><title>5.2 张力与释放的节拍计算</title><link>https://plumephp.com/narr-metric-05-2-tension-release-beat-computation/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-05-2-tension-release-beat-computation/</guid><description>把节拍张力沿一条真实路径串成曲线：走确定性首选项策略，取出路径经过场景上的 11 个节拍，得到张力曲线 1 2 3 2 3 4 4 3 4 4 2，再切出上升段、平台段与回落段，定位峰值与谷值，并算它与目标曲线的 MAE。本节如实说明：当前规格下 MAE 恒为 0，因为标注与目标逐项相同。</description></item><item><title>8.1 好感度随路径的变化</title><link>https://plumephp.com/narr-metric-08-1-affinity-curve-over-path/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-08-1-affinity-curve-over-path/</guid><description>好感度不是一局战斗里的数值，而是沿玩家路径推进的整数序列。本节沿一条确定性路径把 4 个变量 yan/hui/shen/mu 的曲线画出来：起点值、增量点、峰值、终点值，再采样 2000 条路径给出终点值分布。实测确定性路径上 yan 从 20 升到 65、升了 5 次，shen 全程停在 50；终点均值显示单条路径只是分布里的一个样本。</description></item><item><title>8.2 阈值触达的分布</title><link>https://plumephp.com/narr-metric-08-2-threshold-hit-distribution/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-08-2-threshold-hit-distribution/</guid><description>把 14 道好感度阈值门（13 条选项门 + 1 条结局门）抽平，定义路径触达为「变量沿路径最大值 &gt;= 门限」。实测 5000 条采样路径里 18 条（3‰）从未触达任何门，yan&gt;=25 的触达率最高 858‰。B 层把每道门限 ±10 后重走路径：14 道门全部改变了触达率，只打印软告警、exit 0。</description></item><item><title>9.1 一致性残差的度量</title><link>https://plumephp.com/narr-metric-09-1-consistency-residual-metric/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-09-1-consistency-residual-metric/</guid><description>把「声明」与「行为」对齐后统计失配计数：声明来自角色的 affinity / secret、派系 stance 与规则，行为来自选项的 when / effects 与采样路径。本节把一致性残差量成四个整数——声明域 D、秘密 K、立场 S、规则 R，并沿 2000 条路径量路径实现率，全部显式声明为 proxy。</description></item><item><title>9.2 设定-行为对齐的回归</title><link>https://plumephp.com/narr-metric-09-2-setting-behavior-alignment-regression/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-09-2-setting-behavior-alignment-regression/</guid><description>一致性残差只有能在规格改动后朝正确方向移动，才是可用的回归信号。本节在内存克隆上做七种规格变异——补声明域、给秘密与禁则加门、清掉立场提供者，以及一次故意的回归——把残差重算成一张回归表，再用修复阶梯与信任门两条扫描检查单调性。残差全部是代理指标，只做相对比较。</description></item><item><title>9.3 失调的告警阈值</title><link>https://plumephp.com/narr-metric-09-3-dissonance-warning-threshold/</link><pubDate>Fri, 16 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/narr-metric-09-3-dissonance-warning-threshold/</guid><description>残差算出来了，可超过多少才算告警？本节把阈值写成一条显式策略：先算声明基数当分母，取它的四分之一作默认阈值，再把上一节的七种规格变异逐个判定；最后扫描阈值的取值区间，看清阈值过紧与过松各自把告警变成什么样。残差与残差率全部是代理指标，只做相对比较。</description></item><item><title>11.3 快照的向前兼容</title><link>https://plumephp.com/narr-sys-11-3-snapshot-forward-compatibility/</link><pubDate>Fri, 16 Oct 2026 15:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-11-3-snapshot-forward-compatibility/</guid><description>规格演化后（新增 flag、新增物品、新增好感度变量、新增节点），旧存档必须仍能读。本节实跑兼容性矩阵：四种新规格下旧存档全部读入成功并给出补默认值规则；迁移函数三条判据——缺失字段补默认、多余字段丢弃并报告、类型不符拒绝——逐条在本机实跑验证。</description></item><item><title>《叙事策划与叙事工艺》卷二《叙事引擎与分支系统》· 全书目录与章节索引（50 篇）</title><link>https://plumephp.com/posts/books/%E5%8F%99%E4%BA%8B%E5%BC%95%E6%93%8E%E4%B8%8E%E5%88%86%E6%94%AF%E7%B3%BB%E7%BB%9F/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/posts/books/%E5%8F%99%E4%BA%8B%E5%BC%95%E6%93%8E%E4%B8%8E%E5%88%86%E6%94%AF%E7%B3%BB%E7%BB%9F/</guid><description>《叙事策划与叙事工艺》卷二《叙事引擎与分支系统》全 50 篇。卷一回答「一个故事能不能先被写成一份规格」，卷二回答「这份规格能不能被一台机器可复现地、可断言地、可跨语言地执行」。全书围绕虚构的三夜悬疑叙事《雾港夜航》与工具链 inkwell 展开，唯一真源仍是 config/story_spec.json 的十段字段：meta（三幕）、world（4 派系 stance 矩阵、14 个地点的解锁条件、6 条 lore 的揭示旗标）、characters（6 个角色的目标/恐惧/秘密/好感度/弧光）、beats（16 个节拍与整数张力）、scene_graph（14 个节点与 16 条边，其中 5 条带条件）、dialogue（48 个对话节点、115 个选项、5 个结局）、conditions（嵌套数组文法，6 种形式）、state（18 个 flag、4 个好感度、9 个物品）、endings 与 metrics。第一部分（第 1–4 章）搭引擎内核：状态/事件/转移的三元组、规格驱动的对话状态机、引擎与规格的同源、条件求值器与短路、可满足性判定、效果应用、确定性与 set 类幂等、状态快照与差量、确定性回放与逐位一致；第二部分（第 5–8 章）算分支状态空间：990 万可达状态的 BFS 枚举、不可达节点与孤儿结局、死路检测与汇流合法性、结局可达性、分支宽度与采样上界、组合爆炸的控制、好感度状态机与阈值门扰动、整数不变量；第三部分（第 9–12 章）做可玩原型与持久化：把规格内联进单文件 HTML、选择界面与状态显示、Playwright 注入选择序列真玩、断言终局状态与结局、多路径批跑、存档序列化与读档恢复、快照向前兼容、文本表与键的一致性；第四部分（第 13–16 章）做一致、回归与装配：跨语言摘要与 digest、同源不同宿主、偏差与容差、属性测试与随机路径模糊、规模与性能扫描，最后装配成一份规格三处消费的完整链路并交付卷三。按章节提供仿真、逻辑内核与原型；当前试点阶段已有复核记录，完整项目的配置、共享模块和交付验收仍在补齐。全书数字均来自本机实跑：可达状态 9895423 个，分支覆盖率 1000‰，死路节点 0，跨语言摘要 500/500 一致，同输入确定性违例 0。</description></item><item><title>《叙事策划与叙事工艺》卷二《叙事引擎与分支系统》目录</title><link>https://plumephp.com/narr-sys-toc/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-toc/</guid><description>《叙事策划与叙事工艺》卷二《叙事引擎与分支系统》目录：16 章 48 节，把 story_spec.json 变成可执行的对话状态机——条件求值、效果应用、确定性回放、状态空间穷举、可玩原型与跨语言摘要。本页给出分工说明、六档可运行性口径与全书 16 章 48 节完整清单。</description></item><item><title>1.1 状态、事件、转移</title><link>https://plumephp.com/narr-sys-01-1-state-event-transition/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-01-1-state-event-transition/</guid><description>叙事引擎可以被抽象成一个三元组：状态（节点、好感度、flag、物品、路径）、事件（一次选项点击）、转移（纯函数 step）。本节把《雾港夜航》的引擎压到这三个词上，并用一份 S 层脚本打印一条 25 步路径的逐步骤状态轨迹与每一步之后的 FNV-1a 摘要。</description></item><item><title>1.2 规格驱动的对话状态机</title><link>https://plumephp.com/narr-sys-01-2-spec-driven-dialogue-state-machine/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-01-2-spec-driven-dialogue-state-machine/</guid><description>规格驱动的意思是引擎里没有一条硬编码剧情：可用的选项来自 dialogue 的 choices 加 when 求值，状态推进来自 state 的四个效果算子，终局来自 endings 的 when 判定。本节用一份 TypeScript 模块与四条断言证明这台状态机的全部行为都由 spec 的三段决定。</description></item><item><title>1.3 引擎与规格的同源</title><link>https://plumephp.com/narr-sys-01-3-engine-spec-same-origin/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-01-3-engine-spec-same-origin/</guid><description>同源的意思是同一份规格在 Python 与 TypeScript 两侧推进同一选择序列，整数状态摘要逐位相同。本节用四种确定性策略各走一条路径：Python 侧落出四条路径的选择序列与 FNV-1a 摘要，TypeScript 侧读回产物原样重放，断言规范串与摘要两侧完全一致。</description></item><item><title>10.1 注入选择序列真玩</title><link>https://plumephp.com/narr-sys-10-1-playwright-inject-choice-path/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-10-1-playwright-inject-choice-path/</guid><description>用 Playwright 无头打开 web/dist/ne10.html，靠 data-choice-id 选择器契约注入一条 25 步的完整选择序列真玩一遍：逐步记录节点 id 与当前好感度读数，并断言每一步注入的选项都落在规格该节点的可用集合里，终局摘要 4162796975。</description></item><item><title>10.2 断言终局状态与结局</title><link>https://plumephp.com/narr-sys-10-2-assert-final-state-ending/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-10-2-assert-final-state-ending/</guid><description>把 25 步序列走完后的终局状态读回来断言四件事：终局节点 e_lit、结局 灯守、终局摘要 4162796975（与 Python 与 TS 侧逐位一致）、同一序列跑两遍摘要不变；再截图到 out/shots/ 并给出 PNG 字节数。只对整数状态写逐位一致。</description></item><item><title>10.3 多路径批跑</title><link>https://plumephp.com/narr-sys-10-3-multi-path-batch-run/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-10-3-multi-path-batch-run/</guid><description>用固定种子采样 20 条路径，逐条把选择序列注入页面，断言终局节点、结局与状态摘要与 Python 侧一致，批跑通过 20/20、覆盖 4 种结局。失败时原样打印选择序列便于重放；S 层落成 JSON，P 层 core/test 回放对照。</description></item><item><title>11.1 存档的序列化</title><link>https://plumephp.com/narr-sys-11-1-save-serialization/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-11-1-save-serialization/</guid><description>存档是状态的规范序序列化：键按字典序、值全是整数、无浮点、无时间戳、无随机。本节把一条 25 步路径的终局状态写成 795 字节的存档 JSON，验证字段与 canonical 串一一对应，并让序列化到反序列化再序列化两次字节完全相同；同时点明临时 UI 状态、派生量、绝对时间不能进存档。</description></item><item><title>11.2 读档与状态恢复</title><link>https://plumephp.com/narr-sys-11-2-load-state-restore/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-11-2-load-state-restore/</guid><description>读档后从存档点继续推进，必须与从头一次走完得到逐位相同的终局状态。本节沿 25 步路径在第 1、5、10、15、20、25 步分别存档读档，终局规范串全部相同；并给出负例：把存档里的好感度篡改成 999，宽松读档钳位到 100 并记录修复，严格读档直接拒绝，检测器抓得到。</description></item><item><title>12.1 文本表与键</title><link>https://plumephp.com/narr-sys-12-1-text-table-and-key/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-12-1-text-table-and-key/</guid><description>文本是规格的一种渲染产物，而键是文本表与规格之间唯一的连接点。本节从 dialogue 段抽出全部文本键——48 条 line、1 条 else、115 条选项文本，共 164 键——给出键命名规则与漏键 / 悬空键检测，并各给一条负例。只做文本的结构一致性，不评价译文质量。</description></item><item><title>12.2 变体与复数</title><link>https://plumephp.com/narr-sys-12-2-variant-and-plural/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-12-2-variant-and-plural/</guid><description>同一条键在不同状态下要渲染不同文本，这是条件变体；同一句话在不同数量下要选不同形式，这是复数。本节给出 2 个带条件变体节点的覆盖矩阵（1 完整、1 欠声明），并给出 zh-CN 与 en-US 的最小复数规则对照——中文退化为单类，复数只在对照语言上有意义。</description></item><item><title>12.3 文本的一致性校验</title><link>https://plumephp.com/narr-sys-12-3-text-consistency-validation/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-12-3-text-consistency-validation/</guid><description>四类文本一致性校验一次算齐：漏键、悬空键、变体覆盖、占位符。前两类残差为 0；变体覆盖报出 d_lt_2 欠声明（有 line_when 无 line_else，按规则回落，只报不判失败）；占位符残差 0，并给一条负例。本章只做结构一致性，译文质量与字体覆盖需真实业务环境，命令行不可复现。</description></item><item><title>13.1 跨语言摘要与 digest</title><link>https://plumephp.com/narr-sys-13-1-cross-language-digest/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-13-1-cross-language-digest/</guid><description>摘要用 FNV-1a 32 位，只对 canonical 规范串（状态）做，不对台词文本做。本节实测同一批 500 条路径（seed=20261016）在 Python 与 TypeScript 两侧逐位相同 500 / 500，前 3 条摘要为 3976226298、3848604931、1198029437，并与卷一同种子采样逐位相同，证明卷二未另立真源。</description></item><item><title>13.2 同源不同宿主</title><link>https://plumephp.com/narr-sys-13-2-same-origin-different-host/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-13-2-same-origin-different-host/</guid><description>同一条确定性策略路径（总是选第一个可用选项，25 个事件）在 Python、Node 内核与浏览器内联三个宿主上推进，终局节点 e_lit、结局 灯守、FNV-1a 摘要 4162796975 三侧逐位相同。本节给出宿主差异清单：整数运算、取模、Math.imul 与大整数、对象键序、Unicode 归一化，逐条说明为何不影响状态摘要。</description></item><item><title>13.3 偏差与容差</title><link>https://plumephp.com/narr-sys-13-3-deviation-tolerance/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-13-3-deviation-tolerance/</guid><description>什么必须逐位相同、什么允许不同，本节写成一张容差表：整数状态（好感度、flag、item、节点 id、路径）必须逐位；浮点派生量、对象键序、文本渲染、时间戳允许不同。负例把好感度钳位上限从 100 改成 99，实测 12 / 500 条路径摘要改变，首个分歧点定位到路径 #13 第 20 步 c_fg_1a 的 shen。</description></item><item><title>14.1 属性测试与不变量</title><link>https://plumephp.com/narr-sys-14-1-property-test-invariant/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-14-1-property-test-invariant/</guid><description>属性测试不问「跑一遍对不对」，而问「一条命题是否对所有输入都成立」。本节把第 3 / 6 / 8 章的不变量写成六条属性：好感度恒在 [0,100]、set 类算子幂等、add 故意不幂等、静态死路 0、5 个结局全可达、每状态至少一个可用选项，并给每条属性配一个必须 fail 的注入式负例。</description></item><item><title>14.2 随机路径的模糊测试</title><link>https://plumephp.com/narr-sys-14-2-random-path-fuzz/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-14-2-random-path-fuzz/</guid><description>把随机路径当模糊测试的输入：用自实现可播种 PRNG 跑 20000 条路径，断言全部终止于 5 个结局之一、无卡死、无越界。实测分布为离港 10074、沉没 5507、缄默 3223、灯守 1018、真相 178，最稀有的真相仅 178 条。Python 与 TypeScript 两侧对同一批路径的终局状态摘要逐位一致。</description></item><item><title>14.3 回归与告警</title><link>https://plumephp.com/narr-sys-14-3-regression-and-warning/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-14-3-regression-and-warning/</guid><description>把基线摘要、结局分布、整数不变量残差落成回归基线文件，规格每改一次就重跑比对。本节给三类告警：摘要失配、分布漂移、残差非零，各配一个内存内注入负例，实测三组全部触发。告警只打印 WARN 并 exit 0，与 B 层口径一致；而负例测试必须硬失败。</description></item><item><title>16.1 引擎的装配检查表</title><link>https://plumephp.com/narr-sys-16-1-engine-assembly-checklist/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-16-1-engine-assembly-checklist/</guid><description>装配检查表把本卷十五节交付的零件收成十二项可断言的检查：规格可解析、引用完整、写入域合法、整数不变量残差 0、规模对账、BFS 与基线一致、goto 全部存在、结局全部可达、跨语言锚点一致、W 层零外部依赖、覆盖率达目标、无卡死路径。S 层脚本逐项跑出 PASS/FAIL 表，任一项 FAIL 即非零退出。</description></item><item><title>16.2 三处消费的联调</title><link>https://plumephp.com/narr-sys-16-2-three-consumption-integration/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-16-2-three-consumption-integration/</guid><description>把同一份规格上的三处消费串成一次联调：穷举给出完整可达状态数与结局分布，执行让确定性策略 first 走到底并算出整数摘要 4162796975，度量给出覆盖率与张力曲线残差。P 层用 TypeScript 内核重放同一条路径，摘要与 S 层逐位相同，验证引擎与规格同源。</description></item><item><title>2.1 条件表达式的求值器</title><link>https://plumephp.com/narr-sys-02-1-condition-expression-evaluator/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-02-1-condition-expression-evaluator/</guid><description>条件在规格里是嵌套数组写成的表达式树，求值器就是把它递归地读成真假。本节给出六种形态的求值语义，用 Python 与 TypeScript 两条链把 story_spec.json 里 57 个条件位点全部求值一遍，并把声明域与使用域分开数：声明 6 种形态只用 5 种，声明 4 个比较算子只用 &gt;= 一种。</description></item><item><title>2.2 短路与复杂度</title><link>https://plumephp.com/narr-sys-02-2-short-circuit-complexity/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-02-2-short-circuit-complexity/</guid><description>短路是求值器的一条优化纪律：and 左假即停、or 左真即停，但它绝不能改变结果。本节给出短路与不短路两种实现的节点访问步数对照——本规格 57 个位点在 16 个代表状态下 eager 1008 步、短路 992 步——并声明复杂度上界：树内 n 个节点时短路步数恒不超过 n。</description></item><item><title>2.3 条件的可满足性</title><link>https://plumephp.com/narr-sys-02-3-condition-satisfiability/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-02-3-condition-satisfiability/</guid><description>可满足性问的是：一个条件在有限状态域里到底有没有解，会不会恒假。本节用边界值枚举在「节点 × 4 个好感度 × 18 个 flag × 9 个物品」上判定，57 个条件位点里死条件 0 个；并处理一处真实特征——lin 与 hai 声明了好感度却不在状态域里，任何门限都结构性不可达。</description></item><item><title>3.1 效果的应用</title><link>https://plumephp.com/narr-sys-03-1-effect-application/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-03-1-effect-application/</guid><description>效果算子只有四个，每个只写一个命名空间：set 写 flag、add 写好感度、grant 与 revoke 写物品。本节把全规格 138 次写入摊平数一遍，校验写入域越界 0，并点出声明了却一次未用的 revoke；P 层用同一批选项断言命名空间互斥，并以把 add 放大到百万级仍被钳回证明钳位确实生效。</description></item><item><title>3.2 确定性与幂等</title><link>https://plumephp.com/narr-sys-03-2-determinism-idempotence/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-03-2-determinism-idempotence/</guid><description>确定性是同一输入同一输出，幂等是重复应用结果不变，两者常被混为一谈。本节把状态推进拆成三条可断言判据：函数性、set 类算子幂等、add 故意不幂等，并说明全书那句「同输入确定性违例 0」指的是同一状态到同一后继状态，而不是「重复 add 不累加」。</description></item><item><title>3.3 状态快照与差量</title><link>https://plumephp.com/narr-sys-03-3-state-snapshot-delta/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-03-3-state-snapshot-delta/</guid><description>快照是某一刻的完整状态，差量是相邻两快照间真正改变的字段。本节沿一条 25 步的确定性路径输出逐步骤差量表，并点出 7 个 flag 与 1 个物品被写却从未被任何条件读取——这类「只增不减的信息」按声明未用=报告处理，不判 FAIL，只如实报出。</description></item><item><title>4.1 选择序列与路径</title><link>https://plumephp.com/narr-sys-04-1-choice-sequence-and-path/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-04-1-choice-sequence-and-path/</guid><description>选择序列是玩家按下的一串 choice_id，路径是引擎走出来的 node_id 序列。本节用同一趟推进给出双表示对照，实测 115 条选项去重后只有 56 条唯一跳转，因此选项数并不等于路径形状数，并用 Kahn 拓扑排序证明 48 个对话节点构成一张无环 DAG。</description></item><item><title>4.2 同种子同回放</title><link>https://plumephp.com/narr-sys-04-2-same-seed-same-replay/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-04-2-same-seed-same-replay/</guid><description>随机路径采样只用自实现的 Lehmer MINSTD，种子一固定，回放就必然复现。本节实测同一 (seed=20261016, n=500) 采样两次 500 条选择序列逐条相同，而换到 seed=20261017 后逐条相同数为 0、结局分布也整体改变。</description></item><item><title>4.3 回放的逐位一致</title><link>https://plumephp.com/narr-sys-04-3-replay-bitwise-identity/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-04-3-replay-bitwise-identity/</guid><description>对同一串选择序列，Python 与 TypeScript 各自推进一遍，比较 canonical 串与 FNV-1a 32 位摘要。本节实测 500 条路径全部逐位相同，并给出前 3 条摘要值对照表；FNV-1a 的 Math.imul 与 Python 的 &amp; 0xFFFFFFFF 是两侧一致的关键。</description></item><item><title>5.1 状态空间的规模</title><link>https://plumephp.com/narr-sys-05-1-state-space-scale/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-05-1-state-space-scale/</guid><description>一个状态等于节点乘以 4 个好感度、18 个 flag、9 个物品。本节先算出朴素上界 48 × 101 的四次方 × 2 的 18 次方 × 2 的 9 次方约 6.70×10 的 17 次方，再用 BFS 完整枚举跑出真实可达的 9895423 个状态，并把两者相差约 11 个数量级的来源拆成好感度值域、flag 与物品位图、变量相关性三层。</description></item><item><title>5.2 可达状态的枚举</title><link>https://plumephp.com/narr-sys-05-2-reachable-state-enumeration/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-05-2-reachable-state-enumeration/</guid><description>逐层 BFS 把 9895423 个可达状态一层层展开：给出每一层的新增与累计、峰值 frontier，以及 4 个好感度变量的实际值域。去重键是状态的规范串，层号就是最短步数。本节贴出 32 层完整输出，并给出预算 12000000 与峰值内存 3132.8 MB 的口径。</description></item><item><title>5.3 不可达节点与孤儿结局</title><link>https://plumephp.com/narr-sys-05-3-unreachable-node-orphan-ending/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-05-3-unreachable-node-orphan-ending/</guid><description>把「不可达」拆成两种口径：节点不可达（BFS 从未落到它）与选项不可达（它的 when 在任何可达状态下都不成立）。实测两者都是 0，5 个结局全部可达、孤儿结局 0、分支覆盖率 1000‰。另报告规格层面的一处欠声明：节点 d_lt_2 声明了 line_when 却没有 line_else。</description></item><item><title>6.1 死路检测</title><link>https://plumephp.com/narr-sys-06-1-dead-end-detection/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-06-1-dead-end-detection/</guid><description>死路是一个节点在当前状态下没有任何可用选项、且不是结局节点，玩家就卡死了。本节把静态死路与动态死路分开查：静态 0 个；动态用投影状态上的完整 BFS 与 20000 条采样，实测卡死 0 条。再用三组注入负例证明检测器确实会开火，而不是一个永远返回空的摆设。</description></item><item><title>6.2 汇流的合法性</title><link>https://plumephp.com/narr-sys-06-2-merge-legality/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-06-2-merge-legality/</guid><description>汇聚本身不是缺陷——115 条选项去重后只剩 56 条唯一跳转。真正的非法汇流是汇聚之后状态不可区分：两条不同入边到达同一节点后，下游全部条件的求值完全一致，信息被丢弃。本节给出可判定口径 D(M)，实测 34 个汇聚节点里 22 个冗余、3 个跨源冗余，并用合成规格负例证明检测器会开火。</description></item><item><title>6.3 结局的可达性</title><link>https://plumephp.com/narr-sys-06-3-ending-reachability/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-06-3-ending-reachability/</guid><description>5 个结局（灯守 / 离港 / 真相 / 缄默 / 沉没）全部可达，但可达不等于易达。本节为每个结局给出一条真实可回放的到达路径，再用 20000 条均匀随机采样算分布：离港 10074、沉没 5507、缄默 3223、灯守 1018、真相仅 178。并厘清 endings 的 id 与 dialogue 的 ending 两个口径。</description></item><item><title>7.1 分支宽度的度量</title><link>https://plumephp.com/narr-sys-07-1-branch-width-metric/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-07-1-branch-width-metric/</guid><description>宽度就是一个节点的出度：同时摆在玩家面前的选项数。本节给 48 个对话节点量出度，实测直方图是 5 个 0 出度、16 个 2 出度、26 个 3 出度、1 个 5 出度，最宽的一步是 d_dq_2 的 5 个选项；再按边距离分 23 层看每层宽度，并把 115 个选项去重成 56 条唯一跳转、47 个不同目标。</description></item><item><title>7.2 剪枝与采样上界</title><link>https://plumephp.com/narr-sys-07-2-pruning-sampling-bound/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-07-2-pruning-sampling-bound/</guid><description>路径数有两层上界：朴素乘积上界 5 的 31 次方约 4.66×10 的 21 次方，真实结构路径数 450208471680，剪枝后 BFS 可达边 115/115 即 1000‰。本节推导优惠券收集器的采样上界（覆盖 115 条边约 613 条路径），并实测随机与贪心两种策略在 N=100/1000/10000/20000 下的覆盖率收敛曲线。</description></item><item><title>7.3 组合爆炸的控制</title><link>https://plumephp.com/narr-sys-07-3-combinatorial-explosion-control/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-07-3-combinatorial-explosion-control/</guid><description>把分支宽度与深度当两条扰动轴：宽度因子 k 把每个有选项节点的出度乘以 2、3、4，路径数从约 4.50×10 的 11 次方一路涨到 10 的 30 次方量级，而去重跳转覆盖率始终 1000‰ 纹丝不动；深度预算 L 把探索限制在 L 步内，可达覆盖率随 L 上升、在 L=22 触顶。B 层只打印软告警，恒 exit 0。</description></item><item><title>8.1 好感度的状态机</title><link>https://plumephp.com/narr-sys-08-1-affinity-state-machine/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-08-1-affinity-state-machine/</guid><description>好感度是一台受钳位约束的整数状态机：状态 = 节点 + 4 个好感度整数 + 18 个 flag + 9 个物品。本节把《雾港夜航》的完整状态空间 BFS 一遍，实测四个变量的可达值域分别是 yan 21、hui 35、shen 12、mu 16，值域之积 141120，而真正可达的好感度四元组只有 87190——四个变量之间并不独立。P 层用同一批选项断言初值来源、add 累加与钳位。</description></item><item><title>8.2 阈值门与门限扰动</title><link>https://plumephp.com/narr-sys-08-2-threshold-gate-perturbation/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-08-2-threshold-gate-perturbation/</guid><description>好感度的分段在规格里就是一串 [aff, 名, &gt;=, 整数] 阈值门，长在选项 when、节点 line_when、结局 when 三处。本节把 15 条门限全抽出来，再逐条扰动 ±5，在同一采样口径下重算覆盖率与可达结局集合，找出 4 条临界门限；并如实说明为什么放宽 5 点不起作用而收紧 5 点才起作用——基线覆盖率已饱和在 1000‰。B 层只打印 WARN，退出码 0。</description></item><item><title>8.3 好感度的不变量</title><link>https://plumephp.com/narr-sys-08-3-affinity-invariant/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-08-3-affinity-invariant/</guid><description>四条必须恒为 0 的残差：钳位（可达状态与转移后都在 [0,100] 内）、初值（每个声明角色的 init 落在自身 range 内）、累积口径（新值恒等于 clamp(旧值 + add)，set 不写好感度）、门限可达性（15 条门限均可跨过）。四条残差合计 0；lin 与 hai 有 affinity 声明却不在 state.vars，按「声明未用=报告，用了未声明=FAIL」报告。</description></item><item><title>9.1 规格内联进单文件 HTML</title><link>https://plumephp.com/narr-sys-09-1-spec-inline-single-file-html/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-09-1-spec-inline-single-file-html/</guid><description>把 config/story_spec.json 与 core/src/inkwell/engine.ts 一起内联进一个单文件 HTML，产出 web/dist/ne09.html。本节实测产物 41641 字节、script src 0、外部 http(s) 链接 0，给出零外部依赖的自检口径与双击即玩的最小交付形态。</description></item><item><title>9.2 选择界面与状态显示</title><link>https://plumephp.com/narr-sys-09-2-choice-ui-state-display/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-09-2-choice-ui-state-display/</guid><description>给可玩原型挂一套稳定的 data-* 选择器契约：当前节点、每个选择按钮、四个好感度、已置位 flag、持有物品各有一个可寻址的属性。再用 Playwright 无头打开这页单文件 HTML，断言 DOM 已绘制、按钮数等于当前可用选项数、点击后节点推进。</description></item><item><title>9.3 原型与内核的同源</title><link>https://plumephp.com/narr-sys-09-3-prototype-kernel-same-origin/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-09-3-prototype-kernel-same-origin/</guid><description>浏览器里走完同一条确定性策略路径（总是选第一个可用选项，共 25 个事件），读出终局状态，与 Python 侧产物比对 canonical 串与 FNV-1a 摘要。三侧锚点一致：摘要 4162796975、节点 e_lit、结局 灯守。只对整数状态写逐位一致。</description></item><item><title>附录 A 对话树格式、条件文法与数据集索引</title><link>https://plumephp.com/narr-sys-appendix-a/</link><pubDate>Fri, 16 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/narr-sys-appendix-a/</guid><description>《叙事策划与叙事工艺》卷二《叙事引擎与分支系统》附录 A：把全卷 16 章 48 节散落的对话树节点与选项字段、嵌套数组条件文法与四类效果算子汇成索引表，给出本卷 S/P/W/D 四层共 43 个仿真脚本、31 个内核模块与 37 份产物的实盘清点，并附一段可跑的 TypeScript 对话树格式检查器——它连同三个注入负例证明格式约定不是纸面条文。</description></item><item><title>《叙事策划与叙事工艺》卷一《叙事结构与可执行规格》· 全书目录与章节索引（50 篇）</title><link>https://plumephp.com/posts/books/%E5%8F%99%E4%BA%8B%E7%BB%93%E6%9E%84%E4%B8%8E%E5%8F%AF%E6%89%A7%E8%A1%8C%E8%A7%84%E6%A0%BC/</link><pubDate>Fri, 16 Oct 2026 10:00:00 +0800</pubDate><guid>https://plumephp.com/posts/books/%E5%8F%99%E4%BA%8B%E7%BB%93%E6%9E%84%E4%B8%8E%E5%8F%AF%E6%89%A7%E8%A1%8C%E8%A7%84%E6%A0%BC/</guid><description>《叙事策划与叙事工艺》卷一《叙事结构与可执行规格》全 50 篇。它回答一个问题：一个故事能不能先被写成一份规格，再让台词文本成为这份规格的渲染产物？全书围绕虚构的三夜悬疑叙事《雾港夜航》与工具链 inkwell 展开，唯一真源是 config/story_spec.json 的十段字段：meta（三幕）、world（4 派系 stance 矩阵、14 个地点的解锁条件、6 条 lore 的揭示旗标）、characters（6 个角色的目标/恐惧/秘密/好感度/弧光）、beats（16 个节拍与整数张力）、scene_graph（14 个节点与 16 条边，其中 5 条带条件）、dialogue（48 个对话节点、115 个选项、5 个结局）、conditions（嵌套数组文法，6 种形式）、state（18 个 flag、4 个好感度、9 个物品）、endings 与 metrics。第一部分（第 1–4 章）把故事还原成结构：四个最小构成、九段骨架、文本是渲染的分工、字段全表与版本迁移、世界观与角色的形式化；第二部分（第 5–8 章）把结构还原成图与曲线：弧光的可达性、节拍与三种结构模型、场景图的可达性与解锁、分支拓扑与假选择判定；第三部分（第 9–12 章）把条件与数值写透：条件文法与写入域、状态变量的闭包检验、好感度阈值门与曲线形状、对话树的遍历与校验、文本模板与条件变体；第四部分（第 13–16 章）做校验与装配：结构/语义/一致性三层校验、叙事失调的形式化、工具链的目录分工与流水线，最后装配成一份规格三处消费的完整链路并交付卷二。按章节提供仿真、逻辑内核与原型；当前试点阶段已有复核记录，完整项目的配置、共享模块和交付验收仍在补齐。全书数字均来自本机实跑：可达状态 9895423 个，分支覆盖率 1000‰，不可达节点与不可达选项均为 0。</description></item><item><title>《叙事策划与叙事工艺》卷一《叙事结构与可执行规格》目录</title><link>https://plumephp.com/narr-arch-toc/</link><pubDate>Fri, 16 Oct 2026 10:00:00 +0800</pubDate><guid>https://plumephp.com/narr-arch-toc/</guid><description>《叙事策划与叙事工艺》卷一《叙事结构与可执行规格》目录：16 章 48 节，把一个故事写成可执行规格 story_spec.json，让同一份规格被 S 层穷举、P 层确定性内核与 B 层参数扰动三处消费，产出逐位一致的状态摘要。本页给出七处分工说明、六档可运行性口径、《雾港夜航》规格总览与全书 16 章 48 节完整清单。</description></item><item><title>1.3 文本是渲染：规格与文本的分工</title><link>https://plumephp.com/narr-arch-01-3-text-as-rendering-spec-text-division/</link><pubDate>Fri, 16 Oct 2026 10:00:00 +0800</pubDate><guid>https://plumephp.com/narr-arch-01-3-text-as-rendering-spec-text-division/</guid><description>本套的核心主张：台词文本不是规格的输入端，而是规格的一种渲染产物。同一条 dialogue 记录（line 加 line_when 加 line_else）在不同状态下渲染出不同台词。本节给出四分支渲染规则、用 d_tc_2 做最小演示、反向断言文本不进状态，并写死边界——只做文本的结构，不评价文本质量。</description></item><item><title>10.1 好感度的初始化与增减</title><link>https://plumephp.com/narr-arch-10-1-affinity-init-delta/</link><pubDate>Fri, 16 Oct 2026 10:00:00 +0800</pubDate><guid>https://plumephp.com/narr-arch-10-1-affinity-init-delta/</guid><description>好感度只有两个动作：从 characters[].affinity.init 起一个整数，之后每次写入都走 add 再夹回 [0,100]。S 层静态清点出 4 个变量共 66 次写入、8 种增量，并点出声明了却从不推进的 lin 与 hai；P 层用 300 条采样路径断言值域恒定，并以「把某个 add 放大到百万级仍被夹回」的负例证明 clamp 不是冗余算子。</description></item><item><title>10.2 阈值门</title><link>https://plumephp.com/narr-arch-10-2-threshold-gate/</link><pubDate>Fri, 16 Oct 2026 10:00:00 +0800</pubDate><guid>https://plumephp.com/narr-arch-10-2-threshold-gate/</guid><description>阈值门就是条件里的 ['aff', 名, '&gt;=', 整数]：它可能长在选项的 when、节点的 line_when 或结局的 when 上。S 层把全规格 15 条门限抽成一张表，在 20000 条采样路径上给出每条门限的跨越率、最高到达与缺口，基线 0 条死门；P 层断言门限未达时选项不可选、恰好达到时可选的边界行为。</description></item><item><title>10.3 好感度曲线的形状</title><link>https://plumephp.com/narr-arch-10-3-affinity-curve-shape/</link><pubDate>Fri, 16 Oct 2026 10:00:00 +0800</pubDate><guid>https://plumephp.com/narr-arch-10-3-affinity-curve-shape/</guid><description>把好感度沿采样路径画成曲线后，「形状」也成了一个可分类的量：单调上升 / 先升后平 / 单调下降 / 波动 / 全程不变，五类互斥。S 层统计 2000 条路径的形状占比并用纯 xml.etree 出图，B 层把初始值整体上下扰动 ±10，观察门限跨越率的相变——−10 档新增 9 条死门，全程只软告警不硬失败。</description></item><item><title>11.1 对话节点、选项与跳转</title><link>https://plumephp.com/narr-arch-11-1-dialogue-node-choice-goto/</link><pubDate>Fri, 16 Oct 2026 10:00:00 +0800</pubDate><guid>https://plumephp.com/narr-arch-11-1-dialogue-node-choice-goto/</guid><description>对话节点是字段化的记录：节点层八个字段、选项层五个字段，其中 goto 是选项的独立字段而非效果算子。本节给出两张字段表，用 S 层脚本校验 115 条跳转全部命中已声明节点并输出节点度数表，再用 P 层测试断言未知选项被拒绝、推进是纯函数。</description></item><item><title>11.3 对话树的遍历与校验</title><link>https://plumephp.com/narr-arch-11-3-dialogue-tree-traversal-validation/</link><pubDate>Fri, 16 Oct 2026 10:00:00 +0800</pubDate><guid>https://plumephp.com/narr-arch-11-3-dialogue-tree-traversal-validation/</guid><description>把 48 个对话节点当成一张有向图，环、不可达节点、死路三类缺陷就都成了可判定的性质。本节用 DFS 三色标记找环、BFS 从起点算可达性与层号，实测三类缺陷均为 0：115 条选项去重后只有 56 条唯一跳转，5 个无出口节点全是结局，与 na_00 的 BFS 状态空间穷举口径互证。</description></item></channel></rss>