№ · 玩法设计 CH.07.25
主页 · 🎲 玩法设计 · 第一年剧情对白玩法与触发规则 v1

第一年剧情对白玩法与触发规则 v1

📅 2026-07-25 · 📦 47.2 KB · 🎲 玩法设计 · 📝 MD 文档 🆕 14d 🏷️ Buff🏷️ 终局🏷️ 剧情🏷️ 员工🏷️ 第一年🏷️ 玩法设计

状态:phase_b_runtime_integrated_acceptance_pending 范围:开业元年(第 1-360 天)的 76 个月度对白节点;不包含旧账补卷、第二年、角色支线全集或 UI 重做。 本文是第一年对白玩法合同。Phase B 运行时已接入;仍待补齐无明确数值的 effect manifest,并完成中期锚点与第 355/360 日真实浏览器验收。

0. 2026-07-21 完成度快照

  • canonical 数据:76/76 事件、162/162 稳定选项 ID 已进入同一运行时真源,静态文案与编辑器消费回归已通过。
  • 触发与存档:确定性锚点、completed / missed / pending、招募节点延后、错过前置放行、第 360 日唯一收束和旧存档归一化均已接入;当前版本实时存档与周目槽同步不再读写旧 v1 键。
  • 选项后果:当前 122/162 选项具有非零资源、员工、羁绊、掉落、旗标、解锁或终局结算;40 个选项没有非零结算字段,其中 storyline_y1_m02_n03:c 已明确为零后果,另 39 个仍需批准后的 effect manifest,禁止猜填。
  • 员工生日彩蛋:5 名员工、5 个固定生日、15 个选择已接入精确日触发、离线补触发、每 360 日一次、pending 恢复、奖励与任务结算;生日 pending 的实时存档 -> 周目槽 -> 激活链已有回归覆盖。
  • 自动验证:test:year1 26/26test:w29 47/47、根目录 lint、根目录 build 通过。
  • 浏览器验收:已实测新档第 1 日 canonical 对白与第 2-3 日事件推进;生日弹窗刷新后恢复、中期锚点、第 355/360 日仍未形成完整实机证据,因此状态继续保持 acceptance_pending

1. 先定结论

第一年对白采用“经营中的确定性剧情锚点”玩法:玩家正常经营、推进时间,到达当天和时段后,主线对白在弹窗中稳定出现;玩家选择会改变资源、员工状态、羁绊、剧情旗标或后续提示,但不会因为随机数把年线节点永久抽丢。

本年对白的 canonical 真源是:

  1. docs/story/第一年主线剧情对白总纲-v1.md 的年度弧线、节点顺序和第 360 天收束规则。
  2. docs/story/主线故事/月01-月12-*-节气增强版.md 的日期、场景、选择语义、已签效果和解锁条件。
  3. docs/story/主线故事/月01-月12-*-对白稿-v1.md 的玩家可见场景、对白和选项措辞。
  4. docs/story/01-主线故事-目录与总览.mddocs/plans/active/week-plan-2026-07-01-tools-entry-and-year1-mainline.md 的年度阶段、属性支撑、道具投放和闭环验收。
  5. docs/design/completed/systems/quest-event-loop-design-v1.md 的“自动主线 / 剧情任务推进型 / 年终锚点”分界。

当前 tools/剧情编辑器/src/data/storylineBridge.ts 的 79 条 Quest 只作为历史追踪/迁移输入,不再作为运行时对白真源。运行时接入后,编辑器、年线追踪和突发事件弹窗都消费同一份 GameEvent 数据,禁止再复制一套“编辑器剧情”和一套“可玩剧情”。

2. 当前实现审计

2.1 已经可玩、但不是第一年对白真源的内容

GAME_EVENT_TABLES -> GAME_EVENTS -> selectWeightedGameEvent -> useInnSimulationController -> RandomEventPopup 是当前真实玩家路径。它会随机选择事件,满足 dayWindowtimeAffinitybusinessPhaseAffinityyearPhaserequiredStaff,并由 RandomEventPopup 渲染 sceneDescription、选项效果和 dialogue

当前可玩表中有一些与 Year1 节点语义相近的事件,但它们不是 76 个对白稿节点:

| 运行时事件 | 与 Year1 的关系 | 处置 | | --- | --- | --- | | storyline_story_m01_n06 | 郭芙蓉入店,现已在 storyline-guo-lu-pilot,与月 1 节点 6 重复 | Phase B 迁移后删除注册,只保留 canonical 节点 | | night_rooftop_steps | 与月 1 节点 7 的夜巡语义重叠 | 作为普通夜间风险保留,但月 1 锚点日不允许它抢占主线 | | day_guo_front_door | 与月 3 节点 3 的镇场语义重叠 | 保留为非锚点羁绊事件;主线锚点优先 | | dusk_kitchen_smoke | 与月 3 节点 5 重叠 | 保留日常经营插曲;锚点当天不抢占 | | bao_daren_inspectionduan_zhi_visitdazui_supply_shortage | 分别与月 3-2、月 2-4、月 4 经营压力相近 | 保留为条件支线/插曲,不得再宣称是月度对白节点 | | qian_refugeqian_invoice_quarrelwushuang_help_shiftbai_secret_old_friend | 与月 2-3、月 6-5、月 4-3、月 5-3 有关系线重叠 | 保留为条件支线;通过前置旗标降权,禁止同日重复展示 | | martial_match_* 4 条 | 与月 8-1、月 8-2、月 9-4、月 9-5/10-1 有擂台语义重叠 | 保留为擂台随机层;主线锚点日由 Year1 canonical 事件锁定 | | storyline-old-ledger 10 条 | Year1 跨月补卷,是真实可玩事件,不属于 76 节点 | 继续可玩;与对应月度节点使用合并/前后触发合同,不能复制演出 |

2.2 只在编辑器/追踪层存在的内容

  • STORYLINE_QUESTS 当前导出 79 条,进入 STORYLINE_EDITOR_EXPORT_EVENTSSTORYLINE_YEAR_TASK_PLANS,因此 StoryTrackingCard 能显示年线进度,但这 79 条没有统一注册到 GAME_EVENTS
  • storylineEditorExport.ts 当前从编辑器反向导入数据层,形成“编辑器真源 -> 年线追踪”的特殊桥;Phase B 应改成“运行时数据层 -> 编辑器适配/年线追踪”,不得继续扩大反向依赖。
  • GAME_EVENTS 中的 storyline-guo-lu-pilot 只注册了月 1 节点 6;storyline-bai-tong-pilot 当前虽被导入但未注册为表。两者都不能继续作为 Year1 主线接入方案。

