@lemoncat7/dsh-partner 2.8.3 → 2.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/README.md +27 -406
  2. package/docs/THIRD_PARTY_LICENSES.md +4 -0
  3. package/docs/bark-notifications.md +27 -0
  4. package/docs/concern-workflow.md +39 -0
  5. package/docs/director-skills.md +8 -3
  6. package/docs/dsh-021-compatibility.md +9 -0
  7. package/docs/package-distribution.md +11 -0
  8. package/docs/releases/1.12.0.md +16 -0
  9. package/docs/releases/1.14.2.md +8 -0
  10. package/docs/releases/1.15.0.md +15 -0
  11. package/docs/releases/1.16.0.md +15 -0
  12. package/docs/releases/1.16.1.md +12 -0
  13. package/docs/releases/1.16.2.md +12 -0
  14. package/docs/releases/2.0.0.md +19 -0
  15. package/docs/releases/2.1.0.md +8 -0
  16. package/docs/releases/2.2.0.md +8 -0
  17. package/docs/releases/2.3.0.md +8 -0
  18. package/docs/releases/2.4.0.md +8 -0
  19. package/docs/releases/2.5.0.md +8 -0
  20. package/docs/releases/2.8.0.md +6 -0
  21. package/docs/releases/2.8.4.md +35 -0
  22. package/docs/releases/2.8.5.md +23 -0
  23. package/docs/releases/2.8.6.md +22 -0
  24. package/docs/releases/README.md +14 -0
  25. package/lib/agent-runtime.d.ts +1 -0
  26. package/lib/agent-runtime.d.ts.map +1 -1
  27. package/lib/agent-runtime.js +14 -5
  28. package/lib/agent-runtime.js.map +1 -1
  29. package/lib/api/features/push-api.d.ts +4 -0
  30. package/lib/api/features/push-api.d.ts.map +1 -0
  31. package/lib/api/features/push-api.js +47 -0
  32. package/lib/api/features/push-api.js.map +1 -0
  33. package/lib/api.d.ts +2 -0
  34. package/lib/api.d.ts.map +1 -1
  35. package/lib/api.js +5 -1
  36. package/lib/api.js.map +1 -1
  37. package/lib/autonomy.d.ts.map +1 -1
  38. package/lib/autonomy.js +5 -4
  39. package/lib/autonomy.js.map +1 -1
  40. package/lib/channels/direct/message-format.js +13 -8
  41. package/lib/channels/direct/message-format.js.map +3 -3
  42. package/lib/client-api.d.ts +1 -0
  43. package/lib/client-api.d.ts.map +1 -1
  44. package/lib/client-api.js.map +1 -1
  45. package/lib/client.d.ts.map +1 -1
  46. package/lib/client.js +1170 -646
  47. package/lib/client.js.map +4 -4
  48. package/lib/collaboration/composition.d.ts.map +1 -1
  49. package/lib/collaboration/composition.js +1 -0
  50. package/lib/collaboration/composition.js.map +1 -1
  51. package/lib/collaboration/ssh-task-access.d.ts +33 -0
  52. package/lib/collaboration/ssh-task-access.d.ts.map +1 -0
  53. package/lib/collaboration/ssh-task-access.js +26 -0
  54. package/lib/collaboration/ssh-task-access.js.map +1 -0
  55. package/lib/companions/removal.d.ts.map +1 -1
  56. package/lib/companions/removal.js +4 -0
  57. package/lib/companions/removal.js.map +1 -1
  58. package/lib/concern-domain.d.ts +2 -0
  59. package/lib/concern-domain.d.ts.map +1 -1
  60. package/lib/concern-domain.js.map +1 -1
  61. package/lib/concern-execution-notes.d.ts +2 -0
  62. package/lib/concern-execution-notes.d.ts.map +1 -1
  63. package/lib/concern-execution-notes.js +9 -2
  64. package/lib/concern-execution-notes.js.map +1 -1
  65. package/lib/concern-execution-receipt.d.ts.map +1 -1
  66. package/lib/concern-execution-receipt.js +3 -2
  67. package/lib/concern-execution-receipt.js.map +1 -1
  68. package/lib/concern-execution.d.ts.map +1 -1
  69. package/lib/concern-execution.js +1 -0
  70. package/lib/concern-execution.js.map +1 -1
  71. package/lib/concern-knowledge-source.d.ts +23 -0
  72. package/lib/concern-knowledge-source.d.ts.map +1 -0
  73. package/lib/concern-knowledge-source.js +30 -0
  74. package/lib/concern-knowledge-source.js.map +1 -0
  75. package/lib/concern-note-source.d.ts +2 -1
  76. package/lib/concern-note-source.d.ts.map +1 -1
  77. package/lib/concern-note-source.js +6 -2
  78. package/lib/concern-note-source.js.map +1 -1
  79. package/lib/concern-store.d.ts.map +1 -1
  80. package/lib/concern-store.js +5 -0
  81. package/lib/concern-store.js.map +1 -1
  82. package/lib/domain.d.ts +2 -0
  83. package/lib/domain.d.ts.map +1 -1
  84. package/lib/domain.js.map +1 -1
  85. package/lib/index.d.ts.map +1 -1
  86. package/lib/index.js +18 -1
  87. package/lib/index.js.map +1 -1
  88. package/lib/notifications/bark-adapter.d.ts +9 -0
  89. package/lib/notifications/bark-adapter.d.ts.map +1 -0
  90. package/lib/notifications/bark-adapter.js +69 -0
  91. package/lib/notifications/bark-adapter.js.map +1 -0
  92. package/lib/notifications/push-config.d.ts +10 -0
  93. package/lib/notifications/push-config.d.ts.map +1 -0
  94. package/lib/notifications/push-config.js +79 -0
  95. package/lib/notifications/push-config.js.map +1 -0
  96. package/lib/notifications/push-credentials.d.ts +9 -0
  97. package/lib/notifications/push-credentials.d.ts.map +1 -0
  98. package/lib/notifications/push-credentials.js +16 -0
  99. package/lib/notifications/push-credentials.js.map +1 -0
  100. package/lib/notifications/push-domain.d.ts +66 -0
  101. package/lib/notifications/push-domain.d.ts.map +1 -0
  102. package/lib/notifications/push-domain.js +6 -0
  103. package/lib/notifications/push-domain.js.map +1 -0
  104. package/lib/notifications/push-observer.d.ts +19 -0
  105. package/lib/notifications/push-observer.d.ts.map +1 -0
  106. package/lib/notifications/push-observer.js +96 -0
  107. package/lib/notifications/push-observer.js.map +1 -0
  108. package/lib/notifications/push-service.d.ts +33 -0
  109. package/lib/notifications/push-service.d.ts.map +1 -0
  110. package/lib/notifications/push-service.js +228 -0
  111. package/lib/notifications/push-service.js.map +1 -0
  112. package/lib/notifications/push-state.d.ts +3 -0
  113. package/lib/notifications/push-state.d.ts.map +1 -0
  114. package/lib/notifications/push-state.js +23 -0
  115. package/lib/notifications/push-state.js.map +1 -0
  116. package/lib/observation-budget.d.ts +3 -2
  117. package/lib/observation-budget.d.ts.map +1 -1
  118. package/lib/observation-budget.js +5 -3
  119. package/lib/observation-budget.js.map +1 -1
  120. package/lib/observation-loop.d.ts +1 -0
  121. package/lib/observation-loop.d.ts.map +1 -1
  122. package/lib/observation-loop.js +129 -21
  123. package/lib/observation-loop.js.map +1 -1
  124. package/lib/observation-model-retry.d.ts +20 -0
  125. package/lib/observation-model-retry.d.ts.map +1 -0
  126. package/lib/observation-model-retry.js +48 -0
  127. package/lib/observation-model-retry.js.map +1 -0
  128. package/lib/observation-progress.d.ts +1 -0
  129. package/lib/observation-progress.d.ts.map +1 -1
  130. package/lib/observation-progress.js +24 -4
  131. package/lib/observation-progress.js.map +1 -1
  132. package/lib/observation-workflow.d.ts +40 -0
  133. package/lib/observation-workflow.d.ts.map +1 -0
  134. package/lib/observation-workflow.js +154 -0
  135. package/lib/observation-workflow.js.map +1 -0
  136. package/lib/recording-snapshot.d.ts.map +1 -1
  137. package/lib/recording-snapshot.js +12 -2
  138. package/lib/recording-snapshot.js.map +1 -1
  139. package/lib/skills/ai-camera-language-builtin.d.ts +3 -0
  140. package/lib/skills/ai-camera-language-builtin.d.ts.map +1 -0
  141. package/lib/skills/ai-camera-language-builtin.js +89 -0
  142. package/lib/skills/ai-camera-language-builtin.js.map +1 -0
  143. package/lib/skills/builtin.d.ts.map +1 -1
  144. package/lib/skills/builtin.js +2 -0
  145. package/lib/skills/builtin.js.map +1 -1
  146. package/lib/skills/story-builtins.js +2 -2
  147. package/lib/skills/story-builtins.js.map +1 -1
  148. package/lib/storage/migrate-layout.d.ts.map +1 -1
  149. package/lib/storage/migrate-layout.js +2 -0
  150. package/lib/storage/migrate-layout.js.map +1 -1
  151. package/lib/storage/split-state.js +2 -2
  152. package/lib/storage/split-state.js.map +1 -1
  153. package/lib/store.d.ts.map +1 -1
  154. package/lib/store.js +2 -0
  155. package/lib/store.js.map +1 -1
  156. package/lib/ui/capability-editor.d.ts.map +1 -1
  157. package/lib/ui/capability-editor.js +3 -5
  158. package/lib/ui/capability-editor.js.map +1 -1
  159. package/lib/ui/channels-panel.d.ts.map +1 -1
  160. package/lib/ui/channels-panel.js +7 -1
  161. package/lib/ui/channels-panel.js.map +1 -1
  162. package/lib/ui/push-channels.d.ts +11 -0
  163. package/lib/ui/push-channels.d.ts.map +1 -0
  164. package/lib/ui/push-channels.js +28 -0
  165. package/lib/ui/push-channels.js.map +1 -0
  166. package/lib/ui/push-draft.d.ts +30 -0
  167. package/lib/ui/push-draft.d.ts.map +1 -0
  168. package/lib/ui/push-draft.js +13 -0
  169. package/lib/ui/push-draft.js.map +1 -0
  170. package/lib/ui/push-editor.d.ts +10 -0
  171. package/lib/ui/push-editor.d.ts.map +1 -0
  172. package/lib/ui/push-editor.js +99 -0
  173. package/lib/ui/push-editor.js.map +1 -0
  174. package/lib/ui/runtime-settings.d.ts +18 -0
  175. package/lib/ui/runtime-settings.d.ts.map +1 -0
  176. package/lib/ui/runtime-settings.js +25 -0
  177. package/lib/ui/runtime-settings.js.map +1 -0
  178. package/lib/ui/workspace-components.d.ts +7 -1
  179. package/lib/ui/workspace-components.d.ts.map +1 -1
  180. package/lib/ui/workspace-components.js +8 -4
  181. package/lib/ui/workspace-components.js.map +1 -1
  182. package/package.json +56 -47
  183. package/resources/skills/ai-camera-language/manifest.json +26 -0
  184. package/resources/skills/ai-camera-language/references/camera-dictionary.md +315 -0
  185. package/resources/skills/ai-camera-language/references/prompt-workflow.md +186 -0
  186. package/resources/skills/ai-camera-language/references/video-summary.md +123 -0
  187. package/resources/skills/novel-game-creation/manifest.json +2 -245
  188. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/BUILD_BRIEF.md +0 -219
  189. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/.vercelignore +0 -3
  190. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/RUN.md +0 -138
  191. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/bg/compound_new_guofeng.webp +0 -0
  192. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/finale/fate_coda.webp +0 -0
  193. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/finale/meng.webp +0 -0
  194. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/finale/pan.webp +0 -0
  195. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/finale/pinger.webp +0 -0
  196. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/finale/xuee.webp +0 -0
  197. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/finale/yue.webp +0 -0
  198. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_accord_five.webp +0 -0
  199. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_afterglow_five.webp +0 -0
  200. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_alliance.webp +0 -0
  201. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/group/public_day10.webp +0 -0
  202. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/group/public_day15.webp +0 -0
  203. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/group/public_day5.webp +0 -0
  204. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/group/title_new_guofeng.webp +0 -0
  205. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/joint/pan_pinger.webp +0 -0
  206. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/joint/pan_xuee.webp +0 -0
  207. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/joint/yue_meng.webp +0 -0
  208. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/joint/yue_pan.webp +0 -0
  209. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/joint/yue_pinger.webp +0 -0
  210. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/meng/explicit.webp +0 -0
  211. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/meng/prelude.webp +0 -0
  212. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/milestone/meng.webp +0 -0
  213. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/milestone/pan.webp +0 -0
  214. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/milestone/pinger.webp +0 -0
  215. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/milestone/xuee.webp +0 -0
  216. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/milestone/yue.webp +0 -0
  217. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/pan/explicit.webp +0 -0
  218. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/pan/prelude.webp +0 -0
  219. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/pinger/explicit.webp +0 -0
  220. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/pinger/prelude.webp +0 -0
  221. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/xuee/explicit.webp +0 -0
  222. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/xuee/prelude.webp +0 -0
  223. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/yue/explicit.webp +0 -0
  224. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/cg/yue/prelude.webp +0 -0
  225. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/heroine/meng/night.webp +0 -0
  226. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/heroine/pan/night.webp +0 -0
  227. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/heroine/pinger/night.webp +0 -0
  228. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/heroine/xuee/night.webp +0 -0
  229. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/heroine/yue/night.webp +0 -0
  230. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/household/li_jiaoer.webp +0 -0
  231. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/assets/scene/gate_collector.webp +0 -0
  232. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/css/new-guofeng.css +0 -1494
  233. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/css/style.css +0 -2508
  234. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/index.html +0 -18
  235. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/js/assets.js +0 -147
  236. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/js/audio.js +0 -332
  237. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/js/data.js +0 -7470
  238. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/js/engine.js +0 -13066
  239. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/js/main.js +0 -3051
  240. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/js/text.js +0 -32
  241. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/package.json +0 -11
  242. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/app/vercel.json +0 -23
  243. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/build/art/generated-art.json +0 -161
  244. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/example.json +0 -12
  245. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/qa/README.md +0 -26
  246. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/qa/playable-model.json +0 -99
  247. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/qa/verification.json +0 -41
  248. package/resources/skills/novel-game-creation/upstream/examples/jin-ping-mei/qa/verify_playable_model.mjs +0 -152
