@lingjingai/scriptctl 0.63.14 → 0.63.15

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 (777) hide show
  1. package/README.md +7 -1
  2. package/changes/0.63.15.md +15 -0
  3. package/dist/bin.js +1 -20844
  4. package/dist/chunk-3LPIMYYI.js +823 -0
  5. package/dist/cli.d.ts +214 -5
  6. package/dist/cli.js +1 -187
  7. package/dist/review-agent.js +56 -3593
  8. package/package.json +12 -5
  9. package/dist/bin.d.ts +0 -2
  10. package/dist/bin.js.map +0 -7
  11. package/dist/cli/register-authoring.d.ts +0 -4
  12. package/dist/cli/register-authoring.js +0 -35
  13. package/dist/cli/register-authoring.js.map +0 -1
  14. package/dist/cli/register-review.d.ts +0 -3
  15. package/dist/cli/register-review.js +0 -20
  16. package/dist/cli/register-review.js.map +0 -1
  17. package/dist/cli/register-script.d.ts +0 -3
  18. package/dist/cli/register-script.js +0 -297
  19. package/dist/cli/register-script.js.map +0 -1
  20. package/dist/cli/register-tools.d.ts +0 -3
  21. package/dist/cli/register-tools.js +0 -23
  22. package/dist/cli/register-tools.js.map +0 -1
  23. package/dist/cli/register-workflows.d.ts +0 -4
  24. package/dist/cli/register-workflows.js +0 -108
  25. package/dist/cli/register-workflows.js.map +0 -1
  26. package/dist/cli/registry.d.ts +0 -14
  27. package/dist/cli/registry.js +0 -65
  28. package/dist/cli/registry.js.map +0 -1
  29. package/dist/cli.js.map +0 -1
  30. package/dist/common.d.ts +0 -93
  31. package/dist/common.js +0 -240
  32. package/dist/common.js.map +0 -1
  33. package/dist/domain/authoring/apply.d.ts +0 -1
  34. package/dist/domain/authoring/apply.js +0 -2
  35. package/dist/domain/authoring/apply.js.map +0 -1
  36. package/dist/domain/authoring/export.d.ts +0 -1
  37. package/dist/domain/authoring/export.js +0 -2
  38. package/dist/domain/authoring/export.js.map +0 -1
  39. package/dist/domain/authoring/parser.d.ts +0 -2
  40. package/dist/domain/authoring/parser.js +0 -3
  41. package/dist/domain/authoring/parser.js.map +0 -1
  42. package/dist/domain/authoring/serializer.d.ts +0 -1
  43. package/dist/domain/authoring/serializer.js +0 -2
  44. package/dist/domain/authoring/serializer.js.map +0 -1
  45. package/dist/domain/authoring/shared/bracket.d.ts +0 -4
  46. package/dist/domain/authoring/shared/bracket.js +0 -95
  47. package/dist/domain/authoring/shared/bracket.js.map +0 -1
  48. package/dist/domain/authoring/shared/types.d.ts +0 -12
  49. package/dist/domain/authoring/shared/types.js +0 -2
  50. package/dist/domain/authoring/shared/types.js.map +0 -1
  51. package/dist/domain/authoring/types.d.ts +0 -2
  52. package/dist/domain/authoring/types.js +0 -3
  53. package/dist/domain/authoring/types.js.map +0 -1
  54. package/dist/domain/authoring/v3/apply.d.ts +0 -33
  55. package/dist/domain/authoring/v3/apply.js +0 -784
  56. package/dist/domain/authoring/v3/apply.js.map +0 -1
  57. package/dist/domain/authoring/v3/export.d.ts +0 -7
  58. package/dist/domain/authoring/v3/export.js +0 -85
  59. package/dist/domain/authoring/v3/export.js.map +0 -1
  60. package/dist/domain/authoring/v3/parser.d.ts +0 -3
  61. package/dist/domain/authoring/v3/parser.js +0 -823
  62. package/dist/domain/authoring/v3/parser.js.map +0 -1
  63. package/dist/domain/authoring/v3/serializer.d.ts +0 -2
  64. package/dist/domain/authoring/v3/serializer.js +0 -244
  65. package/dist/domain/authoring/v3/serializer.js.map +0 -1
  66. package/dist/domain/authoring/v3/types.d.ts +0 -76
  67. package/dist/domain/authoring/v3/types.js +0 -2
  68. package/dist/domain/authoring/v3/types.js.map +0 -1
  69. package/dist/domain/authoring/v4/apply.d.ts +0 -40
  70. package/dist/domain/authoring/v4/apply.js +0 -451
  71. package/dist/domain/authoring/v4/apply.js.map +0 -1
  72. package/dist/domain/authoring/v4/parser.d.ts +0 -2
  73. package/dist/domain/authoring/v4/parser.js +0 -729
  74. package/dist/domain/authoring/v4/parser.js.map +0 -1
  75. package/dist/domain/authoring/v4/serializer.d.ts +0 -6
  76. package/dist/domain/authoring/v4/serializer.js +0 -280
  77. package/dist/domain/authoring/v4/serializer.js.map +0 -1
  78. package/dist/domain/authoring/v4/types.d.ts +0 -50
  79. package/dist/domain/authoring/v4/types.js +0 -2
  80. package/dist/domain/authoring/v4/types.js.map +0 -1
  81. package/dist/domain/creative-draft/compose.d.ts +0 -18
  82. package/dist/domain/creative-draft/compose.js +0 -448
  83. package/dist/domain/creative-draft/compose.js.map +0 -1
  84. package/dist/domain/ingest/apply-plan.d.ts +0 -23
  85. package/dist/domain/ingest/apply-plan.js +0 -210
  86. package/dist/domain/ingest/apply-plan.js.map +0 -1
  87. package/dist/domain/ingest/assembler.d.ts +0 -65
  88. package/dist/domain/ingest/assembler.js +0 -263
  89. package/dist/domain/ingest/assembler.js.map +0 -1
  90. package/dist/domain/ingest/asset-audit.d.ts +0 -50
  91. package/dist/domain/ingest/asset-audit.js +0 -196
  92. package/dist/domain/ingest/asset-audit.js.map +0 -1
  93. package/dist/domain/ingest/chunker.d.ts +0 -9
  94. package/dist/domain/ingest/chunker.js +0 -49
  95. package/dist/domain/ingest/chunker.js.map +0 -1
  96. package/dist/domain/ingest/environment.d.ts +0 -3
  97. package/dist/domain/ingest/environment.js +0 -32
  98. package/dist/domain/ingest/environment.js.map +0 -1
  99. package/dist/domain/ingest/evidence.d.ts +0 -5
  100. package/dist/domain/ingest/evidence.js +0 -66
  101. package/dist/domain/ingest/evidence.js.map +0 -1
  102. package/dist/domain/ingest/govern.d.ts +0 -3
  103. package/dist/domain/ingest/govern.js +0 -157
  104. package/dist/domain/ingest/govern.js.map +0 -1
  105. package/dist/domain/ingest/jsonl-parser.d.ts +0 -6
  106. package/dist/domain/ingest/jsonl-parser.js +0 -204
  107. package/dist/domain/ingest/jsonl-parser.js.map +0 -1
  108. package/dist/domain/ingest/markdown-parser.d.ts +0 -6
  109. package/dist/domain/ingest/markdown-parser.js +0 -187
  110. package/dist/domain/ingest/markdown-parser.js.map +0 -1
  111. package/dist/domain/ingest/production-validation.d.ts +0 -8
  112. package/dist/domain/ingest/production-validation.js +0 -37
  113. package/dist/domain/ingest/production-validation.js.map +0 -1
  114. package/dist/domain/ingest/records.d.ts +0 -72
  115. package/dist/domain/ingest/records.js +0 -10
  116. package/dist/domain/ingest/records.js.map +0 -1
  117. package/dist/domain/ingest/renumber.d.ts +0 -14
  118. package/dist/domain/ingest/renumber.js +0 -130
  119. package/dist/domain/ingest/renumber.js.map +0 -1
  120. package/dist/domain/ingest/serial-context.d.ts +0 -93
  121. package/dist/domain/ingest/serial-context.js +0 -355
  122. package/dist/domain/ingest/serial-context.js.map +0 -1
  123. package/dist/domain/ingest/state-identity.d.ts +0 -2
  124. package/dist/domain/ingest/state-identity.js +0 -3
  125. package/dist/domain/ingest/state-identity.js.map +0 -1
  126. package/dist/domain/ingest/state-reconcile.d.ts +0 -12
  127. package/dist/domain/ingest/state-reconcile.js +0 -92
  128. package/dist/domain/ingest/state-reconcile.js.map +0 -1
  129. package/dist/domain/ingest/validation.d.ts +0 -1
  130. package/dist/domain/ingest/validation.js +0 -2
  131. package/dist/domain/ingest/validation.js.map +0 -1
  132. package/dist/domain/ingest/video-apply.d.ts +0 -4
  133. package/dist/domain/ingest/video-apply.js +0 -128
  134. package/dist/domain/ingest/video-apply.js.map +0 -1
  135. package/dist/domain/ingest/video-context.d.ts +0 -64
  136. package/dist/domain/ingest/video-context.js +0 -480
  137. package/dist/domain/ingest/video-context.js.map +0 -1
  138. package/dist/domain/ingest/video-records.d.ts +0 -57
  139. package/dist/domain/ingest/video-records.js +0 -9
  140. package/dist/domain/ingest/video-records.js.map +0 -1
  141. package/dist/domain/ingest/video-serial-md.d.ts +0 -81
  142. package/dist/domain/ingest/video-serial-md.js +0 -297
  143. package/dist/domain/ingest/video-serial-md.js.map +0 -1
  144. package/dist/domain/ingest/video-source-evolution.d.ts +0 -25
  145. package/dist/domain/ingest/video-source-evolution.js +0 -40
  146. package/dist/domain/ingest/video-source-evolution.js.map +0 -1
  147. package/dist/domain/ingest/video-state-evidence.d.ts +0 -66
  148. package/dist/domain/ingest/video-state-evidence.js +0 -385
  149. package/dist/domain/ingest/video-state-evidence.js.map +0 -1
  150. package/dist/domain/ingest/video-timestamp.d.ts +0 -8
  151. package/dist/domain/ingest/video-timestamp.js +0 -26
  152. package/dist/domain/ingest/video-timestamp.js.map +0 -1
  153. package/dist/domain/loom/checkpointer.d.ts +0 -3
  154. package/dist/domain/loom/checkpointer.js +0 -30
  155. package/dist/domain/loom/checkpointer.js.map +0 -1
  156. package/dist/domain/loom/index.d.ts +0 -45
  157. package/dist/domain/loom/index.js +0 -277
  158. package/dist/domain/loom/index.js.map +0 -1
  159. package/dist/domain/loom/types.d.ts +0 -101
  160. package/dist/domain/loom/types.js +0 -2
  161. package/dist/domain/loom/types.js.map +0 -1
  162. package/dist/domain/script/address.d.ts +0 -1
  163. package/dist/domain/script/address.js +0 -2
  164. package/dist/domain/script/address.js.map +0 -1
  165. package/dist/domain/script/dispatch.d.ts +0 -18
  166. package/dist/domain/script/dispatch.js +0 -55
  167. package/dist/domain/script/dispatch.js.map +0 -1
  168. package/dist/domain/script/lookups.d.ts +0 -1
  169. package/dist/domain/script/lookups.js +0 -2
  170. package/dist/domain/script/lookups.js.map +0 -1
  171. package/dist/domain/script/migrations/registry.d.ts +0 -4
  172. package/dist/domain/script/migrations/registry.js +0 -76
  173. package/dist/domain/script/migrations/registry.js.map +0 -1
  174. package/dist/domain/script/migrations/types.d.ts +0 -17
  175. package/dist/domain/script/migrations/types.js +0 -2
  176. package/dist/domain/script/migrations/types.js.map +0 -1
  177. package/dist/domain/script/migrations/v3-to-v4.d.ts +0 -3
  178. package/dist/domain/script/migrations/v3-to-v4.js +0 -57
  179. package/dist/domain/script/migrations/v3-to-v4.js.map +0 -1
  180. package/dist/domain/script/names.d.ts +0 -1
  181. package/dist/domain/script/names.js +0 -2
  182. package/dist/domain/script/names.js.map +0 -1
  183. package/dist/domain/script/parse.d.ts +0 -1
  184. package/dist/domain/script/parse.js +0 -2
  185. package/dist/domain/script/parse.js.map +0 -1
  186. package/dist/domain/script/patch/apply.d.ts +0 -1
  187. package/dist/domain/script/patch/apply.js +0 -2
  188. package/dist/domain/script/patch/apply.js.map +0 -1
  189. package/dist/domain/script/patch/helpers.d.ts +0 -1
  190. package/dist/domain/script/patch/helpers.js +0 -2
  191. package/dist/domain/script/patch/helpers.js.map +0 -1
  192. package/dist/domain/script/patch/inline-speaker.d.ts +0 -1
  193. package/dist/domain/script/patch/inline-speaker.js +0 -2
  194. package/dist/domain/script/patch/inline-speaker.js.map +0 -1
  195. package/dist/domain/script/patch/ops-action.d.ts +0 -1
  196. package/dist/domain/script/patch/ops-action.js +0 -2
  197. package/dist/domain/script/patch/ops-action.js.map +0 -1
  198. package/dist/domain/script/patch/ops-asset.d.ts +0 -1
  199. package/dist/domain/script/patch/ops-asset.js +0 -2
  200. package/dist/domain/script/patch/ops-asset.js.map +0 -1
  201. package/dist/domain/script/patch/ops-dialogue.d.ts +0 -1
  202. package/dist/domain/script/patch/ops-dialogue.js +0 -2
  203. package/dist/domain/script/patch/ops-dialogue.js.map +0 -1
  204. package/dist/domain/script/patch/ops-extend.d.ts +0 -1
  205. package/dist/domain/script/patch/ops-extend.js +0 -2
  206. package/dist/domain/script/patch/ops-extend.js.map +0 -1
  207. package/dist/domain/script/patch/ops-meta.d.ts +0 -1
  208. package/dist/domain/script/patch/ops-meta.js +0 -2
  209. package/dist/domain/script/patch/ops-meta.js.map +0 -1
  210. package/dist/domain/script/patch/ops-scene.d.ts +0 -1
  211. package/dist/domain/script/patch/ops-scene.js +0 -2
  212. package/dist/domain/script/patch/ops-scene.js.map +0 -1
  213. package/dist/domain/script/patch/ops-state.d.ts +0 -1
  214. package/dist/domain/script/patch/ops-state.js +0 -2
  215. package/dist/domain/script/patch/ops-state.js.map +0 -1
  216. package/dist/domain/script/patch/registry.d.ts +0 -1
  217. package/dist/domain/script/patch/registry.js +0 -2
  218. package/dist/domain/script/patch/registry.js.map +0 -1
  219. package/dist/domain/script/patch/types.d.ts +0 -1
  220. package/dist/domain/script/patch/types.js +0 -2
  221. package/dist/domain/script/patch/types.js.map +0 -1
  222. package/dist/domain/script/refs.d.ts +0 -1
  223. package/dist/domain/script/refs.js +0 -2
  224. package/dist/domain/script/refs.js.map +0 -1
  225. package/dist/domain/script/scene-refs.d.ts +0 -1
  226. package/dist/domain/script/scene-refs.js +0 -2
  227. package/dist/domain/script/scene-refs.js.map +0 -1
  228. package/dist/domain/script/schema.d.ts +0 -1
  229. package/dist/domain/script/schema.js +0 -2
  230. package/dist/domain/script/schema.js.map +0 -1
  231. package/dist/domain/script/selector.d.ts +0 -1
  232. package/dist/domain/script/selector.js +0 -2
  233. package/dist/domain/script/selector.js.map +0 -1
  234. package/dist/domain/script/shared/regex.d.ts +0 -2
  235. package/dist/domain/script/shared/regex.js +0 -7
  236. package/dist/domain/script/shared/regex.js.map +0 -1
  237. package/dist/domain/script/shared/types.d.ts +0 -1
  238. package/dist/domain/script/shared/types.js +0 -5
  239. package/dist/domain/script/shared/types.js.map +0 -1
  240. package/dist/domain/script/shared/validation.d.ts +0 -1
  241. package/dist/domain/script/shared/validation.js +0 -3
  242. package/dist/domain/script/shared/validation.js.map +0 -1
  243. package/dist/domain/script/shared.d.ts +0 -15
  244. package/dist/domain/script/shared.js +0 -35
  245. package/dist/domain/script/shared.js.map +0 -1
  246. package/dist/domain/script/text-util.d.ts +0 -7
  247. package/dist/domain/script/text-util.js +0 -95
  248. package/dist/domain/script/text-util.js.map +0 -1
  249. package/dist/domain/script/timestamp.d.ts +0 -1
  250. package/dist/domain/script/timestamp.js +0 -3
  251. package/dist/domain/script/timestamp.js.map +0 -1
  252. package/dist/domain/script/types.d.ts +0 -1
  253. package/dist/domain/script/types.js +0 -2
  254. package/dist/domain/script/types.js.map +0 -1
  255. package/dist/domain/script/v3/address.d.ts +0 -32
  256. package/dist/domain/script/v3/address.js +0 -136
  257. package/dist/domain/script/v3/address.js.map +0 -1
  258. package/dist/domain/script/v3/lookups.d.ts +0 -33
  259. package/dist/domain/script/v3/lookups.js +0 -316
  260. package/dist/domain/script/v3/lookups.js.map +0 -1
  261. package/dist/domain/script/v3/ordinal.d.ts +0 -8
  262. package/dist/domain/script/v3/ordinal.js +0 -91
  263. package/dist/domain/script/v3/ordinal.js.map +0 -1
  264. package/dist/domain/script/v3/parse.d.ts +0 -3
  265. package/dist/domain/script/v3/parse.js +0 -164
  266. package/dist/domain/script/v3/parse.js.map +0 -1
  267. package/dist/domain/script/v3/patch/apply.d.ts +0 -2
  268. package/dist/domain/script/v3/patch/apply.js +0 -31
  269. package/dist/domain/script/v3/patch/apply.js.map +0 -1
  270. package/dist/domain/script/v3/patch/helpers.d.ts +0 -15
  271. package/dist/domain/script/v3/patch/helpers.js +0 -155
  272. package/dist/domain/script/v3/patch/helpers.js.map +0 -1
  273. package/dist/domain/script/v3/patch/inline-speaker.d.ts +0 -2
  274. package/dist/domain/script/v3/patch/inline-speaker.js +0 -50
  275. package/dist/domain/script/v3/patch/inline-speaker.js.map +0 -1
  276. package/dist/domain/script/v3/patch/ops-action.d.ts +0 -12
  277. package/dist/domain/script/v3/patch/ops-action.js +0 -355
  278. package/dist/domain/script/v3/patch/ops-action.js.map +0 -1
  279. package/dist/domain/script/v3/patch/ops-asset.d.ts +0 -14
  280. package/dist/domain/script/v3/patch/ops-asset.js +0 -347
  281. package/dist/domain/script/v3/patch/ops-asset.js.map +0 -1
  282. package/dist/domain/script/v3/patch/ops-dialogue.d.ts +0 -2
  283. package/dist/domain/script/v3/patch/ops-dialogue.js +0 -21
  284. package/dist/domain/script/v3/patch/ops-dialogue.js.map +0 -1
  285. package/dist/domain/script/v3/patch/ops-extend.d.ts +0 -8
  286. package/dist/domain/script/v3/patch/ops-extend.js +0 -122
  287. package/dist/domain/script/v3/patch/ops-extend.js.map +0 -1
  288. package/dist/domain/script/v3/patch/ops-meta.d.ts +0 -5
  289. package/dist/domain/script/v3/patch/ops-meta.js +0 -82
  290. package/dist/domain/script/v3/patch/ops-meta.js.map +0 -1
  291. package/dist/domain/script/v3/patch/ops-scene.d.ts +0 -6
  292. package/dist/domain/script/v3/patch/ops-scene.js +0 -351
  293. package/dist/domain/script/v3/patch/ops-scene.js.map +0 -1
  294. package/dist/domain/script/v3/patch/ops-state.d.ts +0 -8
  295. package/dist/domain/script/v3/patch/ops-state.js +0 -155
  296. package/dist/domain/script/v3/patch/ops-state.js.map +0 -1
  297. package/dist/domain/script/v3/patch/ops-timestamp.d.ts +0 -6
  298. package/dist/domain/script/v3/patch/ops-timestamp.js +0 -47
  299. package/dist/domain/script/v3/patch/ops-timestamp.js.map +0 -1
  300. package/dist/domain/script/v3/patch/registry.d.ts +0 -2
  301. package/dist/domain/script/v3/patch/registry.js +0 -56
  302. package/dist/domain/script/v3/patch/registry.js.map +0 -1
  303. package/dist/domain/script/v3/patch/types.d.ts +0 -10
  304. package/dist/domain/script/v3/patch/types.js +0 -2
  305. package/dist/domain/script/v3/patch/types.js.map +0 -1
  306. package/dist/domain/script/v3/refs.d.ts +0 -4
  307. package/dist/domain/script/v3/refs.js +0 -64
  308. package/dist/domain/script/v3/refs.js.map +0 -1
  309. package/dist/domain/script/v3/scene-refs.d.ts +0 -3
  310. package/dist/domain/script/v3/scene-refs.js +0 -35
  311. package/dist/domain/script/v3/scene-refs.js.map +0 -1
  312. package/dist/domain/script/v3/schema.d.ts +0 -6
  313. package/dist/domain/script/v3/schema.js +0 -58
  314. package/dist/domain/script/v3/schema.js.map +0 -1
  315. package/dist/domain/script/v3/selector.d.ts +0 -44
  316. package/dist/domain/script/v3/selector.js +0 -178
  317. package/dist/domain/script/v3/selector.js.map +0 -1
  318. package/dist/domain/script/v3/types.d.ts +0 -106
  319. package/dist/domain/script/v3/types.js +0 -2
  320. package/dist/domain/script/v3/types.js.map +0 -1
  321. package/dist/domain/script/v3/validation.d.ts +0 -2
  322. package/dist/domain/script/v3/validation.js +0 -2
  323. package/dist/domain/script/v3/validation.js.map +0 -1
  324. package/dist/domain/script/v4/address.d.ts +0 -61
  325. package/dist/domain/script/v4/address.js +0 -99
  326. package/dist/domain/script/v4/address.js.map +0 -1
  327. package/dist/domain/script/v4/factory.d.ts +0 -2
  328. package/dist/domain/script/v4/factory.js +0 -13
  329. package/dist/domain/script/v4/factory.js.map +0 -1
  330. package/dist/domain/script/v4/from-v3.d.ts +0 -29
  331. package/dist/domain/script/v4/from-v3.js +0 -307
  332. package/dist/domain/script/v4/from-v3.js.map +0 -1
  333. package/dist/domain/script/v4/ids.d.ts +0 -5
  334. package/dist/domain/script/v4/ids.js +0 -41
  335. package/dist/domain/script/v4/ids.js.map +0 -1
  336. package/dist/domain/script/v4/ordinal.d.ts +0 -3
  337. package/dist/domain/script/v4/ordinal.js +0 -66
  338. package/dist/domain/script/v4/ordinal.js.map +0 -1
  339. package/dist/domain/script/v4/parse.d.ts +0 -5
  340. package/dist/domain/script/v4/parse.js +0 -196
  341. package/dist/domain/script/v4/parse.js.map +0 -1
  342. package/dist/domain/script/v4/patch/apply.d.ts +0 -3
  343. package/dist/domain/script/v4/patch/apply.js +0 -24
  344. package/dist/domain/script/v4/patch/apply.js.map +0 -1
  345. package/dist/domain/script/v4/patch/helpers.d.ts +0 -32
  346. package/dist/domain/script/v4/patch/helpers.js +0 -138
  347. package/dist/domain/script/v4/patch/helpers.js.map +0 -1
  348. package/dist/domain/script/v4/patch/ops-action.d.ts +0 -13
  349. package/dist/domain/script/v4/patch/ops-action.js +0 -351
  350. package/dist/domain/script/v4/patch/ops-action.js.map +0 -1
  351. package/dist/domain/script/v4/patch/ops-asset.d.ts +0 -17
  352. package/dist/domain/script/v4/patch/ops-asset.js +0 -556
  353. package/dist/domain/script/v4/patch/ops-asset.js.map +0 -1
  354. package/dist/domain/script/v4/patch/ops-extend.d.ts +0 -11
  355. package/dist/domain/script/v4/patch/ops-extend.js +0 -103
  356. package/dist/domain/script/v4/patch/ops-extend.js.map +0 -1
  357. package/dist/domain/script/v4/patch/ops-meta.d.ts +0 -5
  358. package/dist/domain/script/v4/patch/ops-meta.js +0 -49
  359. package/dist/domain/script/v4/patch/ops-meta.js.map +0 -1
  360. package/dist/domain/script/v4/patch/ops-scene-ref.d.ts +0 -3
  361. package/dist/domain/script/v4/patch/ops-scene-ref.js +0 -74
  362. package/dist/domain/script/v4/patch/ops-scene-ref.js.map +0 -1
  363. package/dist/domain/script/v4/patch/ops-structure.d.ts +0 -6
  364. package/dist/domain/script/v4/patch/ops-structure.js +0 -236
  365. package/dist/domain/script/v4/patch/ops-structure.js.map +0 -1
  366. package/dist/domain/script/v4/patch/ops-timestamp.d.ts +0 -6
  367. package/dist/domain/script/v4/patch/ops-timestamp.js +0 -40
  368. package/dist/domain/script/v4/patch/ops-timestamp.js.map +0 -1
  369. package/dist/domain/script/v4/patch/registry.d.ts +0 -2
  370. package/dist/domain/script/v4/patch/registry.js +0 -53
  371. package/dist/domain/script/v4/patch/registry.js.map +0 -1
  372. package/dist/domain/script/v4/patch/schema.d.ts +0 -7
  373. package/dist/domain/script/v4/patch/schema.js +0 -77
  374. package/dist/domain/script/v4/patch/schema.js.map +0 -1
  375. package/dist/domain/script/v4/patch/types.d.ts +0 -10
  376. package/dist/domain/script/v4/patch/types.js +0 -2
  377. package/dist/domain/script/v4/patch/types.js.map +0 -1
  378. package/dist/domain/script/v4/selector.d.ts +0 -11
  379. package/dist/domain/script/v4/selector.js +0 -124
  380. package/dist/domain/script/v4/selector.js.map +0 -1
  381. package/dist/domain/script/v4/types.d.ts +0 -120
  382. package/dist/domain/script/v4/types.js +0 -2
  383. package/dist/domain/script/v4/types.js.map +0 -1
  384. package/dist/domain/script/v4/validation.d.ts +0 -2
  385. package/dist/domain/script/v4/validation.js +0 -2
  386. package/dist/domain/script/v4/validation.js.map +0 -1
  387. package/dist/failures.d.ts +0 -58
  388. package/dist/failures.js +0 -96
  389. package/dist/failures.js.map +0 -1
  390. package/dist/infra/converters.d.ts +0 -9
  391. package/dist/infra/converters.js +0 -689
  392. package/dist/infra/converters.js.map +0 -1
  393. package/dist/infra/env.d.ts +0 -2
  394. package/dist/infra/env.js +0 -81
  395. package/dist/infra/env.js.map +0 -1
  396. package/dist/infra/episode-title.d.ts +0 -4
  397. package/dist/infra/episode-title.js +0 -129
  398. package/dist/infra/episode-title.js.map +0 -1
  399. package/dist/infra/ingest/review-renderer.d.ts +0 -1
  400. package/dist/infra/ingest/review-renderer.js +0 -440
  401. package/dist/infra/ingest/review-renderer.js.map +0 -1
  402. package/dist/infra/ingest/source-resolver.d.ts +0 -21
  403. package/dist/infra/ingest/source-resolver.js +0 -51
  404. package/dist/infra/ingest/source-resolver.js.map +0 -1
  405. package/dist/infra/ingest/text-reader.d.ts +0 -3
  406. package/dist/infra/ingest/text-reader.js +0 -27
  407. package/dist/infra/ingest/text-reader.js.map +0 -1
  408. package/dist/infra/ingest/video-discovery.d.ts +0 -8
  409. package/dist/infra/ingest/video-discovery.js +0 -69
  410. package/dist/infra/ingest/video-discovery.js.map +0 -1
  411. package/dist/infra/ingest/video-source-snapshot.d.ts +0 -4
  412. package/dist/infra/ingest/video-source-snapshot.js +0 -47
  413. package/dist/infra/ingest/video-source-snapshot.js.map +0 -1
  414. package/dist/infra/ingest/video-state-evidence.d.ts +0 -14
  415. package/dist/infra/ingest/video-state-evidence.js +0 -140
  416. package/dist/infra/ingest/video-state-evidence.js.map +0 -1
  417. package/dist/infra/ingest/video-transcode.d.ts +0 -7
  418. package/dist/infra/ingest/video-transcode.js +0 -98
  419. package/dist/infra/ingest/video-transcode.js.map +0 -1
  420. package/dist/infra/ingest/workspace-lock.d.ts +0 -1
  421. package/dist/infra/ingest/workspace-lock.js +0 -32
  422. package/dist/infra/ingest/workspace-lock.js.map +0 -1
  423. package/dist/infra/ingest/workspace-store.d.ts +0 -18
  424. package/dist/infra/ingest/workspace-store.js +0 -70
  425. package/dist/infra/ingest/workspace-store.js.map +0 -1
  426. package/dist/infra/llm/anthropic-model.d.ts +0 -11
  427. package/dist/infra/llm/anthropic-model.js +0 -130
  428. package/dist/infra/llm/anthropic-model.js.map +0 -1
  429. package/dist/infra/llm/doubao-model.d.ts +0 -60
  430. package/dist/infra/llm/doubao-model.js +0 -249
  431. package/dist/infra/llm/doubao-model.js.map +0 -1
  432. package/dist/infra/llm/failure-mapping.d.ts +0 -6
  433. package/dist/infra/llm/failure-mapping.js +0 -146
  434. package/dist/infra/llm/failure-mapping.js.map +0 -1
  435. package/dist/infra/llm/gemini-upload.d.ts +0 -13
  436. package/dist/infra/llm/gemini-upload.js +0 -138
  437. package/dist/infra/llm/gemini-upload.js.map +0 -1
  438. package/dist/infra/llm/gemini-video-model.d.ts +0 -50
  439. package/dist/infra/llm/gemini-video-model.js +0 -371
  440. package/dist/infra/llm/gemini-video-model.js.map +0 -1
  441. package/dist/infra/llm/openai-compatible-model.d.ts +0 -14
  442. package/dist/infra/llm/openai-compatible-model.js +0 -207
  443. package/dist/infra/llm/openai-compatible-model.js.map +0 -1
  444. package/dist/infra/llm/retry.d.ts +0 -8
  445. package/dist/infra/llm/retry.js +0 -41
  446. package/dist/infra/llm/retry.js.map +0 -1
  447. package/dist/infra/local-script-output-store.d.ts +0 -43
  448. package/dist/infra/local-script-output-store.js +0 -168
  449. package/dist/infra/local-script-output-store.js.map +0 -1
  450. package/dist/infra/script-output-api.d.ts +0 -50
  451. package/dist/infra/script-output-api.js +0 -251
  452. package/dist/infra/script-output-api.js.map +0 -1
  453. package/dist/infra/script-output-store.d.ts +0 -152
  454. package/dist/infra/script-output-store.js +0 -114
  455. package/dist/infra/script-output-store.js.map +0 -1
  456. package/dist/infra/script-working-copy.d.ts +0 -23
  457. package/dist/infra/script-working-copy.js +0 -157
  458. package/dist/infra/script-working-copy.js.map +0 -1
  459. package/dist/infra/storage.d.ts +0 -35
  460. package/dist/infra/storage.js +0 -91
  461. package/dist/infra/storage.js.map +0 -1
  462. package/dist/llm/composition.d.ts +0 -5
  463. package/dist/llm/composition.js +0 -5
  464. package/dist/llm/composition.js.map +0 -1
  465. package/dist/llm/config.d.ts +0 -28
  466. package/dist/llm/config.js +0 -231
  467. package/dist/llm/config.js.map +0 -1
  468. package/dist/llm/registry.d.ts +0 -43
  469. package/dist/llm/registry.js +0 -69
  470. package/dist/llm/registry.js.map +0 -1
  471. package/dist/llm/router.d.ts +0 -46
  472. package/dist/llm/router.js +0 -512
  473. package/dist/llm/router.js.map +0 -1
  474. package/dist/llm/tasks/ingest/arc-summary.d.ts +0 -8
  475. package/dist/llm/tasks/ingest/arc-summary.js +0 -26
  476. package/dist/llm/tasks/ingest/arc-summary.js.map +0 -1
  477. package/dist/llm/tasks/ingest/asset-audit.d.ts +0 -6
  478. package/dist/llm/tasks/ingest/asset-audit.js +0 -158
  479. package/dist/llm/tasks/ingest/asset-audit.js.map +0 -1
  480. package/dist/llm/tasks/ingest/asset-curate.d.ts +0 -13
  481. package/dist/llm/tasks/ingest/asset-curate.js +0 -45
  482. package/dist/llm/tasks/ingest/asset-curate.js.map +0 -1
  483. package/dist/llm/tasks/ingest/asset-extract.d.ts +0 -12
  484. package/dist/llm/tasks/ingest/asset-extract.js +0 -51
  485. package/dist/llm/tasks/ingest/asset-extract.js.map +0 -1
  486. package/dist/llm/tasks/ingest/asset-govern.d.ts +0 -22
  487. package/dist/llm/tasks/ingest/asset-govern.js +0 -143
  488. package/dist/llm/tasks/ingest/asset-govern.js.map +0 -1
  489. package/dist/llm/tasks/ingest/body-start.d.ts +0 -10
  490. package/dist/llm/tasks/ingest/body-start.js +0 -41
  491. package/dist/llm/tasks/ingest/body-start.js.map +0 -1
  492. package/dist/llm/tasks/ingest/episode-assets.d.ts +0 -29
  493. package/dist/llm/tasks/ingest/episode-assets.js +0 -282
  494. package/dist/llm/tasks/ingest/episode-assets.js.map +0 -1
  495. package/dist/llm/tasks/ingest/mention-resolve.d.ts +0 -9
  496. package/dist/llm/tasks/ingest/mention-resolve.js +0 -39
  497. package/dist/llm/tasks/ingest/mention-resolve.js.map +0 -1
  498. package/dist/llm/tasks/ingest/name-fix.d.ts +0 -9
  499. package/dist/llm/tasks/ingest/name-fix.js +0 -56
  500. package/dist/llm/tasks/ingest/name-fix.js.map +0 -1
  501. package/dist/llm/tasks/ingest/state-reconcile.d.ts +0 -8
  502. package/dist/llm/tasks/ingest/state-reconcile.js +0 -44
  503. package/dist/llm/tasks/ingest/state-reconcile.js.map +0 -1
  504. package/dist/llm/tasks/ingest/text-normalize.d.ts +0 -10
  505. package/dist/llm/tasks/ingest/text-normalize.js +0 -122
  506. package/dist/llm/tasks/ingest/text-normalize.js.map +0 -1
  507. package/dist/llm/tasks/ingest/video-serial.d.ts +0 -24
  508. package/dist/llm/tasks/ingest/video-serial.js +0 -416
  509. package/dist/llm/tasks/ingest/video-serial.js.map +0 -1
  510. package/dist/llm/tasks/schemas.d.ts +0 -9
  511. package/dist/llm/tasks/schemas.js +0 -466
  512. package/dist/llm/tasks/schemas.js.map +0 -1
  513. package/dist/llm/types.d.ts +0 -178
  514. package/dist/llm/types.js +0 -44
  515. package/dist/llm/types.js.map +0 -1
  516. package/dist/output.d.ts +0 -3
  517. package/dist/output.js +0 -94
  518. package/dist/output.js.map +0 -1
  519. package/dist/package-root.d.ts +0 -2
  520. package/dist/package-root.js +0 -38
  521. package/dist/package-root.js.map +0 -1
  522. package/dist/review-agent.js.map +0 -7
  523. package/dist/usecases/changelog.d.ts +0 -9
  524. package/dist/usecases/changelog.js +0 -134
  525. package/dist/usecases/changelog.js.map +0 -1
  526. package/dist/usecases/doctor.d.ts +0 -2
  527. package/dist/usecases/doctor.js +0 -231
  528. package/dist/usecases/doctor.js.map +0 -1
  529. package/dist/usecases/ingest/body-start.d.ts +0 -8
  530. package/dist/usecases/ingest/body-start.js +0 -36
  531. package/dist/usecases/ingest/body-start.js.map +0 -1
  532. package/dist/usecases/ingest/command.d.ts +0 -5
  533. package/dist/usecases/ingest/command.js +0 -183
  534. package/dist/usecases/ingest/command.js.map +0 -1
  535. package/dist/usecases/ingest/failure.d.ts +0 -26
  536. package/dist/usecases/ingest/failure.js +0 -153
  537. package/dist/usecases/ingest/failure.js.map +0 -1
  538. package/dist/usecases/ingest/fanout.d.ts +0 -10
  539. package/dist/usecases/ingest/fanout.js +0 -23
  540. package/dist/usecases/ingest/fanout.js.map +0 -1
  541. package/dist/usecases/ingest/final-asset-audit.d.ts +0 -39
  542. package/dist/usecases/ingest/final-asset-audit.js +0 -88
  543. package/dist/usecases/ingest/final-asset-audit.js.map +0 -1
  544. package/dist/usecases/ingest/generate-video-state-evidence.d.ts +0 -23
  545. package/dist/usecases/ingest/generate-video-state-evidence.js +0 -124
  546. package/dist/usecases/ingest/generate-video-state-evidence.js.map +0 -1
  547. package/dist/usecases/ingest/pass4-mention-resolve.d.ts +0 -11
  548. package/dist/usecases/ingest/pass4-mention-resolve.js +0 -52
  549. package/dist/usecases/ingest/pass4-mention-resolve.js.map +0 -1
  550. package/dist/usecases/ingest/pass5-extract.d.ts +0 -7
  551. package/dist/usecases/ingest/pass5-extract.js +0 -51
  552. package/dist/usecases/ingest/pass5-extract.js.map +0 -1
  553. package/dist/usecases/ingest/pass5-govern.d.ts +0 -13
  554. package/dist/usecases/ingest/pass5-govern.js +0 -157
  555. package/dist/usecases/ingest/pass5-govern.js.map +0 -1
  556. package/dist/usecases/ingest/pipeline.d.ts +0 -28
  557. package/dist/usecases/ingest/pipeline.js +0 -335
  558. package/dist/usecases/ingest/pipeline.js.map +0 -1
  559. package/dist/usecases/ingest/publish-command.d.ts +0 -1
  560. package/dist/usecases/ingest/publish-command.js +0 -4
  561. package/dist/usecases/ingest/publish-command.js.map +0 -1
  562. package/dist/usecases/ingest/serial-govern.d.ts +0 -40
  563. package/dist/usecases/ingest/serial-govern.js +0 -488
  564. package/dist/usecases/ingest/serial-govern.js.map +0 -1
  565. package/dist/usecases/ingest/skip-video-episode.d.ts +0 -4
  566. package/dist/usecases/ingest/skip-video-episode.js +0 -120
  567. package/dist/usecases/ingest/skip-video-episode.js.map +0 -1
  568. package/dist/usecases/ingest/status.d.ts +0 -61
  569. package/dist/usecases/ingest/status.js +0 -347
  570. package/dist/usecases/ingest/status.js.map +0 -1
  571. package/dist/usecases/ingest/timings.d.ts +0 -51
  572. package/dist/usecases/ingest/timings.js +0 -68
  573. package/dist/usecases/ingest/timings.js.map +0 -1
  574. package/dist/usecases/ingest/usage-report.d.ts +0 -125
  575. package/dist/usecases/ingest/usage-report.js +0 -248
  576. package/dist/usecases/ingest/usage-report.js.map +0 -1
  577. package/dist/usecases/ingest/video-pipeline.d.ts +0 -81
  578. package/dist/usecases/ingest/video-pipeline.js +0 -548
  579. package/dist/usecases/ingest/video-pipeline.js.map +0 -1
  580. package/dist/usecases/ingest/video-skip-state.d.ts +0 -29
  581. package/dist/usecases/ingest/video-skip-state.js +0 -148
  582. package/dist/usecases/ingest/video-skip-state.js.map +0 -1
  583. package/dist/usecases/ingest/view-command.d.ts +0 -4
  584. package/dist/usecases/ingest/view-command.js +0 -67
  585. package/dist/usecases/ingest/view-command.js.map +0 -1
  586. package/dist/usecases/ingest/view-server.d.ts +0 -29
  587. package/dist/usecases/ingest/view-server.js +0 -364
  588. package/dist/usecases/ingest/view-server.js.map +0 -1
  589. package/dist/usecases/script/action-span.d.ts +0 -10
  590. package/dist/usecases/script/action-span.js +0 -42
  591. package/dist/usecases/script/action-span.js.map +0 -1
  592. package/dist/usecases/script/actions.d.ts +0 -3
  593. package/dist/usecases/script/actions.js +0 -184
  594. package/dist/usecases/script/actions.js.map +0 -1
  595. package/dist/usecases/script/actor.d.ts +0 -3
  596. package/dist/usecases/script/actor.js +0 -26
  597. package/dist/usecases/script/actor.js.map +0 -1
  598. package/dist/usecases/script/actors.d.ts +0 -3
  599. package/dist/usecases/script/actors.js +0 -25
  600. package/dist/usecases/script/actors.js.map +0 -1
  601. package/dist/usecases/script/add-actor.d.ts +0 -3
  602. package/dist/usecases/script/add-actor.js +0 -13
  603. package/dist/usecases/script/add-actor.js.map +0 -1
  604. package/dist/usecases/script/add-episode.d.ts +0 -3
  605. package/dist/usecases/script/add-episode.js +0 -9
  606. package/dist/usecases/script/add-episode.js.map +0 -1
  607. package/dist/usecases/script/add-location.d.ts +0 -3
  608. package/dist/usecases/script/add-location.js +0 -11
  609. package/dist/usecases/script/add-location.js.map +0 -1
  610. package/dist/usecases/script/add-prop.d.ts +0 -3
  611. package/dist/usecases/script/add-prop.js +0 -11
  612. package/dist/usecases/script/add-prop.js.map +0 -1
  613. package/dist/usecases/script/alias.d.ts +0 -3
  614. package/dist/usecases/script/alias.js +0 -39
  615. package/dist/usecases/script/alias.js.map +0 -1
  616. package/dist/usecases/script/assets.d.ts +0 -3
  617. package/dist/usecases/script/assets.js +0 -46
  618. package/dist/usecases/script/assets.js.map +0 -1
  619. package/dist/usecases/script/audit-assets.d.ts +0 -4
  620. package/dist/usecases/script/audit-assets.js +0 -37
  621. package/dist/usecases/script/audit-assets.js.map +0 -1
  622. package/dist/usecases/script/command-constraints.d.ts +0 -38
  623. package/dist/usecases/script/command-constraints.js +0 -143
  624. package/dist/usecases/script/command-constraints.js.map +0 -1
  625. package/dist/usecases/script/compose-creative-draft.d.ts +0 -3
  626. package/dist/usecases/script/compose-creative-draft.js +0 -106
  627. package/dist/usecases/script/compose-creative-draft.js.map +0 -1
  628. package/dist/usecases/script/context.d.ts +0 -3
  629. package/dist/usecases/script/context.js +0 -52
  630. package/dist/usecases/script/context.js.map +0 -1
  631. package/dist/usecases/script/create.d.ts +0 -3
  632. package/dist/usecases/script/create.js +0 -27
  633. package/dist/usecases/script/create.js.map +0 -1
  634. package/dist/usecases/script/delete.d.ts +0 -3
  635. package/dist/usecases/script/delete.js +0 -88
  636. package/dist/usecases/script/delete.js.map +0 -1
  637. package/dist/usecases/script/describe.d.ts +0 -3
  638. package/dist/usecases/script/describe.js +0 -32
  639. package/dist/usecases/script/describe.js.map +0 -1
  640. package/dist/usecases/script/dialogue.d.ts +0 -3
  641. package/dist/usecases/script/dialogue.js +0 -30
  642. package/dist/usecases/script/dialogue.js.map +0 -1
  643. package/dist/usecases/script/dispatch.d.ts +0 -3
  644. package/dist/usecases/script/dispatch.js +0 -10
  645. package/dist/usecases/script/dispatch.js.map +0 -1
  646. package/dist/usecases/script/do.d.ts +0 -3
  647. package/dist/usecases/script/do.js +0 -186
  648. package/dist/usecases/script/do.js.map +0 -1
  649. package/dist/usecases/script/emotion.d.ts +0 -3
  650. package/dist/usecases/script/emotion.js +0 -24
  651. package/dist/usecases/script/emotion.js.map +0 -1
  652. package/dist/usecases/script/episodes.d.ts +0 -3
  653. package/dist/usecases/script/episodes.js +0 -62
  654. package/dist/usecases/script/episodes.js.map +0 -1
  655. package/dist/usecases/script/export-authoring.d.ts +0 -4
  656. package/dist/usecases/script/export-authoring.js +0 -326
  657. package/dist/usecases/script/export-authoring.js.map +0 -1
  658. package/dist/usecases/script/extend.d.ts +0 -3
  659. package/dist/usecases/script/extend.js +0 -94
  660. package/dist/usecases/script/extend.js.map +0 -1
  661. package/dist/usecases/script/ids.d.ts +0 -3
  662. package/dist/usecases/script/ids.js +0 -148
  663. package/dist/usecases/script/ids.js.map +0 -1
  664. package/dist/usecases/script/importance.d.ts +0 -3
  665. package/dist/usecases/script/importance.js +0 -16
  666. package/dist/usecases/script/importance.js.map +0 -1
  667. package/dist/usecases/script/insert.d.ts +0 -3
  668. package/dist/usecases/script/insert.js +0 -127
  669. package/dist/usecases/script/insert.js.map +0 -1
  670. package/dist/usecases/script/issues.d.ts +0 -3
  671. package/dist/usecases/script/issues.js +0 -35
  672. package/dist/usecases/script/issues.js.map +0 -1
  673. package/dist/usecases/script/lib.d.ts +0 -152
  674. package/dist/usecases/script/lib.js +0 -1654
  675. package/dist/usecases/script/lib.js.map +0 -1
  676. package/dist/usecases/script/locations.d.ts +0 -3
  677. package/dist/usecases/script/locations.js +0 -25
  678. package/dist/usecases/script/locations.js.map +0 -1
  679. package/dist/usecases/script/merge.d.ts +0 -3
  680. package/dist/usecases/script/merge.js +0 -43
  681. package/dist/usecases/script/merge.js.map +0 -1
  682. package/dist/usecases/script/migrate.d.ts +0 -3
  683. package/dist/usecases/script/migrate.js +0 -210
  684. package/dist/usecases/script/migrate.js.map +0 -1
  685. package/dist/usecases/script/move.d.ts +0 -3
  686. package/dist/usecases/script/move.js +0 -50
  687. package/dist/usecases/script/move.js.map +0 -1
  688. package/dist/usecases/script/parenthetical.d.ts +0 -3
  689. package/dist/usecases/script/parenthetical.js +0 -52
  690. package/dist/usecases/script/parenthetical.js.map +0 -1
  691. package/dist/usecases/script/props.d.ts +0 -3
  692. package/dist/usecases/script/props.js +0 -25
  693. package/dist/usecases/script/props.js.map +0 -1
  694. package/dist/usecases/script/refs.d.ts +0 -3
  695. package/dist/usecases/script/refs.js +0 -111
  696. package/dist/usecases/script/refs.js.map +0 -1
  697. package/dist/usecases/script/rename.d.ts +0 -3
  698. package/dist/usecases/script/rename.js +0 -35
  699. package/dist/usecases/script/rename.js.map +0 -1
  700. package/dist/usecases/script/replace.d.ts +0 -3
  701. package/dist/usecases/script/replace.js +0 -33
  702. package/dist/usecases/script/replace.js.map +0 -1
  703. package/dist/usecases/script/review.d.ts +0 -3
  704. package/dist/usecases/script/review.js +0 -187
  705. package/dist/usecases/script/review.js.map +0 -1
  706. package/dist/usecases/script/role.d.ts +0 -3
  707. package/dist/usecases/script/role.js +0 -16
  708. package/dist/usecases/script/role.js.map +0 -1
  709. package/dist/usecases/script/scenes.d.ts +0 -3
  710. package/dist/usecases/script/scenes.js +0 -66
  711. package/dist/usecases/script/scenes.js.map +0 -1
  712. package/dist/usecases/script/script-patch.d.ts +0 -3
  713. package/dist/usecases/script/script-patch.js +0 -321
  714. package/dist/usecases/script/script-patch.js.map +0 -1
  715. package/dist/usecases/script/script-validate.d.ts +0 -3
  716. package/dist/usecases/script/script-validate.js +0 -27
  717. package/dist/usecases/script/script-validate.js.map +0 -1
  718. package/dist/usecases/script/session.d.ts +0 -62
  719. package/dist/usecases/script/session.js +0 -567
  720. package/dist/usecases/script/session.js.map +0 -1
  721. package/dist/usecases/script/split.d.ts +0 -3
  722. package/dist/usecases/script/split.js +0 -41
  723. package/dist/usecases/script/split.js.map +0 -1
  724. package/dist/usecases/script/state-add.d.ts +0 -3
  725. package/dist/usecases/script/state-add.js +0 -22
  726. package/dist/usecases/script/state-add.js.map +0 -1
  727. package/dist/usecases/script/state-delete.d.ts +0 -3
  728. package/dist/usecases/script/state-delete.js +0 -22
  729. package/dist/usecases/script/state-delete.js.map +0 -1
  730. package/dist/usecases/script/state-rename.d.ts +0 -3
  731. package/dist/usecases/script/state-rename.js +0 -16
  732. package/dist/usecases/script/state-rename.js.map +0 -1
  733. package/dist/usecases/script/states.d.ts +0 -3
  734. package/dist/usecases/script/states.js +0 -197
  735. package/dist/usecases/script/states.js.map +0 -1
  736. package/dist/usecases/script/summary.d.ts +0 -3
  737. package/dist/usecases/script/summary.js +0 -72
  738. package/dist/usecases/script/summary.js.map +0 -1
  739. package/dist/usecases/script/synopsis-generate.d.ts +0 -115
  740. package/dist/usecases/script/synopsis-generate.js +0 -776
  741. package/dist/usecases/script/synopsis-generate.js.map +0 -1
  742. package/dist/usecases/script/synopsis.d.ts +0 -3
  743. package/dist/usecases/script/synopsis.js +0 -45
  744. package/dist/usecases/script/synopsis.js.map +0 -1
  745. package/dist/usecases/script/timestamp-filter.d.ts +0 -4
  746. package/dist/usecases/script/timestamp-filter.js +0 -55
  747. package/dist/usecases/script/timestamp-filter.js.map +0 -1
  748. package/dist/usecases/script/timestamp.d.ts +0 -3
  749. package/dist/usecases/script/timestamp.js +0 -11
  750. package/dist/usecases/script/timestamp.js.map +0 -1
  751. package/dist/usecases/script/transition.d.ts +0 -3
  752. package/dist/usecases/script/transition.js +0 -23
  753. package/dist/usecases/script/transition.js.map +0 -1
  754. package/dist/usecases/script/type.d.ts +0 -3
  755. package/dist/usecases/script/type.js +0 -23
  756. package/dist/usecases/script/type.js.map +0 -1
  757. package/dist/usecases/script/v3/mutations.d.ts +0 -2
  758. package/dist/usecases/script/v3/mutations.js +0 -5
  759. package/dist/usecases/script/v3/mutations.js.map +0 -1
  760. package/dist/usecases/script/v4/mutations.d.ts +0 -2
  761. package/dist/usecases/script/v4/mutations.js +0 -6
  762. package/dist/usecases/script/v4/mutations.js.map +0 -1
  763. package/dist/usecases/script/v4/queries.d.ts +0 -15
  764. package/dist/usecases/script/v4/queries.js +0 -196
  765. package/dist/usecases/script/v4/queries.js.map +0 -1
  766. package/dist/usecases/script/working-copy.d.ts +0 -5
  767. package/dist/usecases/script/working-copy.js +0 -399
  768. package/dist/usecases/script/working-copy.js.map +0 -1
  769. package/dist/usecases/script/worldview.d.ts +0 -3
  770. package/dist/usecases/script/worldview.js +0 -17
  771. package/dist/usecases/script/worldview.js.map +0 -1
  772. package/dist/usecases/script/write-authoring.d.ts +0 -3
  773. package/dist/usecases/script/write-authoring.js +0 -263
  774. package/dist/usecases/script/write-authoring.js.map +0 -1
  775. package/dist/usecases/update.d.ts +0 -13
  776. package/dist/usecases/update.js +0 -128
  777. package/dist/usecases/update.js.map +0 -1