2.3 当前消费链的缺口

  1. 选择器当前按权重随机;即使事件有精确 dayWindow,也可能在当天 2% 弹窗机会中没有抽到。
  2. 事件选择后只有 currentEvent,选择提交后立即 setCurrentEvent(null);没有第一年对白的已完成事件、已选选项、错过节点或待恢复弹窗状态。
  3. 存档保存了资源、员工、羁绊等 GameState,但没有剧情进度命名空间;只保存 hasTriggeredEvent 不能证明某个节点已完成。
  4. GameEventOption 有资源、羁绊、掉落、终局和擂台效果,但没有稳定选项 ID,也没有员工 vitals/loyalty、剧情旗标、解锁项等声明式字段。
  5. storylineBridge.ts 的 79 条数据与对白稿的选项语义并不总相同;不能拿旧 bridge 的数字效果静默覆盖增强版月本真值。

补充审计结论:src/utils/storylineYearCompiler.ts 只负责对导出事件按日期排序、生成 tracking task 和第 360 天 fallback,它不负责弹窗或选项结算;src/data/eventTables/storyline-year.ts 目前把 79 条 editor export 接到年线追踪,因此“追踪进度存在”不等于“对白可玩”。src/data/year1Plan.ts 是既有年度计划快照(并含历史 helper 函数),只供阶段/属性/投放展示;Phase B 不把对白常量或新函数塞进去。RandomEventPopup 是现有唯一对白渲染面,useInnInteractionController 已统一资源、掉落、羁绊、擂台和终局效果结算,Year1 只应接入这条 consumer,不新增第二个 popup 或第二套 choice handler。

3. 稳定 ID 与事件分类

3.1 canonical ID

Phase B 使用以下稳定 ID,不把中文标题当作主键:

storyline_y1_m01_n01 ... storyline_y1_m01_n08
storyline_y1_m02_n01 ... storyline_y1_m02_n08
storyline_y1_m03_n01 ... storyline_y1_m03_n06
storyline_y1_m04_n01 ... storyline_y1_m04_n06
storyline_y1_m05_n01 ... storyline_y1_m05_n06
storyline_y1_m06_n01 ... storyline_y1_m06_n06
storyline_y1_m07_n01 ... storyline_y1_m07_n06
storyline_y1_m08_n01 ... storyline_y1_m08_n06
storyline_y1_m09_n01 ... storyline_y1_m09_n06
storyline_y1_m10_n01 ... storyline_y1_m10_n06
storyline_y1_m11_n01 ... storyline_y1_m11_n06
storyline_y1_m12_n01 ... storyline_y1_m12_n06

选项也要稳定:<eventId>:a<eventId>:b<eventId>:c。没有“按数组下标猜选项”的实现。标题或对白可以润色,ID 不因文案调整而变。

3.2 事件分类

| 分类 | 数量 | 玩法职责 | 触发原则 | | --- | ---: | --- | --- | | main_anchor 主线锚点 | 6 | 开业、百日、两百日、擂台、团圆和年终方向的骨架节点 | 确定日/时段、一次性、主线优先 | | conditional_side 条件支线 | 8 | 官面、街坊与江湖外部压力 | 前置满足后出现;不满足时按节点策略 defer/skip | | business_interlude 经营插曲 | 18 | 把现金、桌位、后厨、柴水、清洁和冬储压力变成对白选择 | 仍是确定锚点,但资源只影响提示和选项可用性 | | role_dialogue 角色对白 | 32 | 角色招募、能力、羁绊和去留 | 角色自身解锁节点不设员工门;后续节点用 requiredStaff | | month_close 月份收束 | 12 | 每月把选择写入简报,承接下月 | 12 个月末固定触发;前置缺失时走 closeout fallback | | 合计 | 76 | | |

分类覆盖清单(用于 Phase B regression,不进入玩家 UI):

  • main_anchorm01_n01m04_n02m07_n04m08_n01m10_n01m12_n04
  • conditional_sidem02_n03m02_n06m03_n02m05_n01m08_n03m08_n04m09_n02m10_n05
  • business_interludem01_n02m01_n04m01_n05m02_n01m03_n01m03_n05m04_n01m05_n04m06_n01m06_n02m06_n03m09_n01m10_n02m11_n01m11_n04m12_n01m12_n02m04_n05
  • role_dialoguem01_n03m01_n06m01_n07m02_n02m02_n04m02_n05m02_n07m03_n03m03_n04m04_n03m04_n04m05_n02m05_n03m05_n05m06_n04m06_n05m07_n01m07_n02m07_n03m07_n05m08_n02m08_n05m09_n03m09_n04m09_n05m10_n03m10_n04m11_n02m11_n03m11_n05m12_n03m12_n05
  • month_close:月 01/02 的 n08,月 03-12 的 n06

分类是逻辑层派生索引,不是玩家可见文案;玩家只看到事件标题和对白。

4. 触发门与选择规则

4.1 统一门模型

现有 GameEvent 字段继续承担静态门:dayWindowtimeAffinitybusinessPhaseAffinityyearPhaserequiredStaff。在 GameEvent 上只新增一个最小声明式 storyGate,在 GameEventOption 上新增稳定 idstoryEffects;业务计算放 src/utils/storyEvents/year1DialogueLogic.ts,不把函数塞进数据层。

建议最小字段:

interface StoryGate {
  priority: number;                 // 主线锚点 > 月末收束 > 条件支线 > 普通随机
  once?: boolean;                   // Year1 全部为 true
  legacyIds?: string[];             // 旧 story_mXX_nYY / pilot ID,仅供迁移
  prerequisiteEventIds?: string[]; // 全部已完成
  prerequisiteChoiceIds?: string[];// 由 prerequisiteMode 解释
  prerequisiteMode?: 'all' | 'any';
  requiredFlags?: string[];
  blockedByFlags?: string[];
  pressureHints?: string[];         // 只改变权重/提示,不硬阻塞主线
  graceDays?: number;               // 锚点错过后的补触发窗口
  missPolicy: 'defer' | 'skip' | 'closeout_fallback';
  fallbackEventId?: string;
}

interface StoryOptionEffects {
  staff?: Array<{ staffId: StaffId; delta: Partial<{
    health: number; stamina: number; fatigue: number; mood: number;
    stress: number; loyalty: number; ambition: number; salaryDue: number;
  }> }>;
  flags?: string[];
  clearFlags?: string[];
  unlocks?: string[];
}

StoryGate 是数据,不在数据层写函数。资源成本仍复用 coinsEffectwoodEffectwaterEffectcookedFoodEffect 等现有字段;不另造一套价格字段。玩家选择时沿用现有资源短缺拦截,铜钱继续遵循当前“扣到 0、不因负数卡死”的规则,柴/水/熟食继续由现有 popup 显示材料不足。

