@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,634 @@
1
+ import { BaseAgent } from "./base.js";
2
+ import type { BookConfig } from "../models/book.js";
3
+ import type { GenreProfile } from "../models/genre-profile.js";
4
+ import type { ContextPackage, RuleStack } from "../models/input-governance.js";
5
+ import { readGenreProfile, readBookRules } from "./rules-reader.js";
6
+ import { parseWriterOutput, type ParsedWriterOutput } from "./writer-parser.js";
7
+ import { buildGovernedMemoryEvidenceBlocks } from "../utils/governed-context.js";
8
+ import {
9
+ buildGovernedCharacterMatrixWorkingSet,
10
+ buildGovernedHookWorkingSet,
11
+ } from "../utils/governed-working-set.js";
12
+ import { filterEmotionalArcs, filterSubplots } from "../utils/context-filter.js";
13
+ import { countChapterLength, resolveLengthCountingMode } from "../utils/length-metrics.js";
14
+ import { retrieveMemorySelection } from "../utils/memory-retrieval.js";
15
+ import { readFile } from "node:fs/promises";
16
+ import { join } from "node:path";
17
+ import {
18
+ readStoryFrame,
19
+ readVolumeMap,
20
+ readCharacterContext,
21
+ readCurrentStateWithFallback,
22
+ } from "../utils/outline-paths.js";
23
+
24
+ export interface AnalyzeChapterInput {
25
+ readonly book: BookConfig;
26
+ readonly bookDir: string;
27
+ readonly chapterNumber: number;
28
+ readonly chapterContent: string;
29
+ readonly chapterTitle?: string;
30
+ readonly chapterIntent?: string;
31
+ readonly contextPackage?: ContextPackage;
32
+ readonly ruleStack?: RuleStack;
33
+ }
34
+
35
+ export type AnalyzeChapterOutput = ParsedWriterOutput;
36
+
37
+ export class ChapterAnalyzerAgent extends BaseAgent {
38
+ get name(): string {
39
+ return "chapter-analyzer";
40
+ }
41
+
42
+ async analyzeChapter(input: AnalyzeChapterInput): Promise<AnalyzeChapterOutput> {
43
+ const { book, bookDir, chapterNumber, chapterContent, chapterTitle } = input;
44
+ const { profile: genreProfile, body: genreBody } =
45
+ await readGenreProfile(this.ctx.projectRoot, book.genre);
46
+ const resolvedLanguage = book.language ?? genreProfile.language;
47
+
48
+ // Read current truth files (same set as writer.ts). Phase 5: prefer the
49
+ // new prose outline (story_frame / volume_map) and roles/ directory.
50
+ const placeholder = this.missingFilePlaceholder(resolvedLanguage);
51
+ const [
52
+ currentState, ledger, hooks,
53
+ subplotBoard, emotionalArcs, characterMatrix,
54
+ storyBible, volumeOutline,
55
+ ] = await Promise.all([
56
+ // Phase 5 consolidation: derive initial state from roles + seed hooks
57
+ // when current_state.md is still the architect seed placeholder.
58
+ readCurrentStateWithFallback(bookDir, placeholder),
59
+ this.readFileOrDefault(join(bookDir, "story/particle_ledger.md"), resolvedLanguage),
60
+ this.readFileOrDefault(join(bookDir, "story/pending_hooks.md"), resolvedLanguage),
61
+ this.readFileOrDefault(join(bookDir, "story/subplot_board.md"), resolvedLanguage),
62
+ this.readFileOrDefault(join(bookDir, "story/emotional_arcs.md"), resolvedLanguage),
63
+ readCharacterContext(bookDir, placeholder),
64
+ readStoryFrame(bookDir, placeholder),
65
+ readVolumeMap(bookDir, placeholder),
66
+ ]);
67
+ const parsedBookRules = await readBookRules(bookDir);
68
+ const bookRulesBody = parsedBookRules?.body ?? "";
69
+ const bookRules = parsedBookRules?.rules;
70
+ const governedMode = Boolean(input.chapterIntent && input.contextPackage && input.ruleStack);
71
+ const memorySelection = await retrieveMemorySelection({
72
+ bookDir,
73
+ chapterNumber,
74
+ goal: this.buildMemoryGoal(chapterTitle, chapterContent),
75
+ outlineNode: this.findOutlineNode(volumeOutline, chapterNumber),
76
+ });
77
+ const chapterSummaries = this.renderSummarySnapshot(
78
+ memorySelection.summaries,
79
+ resolvedLanguage,
80
+ );
81
+ const governedMemoryBlocks = input.contextPackage
82
+ ? buildGovernedMemoryEvidenceBlocks(input.contextPackage, resolvedLanguage)
83
+ : undefined;
84
+ const hooksWorkingSet = governedMode && input.contextPackage
85
+ ? buildGovernedHookWorkingSet({
86
+ hooksMarkdown: hooks,
87
+ contextPackage: input.contextPackage,
88
+ chapterIntent: input.chapterIntent,
89
+ chapterNumber,
90
+ language: resolvedLanguage,
91
+ })
92
+ : hooks;
93
+ const subplotWorkingSet = governedMode
94
+ ? filterSubplots(subplotBoard)
95
+ : subplotBoard;
96
+ const emotionalWorkingSet = governedMode
97
+ ? filterEmotionalArcs(emotionalArcs, chapterNumber)
98
+ : emotionalArcs;
99
+ const matrixWorkingSet = governedMode && input.chapterIntent && input.contextPackage
100
+ ? buildGovernedCharacterMatrixWorkingSet({
101
+ matrixMarkdown: characterMatrix,
102
+ chapterIntent: input.chapterIntent,
103
+ contextPackage: input.contextPackage,
104
+ protagonistName: bookRules?.protagonist?.name,
105
+ })
106
+ : characterMatrix;
107
+ const reducedControlBlock = governedMode && input.chapterIntent && input.contextPackage && input.ruleStack
108
+ ? this.buildReducedControlBlock(input.chapterIntent, input.contextPackage, input.ruleStack, resolvedLanguage)
109
+ : "";
110
+
111
+ const systemPrompt = this.buildSystemPrompt(
112
+ book,
113
+ genreProfile,
114
+ genreBody,
115
+ bookRulesBody,
116
+ resolvedLanguage,
117
+ );
118
+
119
+ const userPrompt = this.buildUserPrompt({
120
+ language: resolvedLanguage,
121
+ chapterNumber,
122
+ chapterContent,
123
+ chapterTitle,
124
+ currentState,
125
+ ledger: genreProfile.numericalSystem ? ledger : "",
126
+ hooks: hooksWorkingSet,
127
+ chapterSummaries,
128
+ subplotBoard: subplotWorkingSet,
129
+ emotionalArcs: emotionalWorkingSet,
130
+ characterMatrix: matrixWorkingSet,
131
+ bibleBlock: !governedMode && storyBible !== this.missingFilePlaceholder(resolvedLanguage)
132
+ ? resolvedLanguage === "en"
133
+ ? `\n## Story Bible\n${storyBible}\n`
134
+ : `\n## 世界观设定\n${storyBible}\n`
135
+ : "",
136
+ outlineOrControlBlock: reducedControlBlock || (
137
+ volumeOutline !== this.missingFilePlaceholder(resolvedLanguage)
138
+ ? resolvedLanguage === "en"
139
+ ? `\n## Volume Outline\n${volumeOutline}\n`
140
+ : `\n## 卷纲\n${volumeOutline}\n`
141
+ : ""
142
+ ),
143
+ hooksBlock: governedMemoryBlocks?.hooksBlock
144
+ ?? (
145
+ hooksWorkingSet !== this.missingFilePlaceholder(resolvedLanguage)
146
+ ? resolvedLanguage === "en"
147
+ ? `\n## Current Hooks\n${hooksWorkingSet}\n`
148
+ : `\n## 当前伏笔池\n${hooksWorkingSet}\n`
149
+ : ""
150
+ ),
151
+ summariesBlock: governedMemoryBlocks?.summariesBlock
152
+ ?? (
153
+ chapterSummaries !== this.missingFilePlaceholder(resolvedLanguage)
154
+ ? resolvedLanguage === "en"
155
+ ? `\n## Existing Chapter Summaries\n${chapterSummaries}\n`
156
+ : `\n## 已有章节摘要\n${chapterSummaries}\n`
157
+ : ""
158
+ ),
159
+ volumeSummariesBlock: governedMemoryBlocks?.volumeSummariesBlock ?? "",
160
+ subplotBlock: subplotWorkingSet !== this.missingFilePlaceholder(resolvedLanguage)
161
+ ? resolvedLanguage === "en"
162
+ ? `\n## Current Subplot Board\n${subplotWorkingSet}\n`
163
+ : `\n## 当前支线进度板\n${subplotWorkingSet}\n`
164
+ : "",
165
+ emotionalBlock: emotionalWorkingSet !== this.missingFilePlaceholder(resolvedLanguage)
166
+ ? resolvedLanguage === "en"
167
+ ? `\n## Current Emotional Arcs\n${emotionalWorkingSet}\n`
168
+ : `\n## 当前情感弧线\n${emotionalWorkingSet}\n`
169
+ : "",
170
+ matrixBlock: matrixWorkingSet !== this.missingFilePlaceholder(resolvedLanguage)
171
+ ? resolvedLanguage === "en"
172
+ ? `\n## Current Character Matrix\n${matrixWorkingSet}\n`
173
+ : `\n## 当前角色交互矩阵\n${matrixWorkingSet}\n`
174
+ : "",
175
+ });
176
+
177
+ const response = await this.chat(
178
+ [
179
+ { role: "system", content: systemPrompt },
180
+ { role: "user", content: userPrompt },
181
+ ],
182
+ { temperature: 0.3 },
183
+ );
184
+
185
+ const countingMode = resolveLengthCountingMode(book.language ?? genreProfile.language);
186
+ const output = parseWriterOutput(chapterNumber, response.content, genreProfile, countingMode);
187
+ const canonicalContent = chapterContent;
188
+ const canonicalWordCount = countChapterLength(canonicalContent, countingMode);
189
+
190
+ // If LLM didn't return a title, use the one from input or derive from chapter number
191
+ if (
192
+ chapterTitle
193
+ && (
194
+ output.title === this.defaultChapterTitle(chapterNumber, resolvedLanguage)
195
+ || output.title === `第${chapterNumber}章`
196
+ )
197
+ ) {
198
+ return {
199
+ ...output,
200
+ title: chapterTitle,
201
+ content: canonicalContent,
202
+ wordCount: canonicalWordCount,
203
+ };
204
+ }
205
+
206
+ return {
207
+ ...output,
208
+ content: canonicalContent,
209
+ wordCount: canonicalWordCount,
210
+ };
211
+ }
212
+
213
+ private buildSystemPrompt(
214
+ book: BookConfig,
215
+ genreProfile: GenreProfile,
216
+ genreBody: string,
217
+ bookRulesBody: string,
218
+ language: "zh" | "en",
219
+ ): string {
220
+ if (language === "en") {
221
+ const numericalBlock = genreProfile.numericalSystem
222
+ ? "\n- This genre tracks numerical/resources systems; UPDATED_LEDGER must capture every resource change shown in the chapter."
223
+ : "\n- This genre has no numerical system; leave UPDATED_LEDGER empty.";
224
+
225
+ return `【LANGUAGE OVERRIDE】ALL output MUST be in English. The === TAG === markers remain unchanged.
226
+
227
+ You are a fiction continuity analyst. Analyze a finished chapter, extract every state change, and update the tracking files.
228
+
229
+ ## Working Mode
230
+
231
+ You are not writing new prose. You are reading completed chapter text and updating the book's truth files.
232
+ 1. Read the chapter carefully and extract all important facts.
233
+ 2. Update the existing tracking files incrementally rather than rebuilding them from scratch.
234
+ 3. Keep the output contract identical to the writer pipeline.
235
+
236
+ ## What To Extract
237
+
238
+ - Character entrances, exits, injuries, breakthroughs, deaths, and other status changes
239
+ - Location movement and scene transitions
240
+ - Item or resource gains and losses
241
+ - Hook setup, advancement, and payoff
242
+ - Emotional arc movement
243
+ - Subplot progress
244
+ - Relationship changes and information-boundary changes
245
+
246
+ ## Book Information
247
+
248
+ - Title: ${book.title}
249
+ - Genre: ${genreProfile.name} (${book.genre})
250
+ - Platform: ${book.platform}
251
+ ${numericalBlock}
252
+
253
+ ## Genre Guidance
254
+
255
+ ${genreBody}
256
+
257
+ ${bookRulesBody ? `## Book Rules\n\n${bookRulesBody}` : ""}
258
+
259
+ ## Output Format
260
+
261
+ Use === TAG === delimiters exactly as shown:
262
+
263
+ === CHAPTER_TITLE ===
264
+ (Extract or infer the chapter title. Output title text only.)
265
+
266
+ === CHAPTER_CONTENT ===
267
+ (Repeat the original chapter content exactly. Do not rewrite.)
268
+
269
+ === PRE_WRITE_CHECK ===
270
+ (Leave empty in analysis mode.)
271
+
272
+ === POST_SETTLEMENT ===
273
+ (Leave empty in analysis mode.)
274
+
275
+ === UPDATED_STATE ===
276
+ Updated state card as a Markdown table reflecting the end-of-chapter state:
277
+ | Field | Value |
278
+ | --- | --- |
279
+ | Current Chapter | {chapter_number} |
280
+ | Current Location | ... |
281
+ | Protagonist State | ... |
282
+ | Current Goal | ... |
283
+ | Current Constraint | ... |
284
+ | Current Alliances | ... |
285
+ | Current Conflict | ... |
286
+
287
+ === UPDATED_LEDGER ===
288
+ (If the genre has a numerical system: output the fully updated resource ledger table. Otherwise leave empty.)
289
+
290
+ === UPDATED_HOOKS ===
291
+ Updated hooks pool as a Markdown table with the latest status of every known hook:
292
+ | hook_id | start_chapter | type | status | last_advanced_chapter | expected_payoff | payoff_timing | notes |
293
+
294
+ === CHAPTER_SUMMARY ===
295
+ Single Markdown table row:
296
+ | Chapter | Title | Characters | Key Events | State Changes | Hook Activity | Mood | Chapter Type |
297
+
298
+ === UPDATED_SUBPLOTS ===
299
+ Updated subplot board (Markdown table)
300
+
301
+ === UPDATED_EMOTIONAL_ARCS ===
302
+ Updated emotional arcs (Markdown table)
303
+
304
+ === UPDATED_CHARACTER_MATRIX ===
305
+ Updated character matrix (one ## section per character, bullet-list fields):
306
+
307
+ ## Character Name
308
+ - **Role**: protagonist / antagonist / ally / minor / mentioned
309
+ - **Tags**: core identity tags
310
+ - **Contrast**: distinctive details that defy expectations
311
+ - **Speech**: speaking style summary
312
+ - **Personality**: core personality traits
313
+ - **Motivation**: fundamental driving force
314
+ - **Current**: immediate goal this chapter
315
+ - **Relationships**: OtherChar(type/Ch#) | ...
316
+ - **Known**: what this character knows (only witnessed or told)
317
+ - **Unknown**: what this character does not know
318
+
319
+ (Repeat for each character. Add new characters; keep existing ones updated.)
320
+
321
+ ## Rules
322
+
323
+ 1. UPDATED_STATE and UPDATED_HOOKS must be incremental updates based on the current tracking files.
324
+ 2. Every factual change in the chapter must appear in the corresponding tracking file.
325
+ 3. Do not miss resource changes, movement, relationship changes, or information changes.
326
+ 4. Information boundaries in the character matrix must stay exact: each character only knows what they directly witnessed or learned.`;
327
+ }
328
+
329
+ const numericalBlock = genreProfile.numericalSystem
330
+ ? `\n- 本题材有数值/资源体系,你必须在 UPDATED_LEDGER 中追踪正文中出现的所有资源变动`
331
+ : `\n- 本题材无数值系统,UPDATED_LEDGER 留空`;
332
+
333
+ return `你是小说连续性分析师。你的任务是分析一章已完成的小说正文,从中提取所有状态变化并更新追踪文件。
334
+
335
+ ## 工作模式
336
+
337
+ 你不是在写作,而是在分析已有正文。你需要:
338
+ 1. 仔细阅读正文,提取所有关键信息
339
+ 2. 基于"当前追踪文件"做增量更新
340
+ 3. 输出格式与写作模块完全一致
341
+
342
+ ## 分析维度
343
+
344
+ 从正文中提取以下信息:
345
+ - 角色出场、退场、状态变化(受伤/突破/死亡等)
346
+ - 位置移动、场景转换
347
+ - 物品/资源的获得与消耗
348
+ - 伏笔的埋设、推进、回收
349
+ - 情感弧线变化
350
+ - 支线进展
351
+ - 角色间关系变化、新的信息边界
352
+
353
+ ## 书籍信息
354
+
355
+ - 标题:${book.title}
356
+ - 题材:${genreProfile.name}(${book.genre})
357
+ - 平台:${book.platform}
358
+ ${numericalBlock}
359
+
360
+ ## 题材特征
361
+
362
+ ${genreBody}
363
+
364
+ ${bookRulesBody ? `## 本书规则\n\n${bookRulesBody}` : ""}
365
+
366
+ ## 输出格式(必须严格遵循)
367
+
368
+ 使用 === TAG === 分隔各部分,与写作模块完全一致:
369
+
370
+ === CHAPTER_TITLE ===
371
+ (从正文标题行提取或推断章节标题,只输出标题文字)
372
+
373
+ === CHAPTER_CONTENT ===
374
+ (原样输出正文内容,不做任何修改)
375
+
376
+ === PRE_WRITE_CHECK ===
377
+ (留空,分析模式不需要写作自检)
378
+
379
+ === POST_SETTLEMENT ===
380
+ (留空,分析模式不需要写后结算)
381
+
382
+ === UPDATED_STATE ===
383
+ 更新后的状态卡(Markdown表格),反映本章结束时的最新状态:
384
+ | 字段 | 值 |
385
+ |------|-----|
386
+ | 当前章节 | {章节号} |
387
+ | 当前位置 | ... |
388
+ | 主角状态 | ... |
389
+ | 当前目标 | ... |
390
+ | 当前限制 | ... |
391
+ | 当前敌我 | ... |
392
+ | 当前冲突 | ... |
393
+
394
+ === UPDATED_LEDGER ===
395
+ (如有数值系统:更新后的完整资源账本表格;无则留空)
396
+
397
+ === UPDATED_HOOKS ===
398
+ 更新后的伏笔池(Markdown表格),包含所有已知伏笔的最新状态:
399
+ | hook_id | 起始章节 | 类型 | 状态 | 最近推进 | 预期回收 | 回收节奏 | 备注 |
400
+
401
+ === CHAPTER_SUMMARY ===
402
+ 本章摘要(Markdown表格行):
403
+ | 章节 | 标题 | 出场人物 | 关键事件 | 状态变化 | 伏笔动态 | 情绪基调 | 章节类型 |
404
+
405
+ === UPDATED_SUBPLOTS ===
406
+ 更新后的支线进度板(Markdown表格)
407
+
408
+ === UPDATED_EMOTIONAL_ARCS ===
409
+ 更新后的情感弧线(Markdown表格)
410
+
411
+ === UPDATED_CHARACTER_MATRIX ===
412
+ 更新后的角色矩阵(每个角色一个 ## 块,字段用 bullet list):
413
+
414
+ ## 角色名
415
+ - **定位**: 主角 / 反派 / 盟友 / 配角 / 提及
416
+ - **标签**: 核心身份标签
417
+ - **反差**: 打破刻板印象的独特细节
418
+ - **说话**: 说话风格概述
419
+ - **性格**: 性格底色
420
+ - **动机**: 根本驱动力
421
+ - **当前**: 本章即时目标
422
+ - **关系**: 某角色(关系性质/Ch#) | ...
423
+ - **已知**: 该角色已知的信息(仅限亲历或被告知)
424
+ - **未知**: 该角色不知道的信息
425
+
426
+ (每个角色重复以上格式。新角色追加新 ## 块,已有角色做增量更新。)
427
+
428
+ ## 关键规则
429
+
430
+ 1. 状态卡和伏笔池必须基于"当前追踪文件"做增量更新,不是从零开始
431
+ 2. 正文中的每一个事实性变化都必须反映在对应的追踪文件中
432
+ 3. 不要遗漏细节:数值变化、位置变化、关系变化、信息变化都要记录
433
+ 4. 角色矩阵中的"已知/未知"要准确——角色只知道他在场时发生的事`;
434
+ }
435
+
436
+ private buildUserPrompt(params: {
437
+ readonly language: "zh" | "en";
438
+ readonly chapterNumber: number;
439
+ readonly chapterContent: string;
440
+ readonly chapterTitle?: string;
441
+ readonly currentState: string;
442
+ readonly ledger: string;
443
+ readonly hooks: string;
444
+ readonly chapterSummaries: string;
445
+ readonly subplotBoard: string;
446
+ readonly emotionalArcs: string;
447
+ readonly characterMatrix: string;
448
+ readonly hooksBlock: string;
449
+ readonly summariesBlock: string;
450
+ readonly volumeSummariesBlock: string;
451
+ readonly subplotBlock: string;
452
+ readonly emotionalBlock: string;
453
+ readonly matrixBlock: string;
454
+ readonly bibleBlock: string;
455
+ readonly outlineOrControlBlock: string;
456
+ }): string {
457
+ if (params.language === "en") {
458
+ const titleLine = params.chapterTitle
459
+ ? `Chapter Title: ${params.chapterTitle}\n`
460
+ : "";
461
+
462
+ const ledgerBlock = params.ledger
463
+ ? `\n## Current Resource Ledger\n${params.ledger}\n`
464
+ : "";
465
+
466
+ return `Analyze chapter ${params.chapterNumber} and update all tracking files.
467
+ ${titleLine}
468
+ ## Chapter Content
469
+
470
+ ${params.chapterContent}
471
+
472
+ ## Current State
473
+ ${params.currentState}
474
+ ${ledgerBlock}
475
+ ${params.hooksBlock}${params.volumeSummariesBlock}${params.subplotBlock}${params.emotionalBlock}${params.matrixBlock}${params.summariesBlock}${params.outlineOrControlBlock}${params.bibleBlock}
476
+
477
+ Please return the result strictly in the === TAG === format.`;
478
+ }
479
+
480
+ const titleLine = params.chapterTitle
481
+ ? `章节标题:${params.chapterTitle}\n`
482
+ : "";
483
+
484
+ const ledgerBlock = params.ledger
485
+ ? `\n## 当前资源账本\n${params.ledger}\n`
486
+ : "";
487
+
488
+ return `请分析第${params.chapterNumber}章正文,更新所有追踪文件。
489
+ ${titleLine}
490
+ ## 正文内容
491
+
492
+ ${params.chapterContent}
493
+
494
+ ## 当前状态卡
495
+ ${params.currentState}
496
+ ${ledgerBlock}
497
+ ${params.hooksBlock}${params.volumeSummariesBlock}${params.subplotBlock}${params.emotionalBlock}${params.matrixBlock}${params.summariesBlock}${params.outlineOrControlBlock}${params.bibleBlock}
498
+
499
+ 请严格按照 === TAG === 格式输出分析结果。`;
500
+ }
501
+
502
+ private buildReducedControlBlock(
503
+ chapterIntent: string,
504
+ contextPackage: ContextPackage,
505
+ ruleStack: RuleStack,
506
+ language: "zh" | "en",
507
+ ): string {
508
+ const selectedContext = contextPackage.selectedContext
509
+ .map((entry) => `- ${entry.source}: ${entry.reason}${entry.excerpt ? ` | ${entry.excerpt}` : ""}`)
510
+ .join("\n");
511
+ const overrides = ruleStack.activeOverrides.length > 0
512
+ ? ruleStack.activeOverrides
513
+ .map((override) => `- ${override.from} -> ${override.to}: ${override.reason} (${override.target})`)
514
+ .join("\n")
515
+ : "- none";
516
+
517
+ return language === "en"
518
+ ? `\n## Chapter Control Inputs (compiled by Planner/Composer)
519
+ ${chapterIntent}
520
+
521
+ ### Selected Context
522
+ ${selectedContext || "- none"}
523
+
524
+ ### Rule Stack
525
+ - Hard guardrails: ${ruleStack.sections.hard.join(", ") || "(none)"}
526
+ - Soft constraints: ${ruleStack.sections.soft.join(", ") || "(none)"}
527
+ - Diagnostic rules: ${ruleStack.sections.diagnostic.join(", ") || "(none)"}
528
+
529
+ ### Active Overrides
530
+ ${overrides}\n`
531
+ : `\n## 本章控制输入(由 Planner/Composer 编译)
532
+ ${chapterIntent}
533
+
534
+ ### 已选上下文
535
+ ${selectedContext || "- none"}
536
+
537
+ ### 规则栈
538
+ - 硬护栏:${ruleStack.sections.hard.join("、") || "(无)"}
539
+ - 软约束:${ruleStack.sections.soft.join("、") || "(无)"}
540
+ - 诊断规则:${ruleStack.sections.diagnostic.join("、") || "(无)"}
541
+
542
+ ### 当前覆盖
543
+ ${overrides}\n`;
544
+ }
545
+
546
+ private buildMemoryGoal(chapterTitle: string | undefined, chapterContent: string): string {
547
+ return [chapterTitle ?? "", chapterContent.slice(0, 1500)]
548
+ .filter((part) => part.trim().length > 0)
549
+ .join("\n\n");
550
+ }
551
+
552
+ private findOutlineNode(volumeOutline: string, chapterNumber: number): string | undefined {
553
+ if (!volumeOutline || volumeOutline === this.missingFilePlaceholder("zh") || volumeOutline === this.missingFilePlaceholder("en")) {
554
+ return undefined;
555
+ }
556
+
557
+ const lines = volumeOutline.split("\n").map((line) => line.trim()).filter(Boolean);
558
+ const chapterPatterns = [
559
+ new RegExp(`^#+\\s*Chapter\\s*${chapterNumber}\\b`, "i"),
560
+ new RegExp(`^#+\\s*第\\s*${chapterNumber}\\s*章`),
561
+ ];
562
+
563
+ const heading = lines.find((line) => chapterPatterns.some((pattern) => pattern.test(line)));
564
+ if (!heading) return undefined;
565
+
566
+ const headingIndex = lines.indexOf(heading);
567
+ const nextLine = lines[headingIndex + 1];
568
+ return nextLine && !nextLine.startsWith("#") ? nextLine : heading.replace(/^#+\s*/, "");
569
+ }
570
+
571
+ private renderSummarySnapshot(
572
+ summaries: ReadonlyArray<{
573
+ chapter: number;
574
+ title: string;
575
+ characters: string;
576
+ events: string;
577
+ stateChanges: string;
578
+ hookActivity: string;
579
+ mood: string;
580
+ chapterType: string;
581
+ }>,
582
+ language: "zh" | "en",
583
+ ): string {
584
+ if (summaries.length === 0) {
585
+ return this.missingFilePlaceholder(language);
586
+ }
587
+
588
+ const header = language === "en"
589
+ ? [
590
+ "| Chapter | Title | Characters | Key Events | State Changes | Hook Activity | Mood | Chapter Type |",
591
+ "| --- | --- | --- | --- | --- | --- | --- | --- |",
592
+ ]
593
+ : [
594
+ "| 章节 | 标题 | 出场人物 | 关键事件 | 状态变化 | 伏笔动态 | 情绪基调 | 章节类型 |",
595
+ "| --- | --- | --- | --- | --- | --- | --- | --- |",
596
+ ];
597
+
598
+ const rows = summaries.map((summary) => [
599
+ summary.chapter,
600
+ summary.title,
601
+ summary.characters,
602
+ summary.events,
603
+ summary.stateChanges,
604
+ summary.hookActivity,
605
+ summary.mood,
606
+ summary.chapterType,
607
+ ].map((cell) => this.escapeTableCell(String(cell))).join(" | "));
608
+
609
+ return [
610
+ ...header,
611
+ ...rows.map((row) => `| ${row} |`),
612
+ ].join("\n");
613
+ }
614
+
615
+ private escapeTableCell(value: string): string {
616
+ return value.replace(/\|/g, "\\|").replace(/\n/g, "<br>");
617
+ }
618
+
619
+ private async readFileOrDefault(path: string, language: "zh" | "en"): Promise<string> {
620
+ try {
621
+ return await readFile(path, "utf-8");
622
+ } catch {
623
+ return this.missingFilePlaceholder(language);
624
+ }
625
+ }
626
+
627
+ private missingFilePlaceholder(language: "zh" | "en"): string {
628
+ return language === "en" ? "(file not created yet)" : "(文件尚未创建)";
629
+ }
630
+
631
+ private defaultChapterTitle(chapterNumber: number, language: "zh" | "en"): string {
632
+ return language === "en" ? `Chapter ${chapterNumber}` : `第${chapterNumber}章`;
633
+ }
634
+ }