@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,12 +1,19 @@
|
|
|
1
|
-
import { CliError, EXIT_NEEDS_AGENT, EXIT_OK, EXIT_USAGE, } from "../../common.js";
|
|
2
|
-
import {
|
|
1
|
+
import { CliError, EXIT_INPUT, EXIT_NEEDS_AGENT, 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 { requireScriptV4 } from "../../domain/script/v4/parse.js";
|
|
5
|
+
import { validateScriptV4 } from "../../domain/script/v4/validation.js";
|
|
3
6
|
import { sceneRefs } from "../../domain/script/scene-refs.js";
|
|
4
7
|
import { isDangerousRegex, MAX_GREP_PATTERN_LEN, parseInSelector, selectorSingleActionPoint, WHOLE_SCRIPT, } from "../../domain/script/selector.js";
|
|
5
8
|
import { parseAnyAddress, } from "../../domain/script/address.js";
|
|
9
|
+
import { parseV4Address } from "../../domain/script/v4/address.js";
|
|
6
10
|
import { summarizeIssues } from "../../domain/script/text-util.js";
|
|
7
11
|
import { sortDeep } from "../../domain/script/text-util.js";
|
|
8
12
|
import { asList, idNum, isDict, strOf, } from "../../domain/script/shared.js";
|
|
9
13
|
import { loadScriptForEdit, validateSession, saveScriptSession, syncValidationResult, scriptSourceText, } from "./session.js";
|
|
14
|
+
import { resolveActionTargetsV4 } from "./v4/queries.js";
|
|
15
|
+
import { applyVersionedMutations } from "./dispatch.js";
|
|
16
|
+
import { assertInsertCommandFlags, assertMoveCommandFlags, assertSceneRefCommandFlags, } from "./command-constraints.js";
|
|
10
17
|
export function tokenizeLine(line) {
|
|
11
18
|
const out = [];
|
|
12
19
|
let cur = "";
|
|
@@ -75,6 +82,7 @@ export const DO_BOOL_FLAGS = {
|
|
|
75
82
|
replace: new Set(["all", "regex"]),
|
|
76
83
|
transition: new Set(["clear"]),
|
|
77
84
|
emotion: new Set(["clear"]),
|
|
85
|
+
parenthetical: new Set(["remove"]),
|
|
78
86
|
"scene-ref": new Set(["clear", "remove", "append"]),
|
|
79
87
|
delete: new Set(["force"]),
|
|
80
88
|
extend: new Set(["clear", "json-value"]),
|
|
@@ -82,6 +90,8 @@ export const DO_BOOL_FLAGS = {
|
|
|
82
90
|
export const DO_REPEAT_FLAGS = {
|
|
83
91
|
alias: new Set(["add", "remove"]),
|
|
84
92
|
"add-actor": new Set(["alias"]),
|
|
93
|
+
"scene-ref": new Set(["state"]),
|
|
94
|
+
insert: new Set(["state"]),
|
|
85
95
|
};
|
|
86
96
|
function pushFlag(flags, repeats, name, val) {
|
|
87
97
|
if (repeats.has(name)) {
|
|
@@ -305,9 +315,37 @@ export function dialogueTemplate(f) {
|
|
|
305
315
|
// consumes). `do` = the human/agent-friendly notation for those ops: no JSON,
|
|
306
316
|
// no field-name guessing — the verbs you already type. Multipolar verbs
|
|
307
317
|
// (delete/move/insert/merge/describe) pick their op by the address kind.
|
|
308
|
-
|
|
318
|
+
function repeatedDoFlag(raw) {
|
|
319
|
+
if (raw === undefined)
|
|
320
|
+
return [];
|
|
321
|
+
return Array.isArray(raw) ? raw.map(strOf) : [strOf(raw)];
|
|
322
|
+
}
|
|
323
|
+
function doInsertFlags(flags) {
|
|
324
|
+
return {
|
|
325
|
+
type: flags["type"],
|
|
326
|
+
content: flags["content"],
|
|
327
|
+
emotion: flags["emotion"],
|
|
328
|
+
parenthetical: flags["parenthetical"],
|
|
329
|
+
actionId: flags["action-id"],
|
|
330
|
+
at: flags["at"],
|
|
331
|
+
before: flags["before"],
|
|
332
|
+
after: flags["after"],
|
|
333
|
+
actor: flags["actor"],
|
|
334
|
+
speaker: flags["speaker"],
|
|
335
|
+
speakerState: flags["speaker-state"],
|
|
336
|
+
kind: flags["kind"],
|
|
337
|
+
label: flags["label"],
|
|
338
|
+
location: flags["location"],
|
|
339
|
+
time: flags["time"],
|
|
340
|
+
space: flags["space"],
|
|
341
|
+
sceneId: flags["scene-id"],
|
|
342
|
+
states: repeatedDoFlag(flags["state"]),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
export function lineToOp(verb, args, flags, scriptVersion = 3) {
|
|
309
346
|
const a0 = strOf(args[0]);
|
|
310
347
|
const a1 = strOf(args[1]);
|
|
348
|
+
const parseAddress = (raw) => scriptVersion === 4 ? parseV4Address(raw) : parseAnyAddress(raw);
|
|
311
349
|
switch (verb) {
|
|
312
350
|
case "replace":
|
|
313
351
|
return flags["regex"]
|
|
@@ -320,20 +358,52 @@ export function lineToOp(verb, args, flags) {
|
|
|
320
358
|
case "transition":
|
|
321
359
|
return { ...transitionTemplate(a1, { process: flags["process"], contrast: flags["contrast"], clear: Boolean(flags["clear"]) }), at: a0 };
|
|
322
360
|
case "emotion":
|
|
361
|
+
if (scriptVersion === 4)
|
|
362
|
+
throw doErr("emotion belongs to Script v3; use parenthetical for Script v4");
|
|
323
363
|
return { ...emotionTemplate({ emotion: args[1], clear: Boolean(flags["clear"]) }), at: a0 };
|
|
324
|
-
case "
|
|
364
|
+
case "parenthetical":
|
|
365
|
+
if (scriptVersion === 3)
|
|
366
|
+
throw doErr("parenthetical belongs to Script v4; use emotion for Script v3");
|
|
367
|
+
if (Boolean(flags["remove"]) === (flags["set"] !== undefined)) {
|
|
368
|
+
throw doErr("parenthetical needs exactly one of --set <text> or --remove");
|
|
369
|
+
}
|
|
370
|
+
return Boolean(flags["remove"])
|
|
371
|
+
? { op: "action.parenthetical.remove", at: a0 }
|
|
372
|
+
: { op: "action.parenthetical.set", at: a0, parenthetical: strOf(flags["set"]) };
|
|
373
|
+
case "scene-ref": {
|
|
374
|
+
const sceneRefFlags = {
|
|
375
|
+
states: repeatedDoFlag(flags["state"]),
|
|
376
|
+
clear: Boolean(flags["clear"]),
|
|
377
|
+
remove: Boolean(flags["remove"]),
|
|
378
|
+
append: Boolean(flags["append"]),
|
|
379
|
+
occurrence: flags["occurrence"],
|
|
380
|
+
};
|
|
381
|
+
assertSceneRefCommandFlags(scriptVersion, sceneRefFlags);
|
|
382
|
+
if (scriptVersion === 4) {
|
|
383
|
+
return sceneRefFlags.remove
|
|
384
|
+
? { op: "scene.ref.remove", at: a0, target: a1 }
|
|
385
|
+
: { op: "scene.ref.set", at: a0, target: a1, state_ids: sceneRefFlags.states };
|
|
386
|
+
}
|
|
325
387
|
return {
|
|
326
388
|
...contextTemplate(a1, {
|
|
327
|
-
state:
|
|
328
|
-
clear:
|
|
329
|
-
remove:
|
|
330
|
-
append:
|
|
331
|
-
occurrence:
|
|
389
|
+
state: sceneRefFlags.states[0],
|
|
390
|
+
clear: sceneRefFlags.clear,
|
|
391
|
+
remove: sceneRefFlags.remove,
|
|
392
|
+
append: sceneRefFlags.append,
|
|
393
|
+
occurrence: sceneRefFlags.occurrence,
|
|
332
394
|
}),
|
|
333
395
|
at: a0,
|
|
334
396
|
};
|
|
397
|
+
}
|
|
335
398
|
case "dialogue":
|
|
336
|
-
|
|
399
|
+
if (scriptVersion === 3 && flags["state"] !== undefined) {
|
|
400
|
+
throw doErr("dialogue --state belongs to Script v4");
|
|
401
|
+
}
|
|
402
|
+
return {
|
|
403
|
+
...dialogueTemplate({ actor: flags["actor"], kind: flags["kind"], label: flags["label"] }),
|
|
404
|
+
...(scriptVersion === 4 && flags["state"] !== undefined ? { state_id: flags["state"] } : {}),
|
|
405
|
+
at: a0,
|
|
406
|
+
};
|
|
337
407
|
case "rename":
|
|
338
408
|
return { op: "asset.rename", target: a0, name: a1 };
|
|
339
409
|
case "role":
|
|
@@ -346,14 +416,15 @@ export function lineToOp(verb, args, flags) {
|
|
|
346
416
|
if (args.length > 2)
|
|
347
417
|
throw doErr("synopsis text with spaces must be quoted");
|
|
348
418
|
if (args.length === 1) {
|
|
349
|
-
if (/^ep_/.test(a0))
|
|
419
|
+
if (/^ep_/.test(a0) || /^ep[1-9A-HJ-NP-Za-km-z]{6}$/.test(a0)) {
|
|
350
420
|
throw doErr(`synopsis for ${a0} needs text`);
|
|
421
|
+
}
|
|
351
422
|
return { op: "meta.synopsis.set", synopsis: a0 };
|
|
352
423
|
}
|
|
353
|
-
const addr =
|
|
424
|
+
const addr = parseAddress(a0);
|
|
354
425
|
if (addr.kind !== "episode")
|
|
355
426
|
throw doErr(`synopsis target must be an episode id or omitted for global (${a0})`);
|
|
356
|
-
return { op: "episode.synopsis.set", episode_id: addr.episodeId, synopsis: a1 };
|
|
427
|
+
return { op: "episode.synopsis.set", episode_id: "id" in addr ? addr.id : addr.episodeId, synopsis: a1 };
|
|
357
428
|
}
|
|
358
429
|
case "alias": {
|
|
359
430
|
const add = flags["add"] ?? [];
|
|
@@ -365,7 +436,7 @@ export function lineToOp(verb, args, flags) {
|
|
|
365
436
|
throw doErr("alias needs --add <alias> or --remove <alias>");
|
|
366
437
|
}
|
|
367
438
|
case "describe": {
|
|
368
|
-
const addr =
|
|
439
|
+
const addr = parseAddress(a0);
|
|
369
440
|
if (addr.kind === "state")
|
|
370
441
|
return { op: "state.describe", target: a0, description: a1 };
|
|
371
442
|
if (addr.kind === "asset")
|
|
@@ -373,7 +444,8 @@ export function lineToOp(verb, args, flags) {
|
|
|
373
444
|
throw doErr(`describe cannot operate on a ${addr.kind} address (${a0}); use an asset or asset/state target`);
|
|
374
445
|
}
|
|
375
446
|
case "extend": {
|
|
376
|
-
|
|
447
|
+
if (a0 !== "global")
|
|
448
|
+
parseAddress(a0);
|
|
377
449
|
if (flags["clear"]) {
|
|
378
450
|
if (args.length >= 3)
|
|
379
451
|
throw doErr("extend --clear takes no value (drop --clear to set, or drop the value to delete)");
|
|
@@ -399,37 +471,52 @@ export function lineToOp(verb, args, flags) {
|
|
|
399
471
|
case "state-delete":
|
|
400
472
|
return { op: "state.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
|
|
401
473
|
case "add-actor":
|
|
402
|
-
return { op: "actor.add", name: a0, role_type: flags["role"], description: flags["description"], aliases: flags["alias"] ?? undefined };
|
|
474
|
+
return { op: "actor.add", actor_id: flags["id"], name: a0, role_type: flags["role"], description: flags["description"], aliases: flags["alias"] ?? undefined };
|
|
403
475
|
case "add-location":
|
|
404
|
-
return { op: "location.add", name: a0, description: flags["description"] };
|
|
476
|
+
return { op: "location.add", location_id: flags["id"], name: a0, description: flags["description"] };
|
|
405
477
|
case "add-prop":
|
|
406
|
-
return { op: "prop.add", name: a0, description: flags["description"] };
|
|
478
|
+
return { op: "prop.add", prop_id: flags["id"], name: a0, description: flags["description"] };
|
|
407
479
|
case "add-episode":
|
|
408
480
|
return { op: "episode.add", title: flags["title"], episode_id: flags["id"] };
|
|
409
481
|
case "importance":
|
|
410
482
|
return { op: "importance.set", target: a0, importance: a1 };
|
|
411
483
|
case "split":
|
|
412
|
-
return
|
|
484
|
+
return scriptVersion === 4
|
|
485
|
+
? { op: "scene.split", at: a0, at_action: flags["at"], new_scene_id: flags["new-scene-id"] }
|
|
486
|
+
: { op: "scene.split", at: a0, at_index: Number(flags["at"]), new_scene_id: flags["new-scene-id"] };
|
|
413
487
|
case "delete": {
|
|
414
|
-
const addr =
|
|
488
|
+
const addr = parseAddress(a0);
|
|
415
489
|
if (addr.kind === "action")
|
|
416
490
|
return { op: "action.delete", at: a0 };
|
|
417
491
|
if (addr.kind === "scene")
|
|
418
492
|
return { op: "scene.delete", at: a0, force: Boolean(flags["force"]) };
|
|
493
|
+
if (addr.kind === "state")
|
|
494
|
+
return { op: "state.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
|
|
419
495
|
if (addr.kind === "asset")
|
|
420
496
|
return { op: "asset.delete", target: a0, strategy: flags["strategy"], replacement: flags["replacement"] };
|
|
421
|
-
throw doErr(`delete cannot operate on a ${addr.kind} address (${a0})
|
|
497
|
+
throw doErr(`delete cannot operate on a ${addr.kind} address (${a0})`);
|
|
422
498
|
}
|
|
423
499
|
case "move": {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
500
|
+
assertMoveCommandFlags(scriptVersion, {
|
|
501
|
+
at: flags["at"],
|
|
502
|
+
before: flags["before"],
|
|
503
|
+
after: flags["after"],
|
|
504
|
+
});
|
|
505
|
+
const addr = parseAddress(a0);
|
|
506
|
+
if (addr.kind === "scene") {
|
|
507
|
+
return scriptVersion === 4
|
|
508
|
+
? { op: "scene.move", at: a0, to: a1, before: flags["before"], after: flags["after"] }
|
|
509
|
+
: { op: "scene.move", at: a0, to: a1, at_index: flags["at"] };
|
|
510
|
+
}
|
|
511
|
+
if (addr.kind === "action") {
|
|
512
|
+
return scriptVersion === 4
|
|
513
|
+
? { op: "action.move", at: a0, to: a1, before: flags["before"], after: flags["after"] }
|
|
514
|
+
: { op: "action.move", at: a0, to: a1 };
|
|
515
|
+
}
|
|
429
516
|
throw doErr(`move cannot operate on a ${addr.kind} address (${a0}); move an action or a scene`);
|
|
430
517
|
}
|
|
431
518
|
case "merge": {
|
|
432
|
-
const addr =
|
|
519
|
+
const addr = parseAddress(a0);
|
|
433
520
|
if (addr.kind === "scene")
|
|
434
521
|
return { op: "scene.merge", from: a0, into: strOf(flags["into"]) };
|
|
435
522
|
if (addr.kind === "asset")
|
|
@@ -437,12 +524,46 @@ export function lineToOp(verb, args, flags) {
|
|
|
437
524
|
throw doErr(`merge cannot operate on a ${addr.kind} address (${a0}); merge two assets or two scenes`);
|
|
438
525
|
}
|
|
439
526
|
case "insert": {
|
|
440
|
-
const addr =
|
|
527
|
+
const addr = parseAddress(a0);
|
|
528
|
+
const insertFlags = doInsertFlags(flags);
|
|
441
529
|
if (addr.kind === "episode") {
|
|
442
|
-
|
|
530
|
+
assertInsertCommandFlags(scriptVersion, "scene", insertFlags);
|
|
531
|
+
return {
|
|
532
|
+
op: "scene.insert",
|
|
533
|
+
at: a0,
|
|
534
|
+
location: flags["location"],
|
|
535
|
+
time: flags["time"],
|
|
536
|
+
space: flags["space"],
|
|
537
|
+
...(scriptVersion === 4
|
|
538
|
+
? { location_state_ids: insertFlags.states, before: flags["before"], after: flags["after"] }
|
|
539
|
+
: { at_index: flags["at"], before: flags["before"], after: flags["after"] }),
|
|
540
|
+
scene_id: flags["scene-id"],
|
|
541
|
+
};
|
|
443
542
|
}
|
|
444
543
|
if (addr.kind === "scene") {
|
|
445
|
-
|
|
544
|
+
assertInsertCommandFlags(scriptVersion, "action", insertFlags);
|
|
545
|
+
return {
|
|
546
|
+
op: "action.insert",
|
|
547
|
+
at: a0,
|
|
548
|
+
type: flags["type"],
|
|
549
|
+
content: flags["content"],
|
|
550
|
+
before: flags["before"],
|
|
551
|
+
after: flags["after"],
|
|
552
|
+
actor_id: flags["actor"],
|
|
553
|
+
kind: flags["kind"],
|
|
554
|
+
label: flags["label"],
|
|
555
|
+
...(scriptVersion === 4
|
|
556
|
+
? {
|
|
557
|
+
action_id: flags["action-id"],
|
|
558
|
+
state_id: flags["speaker-state"],
|
|
559
|
+
parenthetical: flags["parenthetical"],
|
|
560
|
+
}
|
|
561
|
+
: {
|
|
562
|
+
at_index: flags["at"],
|
|
563
|
+
speaker_id: flags["speaker"],
|
|
564
|
+
emotion: flags["emotion"],
|
|
565
|
+
}),
|
|
566
|
+
};
|
|
446
567
|
}
|
|
447
568
|
throw doErr(`insert needs ep_NNN (scene insert) or ep_NNN/scn_NNN (action insert), got a ${addr.kind} address (${a0})`);
|
|
448
569
|
}
|
|
@@ -519,22 +640,355 @@ export const SKIPPABLE_EDIT_CODES = new Set([
|
|
|
519
640
|
"FROM_TEXT_NOT_FOUND",
|
|
520
641
|
"OVERLAP_DIALOGUE_UNSUPPORTED",
|
|
521
642
|
]);
|
|
643
|
+
export function applyPatchOperationsForSession(session, source, operations) {
|
|
644
|
+
return applyVersionedMutations(session.version, session.script, source, operations);
|
|
645
|
+
}
|
|
646
|
+
function v4Counts(script) {
|
|
647
|
+
return {
|
|
648
|
+
episodes: script.episodes.length,
|
|
649
|
+
scenes: script.episodes.reduce((sum, episode) => sum + episode.scenes.length, 0),
|
|
650
|
+
actions: script.episodes.reduce((sum, episode) => sum + episode.scenes.reduce((sceneSum, scene) => sceneSum + scene.actions.length, 0), 0),
|
|
651
|
+
actors: script.actors.length,
|
|
652
|
+
locations: script.locations.length,
|
|
653
|
+
props: script.props.length,
|
|
654
|
+
states: [...script.actors, ...script.locations, ...script.props]
|
|
655
|
+
.reduce((sum, asset) => sum + asset.states.length, 0),
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function v4CanonicalIds(script) {
|
|
659
|
+
return [
|
|
660
|
+
...script.actors.flatMap((asset) => [
|
|
661
|
+
asset.actor_id,
|
|
662
|
+
...asset.states.map((state) => `${asset.actor_id}/${state.state_id}`),
|
|
663
|
+
]),
|
|
664
|
+
...script.locations.flatMap((asset) => [
|
|
665
|
+
asset.location_id,
|
|
666
|
+
...asset.states.map((state) => `${asset.location_id}/${state.state_id}`),
|
|
667
|
+
]),
|
|
668
|
+
...script.props.flatMap((asset) => [
|
|
669
|
+
asset.prop_id,
|
|
670
|
+
...asset.states.map((state) => `${asset.prop_id}/${state.state_id}`),
|
|
671
|
+
]),
|
|
672
|
+
...script.episodes.flatMap((episode) => [
|
|
673
|
+
episode.episode_id,
|
|
674
|
+
...episode.scenes.flatMap((scene) => [
|
|
675
|
+
scene.scene_id,
|
|
676
|
+
...scene.actions.map((action) => action.action_id),
|
|
677
|
+
]),
|
|
678
|
+
]),
|
|
679
|
+
];
|
|
680
|
+
}
|
|
681
|
+
function orderedIntersection(left, right) {
|
|
682
|
+
return left.filter((value) => right.has(value));
|
|
683
|
+
}
|
|
684
|
+
function v4OperationTargets(operation) {
|
|
685
|
+
const values = [];
|
|
686
|
+
const isIdentity = (value) => {
|
|
687
|
+
if (value === "global")
|
|
688
|
+
return true;
|
|
689
|
+
if (isV4Id("episode", value)
|
|
690
|
+
|| isV4Id("scene", value)
|
|
691
|
+
|| isV4Id("action", value)
|
|
692
|
+
|| isV4Id("actor", value)
|
|
693
|
+
|| isV4Id("location", value)
|
|
694
|
+
|| isV4Id("prop", value))
|
|
695
|
+
return true;
|
|
696
|
+
const slash = value.indexOf("/");
|
|
697
|
+
if (slash < 0 || slash !== value.lastIndexOf("/"))
|
|
698
|
+
return false;
|
|
699
|
+
const owner = value.slice(0, slash);
|
|
700
|
+
const state = value.slice(slash + 1);
|
|
701
|
+
return (isV4Id("actor", owner)
|
|
702
|
+
|| isV4Id("location", owner)
|
|
703
|
+
|| isV4Id("prop", owner)) && (state === "default" || isV4Id("state", state));
|
|
704
|
+
};
|
|
705
|
+
const add = (value) => {
|
|
706
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
707
|
+
return;
|
|
708
|
+
const normalized = value.trim();
|
|
709
|
+
if (isIdentity(normalized))
|
|
710
|
+
values.push(normalized);
|
|
711
|
+
};
|
|
712
|
+
const first = (...fields) => {
|
|
713
|
+
for (const field of fields) {
|
|
714
|
+
const value = operation[field];
|
|
715
|
+
if (typeof value === "string" && value.trim() !== "")
|
|
716
|
+
return value;
|
|
717
|
+
}
|
|
718
|
+
return undefined;
|
|
719
|
+
};
|
|
720
|
+
const addState = (ownerValue, stateValue) => {
|
|
721
|
+
const owner = strOf(ownerValue).trim();
|
|
722
|
+
const state = strOf(stateValue).trim();
|
|
723
|
+
if (owner && state)
|
|
724
|
+
add(`${owner}/${state}`);
|
|
725
|
+
};
|
|
726
|
+
const addStates = (ownerValue, stateValues) => {
|
|
727
|
+
if (!Array.isArray(stateValues))
|
|
728
|
+
return;
|
|
729
|
+
stateValues.forEach((state) => addState(ownerValue, state));
|
|
730
|
+
};
|
|
731
|
+
const addPlacement = () => {
|
|
732
|
+
add(operation["before"]);
|
|
733
|
+
add(operation["after"]);
|
|
734
|
+
};
|
|
735
|
+
const kind = strOf(operation["op"]);
|
|
736
|
+
switch (kind) {
|
|
737
|
+
case "action.parenthetical.set":
|
|
738
|
+
case "action.parenthetical.remove":
|
|
739
|
+
case "action.content.replace":
|
|
740
|
+
case "action.content.regex-replace":
|
|
741
|
+
case "action.type.set":
|
|
742
|
+
case "action.delete":
|
|
743
|
+
case "action.transition.clear":
|
|
744
|
+
add(operation["at"]);
|
|
745
|
+
break;
|
|
746
|
+
case "action.actor.set":
|
|
747
|
+
case "dialogue.speaker.set":
|
|
748
|
+
add(operation["at"]);
|
|
749
|
+
add(operation["actor_id"]);
|
|
750
|
+
addState(operation["actor_id"], operation["state_id"]);
|
|
751
|
+
break;
|
|
752
|
+
case "action.insert":
|
|
753
|
+
add(operation["at"]);
|
|
754
|
+
add(first("action_id", "id"));
|
|
755
|
+
add(operation["actor_id"]);
|
|
756
|
+
addState(operation["actor_id"], operation["state_id"]);
|
|
757
|
+
addPlacement();
|
|
758
|
+
break;
|
|
759
|
+
case "action.move":
|
|
760
|
+
add(operation["at"]);
|
|
761
|
+
add(operation["to"]);
|
|
762
|
+
addPlacement();
|
|
763
|
+
break;
|
|
764
|
+
case "action.transition.set":
|
|
765
|
+
add(operation["at"]);
|
|
766
|
+
add(operation["target"]);
|
|
767
|
+
break;
|
|
768
|
+
case "scene.ref.set":
|
|
769
|
+
case "scene.ref.remove":
|
|
770
|
+
add(operation["at"]);
|
|
771
|
+
add(operation["target"]);
|
|
772
|
+
addStates(operation["target"], operation["state_ids"]);
|
|
773
|
+
break;
|
|
774
|
+
case "actor.add":
|
|
775
|
+
add(first("actor_id", "id"));
|
|
776
|
+
break;
|
|
777
|
+
case "location.add":
|
|
778
|
+
add(first("location_id", "id"));
|
|
779
|
+
break;
|
|
780
|
+
case "prop.add":
|
|
781
|
+
add(first("prop_id", "id"));
|
|
782
|
+
break;
|
|
783
|
+
case "state.add": {
|
|
784
|
+
const owner = operation["target"];
|
|
785
|
+
add(owner);
|
|
786
|
+
addState(owner, first("state_id", "id"));
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
case "state.rename":
|
|
790
|
+
case "state.describe":
|
|
791
|
+
add(operation["target"]);
|
|
792
|
+
break;
|
|
793
|
+
case "state.delete": {
|
|
794
|
+
const target = strOf(operation["target"]).trim();
|
|
795
|
+
add(target);
|
|
796
|
+
const slash = target.indexOf("/");
|
|
797
|
+
if (slash > 0)
|
|
798
|
+
addState(target.slice(0, slash), operation["replacement"]);
|
|
799
|
+
break;
|
|
800
|
+
}
|
|
801
|
+
case "asset.rename":
|
|
802
|
+
case "asset.describe":
|
|
803
|
+
case "asset.role.set":
|
|
804
|
+
case "asset.alias.set":
|
|
805
|
+
case "asset.alias.add":
|
|
806
|
+
case "asset.alias.remove":
|
|
807
|
+
case "importance.set":
|
|
808
|
+
add(operation["target"]);
|
|
809
|
+
break;
|
|
810
|
+
case "asset.merge":
|
|
811
|
+
add(first("from", "source"));
|
|
812
|
+
add(first("into", "target"));
|
|
813
|
+
break;
|
|
814
|
+
case "asset.delete":
|
|
815
|
+
add(operation["target"]);
|
|
816
|
+
if (operation["strategy"] === "replace")
|
|
817
|
+
add(operation["replacement"]);
|
|
818
|
+
break;
|
|
819
|
+
case "episode.add":
|
|
820
|
+
add(first("episode_id", "id"));
|
|
821
|
+
break;
|
|
822
|
+
case "episode.synopsis.set":
|
|
823
|
+
add(first("episode_id", "target", "at"));
|
|
824
|
+
break;
|
|
825
|
+
case "meta.worldview.set":
|
|
826
|
+
case "meta.synopsis.set":
|
|
827
|
+
add("global");
|
|
828
|
+
break;
|
|
829
|
+
case "scene.insert": {
|
|
830
|
+
const location = first("location", "location_id");
|
|
831
|
+
add(first("at", "episode_id"));
|
|
832
|
+
add(first("scene_id", "id"));
|
|
833
|
+
add(location);
|
|
834
|
+
addStates(location, operation["location_state_ids"]);
|
|
835
|
+
addPlacement();
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
case "scene.move":
|
|
839
|
+
add(operation["at"]);
|
|
840
|
+
add(operation["to"]);
|
|
841
|
+
addPlacement();
|
|
842
|
+
break;
|
|
843
|
+
case "scene.delete":
|
|
844
|
+
add(operation["at"]);
|
|
845
|
+
break;
|
|
846
|
+
case "scene.split":
|
|
847
|
+
add(operation["at"]);
|
|
848
|
+
add(first("at_action", "action_id"));
|
|
849
|
+
add(first("new_scene_id", "scene_id"));
|
|
850
|
+
break;
|
|
851
|
+
case "scene.merge":
|
|
852
|
+
add(operation["from"]);
|
|
853
|
+
add(operation["into"]);
|
|
854
|
+
break;
|
|
855
|
+
case "extend.set":
|
|
856
|
+
case "extend.clear":
|
|
857
|
+
add(operation["at"]);
|
|
858
|
+
break;
|
|
859
|
+
default:
|
|
860
|
+
throw new Error(`V4 plan target mapping is missing for operation ${kind}`);
|
|
861
|
+
}
|
|
862
|
+
return [...new Set(values)];
|
|
863
|
+
}
|
|
864
|
+
export function buildV4MutationPlan(session, operations, options = {}) {
|
|
865
|
+
if (session.version !== 4) {
|
|
866
|
+
throw new CliError("SCRIPT PLAN BLOCKED: wrong version", "A v4 mutation plan requires Script v4.", {
|
|
867
|
+
exitCode: EXIT_USAGE,
|
|
868
|
+
errorCode: "V4_PLAN_VERSION_INVALID",
|
|
869
|
+
received: [`Script v${session.version}`],
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
const original = requireScriptV4(session.script);
|
|
873
|
+
const proposed = structuredClone(original);
|
|
874
|
+
const originalIds = v4CanonicalIds(original);
|
|
875
|
+
const applied = [];
|
|
876
|
+
const steps = [];
|
|
877
|
+
for (const [index, operation] of operations.entries()) {
|
|
878
|
+
const beforeIds = v4CanonicalIds(proposed);
|
|
879
|
+
const beforeSet = new Set(beforeIds);
|
|
880
|
+
const before = v4Counts(proposed);
|
|
881
|
+
let status = "applied";
|
|
882
|
+
try {
|
|
883
|
+
applied.push(...applyPatchOperationsV4(proposed, [operation]));
|
|
884
|
+
}
|
|
885
|
+
catch (error) {
|
|
886
|
+
if (error instanceof CliError
|
|
887
|
+
&& error.errorCode
|
|
888
|
+
&& options.skipCodes?.has(error.errorCode)) {
|
|
889
|
+
status = "skipped";
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
throw error;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
const afterIds = v4CanonicalIds(proposed);
|
|
896
|
+
const afterSet = new Set(afterIds);
|
|
897
|
+
steps.push({
|
|
898
|
+
index,
|
|
899
|
+
operation,
|
|
900
|
+
targets: v4OperationTargets(operation),
|
|
901
|
+
status,
|
|
902
|
+
before,
|
|
903
|
+
after: v4Counts(proposed),
|
|
904
|
+
created_ids: afterIds.filter((id) => !beforeSet.has(id)),
|
|
905
|
+
removed_ids: beforeIds.filter((id) => !afterSet.has(id)),
|
|
906
|
+
retained_ids: orderedIntersection(beforeIds, afterSet),
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
const proposedIds = v4CanonicalIds(proposed);
|
|
910
|
+
const originalSet = new Set(originalIds);
|
|
911
|
+
const proposedSet = new Set(proposedIds);
|
|
912
|
+
const targets = [...new Set(steps.flatMap((step) => step.targets))];
|
|
913
|
+
const touched = new Set([
|
|
914
|
+
...targets,
|
|
915
|
+
...steps.flatMap((step) => step.created_ids),
|
|
916
|
+
...steps.flatMap((step) => step.removed_ids),
|
|
917
|
+
]);
|
|
918
|
+
const plan = {
|
|
919
|
+
version: 1,
|
|
920
|
+
script_version: 4,
|
|
921
|
+
baseline: session.baselineHash,
|
|
922
|
+
operations,
|
|
923
|
+
targets,
|
|
924
|
+
steps,
|
|
925
|
+
before: v4Counts(original),
|
|
926
|
+
after: v4Counts(proposed),
|
|
927
|
+
created_ids: proposedIds.filter((id) => !originalSet.has(id)),
|
|
928
|
+
removed_ids: originalIds.filter((id) => !proposedSet.has(id)),
|
|
929
|
+
retained_ids: orderedIntersection(originalIds, proposedSet),
|
|
930
|
+
untouched_ids: orderedIntersection(originalIds, proposedSet)
|
|
931
|
+
.filter((id) => !touched.has(id)),
|
|
932
|
+
validation: validateScriptV4(proposed),
|
|
933
|
+
};
|
|
934
|
+
return {
|
|
935
|
+
plan,
|
|
936
|
+
digest: `sha256:${sha256Text(JSON.stringify(sortDeep(plan)))}`,
|
|
937
|
+
applied,
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
const V4_PLANNED_ID_FIELDS = {
|
|
941
|
+
"actor.add": "actor_id",
|
|
942
|
+
"location.add": "location_id",
|
|
943
|
+
"prop.add": "prop_id",
|
|
944
|
+
"state.add": "state_id",
|
|
945
|
+
"episode.add": "episode_id",
|
|
946
|
+
"scene.insert": "scene_id",
|
|
947
|
+
"scene.split": "new_scene_id",
|
|
948
|
+
"action.insert": "action_id",
|
|
949
|
+
};
|
|
950
|
+
export function assertV4PlanHasExplicitNewIds(operations) {
|
|
951
|
+
for (const operation of operations) {
|
|
952
|
+
const kind = strOf(operation["op"]);
|
|
953
|
+
const field = V4_PLANNED_ID_FIELDS[kind];
|
|
954
|
+
if (!field || strOf(operation[field]).trim())
|
|
955
|
+
continue;
|
|
956
|
+
const idKind = field === "new_scene_id" ? "scene" : field.replace(/_id$/, "");
|
|
957
|
+
throw new CliError("SCRIPT V4 PLAN BLOCKED: new ID missing", "Planned creation operations require an explicit candidate ID.", {
|
|
958
|
+
exitCode: EXIT_USAGE,
|
|
959
|
+
errorCode: "V4_PLAN_ID_REQUIRED",
|
|
960
|
+
required: [`${kind}.${field}`],
|
|
961
|
+
received: [`${kind}.${field}=<missing>`],
|
|
962
|
+
nextSteps: [`Generate a candidate with \`scriptctl ids --kind ${idKind} --count 1\`, then include it in the operation.`],
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
}
|
|
522
966
|
// ---------------------------------------------------------------------------
|
|
523
967
|
// Single-op helpers
|
|
524
968
|
// ---------------------------------------------------------------------------
|
|
525
|
-
export async function
|
|
969
|
+
export async function applySingleScriptOpToSession(session, opts, op) {
|
|
970
|
+
const plan = strOf(opts["plan"]).trim();
|
|
971
|
+
if (plan) {
|
|
972
|
+
throw new CliError("SCRIPT OP BLOCKED: --plan is not applicable", "Single-point writes do not use plan digests.", {
|
|
973
|
+
exitCode: EXIT_USAGE,
|
|
974
|
+
errorCode: "MULTI_PLAN_USAGE_INVALID",
|
|
975
|
+
received: [plan],
|
|
976
|
+
nextSteps: ["Remove --plan from this single-point edit."],
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
return applyScriptOpsToSession(session, opts, [op]);
|
|
980
|
+
}
|
|
981
|
+
export async function applyScriptOpsToSession(session, opts, operations) {
|
|
526
982
|
const workspace = strOf(opts["workspace_path"] || "workspace");
|
|
527
|
-
const
|
|
528
|
-
const
|
|
529
|
-
const applied = applyPatchOperations(script, scriptSourceText(workspace), [op]);
|
|
530
|
-
const opName = applied[0] ?? strOf(op["op"]);
|
|
983
|
+
const applied = applyPatchOperationsForSession(session, scriptSourceText(workspace), operations);
|
|
984
|
+
const opName = applied.length === 1 ? applied[0] : "script.ops";
|
|
531
985
|
const [newRevision, idempotent] = await saveScriptSession(session, opts, opName);
|
|
532
986
|
const validation = validateSession(session);
|
|
533
987
|
await syncValidationResult(session, validation, newRevision);
|
|
534
988
|
const passed = Boolean(validation["passed"]);
|
|
535
989
|
// One outcome line: what changed + revision (remote) + validation verdict.
|
|
536
990
|
const rev = session.remote ? `; rev ${newRevision}` : "";
|
|
537
|
-
const resultLine = `${
|
|
991
|
+
const resultLine = `${applied.join(", ")} applied${rev}; validation ${passed ? "passed" : "needs repair"}`;
|
|
538
992
|
const report = {
|
|
539
993
|
title: passed ? "SCRIPT OP APPLIED" : "SCRIPT OP APPLIED: Validation needs repair",
|
|
540
994
|
op: opName,
|
|
@@ -549,6 +1003,10 @@ export async function applySingleScriptOp(opts, op) {
|
|
|
549
1003
|
};
|
|
550
1004
|
return [report, passed ? EXIT_OK : EXIT_NEEDS_AGENT];
|
|
551
1005
|
}
|
|
1006
|
+
export async function applySingleScriptOp(opts, op) {
|
|
1007
|
+
const session = await loadScriptForEdit(opts);
|
|
1008
|
+
return applySingleScriptOpToSession(session, opts, op);
|
|
1009
|
+
}
|
|
552
1010
|
export function summarizeScriptOp(_script, op) {
|
|
553
1011
|
const kind = strOf(op["op"]);
|
|
554
1012
|
if (kind === "actor.add")
|
|
@@ -593,50 +1051,116 @@ export function regexPattern(raw) {
|
|
|
593
1051
|
// reports the blast radius and writes nothing; --apply commits. Per-action
|
|
594
1052
|
// "no match here / overlap dialogue" errors are skipped (a sweep); anything else
|
|
595
1053
|
// aborts the whole edit before any write. Shared by every selector-capable verb.
|
|
596
|
-
export async function
|
|
1054
|
+
export async function applySelectorEditsToSession(session, opts, template, verbLabel) {
|
|
597
1055
|
const workspace = strOf(opts["workspace_path"] || "workspace");
|
|
598
1056
|
const apply = Boolean(opts["apply"]);
|
|
599
1057
|
const opName = strOf(template["op"]);
|
|
600
|
-
const session = await loadScriptForEdit(opts);
|
|
601
1058
|
const script = session.script;
|
|
602
|
-
const
|
|
603
|
-
|
|
1059
|
+
const refs = session.version === 3
|
|
1060
|
+
? resolveActionTargets(script, opts).map((target) => `${target.epId}/${target.sceneId}#${target.idx}`)
|
|
1061
|
+
: resolveActionTargetsV4(requireScriptV4(script), opts, { allowOrdinals: false })
|
|
1062
|
+
.map((target) => target.action.action_id);
|
|
1063
|
+
const operations = refs.map((ref) => ({ ...template, at: ref }));
|
|
1064
|
+
const multiV4 = session.version === 4 && refs.length > 1;
|
|
1065
|
+
const planned = multiV4
|
|
1066
|
+
? buildV4MutationPlan(session, operations, { skipCodes: SKIPPABLE_EDIT_CODES })
|
|
1067
|
+
: null;
|
|
1068
|
+
const planDigest = planned?.digest ?? null;
|
|
1069
|
+
const suppliedPlan = strOf(opts["plan"]).trim();
|
|
1070
|
+
if (suppliedPlan && (!multiV4 || !apply)) {
|
|
1071
|
+
throw new CliError("SELECTOR EDIT BLOCKED: --plan is not applicable", "A plan digest is only accepted for a v4 multi-target apply.", {
|
|
1072
|
+
exitCode: EXIT_USAGE,
|
|
1073
|
+
errorCode: "MULTI_PLAN_USAGE_INVALID",
|
|
1074
|
+
received: [suppliedPlan],
|
|
1075
|
+
nextSteps: ["Remove --plan, or apply the same v4 multi-target selection that produced the digest."],
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
if (multiV4 && apply && !suppliedPlan) {
|
|
1079
|
+
throw new CliError("SELECTOR EDIT BLOCKED: plan required", "A v4 multi-target write requires its dry-run plan digest.", {
|
|
1080
|
+
exitCode: EXIT_USAGE,
|
|
1081
|
+
errorCode: "MULTI_PLAN_REQUIRED",
|
|
1082
|
+
required: [planDigest ?? ""],
|
|
1083
|
+
received: ["<missing>"],
|
|
1084
|
+
nextSteps: ["Run the same command without --apply, review the full plan, then retry with `--apply --plan <digest>`."],
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
if (multiV4 && apply && suppliedPlan !== planDigest) {
|
|
1088
|
+
throw new CliError("SELECTOR EDIT BLOCKED: plan mismatch", "The supplied digest does not match the current targets and operations.", {
|
|
1089
|
+
exitCode: EXIT_INPUT,
|
|
1090
|
+
errorCode: "MULTI_PLAN_MISMATCH",
|
|
1091
|
+
required: [planDigest ?? ""],
|
|
1092
|
+
received: [suppliedPlan],
|
|
1093
|
+
nextSteps: ["Review the newly computed dry-run plan, then apply its exact digest."],
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
604
1096
|
const source = scriptSourceText(workspace);
|
|
605
|
-
let applied = 0;
|
|
606
|
-
let skipped = 0;
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
1097
|
+
let applied = planned?.plan.steps.filter((step) => step.status === "applied").length ?? 0;
|
|
1098
|
+
let skipped = planned?.plan.steps.filter((step) => step.status === "skipped").length ?? 0;
|
|
1099
|
+
if (!planned) {
|
|
1100
|
+
for (const ref of refs) {
|
|
1101
|
+
try {
|
|
1102
|
+
applyPatchOperationsForSession(session, source, [{ ...template, at: ref }]);
|
|
1103
|
+
applied += 1;
|
|
1104
|
+
}
|
|
1105
|
+
catch (err) {
|
|
1106
|
+
if (err instanceof CliError && err.errorCode && SKIPPABLE_EDIT_CODES.has(err.errorCode)) {
|
|
1107
|
+
skipped += 1;
|
|
1108
|
+
continue;
|
|
1109
|
+
}
|
|
1110
|
+
throw err;
|
|
1111
|
+
}
|
|
611
1112
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
1113
|
+
}
|
|
1114
|
+
else if (apply) {
|
|
1115
|
+
for (const step of planned.plan.steps) {
|
|
1116
|
+
if (step.status === "applied") {
|
|
1117
|
+
applyPatchOperationsForSession(session, source, [step.operation]);
|
|
616
1118
|
}
|
|
617
|
-
throw err;
|
|
618
1119
|
}
|
|
619
1120
|
}
|
|
620
|
-
const
|
|
1121
|
+
const displayedRefs = multiV4 ? refs : refs.slice(0, 12);
|
|
621
1122
|
const blast = [
|
|
622
1123
|
`verb: ${verbLabel} (${opName})`,
|
|
623
1124
|
`matched: ${refs.length} action(s)`,
|
|
624
1125
|
`${apply ? "applied" : "would-apply"}: ${applied}`,
|
|
625
1126
|
`${apply ? "skipped" : "would-skip"}: ${skipped}`,
|
|
626
|
-
...(
|
|
1127
|
+
...(displayedRefs.length ? [`targets: ${displayedRefs.join(", ")}${refs.length > displayedRefs.length ? ` … (+${refs.length - displayedRefs.length} more)` : ""}`] : []),
|
|
1128
|
+
...(planDigest ? [`plan_digest: ${planDigest}`] : []),
|
|
627
1129
|
];
|
|
628
1130
|
if (!apply) {
|
|
629
|
-
const
|
|
630
|
-
const passed =
|
|
1131
|
+
const legacyValidation = planned ? null : validateSession(session);
|
|
1132
|
+
const passed = planned
|
|
1133
|
+
? planned.plan.validation.ok
|
|
1134
|
+
: Boolean(legacyValidation?.["passed"]);
|
|
1135
|
+
const plannedIssueLines = planned
|
|
1136
|
+
? [...planned.plan.validation.errors, ...planned.plan.validation.warnings]
|
|
1137
|
+
.map((issue) => `${issue.path}: ${issue.code} - ${issue.message}`)
|
|
1138
|
+
: null;
|
|
1139
|
+
const legacyIssueLines = legacyValidation === null
|
|
1140
|
+
? []
|
|
1141
|
+
: summarizeIssues(asList(legacyValidation["issues"]));
|
|
631
1142
|
const report = {
|
|
632
1143
|
title: refs.length === 0 ? "SELECTOR EDIT DRY-RUN: no match" : "SELECTOR EDIT DRY-RUN (no write)",
|
|
633
1144
|
op: `${opName}.dry-run`,
|
|
634
1145
|
changed: false,
|
|
635
1146
|
result: [...blast, `validation: ${passed ? "would pass" : "would need repair"}; dry-run, no write`],
|
|
636
|
-
warnings: passed
|
|
637
|
-
|
|
1147
|
+
warnings: passed
|
|
1148
|
+
? []
|
|
1149
|
+
: plannedIssueLines ?? legacyIssueLines,
|
|
1150
|
+
issues: plannedIssueLines ?? legacyIssueLines,
|
|
638
1151
|
artifacts: [session.artifactLabel],
|
|
639
|
-
|
|
1152
|
+
...(planDigest ? {
|
|
1153
|
+
baseline: session.baselineHash,
|
|
1154
|
+
plan_digest: planDigest,
|
|
1155
|
+
operations,
|
|
1156
|
+
targets: refs,
|
|
1157
|
+
plan: planned?.plan,
|
|
1158
|
+
} : {}),
|
|
1159
|
+
next: [refs.length === 0
|
|
1160
|
+
? "Widen the selection (--in / --grep / predicates)."
|
|
1161
|
+
: planDigest
|
|
1162
|
+
? `Re-run with --apply --plan ${planDigest} to commit this exact plan.`
|
|
1163
|
+
: "Re-run with --apply to commit."],
|
|
640
1164
|
};
|
|
641
1165
|
return [report, passed ? EXIT_OK : EXIT_NEEDS_AGENT];
|
|
642
1166
|
}
|
|
@@ -664,10 +1188,21 @@ export async function applySelectorEdits(opts, template, verbLabel) {
|
|
|
664
1188
|
warnings: passed ? [] : summarizeIssues(asList(validation["issues"])),
|
|
665
1189
|
issues: summarizeIssues(asList(validation["issues"])),
|
|
666
1190
|
artifacts: [session.artifactLabel],
|
|
1191
|
+
...(planDigest ? {
|
|
1192
|
+
baseline: session.baselineHash,
|
|
1193
|
+
plan_digest: planDigest,
|
|
1194
|
+
operations,
|
|
1195
|
+
targets: refs,
|
|
1196
|
+
plan: planned?.plan,
|
|
1197
|
+
} : {}),
|
|
667
1198
|
next: passed ? undefined : ["Inspect issues and apply another edit."],
|
|
668
1199
|
};
|
|
669
1200
|
return [report, passed ? EXIT_OK : EXIT_NEEDS_AGENT];
|
|
670
1201
|
}
|
|
1202
|
+
export async function applySelectorEdits(opts, template, verbLabel) {
|
|
1203
|
+
const session = await loadScriptForEdit(opts);
|
|
1204
|
+
return applySelectorEditsToSession(session, opts, template, verbLabel);
|
|
1205
|
+
}
|
|
671
1206
|
export { sortDeep };
|
|
672
1207
|
// ===========================================================================
|
|
673
1208
|
// 0.6.0 plural-noun query commands (replace `commandScriptInspect --target X`)
|
|
@@ -735,7 +1270,10 @@ export function buildGrepMatcher(raw) {
|
|
|
735
1270
|
}
|
|
736
1271
|
try {
|
|
737
1272
|
const re = new RegExp(pattern, m[2]);
|
|
738
|
-
return (hay) =>
|
|
1273
|
+
return (hay) => {
|
|
1274
|
+
re.lastIndex = 0;
|
|
1275
|
+
return re.test(hay);
|
|
1276
|
+
};
|
|
739
1277
|
}
|
|
740
1278
|
catch {
|
|
741
1279
|
// Malformed regex — treat as literal.
|
|
@@ -854,7 +1392,7 @@ export function resolveActionTargets(script, opts) {
|
|
|
854
1392
|
}
|
|
855
1393
|
// Whether a selection in `opts` has any filter at all (scope or predicate).
|
|
856
1394
|
export function selectionHasAnyFilter(opts) {
|
|
857
|
-
return Boolean(
|
|
1395
|
+
return Boolean(strOf(opts["in"]).trim() ||
|
|
858
1396
|
strOf(opts["grep"]) || strOf(opts["type"]).trim() || strOf(opts["actor"]).trim() ||
|
|
859
1397
|
strOf(opts["has"]).trim());
|
|
860
1398
|
}
|
|
@@ -999,7 +1537,7 @@ export function splitSpeakerList(raw) {
|
|
|
999
1537
|
}
|
|
1000
1538
|
export function blankCreateReport(session, validation, idempotent) {
|
|
1001
1539
|
const passed = Boolean(validation["passed"]);
|
|
1002
|
-
const resultLines = [
|
|
1540
|
+
const resultLines = [`created: blank script (Script v${session.version})`, `validation: ${passed ? "passed" : "needs repair"}`];
|
|
1003
1541
|
if (session.remote) {
|
|
1004
1542
|
resultLines.push(`revision: ${session.revision}`);
|
|
1005
1543
|
if (idempotent !== null)
|