4.2 锚点与优先级

每次游戏 tick 的事件选择顺序:

  1. yearPhase 和硬性门先过滤;未招募的 requiredStaff 事件不可触发。
  2. 在当前日/时段命中的 storyGate.priority >= 100 canonical 锚点中,按 priority、稳定 ID 排序,直接取第一条;不走随机数。
  3. 没有 canonical 锚点时,继续使用现有 selectWeightedGameEvent 选择条件支线/经营插曲/随机事件。
  4. 锚点事件弹窗打开后暂停重复选择;选择提交才写入 storyProgress.completed
  5. 同一天的旧账补卷若与 canonical 节点同语义,按合并规则先解决一条,另一条记录为“已并入”而不再弹出。

4.3 门的解释

  • A(day/time):绝对日和时段命中;窗口通常为 1 天,月 1 节点 3 使用第 5-7 天窗口。
  • P(id):前置 canonical 事件已完成;月内按前一节点串联,跨月按上月收束节点串联。
  • R(staff):要求对应员工已解锁;事件自身负责“解锁某人”时不设置该门,防止新档死锁。
  • F(flag):前置选项产生的故事旗标满足;未满足只影响可选分支/后续提示,不阻塞第一年主线。
  • H(hint):资源、属性或羁绊压力提示,改变候选权重、弹窗提示或可选分支,不把主线变成数值检查题。
  • C(closeout):月末收束一定出现;缺失前置时用摘要文字承认遗漏,不伪造已经做过的选择。

时段同时给出经营阶段默认值:dawn/day -> opendusk -> closingnight -> closed;如果玩家在离线结算或手动暂停后跨过阶段,year1DialogueLogic 仍以事件的 timeAffinity 和锚点窗口为准,不把经营阶段漂移当成新事件。每条目录行的 H 由本月的 YEAR1_PLAN_ATTRIBUTE_LINKS 和节点类别派生:前 30 天 service/cooking/accounting/security,31-90 天叠加 mood/loyalty/health,91-180 天叠加 stamina,181-300 天叠加 martial/stress,301-360 天叠加 accounting/mood/loyalty/stress;具体羁绊由该行的后果契约写明。

主线锚点不设置不可逆硬资源门。否则低铜钱/低清洁/低治安存档会把第 360 天锁死。资源只决定选项能否支付或后果强弱;员工门只用于角色已入店之后的角色对白。

5. 第一年度对白事件目录(76 条)

表中“场景 / 选项”是玩家可见的收束描述;完整逐句对白仍以对应 *-对白稿-v1.md 为文本真源。后果契约 只列效果类别和不可丢失的故事结果,数值必须从对应节气增强版的游戏效果表落盘,禁止从旧 bridge 猜数。

