@lingjingai/scriptctl 0.49.15 → 0.50.0

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 (390) hide show
  1. package/README.md +8 -2
  2. package/changes/0.49.16.md +15 -0
  3. package/changes/0.50.0.md +63 -0
  4. package/changes/unreleased.md +2 -1
  5. package/dist/cli.js +26 -5
  6. package/dist/cli.js.map +1 -1
  7. package/dist/domain/authoring/apply.d.ts +1 -33
  8. package/dist/domain/authoring/apply.js +1 -783
  9. package/dist/domain/authoring/apply.js.map +1 -1
  10. package/dist/domain/authoring/export.d.ts +1 -7
  11. package/dist/domain/authoring/export.js +1 -84
  12. package/dist/domain/authoring/export.js.map +1 -1
  13. package/dist/domain/authoring/parser.d.ts +2 -3
  14. package/dist/domain/authoring/parser.js +2 -914
  15. package/dist/domain/authoring/parser.js.map +1 -1
  16. package/dist/domain/authoring/serializer.d.ts +1 -2
  17. package/dist/domain/authoring/serializer.js +1 -243
  18. package/dist/domain/authoring/serializer.js.map +1 -1
  19. package/dist/domain/authoring/shared/bracket.d.ts +4 -0
  20. package/dist/domain/authoring/shared/bracket.js +95 -0
  21. package/dist/domain/authoring/shared/bracket.js.map +1 -0
  22. package/dist/domain/authoring/shared/types.d.ts +12 -0
  23. package/dist/domain/authoring/shared/types.js +2 -0
  24. package/dist/domain/authoring/shared/types.js.map +1 -0
  25. package/dist/domain/authoring/types.d.ts +2 -87
  26. package/dist/domain/authoring/types.js +2 -1
  27. package/dist/domain/authoring/types.js.map +1 -1
  28. package/dist/domain/authoring/v3/apply.d.ts +33 -0
  29. package/dist/domain/authoring/v3/apply.js +784 -0
  30. package/dist/domain/authoring/v3/apply.js.map +1 -0
  31. package/dist/domain/authoring/v3/export.d.ts +7 -0
  32. package/dist/domain/authoring/v3/export.js +85 -0
  33. package/dist/domain/authoring/v3/export.js.map +1 -0
  34. package/dist/domain/authoring/v3/parser.d.ts +3 -0
  35. package/dist/domain/authoring/v3/parser.js +823 -0
  36. package/dist/domain/authoring/v3/parser.js.map +1 -0
  37. package/dist/domain/authoring/v3/serializer.d.ts +2 -0
  38. package/dist/domain/authoring/v3/serializer.js +244 -0
  39. package/dist/domain/authoring/v3/serializer.js.map +1 -0
  40. package/dist/domain/authoring/v3/types.d.ts +76 -0
  41. package/dist/domain/authoring/v3/types.js +2 -0
  42. package/dist/domain/authoring/v3/types.js.map +1 -0
  43. package/dist/domain/authoring/v4/apply.d.ts +40 -0
  44. package/dist/domain/authoring/v4/apply.js +451 -0
  45. package/dist/domain/authoring/v4/apply.js.map +1 -0
  46. package/dist/domain/authoring/v4/parser.d.ts +2 -0
  47. package/dist/domain/authoring/v4/parser.js +729 -0
  48. package/dist/domain/authoring/v4/parser.js.map +1 -0
  49. package/dist/domain/authoring/v4/serializer.d.ts +6 -0
  50. package/dist/domain/authoring/v4/serializer.js +280 -0
  51. package/dist/domain/authoring/v4/serializer.js.map +1 -0
  52. package/dist/domain/authoring/v4/types.d.ts +50 -0
  53. package/dist/domain/authoring/v4/types.js +2 -0
  54. package/dist/domain/authoring/v4/types.js.map +1 -0
  55. package/dist/domain/ingest/apply-plan.d.ts +1 -1
  56. package/dist/domain/ingest/assembler.d.ts +9 -0
  57. package/dist/domain/ingest/assembler.js +98 -36
  58. package/dist/domain/ingest/assembler.js.map +1 -1
  59. package/dist/domain/ingest/asset-audit.d.ts +50 -0
  60. package/dist/domain/ingest/asset-audit.js +196 -0
  61. package/dist/domain/ingest/asset-audit.js.map +1 -0
  62. package/dist/domain/ingest/production-validation.d.ts +5 -4
  63. package/dist/domain/ingest/production-validation.js +10 -25
  64. package/dist/domain/ingest/production-validation.js.map +1 -1
  65. package/dist/domain/ingest/records.d.ts +1 -1
  66. package/dist/domain/ingest/records.js +1 -1
  67. package/dist/domain/ingest/records.js.map +1 -1
  68. package/dist/domain/ingest/serial-context.d.ts +1 -1
  69. package/dist/domain/ingest/validation.d.ts +1 -11
  70. package/dist/domain/ingest/validation.js +1 -199
  71. package/dist/domain/ingest/validation.js.map +1 -1
  72. package/dist/domain/ingest/video-apply.js +68 -45
  73. package/dist/domain/ingest/video-apply.js.map +1 -1
  74. package/dist/domain/script/address.d.ts +1 -32
  75. package/dist/domain/script/address.js +1 -144
  76. package/dist/domain/script/address.js.map +1 -1
  77. package/dist/domain/script/dispatch.d.ts +14 -0
  78. package/dist/domain/script/dispatch.js +47 -0
  79. package/dist/domain/script/dispatch.js.map +1 -0
  80. package/dist/domain/script/lookups.d.ts +1 -33
  81. package/dist/domain/script/lookups.js +1 -316
  82. package/dist/domain/script/lookups.js.map +1 -1
  83. package/dist/domain/script/parse.d.ts +1 -3
  84. package/dist/domain/script/parse.js +1 -164
  85. package/dist/domain/script/parse.js.map +1 -1
  86. package/dist/domain/script/patch/apply.d.ts +1 -2
  87. package/dist/domain/script/patch/apply.js +1 -30
  88. package/dist/domain/script/patch/apply.js.map +1 -1
  89. package/dist/domain/script/patch/helpers.d.ts +1 -17
  90. package/dist/domain/script/patch/helpers.js +1 -210
  91. package/dist/domain/script/patch/helpers.js.map +1 -1
  92. package/dist/domain/script/patch/inline-speaker.d.ts +1 -2
  93. package/dist/domain/script/patch/inline-speaker.js +1 -49
  94. package/dist/domain/script/patch/inline-speaker.js.map +1 -1
  95. package/dist/domain/script/patch/ops-action.d.ts +1 -12
  96. package/dist/domain/script/patch/ops-action.js +1 -366
  97. package/dist/domain/script/patch/ops-action.js.map +1 -1
  98. package/dist/domain/script/patch/ops-asset.d.ts +1 -14
  99. package/dist/domain/script/patch/ops-asset.js +1 -364
  100. package/dist/domain/script/patch/ops-asset.js.map +1 -1
  101. package/dist/domain/script/patch/ops-dialogue.d.ts +1 -2
  102. package/dist/domain/script/patch/ops-dialogue.js +1 -25
  103. package/dist/domain/script/patch/ops-dialogue.js.map +1 -1
  104. package/dist/domain/script/patch/ops-extend.d.ts +1 -8
  105. package/dist/domain/script/patch/ops-extend.js +1 -110
  106. package/dist/domain/script/patch/ops-extend.js.map +1 -1
  107. package/dist/domain/script/patch/ops-meta.d.ts +1 -5
  108. package/dist/domain/script/patch/ops-meta.js +1 -81
  109. package/dist/domain/script/patch/ops-meta.js.map +1 -1
  110. package/dist/domain/script/patch/ops-scene.d.ts +1 -6
  111. package/dist/domain/script/patch/ops-scene.js +1 -350
  112. package/dist/domain/script/patch/ops-scene.js.map +1 -1
  113. package/dist/domain/script/patch/ops-state.d.ts +1 -8
  114. package/dist/domain/script/patch/ops-state.js +1 -164
  115. package/dist/domain/script/patch/ops-state.js.map +1 -1
  116. package/dist/domain/script/patch/registry.d.ts +1 -2
  117. package/dist/domain/script/patch/registry.js +1 -52
  118. package/dist/domain/script/patch/registry.js.map +1 -1
  119. package/dist/domain/script/patch/types.d.ts +1 -10
  120. package/dist/domain/script/patch/types.js +1 -1
  121. package/dist/domain/script/patch/types.js.map +1 -1
  122. package/dist/domain/script/refs.d.ts +1 -4
  123. package/dist/domain/script/refs.js +1 -63
  124. package/dist/domain/script/refs.js.map +1 -1
  125. package/dist/domain/script/scene-refs.d.ts +1 -3
  126. package/dist/domain/script/scene-refs.js +1 -34
  127. package/dist/domain/script/scene-refs.js.map +1 -1
  128. package/dist/domain/script/schema.d.ts +1 -6
  129. package/dist/domain/script/schema.js +1 -55
  130. package/dist/domain/script/schema.js.map +1 -1
  131. package/dist/domain/script/selector.d.ts +1 -45
  132. package/dist/domain/script/selector.js +1 -184
  133. package/dist/domain/script/selector.js.map +1 -1
  134. package/dist/domain/script/shared/regex.d.ts +2 -0
  135. package/dist/domain/script/shared/regex.js +7 -0
  136. package/dist/domain/script/shared/regex.js.map +1 -0
  137. package/dist/domain/script/shared/types.d.ts +18 -0
  138. package/dist/domain/script/shared/types.js +9 -0
  139. package/dist/domain/script/shared/types.js.map +1 -0
  140. package/dist/domain/script/shared/validation.d.ts +10 -0
  141. package/dist/domain/script/shared/validation.js +2 -0
  142. package/dist/domain/script/shared/validation.js.map +1 -0
  143. package/dist/domain/script/types.d.ts +1 -123
  144. package/dist/domain/script/types.js +1 -8
  145. package/dist/domain/script/types.js.map +1 -1
  146. package/dist/domain/script/v3/address.d.ts +32 -0
  147. package/dist/domain/script/v3/address.js +145 -0
  148. package/dist/domain/script/v3/address.js.map +1 -0
  149. package/dist/domain/script/v3/lookups.d.ts +33 -0
  150. package/dist/domain/script/v3/lookups.js +317 -0
  151. package/dist/domain/script/v3/lookups.js.map +1 -0
  152. package/dist/domain/script/v3/ordinal.d.ts +8 -0
  153. package/dist/domain/script/v3/ordinal.js +92 -0
  154. package/dist/domain/script/v3/ordinal.js.map +1 -0
  155. package/dist/domain/script/v3/parse.d.ts +3 -0
  156. package/dist/domain/script/v3/parse.js +165 -0
  157. package/dist/domain/script/v3/parse.js.map +1 -0
  158. package/dist/domain/script/v3/patch/apply.d.ts +2 -0
  159. package/dist/domain/script/v3/patch/apply.js +31 -0
  160. package/dist/domain/script/v3/patch/apply.js.map +1 -0
  161. package/dist/domain/script/v3/patch/helpers.d.ts +17 -0
  162. package/dist/domain/script/v3/patch/helpers.js +211 -0
  163. package/dist/domain/script/v3/patch/helpers.js.map +1 -0
  164. package/dist/domain/script/v3/patch/inline-speaker.d.ts +2 -0
  165. package/dist/domain/script/v3/patch/inline-speaker.js +50 -0
  166. package/dist/domain/script/v3/patch/inline-speaker.js.map +1 -0
  167. package/dist/domain/script/v3/patch/ops-action.d.ts +12 -0
  168. package/dist/domain/script/v3/patch/ops-action.js +367 -0
  169. package/dist/domain/script/v3/patch/ops-action.js.map +1 -0
  170. package/dist/domain/script/v3/patch/ops-asset.d.ts +14 -0
  171. package/dist/domain/script/v3/patch/ops-asset.js +365 -0
  172. package/dist/domain/script/v3/patch/ops-asset.js.map +1 -0
  173. package/dist/domain/script/v3/patch/ops-dialogue.d.ts +2 -0
  174. package/dist/domain/script/v3/patch/ops-dialogue.js +26 -0
  175. package/dist/domain/script/v3/patch/ops-dialogue.js.map +1 -0
  176. package/dist/domain/script/v3/patch/ops-extend.d.ts +8 -0
  177. package/dist/domain/script/v3/patch/ops-extend.js +111 -0
  178. package/dist/domain/script/v3/patch/ops-extend.js.map +1 -0
  179. package/dist/domain/script/v3/patch/ops-meta.d.ts +5 -0
  180. package/dist/domain/script/v3/patch/ops-meta.js +82 -0
  181. package/dist/domain/script/v3/patch/ops-meta.js.map +1 -0
  182. package/dist/domain/script/v3/patch/ops-scene.d.ts +6 -0
  183. package/dist/domain/script/v3/patch/ops-scene.js +351 -0
  184. package/dist/domain/script/v3/patch/ops-scene.js.map +1 -0
  185. package/dist/domain/script/v3/patch/ops-state.d.ts +8 -0
  186. package/dist/domain/script/v3/patch/ops-state.js +165 -0
  187. package/dist/domain/script/v3/patch/ops-state.js.map +1 -0
  188. package/dist/domain/script/v3/patch/registry.d.ts +2 -0
  189. package/dist/domain/script/v3/patch/registry.js +53 -0
  190. package/dist/domain/script/v3/patch/registry.js.map +1 -0
  191. package/dist/domain/script/v3/patch/types.d.ts +10 -0
  192. package/dist/domain/script/v3/patch/types.js +2 -0
  193. package/dist/domain/script/v3/patch/types.js.map +1 -0
  194. package/dist/domain/script/v3/refs.d.ts +4 -0
  195. package/dist/domain/script/v3/refs.js +64 -0
  196. package/dist/domain/script/v3/refs.js.map +1 -0
  197. package/dist/domain/script/v3/scene-refs.d.ts +3 -0
  198. package/dist/domain/script/v3/scene-refs.js +35 -0
  199. package/dist/domain/script/v3/scene-refs.js.map +1 -0
  200. package/dist/domain/script/v3/schema.d.ts +6 -0
  201. package/dist/domain/script/v3/schema.js +56 -0
  202. package/dist/domain/script/v3/schema.js.map +1 -0
  203. package/dist/domain/script/v3/selector.d.ts +44 -0
  204. package/dist/domain/script/v3/selector.js +180 -0
  205. package/dist/domain/script/v3/selector.js.map +1 -0
  206. package/dist/domain/script/v3/types.d.ts +106 -0
  207. package/dist/domain/script/v3/types.js +2 -0
  208. package/dist/domain/script/v3/types.js.map +1 -0
  209. package/dist/domain/script/v3/validation.d.ts +3 -0
  210. package/dist/domain/script/v3/validation.js +200 -0
  211. package/dist/domain/script/v3/validation.js.map +1 -0
  212. package/dist/domain/script/v4/address.d.ts +61 -0
  213. package/dist/domain/script/v4/address.js +100 -0
  214. package/dist/domain/script/v4/address.js.map +1 -0
  215. package/dist/domain/script/v4/factory.d.ts +2 -0
  216. package/dist/domain/script/v4/factory.js +13 -0
  217. package/dist/domain/script/v4/factory.js.map +1 -0
  218. package/dist/domain/script/v4/from-v3.d.ts +29 -0
  219. package/dist/domain/script/v4/from-v3.js +307 -0
  220. package/dist/domain/script/v4/from-v3.js.map +1 -0
  221. package/dist/domain/script/v4/ids.d.ts +27 -0
  222. package/dist/domain/script/v4/ids.js +63 -0
  223. package/dist/domain/script/v4/ids.js.map +1 -0
  224. package/dist/domain/script/v4/ordinal.d.ts +3 -0
  225. package/dist/domain/script/v4/ordinal.js +67 -0
  226. package/dist/domain/script/v4/ordinal.js.map +1 -0
  227. package/dist/domain/script/v4/parse.d.ts +3 -0
  228. package/dist/domain/script/v4/parse.js +18 -0
  229. package/dist/domain/script/v4/parse.js.map +1 -0
  230. package/dist/domain/script/v4/patch/apply.d.ts +3 -0
  231. package/dist/domain/script/v4/patch/apply.js +24 -0
  232. package/dist/domain/script/v4/patch/apply.js.map +1 -0
  233. package/dist/domain/script/v4/patch/helpers.d.ts +32 -0
  234. package/dist/domain/script/v4/patch/helpers.js +139 -0
  235. package/dist/domain/script/v4/patch/helpers.js.map +1 -0
  236. package/dist/domain/script/v4/patch/ops-action.d.ts +13 -0
  237. package/dist/domain/script/v4/patch/ops-action.js +379 -0
  238. package/dist/domain/script/v4/patch/ops-action.js.map +1 -0
  239. package/dist/domain/script/v4/patch/ops-asset.d.ts +17 -0
  240. package/dist/domain/script/v4/patch/ops-asset.js +617 -0
  241. package/dist/domain/script/v4/patch/ops-asset.js.map +1 -0
  242. package/dist/domain/script/v4/patch/ops-extend.d.ts +11 -0
  243. package/dist/domain/script/v4/patch/ops-extend.js +86 -0
  244. package/dist/domain/script/v4/patch/ops-extend.js.map +1 -0
  245. package/dist/domain/script/v4/patch/ops-meta.d.ts +5 -0
  246. package/dist/domain/script/v4/patch/ops-meta.js +49 -0
  247. package/dist/domain/script/v4/patch/ops-meta.js.map +1 -0
  248. package/dist/domain/script/v4/patch/ops-scene-ref.d.ts +3 -0
  249. package/dist/domain/script/v4/patch/ops-scene-ref.js +98 -0
  250. package/dist/domain/script/v4/patch/ops-scene-ref.js.map +1 -0
  251. package/dist/domain/script/v4/patch/ops-structure.d.ts +6 -0
  252. package/dist/domain/script/v4/patch/ops-structure.js +236 -0
  253. package/dist/domain/script/v4/patch/ops-structure.js.map +1 -0
  254. package/dist/domain/script/v4/patch/registry.d.ts +2 -0
  255. package/dist/domain/script/v4/patch/registry.js +50 -0
  256. package/dist/domain/script/v4/patch/registry.js.map +1 -0
  257. package/dist/domain/script/v4/patch/schema.d.ts +7 -0
  258. package/dist/domain/script/v4/patch/schema.js +75 -0
  259. package/dist/domain/script/v4/patch/schema.js.map +1 -0
  260. package/dist/domain/script/v4/patch/types.d.ts +10 -0
  261. package/dist/domain/script/v4/patch/types.js +2 -0
  262. package/dist/domain/script/v4/patch/types.js.map +1 -0
  263. package/dist/domain/script/v4/selector.d.ts +11 -0
  264. package/dist/domain/script/v4/selector.js +125 -0
  265. package/dist/domain/script/v4/selector.js.map +1 -0
  266. package/dist/domain/script/v4/types.d.ts +120 -0
  267. package/dist/domain/script/v4/types.js +2 -0
  268. package/dist/domain/script/v4/types.js.map +1 -0
  269. package/dist/domain/script/v4/validation.d.ts +2 -0
  270. package/dist/domain/script/v4/validation.js +378 -0
  271. package/dist/domain/script/v4/validation.js.map +1 -0
  272. package/dist/help-text.js +146 -114
  273. package/dist/help-text.js.map +1 -1
  274. package/dist/llm/config.js +2 -0
  275. package/dist/llm/config.js.map +1 -1
  276. package/dist/llm/registry.d.ts +1 -0
  277. package/dist/llm/registry.js +3 -0
  278. package/dist/llm/registry.js.map +1 -1
  279. package/dist/llm/tasks/ingest/asset-audit.d.ts +6 -0
  280. package/dist/llm/tasks/ingest/asset-audit.js +164 -0
  281. package/dist/llm/tasks/ingest/asset-audit.js.map +1 -0
  282. package/dist/llm/tasks/ingest/asset-curate.d.ts +1 -1
  283. package/dist/llm/types.d.ts +1 -1
  284. package/dist/llm/types.js.map +1 -1
  285. package/dist/usecases/ingest/command.js +1 -1
  286. package/dist/usecases/ingest/final-asset-audit.d.ts +39 -0
  287. package/dist/usecases/ingest/final-asset-audit.js +88 -0
  288. package/dist/usecases/ingest/final-asset-audit.js.map +1 -0
  289. package/dist/usecases/ingest/pipeline.js +62 -11
  290. package/dist/usecases/ingest/pipeline.js.map +1 -1
  291. package/dist/usecases/ingest/serial-govern.d.ts +2 -1
  292. package/dist/usecases/ingest/serial-govern.js +11 -4
  293. package/dist/usecases/ingest/serial-govern.js.map +1 -1
  294. package/dist/usecases/ingest/video-pipeline.js +100 -14
  295. package/dist/usecases/ingest/video-pipeline.js.map +1 -1
  296. package/dist/usecases/ingest/view-server.js +2 -2
  297. package/dist/usecases/ingest/view-server.js.map +1 -1
  298. package/dist/usecases/script/actions.js +101 -5
  299. package/dist/usecases/script/actions.js.map +1 -1
  300. package/dist/usecases/script/actors.js +16 -7
  301. package/dist/usecases/script/actors.js.map +1 -1
  302. package/dist/usecases/script/alias.js +7 -6
  303. package/dist/usecases/script/alias.js.map +1 -1
  304. package/dist/usecases/script/assets.js +18 -2
  305. package/dist/usecases/script/assets.js.map +1 -1
  306. package/dist/usecases/script/audit-assets.d.ts +4 -0
  307. package/dist/usecases/script/audit-assets.js +40 -0
  308. package/dist/usecases/script/audit-assets.js.map +1 -0
  309. package/dist/usecases/script/command-constraints.d.ts +36 -0
  310. package/dist/usecases/script/command-constraints.js +115 -0
  311. package/dist/usecases/script/command-constraints.js.map +1 -0
  312. package/dist/usecases/script/context.js +31 -4
  313. package/dist/usecases/script/context.js.map +1 -1
  314. package/dist/usecases/script/create.js +2 -2
  315. package/dist/usecases/script/create.js.map +1 -1
  316. package/dist/usecases/script/delete.js +6 -3
  317. package/dist/usecases/script/delete.js.map +1 -1
  318. package/dist/usecases/script/describe.js +7 -4
  319. package/dist/usecases/script/describe.js.map +1 -1
  320. package/dist/usecases/script/dialogue.js +15 -5
  321. package/dist/usecases/script/dialogue.js.map +1 -1
  322. package/dist/usecases/script/dispatch.d.ts +3 -0
  323. package/dist/usecases/script/dispatch.js +10 -0
  324. package/dist/usecases/script/dispatch.js.map +1 -0
  325. package/dist/usecases/script/do.js +74 -11
  326. package/dist/usecases/script/do.js.map +1 -1
  327. package/dist/usecases/script/emotion.js +14 -3
  328. package/dist/usecases/script/emotion.js.map +1 -1
  329. package/dist/usecases/script/episodes.js +15 -4
  330. package/dist/usecases/script/episodes.js.map +1 -1
  331. package/dist/usecases/script/export-authoring.js +35 -11
  332. package/dist/usecases/script/export-authoring.js.map +1 -1
  333. package/dist/usecases/script/extend.js +23 -15
  334. package/dist/usecases/script/extend.js.map +1 -1
  335. package/dist/usecases/script/ids.js +53 -10
  336. package/dist/usecases/script/ids.js.map +1 -1
  337. package/dist/usecases/script/insert.js +74 -38
  338. package/dist/usecases/script/insert.js.map +1 -1
  339. package/dist/usecases/script/lib.d.ts +50 -1
  340. package/dist/usecases/script/lib.js +599 -61
  341. package/dist/usecases/script/lib.js.map +1 -1
  342. package/dist/usecases/script/locations.js +16 -7
  343. package/dist/usecases/script/locations.js.map +1 -1
  344. package/dist/usecases/script/merge.js +8 -5
  345. package/dist/usecases/script/merge.js.map +1 -1
  346. package/dist/usecases/script/move.js +24 -5
  347. package/dist/usecases/script/move.js.map +1 -1
  348. package/dist/usecases/script/parenthetical.d.ts +3 -0
  349. package/dist/usecases/script/parenthetical.js +55 -0
  350. package/dist/usecases/script/parenthetical.js.map +1 -0
  351. package/dist/usecases/script/props.js +16 -7
  352. package/dist/usecases/script/props.js.map +1 -1
  353. package/dist/usecases/script/refs.js +44 -0
  354. package/dist/usecases/script/refs.js.map +1 -1
  355. package/dist/usecases/script/rename.js +7 -4
  356. package/dist/usecases/script/rename.js.map +1 -1
  357. package/dist/usecases/script/scenes.js +32 -6
  358. package/dist/usecases/script/scenes.js.map +1 -1
  359. package/dist/usecases/script/script-patch.js +180 -16
  360. package/dist/usecases/script/script-patch.js.map +1 -1
  361. package/dist/usecases/script/session.d.ts +3 -0
  362. package/dist/usecases/script/session.js +25 -5
  363. package/dist/usecases/script/session.js.map +1 -1
  364. package/dist/usecases/script/split.js +12 -6
  365. package/dist/usecases/script/split.js.map +1 -1
  366. package/dist/usecases/script/states.js +45 -1
  367. package/dist/usecases/script/states.js.map +1 -1
  368. package/dist/usecases/script/synopsis.js +11 -4
  369. package/dist/usecases/script/synopsis.js.map +1 -1
  370. package/dist/usecases/script/v3/mutations.d.ts +2 -0
  371. package/dist/usecases/script/v3/mutations.js +5 -0
  372. package/dist/usecases/script/v3/mutations.js.map +1 -0
  373. package/dist/usecases/script/v4/mutations.d.ts +2 -0
  374. package/dist/usecases/script/v4/mutations.js +6 -0
  375. package/dist/usecases/script/v4/mutations.js.map +1 -0
  376. package/dist/usecases/script/v4/queries.d.ts +14 -0
  377. package/dist/usecases/script/v4/queries.js +154 -0
  378. package/dist/usecases/script/v4/queries.js.map +1 -0
  379. package/dist/usecases/script/working-copy.js +3 -3
  380. package/dist/usecases/script/working-copy.js.map +1 -1
  381. package/dist/usecases/script/write-authoring.js +99 -5
  382. package/dist/usecases/script/write-authoring.js.map +1 -1
  383. package/package.json +3 -2
  384. package/skills/scriptctl/SKILL.md +126 -283
  385. package/skills/scriptctl/references/atomic-edit-workflow.md +45 -0
  386. package/skills/scriptctl/references/bulk-authoring.md +35 -154
  387. package/skills/scriptctl/references/ingest-workflow.md +12 -11
  388. package/skills/scriptctl/references/production-writing-standard.md +38 -67
  389. package/skills/scriptctl/references/state-reference-repair.md +19 -42
  390. package/skills/scriptctl/references/atomic-write-workflow.md +0 -176