@@ -1,32 +0,0 @@
1
- // 玩家可见文案集中管理。路线对白在 data.js 中按设计节点集中管理。
2
-
3
- export const TEXT = Object.freeze({
4
- title: '金瓶梅·风月总账',
5
- subtitle: '二十日,五扇门。你说过的话,她们都记得。',
6
- identity: '你是西门庆。门外的债已经追到家门,门里有五个人等你把银子、谎话和旧承诺一件件说清。你可以偏爱,但不能叫她们替你撒谎。',
7
- rating: '18+ · 仅限成年人 · 含成人关系、轻度裸露与亲密内容',
8
- ageTitle: '十八岁以下,止步',
9
- ageBody: '本作只供成年人,含成人关系、肩背与腿部等轻度裸露、亲密场景与成熟主题。所有可进入亲密路线的人物均为成年虚构角色。',
10
- ageYes: '我已成年',
11
- ageNo: '离开',
12
- start: '进宅',
13
- continue: '接着玩',
14
- gallery: '场景册',
15
- restart: '从头再来',
16
- muteOn: '开声',
17
- muteOff: '静音',
18
- dayLead: '院里的事已摆到眼前。你先动哪一只手?',
19
- chooseVisit: '暮鼓响过,五处院门仍留着灯。今夜你去见谁?',
20
- sharedNightLead: '五个人都没走。账还没凉,酒已经热了——今夜是各回各院,还是在每个人都独立点头之后让五盏灯留在一处,就等你开口。',
21
- nightLead: '茶还热着,她的手在门闩上停了一会儿。接下来怎样,听她的。',
22
- morningLead: '天刚透进窗纸,昨夜没说尽的话已经到了门外。',
23
- banquetLead: '五只杯子都等着。这一次若把功劳、财权或证词分偏了,夜里就有一扇门先落闩。',
24
- galleryEmpty: '册子还是空的。等有人肯把门留给你,再来看。',
25
- galleryKeep: '从头再来,册页也不会丢。',
26
- saveNote: '每次落子都会存下;旧版账本不续接。',
27
- close: '合上',
28
- sceneContinue: '接着往下',
29
- endingRestart: '再走二十日',
30
- endingGallery: '翻场景册',
31
- reducedMotion: '已按系统设置减少动效',
32
- });
@@ -1,11 +0,0 @@
1
- {
2
- "name": "jinpingmei-fengyue-ledger",
3
- "private": true,
4
- "type": "module",
5
- "description": "《金瓶梅·风月总账》20日男性第一人称成人后宫关系模拟:五条深线、五院共约、联院协力与公开问责",
6
- "scripts": {
7
- "start": "python3 -m http.server 5173",
8
- "verify:model": "node ../../qa/verify_playable_model.mjs",
9
- "verify:visual": "python3 test/verify_visual.py --write-evidence"
10
- }
11
- }
@@ -1,23 +0,0 @@
1
- {
2
- "$schema": "https://openapi.vercel.sh/vercel.json",
3
- "headers": [
4
- {
5
- "source": "/assets/(.*)",
6
- "headers": [
7
- {
8
- "key": "Cache-Control",
9
- "value": "public, max-age=31536000, immutable"
10
- }
11
- ]
12
- },
13
- {
14
- "source": "/(.*)\\.(js|css)",
15
- "headers": [
16
- {
17
- "key": "Cache-Control",
18
- "value": "public, max-age=3600, must-revalidate"
19
- }
20
- ]
21
- }
22
- ]
23
- }
@@ -1,161 +0,0 @@
1
- {
2
- "schemaVersion": 3,
3
- "generatedAt": "2026-08-25",
4
- "toolVersion": "Codex built-in image_gen",
5
- "usage": "《金瓶梅·风月总账》四十一张运行图的二维新国风彻底重塑",
6
- "reason": "旧棕黑 CG、古画册页样张、真人古装样张和现代时尚样张分别被判定为太暗、太旧、太真实和太现代。最终批准方向为完整晚明世界中的成熟理想化二维叙事游戏插画。",
7
- "externalStyleResearch": {
8
- "source": "https://github.com/freestylefly/awesome-gpt-image-2",
9
- "principles": [
10
- "Case 213:首先读作可进入的古代游戏空间,不借 MMO HUD、3D 真人渲染或暗街",
11
- "Case 290:角色卡级身份色、器物锚点和即时情绪,不借 SSR 文案、镭射边框或暗底",
12
- "Case 9:现代、多彩、明亮通透的国潮色光和留白,不借现代城市与宣传构图",
13
- "Case 230:朱红、青蓝、鎏金的克制功能配色,不借品牌海报和现代地标"
14
- ],
15
- "rejected": [
16
- "Case 206/242 式古画与书签媒介",
17
- "Case 343/514 式现代时尚与硬边艺术",
18
- "Case 207 式暗黑真人封面"
19
- ],
20
- "copyrightBoundary": "未复制或提交参考库案例图;只借媒介裁决、游戏化识别、色光与留白方法。"
21
- },
22
- "approvedStyleFrame": {
23
- "asset": "app/assets/cg/group/title_new_guofeng.webp",
24
- "sourceOutput": "codex-imagegen:exec-e1603504-1f87-4923-8f7d-7b6a45751299.png",
25
- "promptSummary": "五名成年女性置于通透明代春庭;二维数字手绘、成熟理想化面孔、流动丝绸、朱砂石青青绿桃粉;人物居中右,左侧留真实 HTML 标题区。",
26
- "required": [
27
- "完整晚明建筑、服饰、发式、器物与关系空间",
28
- "二维手绘游戏 CG 与可想象的人物材质",
29
- "白日中高明度;夜景同时保留蓝紫月光和暖灯",
30
- "五人脸型、成熟度、姿态、衣色与器物互异",
31
- "画面内不承担正文排版"
32
- ],
33
- "forbidden": [
34
- "真人摄影、3D 皮肤、现代时尚棚拍或品牌海报",
35
- "古画复刻、工笔册页、宣纸旧化或全局黄褐滤镜",
36
- "暗黑底、重暗角、全屏烟雾或不可读夜景",
37
- "幼态、未成年人、胁迫、露点或性行为",
38
- "现代物件、文字、标志或水印"
39
- ]
40
- },
41
- "identityMasters": [
42
- {
43
- "character": "吴月娘",
44
- "path": "app/assets/heroine/yue/night.webp",
45
- "sourceOutput": "codex-imagegen:exec-bd1047ec-fc3b-40e4-ac8a-1d0acfe1e174.png",
46
- "anchors": "石青与象牙、总账、铜钥匙"
47
- },
48
- {
49
- "character": "潘金莲",
50
- "path": "app/assets/heroine/pan/night.webp",
51
- "sourceOutput": "codex-imagegen:exec-f521d0b2-b51a-428a-90cb-c3cbb0e5592e.png",
52
- "anchors": "朱砂与暖粉、团扇、回看"
53
- },
54
- {
55
- "character": "李瓶儿",
56
- "path": "app/assets/heroine/pinger/night.webp",
57
- "sourceOutput": "codex-imagegen:exec-314abee8-24ce-4494-9430-22b3122424df.png",
58
- "anchors": "象牙与浅金、漆匣、私钥"
59
- },
60
- {
61
- "character": "孟玉楼",
62
- "path": "app/assets/heroine/meng/night.webp",
63
- "sourceOutput": "codex-imagegen:exec-230a5eec-86c4-4923-8955-3715328c4cbe.png",
64
- "anchors": "青绿与藕荷、名帖、曲谱、空席"
65
- },
66
- {
67
- "character": "孙雪娥",
68
- "path": "app/assets/heroine/xuee/night.webp",
69
- "sourceOutput": "codex-imagegen:exec-262bebeb-8053-46d6-a1ff-5afd4a8811fa.png",
70
- "anchors": "琥珀与深青、米账、仓绳、灶火"
71
- },
72
- {
73
- "character": "李娇儿",
74
- "path": "app/assets/household/li_jiaoer.webp",
75
- "sourceOutput": "codex-imagegen:exec-24cda691-c334-48cc-b23b-e4feefe8e8c8.png",
76
- "anchors": "梅紫与赭金、契纸、银秤、印匣"
77
- }
78
- ],
79
- "batches": [
80
- {
81
- "usage": "世界与入口",
82
- "promptSummary": "春日高机位宅院和明亮门槛催账;压力由契纸、人物姿态和受阻门槛表达。",
83
- "assets": [
84
- ["app/assets/bg/compound_new_guofeng.webp", "codex-imagegen:exec-c623d43c-e15a-4472-b9f4-f748ad848b56.png"],
85
- ["app/assets/scene/gate_collector.webp", "codex-imagegen:exec-a7b0d1b1-e316-41b6-ad57-86d009bfbada.png"]
86
- ]
87
- },
88
- {
89
- "usage": "五人前奏与关系落定",
90
- "promptSummary": "同一身份母版的夜间关系 CG;以目光、开掌、钥匙、出口和共享日用表达成年人的主动选择,完整着装,无性行为。",
91
- "assets": [
92
- ["app/assets/cg/yue/prelude.webp", "codex-imagegen:exec-1ac36cb6-30a6-413d-812c-4b1b482b8b2a.png"],
93
- ["app/assets/cg/yue/explicit.webp", "codex-imagegen:exec-65126819-70a1-4773-9759-706eaf51e6e1.png"],
94
- ["app/assets/cg/pan/prelude.webp", "codex-imagegen:exec-dcd0c85d-b0b1-4ae3-973f-40f8e2fa65e5.png"],
95
- ["app/assets/cg/pan/explicit.webp", "codex-imagegen:exec-ae6c99ab-27ce-4652-81d1-2af468e8260a.png"],
96
- ["app/assets/cg/pinger/prelude.webp", "codex-imagegen:exec-01830d1b-2d87-4e97-b97c-92f15ced287c.png"],
97
- ["app/assets/cg/pinger/explicit.webp", "codex-imagegen:exec-a985ad93-a833-4272-b41e-ed493997eca4.png"],
98
- ["app/assets/cg/meng/prelude.webp", "codex-imagegen:exec-f6a3adb4-0335-497b-8509-ee2c09f61780.png"],
99
- ["app/assets/cg/meng/explicit.webp", "codex-imagegen:exec-00c1529b-543e-42fc-8dad-3de16000a529.png"],
100
- ["app/assets/cg/xuee/prelude.webp", "codex-imagegen:exec-48622697-5ef3-443e-9a34-83e4a9c25859.png"],
101
- ["app/assets/cg/xuee/explicit.webp", "codex-imagegen:exec-216df76e-b036-443a-9e70-529f2b12cdba.png"]
102
- ]
103
- },
104
- {
105
- "usage": "五人公开关系与共同办事",
106
- "promptSummary": "五人以交叉视线、递证、按账、留座和轮值器物形成真实关系动作,不做并排群像。",
107
- "assets": [
108
- ["app/assets/cg/group/public_day5.webp", "codex-imagegen:exec-32d97fcc-b83b-41f4-8bae-d8e5bf286910.png"],
109
- ["app/assets/cg/group/public_day10.webp", "codex-imagegen:exec-60f375a8-ae0f-426d-9de2-fdbda4649142.png"],
110
- ["app/assets/cg/group/public_day15.webp", "codex-imagegen:exec-0be274e2-1562-4cb6-9354-7d437b27aa43.png"],
111
- ["app/assets/cg/group/inner_court_alliance.webp", "codex-imagegen:exec-7651ef0d-f27b-4ed1-86f7-7aaa5d049f99.png"],
112
- ["app/assets/cg/group/inner_court_accord_five.webp", "codex-imagegen:exec-1bc7fb07-e6df-4974-b802-69f6f32cf44b.png"],
113
- ["app/assets/cg/group/inner_court_afterglow_five.webp", "codex-imagegen:exec-19692392-08c1-4eeb-8c63-ea86b1a2e07b.png"]
114
- ]
115
- },
116
- {
117
- "usage": "五组双院结果",
118
- "promptSummary": "两名对应成年女性共同作用于一件证物;脸、衣色、器物和方法冲突继承身份母版。",
119
- "assets": [
120
- ["app/assets/cg/joint/yue_pan.webp", "codex-imagegen:exec-74e2b0e8-c46f-45c7-8ee6-e4ee651bd56d.png"],
121
- ["app/assets/cg/joint/yue_pinger.webp", "codex-imagegen:exec-35f35c39-8dfc-40b2-bfaa-f6071929cdb0.png"],
122
- ["app/assets/cg/joint/pan_pinger.webp", "codex-imagegen:exec-a0bb4acc-0a64-444d-9c5a-30b2d0fad595.png"],
123
- ["app/assets/cg/joint/yue_meng.webp", "codex-imagegen:exec-02c5f590-a171-4fa0-8a79-b0324079a512.png"],
124
- ["app/assets/cg/joint/pan_xuee.webp", "codex-imagegen:exec-5af38352-b063-4dbe-9b4a-af807faa2f94.png"]
125
- ]
126
- },
127
- {
128
- "usage": "五张个人终章与命数空宅",
129
- "promptSummary": "人物用钥匙、席位、退路、名帖、停灶和轮值执行最后规则;命数页以无人空宅、六把钥匙和五张名签承接固定历史。",
130
- "assets": [
131
- ["app/assets/cg/finale/yue.webp", "codex-imagegen:exec-a0272894-bfa1-44e7-a15f-a749322db57f.png"],
132
- ["app/assets/cg/finale/pan.webp", "codex-imagegen:exec-4ab8a42b-3d8b-4f81-8864-82ec3366b40f.png"],
133
- ["app/assets/cg/finale/pinger.webp", "codex-imagegen:exec-8c08054f-b78f-492d-8187-6b80dcaecc73.png"],
134
- ["app/assets/cg/finale/meng.webp", "codex-imagegen:exec-d3764cf3-67a3-4ae7-b98d-1b4f26083aea.png"],
135
- ["app/assets/cg/finale/xuee.webp", "codex-imagegen:exec-ed7203e7-bcbb-4829-b1c1-417ee44cedf8.png"],
136
- ["app/assets/cg/finale/fate_coda.webp", "codex-imagegen:exec-c29af8f8-fca4-4f71-aef0-5af5a4dd4d2a.png"]
137
- ],
138
- "editNote": "月娘、瓶儿、雪娥终章使用 image_gen 二次编辑清除模型伪文字。"
139
- },
140
- {
141
- "usage": "五张中局转折",
142
- "promptSummary": "空主位与轮值钥匙、矛盾口风与封口银、破锁空匣与退路、名帖网络、冷灶拒印分别成为可读危机。",
143
- "assets": [
144
- ["app/assets/cg/milestone/yue.webp", "codex-imagegen:exec-a84bb537-8fc2-4844-9d40-f6552b28fb4c.png"],
145
- ["app/assets/cg/milestone/pan.webp", "codex-imagegen:exec-debb4c41-2c4e-41b8-8eff-3e1a272184ec.png"],
146
- ["app/assets/cg/milestone/pinger.webp", "codex-imagegen:exec-43cace36-0bee-41d1-aa84-798882ad6d49.png"],
147
- ["app/assets/cg/milestone/meng.webp", "codex-imagegen:exec-3adba92b-e8cf-4103-adf7-ac81026dbf41.png"],
148
- ["app/assets/cg/milestone/xuee.webp", "codex-imagegen:exec-de699d51-80ee-4cc5-93d7-c0553f705f0f.png"]
149
- ],
150
- "editNote": "月娘、玉楼、雪娥转折图使用 image_gen 二次编辑清除模型伪文字。"
151
- }
152
- ],
153
- "postProcessing": {
154
- "command": "cwebp -q 88 -m 6 -metadata none",
155
- "assetCount": 41,
156
- "totalBytes": 10938766,
157
- "intermediatePolicy": "image_gen 原始 PNG 留在工具缓存,不复制进仓库;运行目录只保留四十一张新 WebP。",
158
- "reproducible": false
159
- },
160
- "acceptance": "人工巡检身份母版、个人夜景、五人群像、双院结果、终章与中局转折;浏览器 QA 另验证四十一张 URL 解码、旧资产清零、目标视口、流程输入和控制台。"
161
- }
@@ -1,12 +0,0 @@
1
- {
2
- "language": "zh-Hans",
3
- "title": "金瓶梅 · 风月总账",
4
- "targetFinish": "playable-prototype",
5
- "source": {
6
- "chapters": 100,
7
- "headingPattern": "^\\s*第([〇零○一二三四五六七八九十百]+)回\\s+(.+?)\\s*$",
8
- "numeral": "chinese"
9
- },
10
- "coverageHeading": "全书覆盖",
11
- "citationPattern": "第(\\d{1,3})(?:\\s*[-–—至]\\s*(\\d{1,3}))?回"
12
- }
@@ -1,26 +0,0 @@
1
- # QA 证据说明
2
-
3
- 本 example 的当前权威 QA 命令是:
4
-
5
- ```bash
6
- cd examples/jin-ping-mei/build/app
7
- python3 test/verify_visual.py --write-evidence
8
- ```
9
-
10
- 命令开始时先把 `verification.json` 原子写为未运行的失败态,完整路径成功后才原子更新
11
- `verification.json` 与严格 schema-v1 `evidence/run.json`。浏览器由脚本自启临时本地服务;全部推进使用
12
- Playwright `locator.click` 且不使用 `force`,DOM 只负责读取下一项可见可行控件的 selector。
13
-
14
- 当前路径覆盖年龄门、五院标题、五档标题/首日布局、首日真实夜访与选择后章,再以每屏第一项可行
15
- 主动作快速到达一个第二十日失稳结局并换 seed 重开。只保留标题、首日、夜访和结局四张代表图;该路径不
16
- 穷举其他结局,不复测全键盘或五档完整二十日矩阵,也不证明主观吸引力。
17
-
18
- 仓内另提供一条不依赖浏览器的可执行改编合同:
19
-
20
- ```bash
21
- node examples/jin-ping-mei/qa/verify_playable_model.mjs
22
- ```
23
-
24
- 它对照 `playable-model.json` 与实际 `data.js` / `engine.js`,验证两种正堂起手的差异、三拍回响、非空
25
- 回调载荷、证物来源与消费边界、同 seed 确定性、存档重演与分支污染拒绝。它不调用第 5/15/20 日、
26
- 结局、一月笺或命数消费者,是设计回归,不冒充上面的真实渲染、输入或完整二十日证据。
@@ -1,99 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "source": "design/GAME_DESIGN.md#10-可执行切片合同",
4
- "experienceProfile": "narrative-led",
5
- "buildPath": "custom",
6
- "versions": {
7
- "contentRevision": "NOT_AVAILABLE: 现有候选早于内容修订号拆分",
8
- "rulesRevision": "NOT_AVAILABLE: 现有候选早于规则修订号拆分",
9
- "saveSchema": 67
10
- },
11
- "stateSurface": {
12
- "resources": {
13
- "initial": {
14
- "silver": 220,
15
- "power": 2,
16
- "repute": 3,
17
- "exposure": 0,
18
- "strain": 0,
19
- "house": 65
20
- }
21
- },
22
- "relationshipActors": [
23
- "wu_yueniang",
24
- "pan_jinlian",
25
- "li_pinger",
26
- "meng_yulou",
27
- "sun_xuee"
28
- ],
29
- "dayActions": ["ledger", "office", "listen", "banquet"],
30
- "eventLog": "history",
31
- "knowledgeLedger": "secrets"
32
- },
33
- "openingActions": [
34
- {
35
- "id": "opening_open_ledger",
36
- "expected": {
37
- "flag": "opened_true_ledger",
38
- "absentFlag": "heard_all_five",
39
- "house": 69,
40
- "bonds": {
41
- "wu_yueniang|li_pinger": 6,
42
- "wu_yueniang|sun_xuee": 7
43
- }
44
- }
45
- },
46
- {
47
- "id": "opening_hear_five",
48
- "expected": {
49
- "flag": "heard_all_five",
50
- "absentFlag": "opened_true_ledger",
51
- "house": 65,
52
- "bonds": {
53
- "pan_jinlian|meng_yulou": -1,
54
- "pan_jinlian|sun_xuee": 10
55
- }
56
- }
57
- }
58
- ],
59
- "callbacks": [
60
- "publicEcho",
61
- "day15Text",
62
- "finalText",
63
- "endingTexts",
64
- "epilogueTexts",
65
- "fateText"
66
- ],
67
- "knowledgeProbe": {
68
- "opening": "opening_open_ledger",
69
- "action": "listen",
70
- "factId": "missing_fifty",
71
- "source": "正堂开账听来的口风",
72
- "confidence": "待互证",
73
- "expiresOn": 7
74
- },
75
- "replay": {
76
- "seed": 42,
77
- "openingAftermathBeats": 3,
78
- "expectedDayPhase": "day",
79
- "tamperedStateMustBeRejected": true
80
- },
81
- "validationPaths": {
82
- "primary": {
83
- "opening": "opening_open_ledger",
84
- "aftermathAdvances": 3,
85
- "expectedFlag": "opened_true_ledger",
86
- "absentFlag": "heard_all_five",
87
- "expectedHouse": 69,
88
- "expectedFeedback": "openingMemory 非空回调载荷存在"
89
- },
90
- "adjacentCounterexample": {
91
- "opening": "opening_hear_five",
92
- "aftermathAdvances": 3,
93
- "expectedFlag": "heard_all_five",
94
- "absentFlag": "opened_true_ledger",
95
- "expectedHouse": 65,
96
- "expectedFeedback": "openingMemory 非空回调载荷存在且分支摘要不同"
97
- }
98
- }
99
- }
@@ -1,41 +0,0 @@
1
- {
2
- "schemaVersion": 3,
3
- "status": "PASS",
4
- "verify": {
5
- "command": "cd examples/jin-ping-mei/build/app && python3 test/verify_visual.py --write-evidence",
6
- "exitCode": 0
7
- },
8
- "completeRun": {
9
- "id": "jin-ping-mei-visual-reconstruction-2026-09-05",
10
- "cleanContext": true,
11
- "terminal": "day-20-unstable-ending",
12
- "restart": "day-1-opening-new-seed",
13
- "evidence": "qa/evidence/run.json"
14
- },
15
- "checks": {
16
- "launch": "PASS",
17
- "render": "PASS",
18
- "input": "PASS",
19
- "coreLoop": "PASS",
20
- "outcome": "PASS",
21
- "restart": "PASS"
22
- },
23
- "limitations": [
24
- {
25
- "scope": "路径覆盖",
26
- "reason": "快速路径在每屏选择第一项可行主动作,只到达一个失稳结局;没有穷举其他选项或结局。"
27
- },
28
- {
29
- "scope": "输入覆盖",
30
- "reason": "本次使用 Playwright locator.click 且不使用 force;没有复测 2026-08 的全键盘正常速度路径。"
31
- },
32
- {
33
- "scope": "响应式覆盖",
34
- "reason": "五档视口覆盖标题与首日,390×844 和 1280×800 覆盖夜访,1280×800 覆盖本次结局;未声明五档完整二十日矩阵。"
35
- },
36
- {
37
- "scope": "体验判断",
38
- "reason": "自动化只证明当前候选可启动、渲染、输入、走到结果并重开,不判断主观吸引力、长期平衡或其他浏览器。"
39
- }
40
- ]
41
- }
@@ -1,152 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { createHash } from 'node:crypto';
3
- import { readFileSync } from 'node:fs';
4
- import { dirname, resolve } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
-
7
- const here = dirname(fileURLToPath(import.meta.url));
8
- const contract = JSON.parse(readFileSync(resolve(here, 'playable-model.json'), 'utf8'));
9
- const data = await import(resolve(here, '../build/app/js/data.js'));
10
- const engine = await import(resolve(here, '../build/app/js/engine.js'));
11
-
12
- const digest = (value) => createHash('sha256').update(JSON.stringify(value)).digest('hex');
13
- const assertText = (value, label) => assert.equal(typeof value === 'string' && value.length > 0, true, label);
14
- const ROUTE_RULES_DIGEST = '3b3c6bd6dc565ff05825d16738ef3a76ad87bd1392d7d149794dc55ff8c005fa';
15
-
16
- function routeRulesProjection() {
17
- const route = Object.fromEntries(Object.entries(data.ROUTE_CHOICES).map(([heroine, steps]) => [
18
- heroine,
19
- steps.map((choices) => choices.map((choice) => ({
20
- id: choice.id,
21
- effects: choice.effects,
22
- condition: choice.condition ?? null,
23
- }))),
24
- ]));
25
- const accord = Object.fromEntries(Object.entries(data.ACCORD_CHOICES).map(([heroine, choice]) => [
26
- heroine,
27
- { id: choice.id, effects: choice.effects, condition: choice.condition ?? null },
28
- ]));
29
- const shared = data.SHARED_NIGHT_CHOICES.map((choice) => ({
30
- id: choice.id,
31
- effects: choice.effects ?? null,
32
- condition: choice.condition ?? null,
33
- }));
34
- return { route, accord, shared };
35
- }
36
-
37
- function finishOpening(state) {
38
- let beats = 0;
39
- while (state.phase === 'opening_aftermath') {
40
- const current = engine.currentOpeningAftermath(state);
41
- assert.ok(current?.current, '开场后章必须存在当前拍');
42
- assert.equal(engine.advanceOpeningAftermath(state).ok, true);
43
- beats += 1;
44
- }
45
- assert.equal(beats, contract.replay.openingAftermathBeats);
46
- assert.equal(state.phase, contract.replay.expectedDayPhase);
47
- }
48
-
49
- function runOpening(action) {
50
- const state = engine.newGame(contract.replay.seed);
51
- assert.deepEqual(state.resources, contract.stateSurface.resources.initial);
52
- assert.deepEqual(Object.keys(state.relations), contract.stateSurface.relationshipActors);
53
- const eventLog = state[contract.stateSurface.eventLog];
54
- const knowledgeLedger = state[contract.stateSurface.knowledgeLedger];
55
- assert.equal(Array.isArray(eventLog), true, '事件日志字段必须指向数组');
56
- assert.equal(Array.isArray(knowledgeLedger), true, '知识账字段必须指向数组');
57
- assert.equal(engine.chooseOpening(state, action.id).ok, true);
58
- assert.equal(eventLog.length, 1);
59
- assert.deepEqual(eventLog[0], {
60
- day: 1,
61
- type: 'opening',
62
- choice: action.id,
63
- public: true,
64
- });
65
- assert.equal(state.flags[action.expected.flag], true);
66
- assert.equal(state.flags[action.expected.absentFlag], undefined, '未选起手不得污染 history/flags');
67
- assert.equal(state.resources.house, action.expected.house);
68
- for (const [key, value] of Object.entries(action.expected.bonds)) assert.equal(state.bonds[key], value, key);
69
-
70
- finishOpening(state);
71
- const memory = engine.openingMemory(state);
72
- assert.equal(memory.choice, action.id);
73
- for (const field of contract.callbacks) {
74
- if (field === 'endingTexts' || field === 'epilogueTexts') {
75
- assert.equal(Object.keys(memory[field]).length, 5, `${field} 应提供五份长期回调载荷`);
76
- for (const text of Object.values(memory[field])) assertText(text, `${field} 不得为空`);
77
- } else assertText(memory[field], `${field} 不得为空`);
78
- }
79
-
80
- const options = engine.dayOptions(state);
81
- assert.deepEqual(options.map(({ id }) => id), contract.stateSurface.dayActions);
82
- assert.equal(options.filter(({ resolvesPressure }) => resolvesPressure).length >= 1, true);
83
-
84
- const serialized = engine.serialize(state);
85
- assert.deepEqual(engine.deserialize(serialized), state, '合法 snapshot 必须从 history 重演通过');
86
- const tampered = JSON.parse(serialized);
87
- tampered.flags[action.expected.absentFlag] = true;
88
- assert.equal(engine.deserialize(JSON.stringify(tampered)), null, '未选分支注入必须拒读');
89
-
90
- return {
91
- state: engine.snapshot(state),
92
- digest: digest(state),
93
- };
94
- }
95
-
96
- function verifyKnowledgeLedger() {
97
- const probe = contract.knowledgeProbe;
98
- const state = engine.newGame(contract.replay.seed);
99
- assert.equal(engine.chooseOpening(state, probe.opening).ok, true);
100
- finishOpening(state);
101
- assert.equal(engine.chooseDayAction(state, probe.action).ok, true);
102
- assert.equal(state[contract.stateSurface.knowledgeLedger].includes(probe.factId), true, '知识账必须记录已获知事实');
103
- const fact = engine.secretInventory(state).find(({ id }) => id === probe.factId);
104
- assertText(fact?.label, '证物标签不得为空');
105
- assert.deepEqual(fact, {
106
- id: probe.factId,
107
- label: fact.label,
108
- source: probe.source,
109
- confidence: probe.confidence,
110
- expiresOn: probe.expiresOn,
111
- expired: false,
112
- selected: false,
113
- });
114
- assert.equal(state.selectedSecret, null, '获得事实不等于已经选择提交');
115
- assert.deepEqual(state.secretsUsed, [], '未选择的事实不得被动作标成已消费');
116
- assert.equal(state.history.at(-1).secretUsed, null, '事件日志不得伪造事实消费');
117
-
118
- const tampered = JSON.parse(engine.serialize(state));
119
- tampered.secretsUsed.push(probe.factId);
120
- assert.equal(engine.deserialize(JSON.stringify(tampered)), null, '伪造已消费事实必须拒读');
121
- }
122
-
123
- assert.equal(contract.schemaVersion, 1);
124
- assert.equal(contract.source, 'design/GAME_DESIGN.md#10-可执行切片合同');
125
- assert.equal(contract.experienceProfile, 'narrative-led');
126
- assert.equal(contract.buildPath, 'custom');
127
- assert.match(contract.versions.contentRevision, /^NOT_AVAILABLE:/);
128
- assert.match(contract.versions.rulesRevision, /^NOT_AVAILABLE:/);
129
- assert.equal(engine.SAVE_VERSION, contract.versions.saveSchema);
130
- assert.equal(contract.replay.tamperedStateMustBeRejected, true, '合同必须门控伪造状态拒读');
131
- assert.equal(contract.validationPaths.primary.opening, contract.openingActions[0].id);
132
- assert.equal(contract.validationPaths.adjacentCounterexample.opening, contract.openingActions[1].id);
133
- for (const [index, path] of Object.values(contract.validationPaths).entries()) {
134
- const action = contract.openingActions[index];
135
- assert.equal(path.aftermathAdvances, contract.replay.openingAftermathBeats);
136
- assert.equal(path.expectedFlag, action.expected.flag);
137
- assert.equal(path.absentFlag, action.expected.absentFlag);
138
- assert.equal(path.expectedHouse, action.expected.house);
139
- assertText(path.expectedFeedback, '固定验证路径必须声明预期反馈');
140
- }
141
- assert.deepEqual(Object.keys(data.DAY_ACTIONS), contract.stateSurface.dayActions);
142
- assert.deepEqual(data.HEROINE_IDS, contract.stateSurface.relationshipActors);
143
- assert.deepEqual(data.OPENING_CHOICES.map(({ id }) => id), contract.openingActions.map(({ id }) => id));
144
- assert.equal(digest(routeRulesProjection()), ROUTE_RULES_DIGEST, '文案改写不得改动五条路线、五院约或共享终夜的 id/condition/effects');
145
-
146
- const firstRuns = contract.openingActions.map(runOpening);
147
- const replayRuns = contract.openingActions.map(runOpening);
148
- assert.deepEqual(replayRuns.map(({ digest: value }) => value), firstRuns.map(({ digest: value }) => value));
149
- assert.notEqual(firstRuns[0].digest, firstRuns[1].digest, '两条起手必须产生可区分状态');
150
- verifyKnowledgeLedger();
151
-
152
- console.log('可执行改编合同:2 条起手、3 拍回响、非空回调载荷、知识来源、确定性重放与分支污染拒绝均一致');