@zwbigi/ink-xy 0.1.2 → 0.1.4

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 (598) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +2 -2
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/server/app/_global-error.html +1 -1
  5. package/.next/server/app/_global-error.rsc +1 -1
  6. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/server/app/_not-found.html +1 -1
  13. package/.next/server/app/_not-found.rsc +1 -1
  14. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  15. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  16. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  20. package/.next/server/app/api/inkos/route.js.nft.json +1 -1
  21. package/.next/server/app/api/skills/install/route.js.nft.json +1 -1
  22. package/.next/server/app/api/skills/search/route.js.nft.json +1 -1
  23. package/.next/server/app/index.html +1 -1
  24. package/.next/server/app/index.rsc +1 -1
  25. package/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  26. package/.next/server/app/index.segments/_full.segment.rsc +1 -1
  27. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  28. package/.next/server/app/index.segments/_index.segment.rsc +1 -1
  29. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  30. package/.next/server/app-paths-manifest.json +2 -2
  31. package/.next/server/chunks/162.js +1 -1
  32. package/.next/server/middleware-build-manifest.js +1 -1
  33. package/.next/server/pages/404.html +1 -1
  34. package/.next/server/pages/500.html +1 -1
  35. package/.next/trace +4 -4
  36. package/.next/trace-build +1 -1
  37. package/bin/pi-web.js +4 -1
  38. package/inkos/.env.example +20 -0
  39. package/inkos/.node-version +1 -0
  40. package/inkos/.nvmrc +1 -0
  41. package/inkos/CHANGELOG.md +787 -0
  42. package/inkos/CONTRIBUTING.md +89 -0
  43. package/inkos/LICENSE +661 -0
  44. package/inkos/README.en.md +483 -0
  45. package/inkos/README.ja.md +461 -0
  46. package/inkos/README.md +272 -0
  47. package/inkos/assets/15qun.jpg +0 -0
  48. package/inkos/assets/41777702961_.pic.jpg +0 -0
  49. package/inkos/assets/inkos-short-demo-cover.png +0 -0
  50. package/inkos/assets/inkos-text.svg +40 -0
  51. package/inkos/assets/logo.svg +47 -0
  52. package/inkos/assets/screenshot-chapters.png +0 -0
  53. package/inkos/assets/screenshot-pipeline.png +0 -0
  54. package/inkos/assets/screenshot-state.png +0 -0
  55. package/inkos/assets/screenshot-terminal.png +0 -0
  56. package/inkos/assets/wechat-group-v8.jpg +0 -0
  57. package/inkos/package.json +42 -0
  58. package/inkos/packages/cli/package.json +74 -0
  59. package/inkos/packages/cli/src/__tests__/analytics.test.ts +154 -0
  60. package/inkos/packages/cli/src/__tests__/cli-integration.test.ts +1031 -0
  61. package/inkos/packages/cli/src/__tests__/daemon.test.ts +93 -0
  62. package/inkos/packages/cli/src/__tests__/doctor.test.ts +36 -0
  63. package/inkos/packages/cli/src/__tests__/interact-command.test.ts +142 -0
  64. package/inkos/packages/cli/src/__tests__/interaction-tools.test.ts +107 -0
  65. package/inkos/packages/cli/src/__tests__/llm-overrides.test.ts +25 -0
  66. package/inkos/packages/cli/src/__tests__/localization.test.ts +121 -0
  67. package/inkos/packages/cli/src/__tests__/progress-text.test.ts +92 -0
  68. package/inkos/packages/cli/src/__tests__/project-bootstrap.test.ts +71 -0
  69. package/inkos/packages/cli/src/__tests__/publish-package.test.ts +272 -0
  70. package/inkos/packages/cli/src/__tests__/revision-command.test.ts +82 -0
  71. package/inkos/packages/cli/src/__tests__/runtime-requirements.test.ts +89 -0
  72. package/inkos/packages/cli/src/__tests__/short-fiction-command.test.ts +48 -0
  73. package/inkos/packages/cli/src/__tests__/studio-runtime.test.ts +142 -0
  74. package/inkos/packages/cli/src/__tests__/studio.test.ts +87 -0
  75. package/inkos/packages/cli/src/__tests__/tui-activity-state.test.ts +20 -0
  76. package/inkos/packages/cli/src/__tests__/tui-agent-session.test.ts +213 -0
  77. package/inkos/packages/cli/src/__tests__/tui-chat-depth.test.ts +27 -0
  78. package/inkos/packages/cli/src/__tests__/tui-chat-draft.test.ts +44 -0
  79. package/inkos/packages/cli/src/__tests__/tui-command.test.ts +86 -0
  80. package/inkos/packages/cli/src/__tests__/tui-composer-caret.test.ts +46 -0
  81. package/inkos/packages/cli/src/__tests__/tui-composer-display.test.ts +40 -0
  82. package/inkos/packages/cli/src/__tests__/tui-dashboard.test.tsx +219 -0
  83. package/inkos/packages/cli/src/__tests__/tui-effects-i18n.test.ts +29 -0
  84. package/inkos/packages/cli/src/__tests__/tui-i18n.test.ts +22 -0
  85. package/inkos/packages/cli/src/__tests__/tui-input-chrome.test.ts +10 -0
  86. package/inkos/packages/cli/src/__tests__/tui-input-history.test.ts +40 -0
  87. package/inkos/packages/cli/src/__tests__/tui-layout.test.ts +55 -0
  88. package/inkos/packages/cli/src/__tests__/tui-local-commands.test.ts +47 -0
  89. package/inkos/packages/cli/src/__tests__/tui-session-store.test.ts +81 -0
  90. package/inkos/packages/cli/src/__tests__/tui-setup-i18n.test.ts +31 -0
  91. package/inkos/packages/cli/src/__tests__/tui-slash-autocomplete.test.ts +33 -0
  92. package/inkos/packages/cli/src/commands/agent.ts +65 -0
  93. package/inkos/packages/cli/src/commands/analytics.ts +77 -0
  94. package/inkos/packages/cli/src/commands/audit.ts +52 -0
  95. package/inkos/packages/cli/src/commands/book.ts +260 -0
  96. package/inkos/packages/cli/src/commands/compose.ts +50 -0
  97. package/inkos/packages/cli/src/commands/config.ts +328 -0
  98. package/inkos/packages/cli/src/commands/consolidate.ts +50 -0
  99. package/inkos/packages/cli/src/commands/daemon.ts +121 -0
  100. package/inkos/packages/cli/src/commands/detect.ts +125 -0
  101. package/inkos/packages/cli/src/commands/doctor.ts +391 -0
  102. package/inkos/packages/cli/src/commands/draft.ts +43 -0
  103. package/inkos/packages/cli/src/commands/eval.ts +217 -0
  104. package/inkos/packages/cli/src/commands/export.ts +45 -0
  105. package/inkos/packages/cli/src/commands/fanfic.ts +183 -0
  106. package/inkos/packages/cli/src/commands/genre.ts +160 -0
  107. package/inkos/packages/cli/src/commands/import.ts +158 -0
  108. package/inkos/packages/cli/src/commands/init.ts +47 -0
  109. package/inkos/packages/cli/src/commands/interact.ts +109 -0
  110. package/inkos/packages/cli/src/commands/plan.ts +54 -0
  111. package/inkos/packages/cli/src/commands/radar.ts +60 -0
  112. package/inkos/packages/cli/src/commands/review.ts +253 -0
  113. package/inkos/packages/cli/src/commands/revise.ts +58 -0
  114. package/inkos/packages/cli/src/commands/short-fiction.ts +294 -0
  115. package/inkos/packages/cli/src/commands/status.ts +138 -0
  116. package/inkos/packages/cli/src/commands/studio.ts +194 -0
  117. package/inkos/packages/cli/src/commands/style.ts +99 -0
  118. package/inkos/packages/cli/src/commands/tui.ts +18 -0
  119. package/inkos/packages/cli/src/commands/update.ts +45 -0
  120. package/inkos/packages/cli/src/commands/write.ts +324 -0
  121. package/inkos/packages/cli/src/index.ts +5 -0
  122. package/inkos/packages/cli/src/interaction/tools.ts +49 -0
  123. package/inkos/packages/cli/src/localization.ts +215 -0
  124. package/inkos/packages/cli/src/program.ts +106 -0
  125. package/inkos/packages/cli/src/progress-text.ts +85 -0
  126. package/inkos/packages/cli/src/project-bootstrap.ts +175 -0
  127. package/inkos/packages/cli/src/runtime-requirements.ts +135 -0
  128. package/inkos/packages/cli/src/tui/__tests__/markdown.test.ts +64 -0
  129. package/inkos/packages/cli/src/tui/activity-state.ts +41 -0
  130. package/inkos/packages/cli/src/tui/agent-input.ts +264 -0
  131. package/inkos/packages/cli/src/tui/ansi.ts +72 -0
  132. package/inkos/packages/cli/src/tui/app.ts +130 -0
  133. package/inkos/packages/cli/src/tui/chat-depth.ts +22 -0
  134. package/inkos/packages/cli/src/tui/chat-draft.ts +42 -0
  135. package/inkos/packages/cli/src/tui/composer-caret.ts +22 -0
  136. package/inkos/packages/cli/src/tui/composer-display.ts +26 -0
  137. package/inkos/packages/cli/src/tui/dashboard-model.ts +164 -0
  138. package/inkos/packages/cli/src/tui/dashboard.tsx +544 -0
  139. package/inkos/packages/cli/src/tui/effects.ts +542 -0
  140. package/inkos/packages/cli/src/tui/i18n.ts +278 -0
  141. package/inkos/packages/cli/src/tui/input-history.ts +69 -0
  142. package/inkos/packages/cli/src/tui/local-commands.ts +55 -0
  143. package/inkos/packages/cli/src/tui/markdown.ts +64 -0
  144. package/inkos/packages/cli/src/tui/session-store.ts +6 -0
  145. package/inkos/packages/cli/src/tui/setup.ts +397 -0
  146. package/inkos/packages/cli/src/tui/slash-autocomplete.ts +62 -0
  147. package/inkos/packages/cli/src/tui/theme.ts +17 -0
  148. package/inkos/packages/cli/src/utils.ts +222 -0
  149. package/inkos/packages/cli/tsconfig.json +9 -0
  150. package/inkos/packages/core/genres/cozy.md +43 -0
  151. package/inkos/packages/core/genres/cultivation.md +42 -0
  152. package/inkos/packages/core/genres/dungeon-core.md +40 -0
  153. package/inkos/packages/core/genres/horror.md +51 -0
  154. package/inkos/packages/core/genres/isekai.md +43 -0
  155. package/inkos/packages/core/genres/litrpg.md +43 -0
  156. package/inkos/packages/core/genres/other.md +24 -0
  157. package/inkos/packages/core/genres/progression.md +41 -0
  158. package/inkos/packages/core/genres/romantasy.md +45 -0
  159. package/inkos/packages/core/genres/sci-fi.md +42 -0
  160. package/inkos/packages/core/genres/system-apocalypse.md +40 -0
  161. package/inkos/packages/core/genres/tower-climber.md +41 -0
  162. package/inkos/packages/core/genres/urban.md +53 -0
  163. package/inkos/packages/core/genres/xianxia.md +46 -0
  164. package/inkos/packages/core/genres/xuanhuan.md +64 -0
  165. package/inkos/packages/core/package.json +61 -0
  166. package/inkos/packages/core/src/__tests__/agent-max-tokens-policy.test.ts +29 -0
  167. package/inkos/packages/core/src/__tests__/agent-session.test.ts +866 -0
  168. package/inkos/packages/core/src/__tests__/agent-system-prompt.test.ts +167 -0
  169. package/inkos/packages/core/src/__tests__/agent-tools-params.test.ts +197 -0
  170. package/inkos/packages/core/src/__tests__/agent-tools.test.ts +421 -0
  171. package/inkos/packages/core/src/__tests__/ai-tells.test.ts +90 -0
  172. package/inkos/packages/core/src/__tests__/architect-phase5-consolidated.test.ts +445 -0
  173. package/inkos/packages/core/src/__tests__/architect-phase5.test.ts +455 -0
  174. package/inkos/packages/core/src/__tests__/architect-phase7.test.ts +210 -0
  175. package/inkos/packages/core/src/__tests__/architect.test.ts +859 -0
  176. package/inkos/packages/core/src/__tests__/audit-parse.test.ts +78 -0
  177. package/inkos/packages/core/src/__tests__/book-id.test.ts +26 -0
  178. package/inkos/packages/core/src/__tests__/book-session-store.test.ts +447 -0
  179. package/inkos/packages/core/src/__tests__/book-session.test.ts +113 -0
  180. package/inkos/packages/core/src/__tests__/chapter-analyzer.test.ts +574 -0
  181. package/inkos/packages/core/src/__tests__/chapter-memo-parser.test.ts +247 -0
  182. package/inkos/packages/core/src/__tests__/chapter-persistence.test.ts +198 -0
  183. package/inkos/packages/core/src/__tests__/chapter-review-cycle.test.ts +294 -0
  184. package/inkos/packages/core/src/__tests__/chapter-splitter.test.ts +156 -0
  185. package/inkos/packages/core/src/__tests__/chapter-state-recovery.test.ts +235 -0
  186. package/inkos/packages/core/src/__tests__/chapter-truth-validation.test.ts +253 -0
  187. package/inkos/packages/core/src/__tests__/composer.test.ts +627 -0
  188. package/inkos/packages/core/src/__tests__/config-loader.test.ts +325 -0
  189. package/inkos/packages/core/src/__tests__/config-migration.test.ts +102 -0
  190. package/inkos/packages/core/src/__tests__/consolidator.test.ts +32 -0
  191. package/inkos/packages/core/src/__tests__/context-filter.test.ts +60 -0
  192. package/inkos/packages/core/src/__tests__/context-transform.test.ts +108 -0
  193. package/inkos/packages/core/src/__tests__/continuity.test.ts +391 -0
  194. package/inkos/packages/core/src/__tests__/detection-insights.test.ts +59 -0
  195. package/inkos/packages/core/src/__tests__/detector.test.ts +86 -0
  196. package/inkos/packages/core/src/__tests__/draft-directive-parser.test.ts +386 -0
  197. package/inkos/packages/core/src/__tests__/edit-controller.test.ts +190 -0
  198. package/inkos/packages/core/src/__tests__/effective-llm-config.test.ts +486 -0
  199. package/inkos/packages/core/src/__tests__/fanfic-dimensions.test.ts +58 -0
  200. package/inkos/packages/core/src/__tests__/fanfic-models.test.ts +69 -0
  201. package/inkos/packages/core/src/__tests__/governed-working-set.test.ts +155 -0
  202. package/inkos/packages/core/src/__tests__/hook-arbiter.test.ts +124 -0
  203. package/inkos/packages/core/src/__tests__/hook-governance.test.ts +228 -0
  204. package/inkos/packages/core/src/__tests__/hook-health.test.ts +166 -0
  205. package/inkos/packages/core/src/__tests__/hook-ledger-validator.test.ts +236 -0
  206. package/inkos/packages/core/src/__tests__/hook-promotion.test.ts +192 -0
  207. package/inkos/packages/core/src/__tests__/hook-stale-detection.test.ts +136 -0
  208. package/inkos/packages/core/src/__tests__/index-notify-lazy.test.ts +20 -0
  209. package/inkos/packages/core/src/__tests__/interaction-chat-tokens.test.ts +170 -0
  210. package/inkos/packages/core/src/__tests__/interaction-models.test.ts +155 -0
  211. package/inkos/packages/core/src/__tests__/interaction-nl-router.test.ts +223 -0
  212. package/inkos/packages/core/src/__tests__/interaction-runtime.test.ts +633 -0
  213. package/inkos/packages/core/src/__tests__/interaction-tools.test.ts +343 -0
  214. package/inkos/packages/core/src/__tests__/length-metrics.test.ts +82 -0
  215. package/inkos/packages/core/src/__tests__/length-normalizer.test.ts +331 -0
  216. package/inkos/packages/core/src/__tests__/list-models.test.ts +109 -0
  217. package/inkos/packages/core/src/__tests__/llm-env.test.ts +31 -0
  218. package/inkos/packages/core/src/__tests__/logger.test.ts +175 -0
  219. package/inkos/packages/core/src/__tests__/long-span-fatigue.test.ts +160 -0
  220. package/inkos/packages/core/src/__tests__/memory-retrieval.test.ts +1303 -0
  221. package/inkos/packages/core/src/__tests__/models.test.ts +918 -0
  222. package/inkos/packages/core/src/__tests__/outline-paths.test.ts +97 -0
  223. package/inkos/packages/core/src/__tests__/path-safety.test.ts +22 -0
  224. package/inkos/packages/core/src/__tests__/persisted-governed-plan.test.ts +134 -0
  225. package/inkos/packages/core/src/__tests__/phase5-cleanup.test.ts +393 -0
  226. package/inkos/packages/core/src/__tests__/phase5-hotfix.test.ts +288 -0
  227. package/inkos/packages/core/src/__tests__/phase7-hotfix.test.ts +614 -0
  228. package/inkos/packages/core/src/__tests__/pipeline-agent.test.ts +354 -0
  229. package/inkos/packages/core/src/__tests__/pipeline-runner-memory-sync.test.ts +317 -0
  230. package/inkos/packages/core/src/__tests__/pipeline-runner.test.ts +5200 -0
  231. package/inkos/packages/core/src/__tests__/planner-context.test.ts +137 -0
  232. package/inkos/packages/core/src/__tests__/planner-prompts-ratio.test.ts +11 -0
  233. package/inkos/packages/core/src/__tests__/planner-prompts.test.ts +171 -0
  234. package/inkos/packages/core/src/__tests__/planner.test.ts +362 -0
  235. package/inkos/packages/core/src/__tests__/planning-materials.test.ts +90 -0
  236. package/inkos/packages/core/src/__tests__/polisher.test.ts +189 -0
  237. package/inkos/packages/core/src/__tests__/post-write-validator.test.ts +291 -0
  238. package/inkos/packages/core/src/__tests__/probe.test.ts +77 -0
  239. package/inkos/packages/core/src/__tests__/project-interaction.test.ts +241 -0
  240. package/inkos/packages/core/src/__tests__/provider.test.ts +953 -0
  241. package/inkos/packages/core/src/__tests__/providers-group.test.ts +34 -0
  242. package/inkos/packages/core/src/__tests__/providers-lookup.test.ts +81 -0
  243. package/inkos/packages/core/src/__tests__/providers-schema.test.ts +158 -0
  244. package/inkos/packages/core/src/__tests__/proxy-fetch.test.ts +75 -0
  245. package/inkos/packages/core/src/__tests__/revise-foundation.test.ts +514 -0
  246. package/inkos/packages/core/src/__tests__/reviser.test.ts +859 -0
  247. package/inkos/packages/core/src/__tests__/runtime-state-store.test.ts +388 -0
  248. package/inkos/packages/core/src/__tests__/scheduler.test.ts +123 -0
  249. package/inkos/packages/core/src/__tests__/secrets-migration.test.ts +71 -0
  250. package/inkos/packages/core/src/__tests__/secrets.test.ts +95 -0
  251. package/inkos/packages/core/src/__tests__/sensitive-words.test.ts +88 -0
  252. package/inkos/packages/core/src/__tests__/service-presets-regression.test.ts +73 -0
  253. package/inkos/packages/core/src/__tests__/service-resolver-regression.test.ts +75 -0
  254. package/inkos/packages/core/src/__tests__/service-resolver.test.ts +228 -0
  255. package/inkos/packages/core/src/__tests__/session-transcript-restore.test.ts +1311 -0
  256. package/inkos/packages/core/src/__tests__/session-transcript.test.ts +195 -0
  257. package/inkos/packages/core/src/__tests__/settler-delta-parser.test.ts +133 -0
  258. package/inkos/packages/core/src/__tests__/short-fiction-public.test.ts +241 -0
  259. package/inkos/packages/core/src/__tests__/spot-fix-patches.test.ts +104 -0
  260. package/inkos/packages/core/src/__tests__/state-manager.test.ts +1298 -0
  261. package/inkos/packages/core/src/__tests__/state-projections.test.ts +130 -0
  262. package/inkos/packages/core/src/__tests__/state-reducer.test.ts +372 -0
  263. package/inkos/packages/core/src/__tests__/state-validator-agent.test.ts +165 -0
  264. package/inkos/packages/core/src/__tests__/state-validator.test.ts +122 -0
  265. package/inkos/packages/core/src/__tests__/style-analyzer.test.ts +61 -0
  266. package/inkos/packages/core/src/__tests__/temperature-constraints.test.ts +57 -0
  267. package/inkos/packages/core/src/__tests__/v13-hotfix-round4.test.ts +343 -0
  268. package/inkos/packages/core/src/__tests__/verify-service.test.ts +77 -0
  269. package/inkos/packages/core/src/__tests__/webhook.test.ts +91 -0
  270. package/inkos/packages/core/src/__tests__/writer-parser.test.ts +348 -0
  271. package/inkos/packages/core/src/__tests__/writer-prompts.test.ts +269 -0
  272. package/inkos/packages/core/src/__tests__/writer.test.ts +1360 -0
  273. package/inkos/packages/core/src/agent/agent-session.ts +737 -0
  274. package/inkos/packages/core/src/agent/agent-system-prompt.ts +199 -0
  275. package/inkos/packages/core/src/agent/agent-tools.ts +835 -0
  276. package/inkos/packages/core/src/agent/context-transform.ts +85 -0
  277. package/inkos/packages/core/src/agent/index.ts +14 -0
  278. package/inkos/packages/core/src/agents/ai-tells.ts +161 -0
  279. package/inkos/packages/core/src/agents/architect.ts +1291 -0
  280. package/inkos/packages/core/src/agents/base.ts +100 -0
  281. package/inkos/packages/core/src/agents/chapter-analyzer.ts +634 -0
  282. package/inkos/packages/core/src/agents/composer.ts +469 -0
  283. package/inkos/packages/core/src/agents/consolidator.ts +218 -0
  284. package/inkos/packages/core/src/agents/continuity.ts +824 -0
  285. package/inkos/packages/core/src/agents/detection-insights.ts +72 -0
  286. package/inkos/packages/core/src/agents/detector.ts +224 -0
  287. package/inkos/packages/core/src/agents/en-prompt-sections.ts +129 -0
  288. package/inkos/packages/core/src/agents/fanfic-canon-importer.ts +146 -0
  289. package/inkos/packages/core/src/agents/fanfic-dimensions.ts +87 -0
  290. package/inkos/packages/core/src/agents/fanfic-prompt-sections.ts +109 -0
  291. package/inkos/packages/core/src/agents/foundation-reviewer.ts +204 -0
  292. package/inkos/packages/core/src/agents/length-normalizer.ts +218 -0
  293. package/inkos/packages/core/src/agents/observer-prompts.ts +127 -0
  294. package/inkos/packages/core/src/agents/planner-context.ts +297 -0
  295. package/inkos/packages/core/src/agents/planner-prompts.ts +404 -0
  296. package/inkos/packages/core/src/agents/planner.ts +783 -0
  297. package/inkos/packages/core/src/agents/polisher.ts +153 -0
  298. package/inkos/packages/core/src/agents/post-write-validator.ts +873 -0
  299. package/inkos/packages/core/src/agents/radar-source.ts +123 -0
  300. package/inkos/packages/core/src/agents/radar.ts +120 -0
  301. package/inkos/packages/core/src/agents/reviser.ts +701 -0
  302. package/inkos/packages/core/src/agents/rules-reader.ts +155 -0
  303. package/inkos/packages/core/src/agents/sensitive-words.ts +142 -0
  304. package/inkos/packages/core/src/agents/settler-delta-parser.ts +53 -0
  305. package/inkos/packages/core/src/agents/settler-parser.ts +38 -0
  306. package/inkos/packages/core/src/agents/settler-prompts.ts +230 -0
  307. package/inkos/packages/core/src/agents/short-fiction.ts +429 -0
  308. package/inkos/packages/core/src/agents/state-validator.ts +322 -0
  309. package/inkos/packages/core/src/agents/style-analyzer.ts +93 -0
  310. package/inkos/packages/core/src/agents/writer-parser.ts +178 -0
  311. package/inkos/packages/core/src/agents/writer-prompts.ts +899 -0
  312. package/inkos/packages/core/src/agents/writer.ts +1450 -0
  313. package/inkos/packages/core/src/index.ts +392 -0
  314. package/inkos/packages/core/src/interaction/book-session-store.ts +226 -0
  315. package/inkos/packages/core/src/interaction/draft-directive-parser.ts +266 -0
  316. package/inkos/packages/core/src/interaction/edit-controller.ts +270 -0
  317. package/inkos/packages/core/src/interaction/events.ts +41 -0
  318. package/inkos/packages/core/src/interaction/export-artifact.ts +151 -0
  319. package/inkos/packages/core/src/interaction/intents.ts +63 -0
  320. package/inkos/packages/core/src/interaction/modes.ts +13 -0
  321. package/inkos/packages/core/src/interaction/nl-router.ts +258 -0
  322. package/inkos/packages/core/src/interaction/project-control.ts +150 -0
  323. package/inkos/packages/core/src/interaction/project-session-store.ts +81 -0
  324. package/inkos/packages/core/src/interaction/project-tools.ts +704 -0
  325. package/inkos/packages/core/src/interaction/request-router.ts +5 -0
  326. package/inkos/packages/core/src/interaction/runtime.ts +1167 -0
  327. package/inkos/packages/core/src/interaction/session-transcript-legacy.ts +113 -0
  328. package/inkos/packages/core/src/interaction/session-transcript-restore.ts +607 -0
  329. package/inkos/packages/core/src/interaction/session-transcript-schema.ts +76 -0
  330. package/inkos/packages/core/src/interaction/session-transcript.ts +189 -0
  331. package/inkos/packages/core/src/interaction/session.ts +226 -0
  332. package/inkos/packages/core/src/interaction/truth-authority.ts +45 -0
  333. package/inkos/packages/core/src/llm/config-migration.ts +58 -0
  334. package/inkos/packages/core/src/llm/cover-providers.ts +45 -0
  335. package/inkos/packages/core/src/llm/provider.ts +1331 -0
  336. package/inkos/packages/core/src/llm/providers/endpoints/ai360.ts +42 -0
  337. package/inkos/packages/core/src/llm/providers/endpoints/anthropic.ts +82 -0
  338. package/inkos/packages/core/src/llm/providers/endpoints/astronCodingPlan.ts +30 -0
  339. package/inkos/packages/core/src/llm/providers/endpoints/baichuan.ts +28 -0
  340. package/inkos/packages/core/src/llm/providers/endpoints/bailian.ts +65 -0
  341. package/inkos/packages/core/src/llm/providers/endpoints/bailianCodingPlan.ts +30 -0
  342. package/inkos/packages/core/src/llm/providers/endpoints/custom.ts +22 -0
  343. package/inkos/packages/core/src/llm/providers/endpoints/deepseek.ts +35 -0
  344. package/inkos/packages/core/src/llm/providers/endpoints/giteeai.ts +41 -0
  345. package/inkos/packages/core/src/llm/providers/endpoints/githubCopilot.ts +43 -0
  346. package/inkos/packages/core/src/llm/providers/endpoints/glmCodingPlan.ts +28 -0
  347. package/inkos/packages/core/src/llm/providers/endpoints/google.ts +51 -0
  348. package/inkos/packages/core/src/llm/providers/endpoints/hunyuan.ts +42 -0
  349. package/inkos/packages/core/src/llm/providers/endpoints/infiniai.ts +72 -0
  350. package/inkos/packages/core/src/llm/providers/endpoints/internlm.ts +28 -0
  351. package/inkos/packages/core/src/llm/providers/endpoints/kimiCode.ts +23 -0
  352. package/inkos/packages/core/src/llm/providers/endpoints/kimiCodingPlan.ts +24 -0
  353. package/inkos/packages/core/src/llm/providers/endpoints/kkaiapi.ts +56 -0
  354. package/inkos/packages/core/src/llm/providers/endpoints/longcat.ts +25 -0
  355. package/inkos/packages/core/src/llm/providers/endpoints/minimax.ts +39 -0
  356. package/inkos/packages/core/src/llm/providers/endpoints/minimaxCodingPlan.ts +28 -0
  357. package/inkos/packages/core/src/llm/providers/endpoints/mistral.ts +40 -0
  358. package/inkos/packages/core/src/llm/providers/endpoints/modelscope.ts +30 -0
  359. package/inkos/packages/core/src/llm/providers/endpoints/moonshot.ts +39 -0
  360. package/inkos/packages/core/src/llm/providers/endpoints/newapi.ts +21 -0
  361. package/inkos/packages/core/src/llm/providers/endpoints/ollama.ts +73 -0
  362. package/inkos/packages/core/src/llm/providers/endpoints/openai.ts +77 -0
  363. package/inkos/packages/core/src/llm/providers/endpoints/opencodeCodingPlan.ts +30 -0
  364. package/inkos/packages/core/src/llm/providers/endpoints/openrouter.ts +87 -0
  365. package/inkos/packages/core/src/llm/providers/endpoints/ppio.ts +86 -0
  366. package/inkos/packages/core/src/llm/providers/endpoints/qiniu.ts +32 -0
  367. package/inkos/packages/core/src/llm/providers/endpoints/sensenova.ts +45 -0
  368. package/inkos/packages/core/src/llm/providers/endpoints/siliconcloud.ts +126 -0
  369. package/inkos/packages/core/src/llm/providers/endpoints/spark.ts +33 -0
  370. package/inkos/packages/core/src/llm/providers/endpoints/stepfun.ts +35 -0
  371. package/inkos/packages/core/src/llm/providers/endpoints/tencentcloud.ts +25 -0
  372. package/inkos/packages/core/src/llm/providers/endpoints/volcengine.ts +52 -0
  373. package/inkos/packages/core/src/llm/providers/endpoints/volcengineCodingPlan.ts +42 -0
  374. package/inkos/packages/core/src/llm/providers/endpoints/wenxin.ts +106 -0
  375. package/inkos/packages/core/src/llm/providers/endpoints/xai.ts +34 -0
  376. package/inkos/packages/core/src/llm/providers/endpoints/xiaomimimo.ts +26 -0
  377. package/inkos/packages/core/src/llm/providers/endpoints/zeroone.ts +34 -0
  378. package/inkos/packages/core/src/llm/providers/endpoints/zhipu.ts +61 -0
  379. package/inkos/packages/core/src/llm/providers/index.ts +71 -0
  380. package/inkos/packages/core/src/llm/providers/lookup.ts +70 -0
  381. package/inkos/packages/core/src/llm/providers/probe.ts +35 -0
  382. package/inkos/packages/core/src/llm/providers/types.ts +89 -0
  383. package/inkos/packages/core/src/llm/providers/verify.ts +104 -0
  384. package/inkos/packages/core/src/llm/secrets.ts +77 -0
  385. package/inkos/packages/core/src/llm/service-presets.ts +215 -0
  386. package/inkos/packages/core/src/llm/service-resolver.ts +91 -0
  387. package/inkos/packages/core/src/models/book-rules.ts +126 -0
  388. package/inkos/packages/core/src/models/book.ts +70 -0
  389. package/inkos/packages/core/src/models/chapter.ts +42 -0
  390. package/inkos/packages/core/src/models/detection.ts +25 -0
  391. package/inkos/packages/core/src/models/genre-profile.ts +36 -0
  392. package/inkos/packages/core/src/models/input-governance.ts +99 -0
  393. package/inkos/packages/core/src/models/length-governance.ts +46 -0
  394. package/inkos/packages/core/src/models/project.ts +161 -0
  395. package/inkos/packages/core/src/models/runtime-state.ts +144 -0
  396. package/inkos/packages/core/src/models/state.ts +52 -0
  397. package/inkos/packages/core/src/models/style-profile.ts +15 -0
  398. package/inkos/packages/core/src/notify/dispatcher.ts +96 -0
  399. package/inkos/packages/core/src/notify/feishu.ts +34 -0
  400. package/inkos/packages/core/src/notify/telegram.ts +25 -0
  401. package/inkos/packages/core/src/notify/webhook.ts +58 -0
  402. package/inkos/packages/core/src/notify/wechat-work.ts +22 -0
  403. package/inkos/packages/core/src/pipeline/agent.ts +691 -0
  404. package/inkos/packages/core/src/pipeline/chapter-persistence.ts +79 -0
  405. package/inkos/packages/core/src/pipeline/chapter-review-cycle.ts +324 -0
  406. package/inkos/packages/core/src/pipeline/chapter-state-recovery.ts +236 -0
  407. package/inkos/packages/core/src/pipeline/chapter-truth-validation.ts +145 -0
  408. package/inkos/packages/core/src/pipeline/detection-runner.ts +164 -0
  409. package/inkos/packages/core/src/pipeline/persisted-governed-plan.ts +216 -0
  410. package/inkos/packages/core/src/pipeline/runner.ts +3438 -0
  411. package/inkos/packages/core/src/pipeline/scheduler.ts +411 -0
  412. package/inkos/packages/core/src/pipeline/short-fiction-runner.ts +801 -0
  413. package/inkos/packages/core/src/prompts/index.ts +1 -0
  414. package/inkos/packages/core/src/prompts/short-fiction.ts +273 -0
  415. package/inkos/packages/core/src/state/manager.ts +560 -0
  416. package/inkos/packages/core/src/state/memory-db.ts +359 -0
  417. package/inkos/packages/core/src/state/runtime-state-store.ts +164 -0
  418. package/inkos/packages/core/src/state/state-bootstrap.ts +657 -0
  419. package/inkos/packages/core/src/state/state-projections.ts +255 -0
  420. package/inkos/packages/core/src/state/state-reducer.ts +260 -0
  421. package/inkos/packages/core/src/state/state-validator.ts +117 -0
  422. package/inkos/packages/core/src/utils/analytics.ts +92 -0
  423. package/inkos/packages/core/src/utils/book-id.ts +31 -0
  424. package/inkos/packages/core/src/utils/cadence-policy.ts +46 -0
  425. package/inkos/packages/core/src/utils/chapter-cadence.ts +211 -0
  426. package/inkos/packages/core/src/utils/chapter-memo-parser.ts +157 -0
  427. package/inkos/packages/core/src/utils/chapter-splitter.ts +80 -0
  428. package/inkos/packages/core/src/utils/config-loader.ts +29 -0
  429. package/inkos/packages/core/src/utils/context-assembly.ts +98 -0
  430. package/inkos/packages/core/src/utils/context-filter.ts +190 -0
  431. package/inkos/packages/core/src/utils/effective-llm-config.ts +529 -0
  432. package/inkos/packages/core/src/utils/governed-context.ts +101 -0
  433. package/inkos/packages/core/src/utils/governed-working-set.ts +395 -0
  434. package/inkos/packages/core/src/utils/hook-arbiter.ts +332 -0
  435. package/inkos/packages/core/src/utils/hook-governance.ts +199 -0
  436. package/inkos/packages/core/src/utils/hook-health.ts +189 -0
  437. package/inkos/packages/core/src/utils/hook-ledger-validator.ts +277 -0
  438. package/inkos/packages/core/src/utils/hook-lifecycle.ts +224 -0
  439. package/inkos/packages/core/src/utils/hook-policy.ts +115 -0
  440. package/inkos/packages/core/src/utils/hook-promotion.ts +313 -0
  441. package/inkos/packages/core/src/utils/hook-stale-detection.ts +168 -0
  442. package/inkos/packages/core/src/utils/length-metrics.ts +123 -0
  443. package/inkos/packages/core/src/utils/llm-endpoint-auth.ts +40 -0
  444. package/inkos/packages/core/src/utils/llm-env.ts +74 -0
  445. package/inkos/packages/core/src/utils/logger.ts +123 -0
  446. package/inkos/packages/core/src/utils/long-span-fatigue.ts +545 -0
  447. package/inkos/packages/core/src/utils/memory-retrieval.ts +527 -0
  448. package/inkos/packages/core/src/utils/narrative-control.ts +177 -0
  449. package/inkos/packages/core/src/utils/outline-paths.ts +275 -0
  450. package/inkos/packages/core/src/utils/path-safety.ts +11 -0
  451. package/inkos/packages/core/src/utils/planning-materials.ts +185 -0
  452. package/inkos/packages/core/src/utils/pov-filter.ts +149 -0
  453. package/inkos/packages/core/src/utils/proxy-fetch.ts +44 -0
  454. package/inkos/packages/core/src/utils/runtime-writer.ts +41 -0
  455. package/inkos/packages/core/src/utils/spot-fix-patches.ts +189 -0
  456. package/inkos/packages/core/src/utils/story-markdown.ts +346 -0
  457. package/inkos/packages/core/src/utils/web-search.ts +82 -0
  458. package/inkos/packages/core/src/utils/writing-methodology.ts +164 -0
  459. package/inkos/packages/core/tsconfig.json +8 -0
  460. package/inkos/packages/core/vitest.config.ts +7 -0
  461. package/inkos/packages/studio/components.json +25 -0
  462. package/inkos/packages/studio/index.html +13 -0
  463. package/inkos/packages/studio/package.json +72 -0
  464. package/inkos/packages/studio/postcss.config.js +3 -0
  465. package/inkos/packages/studio/src/App.test.ts +25 -0
  466. package/inkos/packages/studio/src/App.tsx +280 -0
  467. package/inkos/packages/studio/src/api/__tests__/normalize-base-url.test.ts +40 -0
  468. package/inkos/packages/studio/src/api/book-create.test.ts +104 -0
  469. package/inkos/packages/studio/src/api/book-create.ts +94 -0
  470. package/inkos/packages/studio/src/api/errors.ts +17 -0
  471. package/inkos/packages/studio/src/api/index.ts +30 -0
  472. package/inkos/packages/studio/src/api/lib/run-store.ts +177 -0
  473. package/inkos/packages/studio/src/api/lib/sse.ts +50 -0
  474. package/inkos/packages/studio/src/api/phase5-hotfix.test.ts +335 -0
  475. package/inkos/packages/studio/src/api/safety.ts +6 -0
  476. package/inkos/packages/studio/src/api/server.test.ts +3162 -0
  477. package/inkos/packages/studio/src/api/server.ts +3666 -0
  478. package/inkos/packages/studio/src/api/v13-hotfix-round4.test.ts +226 -0
  479. package/inkos/packages/studio/src/app-state.test.ts +8 -0
  480. package/inkos/packages/studio/src/app-state.ts +1 -0
  481. package/inkos/packages/studio/src/components/ConfirmDialog.tsx +95 -0
  482. package/inkos/packages/studio/src/components/ServiceConfigSourceCard.tsx +139 -0
  483. package/inkos/packages/studio/src/components/ServiceQuickLinks.tsx +65 -0
  484. package/inkos/packages/studio/src/components/Sidebar.tsx +652 -0
  485. package/inkos/packages/studio/src/components/ai-elements/code-block.tsx +562 -0
  486. package/inkos/packages/studio/src/components/ai-elements/confirmation.tsx +174 -0
  487. package/inkos/packages/studio/src/components/ai-elements/message.tsx +360 -0
  488. package/inkos/packages/studio/src/components/ai-elements/prompt-input.tsx +1457 -0
  489. package/inkos/packages/studio/src/components/ai-elements/reasoning.tsx +226 -0
  490. package/inkos/packages/studio/src/components/ai-elements/shimmer.tsx +77 -0
  491. package/inkos/packages/studio/src/components/ai-elements/tool.tsx +173 -0
  492. package/inkos/packages/studio/src/components/chat/BookSidebar.tsx +291 -0
  493. package/inkos/packages/studio/src/components/chat/ChatMessage.tsx +39 -0
  494. package/inkos/packages/studio/src/components/chat/QuickActions.tsx +73 -0
  495. package/inkos/packages/studio/src/components/chat/ToolExecutionSteps.tsx +320 -0
  496. package/inkos/packages/studio/src/components/chat/__tests__/ToolExecutionSteps.test.ts +114 -0
  497. package/inkos/packages/studio/src/components/chat-utils.ts +56 -0
  498. package/inkos/packages/studio/src/components/chatbar-state.test.ts +69 -0
  499. package/inkos/packages/studio/src/components/sidebar/ChaptersSection.tsx +66 -0
  500. package/inkos/packages/studio/src/components/sidebar/CharacterSection.tsx +129 -0
  501. package/inkos/packages/studio/src/components/sidebar/FoundationSection.tsx +61 -0
  502. package/inkos/packages/studio/src/components/sidebar/ProgressSection.tsx +124 -0
  503. package/inkos/packages/studio/src/components/sidebar/SidebarCard.tsx +30 -0
  504. package/inkos/packages/studio/src/components/sidebar/SummarySection.tsx +89 -0
  505. package/inkos/packages/studio/src/components/ui/alert.tsx +76 -0
  506. package/inkos/packages/studio/src/components/ui/badge.tsx +52 -0
  507. package/inkos/packages/studio/src/components/ui/button-group.tsx +87 -0
  508. package/inkos/packages/studio/src/components/ui/button.tsx +58 -0
  509. package/inkos/packages/studio/src/components/ui/collapsible.tsx +19 -0
  510. package/inkos/packages/studio/src/components/ui/command.tsx +194 -0
  511. package/inkos/packages/studio/src/components/ui/dialog.tsx +158 -0
  512. package/inkos/packages/studio/src/components/ui/dropdown-menu.tsx +266 -0
  513. package/inkos/packages/studio/src/components/ui/hover-card.tsx +51 -0
  514. package/inkos/packages/studio/src/components/ui/input-group.tsx +158 -0
  515. package/inkos/packages/studio/src/components/ui/input.tsx +20 -0
  516. package/inkos/packages/studio/src/components/ui/select.tsx +199 -0
  517. package/inkos/packages/studio/src/components/ui/separator.tsx +23 -0
  518. package/inkos/packages/studio/src/components/ui/spinner.tsx +10 -0
  519. package/inkos/packages/studio/src/components/ui/textarea.tsx +18 -0
  520. package/inkos/packages/studio/src/components/ui/tooltip.tsx +66 -0
  521. package/inkos/packages/studio/src/constants/service-groups.ts +29 -0
  522. package/inkos/packages/studio/src/hooks/use-api.test.ts +93 -0
  523. package/inkos/packages/studio/src/hooks/use-api.ts +189 -0
  524. package/inkos/packages/studio/src/hooks/use-book-activity.test.ts +129 -0
  525. package/inkos/packages/studio/src/hooks/use-book-activity.ts +180 -0
  526. package/inkos/packages/studio/src/hooks/use-colors.ts +27 -0
  527. package/inkos/packages/studio/src/hooks/use-hash-route.test.ts +101 -0
  528. package/inkos/packages/studio/src/hooks/use-hash-route.ts +89 -0
  529. package/inkos/packages/studio/src/hooks/use-i18n.ts +289 -0
  530. package/inkos/packages/studio/src/hooks/use-session-events.ts +64 -0
  531. package/inkos/packages/studio/src/hooks/use-sse.test.ts +52 -0
  532. package/inkos/packages/studio/src/hooks/use-sse.ts +92 -0
  533. package/inkos/packages/studio/src/hooks/use-theme.test.ts +31 -0
  534. package/inkos/packages/studio/src/hooks/use-theme.ts +75 -0
  535. package/inkos/packages/studio/src/index.css +323 -0
  536. package/inkos/packages/studio/src/lib/error-copy.test.ts +34 -0
  537. package/inkos/packages/studio/src/lib/error-copy.ts +37 -0
  538. package/inkos/packages/studio/src/lib/utils.ts +6 -0
  539. package/inkos/packages/studio/src/main.tsx +10 -0
  540. package/inkos/packages/studio/src/pages/Analytics.tsx +80 -0
  541. package/inkos/packages/studio/src/pages/BookCreate.tsx +895 -0
  542. package/inkos/packages/studio/src/pages/BookDetail.tsx +652 -0
  543. package/inkos/packages/studio/src/pages/ChapterReader.tsx +266 -0
  544. package/inkos/packages/studio/src/pages/ChatPage.tsx +521 -0
  545. package/inkos/packages/studio/src/pages/DaemonControl.tsx +116 -0
  546. package/inkos/packages/studio/src/pages/Dashboard.tsx +379 -0
  547. package/inkos/packages/studio/src/pages/DoctorView.tsx +82 -0
  548. package/inkos/packages/studio/src/pages/GenreManager.tsx +464 -0
  549. package/inkos/packages/studio/src/pages/ImportManager.tsx +216 -0
  550. package/inkos/packages/studio/src/pages/LanguageSelector.tsx +74 -0
  551. package/inkos/packages/studio/src/pages/LogViewer.tsx +82 -0
  552. package/inkos/packages/studio/src/pages/RadarView.tsx +157 -0
  553. package/inkos/packages/studio/src/pages/ServiceDetailPage.tsx +393 -0
  554. package/inkos/packages/studio/src/pages/ServiceListPage.tsx +463 -0
  555. package/inkos/packages/studio/src/pages/StyleManager.tsx +225 -0
  556. package/inkos/packages/studio/src/pages/TruthFiles.tsx +194 -0
  557. package/inkos/packages/studio/src/pages/chat-page-state.test.ts +206 -0
  558. package/inkos/packages/studio/src/pages/chat-page-state.ts +112 -0
  559. package/inkos/packages/studio/src/pages/page-state.test.ts +258 -0
  560. package/inkos/packages/studio/src/pages/service-detail-state.test.ts +294 -0
  561. package/inkos/packages/studio/src/pages/service-detail-state.ts +234 -0
  562. package/inkos/packages/studio/src/pages/style-manager-state.test.ts +22 -0
  563. package/inkos/packages/studio/src/pages/truth-files-state.test.ts +61 -0
  564. package/inkos/packages/studio/src/shared/contracts.ts +143 -0
  565. package/inkos/packages/studio/src/store/chat/__tests__/message-parts.test.ts +172 -0
  566. package/inkos/packages/studio/src/store/chat/index.ts +3 -0
  567. package/inkos/packages/studio/src/store/chat/initialState.ts +8 -0
  568. package/inkos/packages/studio/src/store/chat/message-policy.test.ts +16 -0
  569. package/inkos/packages/studio/src/store/chat/message-policy.ts +5 -0
  570. package/inkos/packages/studio/src/store/chat/parts-builder.ts +187 -0
  571. package/inkos/packages/studio/src/store/chat/selectors.ts +13 -0
  572. package/inkos/packages/studio/src/store/chat/slices/create/action.ts +10 -0
  573. package/inkos/packages/studio/src/store/chat/slices/create/initialState.ts +9 -0
  574. package/inkos/packages/studio/src/store/chat/slices/message/action.ts +417 -0
  575. package/inkos/packages/studio/src/store/chat/slices/message/initialState.ts +10 -0
  576. package/inkos/packages/studio/src/store/chat/slices/message/runtime.test.ts +21 -0
  577. package/inkos/packages/studio/src/store/chat/slices/message/runtime.ts +233 -0
  578. package/inkos/packages/studio/src/store/chat/slices/message/stream-events.ts +272 -0
  579. package/inkos/packages/studio/src/store/chat/store.ts +11 -0
  580. package/inkos/packages/studio/src/store/chat/types.ts +169 -0
  581. package/inkos/packages/studio/src/store/service/index.ts +2 -0
  582. package/inkos/packages/studio/src/store/service/store.ts +123 -0
  583. package/inkos/packages/studio/src/store/service/types.ts +50 -0
  584. package/inkos/packages/studio/tsconfig.json +24 -0
  585. package/inkos/packages/studio/tsconfig.server.json +11 -0
  586. package/inkos/packages/studio/vite.config.ts +34 -0
  587. package/inkos/packages/studio/vitest.config.ts +14 -0
  588. package/inkos/pnpm-lock.yaml +9569 -0
  589. package/inkos/pnpm-workspace.yaml +2 -0
  590. package/inkos/scripts/prepare-package-for-publish.mjs +135 -0
  591. package/inkos/scripts/restore-package-json.mjs +31 -0
  592. package/inkos/scripts/set-package-versions.mjs +74 -0
  593. package/inkos/scripts/verify-no-workspace-protocol.mjs +140 -0
  594. package/inkos/skills/SKILL.md +654 -0
  595. package/inkos/tsconfig.json +19 -0
  596. package/package.json +4 -3
  597. /package/.next/static/{F2hMZMf1IyCVAWpkbtRz7 → -3vIrBZXdQ0rp7Wa3Kz40}/_buildManifest.js +0 -0
  598. /package/.next/static/{F2hMZMf1IyCVAWpkbtRz7 → -3vIrBZXdQ0rp7Wa3Kz40}/_ssgManifest.js +0 -0
