@lingjingai/scriptctl 0.49.16 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/changes/0.50.0.md +63 -0
- package/changes/unreleased.md +2 -1
- package/dist/cli.js +26 -5
- package/dist/cli.js.map +1 -1
- package/dist/domain/authoring/apply.d.ts +1 -33
- package/dist/domain/authoring/apply.js +1 -783
- package/dist/domain/authoring/apply.js.map +1 -1
- package/dist/domain/authoring/export.d.ts +1 -7
- package/dist/domain/authoring/export.js +1 -84
- package/dist/domain/authoring/export.js.map +1 -1
- package/dist/domain/authoring/parser.d.ts +2 -3
- package/dist/domain/authoring/parser.js +2 -914
- package/dist/domain/authoring/parser.js.map +1 -1
- package/dist/domain/authoring/serializer.d.ts +1 -2
- package/dist/domain/authoring/serializer.js +1 -243
- package/dist/domain/authoring/serializer.js.map +1 -1
- package/dist/domain/authoring/shared/bracket.d.ts +4 -0
- package/dist/domain/authoring/shared/bracket.js +95 -0
- package/dist/domain/authoring/shared/bracket.js.map +1 -0
- package/dist/domain/authoring/shared/types.d.ts +12 -0
- package/dist/domain/authoring/shared/types.js +2 -0
- package/dist/domain/authoring/shared/types.js.map +1 -0
- package/dist/domain/authoring/types.d.ts +2 -87
- package/dist/domain/authoring/types.js +2 -1
- package/dist/domain/authoring/types.js.map +1 -1
- package/dist/domain/authoring/v3/apply.d.ts +33 -0
- package/dist/domain/authoring/v3/apply.js +784 -0
- package/dist/domain/authoring/v3/apply.js.map +1 -0
- package/dist/domain/authoring/v3/export.d.ts +7 -0
- package/dist/domain/authoring/v3/export.js +85 -0
- package/dist/domain/authoring/v3/export.js.map +1 -0
- package/dist/domain/authoring/v3/parser.d.ts +3 -0
- package/dist/domain/authoring/v3/parser.js +823 -0
- package/dist/domain/authoring/v3/parser.js.map +1 -0
- package/dist/domain/authoring/v3/serializer.d.ts +2 -0
- package/dist/domain/authoring/v3/serializer.js +244 -0
- package/dist/domain/authoring/v3/serializer.js.map +1 -0
- package/dist/domain/authoring/v3/types.d.ts +76 -0
- package/dist/domain/authoring/v3/types.js +2 -0
- package/dist/domain/authoring/v3/types.js.map +1 -0
- package/dist/domain/authoring/v4/apply.d.ts +40 -0
- package/dist/domain/authoring/v4/apply.js +451 -0
- package/dist/domain/authoring/v4/apply.js.map +1 -0
- package/dist/domain/authoring/v4/parser.d.ts +2 -0
- package/dist/domain/authoring/v4/parser.js +729 -0
- package/dist/domain/authoring/v4/parser.js.map +1 -0
- package/dist/domain/authoring/v4/serializer.d.ts +6 -0
- package/dist/domain/authoring/v4/serializer.js +280 -0
- package/dist/domain/authoring/v4/serializer.js.map +1 -0
- package/dist/domain/authoring/v4/types.d.ts +50 -0
- package/dist/domain/authoring/v4/types.js +2 -0
- package/dist/domain/authoring/v4/types.js.map +1 -0
- package/dist/domain/ingest/apply-plan.d.ts +1 -1
- package/dist/domain/ingest/assembler.d.ts +9 -0
- package/dist/domain/ingest/assembler.js +98 -36
- package/dist/domain/ingest/assembler.js.map +1 -1
- package/dist/domain/ingest/asset-audit.d.ts +50 -0
- package/dist/domain/ingest/asset-audit.js +196 -0
- package/dist/domain/ingest/asset-audit.js.map +1 -0
- package/dist/domain/ingest/production-validation.d.ts +5 -4
- package/dist/domain/ingest/production-validation.js +10 -25
- package/dist/domain/ingest/production-validation.js.map +1 -1
- package/dist/domain/ingest/records.d.ts +1 -1
- package/dist/domain/ingest/records.js +1 -1
- package/dist/domain/ingest/records.js.map +1 -1
- package/dist/domain/ingest/serial-context.d.ts +1 -1
- package/dist/domain/ingest/validation.d.ts +1 -11
- package/dist/domain/ingest/validation.js +1 -199
- package/dist/domain/ingest/validation.js.map +1 -1
- package/dist/domain/ingest/video-apply.js +68 -45
- package/dist/domain/ingest/video-apply.js.map +1 -1
- package/dist/domain/script/address.d.ts +1 -32
- package/dist/domain/script/address.js +1 -144
- package/dist/domain/script/address.js.map +1 -1
- package/dist/domain/script/dispatch.d.ts +14 -0
- package/dist/domain/script/dispatch.js +47 -0
- package/dist/domain/script/dispatch.js.map +1 -0
- package/dist/domain/script/lookups.d.ts +1 -33
- package/dist/domain/script/lookups.js +1 -316
- package/dist/domain/script/lookups.js.map +1 -1
- package/dist/domain/script/parse.d.ts +1 -3
- package/dist/domain/script/parse.js +1 -164
- package/dist/domain/script/parse.js.map +1 -1
- package/dist/domain/script/patch/apply.d.ts +1 -2
- package/dist/domain/script/patch/apply.js +1 -30
- package/dist/domain/script/patch/apply.js.map +1 -1
- package/dist/domain/script/patch/helpers.d.ts +1 -17
- package/dist/domain/script/patch/helpers.js +1 -210
- package/dist/domain/script/patch/helpers.js.map +1 -1
- package/dist/domain/script/patch/inline-speaker.d.ts +1 -2
- package/dist/domain/script/patch/inline-speaker.js +1 -49
- package/dist/domain/script/patch/inline-speaker.js.map +1 -1
- package/dist/domain/script/patch/ops-action.d.ts +1 -12
- package/dist/domain/script/patch/ops-action.js +1 -366
- package/dist/domain/script/patch/ops-action.js.map +1 -1
- package/dist/domain/script/patch/ops-asset.d.ts +1 -14
- package/dist/domain/script/patch/ops-asset.js +1 -364
- package/dist/domain/script/patch/ops-asset.js.map +1 -1
- package/dist/domain/script/patch/ops-dialogue.d.ts +1 -2
- package/dist/domain/script/patch/ops-dialogue.js +1 -25
- package/dist/domain/script/patch/ops-dialogue.js.map +1 -1
- package/dist/domain/script/patch/ops-extend.d.ts +1 -8
- package/dist/domain/script/patch/ops-extend.js +1 -110
- package/dist/domain/script/patch/ops-extend.js.map +1 -1
- package/dist/domain/script/patch/ops-meta.d.ts +1 -5
- package/dist/domain/script/patch/ops-meta.js +1 -81
- package/dist/domain/script/patch/ops-meta.js.map +1 -1
- package/dist/domain/script/patch/ops-scene.d.ts +1 -6
- package/dist/domain/script/patch/ops-scene.js +1 -350
- package/dist/domain/script/patch/ops-scene.js.map +1 -1
- package/dist/domain/script/patch/ops-state.d.ts +1 -8
- package/dist/domain/script/patch/ops-state.js +1 -164
- package/dist/domain/script/patch/ops-state.js.map +1 -1
- package/dist/domain/script/patch/registry.d.ts +1 -2
- package/dist/domain/script/patch/registry.js +1 -52
- package/dist/domain/script/patch/registry.js.map +1 -1
- package/dist/domain/script/patch/types.d.ts +1 -10
- package/dist/domain/script/patch/types.js +1 -1
- package/dist/domain/script/patch/types.js.map +1 -1
- package/dist/domain/script/refs.d.ts +1 -4
- package/dist/domain/script/refs.js +1 -63
- package/dist/domain/script/refs.js.map +1 -1
- package/dist/domain/script/scene-refs.d.ts +1 -3
- package/dist/domain/script/scene-refs.js +1 -34
- package/dist/domain/script/scene-refs.js.map +1 -1
- package/dist/domain/script/schema.d.ts +1 -6
- package/dist/domain/script/schema.js +1 -55
- package/dist/domain/script/schema.js.map +1 -1
- package/dist/domain/script/selector.d.ts +1 -45
- package/dist/domain/script/selector.js +1 -184
- package/dist/domain/script/selector.js.map +1 -1
- package/dist/domain/script/shared/regex.d.ts +2 -0
- package/dist/domain/script/shared/regex.js +7 -0
- package/dist/domain/script/shared/regex.js.map +1 -0
- package/dist/domain/script/shared/types.d.ts +18 -0
- package/dist/domain/script/shared/types.js +9 -0
- package/dist/domain/script/shared/types.js.map +1 -0
- package/dist/domain/script/shared/validation.d.ts +10 -0
- package/dist/domain/script/shared/validation.js +2 -0
- package/dist/domain/script/shared/validation.js.map +1 -0
- package/dist/domain/script/types.d.ts +1 -123
- package/dist/domain/script/types.js +1 -8
- package/dist/domain/script/types.js.map +1 -1
- package/dist/domain/script/v3/address.d.ts +32 -0
- package/dist/domain/script/v3/address.js +145 -0
- package/dist/domain/script/v3/address.js.map +1 -0
- package/dist/domain/script/v3/lookups.d.ts +33 -0
- package/dist/domain/script/v3/lookups.js +317 -0
- package/dist/domain/script/v3/lookups.js.map +1 -0
- package/dist/domain/script/v3/ordinal.d.ts +8 -0
- package/dist/domain/script/v3/ordinal.js +92 -0
- package/dist/domain/script/v3/ordinal.js.map +1 -0
- package/dist/domain/script/v3/parse.d.ts +3 -0
- package/dist/domain/script/v3/parse.js +165 -0
- package/dist/domain/script/v3/parse.js.map +1 -0
- package/dist/domain/script/v3/patch/apply.d.ts +2 -0
- package/dist/domain/script/v3/patch/apply.js +31 -0
- package/dist/domain/script/v3/patch/apply.js.map +1 -0
- package/dist/domain/script/v3/patch/helpers.d.ts +17 -0
- package/dist/domain/script/v3/patch/helpers.js +211 -0
- package/dist/domain/script/v3/patch/helpers.js.map +1 -0
- package/dist/domain/script/v3/patch/inline-speaker.d.ts +2 -0
- package/dist/domain/script/v3/patch/inline-speaker.js +50 -0
- package/dist/domain/script/v3/patch/inline-speaker.js.map +1 -0
- package/dist/domain/script/v3/patch/ops-action.d.ts +12 -0
- package/dist/domain/script/v3/patch/ops-action.js +367 -0
- package/dist/domain/script/v3/patch/ops-action.js.map +1 -0
- package/dist/domain/script/v3/patch/ops-asset.d.ts +14 -0
- package/dist/domain/script/v3/patch/ops-asset.js +365 -0
- package/dist/domain/script/v3/patch/ops-asset.js.map +1 -0
- package/dist/domain/script/v3/patch/ops-dialogue.d.ts +2 -0
- package/dist/domain/script/v3/patch/ops-dialogue.js +26 -0
- package/dist/domain/script/v3/patch/ops-dialogue.js.map +1 -0
- package/dist/domain/script/v3/patch/ops-extend.d.ts +8 -0
- package/dist/domain/script/v3/patch/ops-extend.js +111 -0
- package/dist/domain/script/v3/patch/ops-extend.js.map +1 -0
- package/dist/domain/script/v3/patch/ops-meta.d.ts +5 -0
- package/dist/domain/script/v3/patch/ops-meta.js +82 -0
- package/dist/domain/script/v3/patch/ops-meta.js.map +1 -0
- package/dist/domain/script/v3/patch/ops-scene.d.ts +6 -0
- package/dist/domain/script/v3/patch/ops-scene.js +351 -0
- package/dist/domain/script/v3/patch/ops-scene.js.map +1 -0
- package/dist/domain/script/v3/patch/ops-state.d.ts +8 -0
- package/dist/domain/script/v3/patch/ops-state.js +165 -0
- package/dist/domain/script/v3/patch/ops-state.js.map +1 -0
- package/dist/domain/script/v3/patch/registry.d.ts +2 -0
- package/dist/domain/script/v3/patch/registry.js +53 -0
- package/dist/domain/script/v3/patch/registry.js.map +1 -0
- package/dist/domain/script/v3/patch/types.d.ts +10 -0
- package/dist/domain/script/v3/patch/types.js +2 -0
- package/dist/domain/script/v3/patch/types.js.map +1 -0
- package/dist/domain/script/v3/refs.d.ts +4 -0
- package/dist/domain/script/v3/refs.js +64 -0
- package/dist/domain/script/v3/refs.js.map +1 -0
- package/dist/domain/script/v3/scene-refs.d.ts +3 -0
- package/dist/domain/script/v3/scene-refs.js +35 -0
- package/dist/domain/script/v3/scene-refs.js.map +1 -0
- package/dist/domain/script/v3/schema.d.ts +6 -0
- package/dist/domain/script/v3/schema.js +56 -0
- package/dist/domain/script/v3/schema.js.map +1 -0
- package/dist/domain/script/v3/selector.d.ts +44 -0
- package/dist/domain/script/v3/selector.js +180 -0
- package/dist/domain/script/v3/selector.js.map +1 -0
- package/dist/domain/script/v3/types.d.ts +106 -0
- package/dist/domain/script/v3/types.js +2 -0
- package/dist/domain/script/v3/types.js.map +1 -0
- package/dist/domain/script/v3/validation.d.ts +3 -0
- package/dist/domain/script/v3/validation.js +200 -0
- package/dist/domain/script/v3/validation.js.map +1 -0
- package/dist/domain/script/v4/address.d.ts +61 -0
- package/dist/domain/script/v4/address.js +100 -0
- package/dist/domain/script/v4/address.js.map +1 -0
- package/dist/domain/script/v4/factory.d.ts +2 -0
- package/dist/domain/script/v4/factory.js +13 -0
- package/dist/domain/script/v4/factory.js.map +1 -0
- package/dist/domain/script/v4/from-v3.d.ts +29 -0
- package/dist/domain/script/v4/from-v3.js +307 -0
- package/dist/domain/script/v4/from-v3.js.map +1 -0
- package/dist/domain/script/v4/ids.d.ts +27 -0
- package/dist/domain/script/v4/ids.js +63 -0
- package/dist/domain/script/v4/ids.js.map +1 -0
- package/dist/domain/script/v4/ordinal.d.ts +3 -0
- package/dist/domain/script/v4/ordinal.js +67 -0
- package/dist/domain/script/v4/ordinal.js.map +1 -0
- package/dist/domain/script/v4/parse.d.ts +3 -0
- package/dist/domain/script/v4/parse.js +18 -0
- package/dist/domain/script/v4/parse.js.map +1 -0
- package/dist/domain/script/v4/patch/apply.d.ts +3 -0
- package/dist/domain/script/v4/patch/apply.js +24 -0
- package/dist/domain/script/v4/patch/apply.js.map +1 -0
- package/dist/domain/script/v4/patch/helpers.d.ts +32 -0
- package/dist/domain/script/v4/patch/helpers.js +139 -0
- package/dist/domain/script/v4/patch/helpers.js.map +1 -0
- package/dist/domain/script/v4/patch/ops-action.d.ts +13 -0
- package/dist/domain/script/v4/patch/ops-action.js +379 -0
- package/dist/domain/script/v4/patch/ops-action.js.map +1 -0
- package/dist/domain/script/v4/patch/ops-asset.d.ts +17 -0
- package/dist/domain/script/v4/patch/ops-asset.js +617 -0
- package/dist/domain/script/v4/patch/ops-asset.js.map +1 -0
- package/dist/domain/script/v4/patch/ops-extend.d.ts +11 -0
- package/dist/domain/script/v4/patch/ops-extend.js +86 -0
- package/dist/domain/script/v4/patch/ops-extend.js.map +1 -0
- package/dist/domain/script/v4/patch/ops-meta.d.ts +5 -0
- package/dist/domain/script/v4/patch/ops-meta.js +49 -0
- package/dist/domain/script/v4/patch/ops-meta.js.map +1 -0
- package/dist/domain/script/v4/patch/ops-scene-ref.d.ts +3 -0
- package/dist/domain/script/v4/patch/ops-scene-ref.js +98 -0
- package/dist/domain/script/v4/patch/ops-scene-ref.js.map +1 -0
- package/dist/domain/script/v4/patch/ops-structure.d.ts +6 -0
- package/dist/domain/script/v4/patch/ops-structure.js +236 -0
- package/dist/domain/script/v4/patch/ops-structure.js.map +1 -0
- package/dist/domain/script/v4/patch/registry.d.ts +2 -0
- package/dist/domain/script/v4/patch/registry.js +50 -0
- package/dist/domain/script/v4/patch/registry.js.map +1 -0
- package/dist/domain/script/v4/patch/schema.d.ts +7 -0
- package/dist/domain/script/v4/patch/schema.js +75 -0
- package/dist/domain/script/v4/patch/schema.js.map +1 -0
- package/dist/domain/script/v4/patch/types.d.ts +10 -0
- package/dist/domain/script/v4/patch/types.js +2 -0
- package/dist/domain/script/v4/patch/types.js.map +1 -0
- package/dist/domain/script/v4/selector.d.ts +11 -0
- package/dist/domain/script/v4/selector.js +125 -0
- package/dist/domain/script/v4/selector.js.map +1 -0
- package/dist/domain/script/v4/types.d.ts +120 -0
- package/dist/domain/script/v4/types.js +2 -0
- package/dist/domain/script/v4/types.js.map +1 -0
- package/dist/domain/script/v4/validation.d.ts +2 -0
- package/dist/domain/script/v4/validation.js +378 -0
- package/dist/domain/script/v4/validation.js.map +1 -0
- package/dist/help-text.js +146 -114
- package/dist/help-text.js.map +1 -1
- package/dist/llm/config.js +2 -0
- package/dist/llm/config.js.map +1 -1
- package/dist/llm/registry.d.ts +1 -0
- package/dist/llm/registry.js +3 -0
- package/dist/llm/registry.js.map +1 -1
- package/dist/llm/tasks/ingest/asset-audit.d.ts +6 -0
- package/dist/llm/tasks/ingest/asset-audit.js +164 -0
- package/dist/llm/tasks/ingest/asset-audit.js.map +1 -0
- package/dist/llm/tasks/ingest/asset-curate.d.ts +1 -1
- package/dist/llm/types.d.ts +1 -1
- package/dist/llm/types.js.map +1 -1
- package/dist/usecases/ingest/command.js +1 -1
- package/dist/usecases/ingest/final-asset-audit.d.ts +39 -0
- package/dist/usecases/ingest/final-asset-audit.js +88 -0
- package/dist/usecases/ingest/final-asset-audit.js.map +1 -0
- package/dist/usecases/ingest/pipeline.js +62 -11
- package/dist/usecases/ingest/pipeline.js.map +1 -1
- package/dist/usecases/ingest/serial-govern.d.ts +2 -1
- package/dist/usecases/ingest/serial-govern.js +11 -4
- package/dist/usecases/ingest/serial-govern.js.map +1 -1
- package/dist/usecases/ingest/video-pipeline.js +100 -14
- package/dist/usecases/ingest/video-pipeline.js.map +1 -1
- package/dist/usecases/ingest/view-server.js +2 -2
- package/dist/usecases/ingest/view-server.js.map +1 -1
- package/dist/usecases/script/actions.js +101 -5
- package/dist/usecases/script/actions.js.map +1 -1
- package/dist/usecases/script/actors.js +16 -7
- package/dist/usecases/script/actors.js.map +1 -1
- package/dist/usecases/script/alias.js +7 -6
- package/dist/usecases/script/alias.js.map +1 -1
- package/dist/usecases/script/assets.js +18 -2
- package/dist/usecases/script/assets.js.map +1 -1
- package/dist/usecases/script/audit-assets.d.ts +4 -0
- package/dist/usecases/script/audit-assets.js +40 -0
- package/dist/usecases/script/audit-assets.js.map +1 -0
- package/dist/usecases/script/command-constraints.d.ts +36 -0
- package/dist/usecases/script/command-constraints.js +115 -0
- package/dist/usecases/script/command-constraints.js.map +1 -0
- package/dist/usecases/script/context.js +31 -4
- package/dist/usecases/script/context.js.map +1 -1
- package/dist/usecases/script/create.js +2 -2
- package/dist/usecases/script/create.js.map +1 -1
- package/dist/usecases/script/delete.js +6 -3
- package/dist/usecases/script/delete.js.map +1 -1
- package/dist/usecases/script/describe.js +7 -4
- package/dist/usecases/script/describe.js.map +1 -1
- package/dist/usecases/script/dialogue.js +15 -5
- package/dist/usecases/script/dialogue.js.map +1 -1
- package/dist/usecases/script/dispatch.d.ts +3 -0
- package/dist/usecases/script/dispatch.js +10 -0
- package/dist/usecases/script/dispatch.js.map +1 -0
- package/dist/usecases/script/do.js +74 -11
- package/dist/usecases/script/do.js.map +1 -1
- package/dist/usecases/script/emotion.js +14 -3
- package/dist/usecases/script/emotion.js.map +1 -1
- package/dist/usecases/script/episodes.js +15 -4
- package/dist/usecases/script/episodes.js.map +1 -1
- package/dist/usecases/script/export-authoring.js +35 -11
- package/dist/usecases/script/export-authoring.js.map +1 -1
- package/dist/usecases/script/extend.js +23 -15
- package/dist/usecases/script/extend.js.map +1 -1
- package/dist/usecases/script/ids.js +53 -10
- package/dist/usecases/script/ids.js.map +1 -1
- package/dist/usecases/script/insert.js +74 -38
- package/dist/usecases/script/insert.js.map +1 -1
- package/dist/usecases/script/lib.d.ts +50 -1
- package/dist/usecases/script/lib.js +599 -61
- package/dist/usecases/script/lib.js.map +1 -1
- package/dist/usecases/script/locations.js +16 -7
- package/dist/usecases/script/locations.js.map +1 -1
- package/dist/usecases/script/merge.js +8 -5
- package/dist/usecases/script/merge.js.map +1 -1
- package/dist/usecases/script/move.js +24 -5
- package/dist/usecases/script/move.js.map +1 -1
- package/dist/usecases/script/parenthetical.d.ts +3 -0
- package/dist/usecases/script/parenthetical.js +55 -0
- package/dist/usecases/script/parenthetical.js.map +1 -0
- package/dist/usecases/script/props.js +16 -7
- package/dist/usecases/script/props.js.map +1 -1
- package/dist/usecases/script/refs.js +44 -0
- package/dist/usecases/script/refs.js.map +1 -1
- package/dist/usecases/script/rename.js +7 -4
- package/dist/usecases/script/rename.js.map +1 -1
- package/dist/usecases/script/scenes.js +32 -6
- package/dist/usecases/script/scenes.js.map +1 -1
- package/dist/usecases/script/script-patch.js +180 -16
- package/dist/usecases/script/script-patch.js.map +1 -1
- package/dist/usecases/script/session.d.ts +3 -0
- package/dist/usecases/script/session.js +25 -5
- package/dist/usecases/script/session.js.map +1 -1
- package/dist/usecases/script/split.js +12 -6
- package/dist/usecases/script/split.js.map +1 -1
- package/dist/usecases/script/states.js +45 -1
- package/dist/usecases/script/states.js.map +1 -1
- package/dist/usecases/script/synopsis.js +11 -4
- package/dist/usecases/script/synopsis.js.map +1 -1
- package/dist/usecases/script/v3/mutations.d.ts +2 -0
- package/dist/usecases/script/v3/mutations.js +5 -0
- package/dist/usecases/script/v3/mutations.js.map +1 -0
- package/dist/usecases/script/v4/mutations.d.ts +2 -0
- package/dist/usecases/script/v4/mutations.js +6 -0
- package/dist/usecases/script/v4/mutations.js.map +1 -0
- package/dist/usecases/script/v4/queries.d.ts +14 -0
- package/dist/usecases/script/v4/queries.js +154 -0
- package/dist/usecases/script/v4/queries.js.map +1 -0
- package/dist/usecases/script/working-copy.js +3 -3
- package/dist/usecases/script/working-copy.js.map +1 -1
- package/dist/usecases/script/write-authoring.js +99 -5
- package/dist/usecases/script/write-authoring.js.map +1 -1
- package/package.json +3 -2
- package/skills/scriptctl/SKILL.md +122 -282
- package/skills/scriptctl/references/atomic-edit-workflow.md +23 -38
- package/skills/scriptctl/references/bulk-authoring.md +35 -154
- package/skills/scriptctl/references/ingest-workflow.md +12 -11
- package/skills/scriptctl/references/production-writing-standard.md +38 -67
- package/skills/scriptctl/references/state-reference-repair.md +19 -42
|
@@ -1,784 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { validateScriptV3 } from "../ingest/validation.js";
|
|
3
|
-
function fail(code, message, received, nextSteps, exitCode = EXIT_INPUT) {
|
|
4
|
-
throw new CliError("AUTHORING BLOCKED", message, {
|
|
5
|
-
exitCode,
|
|
6
|
-
errorCode: code,
|
|
7
|
-
received,
|
|
8
|
-
nextSteps,
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
function sourceLabel(source) {
|
|
12
|
-
return `line ${source.line}, column ${source.column}`;
|
|
13
|
-
}
|
|
14
|
-
function canonicalize(value) {
|
|
15
|
-
if (Array.isArray(value))
|
|
16
|
-
return value.map(canonicalize);
|
|
17
|
-
if (value !== null && typeof value === "object") {
|
|
18
|
-
const result = {};
|
|
19
|
-
for (const [key, item] of Object.entries(value).sort(([left], [right]) => left.localeCompare(right))) {
|
|
20
|
-
result[key] = canonicalize(item);
|
|
21
|
-
}
|
|
22
|
-
return result;
|
|
23
|
-
}
|
|
24
|
-
return value;
|
|
25
|
-
}
|
|
26
|
-
function semanticEqual(left, right) {
|
|
27
|
-
return JSON.stringify(canonicalize(left)) === JSON.stringify(canonicalize(right));
|
|
28
|
-
}
|
|
29
|
-
function assetId(_kind, value) {
|
|
30
|
-
if ("actor_id" in value)
|
|
31
|
-
return value.actor_id;
|
|
32
|
-
if ("location_id" in value)
|
|
33
|
-
return value.location_id;
|
|
34
|
-
return value.prop_id;
|
|
35
|
-
}
|
|
36
|
-
function assetName(_kind, value) {
|
|
37
|
-
if ("actor_name" in value)
|
|
38
|
-
return value.actor_name;
|
|
39
|
-
if ("location_name" in value)
|
|
40
|
-
return value.location_name;
|
|
41
|
-
return value.prop_name;
|
|
42
|
-
}
|
|
43
|
-
function assetsFor(script, kind) {
|
|
44
|
-
if (kind === "actor")
|
|
45
|
-
return script.actors;
|
|
46
|
-
if (kind === "location")
|
|
47
|
-
return script.locations;
|
|
48
|
-
return script.props;
|
|
49
|
-
}
|
|
50
|
-
function pushAsset(script, asset) {
|
|
51
|
-
if ("actor_id" in asset.value)
|
|
52
|
-
script.actors.push(asset.value);
|
|
53
|
-
else if ("location_id" in asset.value)
|
|
54
|
-
script.locations.push(asset.value);
|
|
55
|
-
else
|
|
56
|
-
script.props.push(asset.value);
|
|
57
|
-
}
|
|
58
|
-
function findAsset(script, kind, id) {
|
|
59
|
-
return assetsFor(script, kind).find((asset) => assetId(kind, asset) === id);
|
|
60
|
-
}
|
|
61
|
-
function findAssetByAnyId(script, id) {
|
|
62
|
-
for (const kind of ["actor", "location", "prop"]) {
|
|
63
|
-
const value = findAsset(script, kind, id);
|
|
64
|
-
if (value !== undefined)
|
|
65
|
-
return { kind, value };
|
|
66
|
-
}
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
|
-
function prepareDeclarations(declarations) {
|
|
70
|
-
const assets = [];
|
|
71
|
-
const states = [];
|
|
72
|
-
const groupOrder = { actor: 0, location: 1, prop: 2 };
|
|
73
|
-
let lastGroup = -1;
|
|
74
|
-
let currentAsset;
|
|
75
|
-
let standaloneStarted = false;
|
|
76
|
-
const seenOwners = new Set();
|
|
77
|
-
for (const declaration of declarations) {
|
|
78
|
-
if (declaration.declarationKind !== "state") {
|
|
79
|
-
if (standaloneStarted) {
|
|
80
|
-
fail("AUTHORING_DECLARATION_ORDER", "Asset declarations must precede standalone state declarations.", [sourceLabel(declaration.source)], ["Move standalone states to the end of <create>."]);
|
|
81
|
-
}
|
|
82
|
-
const kind = declaration.declarationKind;
|
|
83
|
-
if (groupOrder[kind] < lastGroup) {
|
|
84
|
-
fail("AUTHORING_DECLARATION_ORDER", "Asset declaration groups are out of canonical order.", [sourceLabel(declaration.source), kind], ["Order asset declarations as actor, location, then prop."]);
|
|
85
|
-
}
|
|
86
|
-
lastGroup = groupOrder[kind];
|
|
87
|
-
const value = structuredClone(declaration.value);
|
|
88
|
-
value.states = [];
|
|
89
|
-
const prepared = { kind, value, source: declaration.source };
|
|
90
|
-
const ownerKey = `${kind}:${assetId(kind, value)}`;
|
|
91
|
-
if (seenOwners.has(ownerKey)) {
|
|
92
|
-
fail("AUTHORING_DECLARATION_DUPLICATE", "Asset declaration is duplicated.", [sourceLabel(declaration.source), ownerKey], ["Keep one declaration per asset."]);
|
|
93
|
-
}
|
|
94
|
-
seenOwners.add(ownerKey);
|
|
95
|
-
assets.push(prepared);
|
|
96
|
-
currentAsset = prepared;
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
const ownerKey = `${declaration.ownerKind}:${declaration.ownerId}`;
|
|
100
|
-
if (currentAsset !== undefined
|
|
101
|
-
&& currentAsset.kind === declaration.ownerKind
|
|
102
|
-
&& assetId(currentAsset.kind, currentAsset.value) === declaration.ownerId) {
|
|
103
|
-
currentAsset.value.states.push(structuredClone(declaration.value));
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
standaloneStarted = true;
|
|
107
|
-
currentAsset = undefined;
|
|
108
|
-
states.push({
|
|
109
|
-
kind: declaration.ownerKind,
|
|
110
|
-
ownerId: declaration.ownerId,
|
|
111
|
-
value: structuredClone(declaration.value),
|
|
112
|
-
source: declaration.source,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
for (const asset of assets) {
|
|
116
|
-
const id = assetId(asset.kind, asset.value);
|
|
117
|
-
if (asset.value.states.length === 0 || asset.value.states[0].state_id !== "default") {
|
|
118
|
-
fail("AUTHORING_DEFAULT_STATE_REQUIRED", "Every declared asset must be immediately followed by its states, beginning with default.", [sourceLabel(asset.source), `${asset.kind}:${id}`], [`Add [state|${asset.kind}:${id}|default|...] directly after the asset declaration.`]);
|
|
119
|
-
}
|
|
120
|
-
if (asset.value.states.filter((state) => state.state_id === "default").length !== 1) {
|
|
121
|
-
fail("AUTHORING_DEFAULT_STATE_DUPLICATE", "Every declared asset must contain exactly one default state.", [sourceLabel(asset.source), `${asset.kind}:${id}`], ["Keep exactly one default state."]);
|
|
122
|
-
}
|
|
123
|
-
const aliases = asset.value.aliases ?? [];
|
|
124
|
-
if (new Set(aliases).size !== aliases.length || aliases.includes(assetName(asset.kind, asset.value))) {
|
|
125
|
-
fail("AUTHORING_ALIAS_INVALID", "Asset aliases must be unique and must differ from the canonical name.", [sourceLabel(asset.source), `${asset.kind}:${id}`], ["Remove duplicate aliases and the canonical name from aliases."]);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return { assets, states };
|
|
129
|
-
}
|
|
130
|
-
function emptyDeclarationPlan() {
|
|
131
|
-
return {
|
|
132
|
-
createdAssets: [],
|
|
133
|
-
existingAssets: [],
|
|
134
|
-
createdStates: [],
|
|
135
|
-
existingStates: [],
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
function applyDeclarations(script, declarations) {
|
|
139
|
-
const prepared = prepareDeclarations(declarations);
|
|
140
|
-
const plan = emptyDeclarationPlan();
|
|
141
|
-
for (const asset of prepared.assets) {
|
|
142
|
-
const id = assetId(asset.kind, asset.value);
|
|
143
|
-
const address = `${asset.kind}:${id}`;
|
|
144
|
-
const anyExisting = findAssetByAnyId(script, id);
|
|
145
|
-
if (anyExisting !== undefined) {
|
|
146
|
-
if (anyExisting.kind === asset.kind && semanticEqual(anyExisting.value, asset.value)) {
|
|
147
|
-
plan.existingAssets.push(address);
|
|
148
|
-
plan.existingStates.push(...asset.value.states.map((state) => `${address}/${state.state_id}`));
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
fail("AUTHORING_ASSET_CONFLICT", "Create-only asset declaration conflicts with an existing asset.", [sourceLabel(asset.source), `${asset.kind}:${id}`], ["Use the existing identical definition or change it with an explicit mutation verb."]);
|
|
152
|
-
}
|
|
153
|
-
pushAsset(script, asset);
|
|
154
|
-
plan.createdAssets.push(address);
|
|
155
|
-
plan.createdStates.push(...asset.value.states.map((state) => `${address}/${state.state_id}`));
|
|
156
|
-
}
|
|
157
|
-
for (const state of prepared.states) {
|
|
158
|
-
const owner = findAsset(script, state.kind, state.ownerId);
|
|
159
|
-
if (owner === undefined) {
|
|
160
|
-
fail("AUTHORING_STATE_OWNER_NOT_FOUND", "Standalone state owner does not exist.", [sourceLabel(state.source), `${state.kind}:${state.ownerId}`], ["Declare the asset before its states or use an existing asset ID."]);
|
|
161
|
-
}
|
|
162
|
-
const existing = owner.states.find((candidate) => candidate.state_id === state.value.state_id);
|
|
163
|
-
if (existing !== undefined && !semanticEqual(existing, state.value)) {
|
|
164
|
-
fail("AUTHORING_STATE_CONFLICT", "Create-only state declaration conflicts with an existing state on the same asset.", [sourceLabel(state.source), `${state.kind}:${state.ownerId}/${state.value.state_id}`], ["Use an unused state ID for this asset, or reuse the identical existing state."]);
|
|
165
|
-
}
|
|
166
|
-
const stateAddress = `${state.kind}:${state.ownerId}/${state.value.state_id}`;
|
|
167
|
-
if (existing === undefined) {
|
|
168
|
-
owner.states.push(state.value);
|
|
169
|
-
plan.createdStates.push(stateAddress);
|
|
170
|
-
}
|
|
171
|
-
else
|
|
172
|
-
plan.existingStates.push(stateAddress);
|
|
173
|
-
}
|
|
174
|
-
return plan;
|
|
175
|
-
}
|
|
176
|
-
function sceneCounts(scene) {
|
|
177
|
-
return { episodes: 0, scenes: scene === undefined ? 0 : 1, actions: scene?.actions.length ?? 0 };
|
|
178
|
-
}
|
|
179
|
-
function episodeCounts(episode) {
|
|
180
|
-
return {
|
|
181
|
-
episodes: episode === undefined ? 0 : 1,
|
|
182
|
-
scenes: episode?.scenes.length ?? 0,
|
|
183
|
-
actions: episode?.scenes.reduce((total, scene) => total + scene.actions.length, 0) ?? 0,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
function episodesCounts(episodes) {
|
|
187
|
-
return episodes.reduce((counts, episode) => ({
|
|
188
|
-
episodes: counts.episodes + 1,
|
|
189
|
-
scenes: counts.scenes + episode.scenes.length,
|
|
190
|
-
actions: counts.actions + episode.scenes.reduce((total, scene) => total + scene.actions.length, 0),
|
|
191
|
-
}), { episodes: 0, scenes: 0, actions: 0 });
|
|
192
|
-
}
|
|
193
|
-
function scenesCounts(scenes) {
|
|
194
|
-
return {
|
|
195
|
-
episodes: 0,
|
|
196
|
-
scenes: scenes.length,
|
|
197
|
-
actions: scenes.reduce((total, scene) => total + scene.actions.length, 0),
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
function idDiff(before, after) {
|
|
201
|
-
const beforeSet = new Set(before);
|
|
202
|
-
const afterSet = new Set(after);
|
|
203
|
-
return {
|
|
204
|
-
retainedIds: after.filter((id) => beforeSet.has(id)),
|
|
205
|
-
createdIds: after.filter((id) => !beforeSet.has(id)),
|
|
206
|
-
removedIds: before.filter((id) => !afterSet.has(id)),
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
function assertSceneReferencesMaterialized(scene, source) {
|
|
210
|
-
const unmaterialized = [];
|
|
211
|
-
if (scene.location !== null && !scene.location.state_id)
|
|
212
|
-
unmaterialized.push(`location:${scene.location.location_id}`);
|
|
213
|
-
for (const actor of scene.actors)
|
|
214
|
-
if (!actor.state_id)
|
|
215
|
-
unmaterialized.push(`actor:${actor.actor_id}`);
|
|
216
|
-
for (const prop of scene.props)
|
|
217
|
-
if (!prop.state_id)
|
|
218
|
-
unmaterialized.push(`prop:${prop.prop_id}`);
|
|
219
|
-
if (unmaterialized.length > 0) {
|
|
220
|
-
fail("AUTHORING_SCENE_REF_UNMATERIALIZED", "Every scene asset reference in an authored block must bind a state.", [sourceLabel(source), ...unmaterialized], ["Add the concrete state ID to every location, cast, and prop record."]);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
function assertEpisodeReferencesMaterialized(episode, source) {
|
|
224
|
-
for (const scene of episode.scenes)
|
|
225
|
-
assertSceneReferencesMaterialized(scene, source);
|
|
226
|
-
}
|
|
227
|
-
function episodeIndex(script, episodeId) {
|
|
228
|
-
return script.episodes.findIndex((episode) => episode.episode_id === episodeId);
|
|
229
|
-
}
|
|
230
|
-
function sceneIndex(episode, sceneId) {
|
|
231
|
-
return episode.scenes.findIndex((scene) => scene.scene_id === sceneId);
|
|
232
|
-
}
|
|
233
|
-
function sceneCoordinate(script, parent, sceneId) {
|
|
234
|
-
const epIndex = episodeIndex(script, parent);
|
|
235
|
-
if (epIndex < 0)
|
|
236
|
-
fail("AUTHORING_EPISODE_NOT_FOUND", "Episode target does not exist.", [parent], ["Inspect episodes and use an existing parent."]);
|
|
237
|
-
const index = sceneIndex(script.episodes[epIndex], sceneId);
|
|
238
|
-
if (index < 0)
|
|
239
|
-
fail("AUTHORING_SCENE_NOT_FOUND", "Scene target does not exist.", [`${parent}/${sceneId}`], ["Inspect scenes and use an existing target."]);
|
|
240
|
-
return [epIndex, index];
|
|
241
|
-
}
|
|
242
|
-
function compareCoordinate(left, right) {
|
|
243
|
-
const length = Math.max(left.length, right.length);
|
|
244
|
-
for (let index = 0; index < length; index += 1) {
|
|
245
|
-
const diff = (left[index] ?? 0) - (right[index] ?? 0);
|
|
246
|
-
if (diff !== 0)
|
|
247
|
-
return diff;
|
|
248
|
-
}
|
|
249
|
-
return 0;
|
|
250
|
-
}
|
|
251
|
-
function assertStrictOrder(coords, message) {
|
|
252
|
-
for (let index = 1; index < coords.length; index += 1) {
|
|
253
|
-
if (compareCoordinate(coords[index - 1].coord, coords[index].coord) >= 0) {
|
|
254
|
-
fail("AUTHORING_TARGET_ORDER", message, [sourceLabel(coords[index].source)], ["List replace targets in current document order without duplicates."], EXIT_USAGE);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
function applyEpisodeTargets(baseline, script, targets, mode) {
|
|
259
|
-
const plans = [];
|
|
260
|
-
if (mode === "replace") {
|
|
261
|
-
const coords = targets.map((target) => {
|
|
262
|
-
const index = episodeIndex(baseline, target.value.episode_id);
|
|
263
|
-
if (index < 0)
|
|
264
|
-
fail("AUTHORING_EPISODE_NOT_FOUND", "Episode replace target does not exist.", [sourceLabel(target.source), target.value.episode_id], ["Use --create for a new episode or choose an existing ID."]);
|
|
265
|
-
return { coord: [index], source: target.source };
|
|
266
|
-
});
|
|
267
|
-
assertStrictOrder(coords, "Episode replace targets are not in document order.");
|
|
268
|
-
}
|
|
269
|
-
for (const target of targets) {
|
|
270
|
-
assertEpisodeReferencesMaterialized(target.value, target.source);
|
|
271
|
-
const existingIndex = episodeIndex(baseline, target.value.episode_id);
|
|
272
|
-
const existing = existingIndex < 0 ? undefined : baseline.episodes[existingIndex];
|
|
273
|
-
if (mode === "create") {
|
|
274
|
-
if (existing !== undefined) {
|
|
275
|
-
if (!semanticEqual(existing, target.value)) {
|
|
276
|
-
fail("AUTHORING_CREATE_CONFLICT", "Episode create target already exists with different content.", [sourceLabel(target.source), target.value.episode_id], ["Use --replace to replace it, or make the create block identical for a no-op retry."]);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
script.episodes.push(structuredClone(target.value));
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
script.episodes[existingIndex] = structuredClone(target.value);
|
|
285
|
-
}
|
|
286
|
-
plans.push({
|
|
287
|
-
kind: "episode",
|
|
288
|
-
address: target.value.episode_id,
|
|
289
|
-
before: episodeCounts(existing),
|
|
290
|
-
after: episodeCounts(target.value),
|
|
291
|
-
...idDiff(existing?.scenes.map((scene) => scene.scene_id) ?? [], target.value.scenes.map((scene) => scene.scene_id)),
|
|
292
|
-
untouchedSiblings: Math.max(0, baseline.episodes.length - (existing === undefined ? 0 : 1)),
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
return plans;
|
|
296
|
-
}
|
|
297
|
-
function applySceneTargets(baseline, script, targets, mode) {
|
|
298
|
-
const plans = [];
|
|
299
|
-
if (mode === "replace") {
|
|
300
|
-
const coords = targets.map((target) => ({ coord: sceneCoordinate(baseline, target.parent, target.value.scene_id), source: target.source }));
|
|
301
|
-
assertStrictOrder(coords, "Scene replace targets are not in document order.");
|
|
302
|
-
}
|
|
303
|
-
for (const target of targets) {
|
|
304
|
-
assertSceneReferencesMaterialized(target.value, target.source);
|
|
305
|
-
const epIndex = episodeIndex(baseline, target.parent);
|
|
306
|
-
if (epIndex < 0)
|
|
307
|
-
fail("AUTHORING_EPISODE_NOT_FOUND", "Scene parent episode does not exist.", [sourceLabel(target.source), target.parent], ["Use an existing episode parent."]);
|
|
308
|
-
const baseEpisode = baseline.episodes[epIndex];
|
|
309
|
-
const outputEpisode = script.episodes[epIndex];
|
|
310
|
-
const existingIndex = sceneIndex(baseEpisode, target.value.scene_id);
|
|
311
|
-
const existing = existingIndex < 0 ? undefined : baseEpisode.scenes[existingIndex];
|
|
312
|
-
if (mode === "create") {
|
|
313
|
-
if (existing !== undefined) {
|
|
314
|
-
if (!semanticEqual(existing, target.value)) {
|
|
315
|
-
fail("AUTHORING_CREATE_CONFLICT", "Scene create target already exists with different content.", [sourceLabel(target.source), `${target.parent}/${target.value.scene_id}`], ["Use --replace or make the create block identical for a no-op retry."]);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
outputEpisode.scenes.push(structuredClone(target.value));
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
if (existingIndex < 0)
|
|
324
|
-
fail("AUTHORING_SCENE_NOT_FOUND", "Scene replace target does not exist.", [sourceLabel(target.source), `${target.parent}/${target.value.scene_id}`], ["Use --create for a new scene or choose an existing scene."]);
|
|
325
|
-
outputEpisode.scenes[existingIndex] = structuredClone(target.value);
|
|
326
|
-
}
|
|
327
|
-
plans.push({
|
|
328
|
-
kind: "scene",
|
|
329
|
-
address: `${target.parent}/${target.value.scene_id}`,
|
|
330
|
-
before: sceneCounts(existing),
|
|
331
|
-
after: sceneCounts(target.value),
|
|
332
|
-
...idDiff(existing === undefined ? [] : [existing.scene_id], [target.value.scene_id]),
|
|
333
|
-
untouchedSiblings: Math.max(0, baseEpisode.scenes.length - (existing === undefined ? 0 : 1)),
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
return plans;
|
|
337
|
-
}
|
|
338
|
-
function applyEpisodeSpans(baseline, script, targets) {
|
|
339
|
-
const resolved = targets.map((target) => {
|
|
340
|
-
const from = episodeIndex(baseline, target.from);
|
|
341
|
-
const through = episodeIndex(baseline, target.through);
|
|
342
|
-
if (from < 0 || through < 0)
|
|
343
|
-
fail("AUTHORING_SPAN_ENDPOINT_NOT_FOUND", "Episode-span endpoint does not exist.", [sourceLabel(target.source), `${target.from}..${target.through}`], ["Use existing episode IDs as span endpoints."]);
|
|
344
|
-
if (from > through)
|
|
345
|
-
fail("AUTHORING_SPAN_REVERSED", "Episode-span endpoints are reversed in current document order.", [sourceLabel(target.source), `${target.from}..${target.through}`], ["Swap from and through."]);
|
|
346
|
-
if (target.episodes.length === 0)
|
|
347
|
-
fail("AUTHORING_EMPTY_SPAN", "Episode-span replacement cannot be empty.", [sourceLabel(target.source)], ["Include at least one complete episode."]);
|
|
348
|
-
for (const episode of target.episodes)
|
|
349
|
-
assertEpisodeReferencesMaterialized(episode, target.source);
|
|
350
|
-
return { target, from, through };
|
|
351
|
-
});
|
|
352
|
-
assertStrictOrder(resolved.map((item) => ({ coord: [item.from], source: item.target.source })), "Episode spans are not in document order.");
|
|
353
|
-
for (let index = 1; index < resolved.length; index += 1) {
|
|
354
|
-
if (resolved[index].from <= resolved[index - 1].through)
|
|
355
|
-
fail("AUTHORING_SPAN_OVERLAP", "Episode spans overlap.", [sourceLabel(resolved[index].target.source)], ["Use disjoint episode spans."]);
|
|
356
|
-
}
|
|
357
|
-
const plans = resolved.map(({ target, from, through }) => {
|
|
358
|
-
const before = baseline.episodes.slice(from, through + 1);
|
|
359
|
-
return {
|
|
360
|
-
kind: "episode-span",
|
|
361
|
-
address: `${target.from}..${target.through}`,
|
|
362
|
-
before: episodesCounts(before),
|
|
363
|
-
after: episodesCounts(target.episodes),
|
|
364
|
-
...idDiff(before.map((episode) => episode.episode_id), target.episodes.map((episode) => episode.episode_id)),
|
|
365
|
-
untouchedSiblings: baseline.episodes.length - before.length,
|
|
366
|
-
};
|
|
367
|
-
});
|
|
368
|
-
for (const { target, from, through } of [...resolved].reverse()) {
|
|
369
|
-
script.episodes.splice(from, through - from + 1, ...structuredClone(target.episodes));
|
|
370
|
-
}
|
|
371
|
-
return plans;
|
|
372
|
-
}
|
|
373
|
-
function applySceneSpans(baseline, script, targets) {
|
|
374
|
-
const resolved = targets.map((target) => {
|
|
375
|
-
const epIndex = episodeIndex(baseline, target.parent);
|
|
376
|
-
if (epIndex < 0)
|
|
377
|
-
fail("AUTHORING_EPISODE_NOT_FOUND", "Scene-span parent does not exist.", [sourceLabel(target.source), target.parent], ["Use an existing parent episode."]);
|
|
378
|
-
const episode = baseline.episodes[epIndex];
|
|
379
|
-
const from = sceneIndex(episode, target.from);
|
|
380
|
-
const through = sceneIndex(episode, target.through);
|
|
381
|
-
if (from < 0 || through < 0)
|
|
382
|
-
fail("AUTHORING_SPAN_ENDPOINT_NOT_FOUND", "Scene-span endpoint does not exist in its parent.", [sourceLabel(target.source), `${target.parent}:${target.from}..${target.through}`], ["Use scene IDs from the same existing episode."]);
|
|
383
|
-
if (from > through)
|
|
384
|
-
fail("AUTHORING_SPAN_REVERSED", "Scene-span endpoints are reversed in current document order.", [sourceLabel(target.source), `${target.from}..${target.through}`], ["Swap from and through."]);
|
|
385
|
-
if (target.scenes.length === 0)
|
|
386
|
-
fail("AUTHORING_EMPTY_SPAN", "Scene-span replacement cannot be empty.", [sourceLabel(target.source)], ["Include at least one complete scene."]);
|
|
387
|
-
for (const scene of target.scenes)
|
|
388
|
-
assertSceneReferencesMaterialized(scene, target.source);
|
|
389
|
-
return { target, epIndex, from, through };
|
|
390
|
-
});
|
|
391
|
-
assertStrictOrder(resolved.map((item) => ({ coord: [item.epIndex, item.from], source: item.target.source })), "Scene spans are not in document order.");
|
|
392
|
-
for (let index = 1; index < resolved.length; index += 1) {
|
|
393
|
-
const previous = resolved[index - 1];
|
|
394
|
-
const current = resolved[index];
|
|
395
|
-
if (current.epIndex === previous.epIndex && current.from <= previous.through)
|
|
396
|
-
fail("AUTHORING_SPAN_OVERLAP", "Scene spans overlap.", [sourceLabel(current.target.source)], ["Use disjoint scene spans."]);
|
|
397
|
-
}
|
|
398
|
-
const plans = resolved.map(({ target, epIndex, from, through }) => {
|
|
399
|
-
const before = baseline.episodes[epIndex].scenes.slice(from, through + 1);
|
|
400
|
-
return {
|
|
401
|
-
kind: "scene-span",
|
|
402
|
-
address: `${target.parent}/${target.from}..${target.parent}/${target.through}`,
|
|
403
|
-
before: scenesCounts(before),
|
|
404
|
-
after: scenesCounts(target.scenes),
|
|
405
|
-
...idDiff(before.map((scene) => scene.scene_id), target.scenes.map((scene) => scene.scene_id)),
|
|
406
|
-
untouchedSiblings: baseline.episodes[epIndex].scenes.length - before.length,
|
|
407
|
-
};
|
|
408
|
-
});
|
|
409
|
-
const grouped = new Map();
|
|
410
|
-
for (const item of resolved)
|
|
411
|
-
grouped.set(item.epIndex, [...(grouped.get(item.epIndex) ?? []), item]);
|
|
412
|
-
for (const [epIndex, spans] of grouped) {
|
|
413
|
-
for (const { target, from, through } of [...spans].reverse()) {
|
|
414
|
-
script.episodes[epIndex].scenes.splice(from, through - from + 1, ...structuredClone(target.scenes));
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
return plans;
|
|
418
|
-
}
|
|
419
|
-
function applyActionSpans(baseline, script, targets) {
|
|
420
|
-
const resolved = targets.map((target) => {
|
|
421
|
-
const slash = target.parent.indexOf("/");
|
|
422
|
-
if (slash < 1 || slash === target.parent.length - 1)
|
|
423
|
-
fail("AUTHORING_SCENE_ADDRESS_INVALID", "Action-span parent is not a complete scene address.", [sourceLabel(target.source), target.parent], ["Use parent=ep_ID/scn_ID."]);
|
|
424
|
-
const parent = target.parent.slice(0, slash);
|
|
425
|
-
const sceneId = target.parent.slice(slash + 1);
|
|
426
|
-
const [epIndex, scIndex] = sceneCoordinate(baseline, parent, sceneId);
|
|
427
|
-
const scene = baseline.episodes[epIndex].scenes[scIndex];
|
|
428
|
-
if (target.from > target.through)
|
|
429
|
-
fail("AUTHORING_SPAN_REVERSED", "Action-span endpoints are reversed.", [sourceLabel(target.source), `${target.from}..${target.through}`], ["Swap from and through."]);
|
|
430
|
-
if (target.through >= scene.actions.length)
|
|
431
|
-
fail("AUTHORING_SPAN_ENDPOINT_NOT_FOUND", "Action-span endpoint is outside the current scene body.", [sourceLabel(target.source), `${target.from}..${target.through}`, `actions=${scene.actions.length}`], ["Use zero-based endpoints within the current body."]);
|
|
432
|
-
if (target.actions.length === 0)
|
|
433
|
-
fail("AUTHORING_EMPTY_SPAN", "Action-span replacement cannot be empty.", [sourceLabel(target.source)], ["Include at least one action."]);
|
|
434
|
-
return { target, epIndex, scIndex, scene, from: target.from, through: target.through };
|
|
435
|
-
});
|
|
436
|
-
assertStrictOrder(resolved.map((item) => ({ coord: [item.epIndex, item.scIndex, item.from], source: item.target.source })), "Action spans are not in document order.");
|
|
437
|
-
for (let index = 1; index < resolved.length; index += 1) {
|
|
438
|
-
const previous = resolved[index - 1];
|
|
439
|
-
const current = resolved[index];
|
|
440
|
-
if (current.epIndex === previous.epIndex && current.scIndex === previous.scIndex && current.from <= previous.through) {
|
|
441
|
-
fail("AUTHORING_SPAN_OVERLAP", "Action spans overlap.", [sourceLabel(current.target.source)], ["Use disjoint action spans."]);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
const plans = resolved.map(({ target, scene, from, through }) => ({
|
|
445
|
-
kind: "action-span",
|
|
446
|
-
address: `${target.parent}#${from}..${target.parent}#${through}`,
|
|
447
|
-
before: { episodes: 0, scenes: 0, actions: through - from + 1 },
|
|
448
|
-
after: { episodes: 0, scenes: 0, actions: target.actions.length },
|
|
449
|
-
retainedIds: [],
|
|
450
|
-
createdIds: [],
|
|
451
|
-
removedIds: [],
|
|
452
|
-
untouchedSiblings: scene.actions.length - (through - from + 1),
|
|
453
|
-
}));
|
|
454
|
-
const grouped = new Map();
|
|
455
|
-
for (const item of resolved) {
|
|
456
|
-
const key = `${item.epIndex}/${item.scIndex}`;
|
|
457
|
-
grouped.set(key, [...(grouped.get(key) ?? []), item]);
|
|
458
|
-
}
|
|
459
|
-
for (const spans of grouped.values()) {
|
|
460
|
-
for (const { target, epIndex, scIndex, from, through } of [...spans].reverse()) {
|
|
461
|
-
script.episodes[epIndex].scenes[scIndex].actions.splice(from, through - from + 1, ...structuredClone(target.actions));
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
return plans;
|
|
465
|
-
}
|
|
466
|
-
function assertUniqueStructureIds(script) {
|
|
467
|
-
const episodeIds = new Set();
|
|
468
|
-
const sceneIds = new Set();
|
|
469
|
-
for (const episode of script.episodes) {
|
|
470
|
-
if (episodeIds.has(episode.episode_id))
|
|
471
|
-
fail("AUTHORING_EPISODE_ID_CONFLICT", "Episode ID occurs more than once.", [episode.episode_id], ["Use globally unique episode IDs."]);
|
|
472
|
-
episodeIds.add(episode.episode_id);
|
|
473
|
-
for (const scene of episode.scenes) {
|
|
474
|
-
if (sceneIds.has(scene.scene_id))
|
|
475
|
-
fail("AUTHORING_SCENE_ID_CONFLICT", "Scene ID occurs more than once.", [scene.scene_id], ["Use globally unique stable scene IDs."]);
|
|
476
|
-
sceneIds.add(scene.scene_id);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
function stableValidationPath(path, script) {
|
|
481
|
-
const episodeMatch = /^\$\.episodes\[(\d+)]/.exec(path);
|
|
482
|
-
if (episodeMatch === null)
|
|
483
|
-
return path;
|
|
484
|
-
const episode = script.episodes[Number(episodeMatch[1])];
|
|
485
|
-
if (episode === undefined)
|
|
486
|
-
return path;
|
|
487
|
-
let stable = path.replace(episodeMatch[0], `$.episodes[${episode.episode_id}]`);
|
|
488
|
-
const sceneMatch = /^(\$\.episodes\[\d+]\.scenes)\[(\d+)]/.exec(path);
|
|
489
|
-
if (sceneMatch !== null) {
|
|
490
|
-
const scene = episode.scenes[Number(sceneMatch[2])];
|
|
491
|
-
if (scene !== undefined) {
|
|
492
|
-
const oldPrefix = `${episodeMatch[0]}.scenes[${sceneMatch[2]}]`;
|
|
493
|
-
stable = path.replace(oldPrefix, `$.episodes[${episode.episode_id}].scenes[${scene.scene_id}]`);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
return stable;
|
|
497
|
-
}
|
|
498
|
-
function validationKey(issue, script) {
|
|
499
|
-
return `${issue.code}\u0000${stableValidationPath(issue.path, script)}\u0000${issue.message}`;
|
|
500
|
-
}
|
|
501
|
-
function authoredScope(authored) {
|
|
502
|
-
const scope = {
|
|
503
|
-
episodeIds: new Set(),
|
|
504
|
-
sceneIds: new Set(),
|
|
505
|
-
fullEpisodeIds: new Set(),
|
|
506
|
-
fullSceneIds: new Set(),
|
|
507
|
-
actionSpans: [],
|
|
508
|
-
};
|
|
509
|
-
const includeScene = (scene) => {
|
|
510
|
-
scope.sceneIds.add(scene.scene_id);
|
|
511
|
-
scope.fullSceneIds.add(scene.scene_id);
|
|
512
|
-
};
|
|
513
|
-
const includeEpisode = (episode) => {
|
|
514
|
-
scope.episodeIds.add(episode.episode_id);
|
|
515
|
-
scope.fullEpisodeIds.add(episode.episode_id);
|
|
516
|
-
for (const scene of episode.scenes)
|
|
517
|
-
includeScene(scene);
|
|
518
|
-
};
|
|
519
|
-
for (const target of authored) {
|
|
520
|
-
if (target.kind === "script") {
|
|
521
|
-
for (const episode of target.episodes)
|
|
522
|
-
includeEpisode(episode);
|
|
523
|
-
}
|
|
524
|
-
else if (target.kind === "episode")
|
|
525
|
-
includeEpisode(target.value);
|
|
526
|
-
else if (target.kind === "episode-span") {
|
|
527
|
-
for (const episode of target.episodes)
|
|
528
|
-
includeEpisode(episode);
|
|
529
|
-
}
|
|
530
|
-
else if (target.kind === "scene")
|
|
531
|
-
includeScene(target.value);
|
|
532
|
-
else if (target.kind === "scene-span") {
|
|
533
|
-
for (const scene of target.scenes)
|
|
534
|
-
includeScene(scene);
|
|
535
|
-
}
|
|
536
|
-
else {
|
|
537
|
-
scope.sceneIds.add(target.parent.split("/")[1] ?? "");
|
|
538
|
-
scope.actionSpans.push(target);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return scope;
|
|
542
|
-
}
|
|
543
|
-
function authoredCompletenessWarnings(before, after, scope) {
|
|
544
|
-
const warnings = [];
|
|
545
|
-
const beforeEpisodes = new Map(before?.episodes.map((episode) => [episode.episode_id, episode]) ?? []);
|
|
546
|
-
const beforeScenes = new Map();
|
|
547
|
-
for (const episode of before?.episodes ?? []) {
|
|
548
|
-
for (const scene of episode.scenes)
|
|
549
|
-
beforeScenes.set(scene.scene_id, scene);
|
|
550
|
-
}
|
|
551
|
-
const afterEpisodes = new Map(after.episodes.map((episode) => [episode.episode_id, episode]));
|
|
552
|
-
const afterScenes = new Map();
|
|
553
|
-
for (const episode of after.episodes) {
|
|
554
|
-
for (const scene of episode.scenes)
|
|
555
|
-
afterScenes.set(scene.scene_id, { episodeId: episode.episode_id, scene });
|
|
556
|
-
}
|
|
557
|
-
for (const episodeId of scope.fullEpisodeIds) {
|
|
558
|
-
const episode = afterEpisodes.get(episodeId);
|
|
559
|
-
if (episode === undefined || episode.scenes.length > 0)
|
|
560
|
-
continue;
|
|
561
|
-
const cleared = (beforeEpisodes.get(episodeId)?.scenes.length ?? 0) > 0;
|
|
562
|
-
warnings.push({
|
|
563
|
-
code: cleared ? "authoring_episode_cleared" : "authoring_empty_episode",
|
|
564
|
-
path: `$.episodes[${episodeId}]`,
|
|
565
|
-
message: cleared
|
|
566
|
-
? `authoring replaced episode ${episodeId} with an empty scene list`
|
|
567
|
-
: `authored episode ${episodeId} has no scenes`,
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
for (const sceneId of scope.fullSceneIds) {
|
|
571
|
-
const located = afterScenes.get(sceneId);
|
|
572
|
-
if (located === undefined)
|
|
573
|
-
continue;
|
|
574
|
-
const scenePath = `$.episodes[${located.episodeId}].scenes[${sceneId}]`;
|
|
575
|
-
if (located.scene.actions.length === 0) {
|
|
576
|
-
const cleared = (beforeScenes.get(sceneId)?.actions.length ?? 0) > 0;
|
|
577
|
-
warnings.push({
|
|
578
|
-
code: cleared ? "authoring_scene_cleared" : "authoring_empty_scene",
|
|
579
|
-
path: scenePath,
|
|
580
|
-
message: cleared
|
|
581
|
-
? `authoring replaced scene ${sceneId} with an empty body`
|
|
582
|
-
: `authored scene ${sceneId} has an empty body`,
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
located.scene.actions.forEach((action, index) => {
|
|
586
|
-
if (action.content.trim() !== "")
|
|
587
|
-
return;
|
|
588
|
-
warnings.push({
|
|
589
|
-
code: "authoring_empty_action_content",
|
|
590
|
-
path: `${scenePath}.actions[${index}]`,
|
|
591
|
-
message: "authored action content is empty",
|
|
592
|
-
});
|
|
593
|
-
});
|
|
594
|
-
}
|
|
595
|
-
for (const target of scope.actionSpans) {
|
|
596
|
-
target.actions.forEach((action, index) => {
|
|
597
|
-
if (action.content.trim() !== "")
|
|
598
|
-
return;
|
|
599
|
-
warnings.push({
|
|
600
|
-
code: "authoring_empty_action_content",
|
|
601
|
-
path: `${target.parent}#replacement[${index}]`,
|
|
602
|
-
message: "authored action-span replacement contains an action with empty content",
|
|
603
|
-
});
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
return warnings;
|
|
607
|
-
}
|
|
608
|
-
function assertValidationAllowed(before, after, authored) {
|
|
609
|
-
const result = validateScriptV3(after);
|
|
610
|
-
const scope = authoredScope(authored);
|
|
611
|
-
const withWarnings = () => ({
|
|
612
|
-
...result,
|
|
613
|
-
warnings: [...result.warnings, ...authoredCompletenessWarnings(before, after, scope)],
|
|
614
|
-
});
|
|
615
|
-
if (result.ok || (before !== null && semanticEqual(before, after)))
|
|
616
|
-
return withWarnings();
|
|
617
|
-
const beforeKeys = new Set(before === null
|
|
618
|
-
? []
|
|
619
|
-
: validateScriptV3(before).errors.map((issue) => validationKey(issue, before)));
|
|
620
|
-
const blocking = result.errors.filter((issue) => {
|
|
621
|
-
if (!beforeKeys.has(validationKey(issue, after)))
|
|
622
|
-
return true;
|
|
623
|
-
const episodeMatch = /^\$\.episodes\[(\d+)]/.exec(issue.path);
|
|
624
|
-
if (!episodeMatch)
|
|
625
|
-
return false;
|
|
626
|
-
const episode = after.episodes[Number(episodeMatch[1])];
|
|
627
|
-
if (episode === undefined)
|
|
628
|
-
return true;
|
|
629
|
-
if (scope.episodeIds.has(episode.episode_id))
|
|
630
|
-
return true;
|
|
631
|
-
const sceneMatch = /^\$\.episodes\[\d+]\.scenes\[(\d+)]/.exec(issue.path);
|
|
632
|
-
const scene = sceneMatch === null ? undefined : episode.scenes[Number(sceneMatch[1])];
|
|
633
|
-
return scene !== undefined && scope.sceneIds.has(scene.scene_id);
|
|
634
|
-
});
|
|
635
|
-
if (blocking.length > 0) {
|
|
636
|
-
fail("AUTHORING_VALIDATION_FAILED", "The proposed script has blocking validation errors.", blocking.map((issue) => `${issue.path}: ${issue.code} ${issue.message}`), ["Repair the authoring source and rerun the plan."]);
|
|
637
|
-
}
|
|
638
|
-
return withWarnings();
|
|
639
|
-
}
|
|
640
|
-
function orphanAssets(script) {
|
|
641
|
-
const referenced = new Set();
|
|
642
|
-
for (const episode of script.episodes) {
|
|
643
|
-
for (const scene of episode.scenes) {
|
|
644
|
-
if (scene.location !== null)
|
|
645
|
-
referenced.add(scene.location.location_id);
|
|
646
|
-
for (const actor of scene.actors)
|
|
647
|
-
referenced.add(actor.actor_id);
|
|
648
|
-
for (const prop of scene.props)
|
|
649
|
-
referenced.add(prop.prop_id);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
return [
|
|
653
|
-
...script.actors.map((asset) => asset.actor_id),
|
|
654
|
-
...script.locations.map((asset) => asset.location_id),
|
|
655
|
-
...script.props.map((asset) => asset.prop_id),
|
|
656
|
-
].filter((id) => !referenced.has(id));
|
|
657
|
-
}
|
|
658
|
-
function buildScriptTarget(document) {
|
|
659
|
-
const target = document.targets[0];
|
|
660
|
-
if (target?.kind !== "script")
|
|
661
|
-
fail("AUTHORING_TARGET_MODE", "Script create requires exactly one script target.", [], ["Use a single <script> block."], EXIT_USAGE);
|
|
662
|
-
for (const episode of target.episodes)
|
|
663
|
-
assertEpisodeReferencesMaterialized(episode, target.source);
|
|
664
|
-
const script = {
|
|
665
|
-
version: 3,
|
|
666
|
-
title: target.title,
|
|
667
|
-
worldview: target.worldview,
|
|
668
|
-
style: target.style,
|
|
669
|
-
actors: [],
|
|
670
|
-
locations: [],
|
|
671
|
-
props: [],
|
|
672
|
-
episodes: structuredClone(target.episodes),
|
|
673
|
-
};
|
|
674
|
-
if (target.worldviewRaw !== undefined)
|
|
675
|
-
script.worldview_raw = target.worldviewRaw;
|
|
676
|
-
if (target.synopsis !== undefined)
|
|
677
|
-
script.synopsis = target.synopsis;
|
|
678
|
-
if (target.logline !== undefined)
|
|
679
|
-
script.logline = target.logline;
|
|
680
|
-
if (target.theme !== undefined)
|
|
681
|
-
script.theme = target.theme;
|
|
682
|
-
if (target.mainCharacters !== undefined)
|
|
683
|
-
script.main_characters = structuredClone(target.mainCharacters);
|
|
684
|
-
if (target.extend !== undefined)
|
|
685
|
-
script.extend = structuredClone(target.extend);
|
|
686
|
-
const declarations = applyDeclarations(script, document.declarations);
|
|
687
|
-
assertUniqueStructureIds(script);
|
|
688
|
-
return { script, declarations };
|
|
689
|
-
}
|
|
690
|
-
export function applyAuthoring(current, document, mode) {
|
|
691
|
-
if (document.targetKind === "script") {
|
|
692
|
-
if (mode !== "create")
|
|
693
|
-
fail("AUTHORING_TARGET_MODE", "Script targets support create only.", [mode], ["Use --create."], EXIT_USAGE);
|
|
694
|
-
const built = buildScriptTarget(document);
|
|
695
|
-
const script = built.script;
|
|
696
|
-
if (current !== null && !semanticEqual(current, script)) {
|
|
697
|
-
fail("AUTHORING_CREATE_CONFLICT", "The script target already exists with different content.", ["script"], ["Use episode replacement for an existing script, or write an identical script for a no-op retry."]);
|
|
698
|
-
}
|
|
699
|
-
const declarations = current === null
|
|
700
|
-
? built.declarations
|
|
701
|
-
: {
|
|
702
|
-
createdAssets: [],
|
|
703
|
-
existingAssets: [...built.declarations.existingAssets, ...built.declarations.createdAssets],
|
|
704
|
-
createdStates: [],
|
|
705
|
-
existingStates: [...built.declarations.existingStates, ...built.declarations.createdStates],
|
|
706
|
-
};
|
|
707
|
-
const validation = assertValidationAllowed(current, script, document.targets);
|
|
708
|
-
return {
|
|
709
|
-
script,
|
|
710
|
-
changed: current === null || !semanticEqual(current, script),
|
|
711
|
-
declarations,
|
|
712
|
-
targets: [{
|
|
713
|
-
kind: "script",
|
|
714
|
-
address: "global",
|
|
715
|
-
before: current === null ? { episodes: 0, scenes: 0, actions: 0 } : episodesCounts(current.episodes),
|
|
716
|
-
after: episodesCounts(script.episodes),
|
|
717
|
-
...idDiff(current?.episodes.map((episode) => episode.episode_id) ?? [], script.episodes.map((episode) => episode.episode_id)),
|
|
718
|
-
untouchedSiblings: 0,
|
|
719
|
-
}],
|
|
720
|
-
retainedOrphanAssets: orphanAssets(script),
|
|
721
|
-
validation,
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
if (current === null) {
|
|
725
|
-
fail("AUTHORING_SCRIPT_NOT_FOUND", "A local Script v3 file is required for this target kind.", ["<missing>"], ["Create a script first or select an existing --script-path."]);
|
|
726
|
-
}
|
|
727
|
-
if ((document.targetKind === "episode-span" || document.targetKind === "scene-span" || document.targetKind === "action-span") && mode !== "replace") {
|
|
728
|
-
fail("AUTHORING_TARGET_MODE", `${document.targetKind} supports replace only.`, [mode], ["Use --replace."], EXIT_USAGE);
|
|
729
|
-
}
|
|
730
|
-
const baseline = structuredClone(current);
|
|
731
|
-
const script = structuredClone(current);
|
|
732
|
-
const declarations = applyDeclarations(script, document.declarations);
|
|
733
|
-
let targets;
|
|
734
|
-
switch (document.targetKind) {
|
|
735
|
-
case "episode": {
|
|
736
|
-
const selected = document.targets.flatMap((target) => target.kind === "episode" ? [target] : []);
|
|
737
|
-
if (selected.length !== document.targets.length)
|
|
738
|
-
fail("AUTHORING_TARGET_MODE", "Authoring targets are not homogeneous.", [], ["Keep one target kind per file."], EXIT_USAGE);
|
|
739
|
-
targets = applyEpisodeTargets(baseline, script, selected, mode);
|
|
740
|
-
break;
|
|
741
|
-
}
|
|
742
|
-
case "scene": {
|
|
743
|
-
const selected = document.targets.flatMap((target) => target.kind === "scene" ? [target] : []);
|
|
744
|
-
if (selected.length !== document.targets.length)
|
|
745
|
-
fail("AUTHORING_TARGET_MODE", "Authoring targets are not homogeneous.", [], ["Keep one target kind per file."], EXIT_USAGE);
|
|
746
|
-
targets = applySceneTargets(baseline, script, selected, mode);
|
|
747
|
-
break;
|
|
748
|
-
}
|
|
749
|
-
case "episode-span": {
|
|
750
|
-
const selected = document.targets.flatMap((target) => target.kind === "episode-span" ? [target] : []);
|
|
751
|
-
if (selected.length !== document.targets.length)
|
|
752
|
-
fail("AUTHORING_TARGET_MODE", "Authoring targets are not homogeneous.", [], ["Keep one target kind per file."], EXIT_USAGE);
|
|
753
|
-
targets = applyEpisodeSpans(baseline, script, selected);
|
|
754
|
-
break;
|
|
755
|
-
}
|
|
756
|
-
case "scene-span": {
|
|
757
|
-
const selected = document.targets.flatMap((target) => target.kind === "scene-span" ? [target] : []);
|
|
758
|
-
if (selected.length !== document.targets.length)
|
|
759
|
-
fail("AUTHORING_TARGET_MODE", "Authoring targets are not homogeneous.", [], ["Keep one target kind per file."], EXIT_USAGE);
|
|
760
|
-
targets = applySceneSpans(baseline, script, selected);
|
|
761
|
-
break;
|
|
762
|
-
}
|
|
763
|
-
case "action-span": {
|
|
764
|
-
const selected = document.targets.flatMap((target) => target.kind === "action-span" ? [target] : []);
|
|
765
|
-
if (selected.length !== document.targets.length)
|
|
766
|
-
fail("AUTHORING_TARGET_MODE", "Authoring targets are not homogeneous.", [], ["Keep one target kind per file."], EXIT_USAGE);
|
|
767
|
-
targets = applyActionSpans(baseline, script, selected);
|
|
768
|
-
break;
|
|
769
|
-
}
|
|
770
|
-
default:
|
|
771
|
-
fail("AUTHORING_TARGET_MODE", "Unsupported authoring target.", [document.targetKind], ["Use a supported homogeneous target kind."]);
|
|
772
|
-
}
|
|
773
|
-
assertUniqueStructureIds(script);
|
|
774
|
-
const validation = assertValidationAllowed(current, script, document.targets);
|
|
775
|
-
return {
|
|
776
|
-
script,
|
|
777
|
-
changed: !semanticEqual(current, script),
|
|
778
|
-
declarations,
|
|
779
|
-
targets,
|
|
780
|
-
retainedOrphanAssets: orphanAssets(script),
|
|
781
|
-
validation,
|
|
782
|
-
};
|
|
783
|
-
}
|
|
1
|
+
export * from "./v3/apply.js";
|
|
784
2
|
//# sourceMappingURL=apply.js.map
|