@@ -0,0 +1,617 @@
1
+ import { strOf } from "../../shared.js";
2
+ import { IMPORTANCE_TIER_SET, ROLE_TYPE_SET, } from "../../shared/types.js";
3
+ import { generateV4Id, isV4Id } from "../ids.js";
4
+ import { sortDeep } from "../../text-util.js";
5
+ import { opUsage, requireAsset, requireState, stringField } from "./helpers.js";
6
+ function aliasesFrom(raw) {
7
+ if (raw === undefined)
8
+ return undefined;
9
+ if (!Array.isArray(raw) || !raw.every((value) => typeof value === "string")) {
10
+ return opUsage("ASSET BLOCKED: aliases invalid", "aliases must be an array of strings.", {
11
+ code: "ALIASES_INVALID",
12
+ received: [JSON.stringify(raw)],
13
+ });
14
+ }
15
+ if (raw.some((value) => value === "") || new Set(raw).size !== raw.length) {
16
+ return opUsage("ASSET BLOCKED: aliases invalid", "aliases must be non-empty and unique.", {
17
+ code: "ALIASES_INVALID",
18
+ received: raw,
19
+ });
20
+ }
21
+ return raw;
22
+ }
23
+ function importanceFrom(raw) {
24
+ const value = strOf(raw).trim() || "featured";
25
+ if (!IMPORTANCE_TIER_SET.has(value)) {
26
+ return opUsage("ASSET BLOCKED: importance invalid", "importance must be featured or background.", {
27
+ code: "IMPORTANCE_INVALID",
28
+ received: [value],
29
+ });
30
+ }
31
+ return value;
32
+ }
33
+ function requestedId(ctx, kind, key, existing) {
34
+ const raw = strOf(ctx.op[key] ?? ctx.op.id).trim();
35
+ if (!raw)
36
+ return generateV4Id(kind, existing);
37
+ if (!isV4Id(kind, raw)) {
38
+ return opUsage("ASSET BLOCKED: ID invalid", `New ${kind} ID has the wrong format.`, {
39
+ code: "V4_ID_INVALID",
40
+ received: [raw],
41
+ });
42
+ }
43
+ if (existing.has(raw)) {
44
+ return opUsage("ASSET BLOCKED: ID exists", `New ${kind} ID already exists.`, {
45
+ code: "ASSET_ID_EXISTS",
46
+ received: [raw],
47
+ });
48
+ }
49
+ return raw;
50
+ }
51
+ function defaultState() {
52
+ return { state_id: "default", state_name: "default", description: "" };
53
+ }
54
+ export const op_actor_add = (ctx) => {
55
+ const name = strOf(ctx.op.name ?? ctx.op.actor_name).trim();
56
+ if (!name) {
57
+ return opUsage("ASSET BLOCKED: actor name empty", "Actor name is required.", {
58
+ code: "ASSET_NAME_EMPTY",
59
+ });
60
+ }
61
+ if (ctx.script.actors.some((actor) => actor.actor_name.trim().toLocaleLowerCase() === name.toLocaleLowerCase())) {
62
+ return opUsage("ASSET BLOCKED: actor name exists", "Actor names must be unique.", {
63
+ code: "ACTOR_NAME_EXISTS",
64
+ received: [name],
65
+ });
66
+ }
67
+ const existing = new Set(ctx.script.actors.map((actor) => actor.actor_id));
68
+ const actorId = requestedId(ctx, "actor", "actor_id", existing);
69
+ const role = strOf(ctx.op.role_type ?? ctx.op.role).trim();
70
+ if (role && !ROLE_TYPE_SET.has(role)) {
71
+ return opUsage("ASSET BLOCKED: role invalid", "role_type must be 主角 or 配角.", {
72
+ code: "ROLE_TYPE_INVALID",
73
+ received: [role],
74
+ });
75
+ }
76
+ const aliases = aliasesFrom(ctx.op.aliases);
77
+ if (aliases?.includes(name)) {
78
+ return opUsage("ASSET BLOCKED: alias equals name", "An alias must differ from the asset name.", {
79
+ code: "ALIAS_EQUALS_NAME",
80
+ received: [name],
81
+ });
82
+ }
83
+ ctx.script.actors.push({
84
+ actor_id: actorId,
85
+ actor_name: name,
86
+ importance: importanceFrom(ctx.op.importance),
87
+ description: strOf(ctx.op.description).trim(),
88
+ states: [defaultState()],
89
+ ...(role ? { role_type: role } : {}),
90
+ ...(aliases && aliases.length > 0 ? { aliases } : {}),
91
+ });
92
+ ctx.applied.push(ctx.kind);
93
+ };
94
+ export const op_location_add = (ctx) => {
95
+ const name = strOf(ctx.op.name ?? ctx.op.location_name).trim();
96
+ if (!name) {
97
+ return opUsage("ASSET BLOCKED: location name empty", "Location name is required.", {
98
+ code: "ASSET_NAME_EMPTY",
99
+ });
100
+ }
101
+ const existing = new Set(ctx.script.locations.map((asset) => asset.location_id));
102
+ ctx.script.locations.push({
103
+ location_id: requestedId(ctx, "location", "location_id", existing),
104
+ location_name: name,
105
+ importance: importanceFrom(ctx.op.importance),
106
+ description: strOf(ctx.op.description).trim(),
107
+ states: [defaultState()],
108
+ });
109
+ ctx.applied.push(ctx.kind);
110
+ };
111
+ export const op_prop_add = (ctx) => {
112
+ const name = strOf(ctx.op.name ?? ctx.op.prop_name).trim();
113
+ if (!name) {
114
+ return opUsage("ASSET BLOCKED: prop name empty", "Prop name is required.", {
115
+ code: "ASSET_NAME_EMPTY",
116
+ });
117
+ }
118
+ const existing = new Set(ctx.script.props.map((asset) => asset.prop_id));
119
+ ctx.script.props.push({
120
+ prop_id: requestedId(ctx, "prop", "prop_id", existing),
121
+ prop_name: name,
122
+ importance: importanceFrom(ctx.op.importance),
123
+ description: strOf(ctx.op.description).trim(),
124
+ states: [defaultState()],
125
+ });
126
+ ctx.applied.push(ctx.kind);
127
+ };
128
+ export const op_state_add = (ctx) => {
129
+ const target = requireAsset(ctx.script, ctx.op.target);
130
+ const name = strOf(ctx.op.name ?? ctx.op.state_name).trim();
131
+ if (!name) {
132
+ return opUsage("STATE BLOCKED: name empty", "State name is required.", {
133
+ code: "STATE_NAME_EMPTY",
134
+ });
135
+ }
136
+ if (target.asset.states.some((state) => state.state_name === name)) {
137
+ return opUsage("STATE BLOCKED: name exists", "State name already exists on this asset.", {
138
+ code: "STATE_NAME_EXISTS",
139
+ received: [name],
140
+ });
141
+ }
142
+ const existing = new Set(target.asset.states.map((state) => state.state_id));
143
+ const raw = strOf(ctx.op.state_id ?? ctx.op.id).trim();
144
+ const stateId = raw || generateV4Id("state", existing);
145
+ if (stateId === "default" || !isV4Id("state", stateId)) {
146
+ return opUsage("STATE BLOCKED: ID invalid", "New state ID must use the v4 random state format.", {
147
+ code: "STATE_ID_INVALID",
148
+ received: [stateId],
149
+ });
150
+ }
151
+ if (existing.has(stateId)) {
152
+ return opUsage("STATE BLOCKED: ID exists", "State ID already exists on this asset.", {
153
+ code: "STATE_ID_EXISTS",
154
+ received: [stateId],
155
+ });
156
+ }
157
+ target.asset.states.push({
158
+ state_id: stateId,
159
+ state_name: name,
160
+ description: strOf(ctx.op.description).trim(),
161
+ });
162
+ ctx.applied.push(ctx.kind);
163
+ };
164
+ export const op_asset_rename = (ctx) => {
165
+ const target = requireAsset(ctx.script, ctx.op.target);
166
+ const name = stringField(ctx.op, "name").trim();
167
+ if (!name) {
168
+ return opUsage("ASSET BLOCKED: name empty", "Name must not be empty.", {
169
+ code: "ASSET_NAME_EMPTY",
170
+ });
171
+ }
172
+ if (target.asset.aliases?.includes(name)) {
173
+ return opUsage("ASSET BLOCKED: name equals alias", "The new name must differ from every alias.", {
174
+ code: "ASSET_NAME_EQUALS_ALIAS",
175
+ received: [name],
176
+ });
177
+ }
178
+ if (target.kind === "actor"
179
+ && ctx.script.actors.some((actor) => actor.actor_id !== target.id
180
+ && actor.actor_name.trim().toLocaleLowerCase() === name.toLocaleLowerCase())) {
181
+ return opUsage("ASSET BLOCKED: actor name exists", "Actor names must be unique.", {
182
+ code: "ACTOR_NAME_EXISTS",
183
+ received: [name],
184
+ });
185
+ }
186
+ if (target.kind === "actor")
187
+ target.asset.actor_name = name;
188
+ else if (target.kind === "location")
189
+ target.asset.location_name = name;
190
+ else
191
+ target.asset.prop_name = name;
192
+ ctx.applied.push(ctx.kind);
193
+ };
194
+ export const op_asset_describe = (ctx) => {
195
+ requireAsset(ctx.script, ctx.op.target).asset.description = stringField(ctx.op, "description");
196
+ ctx.applied.push(ctx.kind);
197
+ };
198
+ export const op_importance_set = (ctx) => {
199
+ requireAsset(ctx.script, ctx.op.target).asset.importance = importanceFrom(ctx.op.importance);
200
+ ctx.applied.push(ctx.kind);
201
+ };
202
+ export const op_asset_role_set = (ctx) => {
203
+ const target = requireAsset(ctx.script, ctx.op.target);
204
+ if (target.kind !== "actor") {
205
+ return opUsage("ROLE BLOCKED: target is not an actor", "Role only belongs to actor assets.", {
206
+ code: "ROLE_TARGET_INVALID",
207
+ received: [target.id],
208
+ });
209
+ }
210
+ const role = strOf(ctx.op.role_type ?? ctx.op.role).trim();
211
+ if (!ROLE_TYPE_SET.has(role)) {
212
+ return opUsage("ROLE BLOCKED: role invalid", "role_type must be 主角 or 配角.", {
213
+ code: "ROLE_TYPE_INVALID",
214
+ received: [role || "<empty>"],
215
+ });
216
+ }
217
+ target.asset.role_type = role;
218
+ ctx.applied.push(ctx.kind);
219
+ };
220
+ function aliasesFromOp(ctx) {
221
+ const raw = ctx.op.alias ?? ctx.op.aliases;
222
+ const values = Array.isArray(raw) ? raw : [raw];
223
+ if (!values.every((value) => typeof value === "string" && value.trim() !== "")) {
224
+ return opUsage("ALIAS BLOCKED: alias invalid", "Aliases must be non-empty strings.", {
225
+ code: "ALIAS_INVALID",
226
+ received: [JSON.stringify(raw)],
227
+ });
228
+ }
229
+ const aliases = values.map((value) => value.trim());
230
+ if (new Set(aliases).size !== aliases.length) {
231
+ return opUsage("ALIAS BLOCKED: alias duplicated", "Aliases in one operation must be unique.", {
232
+ code: "ALIAS_DUPLICATE",
233
+ received: aliases,
234
+ });
235
+ }
236
+ return aliases;
237
+ }
238
+ function assetName(asset) {
239
+ if ("actor_name" in asset)
240
+ return asset.actor_name;
241
+ if ("location_name" in asset)
242
+ return asset.location_name;
243
+ return asset.prop_name;
244
+ }
245
+ function assertAliasesDifferFromName(target, aliases) {
246
+ const name = assetName(target);
247
+ if (aliases.includes(name)) {
248
+ opUsage("ALIAS BLOCKED: alias equals name", "An alias must differ from the asset name.", {
249
+ code: "ALIAS_EQUALS_NAME",
250
+ received: [name],
251
+ });
252
+ }
253
+ }
254
+ export const op_asset_alias_set = (ctx) => {
255
+ const target = requireAsset(ctx.script, ctx.op.target).asset;
256
+ const aliases = aliasesFromOp(ctx);
257
+ assertAliasesDifferFromName(target, aliases);
258
+ target.aliases = aliases;
259
+ if (target.aliases.length === 0)
260
+ delete target.aliases;
261
+ ctx.applied.push(ctx.kind);
262
+ };
263
+ export const op_asset_alias_add = (ctx) => {
264
+ const target = requireAsset(ctx.script, ctx.op.target).asset;
265
+ const added = aliasesFromOp(ctx);
266
+ assertAliasesDifferFromName(target, added);
267
+ const duplicates = added.filter((alias) => target.aliases?.includes(alias));
268
+ if (duplicates.length > 0) {
269
+ return opUsage("ALIAS BLOCKED: alias exists", "The asset already has this alias.", {
270
+ code: "ALIAS_EXISTS",
271
+ received: duplicates,
272
+ });
273
+ }
274
+ const aliases = [...(target.aliases ?? []), ...added];
275
+ target.aliases = aliases;
276
+ ctx.applied.push(ctx.kind);
277
+ };
278
+ export const op_asset_alias_remove = (ctx) => {
279
+ const target = requireAsset(ctx.script, ctx.op.target).asset;
280
+ const removing = new Set(aliasesFromOp(ctx));
281
+ const aliases = (target.aliases ?? []).filter((alias) => !removing.has(alias));
282
+ if (aliases.length > 0)
283
+ target.aliases = aliases;
284
+ else
285
+ delete target.aliases;
286
+ ctx.applied.push(ctx.kind);
287
+ };
288
+ export const op_state_rename = (ctx) => {
289
+ const target = requireState(ctx.script, ctx.op.target);
290
+ const name = stringField(ctx.op, "name").trim();
291
+ if (!name) {
292
+ return opUsage("STATE BLOCKED: name empty", "State name must not be empty.", {
293
+ code: "STATE_NAME_EMPTY",
294
+ });
295
+ }
296
+ if (target.owner.asset.states.some((state) => state !== target.state && state.state_name === name)) {
297
+ return opUsage("STATE BLOCKED: name exists", "State name already exists on this asset.", {
298
+ code: "STATE_NAME_EXISTS",
299
+ received: [name],
300
+ });
301
+ }
302
+ target.state.state_name = name;
303
+ ctx.applied.push(ctx.kind);
304
+ };
305
+ export const op_state_describe = (ctx) => {
306
+ requireState(ctx.script, ctx.op.target).state.description = stringField(ctx.op, "description");
307
+ ctx.applied.push(ctx.kind);
308
+ };
309
+ function replaceStateId(ids, from, replacement) {
310
+ const next = ids.flatMap((id) => id === from ? (replacement ? [replacement] : []) : [id]);
311
+ return [...new Set(next)].sort();
312
+ }
313
+ export const op_state_delete = (ctx) => {
314
+ const target = requireState(ctx.script, ctx.op.target);
315
+ if (target.state.state_id === "default") {
316
+ return opUsage("STATE DELETE BLOCKED: default is protected", "Every asset must retain its default state.", {
317
+ code: "STATE_DEFAULT_PROTECTED",
318
+ });
319
+ }
320
+ const strategy = strOf(ctx.op.strategy).trim();
321
+ if (strategy !== "replace" && strategy !== "remove") {
322
+ return opUsage("STATE DELETE BLOCKED: strategy invalid", "Choose replace or remove.", {
323
+ code: "DELETE_STRATEGY_INVALID",
324
+ received: [strategy || "<empty>"],
325
+ });
326
+ }
327
+ if (strategy === "remove" && ctx.op.replacement !== undefined) {
328
+ return opUsage("STATE DELETE BLOCKED: replacement conflicts with remove", "replacement only belongs to the replace strategy.", {
329
+ code: "DELETE_REPLACEMENT_UNEXPECTED",
330
+ received: [strOf(ctx.op.replacement)],
331
+ });
332
+ }
333
+ const replacementRaw = strOf(ctx.op.replacement).trim();
334
+ const replacement = strategy === "replace"
335
+ ? target.owner.asset.states.find((state) => state.state_id === replacementRaw && state.state_id !== target.state.state_id)
336
+ : undefined;
337
+ if (strategy === "replace" && !replacement) {
338
+ return opUsage("STATE DELETE BLOCKED: replacement invalid", "Replacement must be another state on the same asset.", {
339
+ code: "REPLACEMENT_INVALID",
340
+ received: [replacementRaw || "<empty>"],
341
+ });
342
+ }
343
+ const fromId = target.state.state_id;
344
+ const replacementId = replacement?.state_id ?? null;
345
+ const stateRefUpdates = [];
346
+ const queueStateRefUpdate = (sceneId, stateIds, write) => {
347
+ const next = replaceStateId(stateIds, fromId, replacementId);
348
+ if (next.length === 0) {
349
+ return opUsage("STATE DELETE BLOCKED: scene state set would be empty", "Replace the state or add another state to the scene first.", {
350
+ code: "SCENE_REF_STATES_EMPTY",
351
+ received: [sceneId, fromId],
352
+ });
353
+ }
354
+ stateRefUpdates.push(() => write(next));
355
+ };
356
+ for (const episode of ctx.script.episodes) {
357
+ for (const scene of episode.scenes) {
358
+ if (target.owner.kind === "location" && scene.location?.location_id === target.owner.id) {
359
+ const ref = scene.location;
360
+ queueStateRefUpdate(scene.scene_id, ref.state_ids, (next) => {
361
+ ref.state_ids = next;
362
+ });
363
+ }
364
+ else if (target.owner.kind === "actor") {
365
+ const ref = scene.actors.find((candidate) => candidate.actor_id === target.owner.id);
366
+ if (ref) {
367
+ queueStateRefUpdate(scene.scene_id, ref.state_ids, (next) => {
368
+ ref.state_ids = next;
369
+ });
370
+ }
371
+ }
372
+ else if (target.owner.kind === "prop") {
373
+ const ref = scene.props.find((candidate) => candidate.prop_id === target.owner.id);
374
+ if (ref) {
375
+ queueStateRefUpdate(scene.scene_id, ref.state_ids, (next) => {
376
+ ref.state_ids = next;
377
+ });
378
+ }
379
+ }
380
+ }
381
+ }
382
+ for (const update of stateRefUpdates)
383
+ update();
384
+ if (target.owner.kind === "actor") {
385
+ for (const episode of ctx.script.episodes) {
386
+ for (const scene of episode.scenes) {
387
+ for (const action of scene.actions) {
388
+ if ((action.type === "dialogue" || action.type === "inner_thought")
389
+ && "actor_id" in action.speaker
390
+ && action.speaker.actor_id === target.owner.id
391
+ && action.speaker.state_id === fromId) {
392
+ if (replacementId)
393
+ action.speaker.state_id = replacementId;
394
+ else
395
+ delete action.speaker.state_id;
396
+ }
397
+ }
398
+ }
399
+ }
400
+ }
401
+ target.owner.asset.states.splice(target.stateIndex, 1);
402
+ ctx.applied.push(ctx.kind);
403
+ };
404
+ function assetRefCount(ctx, kind, id) {
405
+ let count = 0;
406
+ for (const episode of ctx.script.episodes) {
407
+ for (const scene of episode.scenes) {
408
+ if (kind === "actor") {
409
+ if (scene.actors.some((ref) => ref.actor_id === id))
410
+ count++;
411
+ count += scene.actions.filter((action) => (action.type === "dialogue" || action.type === "inner_thought")
412
+ && "actor_id" in action.speaker
413
+ && action.speaker.actor_id === id).length;
414
+ }
415
+ else if (kind === "location" && scene.location?.location_id === id) {
416
+ count++;
417
+ }
418
+ else if (kind === "prop" && scene.props.some((ref) => ref.prop_id === id)) {
419
+ count++;
420
+ }
421
+ count += scene.actions.filter((action) => action.transition_prompt?.target === id).length;
422
+ }
423
+ }
424
+ return count;
425
+ }
426
+ export const op_asset_merge = (ctx) => {
427
+ const from = requireAsset(ctx.script, ctx.op.from ?? ctx.op.source);
428
+ const into = requireAsset(ctx.script, ctx.op.into ?? ctx.op.target);
429
+ if (from.kind !== into.kind) {
430
+ return opUsage("ASSET MERGE BLOCKED: kind mismatch", "Both assets must have the same kind.", {
431
+ code: "MERGE_KIND_MISMATCH",
432
+ received: [from.kind, into.kind],
433
+ });
434
+ }
435
+ if (from.id === into.id) {
436
+ return opUsage("ASSET MERGE BLOCKED: same asset", "An asset cannot be merged into itself.", {
437
+ code: "MERGE_SELF",
438
+ received: [from.id],
439
+ });
440
+ }
441
+ const fromStates = new Map(from.asset.states.map((state) => [state.state_id, state]));
442
+ const intoStates = new Map(into.asset.states.map((state) => [state.state_id, state]));
443
+ const referencedStates = new Set();
444
+ for (const episode of ctx.script.episodes) {
445
+ for (const scene of episode.scenes) {
446
+ if (from.kind === "location" && scene.location?.location_id === from.id) {
447
+ scene.location.state_ids.forEach((id) => referencedStates.add(id));
448
+ }
449
+ else if (from.kind === "actor") {
450
+ scene.actors.find((ref) => ref.actor_id === from.id)?.state_ids.forEach((id) => referencedStates.add(id));
451
+ }
452
+ else if (from.kind === "prop") {
453
+ scene.props.find((ref) => ref.prop_id === from.id)?.state_ids.forEach((id) => referencedStates.add(id));
454
+ }
455
+ if (from.kind === "actor") {
456
+ for (const action of scene.actions) {
457
+ if ((action.type === "dialogue" || action.type === "inner_thought")
458
+ && "actor_id" in action.speaker
459
+ && action.speaker.actor_id === from.id
460
+ && action.speaker.state_id)
461
+ referencedStates.add(action.speaker.state_id);
462
+ }
463
+ }
464
+ }
465
+ }
466
+ const missing = [...referencedStates].filter((id) => !intoStates.has(id));
467
+ const conflicting = [...referencedStates].filter((id) => {
468
+ if (id === "default")
469
+ return false;
470
+ const sourceState = fromStates.get(id);
471
+ const survivorState = intoStates.get(id);
472
+ return sourceState !== undefined
473
+ && survivorState !== undefined
474
+ && JSON.stringify(sortDeep(sourceState)) !== JSON.stringify(sortDeep(survivorState));
475
+ });
476
+ if (missing.length > 0 || conflicting.length > 0) {
477
+ return opUsage("ASSET MERGE BLOCKED: state mismatch", "The survivor lacks a referenced source state or uses the same owner-local ID for a different state.", {
478
+ code: "MERGE_STATE_CONFLICT",
479
+ received: [
480
+ ...missing.map((id) => `missing:${id}`),
481
+ ...conflicting.map((id) => `different:${id}`),
482
+ ],
483
+ });
484
+ }
485
+ for (const episode of ctx.script.episodes) {
486
+ for (const scene of episode.scenes) {
487
+ if (from.kind === "location" && into.kind === "location" && scene.location?.location_id === from.id) {
488
+ scene.location.location_id = into.id;
489
+ }
490
+ else if (from.kind === "actor" && into.kind === "actor") {
491
+ const sourceIndex = scene.actors.findIndex((ref) => ref.actor_id === from.id);
492
+ if (sourceIndex >= 0) {
493
+ const sourceRef = scene.actors[sourceIndex];
494
+ const targetRef = scene.actors.find((ref) => ref.actor_id === into.id);
495
+ if (targetRef) {
496
+ targetRef.state_ids = [...new Set([...targetRef.state_ids, ...sourceRef.state_ids])].sort();
497
+ scene.actors.splice(sourceIndex, 1);
498
+ }
499
+ else {
500
+ sourceRef.actor_id = into.id;
501
+ }
502
+ }
503
+ }
504
+ else if (from.kind === "prop" && into.kind === "prop") {
505
+ const sourceIndex = scene.props.findIndex((ref) => ref.prop_id === from.id);
506
+ if (sourceIndex >= 0) {
507
+ const sourceRef = scene.props[sourceIndex];
508
+ const targetRef = scene.props.find((ref) => ref.prop_id === into.id);
509
+ if (targetRef) {
510
+ targetRef.state_ids = [...new Set([...targetRef.state_ids, ...sourceRef.state_ids])].sort();
511
+ scene.props.splice(sourceIndex, 1);
512
+ }
513
+ else {
514
+ sourceRef.prop_id = into.id;
515
+ }
516
+ }
517
+ }
518
+ for (const action of scene.actions) {
519
+ if (from.kind === "actor"
520
+ && into.kind === "actor"
521
+ && (action.type === "dialogue" || action.type === "inner_thought")
522
+ && "actor_id" in action.speaker
523
+ && action.speaker.actor_id === from.id)
524
+ action.speaker.actor_id = into.id;
525
+ if (action.transition_prompt?.target === from.id)
526
+ action.transition_prompt.target = into.id;
527
+ }
528
+ }
529
+ }
530
+ const survivorName = assetName(into.asset);
531
+ const mergedAliases = [...new Set([
532
+ ...(into.asset.aliases ?? []),
533
+ assetName(from.asset),
534
+ ...(from.asset.aliases ?? []),
535
+ ])].filter((alias) => alias !== survivorName);
536
+ assertAliasesDifferFromName(into.asset, mergedAliases);
537
+ into.asset.aliases = mergedAliases;
538
+ if (into.asset.aliases.length === 0)
539
+ delete into.asset.aliases;
540
+ if (from.asset.extend)
541
+ into.asset.extend = { ...from.asset.extend, ...(into.asset.extend ?? {}) };
542
+ if (from.kind === "actor")
543
+ ctx.script.actors = ctx.script.actors.filter((asset) => asset.actor_id !== from.id);
544
+ else if (from.kind === "location")
545
+ ctx.script.locations = ctx.script.locations.filter((asset) => asset.location_id !== from.id);
546
+ else
547
+ ctx.script.props = ctx.script.props.filter((asset) => asset.prop_id !== from.id);
548
+ ctx.applied.push(ctx.kind);
549
+ };
550
+ export const op_asset_delete = (ctx) => {
551
+ const target = requireAsset(ctx.script, ctx.op.target);
552
+ const count = assetRefCount(ctx, target.kind, target.id);
553
+ const strategy = strOf(ctx.op.strategy).trim();
554
+ if (strategy !== "" && strategy !== "replace" && strategy !== "remove") {
555
+ return opUsage("ASSET DELETE BLOCKED: strategy invalid", "Choose replace or remove.", {
556
+ code: "DELETE_STRATEGY_INVALID",
557
+ received: [strategy],
558
+ });
559
+ }
560
+ if (strategy === "replace") {
561
+ const replacement = strOf(ctx.op.replacement).trim();
562
+ if (!replacement) {
563
+ return opUsage("ASSET DELETE BLOCKED: replacement missing", "The replace strategy requires a replacement asset.", {
564
+ code: "REPLACEMENT_INVALID",
565
+ received: ["<empty>"],
566
+ });
567
+ }
568
+ ctx.runOps([{ op: "asset.merge", from: target.id, into: replacement }]);
569
+ ctx.applied.push(ctx.kind);
570
+ return;
571
+ }
572
+ if (ctx.op.replacement !== undefined) {
573
+ return opUsage("ASSET DELETE BLOCKED: replacement conflicts with remove", "replacement only belongs to the replace strategy.", {
574
+ code: "DELETE_REPLACEMENT_UNEXPECTED",
575
+ received: [strOf(ctx.op.replacement)],
576
+ });
577
+ }
578
+ if (count > 0 && !strategy) {
579
+ return opUsage("ASSET DELETE BLOCKED: asset is referenced", "Choose replace or remove.", {
580
+ code: "ASSET_HAS_REFS",
581
+ received: [`refs=${count}`],
582
+ });
583
+ }
584
+ if (target.kind === "actor") {
585
+ const speaking = ctx.script.episodes.flatMap((episode) => episode.scenes).some((scene) => scene.actions.some((action) => (action.type === "dialogue" || action.type === "inner_thought")
586
+ && "actor_id" in action.speaker
587
+ && action.speaker.actor_id === target.id));
588
+ if (speaking) {
589
+ return opUsage("ASSET DELETE BLOCKED: actor still speaks", "Reassign or delete the actor's speaking actions first.", {
590
+ code: "ACTOR_SPEAKER_IN_USE",
591
+ received: [target.id],
592
+ });
593
+ }
594
+ }
595
+ for (const episode of ctx.script.episodes) {
596
+ for (const scene of episode.scenes) {
597
+ if (target.kind === "actor")
598
+ scene.actors = scene.actors.filter((ref) => ref.actor_id !== target.id);
599
+ else if (target.kind === "location" && scene.location?.location_id === target.id)
600
+ scene.location = null;
601
+ else if (target.kind === "prop")
602
+ scene.props = scene.props.filter((ref) => ref.prop_id !== target.id);
603
+ for (const action of scene.actions) {
604
+ if (action.transition_prompt?.target === target.id)
605
+ delete action.transition_prompt;
606
+ }
607
+ }
608
+ }
609
+ if (target.kind === "actor")
610
+ ctx.script.actors = ctx.script.actors.filter((asset) => asset.actor_id !== target.id);
611
+ else if (target.kind === "location")
612
+ ctx.script.locations = ctx.script.locations.filter((asset) => asset.location_id !== target.id);
613
+ else
614
+ ctx.script.props = ctx.script.props.filter((asset) => asset.prop_id !== target.id);
615
+ ctx.applied.push(ctx.kind);
616
+ };
617
+ //# sourceMappingURL=ops-asset.js.map