月 01:开张适应期(第 1-30 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m01_n01 | 1 / 清晨 | 挂起招牌、迎第一位客人;A 掌柜带伙计走流程;B 放手摸索 | 教学“服务优先还是现金优先” | A + 先导 | A 服务熟练/名声/清洁;B 铜钱↑、清洁↓;写入开业旗标 | | storyline_y1_m01_n02 | 3 / 傍晚 | 三日账本摊开;A 按问题清单定责;B 先听自报 | 把失败变成可修正的经营动作 | A + P(n01) | A 清洁↑、压力记录;B 保留现金、压力不增;生成首份简报 | | storyline_y1_m01_n03 | 5-7 / 午间 | 白展堂泼汤、客流高峰;A 私下扣工钱;B 当众鼓励 | 招募白展堂,建立白佟种子 | A(5-7) + P(n02) | A 规矩/忠诚;B 名声/心情/白佟羁绊;unlock:bai | | storyline_y1_m01_n04 | 10 / 午间 | 邢捕头吃白食;A 记人情账;B 硬要钱;C 用巡逻情报换饭 | 第一次现金流与官面关系选择 | A + P(n03) | A 铜钱↓治安↑欠条;B 铜钱↑治安↓;C 情报旗标/治安↑ | | storyline_y1_m01_n05 | 15 / 全天 | 赶集客流放大;A 囤柴水;B 保现金;C 门口卖冰糖葫芦 | 采购储备与临时营销 | A + P(n04) | A 柴/水↑铜钱↓;B 现金保留;C 铜钱/名声↑、清洁或治安压力 | | storyline_y1_m01_n06 | 20 / 午后 | 郭芙蓉砸桌、要求留下;A 签洗碗契;B 自选洗碗或赔款 | 招募郭芙蓉,建立郭吕种子 | A + P(n05) | A 名声/忠诚;B 清洁或压力分支;unlock:guo、郭吕旗标 | | storyline_y1_m01_n07 | 25 / 深夜 | 屋顶轻功;A 白展堂暗中处理;B 点灯惊走 | 夜间治安教学与白佟信任 | A + P(n06) + R(bai) | A 治安↑、白展堂压力/白佟羁绊、名刺;B 治安↑但名声↓ | | storyline_y1_m01_n08 | 30 / 雨水末 | 全员围桌满月小结;A 全员立下春分目标;B 掌柜定三条 | 把第一月变成团队承诺 | C + P(n07) | A 名声/心情;B 清洁/压力;写入月 1 简报 |

月 02:街坊熟络期(第 31-60 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m02_n01 | 32 / 清晨 | 赛西施带点心“考察敌情”;A 招牌菜待客;B 客气送客 | 同行竞争不只靠吵赢 | A(32) + P(m01_n08) | A 名声↑、街坊竞争旗标;B 保现金、竞争疑心旗标 | | storyline_y1_m02_n02 | 35 / 上午 | 吕秀才带三本账;A 立刻加薪全权管账;B 试用一个月 | 招募账房,建立 accounting 反馈 | A + P(n01) | A 账目能力/铜钱成本、郭吕种子;B 账目能力较慢、试用旗标;unlock:lu | | storyline_y1_m02_n03 | 38 / 傍晚 | 钱掌柜藏柴房;A 掩护;B 当面解决;C 谁都不帮 | 练习人情边界 | A + P(n02) | A 名声/货物;B 钱钱羁绊/供货旗标;C 保边界、关系不增 | | storyline_y1_m02_n04 | 42 / 惊蛰末 | 断指轩辕来访、把铜钱当考题;A 让大嘴做答卷菜;B 挂铜钱每日自省 | 把厨艺变成传承与自尊 | A + P(n03) | A 名声/厨艺信物;B 忠诚/传承旗标;不提前触发终局 | | storyline_y1_m02_n05 | 48 / 清晨 | 小贝逃学;A 陪摘桂花再送学;B 秀才顺路带去 | 家庭关系与经营时间取舍 | A + P(n04) | A 名声/莫佟羁绊/桂花物;B 效率/较低关系收益 | | storyline_y1_m02_n06 | 52 / 午后 | 小米用剩饭换消息;A 热饭换详细消息;B 赶走自行查 | 第一个江湖线索入口 | A + P(n05) | A 治安/情报与物品;B 治安小增、白展堂疲劳/线索缺失 | | storyline_y1_m02_n07 | 58 / 春分 | 大嘴河鲜蛋羹试菜;A 立刻上菜单;B 先试三天 | 招募厨师并建立菜品反馈 | A + P(n06) | A 铜钱/名声/菜品;B 稳定口碑、延迟收入;unlock:li | | storyline_y1_m02_n08 | 60 / 春分末 | 两月总结,写给清明;A 全员立目标;B 掌柜定三条 | 让街坊熟络沉淀成团队 | C + P(n07) | A 名声/心情;B 清洁/压力;写入月 2 简报、稀客权重微增 |

月 03:初遇挑战期(第 61-90 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m03_n01 | 63 / 清晨 | 客人吃坏肚子;A 全额退款请大夫送赔礼;B 退款但解释柿饼责任 | 第一次食安责任教学 | A + P(m02_n08) + R(li) | A 铜钱↓、名声/清洁↑、暖胃食谱;B 成本较低、关系收益低 | | storyline_y1_m03_n02 | 68 / 午后 | 包大仁微服查价;A 承认记错;B 坚持浮动价 | 诚信校验与官面关注 | A + P(n01) | A 名声/治安/巡查记录;B 怀疑旗标,后续官面压力 | | storyline_y1_m03_n03 | 72 / 清明末 | 江湖混混上门;A 郭芙蓉公开镇场;B 私下提醒别只靠武力 | 能打与会处理的差异 | A + P(n02) + R(guo) | A 名声/治安;B 郭压力/较小名声,郭吕摩擦推进 | | storyline_y1_m03_n04 | 78 / 月夜 | 秀才算错账;A 每月自查;B 伙计共写错账本 | 把错误责任变成流程 | A + P(n03) + R(lu) | A 忠诚/账目能力;B 团队清洁/压力;错误计数 +1 | | storyline_y1_m03_n05 | 84 / 晚高峰 | 后厨烟火过旺;A 赶菜;B 停火清灶 | 现金与清洁安全冲突 | A + P(n04) + R(li) | A 铜钱↑清洁↓;B 铜钱↓清洁/名声↑、润喉散 | | storyline_y1_m03_n06 | 90 / 傍晚 | 三个月总结;A 把未完事项带下月;B 写信给下月自己 | 第一个季度收束 | C + P(n05) | A 进入扩建期;B 清洁/心情↑;生成季度简报 |

月 04:扩建起步期(第 91-120 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m04_n01 | 95 / 午市 | 客满到站不下;A 加两张新桌四把椅;B 先加旧桌 | 扩容与现金流 | A + P(m03_n06) | A 桌位/铜钱/清洁;B 低成本扩容、后续压力 | | storyline_y1_m04_n02 | 100 / 全天 | 熟客自发百日捧场;A 记入账本并挂百日牌 | 用纪念物确认客栈被街坊接纳 | A + P(n01) | 百日纪念牌、关系氛围/名声;无二次分支 | | storyline_y1_m04_n03 | 105 / 傍晚 | 无双端凉茶来帮工;A 正式帮工;B 只留住不接活 | 引入无双、建立无双吕种子 | A + P(n02) | A 清洁/服务/开支/无双吕;B 保现金、角色线等待唤醒 | | storyline_y1_m04_n04 | 110 / 上午 | 燕小六第一次单独盘查;A 耐心配合;B 公事公办 | 官面边界与师徒关系 | A + P(n03) | A 人情/治安/邢燕旗标;B 边界稳定、关系收益低 | | storyline_y1_m04_n05 | 115 / 下午 | 大嘴拿厨房扩建图;A 按图施工 | 把扩建落到后厨能力 | A + P(n04) + R(li) | 后厨 Lv.1、清洁/安全/忠诚↑、改造图;执行确认无分支 | | storyline_y1_m04_n06 | 120 / 傍晚 | 两寸账本四月小结;A 确认总结并开放二楼预订 | 月度收束与区域解锁 | C + P(n05) | 二楼住店 Lv.1、扩建债务记录、羁绊快照 |

月 05:江湖初闻期(第 121-150 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m05_n01 | 125 / 午后 | 江湖刀客点名“郭女侠镇场的客栈”;A 郭芙蓉接待;B 白展堂低调接待 | 名声外溢与风险暴露 | A + P(m04_n06) | A 名声/治安压力、郭成长;B 低调稳定、白线加压 | | storyline_y1_m05_n02 | 130 / 午市后 | 赛西施挖角大嘴;A 加薪挽留;B 让大嘴自己选 | 忠诚不是口号,是待遇与自主权 | A + P(n01) + R(li) | A 铜钱/大嘴忠诚;B 保现金但挖角线保留 | | storyline_y1_m05_n03 | 135 / 深夜 | 白展堂旧友夜访;A 用江湖道义换平安;B 拒绝并面对 | 旧身份只露压力,不提前揭底 | A + P(n02) + R(bai) | A 安全/身份风险/白佟压力;B 风险更直接但保边界;旧账补卷同日合并 | | storyline_y1_m05_n04 | 140 / 午市 | 十二人商队午歇;A 加急出菜;B 分批保品质 | 大单经营能力验证 | A + P(n03) | A 铜钱/名声↑、清洁/治安压力;B 口碑/路线物、收入较稳 | | storyline_y1_m05_n05 | 145 / 午后至傍晚 | 赶考书生文斗/对联;A 住到考期 | 让秀才用本事而非笑点赢认可 | A + P(n04) + R(lu) | 账本文斗集、郭吕关系、短期住宿收入;驻留旗标 | | storyline_y1_m05_n06 | 150 / 傍晚 | 五月双刃剑小结;A 确认并开启下月 | 把名声变成持续关注而非终局 | C + P(n05) | 二楼正式运作、白展堂旧识永久加压、五月简报 |

月 06:盛夏经营期(第 151-180 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m06_n01 | 155 / 午市后 | 半年结算,账本越来越厚;确认半年报告 | 把经营反馈变成可读报告 | A + P(m05_n06) + R(lu) | 半年报告、成就“同福一期”、江湖阅历/心情 | | storyline_y1_m06_n02 | 160 / 入夜 | 盛夏夜市客流激增;A 延长经营;B 正常营业加安防 | 收入与治安疲劳权衡 | A + P(n01) + R(li) | A 铜钱/名声↑、清洁/治安/疲劳压力;B 收入较低、治安↑ | | storyline_y1_m06_n03 | 165 / 午市前 | 旱灾井水见底;A 买水;B 限水;C 与街坊共用深井 | 资源危机中的三种治理方式 | A + P(n02) | A 水↑铜钱↓;B 水少、清洁/名声↓;C 水/名声/街坊互助旗标 | | storyline_y1_m06_n04 | 170 / 午后 | 无双发现账本漏洞;A 接受她按方法修正 | 让能力被看见,承接旧账证据 | A + P(n03) | 账页、清洁/账目↑、无双吕摩擦;旧账同日合并 | | storyline_y1_m06_n05 | 175 / 午后 | 钱夫人追到客栈;A 劝和让钱掌柜交代;B 掩护溜走 | 家务账、供货账与客栈边界 | A + P(n04) | A 钱钱羁绊/供货旗标;B 人情收益低、治安/麻烦压力 | | storyline_y1_m06_n06 | 180 / 傍晚 | 半年大结,准备立秋 | 上半年收束,关系进入下一段 | C + P(n05) | 黄酒解锁、四线羁绊快照、旱灾种子激活 |

月 07:羁绊萌芽期(第 181-210 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m07_n01 | 185 / 午后 | 芙蓉与秀才争“谁替谁出头”;A 武力;B 文雅 | 关系选择必须落在工作场面 | A + P(m06_n06) + R(guo,lu) | A 名声↓治安↑郭吕小增;B 名声/郭吕↑、文斗旗标 | | storyline_y1_m07_n02 | 190 / 月夜 | 白展堂夜巡谈心;A 写承诺入账本;B 不留字据 | 口头信任与书面承诺 | A + P(n01) + R(bai) | A 白佟旗标、压力小增;B 压力下降、风险不留凭证 | | storyline_y1_m07_n03 | 195 / 深夜 | 小贝练功走火;A 严格管教;B 请白展堂温和教功 | 家庭、治安和小贝成长 | A + P(n02) + R(bai) | A 治安/莫佟小增、心情↓;B 莫佟/心情↑、白压力/清洁↓ | | storyline_y1_m07_n04 | 200 / 清晨 | 两百日记,六封信;A 围坐公开念;B 各自带回再分享 | 关系从打闹变成承诺 | A + P(n03) | A 氛围/名声;B 安静沉淀旗标;六封信存档 | | storyline_y1_m07_n05 | 205 / 深夜 | 无双留下还是离开;A 留撕掉的信;B 留影存档 | 无双必须有自己的理由 | A + P(n04) | A 关系守恒;B 无双吕加固、存档旗标;不影响郭吕终局 | | storyline_y1_m07_n06 | 210 / 傍晚 | 七月小结,更像一家人;唯一确认 | 把关系变化写入月报 | C + P(n05) | 七月简报、进入白露;旧账官面锚点同日合并 |

月 08:擂台预热期(第 211-240 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m08_n01 | 215 / 白露秋风 | 挂红绸误会;A 立刻搭擂;B 先立告示等两天 | 把年度大事件入口交给玩家 | A + P(m07_n06) | A 铜钱↓名声/热度↑、立即报名;B 成本低、热度慢 | | storyline_y1_m08_n02 | 220 / 白露秋风 | 大嘴误挂红绸;A 留研发存档;B 给街坊试吃 | 梦想可被看见但不抢主擂 | A + P(n01) + R(li) | A 研发速度/失败配方;B 口碑波动、研发经验 | | storyline_y1_m08_n03 | 225 / 白露末 | 江湖客聚集;A 主动收情报;B 低调回避 | 外部风险与白展堂压力 | A + P(n02) | A 情报/治安↑、白压力↑;B 白压力↓、治安小降 | | storyline_y1_m08_n04 | 230 / 秋分 | 邢捕头站岗;A 每天供菜;B 只请一次 | 官差秩序的成本与边界 | A + P(n03) | A 持续现金成本/口碑/邢燕;B 成本可控、关系守恒 | | storyline_y1_m08_n05 | 235 / 擂台 | 郭芙蓉守擂宣言;A 秋菜分给全场;B 留到赛后 | 角色站上擂台前先决定承担方式 | A + P(n04) + R(guo) | A 热度/口碑快升;B 关系更稳、赛后旗标;郭吕推进 | | storyline_y1_m08_n06 | 240 / 傍晚 | 八月简报与报名册入匣 | 从看热闹转为备战 | C + P(n05) | 八月简报、擂台报名状态、下一月入口 |

月 09:大日子逼近期(第 241-270 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m09_n01 | 245 / 正午 | 寒露大集;A 全员接客;B 一半备赛;C 优先备赛 | 客流、疲劳、备赛进度三线取舍 | A + P(m08_n06) | 收入/名声/清洁/疲劳/备赛进度按 A/B/C 分化 | | storyline_y1_m09_n02 | 250 / 午后 | 初擂报名截止;A 全公布;B 秀才先查;C 邢捕头协查 | 信息公开、文书安全与官面风险 | A + P(n01) + R(lu) | 名册/查验旗标;A 风险公开,B 安全,C 官面知情 | | storyline_y1_m09_n03 | 255 / 傍晚 | 杨慧兰来尝菜;A 掌柜泼冷水;B 白展堂鼓励;C 秀才算账 | 大嘴梦想的现实、鼓励与账目 | A + P(n02) + R(li) | 大嘴杨慧兰羁绊/心情/账目记录,不能直接决定去留 | | storyline_y1_m09_n04 | 260 / 深夜 | 旧识借擂试探;A 不出手;B 必要时一招;C 暴露一点 | 白展堂旧身份风险分档 | A + P(n03) + R(bai) | 暴露风险按 A/B/C 低中高;白佟加固;旧账摊牌合并 | | storyline_y1_m09_n05 | 265 / 书房 | 秀才文斗报名;A 独立赛道;B 文武混合;C 只做噱头 | 让文斗成为正式玩法,不是笑话 | A + P(n04) + R(lu) | 文斗规则书、名声/安全/郭吕;设置擂台分支旗标 | | storyline_y1_m09_n06 | 270 / 傍晚 | 九月简报和名册副本入匣 | 安静收束,避免提前消费高潮 | C + P(n05) | 九月简报、明日决擂入口,所有未决分支保持 |

月 10:高潮迭起期(第 271-300 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m10_n01 | 275 / 清晨 | 决擂之日;A 公开大办;B 邢捕头公证;C 直接庆功宴 | 年度高潮,把前九月选择兑现 | A + P(m09_n06) + R(guo) | A 名声/收入↑清洁↓;B 官面/治安;C 心情/庆典;擂台结算只发生一次 | | storyline_y1_m10_n02 | 278 / 立冬尾声 | 擂台余波;A 接商队;B 留名帖;C 请一顿后延 | 高光之后的经营承载 | A + P(n01) | A 客源/桌位压力;B 热度保留;C 口碑先行、合作延期 | | storyline_y1_m10_n03 | 282 / 立冬尾声 | 赵采办带来御厨风声;A 让带笔记;B 只抄菜谱不带人;C 请吃饭留笔记 | 大嘴梦想与去留自主 | A + P(n02) + R(li) | 名声/御膳房认可/大嘴忠诚旗标;不在第一年强制离店 | | storyline_y1_m10_n04 | 288 / 午后 | 郭巨侠来信;A 正式回信;B 秀才写事由;C 不回但内部公开留下 | 家族压力与郭芙蓉自主 | A + P(n03) + R(guo) | 郭吕 settled 进度/公开程度旗标;不触发第二年查封 | | storyline_y1_m10_n05 | 295 / 寒风 | 稀客接连登门;A 当普通客;B 白展堂婉拒;C 后院单谈 | 名声远播带来安全成本 | A + P(n04) + R(bai) | A 治安风险/后续试探;B 口碑↓安全↑;C 信息量↑、经营打乱 | | storyline_y1_m10_n06 | 300 / 夕阳 | 三百日总结;唯一确认“把第一年带进下一段” | 高潮后记录成长,不提前终局 | C + P(n05) | 三百日简报、白佟 settled 加固、旧账夹层同日合并 |

月 11:余波与反思期(第 301-330 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m11_n01 | 305 / 午后 | 擂台余热消退;A 休息半天;B 纪念品成册卖;C 提前备冬至饺子 | 热闹结束后的时间安排 | A + P(m10_n06) | 休息/短钱/冬储三种方向,年关任务旗标不同 | | storyline_y1_m11_n02 | 310 / 雪地 | 无双决定留下;A 立刻回信;B 先告诉内部;C 自己写回信 | 无双的边界与自我成长 | A + P(n01) | 无双吕 settled/公开程度/清洁服务加成;不改变郭吕 | | storyline_y1_m11_n03 | 315 / 账房 | 秀才补全年错账;A 自罚;B 研究费;C 捐腊八粥 | 责任是成本、学习还是善意 | A + P(n02) + R(lu) | 铜钱/账目错误计数/名声或施粥旗标 | | storyline_y1_m11_n04 | 320 / 寒风 | 冬储采购;A 大量囤货;B 精打细算;C 钱掌柜赊货 | 冬季资源与现金流 | A + P(n03) | 铜钱、食材/炭火/棉被或赊账旗标 | | storyline_y1_m11_n05 | 325 / 傍晚 | 钱夫人和解;A 夫妻自收家务账;B 掌柜安排冬至饭;C 秀才写分账说明 | 成熟的关系边界与供货合作 | A + P(n04) | 钱钱 settled、佟钱业务、供货折扣;掌柜不替他们永远解决 | | storyline_y1_m11_n06 | 330 / 傍晚 | 十一月总结入匣 | 把选择交给岁末,而非重复回忆 | C + P(n05) | 十一月简报、岁末入口;未完成可在 summary 中显示 |

月 12:岁末收束期(第 331-360 天)

| ID | 锚点 | 玩家可见场景与选项 | 玩法目的 | 门 | 后果契约 | | --- | --- | --- | --- | --- | --- | | storyline_y1_m12_n01 | 335 / 午间 | 年关催账;A 先官面后街坊再商队;B 先小后大;C 不催邢捕头 | 把人情账变成付款顺序 | A + P(m11_n06) | 铜钱/治安/官面旗标;旧账并账节点同场只演一次 | | storyline_y1_m12_n02 | 340 / 雪天 | 岁末大扫除;A 放半天假;B 姜丝热黄酒;C 秀才归档旧物 | 用劳动整理一年记忆 | A + P(n01) | 清洁、休息、铜钱或元年档案 | | storyline_y1_m12_n03 | 345 / 风雪 | 白三娘到访;A 多住几天;B 白展堂送母亲;C 留暖手炉垫 | 家庭认可保持克制 | A + P(n02) + R(bai) | 白三娘羁绊、白佟关系温度、纪念物 | | storyline_y1_m12_n04 | 350 / 雪夜 | 岁末团圆饭;A 吃到子时;B 各自回家;C 再做一碗腊八粥 | 让“家”由选择构成 | A + P(n03) | 铜钱/心情/清洁/治安;团圆暖 buff;不提前跨年 | | storyline_y1_m12_n05 | 355 / 午后 | 年终经营总录;A 更大;B 更稳;C 更有人味 | 让玩家选择下一年侧重点 | A + P(n04) + R(lu) | 记录下一年偏好旗标;不得在此处直接切换第二年 | | storyline_y1_m12_n06 | 360 / 深夜 | 跨年之夜,关最后一盏灯 | 第一年的唯一终结锚点 | A + P(n05) + C(360) | 结算全年报告、羁绊快照、传承入口;year1Closed=true,只在此切换第二年 |

6. 月 04 / 月 05 的 79 -> 76 零损失迁移决策

总纲承认的 Year1 月度数量为 8/8/6/6/6/6/6/6/6/6/6/6 = 76。当前编辑器桥却是 8/8/6/8/7/6/6/6/6/6/6/6 = 79。这不是数量小误差,而是旧 bridge 混入了旧版经营节点和不同月份的角色节点。

月 04:保留 6 个 canonical,退役 2 个旧节点

| 旧 ID | 旧标题 | 决策 | 原因 | | --- | --- | --- | --- | | story_m04_n01 | 堂中加桌 | 映射 y1_m04_n01 | 同一日期/主题;以增强版两档扩容选项为准 | | story_m04_n07 | 百日记 | 映射 y1_m04_n02 | 同一第 100 天节点;ID 序号漂移,迁移表必须显式记录 | | story_m04_n02 | 祝无双帮工 | 映射 y1_m04_n03 | 同一角色入口;以对白稿 A/B 语义为准 | | story_m04_n03 | 燕小六拜师(第 108 天) | 迁移为 y1_m04_n04 的 legacy alias | 正文增强版为第 110 天“第一次单独盘查”;保留师徒关系事实,日期改用高优先级正文 | | story_m04_n08 | 大嘴厨房扩建 | 映射 y1_m04_n05 | 同一第 115 天施工节点 | | story_m04_n06 | 四月小结 | 映射 y1_m04_n06 | 同一月末收束 | | story_m04_n04 | 李大嘴采购断档 | 退役独立节点;效果并入 y1_m04_n05 前置压力提示 | 不是增强版六节点之一;作为经营插曲可由 dazui_supply_shortage 覆盖,不能再次占用 Year1 主线 | | story_m04_n05 | 赛西施门口抢客 | 退役独立节点;保留 saixishi_poach_customers 普通支线 | 与月 2 竞争和月 5 挖角重复,旧 bridge 不得继续追踪为月 4 主线 |

月 05:保留 6 个 canonical,旧 7 个全部显式处置

| 旧 ID | 旧标题 | 决策 | | --- | --- | --- | | story_m05_n01 | 说书人慕名而来 | 退役为 Year1 主线;可由 rare_guest_story_table 作为随机江湖插曲承接 | | story_m05_n02 | 杨慧兰初登场 | 移入 canonical y1_m09_n03 的前置人物事实,不在月 5 另演 | | story_m05_n03 | 莫小贝掌门身份曝光 | 退役为主线节点;角色支线后续另有 mobeibei_* 事件,不抢月 5 江湖主轴 | | story_m05_n07 | 官道商队午歇(升级版) | 映射 y1_m05_n04;保留升级版商队选项 | | story_m05_n04 | 郭芙蓉收到家书 | 移入 canonical y1_m10_n04,旧月 5 条目标记迁移 alias | | story_m05_n05 | 姬无命初现端倪 | 退役为主线;由 ji_wuming_invade 作为条件夜间风险承接 | | story_m05_n06 | 五月小结 | 映射 y1_m05_n06,以对白稿“二楼正式运作/旧识加压”收束 |

迁移规则:旧 ID 只存在于 legacyAliases/存档迁移表,不再出现在玩家默认列表;新档只写 canonical ID。任何实现若直接把 79 条追加进 GAME_EVENTS,即判定重复定义和零损失迁移失败。

7. 旧账补卷的合并与错过策略

storyline-old-ledger 的 10 个节点仍是可玩跨月补卷,不纳入 76 的月度计数。与主线对白的关系固定如下:

| 旧账日 | canonical 关系 | 运行规则 | | ---: | --- | --- | | 52 | 月 2-6 小米消息 | 先触发月 2-6;旧账残页作为同场追加线索,不能再开第二个 popup | | 68 | 月 3-2 包大仁巡查 | 月 3-2 结算后追加后门风声;若月 3-2 错过,旧账节点可独立补述 | | 90 | 月 3-6 季末小结 | 合入季度简报底稿,不能覆盖小结选择 | | 135 | 月 5-3 白展堂夜访 | 同一夜访只演一次;选项后果合并写入白展堂身份风险 | | 170 | 月 6-4 无双账本漏洞 | 作为证据落账段落,不另弹相同账本场景 | | 210 | 月 7-6 七月小结 | 月报后显示官面口径变化,不抢情感小结 | | 260 | 月 9-4 旧账擂台 | 作为同一擂台事件的线索层,不重复结算安全/暴露风险 | | 300 | 月 10-6 三百日总结 | 夹层底稿进入年终档案,放在总结前后由逻辑层固定一次 | | 335 | 月 12-1 年关催账 | 并账清单只出现一次;若玩家选择不催官面,记录待结旗标 | | 360 | 月 12-6 跨年夜 | 只补一句“旧账过去了”的收束语,不改 year1Closed 和胜利/失败结论 |

8. 错过、fallback、重复与确定性

8.1 主线锚点

  • 当天时段错过:在 graceDays 内继续等同一事件;默认 graceDays=2,不改变原定日,只把实际完成日记录为玩家进度。
  • 前置节点未完成:不强行显示选项;进入 defer。到下一锚点仍不满足时,主线用 closeout_fallback 生成一段“本月经营简报已记下遗漏”的低收益收束,随后仍允许进入下月。
  • 解锁节点不得被资源门挡住。若玩家资源不足,事件照常出现,选择按钮沿用现有材料不足提示;月末报告显示“未能执行”,不能悄悄替换成成功。

8.2 条件角色与经营插曲

  • requiredStaff 未满足:候选集硬过滤;窗口结束标记 missed,不追补第二次。
  • 四个关键入店节点 m01_n03m01_n06m02_n02m02_n07 例外:它们自身不设员工门,missPolicy=defer,在玩家明确选择前不进入 missed,也不自动替玩家选。其余角色对白的错过只影响该角色旗标/奖励,不影响第 360 天主线;之后可由普通角色支线以低权重补一句收束。
  • canonical 节点的 once=true 就是永久冷却:完成或明确错过后不再进入候选集。经营插曲采用现有随机权重;语义重复的普通事件在 canonical 锚点前后 1 个游戏时段权重降为 0.25,并在同类普通事件完成后进入 7 天冷却。

8.3 选择确定性

  • 主线事件一旦弹出,玩家选择前不自动换题;刷新、窗口缩放、切换面板不得重抽。
  • 同一事件只允许一个 choiceId 写入;重复点击、重复回放、浏览器刷新都必须幂等。
  • 事件选择排序:priority 降序 -> 锚点日升序 -> storyline canonical ID 字典序。随机只用于没有确定性锚点的普通事件。

9. 存档恢复合同

新增的最小存档命名空间建议为 storyProgress,附着在 PlaythroughRuntimeSaveData 上:

interface Year1StoryProgress {
  version: 1;
  completed: Record<string, { choiceId: string; day: number }>;
  missed: Record<string, { reason: string; day: number }>;
  flags: Record<string, boolean>;
  pendingEventId?: string;
  year1Closed: boolean;
}

规则:

  1. 打开弹窗时写入 pendingEventId;点击选项后写入 completed[eventId]choiceId、实际日,再清除 pending。
  2. 存档在弹窗打开时恢复:从 canonical GAME_EVENTS 重新查找 pendingEventId,校验当前年份后重新打开;找不到则移入 missed 并走 fallback。
  3. 旧存档没有 storyProgress 时按空进度启动,不伪造已完成;只用旧 story_mXX_nYY 记录时按本文件迁移表映射到 canonical ID。
  4. year1Closed=true 只能由第 360 天事件写入;第 355 天“解锁第二年”选项只写 nextYearFocus,不提前切换运行年份。
  5. 多周目继承只读取第 360 天结算快照和明确允许的传承字段,不把 completed/missed/pending 带入下一周目。

10. 与第 360 天唯一收束锚点的关系

月 12 的 335/340/345/350/355 节点都是可错过或可降级的准备与收束;第 360 天 storyline_y1_m12_n06 是第一年唯一承认的终结锚点。它必须:

  • 只在 day=360timeOfDay=nightyearPhase=opening_year_focus 出现;
  • 在此前所有未完成 canonical 节点上生成只读摘要,不替玩家补选;
  • 结算全年收入、客流、事件数、羁绊快照、已解锁角色/菜品/区域和选择的下一年侧重点;
  • 写入 year1Closed 后才允许年切换/第二年事件池;
  • 不因旧账补卷的 360 日落款、失败链或第二年预览而重复触发。

11. Phase B 建议文件围栏

必须等 G20-1 形式回调被吸收、共享注册/选择器锁释放后,再开 Year1 实现;本设计不授权现在修改这些文件。

数据层(第一阶段)

  • 新增:src/data/eventTables/storyline-year1-month01.ts ... storyline-year1-month12.ts(只放类型、常量、静态事件表)。
  • 新增:src/data/eventTables/storyline-year1.ts(聚合 12 月表,不放函数)。
  • 共享注册:src/data/eventTables/index.ts(G20-1 释放后才可改)。
  • 可选类型扩展:src/data/eventTables/types.ts(只加 StoryGateStoryOptionEffects 声明)。

逻辑层(第二阶段)

  • 新增:src/utils/storyEvents/year1DialogueLogic.ts(门判断、锚点优先、错过/fallback、旧 ID 迁移、幂等)。
  • 新增:src/utils/storyEvents/year1DialogueLogic.regression.ts(76/76、ID、门、fallback、choice 幂等)。
  • 共享选择器:src/utils/storyEvents/gameEventSelectionLogic.ts(只加入 canonical 锚点优先,G20-1 释放后修改)。

存档与现有 consumer(第三阶段)

  • src/data/playthroughs/types.tssrc/utils/playthroughSlots.tssrc/utils/saveVersioning.ts:加入/迁移 storyProgress
  • src/components/app/useSaveRestoreController.tssrc/App.tsx:恢复 pending、把 storyProgress 纳入 stateRef/save payload。
  • src/components/app/useInnSimulationController.tssrc/components/app/useInnInteractionController.ts:调用逻辑层并记录 choice;不重造 popup。
  • src/components/RandomEventPopup.tsx:只在需要时接收稳定 option ID/阻断提示,保持现有视觉和交互。

编辑器适配(第四阶段)

  • tools/剧情编辑器/src/utils/gameEventBridgeLogic.ts:只消费 RUNTIME_GAME_EVENT_TABLES 中的 canonical Year1 表;移除 STORYLINE_QUESTS 的重复拼接。
  • tools/剧情编辑器/src/data/storylineBridge.ts:保留历史迁移输入或标记 deprecated,不再作为当前 Year1 runtime truth。
  • src/data/storyEvents/storylineEditorExport.tssrc/data/eventTables/storyline-year.ts:改为从 runtime canonical 表生成追踪计划,避免反向依赖编辑器。

明确禁止

不在本 lane 扩第二年、不接终局深层压力、不改多人、不造对白历史/立绘/schema、不做第二个对话引擎、不把随机普通事件改成全都确定锚点、不在 G20-1 共享锁未释放时改 index.ts/selector/controller。

12. 可执行验收

静态与注册

  • 12 月计数严格为 8/8/6/6/6/6/6/6/6/6/6/6 = 76;旧 79 条只存在迁移/历史输入,不进入 canonical 默认列表。
  • canonical ID 76 个全局唯一;76 个事件各有稳定 option ID,无重复 eventId:choiceId
  • 12 份对白稿的玩家选择段合计 162 个 A/B/C 选项契约;执行性/月末节点的“唯一确认”也必须落成一个稳定 choice ID,不能因无分支而省略记录。
  • GAME_EVENT_TABLESGAME_EVENTS、编辑器 getRealQuests 与年线追踪均来自同一 canonical 数据,注册数与月度计数一致。
  • 玩家可见 titlesceneDescriptionoption.textdialogue 不出现内部 ID、snake_case、Bridge/Refs/Tags/Source/Seed/mainchain 或技术拼接串。

触发正反例

  • 每个锚点在正确日/时段稳定触发;同日普通事件不能抢占;前一天/错误时段不触发。
  • requiredStaff 未满足时角色事件不出现,满足后在窗口内出现;主线解锁事件不能因员工未解锁而死锁。
  • 依赖未完成时主线按 defer -> closeout_fallback,不重复弹窗、不跳过第 360 天。
  • 月 04 的采购断档/价格战、月 05 的旧桥节点不会再次当作主线;旧账十锚点与 52/68/90/135/170/210/260/300/335/360 的对白不重复演出。

选项、恢复与回归

  • 每个节点每个选项的资源、员工状态、羁绊、掉落、旗标和解锁结果与对应节气增强版游戏效果表一致;旧 bridge 缺失的效果不得猜填。
  • 选择后重复点击、刷新、重新打开不能重复结算;存档在 popup 打开/选择后/错过后恢复结果一致。
  • 第 355 天不提前关闭第一年;第 360 天只收束一次,结算摘要包含未完成/错过清单但不替选。
  • 定向回归覆盖:76/76 events76 unique IDsoption IDs、12 月计数、锚点正反例、员工门、资源不足、fallback、旧 ID 迁移、存档恢复、360 唯一收束。
  • 工程门:npm.cmd run lintnpm.cmd run build、现有 test:w29 全通过;浏览器手验至少覆盖新档第 1 天、一个中期锚点、第 355/360 天,保留无法真实跑完时的残余风险。

13. Phase A 历史回包模板(已过期)

以下内容仅保留 Phase A 设计交接记录,不代表当前实现状态;当前状态以第 0 节完成度快照为准。

completed:
- 读取总纲、月01-12对白稿、节气增强版和当前 runtime/editor consumer
- 形成 76 条 canonical 事件目录、触发门、选项后果和 fallback/save 合同
- 解释月04 8->6、月05 7->6 的合并/退役/迁移策略

incomplete:
- Phase B 代码接入尚未开始,等待 manager 审查本设计合同

blockers:
- G20-1 仍占 shared registry/selector/controller 锁;不能在本回合改产品代码
- 节气增强版中若存在未被现有 GameEvent 字段承载的员工 vitals/解锁效果,必须在 Phase B 前按本文件的最小 schema 拍板,禁止猜数

next action:
- manager 审查后,按第 11 节文件围栏串行放行 Phase B

evidence:
- `docs/story/第一年主线剧情对白总纲-v1.md`
- `docs/story/主线故事/月01-月12-节气增强版.md`
- `docs/story/主线故事/月01-月12-对白稿-v1.md`
- `tools/剧情编辑器/src/data/storylineBridge.ts` 当前 79 条
- `src/data/eventTables/index.ts` 当前真实注册表