@@ -1,1654 +0,0 @@
1
- import { CliError, EXIT_INPUT, EXIT_OK, EXIT_USAGE, sha256Text, } from "../../common.js";
2
- import { applyPatchOperationsV4 } from "../../domain/script/v4/patch/apply.js";
3
- import { isV4Id } from "../../domain/script/v4/ids.js";
4
- import { requireStructurallyReadableScriptV4 } from "../../domain/script/v4/parse.js";
5
- import { validateScriptV4 } from "../../domain/script/v4/validation.js";
6
- import { sceneRefs } from "../../domain/script/scene-refs.js";
7
- import { isDangerousRegex, MAX_GREP_PATTERN_LEN, parseInSelector, selectorSingleActionPoint, WHOLE_SCRIPT, } from "../../domain/script/selector.js";
8
- import { parseAnyAddress, } from "../../domain/script/address.js";
9
- import { parseV4Address } from "../../domain/script/v4/address.js";
10
- import { summarizeIssues } from "../../domain/script/text-util.js";
11
- import { sortDeep } from "../../domain/script/text-util.js";
12
- import { asList, idNum, isDict, strOf, } from "../../domain/script/shared.js";
13
- import { loadScriptForEdit, validateSession, saveScriptSession, syncValidationResult, scriptSourceText, mutationValidationWarnings, } from "./session.js";
14
- import { resolveActionTargetsV4 } from "./v4/queries.js";
15
- import { actionTimestampFilter, actionTimestampMatches } from "./timestamp-filter.js";
16
- import { applyVersionedMutations } from "./dispatch.js";
17
- import { assertInsertCommandFlags, assertMoveCommandFlags, assertSceneRefCommandFlags, buildTimestampOperation, } from "./command-constraints.js";
18
- export function tokenizeLine(line) {
19
- const out = [];
20
- let cur = "";
21
- let started = false;
22
- let quoted = false;
23
- let inSingle = false;
24
- let inDouble = false;
25
- const flush = () => { if (started) {
26
- out.push({ text: cur, quoted });
27
- cur = "";
28
- started = false;
29
- quoted = false;
30
- } };
31
- for (let i = 0; i < line.length; i++) {
32
- const ch = line[i];
33
- if (inSingle) {
34
- if (ch === "'")
35
- inSingle = false;
36
- else {
37
- cur += ch;
38
- quoted = true;
39
- }
40
- }
41
- else if (inDouble) {
42
- if (ch === '"')
43
- inDouble = false;
44
- else if (ch === "\\" && i + 1 < line.length) {
45
- cur += line[++i];
46
- quoted = true;
47
- }
48
- else {
49
- cur += ch;
50
- quoted = true;
51
- }
52
- }
53
- else if (ch === "'") {
54
- inSingle = true;
55
- started = true;
56
- }
57
- else if (ch === '"') {
58
- inDouble = true;
59
- started = true;
60
- }
61
- else if (ch === "\\" && i + 1 < line.length) {
62
- cur += line[++i];
63
- started = true;
64
- quoted = true;
65
- }
66
- else if (ch === " " || ch === "\t" || ch === "\r") {
67
- flush();
68
- }
69
- else {
70
- cur += ch;
71
- started = true;
72
- }
73
- }
74
- flush();
75
- return out;
76
- }
77
- // A token is a flag only if it was unquoted AND starts with `--`.
78
- function isDoFlag(t) {
79
- return !t.quoted && t.text.startsWith("--");
80
- }
81
- // Per-verb flag arity. Everything else takes the next token as its value.
82
- export const DO_BOOL_FLAGS = {
83
- replace: new Set(["all", "regex"]),
84
- transition: new Set(["clear"]),
85
- emotion: new Set(["clear"]),
86
- parenthetical: new Set(["remove"]),
87
- timestamp: new Set(["remove"]),
88
- "scene-ref": new Set(["clear", "remove", "append"]),
89
- delete: new Set(["force"]),
90
- extend: new Set(["clear", "json-value"]),
91
- };
92
- export const DO_REPEAT_FLAGS = {
93
- alias: new Set(["add", "remove"]),
94
- "add-actor": new Set(["alias"]),
95
- "scene-ref": new Set(["state"]),
96
- insert: new Set(["state"]),
97
- };
98
- function pushFlag(flags, repeats, name, val) {
99
- if (repeats.has(name)) {
100
- const arr = flags[name] ?? [];
101
- arr.push(val);
102
- flags[name] = arr;
103
- }
104
- else {
105
- flags[name] = val;
106
- }
107
- }
108
- export function parseDoLine(tokens) {
109
- if (tokens.length === 0 || isDoFlag(tokens[0])) {
110
- throw doErr("a line must start with a verb (not a flag)");
111
- }
112
- const verb = tokens[0].text;
113
- const bools = DO_BOOL_FLAGS[verb] ?? new Set();
114
- const repeats = DO_REPEAT_FLAGS[verb] ?? new Set();
115
- const args = [];
116
- const flags = {};
117
- for (let i = 1; i < tokens.length; i++) {
118
- const t = tokens[i];
119
- if (isDoFlag(t)) {
120
- let name = t.text.slice(2);
121
- // Support `--flag=value` (a common CLI habit) alongside `--flag value`.
122
- const eq = name.indexOf("=");
123
- if (eq >= 0) {
124
- const inlineVal = name.slice(eq + 1);
125
- name = name.slice(0, eq);
126
- if (!name)
127
- throw doErr(`empty flag name in "${t.text}"`);
128
- // A boolean flag written as `--all=false` must become false, not the
129
- // truthy string "false" — `--force=false` especially must NOT force.
130
- if (bools.has(name)) {
131
- flags[name] = !["false", "0", "no", "off"].includes(inlineVal.toLowerCase());
132
- }
133
- else {
134
- pushFlag(flags, repeats, name, inlineVal);
135
- }
136
- continue;
137
- }
138
- if (!name)
139
- throw doErr(`empty flag name "${t.text}"`);
140
- if (bools.has(name)) {
141
- flags[name] = true;
142
- continue;
143
- }
144
- // A value-taking flag must be followed by an actual value, not another
145
- // unquoted `--flag` (or end-of-line) — otherwise `--to --from x` silently
146
- // binds '--from' as --to's value. A quoted `"--x"` IS a valid value.
147
- const next = tokens[i + 1];
148
- if (next === undefined || isDoFlag(next)) {
149
- throw doErr(`--${name} needs a value`);
150
- }
151
- pushFlag(flags, repeats, name, tokens[++i].text);
152
- }
153
- else {
154
- args.push(t.text);
155
- }
156
- }
157
- return { verb, args, flags };
158
- }
159
- export function doErr(detail) {
160
- return new CliError(detail, {
161
- exitCode: EXIT_USAGE,
162
- errorCode: "DO_LINE_INVALID",
163
- hint: "Each line is a scriptctl verb minus the leading `scriptctl`; see `scriptctl do --help`.",
164
- data: { expected: ["a valid <verb> ...args... line"], actual: [detail] },
165
- });
166
- }
167
- // ---- shared op-template builders ------------------------------------------
168
- // One source of truth for the verbs whose op has validation/defaults, so the
169
- // typed CLI handler and `do`'s lineToOp can never drift. Each returns the op
170
- // WITHOUT `at` (the caller adds the single address or sweeps it over a selector)
171
- // and throws the SAME CliError the handler used to throw inline.
172
- export function stateChangeTemplate(target, f) {
173
- const toSet = f.to !== undefined;
174
- const clearSet = Boolean(f.clear);
175
- if (toSet && clearSet) {
176
- throw new CliError("state-change: --to and --clear are mutually exclusive.", {
177
- exitCode: EXIT_USAGE,
178
- errorCode: "STATE_CHANGE_FLAG_CONFLICT",
179
- hint: "Pick one and retry.",
180
- data: { expected: ["exactly one of --to <state> / --clear"], actual: ["--to", "--clear"] },
181
- });
182
- }
183
- if (!toSet && !clearSet) {
184
- throw new CliError("state-change: must specify --to <state> or --clear.", {
185
- exitCode: EXIT_USAGE,
186
- errorCode: "STATE_CHANGE_FLAG_MISSING",
187
- hint: "Pick exactly one flag.",
188
- data: { expected: ["one of --to <state> / --clear"], actual: ["<missing>"] },
189
- });
190
- }
191
- // v3 has no per-action state_changes; state lives on scene.ref.* only.
192
- throw new CliError("state-change was removed in v3; set a scene ref's state instead.", {
193
- exitCode: EXIT_USAGE,
194
- errorCode: "STATE_CHANGE_REMOVED",
195
- hint: "Use `scene-ref <ep/scn> <kind:id> --state <state_id>` (op scene.ref.set).",
196
- data: { expected: ["scene-ref state edit"], actual: ["state-change"] },
197
- });
198
- }
199
- export function transitionTemplate(target, f) {
200
- const setBoth = f.process !== undefined || f.contrast !== undefined;
201
- const clearSet = Boolean(f.clear);
202
- if (setBoth && clearSet) {
203
- throw new CliError("transition: --clear is mutually exclusive with --process/--contrast.", {
204
- exitCode: EXIT_USAGE,
205
- errorCode: "TRANSITION_FLAG_CONFLICT",
206
- hint: "Pick one mode and retry.",
207
- data: { expected: ["either --clear, or --process + --contrast"], actual: ["--clear", "--process/--contrast"] },
208
- });
209
- }
210
- if (!setBoth && !clearSet) {
211
- throw new CliError("transition: must specify --process/--contrast or --clear.", {
212
- exitCode: EXIT_USAGE,
213
- errorCode: "TRANSITION_FLAG_MISSING",
214
- hint: "Pick exactly one mode.",
215
- data: { expected: ["--process + --contrast, or --clear"], actual: ["<missing>"] },
216
- });
217
- }
218
- return clearSet
219
- ? { op: "action.transition.clear", target }
220
- : { op: "action.transition.set", target, process: f.process, contrast: f.contrast };
221
- }
222
- export function emotionTemplate(f) {
223
- const emotionSet = f.emotion !== undefined;
224
- const clearSet = Boolean(f.clear);
225
- if (emotionSet && clearSet) {
226
- throw new CliError("emotion: value and --clear are mutually exclusive.", {
227
- exitCode: EXIT_USAGE,
228
- errorCode: "EMOTION_FLAG_CONFLICT",
229
- hint: "Pick one mode and retry.",
230
- data: { expected: ["either <emotion>, or --clear"], actual: ["<emotion>", "--clear"] },
231
- });
232
- }
233
- if (!emotionSet && !clearSet) {
234
- throw new CliError("emotion: must specify <emotion> or --clear.", {
235
- exitCode: EXIT_USAGE,
236
- errorCode: "EMOTION_VALUE_MISSING",
237
- hint: "Pass an emotion label, or use --clear.",
238
- data: { expected: ["<emotion>, or --clear"], actual: ["<missing>"] },
239
- });
240
- }
241
- return clearSet
242
- ? { op: "action.emotion.clear" }
243
- : { op: "action.emotion.set", emotion: f.emotion };
244
- }
245
- export function contextTemplate(target, f) {
246
- const stateSet = f.state !== undefined;
247
- const clearSet = Boolean(f.clear);
248
- const removeSet = Boolean(f.remove);
249
- const n = (stateSet ? 1 : 0) + (clearSet ? 1 : 0) + (removeSet ? 1 : 0);
250
- if (n === 0) {
251
- throw new CliError("context: must specify --state X, --clear, or --remove.", {
252
- exitCode: EXIT_USAGE,
253
- errorCode: "CONTEXT_FLAG_MISSING",
254
- hint: "Pick exactly one flag.",
255
- data: { expected: ["one of --state <state_id> / --clear / --remove"], actual: ["<missing>"] },
256
- });
257
- }
258
- if (n > 1) {
259
- const passed = [];
260
- if (stateSet)
261
- passed.push("--state");
262
- if (clearSet)
263
- passed.push("--clear");
264
- if (removeSet)
265
- passed.push("--remove");
266
- throw new CliError("context: --state / --clear / --remove are mutually exclusive.", {
267
- exitCode: EXIT_USAGE,
268
- errorCode: "CONTEXT_FLAG_CONFLICT",
269
- hint: "Pick one and retry.",
270
- data: { expected: ["exactly one of --state / --clear / --remove"], actual: passed },
271
- });
272
- }
273
- const append = Boolean(f.append);
274
- const occurrenceRaw = strOf(f.occurrence).trim();
275
- const occurrence = occurrenceRaw ? Number(occurrenceRaw) : undefined;
276
- if (occurrence !== undefined && (!Number.isInteger(occurrence) || occurrence < 1)) {
277
- throw new CliError("scene-ref: --occurrence must be a positive integer.", {
278
- exitCode: EXIT_USAGE,
279
- errorCode: "SCENE_REF_OCCURRENCE_INVALID",
280
- hint: "Use 1 for the first matching scene ref, 2 for the second, and so on.",
281
- data: { expected: ["--occurrence <positive integer> (1-based)"], actual: [occurrenceRaw] },
282
- });
283
- }
284
- if (append && (!stateSet || occurrence !== undefined)) {
285
- throw new CliError("scene-ref: --append requires --state and cannot be combined with --occurrence.", {
286
- exitCode: EXIT_USAGE,
287
- errorCode: "SCENE_REF_APPEND_FLAG_CONFLICT",
288
- hint: "Append a new actor ref with --state <state_id> --append, or target an existing ref with --occurrence <n>.",
289
- data: { expected: ["--state <state_id> --append"], actual: [append ? "--append" : "", occurrence !== undefined ? "--occurrence" : "", clearSet ? "--clear" : "", removeSet ? "--remove" : ""].filter(Boolean) },
290
- });
291
- }
292
- if (removeSet)
293
- return { op: "scene.ref.remove", target, occurrence };
294
- if (clearSet)
295
- return { op: "scene.ref.clear", target, occurrence };
296
- return { op: "scene.ref.set", target, state: f.state === "none" ? "" : f.state, append, occurrence };
297
- }
298
- // v3 dialogue speaker: a single inline speaker — an actor, OR a non-actor kind
299
- // (system|broadcast|offscreen|group) with an optional label.
300
- export function dialogueTemplate(f) {
301
- const actorId = strOf(f.actor).trim();
302
- const speakerKind = strOf(f.kind).trim();
303
- const label = strOf(f.label).trim();
304
- if (actorId && speakerKind) {
305
- throw new CliError("dialogue: --actor and --kind are mutually exclusive.", {
306
- exitCode: EXIT_USAGE,
307
- errorCode: "SPEAKER_AMBIGUOUS",
308
- hint: "Keep --actor for a character, or --kind for a non-actor source.",
309
- data: { expected: ["exactly one of --actor <actor_id> or --kind <non-actor kind>"], actual: ["--actor", "--kind"] },
310
- });
311
- }
312
- if (actorId && label) {
313
- throw new CliError("dialogue: --label is only valid with --kind.", {
314
- exitCode: EXIT_USAGE,
315
- errorCode: "SPEAKER_LABEL_WITHOUT_KIND",
316
- hint: "Remove --label for an actor line, or use --kind for a labeled non-actor source.",
317
- data: { expected: ["omit --label with --actor, or pair --label with --kind"], actual: ["--actor", "--label"] },
318
- });
319
- }
320
- if (actorId)
321
- return { op: "dialogue.speaker.set", actor_id: actorId };
322
- if (speakerKind)
323
- return { op: "dialogue.speaker.set", kind: speakerKind, label: label || undefined };
324
- throw new CliError("dialogue: pass --actor <id> or --kind <system|broadcast|offscreen|group>.", {
325
- exitCode: EXIT_USAGE,
326
- errorCode: "DIALOGUE_SPEAKER_MISSING",
327
- hint: "Set --actor for an actor line, or --kind for a non-actor line.",
328
- data: { expected: ["--actor <actor_id> or --kind <non-actor kind>"], actual: ["<missing>"] },
329
- });
330
- }
331
- // Translate one parsed verb line into a patch op dict (the SAME ops `patch`
332
- // consumes). `do` = the human/agent-friendly notation for those ops: no JSON,
333
- // no field-name guessing — the verbs you already type. Multipolar verbs
334
- // (delete/move/insert/merge/describe) pick their op by the address kind.
335
- function repeatedDoFlag(raw) {
336
- if (raw === undefined)
337
- return [];
338
- return Array.isArray(raw) ? raw.map(strOf) : [strOf(raw)];
339
- }
340
- function doInsertFlags(flags) {
341
- return {
342
- type: flags["type"],
343
- content: flags["content"],
344
- emotion: flags["emotion"],
345
- parenthetical: flags["parenthetical"],
346
- actionId: flags["action-id"],
347
- at: flags["at"],
348
- before: flags["before"],
349
- after: flags["after"],
350
- actor: flags["actor"],
351
- speaker: flags["speaker"],
352
- speakerState: flags["speaker-state"],
353
- kind: flags["kind"],
354
- label: flags["label"],
355
- location: flags["location"],
356
- time: flags["time"],
357
- space: flags["space"],
358
- sceneId: flags["scene-id"],
359
- states: repeatedDoFlag(flags["state"]),
360
- };
361
- }
362
- export function lineToOp(verb, args, flags, scriptVersion = 3) {
363
- const a0 = strOf(args[0]);
364
- const a1 = strOf(args[1]);
365
- const parseAddress = (raw) => scriptVersion === 4 ? parseV4Address(raw) : parseAnyAddress(raw);
366
- switch (verb) {
367
- case "replace":
368
- return flags["regex"]
369
- ? { op: "action.content.regex-replace", at: a0, pattern: regexPattern(strOf(flags["from"])), to: flags["to"] ?? "", all: Boolean(flags["all"]) }
370
- : { op: "action.content.replace", at: a0, from: strOf(flags["from"]), to: flags["to"] ?? "", all: Boolean(flags["all"]) };
371
- case "type":
372
- return { op: "action.type.set", at: a0, type: a1 };
373
- case "actor":
374
- return { op: "action.actor.set", at: a0, actor_id: a1 };
375
- case "transition":
376
- return { ...transitionTemplate(a1, { process: flags["process"], contrast: flags["contrast"], clear: Boolean(flags["clear"]) }), at: a0 };
377
- case "emotion":
378
- if (scriptVersion === 4)
379
- throw doErr("emotion belongs to Script v3; use parenthetical for Script v4");
380
- return { ...emotionTemplate({ emotion: args[1], clear: Boolean(flags["clear"]) }), at: a0 };
381
- case "parenthetical":
382
- if (scriptVersion === 3)
383
- throw doErr("parenthetical belongs to Script v4; use emotion for Script v3");
384
- if (Boolean(flags["remove"]) === (flags["set"] !== undefined)) {
385
- throw doErr("parenthetical needs exactly one of --set <text> or --remove");
386
- }
387
- return Boolean(flags["remove"])
388
- ? { op: "action.parenthetical.remove", at: a0 }
389
- : { op: "action.parenthetical.set", at: a0, parenthetical: strOf(flags["set"]) };
390
- case "timestamp":
391
- return buildTimestampOperation(a0, flags["set"], Boolean(flags["remove"]));
392
- case "scene-ref": {
393
- const sceneRefFlags = {
394
- states: repeatedDoFlag(flags["state"]),
395
- clear: Boolean(flags["clear"]),
396
- remove: Boolean(flags["remove"]),
397
- append: Boolean(flags["append"]),
398
- occurrence: flags["occurrence"],
399
- };
400
- assertSceneRefCommandFlags(scriptVersion, sceneRefFlags);
401
- if (scriptVersion === 4) {
402
- return sceneRefFlags.remove
403
- ? { op: "scene.ref.remove", at: a0, target: a1 }
404
- : { op: "scene.ref.set", at: a0, target: a1, state_ids: sceneRefFlags.states };
405
- }
406
- return {
407
- ...contextTemplate(a1, {
408
- state: sceneRefFlags.states[0],
409
- clear: sceneRefFlags.clear,
410
- remove: sceneRefFlags.remove,
411
- append: sceneRefFlags.append,
412
- occurrence: sceneRefFlags.occurrence,
413
- }),
414
- at: a0,
415
- };
416
- }
417
- case "dialogue":
418
- if (scriptVersion === 3 && flags["state"] !== undefined) {
419
- throw doErr("dialogue --state belongs to Script v4");
420
- }
421
- return {
422
- ...dialogueTemplate({ actor: flags["actor"], kind: flags["kind"], label: flags["label"] }),
423
- ...(scriptVersion === 4 && flags["state"] !== undefined ? { state_id: flags["state"] } : {}),
424
- at: a0,
425
- };
426
- case "rename":
427
- return { op: "asset.rename", target: a0, name: a1 };
428
- case "role":
429
- return { op: "asset.role.set", target: a0, role_type: a1 };
430
- case "worldview":
431
- return { op: "meta.worldview.set", worldview: a0 };
432
- case "synopsis": {
433
- if (args.length === 0)
434
- throw doErr("synopsis needs <text> or <episode_id> <text>");
435
- if (args.length > 2)
436
- throw doErr("synopsis text with spaces must be quoted");
437
- if (args.length === 1) {
438
- if (/^ep_/.test(a0) || /^ep[1-9A-HJ-NP-Za-km-z]{6}$/.test(a0)) {
439
- throw doErr(`synopsis for ${a0} needs text`);
440
- }
441
- return { op: "meta.synopsis.set", synopsis: a0 };
442
- }
443
- const addr = parseAddress(a0);
444
- if (addr.kind !== "episode")
445
- throw doErr(`synopsis target must be an episode id or omitted for global (${a0})`);
446
- return { op: "episode.synopsis.set", episode_id: "id" in addr ? addr.id : addr.episodeId, synopsis: a1 };
447
- }
448
- case "alias": {
449
- const add = flags["add"] ?? [];
450
- const remove = flags["remove"] ?? [];
451
- if (add.length)
452
- return { op: "asset.alias.add", target: a0, alias: add };
453
- if (remove.length)
454
- return { op: "asset.alias.remove", target: a0, alias: remove };
455
- throw doErr("alias needs --add <alias> or --remove <alias>");
456
- }
457
- case "describe": {
458
- const addr = parseAddress(a0);
459
- if (addr.kind === "state")
460
- return { op: "state.describe", target: a0, description: a1 };
461
- if (addr.kind === "asset")
462
- return { op: "asset.describe", target: a0, description: a1 };
463
- throw doErr(`describe cannot operate on a ${addr.kind} address (${a0}); use an asset or asset/state target`);
464
- }
465
- case "extend": {
466
- if (a0 !== "global")
467
- parseAddress(a0);
468
- if (flags["clear"]) {
469
- if (args.length >= 3)
470
- throw doErr("extend --clear takes no value (drop --clear to set, or drop the value to delete)");
471
- return { op: "extend.clear", at: a0, key: a1 || undefined };
472
- }
473
- if (args.length < 3)
474
- throw doErr("extend needs <addr> <key> <value> (or --clear)");
475
- let value = args[2];
476
- if (flags["json-value"]) {
477
- try {
478
- value = JSON.parse(strOf(args[2]));
479
- }
480
- catch {
481
- throw doErr("extend --json-value: value is not valid JSON");
482
- }
483
- }
484
- return { op: "extend.set", at: a0, key: a1, value };
485
- }
486
- case "state-add":
487
- return { op: "state.add", target: a0, name: a1, description: flags["description"], state_id: flags["state-id"] };
488
- case "state-rename":
489
- return { op: "state.rename", target: a0, name: a1 };
490
- case "state-delete":
491
- return { op: "state.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
492
- case "add-actor":
493
- return { op: "actor.add", actor_id: flags["id"], name: a0, role_type: flags["role"], description: flags["description"], aliases: flags["alias"] ?? undefined };
494
- case "add-location":
495
- return { op: "location.add", location_id: flags["id"], name: a0, description: flags["description"] };
496
- case "add-prop":
497
- return { op: "prop.add", prop_id: flags["id"], name: a0, description: flags["description"] };
498
- case "add-episode":
499
- return { op: "episode.add", title: flags["title"], episode_id: flags["id"] };
500
- case "importance":
501
- return { op: "importance.set", target: a0, importance: a1 };
502
- case "split":
503
- return scriptVersion === 4
504
- ? { op: "scene.split", at: a0, at_action: flags["at"], new_scene_id: flags["new-scene-id"] }
505
- : { op: "scene.split", at: a0, at_index: Number(flags["at"]), new_scene_id: flags["new-scene-id"] };
506
- case "delete": {
507
- const addr = parseAddress(a0);
508
- if (addr.kind === "action")
509
- return { op: "action.delete", at: a0 };
510
- if (addr.kind === "scene")
511
- return { op: "scene.delete", at: a0, force: Boolean(flags["force"]) };
512
- if (addr.kind === "state")
513
- return { op: "state.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
514
- if (addr.kind === "asset")
515
- return { op: "asset.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
516
- throw doErr(`delete cannot operate on a ${addr.kind} address (${a0})`);
517
- }
518
- case "move": {
519
- assertMoveCommandFlags(scriptVersion, {
520
- at: flags["at"],
521
- before: flags["before"],
522
- after: flags["after"],
523
- });
524
- const addr = parseAddress(a0);
525
- if (addr.kind === "scene") {
526
- return scriptVersion === 4
527
- ? { op: "scene.move", at: a0, to: a1, before: flags["before"], after: flags["after"] }
528
- : { op: "scene.move", at: a0, to: a1, at_index: flags["at"] };
529
- }
530
- if (addr.kind === "action") {
531
- return scriptVersion === 4
532
- ? { op: "action.move", at: a0, to: a1, before: flags["before"], after: flags["after"] }
533
- : { op: "action.move", at: a0, to: a1 };
534
- }
535
- throw doErr(`move cannot operate on a ${addr.kind} address (${a0}); move an action or a scene`);
536
- }
537
- case "merge": {
538
- const addr = parseAddress(a0);
539
- if (addr.kind === "scene")
540
- return { op: "scene.merge", from: a0, into: strOf(flags["into"]) };
541
- if (addr.kind === "asset")
542
- return { op: "asset.merge", from: a0, into: strOf(flags["into"]) };
543
- throw doErr(`merge cannot operate on a ${addr.kind} address (${a0}); merge two assets or two scenes`);
544
- }
545
- case "insert": {
546
- const addr = parseAddress(a0);
547
- const insertFlags = doInsertFlags(flags);
548
- if (addr.kind === "episode") {
549
- assertInsertCommandFlags(scriptVersion, "scene", insertFlags);
550
- return {
551
- op: "scene.insert",
552
- at: a0,
553
- location: flags["location"],
554
- time: flags["time"],
555
- space: flags["space"],
556
- ...(scriptVersion === 4
557
- ? { location_state_ids: insertFlags.states, before: flags["before"], after: flags["after"] }
558
- : { at_index: flags["at"], before: flags["before"], after: flags["after"] }),
559
- scene_id: flags["scene-id"],
560
- };
561
- }
562
- if (addr.kind === "scene") {
563
- assertInsertCommandFlags(scriptVersion, "action", insertFlags);
564
- return {
565
- op: "action.insert",
566
- at: a0,
567
- type: flags["type"],
568
- content: flags["content"],
569
- before: flags["before"],
570
- after: flags["after"],
571
- actor_id: flags["actor"],
572
- kind: flags["kind"],
573
- label: flags["label"],
574
- ...(scriptVersion === 4
575
- ? {
576
- action_id: flags["action-id"],
577
- state_id: flags["speaker-state"],
578
- parenthetical: flags["parenthetical"],
579
- }
580
- : {
581
- at_index: flags["at"],
582
- speaker_id: flags["speaker"],
583
- emotion: flags["emotion"],
584
- }),
585
- };
586
- }
587
- throw doErr(`insert needs ep_NNN (scene insert) or ep_NNN/scn_NNN (action insert), got a ${addr.kind} address (${a0})`);
588
- }
589
- default:
590
- throw doErr(`unknown verb '${verb}' (structural/edit/create verbs are supported; queries are not)`);
591
- }
592
- }
593
- export function actionAddress(epId, sceneId, idx) {
594
- return `${epId}/${sceneId}#${idx}`;
595
- }
596
- // The action's authored timeline position, carried in extend.timestamp as a
597
- // "M:SS" / "MM:SS" string (episode-local by convention). Empty string when the
598
- // action carries no timestamp. This is the anchor event-level alignment reads:
599
- // an event's span is the delta between its first and last action timestamp.
600
- export function actionTimestamp(action) {
601
- const extend = isDict(action["extend"]) ? action["extend"] : {};
602
- return strOf(extend["timestamp"]).trim();
603
- }
604
- // First and last non-empty action timestamps within a scene, in document order.
605
- // Timestamps are monotonic within an episode, so first = t_start, last = t_end.
606
- export function sceneTimeSpan(scene) {
607
- let t_start = "";
608
- let t_end = "";
609
- for (const action of asList(scene["actions"])) {
610
- const ts = actionTimestamp(action);
611
- if (!ts)
612
- continue;
613
- if (!t_start)
614
- t_start = ts;
615
- t_end = ts;
616
- }
617
- return { t_start, t_end };
618
- }
619
- export function actionDisplayFields(epId, sceneId, idx, action) {
620
- const actorId = actionActorId(action);
621
- const s = isDict(action["speaker"]) ? action["speaker"] : null;
622
- // For a non-actor speaker ({kind,label}) surface it under `speaker`; an actor
623
- // line surfaces under `actor` (its id). Narrative lines have neither.
624
- const speaker = s && !actorId ? (strOf(s["label"]).trim() || strOf(s["kind"]).trim()) : "";
625
- return {
626
- addr: actionAddress(epId, sceneId, idx),
627
- timestamp: actionTimestamp(action),
628
- type: strOf(action["type"]).trim() || "action",
629
- speaker,
630
- actor: actorId,
631
- emotion: strOf(action["emotion"]).trim(),
632
- content: strOf(action["content"]),
633
- };
634
- }
635
- export function formatInspectAction(epId, sceneId, idx, action) {
636
- const fields = actionDisplayFields(epId, sceneId, idx, action);
637
- const addr = strOf(fields["addr"]);
638
- const type = strOf(fields["type"]);
639
- const delivery = strOf(fields["delivery"]);
640
- const tag = delivery ? `${type} ${delivery}` : type;
641
- // Prefer the speaker_id (concrete) over actor_id (asset), and skip both when
642
- // the action is narrative (no speaker). Format kept on a single line so agents
643
- // can grep the output.
644
- const speakerId = strOf(fields["speaker"]);
645
- const actorId = strOf(fields["actor"]);
646
- const who = speakerId || actorId;
647
- const emotion = strOf(fields["emotion"]);
648
- const timestamp = strOf(fields["timestamp"]);
649
- const content = strOf(fields["content"]);
650
- const meta = [tag, timestamp ? `t=${timestamp}` : "", emotion ? `emotion=${emotion}` : "", who].filter((v) => v).join(" ");
651
- const prefix = `${addr} [${meta}]`;
652
- return content ? `${prefix} ${content}` : prefix;
653
- }
654
- // ---------------------------------------------------------------------------
655
- // command_script_patch
656
- // ---------------------------------------------------------------------------
657
- export const SKIPPABLE_EDIT_CODES = new Set([
658
- "REGEX_NO_MATCH",
659
- "FROM_TEXT_NOT_FOUND",
660
- "OVERLAP_DIALOGUE_UNSUPPORTED",
661
- ]);
662
- export function applyPatchOperationsForSession(session, source, operations) {
663
- return applyVersionedMutations(session.version, session.script, source, operations);
664
- }
665
- function v4Counts(script) {
666
- return {
667
- episodes: script.episodes.length,
668
- scenes: script.episodes.reduce((sum, episode) => sum + episode.scenes.length, 0),
669
- actions: script.episodes.reduce((sum, episode) => sum + episode.scenes.reduce((sceneSum, scene) => sceneSum + scene.actions.length, 0), 0),
670
- actors: script.actors.length,
671
- locations: script.locations.length,
672
- props: script.props.length,
673
- states: [...script.actors, ...script.locations, ...script.props]
674
- .reduce((sum, asset) => sum + asset.states.length, 0),
675
- };
676
- }
677
- function v4CanonicalIds(script) {
678
- return [
679
- ...script.actors.flatMap((asset) => [
680
- asset.actor_id,
681
- ...asset.states.map((state) => `${asset.actor_id}/${state.state_id}`),
682
- ]),
683
- ...script.locations.flatMap((asset) => [
684
- asset.location_id,
685
- ...asset.states.map((state) => `${asset.location_id}/${state.state_id}`),
686
- ]),
687
- ...script.props.flatMap((asset) => [
688
- asset.prop_id,
689
- ...asset.states.map((state) => `${asset.prop_id}/${state.state_id}`),
690
- ]),
691
- ...script.episodes.flatMap((episode) => [
692
- episode.episode_id,
693
- ...episode.scenes.flatMap((scene) => [
694
- scene.scene_id,
695
- ...scene.actions.map((action) => action.action_id),
696
- ]),
697
- ]),
698
- ];
699
- }
700
- function orderedIntersection(left, right) {
701
- return left.filter((value) => right.has(value));
702
- }
703
- function v4OperationTargets(operation) {
704
- const values = [];
705
- const isIdentity = (value) => {
706
- if (value === "global")
707
- return true;
708
- if (isV4Id("episode", value)
709
- || isV4Id("scene", value)
710
- || isV4Id("action", value)
711
- || isV4Id("actor", value)
712
- || isV4Id("location", value)
713
- || isV4Id("prop", value))
714
- return true;
715
- const slash = value.indexOf("/");
716
- if (slash < 0 || slash !== value.lastIndexOf("/"))
717
- return false;
718
- const owner = value.slice(0, slash);
719
- const state = value.slice(slash + 1);
720
- return (isV4Id("actor", owner)
721
- || isV4Id("location", owner)
722
- || isV4Id("prop", owner)) && (state === "default" || isV4Id("state", state));
723
- };
724
- const add = (value) => {
725
- if (typeof value !== "string" || value.trim() === "")
726
- return;
727
- const normalized = value.trim();
728
- if (isIdentity(normalized))
729
- values.push(normalized);
730
- };
731
- const first = (...fields) => {
732
- for (const field of fields) {
733
- const value = operation[field];
734
- if (typeof value === "string" && value.trim() !== "")
735
- return value;
736
- }
737
- return undefined;
738
- };
739
- const addState = (ownerValue, stateValue) => {
740
- const owner = strOf(ownerValue).trim();
741
- const state = strOf(stateValue).trim();
742
- if (owner && state)
743
- add(`${owner}/${state}`);
744
- };
745
- const addStates = (ownerValue, stateValues) => {
746
- if (!Array.isArray(stateValues))
747
- return;
748
- stateValues.forEach((state) => addState(ownerValue, state));
749
- };
750
- const addPlacement = () => {
751
- add(operation["before"]);
752
- add(operation["after"]);
753
- };
754
- const kind = strOf(operation["op"]);
755
- switch (kind) {
756
- case "action.parenthetical.set":
757
- case "action.parenthetical.remove":
758
- case "action.timestamp.set":
759
- case "action.timestamp.remove":
760
- case "action.content.replace":
761
- case "action.content.regex-replace":
762
- case "action.type.set":
763
- case "action.delete":
764
- case "action.transition.clear":
765
- add(operation["at"]);
766
- break;
767
- case "action.actor.set":
768
- case "dialogue.speaker.set":
769
- add(operation["at"]);
770
- add(operation["actor_id"]);
771
- addState(operation["actor_id"], operation["state_id"]);
772
- break;
773
- case "action.insert":
774
- add(operation["at"]);
775
- add(first("action_id", "id"));
776
- add(operation["actor_id"]);
777
- addState(operation["actor_id"], operation["state_id"]);
778
- addPlacement();
779
- break;
780
- case "action.move":
781
- add(operation["at"]);
782
- add(operation["to"]);
783
- addPlacement();
784
- break;
785
- case "action.transition.set":
786
- add(operation["at"]);
787
- add(operation["target"]);
788
- break;
789
- case "scene.ref.set":
790
- case "scene.ref.remove":
791
- add(operation["at"]);
792
- add(operation["target"]);
793
- addStates(operation["target"], operation["state_ids"]);
794
- break;
795
- case "actor.add":
796
- add(first("actor_id", "id"));
797
- break;
798
- case "location.add":
799
- add(first("location_id", "id"));
800
- break;
801
- case "prop.add":
802
- add(first("prop_id", "id"));
803
- break;
804
- case "state.add": {
805
- const owner = operation["target"];
806
- add(owner);
807
- addState(owner, first("state_id", "id"));
808
- break;
809
- }
810
- case "state.rename":
811
- case "state.describe":
812
- add(operation["target"]);
813
- break;
814
- case "state.delete": {
815
- const target = strOf(operation["target"]).trim();
816
- add(target);
817
- const slash = target.indexOf("/");
818
- if (slash > 0)
819
- addState(target.slice(0, slash), operation["replacement"]);
820
- break;
821
- }
822
- case "asset.rename":
823
- case "asset.describe":
824
- case "asset.role.set":
825
- case "asset.alias.set":
826
- case "asset.alias.add":
827
- case "asset.alias.remove":
828
- case "importance.set":
829
- add(operation["target"]);
830
- break;
831
- case "asset.merge":
832
- add(first("from", "source"));
833
- add(first("into", "target"));
834
- break;
835
- case "asset.delete":
836
- add(operation["target"]);
837
- if (operation["strategy"] === "replace")
838
- add(operation["replacement"]);
839
- break;
840
- case "episode.add":
841
- add(first("episode_id", "id"));
842
- break;
843
- case "episode.synopsis.set":
844
- add(first("episode_id", "target", "at"));
845
- break;
846
- case "meta.worldview.set":
847
- case "meta.synopsis.set":
848
- add("global");
849
- break;
850
- case "scene.insert": {
851
- const location = first("location", "location_id");
852
- add(first("at", "episode_id"));
853
- add(first("scene_id", "id"));
854
- add(location);
855
- addStates(location, operation["location_state_ids"]);
856
- addPlacement();
857
- break;
858
- }
859
- case "scene.move":
860
- add(operation["at"]);
861
- add(operation["to"]);
862
- addPlacement();
863
- break;
864
- case "scene.delete":
865
- add(operation["at"]);
866
- break;
867
- case "scene.split":
868
- add(operation["at"]);
869
- add(first("at_action", "action_id"));
870
- add(first("new_scene_id", "scene_id"));
871
- break;
872
- case "scene.merge":
873
- add(operation["from"]);
874
- add(operation["into"]);
875
- break;
876
- case "extend.set":
877
- case "extend.clear":
878
- add(operation["at"]);
879
- break;
880
- default:
881
- throw new Error(`V4 plan target mapping is missing for operation ${kind}`);
882
- }
883
- return [...new Set(values)];
884
- }
885
- export function buildV4MutationPlan(session, operations, options = {}) {
886
- if (session.version !== 4) {
887
- throw new CliError("A v4 mutation plan requires Script v4.", {
888
- exitCode: EXIT_USAGE,
889
- errorCode: "V4_PLAN_VERSION_INVALID",
890
- data: { actual: [`Script v${session.version}`] },
891
- });
892
- }
893
- const original = requireStructurallyReadableScriptV4(session.script);
894
- const proposed = structuredClone(original);
895
- const originalIds = v4CanonicalIds(original);
896
- const applied = [];
897
- const steps = [];
898
- for (const [index, operation] of operations.entries()) {
899
- const beforeIds = v4CanonicalIds(proposed);
900
- const beforeSet = new Set(beforeIds);
901
- const before = v4Counts(proposed);
902
- let status = "applied";
903
- try {
904
- applied.push(...applyPatchOperationsV4(proposed, [operation]));
905
- }
906
- catch (error) {
907
- if (error instanceof CliError
908
- && error.errorCode
909
- && options.skipCodes?.has(error.errorCode)) {
910
- status = "skipped";
911
- }
912
- else {
913
- throw error;
914
- }
915
- }
916
- const afterIds = v4CanonicalIds(proposed);
917
- const afterSet = new Set(afterIds);
918
- steps.push({
919
- index,
920
- operation,
921
- targets: v4OperationTargets(operation),
922
- status,
923
- before,
924
- after: v4Counts(proposed),
925
- created_ids: afterIds.filter((id) => !beforeSet.has(id)),
926
- removed_ids: beforeIds.filter((id) => !afterSet.has(id)),
927
- retained_ids: orderedIntersection(beforeIds, afterSet),
928
- });
929
- }
930
- const proposedIds = v4CanonicalIds(proposed);
931
- const originalSet = new Set(originalIds);
932
- const proposedSet = new Set(proposedIds);
933
- const targets = [...new Set(steps.flatMap((step) => step.targets))];
934
- const touched = new Set([
935
- ...targets,
936
- ...steps.flatMap((step) => step.created_ids),
937
- ...steps.flatMap((step) => step.removed_ids),
938
- ]);
939
- const plan = {
940
- version: 1,
941
- script_version: 4,
942
- baseline: session.baselineHash,
943
- operations,
944
- targets,
945
- steps,
946
- before: v4Counts(original),
947
- after: v4Counts(proposed),
948
- created_ids: proposedIds.filter((id) => !originalSet.has(id)),
949
- removed_ids: originalIds.filter((id) => !proposedSet.has(id)),
950
- retained_ids: orderedIntersection(originalIds, proposedSet),
951
- untouched_ids: orderedIntersection(originalIds, proposedSet)
952
- .filter((id) => !touched.has(id)),
953
- validation: validateScriptV4(proposed),
954
- };
955
- return {
956
- plan,
957
- digest: `sha256:${sha256Text(JSON.stringify(sortDeep(plan)))}`,
958
- applied,
959
- };
960
- }
961
- const V4_PLANNED_ID_FIELDS = {
962
- "actor.add": "actor_id",
963
- "location.add": "location_id",
964
- "prop.add": "prop_id",
965
- "state.add": "state_id",
966
- "episode.add": "episode_id",
967
- "scene.insert": "scene_id",
968
- "scene.split": "new_scene_id",
969
- "action.insert": "action_id",
970
- };
971
- export function assertV4PlanHasExplicitNewIds(operations) {
972
- for (const operation of operations) {
973
- const kind = strOf(operation["op"]);
974
- const field = V4_PLANNED_ID_FIELDS[kind];
975
- if (!field || strOf(operation[field]).trim())
976
- continue;
977
- const idKind = field === "new_scene_id" ? "scene" : field.replace(/_id$/, "");
978
- throw new CliError("Planned creation operations require an explicit candidate ID.", {
979
- exitCode: EXIT_USAGE,
980
- errorCode: "V4_PLAN_ID_REQUIRED",
981
- hint: `Generate a candidate with \`scriptctl ids --kind ${idKind} --count 1\`, then include it in the operation.`,
982
- data: { expected: [`${kind}.${field}`], actual: [`${kind}.${field}=<missing>`] },
983
- });
984
- }
985
- }
986
- // ---------------------------------------------------------------------------
987
- // Single-op helpers
988
- // ---------------------------------------------------------------------------
989
- export async function applySingleScriptOpToSession(session, opts, op) {
990
- const plan = strOf(opts["plan"]).trim();
991
- if (plan) {
992
- throw new CliError("Single-point writes do not use plan digests.", {
993
- exitCode: EXIT_USAGE,
994
- errorCode: "MULTI_PLAN_USAGE_INVALID",
995
- hint: "Remove --plan from this single-point edit.",
996
- data: { actual: [plan] },
997
- });
998
- }
999
- return applyScriptOpsToSession(session, opts, [op]);
1000
- }
1001
- export async function applyScriptOpsToSession(session, opts, operations) {
1002
- const workspace = strOf(opts["workspace_path"] || "workspace");
1003
- const applied = applyPatchOperationsForSession(session, scriptSourceText(workspace), operations);
1004
- const opName = applied.length === 1 ? applied[0] : "script.ops";
1005
- const [newRevision, idempotent] = await saveScriptSession(session, opts, opName);
1006
- const validation = validateSession(session);
1007
- await syncValidationResult(session, validation, newRevision);
1008
- const passed = Boolean(validation["passed"]);
1009
- const warnings = mutationValidationWarnings(session, validation);
1010
- // One outcome line: what changed + revision (remote) + validation verdict.
1011
- const rev = session.remote ? `; rev ${newRevision}` : "";
1012
- const resultLine = `${applied.join(", ")} applied${rev}; validation ${passed ? "passed" : "needs repair"}`;
1013
- const issues = summarizeIssues(asList(validation["issues"]));
1014
- const warningLines = summarizeIssues(warnings);
1015
- const report = {
1016
- text: [resultLine, ...warningLines].join("\n"),
1017
- data: {
1018
- op: opName,
1019
- changed: applied.length > 0,
1020
- revision: session.remote ? newRevision : undefined,
1021
- idempotent: session.remote ? idempotent : undefined,
1022
- validation,
1023
- issues,
1024
- warnings,
1025
- script_path: session.artifactLabel,
1026
- },
1027
- };
1028
- return [report, EXIT_OK];
1029
- }
1030
- export async function applySingleScriptOp(opts, op) {
1031
- const session = await loadScriptForEdit(opts);
1032
- return applySingleScriptOpToSession(session, opts, op);
1033
- }
1034
- export function summarizeScriptOp(_script, op) {
1035
- const kind = strOf(op["op"]);
1036
- if (kind === "actor.add")
1037
- return `Added actor ${op["name"] || op["actor_name"]}${op["role_type"] ? ` (${op["role_type"]})` : ""}`;
1038
- if (kind === "location.add")
1039
- return `Added location ${op["name"] || op["location_name"]}`;
1040
- if (kind === "prop.add")
1041
- return `Added prop ${op["name"] || op["prop_name"]}`;
1042
- if (kind === "episode.add")
1043
- return `Added episode${op["episode_id"] ? ` ${op["episode_id"]}` : " (generated ID)"}${op["title"] ? `: ${op["title"]}` : ""}`;
1044
- if (kind === "meta.synopsis.set")
1045
- return "Updated script synopsis";
1046
- if (kind === "episode.synopsis.set")
1047
- return `Updated episode synopsis ${op["episode_id"] ?? op["target"] ?? op["at"]}`;
1048
- if (kind === "state.add")
1049
- return `Added state ${op["state_id"]}: ${op["name"] || op["state_name"]} to ${op["target"]}`;
1050
- if (kind === "importance.set")
1051
- return `Set ${op["target"]} importance to ${op["importance"]}`;
1052
- if (kind === "scene.ref.set")
1053
- return `Set reference ${op["target"]} on ${op["at"]}${op["state"] ? ` (state ${op["state"]})` : ""}`;
1054
- if (kind === "extend.set")
1055
- return `Set extend.${op["key"]} on ${op["at"]}`;
1056
- if (kind === "extend.clear")
1057
- return op["key"] ? `Removed extend.${op["key"]} from ${op["at"]}` : `Cleared extend on ${op["at"]}`;
1058
- if (kind === "action.timestamp.set")
1059
- return `Set timestamp on ${op["at"]}`;
1060
- if (kind === "action.timestamp.remove")
1061
- return `Removed timestamp from ${op["at"]}`;
1062
- if (kind.startsWith("state."))
1063
- return `Applied ${kind}: ${op["target"]}`;
1064
- if (kind.startsWith("dialogue."))
1065
- return `Applied ${kind}: ${op["at"]}`;
1066
- return `Applied ${kind}`;
1067
- }
1068
- // Accept `/re/flags` as-is; wrap a bare pattern as `/pattern/` so
1069
- // `replace --regex --from '^\s*\[[^\]]*\]'` works without the user typing slashes.
1070
- export function regexPattern(raw) {
1071
- const s = raw.trim();
1072
- if (s.length >= 2 && s.startsWith("/") && s.lastIndexOf("/") > 0)
1073
- return s;
1074
- return `/${s}/`;
1075
- }
1076
- // The selector-driven write runner. Resolves `opts` to its matched actions
1077
- // (range/region + predicates) and applies one op template to each, as a single
1078
- // in-memory pass committed once. Guardrail: with no --apply it's a DRY-RUN that
1079
- // reports the blast radius and writes nothing; --apply commits. Per-action
1080
- // "no match here / overlap dialogue" errors are skipped (a sweep); anything else
1081
- // aborts the whole edit before any write. Shared by every selector-capable verb.
1082
- export async function applySelectorEditsToSession(session, opts, template, verbLabel) {
1083
- const workspace = strOf(opts["workspace_path"] || "workspace");
1084
- const apply = Boolean(opts["apply"]);
1085
- const opName = strOf(template["op"]);
1086
- const script = session.script;
1087
- const refs = session.version === 3
1088
- ? resolveActionTargets(script, opts).map((target) => `${target.epId}/${target.sceneId}#${target.idx}`)
1089
- : resolveActionTargetsV4(requireStructurallyReadableScriptV4(script), opts, { allowOrdinals: false })
1090
- .map((target) => target.action.action_id);
1091
- const operations = refs.map((ref) => ({ ...template, at: ref }));
1092
- const multiV4 = session.version === 4 && refs.length > 1;
1093
- const planned = multiV4
1094
- ? buildV4MutationPlan(session, operations, { skipCodes: SKIPPABLE_EDIT_CODES })
1095
- : null;
1096
- const planDigest = planned?.digest ?? null;
1097
- const suppliedPlan = strOf(opts["plan"]).trim();
1098
- if (suppliedPlan && (!multiV4 || !apply)) {
1099
- throw new CliError("A plan digest is only accepted for a v4 multi-target apply.", {
1100
- exitCode: EXIT_USAGE,
1101
- errorCode: "MULTI_PLAN_USAGE_INVALID",
1102
- hint: "Remove --plan, or apply the same v4 multi-target selection that produced the digest.",
1103
- data: { actual: [suppliedPlan] },
1104
- });
1105
- }
1106
- if (multiV4 && apply && !suppliedPlan) {
1107
- throw new CliError("A v4 multi-target write requires its dry-run plan digest.", {
1108
- exitCode: EXIT_USAGE,
1109
- errorCode: "MULTI_PLAN_REQUIRED",
1110
- hint: "Run the same command without --apply, review the full plan, then retry with `--apply --plan <digest>`.",
1111
- data: { expected: [planDigest ?? ""], actual: ["<missing>"] },
1112
- });
1113
- }
1114
- if (multiV4 && apply && suppliedPlan !== planDigest) {
1115
- throw new CliError("The supplied digest does not match the current targets and operations.", {
1116
- exitCode: EXIT_INPUT,
1117
- errorCode: "MULTI_PLAN_MISMATCH",
1118
- hint: "Review the newly computed dry-run plan, then apply its exact digest.",
1119
- data: { expected: [planDigest ?? ""], actual: [suppliedPlan] },
1120
- });
1121
- }
1122
- const source = scriptSourceText(workspace);
1123
- let applied = planned?.plan.steps.filter((step) => step.status === "applied").length ?? 0;
1124
- let skipped = planned?.plan.steps.filter((step) => step.status === "skipped").length ?? 0;
1125
- if (!planned) {
1126
- for (const ref of refs) {
1127
- try {
1128
- applyPatchOperationsForSession(session, source, [{ ...template, at: ref }]);
1129
- applied += 1;
1130
- }
1131
- catch (err) {
1132
- if (err instanceof CliError && err.errorCode && SKIPPABLE_EDIT_CODES.has(err.errorCode)) {
1133
- skipped += 1;
1134
- continue;
1135
- }
1136
- throw err;
1137
- }
1138
- }
1139
- }
1140
- else if (apply) {
1141
- for (const step of planned.plan.steps) {
1142
- if (step.status === "applied") {
1143
- applyPatchOperationsForSession(session, source, [step.operation]);
1144
- }
1145
- }
1146
- }
1147
- const displayedRefs = multiV4 ? refs : refs.slice(0, 12);
1148
- const blast = [
1149
- `verb: ${verbLabel} (${opName})`,
1150
- `matched: ${refs.length} action(s)`,
1151
- `${apply ? "applied" : "would-apply"}: ${applied}`,
1152
- `${apply ? "skipped" : "would-skip"}: ${skipped}`,
1153
- ...(displayedRefs.length ? [`targets: ${displayedRefs.join(", ")}${refs.length > displayedRefs.length ? ` … (+${refs.length - displayedRefs.length} more)` : ""}`] : []),
1154
- ...(planDigest ? [`plan_digest: ${planDigest}`] : []),
1155
- ];
1156
- if (!apply) {
1157
- const legacyValidation = planned ? null : validateSession(session);
1158
- const passed = planned
1159
- ? planned.plan.validation.ok
1160
- : Boolean(legacyValidation?.["passed"]);
1161
- const plannedIssueLines = planned
1162
- ? [...planned.plan.validation.errors, ...planned.plan.validation.warnings]
1163
- .map((issue) => `${issue.path}: ${issue.code} - ${issue.message}`)
1164
- : null;
1165
- const legacyIssueLines = legacyValidation === null
1166
- ? []
1167
- : summarizeIssues(asList(legacyValidation["issues"]));
1168
- const issues = plannedIssueLines ?? legacyIssueLines;
1169
- const hint = refs.length === 0
1170
- ? "Widen the selection with --in, --grep, or predicates."
1171
- : planDigest
1172
- ? `Run again with --apply --plan ${planDigest} to commit this exact plan${passed ? "." : "; validation issues will remain available as follow-up diagnostics."}`
1173
- : `Run again with --apply to commit${passed ? "." : "; validation issues will remain available as follow-up diagnostics."}`;
1174
- const lines = [...blast, `validation: ${passed ? "would pass" : "would need repair"}; no write`, ...issues, hint];
1175
- const report = {
1176
- text: lines.join("\n"),
1177
- data: {
1178
- op: `${opName}.dry-run`,
1179
- changed: false,
1180
- matched: refs.length,
1181
- applied,
1182
- skipped,
1183
- issues,
1184
- script_path: session.artifactLabel,
1185
- ...(planDigest ? {
1186
- baseline: session.baselineHash,
1187
- plan_digest: planDigest,
1188
- operations,
1189
- targets: refs,
1190
- plan: planned?.plan,
1191
- } : {}),
1192
- },
1193
- };
1194
- return [report, EXIT_OK];
1195
- }
1196
- if (refs.length === 0) {
1197
- return [{
1198
- text: [...blast, "Widen the selection with --in, --grep, or predicates."].join("\n"),
1199
- data: {
1200
- op: opName,
1201
- changed: false,
1202
- matched: 0,
1203
- script_path: session.artifactLabel,
1204
- },
1205
- }, EXIT_OK];
1206
- }
1207
- const [newRevision, idempotent] = await saveScriptSession(session, opts, opName);
1208
- const validation = validateSession(session);
1209
- await syncValidationResult(session, validation, newRevision);
1210
- const passed = Boolean(validation["passed"]);
1211
- const warnings = mutationValidationWarnings(session, validation);
1212
- const rev = session.remote ? `; rev ${newRevision}` : "";
1213
- const issues = summarizeIssues(asList(validation["issues"]));
1214
- const warningLines = summarizeIssues(warnings);
1215
- const report = {
1216
- text: [...blast, `validation: ${passed ? "passed" : "needs repair"}${rev}`, ...warningLines].join("\n"),
1217
- data: {
1218
- op: opName,
1219
- changed: applied > 0,
1220
- matched: refs.length,
1221
- applied,
1222
- skipped,
1223
- revision: session.remote ? newRevision : undefined,
1224
- idempotent: session.remote ? idempotent : undefined,
1225
- validation,
1226
- issues,
1227
- warnings,
1228
- script_path: session.artifactLabel,
1229
- ...(planDigest ? {
1230
- baseline: session.baselineHash,
1231
- plan_digest: planDigest,
1232
- operations,
1233
- targets: refs,
1234
- plan: planned?.plan,
1235
- } : {}),
1236
- },
1237
- };
1238
- return [report, EXIT_OK];
1239
- }
1240
- export async function applySelectorEdits(opts, template, verbLabel) {
1241
- const session = await loadScriptForEdit(opts);
1242
- return applySelectorEditsToSession(session, opts, template, verbLabel);
1243
- }
1244
- export { sortDeep };
1245
- // ===========================================================================
1246
- // 0.6.0 plural-noun query commands (replace `commandScriptInspect --target X`)
1247
- // ===========================================================================
1248
- //
1249
- // Each command is a thin read-only wrapper around the underlying script
1250
- // document. They all return a CommandOutput shaped like inspect's existing output but
1251
- // without the `--target` flag — the verb itself encodes the target. Filters
1252
- // use `--in <addr>` (compose with the address parsers) plus per-target
1253
- // predicates (--name / --kind / --has / --grep / --context / --type / --actor
1254
- // / --speaker / --severity / --code / --has-{actor,location,prop}).
1255
- // Resolve the speaker_id → source actor mapping once per call. Used by
1256
- // commandActions's --actor filter when the action speaks via a speaker.
1257
- // v3: a dialogue line carries a single inline speaker — an actor ({actor_id})
1258
- // or a non-actor source ({kind, label?}). These read that shape.
1259
- // The actor id behind an action's speaker, or "" for a non-actor / narrative line.
1260
- export function actionActorId(action) {
1261
- const s = action["speaker"];
1262
- if (isDict(s) && strOf(s["actor_id"]).trim())
1263
- return strOf(s["actor_id"]).trim();
1264
- return "";
1265
- }
1266
- // A human label for the speaker: the actor's name (resolved via `names`), or a
1267
- // non-actor kind's label / kind, or "" when the line has no speaker.
1268
- export function actionSpeakerLabel(action, actorNames) {
1269
- const s = action["speaker"];
1270
- if (!isDict(s))
1271
- return "";
1272
- const actorId = strOf(s["actor_id"]).trim();
1273
- if (actorId)
1274
- return actorNames?.get(actorId) || actorId;
1275
- const kind = strOf(s["kind"]).trim();
1276
- if (kind)
1277
- return strOf(s["label"]).trim() || kind;
1278
- return "";
1279
- }
1280
- export function actorIdsInAction(action) {
1281
- const ids = new Set();
1282
- const id = actionActorId(action);
1283
- if (id)
1284
- ids.add(id);
1285
- return ids;
1286
- }
1287
- // Build a grep matcher. /pattern/flags → RegExp, otherwise literal substring.
1288
- // Pre-flight checks block the common ReDoS shapes before they hit V8's regex
1289
- // engine: nested quantifiers like (a+)+, (a*)+, (a*|b*)+ etc. compile fine
1290
- // but hang the process on adversarial input. Since --grep accepts caller-
1291
- // controlled patterns and runs over every action in scope, the safe move is
1292
- // to reject patterns with quantifier-on-group-with-internal-quantifier and
1293
- // cap the pattern length.
1294
- export function buildGrepMatcher(raw) {
1295
- if (!raw)
1296
- return null;
1297
- const m = /^\/(.+)\/([gimsuy]*)$/.exec(raw);
1298
- if (m) {
1299
- const pattern = m[1];
1300
- if (isDangerousRegex(pattern)) {
1301
- throw new CliError("regex pattern has nested quantifiers (ReDoS risk) or exceeds the length limit.", {
1302
- exitCode: EXIT_USAGE,
1303
- errorCode: "REGEX_UNSAFE",
1304
- hint: "Rewrite the regex to avoid nested quantifiers, or use a literal substring (drop the /…/ wrapper).",
1305
- data: { expected: [`pattern length <= ${MAX_GREP_PATTERN_LEN}; no quantifier-on-group-with-internal-quantifier (e.g. (a+)+)`], actual: [`length=${pattern.length}, sample=${pattern.slice(0, 80)}`] },
1306
- });
1307
- }
1308
- try {
1309
- const re = new RegExp(pattern, m[2]);
1310
- return (hay) => {
1311
- re.lastIndex = 0;
1312
- return re.test(hay);
1313
- };
1314
- }
1315
- catch {
1316
- // Malformed regex — treat as literal.
1317
- }
1318
- }
1319
- return (hay) => hay.includes(raw);
1320
- }
1321
- export function buildReport(op, lines) {
1322
- const outputLines = lines.length > 0 ? lines : ["No matches."];
1323
- return {
1324
- text: outputLines.join("\n"),
1325
- data: {
1326
- op,
1327
- changed: false,
1328
- },
1329
- };
1330
- }
1331
- export function buildTableReport(op, lines, rowColumns, rows) {
1332
- const report = buildReport(op, lines);
1333
- report.data["row_columns"] = rowColumns;
1334
- report.data["rows"] = rows;
1335
- return report;
1336
- }
1337
- // ----- summary --------------------------------------------------------------
1338
- export function synopsisPreview(text, limit) {
1339
- const oneLine = text.replace(/\s+/g, " ").trim();
1340
- return oneLine.length > limit ? `${oneLine.slice(0, limit)}…` : oneLine;
1341
- }
1342
- export function episodeInSelector(selector, epId, scenes) {
1343
- if (selector.isEmpty)
1344
- return true;
1345
- if (selector.matchesScene(epId, "scn_000000"))
1346
- return true;
1347
- for (const scene of scenes) {
1348
- if (selector.matchesScene(epId, strOf(scene["scene_id"])))
1349
- return true;
1350
- }
1351
- return false;
1352
- }
1353
- export function nameMaps(script) {
1354
- const out = { actor: new Map(), location: new Map(), prop: new Map() };
1355
- for (const a of asList(script["actors"]))
1356
- out.actor.set(strOf(a["actor_id"]), strOf(a["actor_name"]));
1357
- for (const l of asList(script["locations"]))
1358
- out.location.set(strOf(l["location_id"]), strOf(l["location_name"]));
1359
- for (const p of asList(script["props"]))
1360
- out.prop.set(strOf(p["prop_id"]), strOf(p["prop_name"]));
1361
- return out;
1362
- }
1363
- export function formatScene(epId, scene, names) {
1364
- const ctx = sceneRefs(scene);
1365
- const env = isDict(scene["environment"]) ? scene["environment"] : {};
1366
- const space = strOf(env["space"]) || "-";
1367
- const time = strOf(env["time"]) || "-";
1368
- const locations = asList(ctx["locations"]).map((r) => {
1369
- const id = strOf(r["location_id"]);
1370
- return `${id}(${names.location.get(id) || "?"})`;
1371
- });
1372
- const actors = asList(ctx["actors"]).map((r) => {
1373
- const id = strOf(r["actor_id"]);
1374
- return `${id}(${names.actor.get(id) || "?"})`;
1375
- });
1376
- const props = asList(ctx["props"]).map((r) => {
1377
- const id = strOf(r["prop_id"]);
1378
- return `${id}(${names.prop.get(id) || "?"})`;
1379
- });
1380
- const actionCount = asList(scene["actions"]).length;
1381
- const { t_start, t_end } = sceneTimeSpan(scene);
1382
- const timePart = t_start || t_end ? ` t=${t_start || "?"}..${t_end || "?"}` : "";
1383
- return `${epId}/${scene["scene_id"]} [${space} ${time}] location=${locations.join(",") || "-"} actors=${actors.join(",") || "-"} props=${props.join(",") || "-"} actions=${actionCount}${timePart}`;
1384
- }
1385
- export const HAS_FILTERS = new Set(["transition", "speaker"]);
1386
- // Resolve a selection (--in range/region selector + --type/--actor/--speaker/
1387
- // --grep/--has predicates, AND-combined) to the matching actions, in document
1388
- // order. The single matcher behind both `actions` queries and selector-driven
1389
- // writes. Does NOT enforce "at least one filter" — that policy is caller-owned
1390
- // (queries refuse a bare dump; writes gate on --all). Validates the --has value.
1391
- export function resolveActionTargets(script, opts) {
1392
- const selector = parseInSelector(strOf(opts["in"]));
1393
- const timestampRange = actionTimestampFilter(opts);
1394
- const typeFilter = strOf(opts["type"]).trim();
1395
- const actorFilter = strOf(opts["actor"]).trim();
1396
- const hasFilter = strOf(opts["has"]).trim();
1397
- // Whitelist --has: silently accepting unknown values means a typo like
1398
- // "state_changes" (underscore) passed the filter-missing guard but bypassed
1399
- // every concrete predicate, returning the whole script.
1400
- if (hasFilter && !HAS_FILTERS.has(hasFilter)) {
1401
- throw new CliError("--has value invalid.", {
1402
- exitCode: EXIT_USAGE,
1403
- errorCode: "HAS_FILTER_INVALID",
1404
- hint: "Use a supported --has value.",
1405
- data: { expected: [`--has: one of ${[...HAS_FILTERS].join(", ")}`], actual: [hasFilter] },
1406
- });
1407
- }
1408
- const grepMatcher = buildGrepMatcher(strOf(opts["grep"]));
1409
- const out = [];
1410
- for (const ep of asList(script["episodes"])) {
1411
- const epId = strOf(ep["episode_id"]);
1412
- for (const scene of asList(ep["scenes"])) {
1413
- const sceneId = strOf(scene["scene_id"]);
1414
- if (!selector.matchesScene(epId, sceneId))
1415
- continue;
1416
- const actions = asList(scene["actions"]);
1417
- for (let i = 0; i < actions.length; i++) {
1418
- if (!selector.matchesAction(epId, sceneId, i))
1419
- continue;
1420
- const a = actions[i];
1421
- if (timestampRange
1422
- && !actionTimestampMatches(isDict(a["extend"]) ? a["extend"]["timestamp"] : undefined, timestampRange, actionAddress(epId, sceneId, i)))
1423
- continue;
1424
- if (typeFilter && strOf(a["type"]).trim() !== typeFilter)
1425
- continue;
1426
- if (actorFilter && !actorIdsInAction(a).has(actorFilter))
1427
- continue;
1428
- if (hasFilter === "transition" && !isDict(a["transition_prompt"]))
1429
- continue;
1430
- if (hasFilter === "speaker" && !isDict(a["speaker"]))
1431
- continue;
1432
- if (grepMatcher && !grepMatcher(strOf(a["content"])))
1433
- continue;
1434
- out.push({ epId, sceneId, idx: i, action: a });
1435
- }
1436
- }
1437
- }
1438
- return out;
1439
- }
1440
- // Whether a selection in `opts` has any filter at all (scope or predicate).
1441
- export function selectionHasAnyFilter(opts) {
1442
- return Boolean(strOf(opts["in"]).trim() ||
1443
- strOf(opts["grep"]) || strOf(opts["type"]).trim() || strOf(opts["actor"]).trim() ||
1444
- strOf(opts["has"]).trim());
1445
- }
1446
- // Collapse a set of episode ids into sorted, comma-joined ranges:
1447
- // {ep_001, ep_002, ep_003, ep_007} → "ep_001..ep_003,ep_007". Keeps the state
1448
- // arc / appearance lines readable even when an item spans dozens of episodes.
1449
- export function compactEpisodeRanges(ids) {
1450
- const nums = [...new Set([...ids])]
1451
- .map((id) => ({ id, n: idNum(id, "ep") }))
1452
- .filter((x) => Number.isFinite(x.n))
1453
- .sort((a, b) => a.n - b.n);
1454
- if (nums.length === 0)
1455
- return "";
1456
- const parts = [];
1457
- let start = nums[0];
1458
- let prev = nums[0];
1459
- const flush = () => parts.push(start.id === prev.id ? start.id : `${start.id}..${prev.id}`);
1460
- for (let i = 1; i < nums.length; i++) {
1461
- const cur = nums[i];
1462
- if (cur.n === prev.n + 1) {
1463
- prev = cur;
1464
- continue;
1465
- }
1466
- flush();
1467
- start = cur;
1468
- prev = cur;
1469
- }
1470
- flush();
1471
- return parts.join(",");
1472
- }
1473
- // One pass over scene context: for each asset id of `kind`, the set of episodes
1474
- // and count of scenes it is referenced in. "Appearance" = presence in a scene's
1475
- // context (the canonical who/what-is-in-this-scene list direct-init populates).
1476
- export function assetAppearanceCounts(script, kind) {
1477
- const idKey = kind === "actor" ? "actor_id" : kind === "location" ? "location_id" : "prop_id";
1478
- const pluralKey = kind === "actor" ? "actors" : kind === "location" ? "locations" : "props";
1479
- const out = new Map();
1480
- for (const ep of asList(script["episodes"])) {
1481
- const epId = strOf(ep["episode_id"]);
1482
- for (const scene of asList(ep["scenes"])) {
1483
- const ctx = sceneRefs(scene);
1484
- const seen = new Set();
1485
- for (const ref of asList(ctx[pluralKey])) {
1486
- const id = strOf(ref[idKey]);
1487
- if (!id || seen.has(id))
1488
- continue;
1489
- seen.add(id);
1490
- const entry = out.get(id) ?? { episodes: new Set(), scenes: 0 };
1491
- entry.episodes.add(epId);
1492
- entry.scenes += 1;
1493
- out.set(id, entry);
1494
- }
1495
- }
1496
- }
1497
- return out;
1498
- }
1499
- export function listAssetsByKind(script, kind, opts) {
1500
- const lines = [];
1501
- const rows = [];
1502
- const [key, idKey, nameKey] = (() => {
1503
- switch (kind) {
1504
- case "actor": return ["actors", "actor_id", "actor_name"];
1505
- case "location": return ["locations", "location_id", "location_name"];
1506
- case "prop": return ["props", "prop_id", "prop_name"];
1507
- }
1508
- })();
1509
- // Build the set of asset ids referenced inside the --in scope. A range or
1510
- // multi-region selector takes the union of context refs over every matched
1511
- // scene; a bare single action point (e.g. ep_001/scn_003#2) keeps the legacy
1512
- // "narrow to that one action's actor" behavior.
1513
- // WHOLE_SCRIPT ('--in *') means "all assets" — it must NOT narrow to the set
1514
- // of assets referenced in scene context (that would drop registered-but-not-
1515
- // yet-placed assets). Only a real address-region selector narrows.
1516
- let scopeIds = null;
1517
- if (!opts.selector.isEmpty && opts.selector !== WHOLE_SCRIPT) {
1518
- scopeIds = new Set();
1519
- const single = selectorSingleActionPoint(opts.selector);
1520
- const pluralKey = kind === "actor" ? "actors" : kind === "location" ? "locations" : "props";
1521
- for (const ep of asList(script["episodes"])) {
1522
- const epId = strOf(ep["episode_id"]);
1523
- for (const scene of asList(ep["scenes"])) {
1524
- const sceneId = strOf(scene["scene_id"]);
1525
- if (!opts.selector.matchesScene(epId, sceneId))
1526
- continue;
1527
- if (single) {
1528
- // Single action point: matchesScene already isolates the target
1529
- // scene. Legacy narrowing is implemented for actor only.
1530
- if (kind === "actor") {
1531
- const a = asList(scene["actions"])[single.idx];
1532
- const aid = a ? actionActorId(a) : "";
1533
- if (aid)
1534
- scopeIds.add(aid);
1535
- }
1536
- continue;
1537
- }
1538
- const ctx = sceneRefs(scene);
1539
- for (const ref of asList(ctx[pluralKey])) {
1540
- scopeIds.add(strOf(ref[idKey]));
1541
- }
1542
- }
1543
- }
1544
- }
1545
- // Appearance counts (scenes / episodes) computed in one pass, only when asked
1546
- // — keeps the default listing lean.
1547
- const appearances = opts.counts ? assetAppearanceCounts(script, kind) : null;
1548
- for (const asset of asList(script[key])) {
1549
- const id = strOf(asset[idKey]);
1550
- const name = strOf(asset[nameKey]);
1551
- if (opts.id && opts.id !== id)
1552
- continue;
1553
- if (opts.name && !name.includes(opts.name))
1554
- continue;
1555
- if (scopeIds && !scopeIds.has(id))
1556
- continue;
1557
- const aliases = asList(asset["aliases"]).map((s) => strOf(s));
1558
- const role = strOf(asset["role_type"]);
1559
- const importance = strOf(asset["importance"]);
1560
- const descPresent = strOf(asset["description"]).trim() ? "yes" : "missing";
1561
- const states = asList(asset["states"]).length;
1562
- const extra = [];
1563
- if (aliases.length > 0)
1564
- extra.push(`aliases=(${aliases.join(",")})`);
1565
- if (importance)
1566
- extra.push(`importance=${importance}`);
1567
- if (role)
1568
- extra.push(`role=${role}`);
1569
- extra.push(`states=${states}`, `description=${descPresent}`);
1570
- if (appearances) {
1571
- const seen = appearances.get(id);
1572
- const eps = seen ? seen.episodes.size : 0;
1573
- const scns = seen ? seen.scenes : 0;
1574
- const arc = seen && eps > 0 ? ` episodes=${compactEpisodeRanges(seen.episodes)}` : "";
1575
- extra.push(`scenes=${scns}`, `episodes_count=${eps}${arc}`);
1576
- }
1577
- lines.push(`${kind} ${id}: ${name || "-"} ${extra.join(" ")}`);
1578
- const seen = appearances?.get(id);
1579
- rows.push({
1580
- addr: `${kind}:${id}`,
1581
- kind,
1582
- id,
1583
- name,
1584
- aliases,
1585
- importance,
1586
- role,
1587
- states,
1588
- description_present: descPresent === "yes",
1589
- ...(appearances
1590
- ? {
1591
- scenes: seen?.scenes ?? 0,
1592
- episodes_count: seen?.episodes.size ?? 0,
1593
- episodes: seen ? compactEpisodeRanges(seen.episodes) : "",
1594
- }
1595
- : {}),
1596
- });
1597
- }
1598
- return {
1599
- lines,
1600
- rows,
1601
- rowColumns: [
1602
- "addr",
1603
- "kind",
1604
- "id",
1605
- "name",
1606
- "aliases",
1607
- "importance",
1608
- "role",
1609
- "states",
1610
- "description_present",
1611
- ...(appearances ? ["scenes", "episodes_count", "episodes"] : []),
1612
- ],
1613
- };
1614
- }
1615
- export function splitSpeakerList(raw) {
1616
- if (Array.isArray(raw))
1617
- return raw.map((v) => strOf(v)).filter((v) => v);
1618
- return strOf(raw).split(",").map((s) => s.trim()).filter((s) => s);
1619
- }
1620
- export function blankCreateReport(session, validation, idempotent) {
1621
- const passed = Boolean(validation["passed"]);
1622
- const resultLines = [`created: blank script (Script v${session.version})`, `validation: ${passed ? "passed" : "needs repair"}`];
1623
- if (session.remote) {
1624
- resultLines.push(`revision: ${session.revision}`);
1625
- if (idempotent !== null)
1626
- resultLines.push(`idempotent: ${String(idempotent).toLowerCase()}`);
1627
- }
1628
- return {
1629
- text: resultLines.join("\n"),
1630
- data: {
1631
- op: "script.create",
1632
- changed: true,
1633
- validation,
1634
- script_path: session.artifactLabel,
1635
- ...(session.remote ? { revision: session.revision, idempotent } : {}),
1636
- },
1637
- };
1638
- }
1639
- // ----- add-* (register new entities) ----------------------------------------
1640
- // Read the single positional <name> arg shared by add-actor/location/prop, or
1641
- // throw the common ARGS_MISSING usage error with a verb-specific example.
1642
- export function requireNameArg(opts, verb, example) {
1643
- const args = asList(opts["_args"]);
1644
- if (args.length < 1) {
1645
- throw new CliError("Name missing.", {
1646
- exitCode: EXIT_USAGE,
1647
- errorCode: "ARGS_MISSING",
1648
- hint: example,
1649
- data: { expected: ["<name>"], actual: ["<empty>"] },
1650
- });
1651
- }
1652
- return args[0];
1653
- }
1654
- //# sourceMappingURL=lib.js.map