@@ -0,0 +1,155 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import { join, dirname } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { parseGenreProfile, type ParsedGenreProfile } from "../models/genre-profile.js";
5
+ import { parseBookRules, tryParseBookRulesFrontmatter, type ParsedBookRules } from "../models/book-rules.js";
6
+ import { BookConfigSchema } from "../models/book.js";
7
+
8
+ const BUILTIN_GENRES_DIR = join(dirname(fileURLToPath(import.meta.url)), "../../genres");
9
+
10
+ async function tryReadFile(path: string): Promise<string | null> {
11
+ try {
12
+ return await readFile(path, "utf-8");
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Load genre profile. Lookup order:
20
+ * 1. Project-level: {projectRoot}/genres/{genreId}.md
21
+ * 2. Built-in: packages/core/genres/{genreId}.md
22
+ * 3. Fallback: built-in other.md
23
+ */
24
+ export async function readGenreProfile(
25
+ projectRoot: string,
26
+ genreId: string,
27
+ ): Promise<ParsedGenreProfile> {
28
+ const projectPath = join(projectRoot, "genres", `${genreId}.md`);
29
+ const builtinPath = join(BUILTIN_GENRES_DIR, `${genreId}.md`);
30
+ const fallbackPath = join(BUILTIN_GENRES_DIR, "other.md");
31
+
32
+ const raw =
33
+ (await tryReadFile(projectPath)) ??
34
+ (await tryReadFile(builtinPath)) ??
35
+ (await tryReadFile(fallbackPath));
36
+
37
+ if (!raw) {
38
+ throw new Error(`Genre profile not found for "${genreId}" and fallback "other.md" is missing`);
39
+ }
40
+
41
+ return parseGenreProfile(raw);
42
+ }
43
+
44
+ /**
45
+ * List all available genre profiles (project-level + built-in, deduped).
46
+ * Returns array of { id, name, source }.
47
+ */
48
+ export async function listAvailableGenres(
49
+ projectRoot: string,
50
+ ): Promise<ReadonlyArray<{ readonly id: string; readonly name: string; readonly source: "project" | "builtin" }>> {
51
+ const results = new Map<string, { id: string; name: string; source: "project" | "builtin" }>();
52
+
53
+ // Built-in genres first
54
+ try {
55
+ const builtinFiles = await readdir(BUILTIN_GENRES_DIR);
56
+ for (const file of builtinFiles) {
57
+ if (!file.endsWith(".md")) continue;
58
+ const id = file.replace(/\.md$/, "");
59
+ const raw = await tryReadFile(join(BUILTIN_GENRES_DIR, file));
60
+ if (!raw) continue;
61
+ const parsed = parseGenreProfile(raw);
62
+ results.set(id, { id, name: parsed.profile.name, source: "builtin" });
63
+ }
64
+ } catch { /* no builtin dir */ }
65
+
66
+ // Project-level genres override
67
+ const projectDir = join(projectRoot, "genres");
68
+ try {
69
+ const projectFiles = await readdir(projectDir);
70
+ for (const file of projectFiles) {
71
+ if (!file.endsWith(".md")) continue;
72
+ const id = file.replace(/\.md$/, "");
73
+ const raw = await tryReadFile(join(projectDir, file));
74
+ if (!raw) continue;
75
+ const parsed = parseGenreProfile(raw);
76
+ results.set(id, { id, name: parsed.profile.name, source: "project" });
77
+ }
78
+ } catch { /* no project genres dir */ }
79
+
80
+ return [...results.values()].sort((a, b) => a.id.localeCompare(b.id));
81
+ }
82
+
83
+ /** Return the path to the built-in genres directory. */
84
+ export function getBuiltinGenresDir(): string {
85
+ return BUILTIN_GENRES_DIR;
86
+ }
87
+
88
+ /**
89
+ * Load the structured book rules (YAML frontmatter).
90
+ *
91
+ * Phase 5 cleanup #3: the YAML frontmatter now lives at the top of
92
+ * outline/story_frame.md. For books initialized before that cleanup it may
93
+ * still live in book_rules.md instead, so we fall back to that legacy path
94
+ * when story_frame.md has no frontmatter (or no file at all).
95
+ *
96
+ * Phase 5 hotfix 2: when the source is story_frame.md, the prose body
97
+ * underneath the frontmatter is NOT semantic "book rules" text — it is the
98
+ * 5-section outline essay. We therefore slice out ONLY the frontmatter block
99
+ * for parseBookRules, so ParsedBookRules.body ends up empty for new-layout
100
+ * books. Legacy book_rules.md still carries narrow narrative rules in its
101
+ * body, so we pass it through verbatim.
102
+ *
103
+ * Returns null only if NEITHER source yields parseable rules.
104
+ */
105
+ export async function readBookRules(bookDir: string): Promise<ParsedBookRules | null> {
106
+ const storyFrameRaw = await tryReadFile(join(bookDir, "story/outline/story_frame.md"));
107
+ if (storyFrameRaw) {
108
+ // Extract just the leading `---\n...\n---` block. Anything after it is
109
+ // outline prose and must NOT leak into ParsedBookRules.body.
110
+ const frontmatterMatch = storyFrameRaw.match(/^\s*(---\s*\n[\s\S]*?\n---\s*)(?:\n|$)/);
111
+ if (frontmatterMatch) {
112
+ // Phase 5 hotfix 3: use the strict parser so a broken YAML block does
113
+ // NOT silently zero out protagonist / prohibitions / genreLock. If the
114
+ // frontmatter is malformed we log and fall through to legacy.
115
+ const parsed = tryParseBookRulesFrontmatter(frontmatterMatch[1], (err) => {
116
+ // eslint-disable-next-line no-console
117
+ console.warn(
118
+ `[rules-reader] story_frame.md frontmatter is malformed at ${bookDir}/story/outline/story_frame.md — falling back to legacy book_rules.md. Error: ${err instanceof Error ? err.message : String(err)}`,
119
+ );
120
+ });
121
+ if (parsed) return parsed;
122
+ // fall through to legacy fallback below
123
+ }
124
+ }
125
+
126
+ const legacyRaw = await tryReadFile(join(bookDir, "story/book_rules.md"));
127
+ if (!legacyRaw) return null;
128
+ // Legacy file: body intentionally preserved (narrow narrative rules).
129
+ //
130
+ // Phase hotfix 1: parseBookRules now returns null if the file is a Phase 5
131
+ // compat shim (no YAML, only the architect-emitted pointer prose). In that
132
+ // case we surface a warning so callers don't silently fall back to default
133
+ // empty rules — the common new-book path where story_frame.md frontmatter
134
+ // is broken AND no legacy rules ever existed.
135
+ const parsed = parseBookRules(legacyRaw);
136
+ if (parsed === null) {
137
+ // eslint-disable-next-line no-console
138
+ console.warn(
139
+ `[rules-reader] book_rules.md at ${bookDir}/story/book_rules.md is a Phase 5 compat shim with no authoritative rules — returning null instead of silently zeroing out rules. Fix the YAML frontmatter on outline/story_frame.md.`,
140
+ );
141
+ }
142
+ return parsed;
143
+ }
144
+
145
+ export async function readBookLanguage(bookDir: string): Promise<"zh" | "en" | undefined> {
146
+ const raw = await tryReadFile(join(bookDir, "book.json"));
147
+ if (!raw) return undefined;
148
+
149
+ try {
150
+ const parsed = BookConfigSchema.pick({ language: true }).safeParse(JSON.parse(raw));
151
+ return parsed.success ? parsed.data.language : undefined;
152
+ } catch {
153
+ return undefined;
154
+ }
155
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Sensitive word detection — rule-based analysis (no LLM).
3
+ *
4
+ * Detects politically sensitive, sexually explicit, and extremely violent terms
5
+ * in Chinese web novel content. Used in audit pipeline to flag or block content.
6
+ */
7
+
8
+ import type { AuditIssue } from "./continuity.js";
9
+
10
+ export interface SensitiveWordMatch {
11
+ readonly word: string;
12
+ readonly count: number;
13
+ readonly severity: "block" | "warn";
14
+ }
15
+
16
+ export interface SensitiveWordResult {
17
+ readonly issues: ReadonlyArray<AuditIssue>;
18
+ readonly found: ReadonlyArray<SensitiveWordMatch>;
19
+ }
20
+
21
+ type SensitiveWordLanguage = "zh" | "en";
22
+
23
+ // Political terms — severity "block"
24
+ const POLITICAL_WORDS: ReadonlyArray<string> = [
25
+ "习近平", "习主席", "习总书记", "共产党", "中国共产党", "共青团",
26
+ "六四", "天安门事件", "天安门广场事件", "法轮功", "法轮大法",
27
+ "台独", "藏独", "疆独", "港独",
28
+ "新疆集中营", "再教育营",
29
+ "维吾尔", "达赖喇嘛", "达赖",
30
+ "刘晓波", "艾未未", "赵紫阳",
31
+ "文化大革命", "文革", "大跃进",
32
+ "反右运动", "镇压", "六四屠杀",
33
+ "中南海", "政治局常委",
34
+ "翻墙", "防火长城",
35
+ ];
36
+
37
+ // Sexual terms — severity "warn"
38
+ const SEXUAL_WORDS: ReadonlyArray<string> = [
39
+ "性交", "做爱", "口交", "肛交", "自慰", "手淫",
40
+ "阴茎", "阴道", "阴蒂", "乳房", "乳头",
41
+ "射精", "高潮", "潮吹",
42
+ "淫荡", "淫乱", "荡妇", "婊子",
43
+ "强奸", "轮奸",
44
+ ];
45
+
46
+ // Extreme violence — severity "warn"
47
+ const VIOLENCE_EXTREME: ReadonlyArray<string> = [
48
+ "肢解", "碎尸", "挖眼", "剥皮", "开膛破肚",
49
+ "虐杀", "凌迟", "活剥", "活埋", "烹煮活人",
50
+ ];
51
+
52
+ interface WordListEntry {
53
+ readonly words: ReadonlyArray<string>;
54
+ readonly severity: "block" | "warn";
55
+ readonly label: string;
56
+ readonly englishLabel: string;
57
+ }
58
+
59
+ const WORD_LISTS: ReadonlyArray<WordListEntry> = [
60
+ { words: POLITICAL_WORDS, severity: "block", label: "政治敏感词", englishLabel: "political sensitive terms" },
61
+ { words: SEXUAL_WORDS, severity: "warn", label: "色情敏感词", englishLabel: "sexual sensitive terms" },
62
+ { words: VIOLENCE_EXTREME, severity: "warn", label: "极端暴力词", englishLabel: "extreme violence terms" },
63
+ ];
64
+
65
+ /**
66
+ * Analyze text content for sensitive words.
67
+ * Returns issues that can be merged into audit results.
68
+ */
69
+ export function analyzeSensitiveWords(
70
+ content: string,
71
+ customWords?: ReadonlyArray<string>,
72
+ language: SensitiveWordLanguage = "zh",
73
+ ): SensitiveWordResult {
74
+ const found: SensitiveWordMatch[] = [];
75
+ const issues: AuditIssue[] = [];
76
+ const isEnglish = language === "en";
77
+ const joiner = isEnglish ? ", " : "、";
78
+
79
+ // Check built-in word lists
80
+ for (const list of WORD_LISTS) {
81
+ const matches = scanWords(content, list.words, list.severity);
82
+ if (matches.length > 0) {
83
+ found.push(...matches);
84
+ const wordSummary = matches.map((m) => `"${m.word}"×${m.count}`).join(joiner);
85
+ issues.push({
86
+ severity: list.severity === "block" ? "critical" : "warning",
87
+ category: isEnglish ? "Sensitive terms" : "敏感词",
88
+ description: isEnglish
89
+ ? `Detected ${list.englishLabel}: ${wordSummary}`
90
+ : `检测到${list.label}:${wordSummary}`,
91
+ suggestion: isEnglish
92
+ ? (list.severity === "block"
93
+ ? "You must remove or replace these blocked terms before publication"
94
+ : `Replace or soften these ${list.englishLabel} to reduce moderation risk`)
95
+ : (list.severity === "block"
96
+ ? "必须删除或替换政治敏感词,否则无法发布"
97
+ : `建议替换或弱化${list.label},避免平台审核问题`),
98
+ });
99
+ }
100
+ }
101
+
102
+ // Check custom words
103
+ if (customWords && customWords.length > 0) {
104
+ const customMatches = scanWords(content, customWords, "warn");
105
+ if (customMatches.length > 0) {
106
+ found.push(...customMatches);
107
+ const wordSummary = customMatches.map((m) => `"${m.word}"×${m.count}`).join(joiner);
108
+ issues.push({
109
+ severity: "warning",
110
+ category: isEnglish ? "Sensitive terms" : "敏感词",
111
+ description: isEnglish
112
+ ? `Detected custom sensitive term(s): ${wordSummary}`
113
+ : `检测到自定义敏感词:${wordSummary}`,
114
+ suggestion: isEnglish
115
+ ? "Replace or remove these terms according to project rules"
116
+ : "根据项目规则替换或删除这些词语",
117
+ });
118
+ }
119
+ }
120
+
121
+ return { issues, found };
122
+ }
123
+
124
+ function scanWords(
125
+ content: string,
126
+ words: ReadonlyArray<string>,
127
+ severity: "block" | "warn",
128
+ ): ReadonlyArray<SensitiveWordMatch> {
129
+ const matches: SensitiveWordMatch[] = [];
130
+ for (const word of words) {
131
+ const regex = new RegExp(escapeRegExp(word), "g");
132
+ const hits = content.match(regex);
133
+ if (hits && hits.length > 0) {
134
+ matches.push({ word, count: hits.length, severity });
135
+ }
136
+ }
137
+ return matches;
138
+ }
139
+
140
+ function escapeRegExp(str: string): string {
141
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
142
+ }
@@ -0,0 +1,53 @@
1
+ import {
2
+ RuntimeStateDeltaSchema,
3
+ type RuntimeStateDelta,
4
+ } from "../models/runtime-state.js";
5
+
6
+ export interface SettlerDeltaOutput {
7
+ readonly postSettlement: string;
8
+ readonly runtimeStateDelta: RuntimeStateDelta;
9
+ }
10
+
11
+ function sanitizeJSON(str: string): string {
12
+ return str
13
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "")
14
+ .replace(/,\s*([}\]])/g, "$1");
15
+ }
16
+
17
+ export function parseSettlerDeltaOutput(content: string): SettlerDeltaOutput {
18
+ const extract = (tag: string): string => {
19
+ const regex = new RegExp(
20
+ `=== ${tag} ===\\s*([\\s\\S]*?)(?==== [A-Z_]+ ===|$)`,
21
+ );
22
+ const match = content.match(regex);
23
+ return match?.[1]?.trim() ?? "";
24
+ };
25
+
26
+ const rawDelta = extract("RUNTIME_STATE_DELTA");
27
+ if (!rawDelta) {
28
+ throw new Error("runtime state delta block is missing");
29
+ }
30
+
31
+ const jsonPayload = stripCodeFence(rawDelta);
32
+ let parsed: unknown;
33
+ try {
34
+ parsed = JSON.parse(sanitizeJSON(jsonPayload));
35
+ } catch (error) {
36
+ throw new Error(`runtime state delta is not valid JSON: ${String(error)}`);
37
+ }
38
+
39
+ try {
40
+ return {
41
+ postSettlement: extract("POST_SETTLEMENT"),
42
+ runtimeStateDelta: RuntimeStateDeltaSchema.parse(parsed),
43
+ };
44
+ } catch (error) {
45
+ throw new Error(`runtime state delta failed schema validation: ${String(error)}`);
46
+ }
47
+ }
48
+
49
+ function stripCodeFence(value: string): string {
50
+ const trimmed = value.trim();
51
+ const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);
52
+ return fenced?.[1]?.trim() ?? trimmed;
53
+ }
@@ -0,0 +1,38 @@
1
+ import type { GenreProfile } from "../models/genre-profile.js";
2
+
3
+ export interface SettlementOutput {
4
+ readonly postSettlement: string;
5
+ readonly updatedState: string;
6
+ readonly updatedLedger: string;
7
+ readonly updatedHooks: string;
8
+ readonly chapterSummary: string;
9
+ readonly updatedSubplots: string;
10
+ readonly updatedEmotionalArcs: string;
11
+ readonly updatedCharacterMatrix: string;
12
+ }
13
+
14
+ export function parseSettlementOutput(
15
+ content: string,
16
+ genreProfile: GenreProfile,
17
+ ): SettlementOutput {
18
+ const extract = (tag: string): string => {
19
+ const regex = new RegExp(
20
+ `=== ${tag} ===\\s*([\\s\\S]*?)(?==== [A-Z_]+ ===|$)`,
21
+ );
22
+ const match = content.match(regex);
23
+ return match?.[1]?.trim() ?? "";
24
+ };
25
+
26
+ return {
27
+ postSettlement: extract("POST_SETTLEMENT"),
28
+ updatedState: extract("UPDATED_STATE") || "(状态卡未更新)",
29
+ updatedLedger: genreProfile.numericalSystem
30
+ ? (extract("UPDATED_LEDGER") || "(账本未更新)")
31
+ : "",
32
+ updatedHooks: extract("UPDATED_HOOKS") || "(伏笔池未更新)",
33
+ chapterSummary: extract("CHAPTER_SUMMARY"),
34
+ updatedSubplots: extract("UPDATED_SUBPLOTS"),
35
+ updatedEmotionalArcs: extract("UPDATED_EMOTIONAL_ARCS"),
36
+ updatedCharacterMatrix: extract("UPDATED_CHARACTER_MATRIX"),
37
+ };
38
+ }
@@ -0,0 +1,230 @@
1
+ import type { BookConfig } from "../models/book.js";
2
+ import type { GenreProfile } from "../models/genre-profile.js";
3
+ import type { BookRules } from "../models/book-rules.js";
4
+
5
+ export function buildSettlerSystemPrompt(
6
+ book: BookConfig,
7
+ genreProfile: GenreProfile,
8
+ bookRules: BookRules | null,
9
+ language?: "zh" | "en",
10
+ ): string {
11
+ const resolvedLang = language ?? genreProfile.language;
12
+ const isEnglish = resolvedLang === "en";
13
+ const numericalBlock = genreProfile.numericalSystem
14
+ ? `\n- 本题材有数值/资源体系,你必须在 UPDATED_LEDGER 中追踪正文中出现的所有资源变动
15
+ - 数值验算铁律:期初 + 增量 = 期末,三项必须可验算`
16
+ : `\n- 本题材无数值系统,UPDATED_LEDGER 留空`;
17
+
18
+ const hookRules = `
19
+ ## 伏笔追踪规则(严格执行)
20
+
21
+ - 新伏笔:只有当正文中出现一个会延续到后续章节、且有具体回收方向的未解问题时,才新增 hook_id。不要为旧 hook 的换说法、重述、抽象总结再开新 hook
22
+ - 提及伏笔:已有伏笔在本章被提到,但没有新增信息、没有改变读者或角色对该问题的理解 → 放入 mention 数组,不要更新最近推进
23
+ - 推进伏笔:已有伏笔在本章出现了新的事实、证据、关系变化、风险升级或范围收缩 → **必须**更新"最近推进"列为当前章节号,更新状态和备注
24
+ - 回收伏笔:伏笔在本章被明确揭示、解决、或不再成立 → 状态改为"已回收",备注回收方式
25
+ - 延后伏笔:只有当正文明确显示该线被主动搁置、转入后台、或被剧情压后时,才标注"延后";不要因为“已经过了几章”就机械延后
26
+ - brand-new unresolved thread:不要直接发明新的 hookId。把候选放进 newHookCandidates,由系统决定它是映射到旧 hook、变成真正新 hook,还是被拒绝为重述
27
+ - payoffTiming 使用语义节奏,不用硬写章节号:只允许 immediate / near-term / mid-arc / slow-burn / endgame
28
+ - **铁律**:不要把“再次提到”“换个说法重述”“抽象复盘”当成推进。只有状态真的变了,才更新最近推进。只是出现过的旧 hook,放进 mention 数组。`;
29
+
30
+ const fullCastBlock = bookRules?.enableFullCastTracking
31
+ ? `\n## 全员追踪\nPOST_SETTLEMENT 必须额外包含:本章出场角色清单、角色间关系变动、未出场但被提及的角色。`
32
+ : "";
33
+
34
+ const langPrefix = isEnglish
35
+ ? `【LANGUAGE OVERRIDE】ALL output (state card, hooks, summaries, subplots, emotional arcs, character matrix) MUST be in English. The === TAG === markers remain unchanged.\n\n`
36
+ : "";
37
+
38
+ return `${langPrefix}你是状态追踪分析师。给定新章节正文和当前 truth 文件,你的任务是产出更新后的 truth 文件。
39
+
40
+ ## 工作模式
41
+
42
+ 你不是在写作。你的任务是:
43
+ 1. 仔细阅读正文,提取所有状态变化
44
+ 2. 基于"当前追踪文件"做增量更新
45
+ 3. 严格按照 === TAG === 格式输出
46
+
47
+ ## 分析维度
48
+
49
+ 从正文中提取以下信息:
50
+ - 角色出场、退场、状态变化(受伤/突破/死亡等)
51
+ - 位置移动、场景转换
52
+ - 物品/资源的获得与消耗
53
+ - 伏笔的埋设、推进、回收
54
+ - 情感弧线变化
55
+ - 支线进展
56
+ - 角色间关系变化、新的信息边界
57
+
58
+ ## 书籍信息
59
+
60
+ - 标题:${book.title}
61
+ - 题材:${genreProfile.name}(${book.genre})
62
+ - 平台:${book.platform}
63
+ ${numericalBlock}
64
+ ${hookRules}${fullCastBlock}
65
+
66
+ ## 输出格式(必须严格遵循)
67
+
68
+ ${buildSettlerOutputFormat(genreProfile)}
69
+
70
+ ## 关键规则
71
+
72
+ 1. 状态卡和伏笔池必须基于"当前追踪文件"做增量更新,不是从零开始
73
+ 2. 正文中的每一个事实性变化都必须反映在对应的追踪文件中
74
+ 3. 不要遗漏细节:数值变化、位置变化、关系变化、信息变化都要记录
75
+ 4. 角色交互矩阵中的"信息边界"要准确——角色只知道他在场时发生的事
76
+
77
+ ## 铁律:只记录正文中实际发生的事(严格执行)
78
+
79
+ - **只提取正文中明确描写的事件和状态变化**。不要推断、预测、或补充正文没有写到的内容
80
+ - 如果正文只写到角色走到门口还没进去,状态卡就不能写"角色已进入房间"
81
+ - 如果正文只暗示了某种可能性但没有确认,不要把它当作已发生的事实记录
82
+ - 不要从卷纲或大纲中补充正文尚未到达的剧情到状态卡
83
+ - 不要删除或修改已有 hooks 中与本章无关的内容——只更新本章正文涉及的 hooks
84
+ - 第 1 章尤其注意:初始追踪文件可能包含从大纲预生成的内容,只保留正文实际支持的部分,不要保留正文未涉及的预设
85
+ - **伏笔例外**:正文中出现的未解疑问、悬念、伏笔线索必须在 hooks 中记录。这不是"推断",而是"提取正文中的叙事承诺"。如果正文暗示了一个谜题/冲突/秘密但没有解答,那就是一个 hook,必须记录`;
86
+ }
87
+
88
+ function buildSettlerOutputFormat(gp: GenreProfile): string {
89
+ const chapterTypeExample = gp.chapterTypes.length > 0
90
+ ? gp.chapterTypes[0]
91
+ : "主线推进";
92
+
93
+ return `=== POST_SETTLEMENT ===
94
+ (简要说明本章有哪些状态变动、伏笔推进、结算注意事项;允许 Markdown 表格或要点)
95
+
96
+ === RUNTIME_STATE_DELTA ===
97
+ (必须输出 JSON,不要输出 Markdown,不要加解释)
98
+ \`\`\`json
99
+ {
100
+ "chapter": 12,
101
+ "currentStatePatch": {
102
+ "currentLocation": "可选",
103
+ "protagonistState": "可选",
104
+ "currentGoal": "可选",
105
+ "currentConstraint": "可选",
106
+ "currentAlliances": "可选",
107
+ "currentConflict": "可选"
108
+ },
109
+ "hookOps": {
110
+ "upsert": [
111
+ {
112
+ "hookId": "mentor-oath",
113
+ "startChapter": 8,
114
+ "type": "relationship",
115
+ "status": "progressing",
116
+ "lastAdvancedChapter": 12,
117
+ "expectedPayoff": "揭开师债真相",
118
+ "payoffTiming": "slow-burn",
119
+ "notes": "本章为何推进/延后/回收"
120
+ }
121
+ ],
122
+ "mention": ["本章只是被提到、没有真实推进的 hookId"],
123
+ "resolve": ["已回收的 hookId"],
124
+ "defer": ["需要标记延后的 hookId"]
125
+ },
126
+ "newHookCandidates": [
127
+ {
128
+ "type": "mystery",
129
+ "expectedPayoff": "新伏笔未来要回收到哪里",
130
+ "payoffTiming": "near-term",
131
+ "notes": "本章为什么会形成新的未解问题"
132
+ }
133
+ ],
134
+ "chapterSummary": {
135
+ "chapter": 12,
136
+ "title": "本章标题",
137
+ "characters": "角色1,角色2",
138
+ "events": "一句话概括关键事件",
139
+ "stateChanges": "一句话概括状态变化",
140
+ "hookActivity": "mentor-oath advanced",
141
+ "mood": "紧绷",
142
+ "chapterType": "${chapterTypeExample}"
143
+ },
144
+ "subplotOps": [],
145
+ "emotionalArcOps": [],
146
+ "characterMatrixOps": [],
147
+ "notes": []
148
+ }
149
+ \`\`\`
150
+
151
+ 规则:
152
+ 1. 只输出增量,不要重写完整 truth files
153
+ 2. 所有章节号字段都必须是整数,不能写自然语言
154
+ 3. hookOps.upsert 里只能写“当前伏笔池里已经存在”的 hookId,不允许发明新的 hookId
155
+ 4. brand-new unresolved thread 一律写进 newHookCandidates,不要自造 hookId
156
+ 5. 如果旧 hook 只是被提到、没有真实状态变化,把它放进 mention,不要更新 lastAdvancedChapter
157
+ 6. 如果本章推进了旧 hook,lastAdvancedChapter 必须等于当前章号
158
+ 7. 如果回收或延后 hook,必须放在 resolve / defer 数组里
159
+ 8. chapterSummary.chapter 必须等于当前章节号`;
160
+ }
161
+
162
+ export function buildSettlerUserPrompt(params: {
163
+ readonly chapterNumber: number;
164
+ readonly title: string;
165
+ readonly content: string;
166
+ readonly currentState: string;
167
+ readonly ledger: string;
168
+ readonly hooks: string;
169
+ readonly chapterSummaries: string;
170
+ readonly subplotBoard: string;
171
+ readonly emotionalArcs: string;
172
+ readonly characterMatrix: string;
173
+ readonly volumeOutline: string;
174
+ readonly observations?: string;
175
+ readonly selectedEvidenceBlock?: string;
176
+ readonly governedControlBlock?: string;
177
+ readonly validationFeedback?: string;
178
+ }): string {
179
+ const ledgerBlock = params.ledger
180
+ ? `\n## 当前资源账本\n${params.ledger}\n`
181
+ : "";
182
+
183
+ const summariesBlock = params.chapterSummaries !== "(文件尚未创建)"
184
+ ? `\n## 已有章节摘要\n${params.chapterSummaries}\n`
185
+ : "";
186
+
187
+ const subplotBlock = params.subplotBoard !== "(文件尚未创建)"
188
+ ? `\n## 当前支线进度板\n${params.subplotBoard}\n`
189
+ : "";
190
+
191
+ const emotionalBlock = params.emotionalArcs !== "(文件尚未创建)"
192
+ ? `\n## 当前情感弧线\n${params.emotionalArcs}\n`
193
+ : "";
194
+
195
+ const matrixBlock = params.characterMatrix !== "(文件尚未创建)"
196
+ ? `\n## 当前角色交互矩阵\n${params.characterMatrix}\n`
197
+ : "";
198
+
199
+ const observationsBlock = params.observations
200
+ ? `\n## 观察日志(由 Observer 提取,包含本章所有事实变化)\n${params.observations}\n\n基于以上观察日志和正文,更新所有追踪文件。确保观察日志中的每一项变化都反映在对应的文件中。\n`
201
+ : "";
202
+ const selectedEvidenceBlock = params.selectedEvidenceBlock
203
+ ? `\n## 已选长程证据\n${params.selectedEvidenceBlock}\n`
204
+ : "";
205
+ const controlBlock = params.governedControlBlock ?? "";
206
+ const outlineBlock = controlBlock.length === 0
207
+ ? `\n## 卷纲\n${params.volumeOutline}\n`
208
+ : "";
209
+ const validationFeedbackBlock = params.validationFeedback
210
+ ? `\n## 状态校验反馈\n${params.validationFeedback}\n\n请严格纠正这些矛盾,只修正 truth files,不要改写正文,不要引入正文中不存在的新事实。\n`
211
+ : "";
212
+
213
+ return `请分析第${params.chapterNumber}章「${params.title}」的正文,更新所有追踪文件。
214
+ ${observationsBlock}
215
+ ${validationFeedbackBlock}
216
+ ## 本章正文
217
+
218
+ ${params.content}
219
+ ${controlBlock}
220
+
221
+ ## 当前状态卡
222
+ ${params.currentState}
223
+ ${ledgerBlock}
224
+ ## 当前伏笔池
225
+ ${params.hooks}
226
+ ${selectedEvidenceBlock}${summariesBlock}${subplotBlock}${emotionalBlock}${matrixBlock}
227
+ ${outlineBlock}
228
+
229
+ 请严格按照 === TAG === 格式输出结算结果。`;
230
+ }