scriptnow-cli 0.4.14__tar.gz → 0.4.19__tar.gz
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.
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/PKG-INFO +1 -1
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/README.md +3 -1
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/README.md +3 -1
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/__init__.py +1 -1
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/scriptnow_cli.py +211 -29
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/SKILL.md +1 -0
- scriptnow_cli-0.4.19/cli_anything/scriptnow/skills/references/recreation.md +13 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/scriptnow_cli.egg-info/PKG-INFO +1 -1
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/scriptnow_cli.egg-info/SOURCES.txt +2 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_guide_chain.py +1 -1
- scriptnow_cli-0.4.19/tests/test_translate_local_commands.py +92 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/LICENSE +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/README.pypi.md +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/__init__.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/__main__.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/agents/openai.yaml +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/methods.md +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/operations.md +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/planning.md +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/review.md +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/setup.md +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/storyboard.md +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/writing.md +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/ui.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/__init__.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/browser_login.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/device_login.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/diag.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/hosted.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/json_input.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/request_identity.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/review.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/session.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/upgrade.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/pyproject.toml +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/scriptnow_cli.egg-info/dependency_links.txt +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/scriptnow_cli.egg-info/entry_points.txt +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/scriptnow_cli.egg-info/requires.txt +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/scriptnow_cli.egg-info/top_level.txt +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/setup.cfg +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/setup.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_append_commands.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_batch_commands.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_blueprint_request_identity.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_browser_login.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_chapter_request_identity.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_device_login.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_document_revision_state.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_execution_attempt_commands.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_host_refresh.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_hosted_instance.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_interpret_propose.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_json_errors.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_json_input_paths.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_outline_commands.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_planning_status_direction.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_review_commands.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_run_commands.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_scene_request_identity.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_session.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_session_isolation.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_skill_bundle.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_storyboard_commands.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_unbound_aliases.py +0 -0
- {scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/tests/test_upgrade.py +0 -0
|
@@ -358,7 +358,9 @@ scriptnow script adopt-scene <pid> scene-1-1 <rev> --human --review-token <定
|
|
|
358
358
|
| novel | 小说创作链:story-cores / blueprint / adopt-core / adopt-blueprint / bible-candidates / bible-candidate-preview / bible-candidate-adopt / outline / outline-candidates / outline-adopt-preview / outline-adopt / outline-status / graph(叙事图谱对账)/ planning-quality / planning-status / ready-check / propose(本地 JSON 导入)/ orchestrate / **rough-outline 平铺链:rough-outline / adopt / check / example** / **storymap-rebuild 隔离重建链:start / rebuild / rebuild-phase / rebuild-phase-preview / rebuild-check / rebuild-propose** / **storymap-archives / storymap-archive(旧结构归档读取)/ storymap-restore(归档导出恢复候选)**;重建须先采纳小说粗纲,阶段按全书章区间且不强制一阶段一卷 |
|
|
359
359
|
| script | 剧本创作链:story-cores / blueprint / adopt-blueprint / adopt-core / outline / outline-candidates / outline-adopt-preview / outline-adopt / outline-status / **rough-outline 分阶段链:-start / -phase / -progress / -propose / -phase-preview / -check** / episode-outline / **episode-outline-check / episode-outline-example** / **bible-example / bible-candidates / bible-candidate-preview / bible-candidate-adopt** / state / storymap / **storymap-phases / storymap-append-phase** / adopt-storymap(高危)/ planning-quality / **ready-check** / propose(本地 JSON 导入)/ adopt-scene / scene / scene-list / scene-show / scene-propose(--help-format/--example;--auto-adopt 已停用)/ scene-batch / scene-quality / scene-diff / quality-report / **storymap-rebuild 隔离重建链:start / rebuild / rebuild-phase / rebuild-phase-preview / rebuild-check / rebuild-propose** / **storymap-archives / storymap-archive(旧结构归档读取)/ storymap-restore(归档导出恢复候选)** / **analytics(分集量化仪表盘:节拍密度/冲突分量/角色戏份分布/关键节点覆盖矩阵,确定性算出,只读)** |
|
|
360
360
|
| storyboard | 分镜回填链:state / source-preflight / source-import / source-range / source-revoke / propose / **candidate-preview / adopt(内容绑定审阅凭证)** / assets / asset-add / continuity / **scene-board upload|generate|list|inspect|delete** / readiness / export;规划板是显式单场操作,不写 shot.frame_refs |
|
|
361
|
-
| translate | 故事归化:create /
|
|
361
|
+
| translate | 故事归化:create / state / contract / propose / adopt / review-unit / revise-unit / manuscript / export;旧 analyze-source 改为本地回填指引 |
|
|
362
|
+
|
|
363
|
+
故事归化的原著文件及抽取全文留在 Agent 本地。Agent 阅读授权范围、记录来源指纹和定位锚点,围绕叙事功能与目标文化中的制度、关系和动机形成重构方案;只有实际迁移或重构文化载体时才提交映射,触及保护项时才等待作者裁决。用 `translate state`、`translate contract` 读取当前基线并保存契约回执,`run claim` 领取归化资源写资格,`translate propose <作品号> <kind> @file.json --contract @contract.json --execution-token <凭据> --request-key <请求号>` 回填候选。同请求重试复用同一契约文件。逐章回填前用带同一执行凭据的 `translate state --unit-key <工作包键> --read-kind facts|methods` 分别取得平台事实和所选方法全文;提交时带方法摘要,平台核实两次读取收据。读取不等于已应用,原著本地阅读仍只可自证。章节用 `review-unit` 审读,可用 `revise-unit` 另存人工候选,作者通过 review confirm/claim 和 `translate adopt` 独立采纳;`manuscript` 与 `export -o 稿.docx` 显示当前或历史基线。旧 `/analyze-source` 已停用,其他平台生成仅为显式后台后备。
|
|
362
364
|
| cover | 封面:package(平台生成包装包)/ package-propose(Agent 自主提交包装文案)/ package-show / models / specs / generate(默认 1 张 1024×1600)/ list / delete |
|
|
363
365
|
| export | 导出交付:options / create / **preview(交付范围审阅,返回一键审阅地址)** / download / zip;剧本 working DOCX 含每场制作信息 |
|
|
364
366
|
| skill | Skill 工坊:**setup(按推荐预设与作者点选共建,服务端编译并挂载;剧本域含 Method DNA)** / craft(六问深度共创、预检、确认、挂载回读)/ list / create / **detail(个人 Skill 摘要)** / update / versions / archive / mount / **unmount(仅解除本项目挂载,需 --confirm)** / mounts / upload;**method-current / method-compile / method-compare / method-bind / method-resolve**(服务端 Method DNA 核心密码版本与 scope 解析);**growth**(方法论进化);**canary**(版本灰度) |
|
|
@@ -182,7 +182,9 @@ scriptnow script adopt-scene <pid> scene-1-1 <rev> --human --review-token <定
|
|
|
182
182
|
| novel | 小说创作链:story-cores / blueprint / adopt-core / adopt-blueprint / bible-candidates / bible-candidate-preview / bible-candidate-adopt / outline / outline-candidates / outline-adopt-preview / outline-adopt / outline-status / graph(叙事图谱对账)/ planning-quality / planning-status / ready-check / propose(本地 JSON 导入)/ orchestrate / **rough-outline 平铺链:rough-outline / adopt / check / example** / **storymap-rebuild 隔离重建链:start / rebuild / rebuild-phase / rebuild-phase-preview / rebuild-check / rebuild-propose** / **storymap-archives / storymap-archive(旧结构归档读取)/ storymap-restore(归档导出恢复候选)**;重建须先采纳小说粗纲,阶段按全书章区间且不强制一阶段一卷 |
|
|
183
183
|
| script | 剧本创作链:story-cores / blueprint / adopt-blueprint / adopt-core / outline / outline-candidates / outline-adopt-preview / outline-adopt / outline-status / **rough-outline 分阶段链:-start / -phase / -progress / -propose / -phase-preview / -check** / episode-outline / **episode-outline-check / episode-outline-example** / **bible-example / bible-candidates / bible-candidate-preview / bible-candidate-adopt** / state / storymap / **storymap-phases / storymap-append-phase** / adopt-storymap(高危)/ planning-quality / **ready-check** / propose(本地 JSON 导入)/ adopt-scene / scene / scene-list / scene-show / scene-propose(--help-format/--example;--auto-adopt 已停用)/ scene-batch / scene-quality / scene-diff / quality-report / **storymap-rebuild 隔离重建链:start / rebuild / rebuild-phase / rebuild-phase-preview / rebuild-check / rebuild-propose** / **storymap-archives / storymap-archive(旧结构归档读取)/ storymap-restore(归档导出恢复候选)** / **analytics(分集量化仪表盘:节拍密度/冲突分量/角色戏份分布/关键节点覆盖矩阵,确定性算出、只读)** |
|
|
184
184
|
| storyboard | 分镜回填链:state / source-preflight / source-import / source-range / source-revoke / propose / **candidate-preview / adopt(内容绑定审阅凭证)** / assets / asset-add / continuity / **scene-board upload|generate|list|inspect|delete** / readiness / export;规划板是显式单场操作,不写 shot.frame_refs |
|
|
185
|
-
| translate | 故事归化:create /
|
|
185
|
+
| translate | 故事归化:create / state / contract / propose / adopt / review-unit / revise-unit / manuscript / export;旧源分析入口已停用 |
|
|
186
|
+
|
|
187
|
+
归化项目默认由 Agent 本地阅读原著,原文不上传平台。先 `translate state/contract` 读取并保存已采纳基线,再 `run claim` 取得限域写资格;按叙事功能重构目标文化中的制度、关系和动机,用 `translate propose --contract @contract.json` 保存候选。实际迁移或重构文化载体才需要映射,触及保护项才需要作者冲突裁决。章节前以相同执行凭据 `translate state --unit-key <键> --read-kind facts|methods` 分别读取平台事实和服务端选中方法,并随候选提交 material_digest;收据只证明调用与返回,不证明方法应用。候选回读后由作者用 review confirm/claim 与 `translate adopt` 采纳;`review-unit`、`revise-unit`、`manuscript` 和 `export` 完成章节审读、人工修订与按基线交付。旧平台原文分析停用,其他平台生成只作显式后台后备。
|
|
186
188
|
| cover | 封面:package(平台生成包装包)/ package-propose(Agent 自主提交包装文案)/ package-show / models / specs / generate(默认 1 张 1024×1600)/ list / delete |
|
|
187
189
|
| export | 导出交付:options / create / **preview(交付范围审阅,返回一键审阅地址)** / download / zip;剧本 working DOCX 含每场制作信息 |
|
|
188
190
|
| skill | Skill 工坊:**setup(按推荐预设与作者点选共建,服务端编译并挂载;剧本域含 Method DNA)** / craft(六问深度共创、预检、确认、挂载回读)/ list / create / **detail(个人 Skill 摘要)** / update / versions / archive / mount / **unmount(仅本项目,需 --confirm)** / mounts / upload;**method-current / method-compile / method-compare / method-bind / method-resolve**(服务端 Method DNA 核心密码版本与 scope 解析);**growth**(方法论进化);**canary**(版本灰度) |
|
|
@@ -1450,6 +1450,7 @@ _AGENT_CONTRACT = {
|
|
|
1450
1450
|
"一切平台操作必须经 scriptnow 命令:创建项目、规划、回传(propose)、采纳(adopt)、生成(generate)、导出(export)。离线创作的正文只是草稿,成品必须以 propose 回传为平台候选,由平台校验格式与质量。",
|
|
1451
1451
|
"正文与规划默认由 dsh 在当前创作会话中完成:先通过 scriptnow run claim 取得绑定项目、资源与执行代次的候选写资格,再读取平台事实;正文前用 skill selected --unit-id <单元ID> --json 取得所选方法全文及 material_digest,确认 execution_ready 后使用 chapter/scene propose --execution-token --material-digest 回填候选;规划用对应 propose --execution-token。平台只负责校验、保存、审阅与采纳;平台 AgentScope generate 仅为作者显式选择的后备。作者对 dsh 的委托绝不自动扩大为采纳、结构覆盖、删除或发布。候选写资格不等于采纳授权:作者看到平台回读的完整候选并明确决定后,才运行 confirm/claim 和 adopt。旧执行被撤销或接管后不能写新候选;取消写资格不冒充引擎已停止。",
|
|
1452
1452
|
"取消时 run revoke 先撤销写资格;只有回执 engine_stopped=true 才表示 dsh 已停。若仍为 false,用 run stop-status 只读复查,不重复发取消。dsh shell 的 DSH_SESSION_ID 随 run claim 绑定到 attempt,旧会话未确认停止前不得接管同任务。",
|
|
1453
|
+
"故事归化专用链:原著文件、抽取全文和逐页阅读留在 Agent 环境,平台旧 analyze-source 已停用。先 translate state/contract 读取基线并保存契约回执,run claim 领取限域写资格,本地分析原作叙事功能、目标文化制度/关系/动机,按需保留、解释、迁移或重构,再用 translate propose @file --contract @contract.json 保存候选;同请求重试复用同一契约。迁移或重构实际文化载体时给因果映射,触及保护项时由作者裁决;不凑类别或固定篇幅。逐章前用本次凭据分别读取 translate state --unit-key <键> --read-kind facts 与 methods,随 propose 提交 methods 回执的 material_digest;未采纳前序单元或任一读取缺失会拒绝。章节以 review-unit 审读,可 revise-unit 另存人工版,再经上述完整人工审阅命令确认、领取凭证并用 translate adopt 独立采纳;manuscript/export 标明基线状态。平台其余生成入口只在作者显式选择时作为后台后备,仍产候选。",
|
|
1453
1454
|
"StoryMap 普通提案不得偷偷纯追加或全置换。新增卷章用带 execution-token 的 append 通道;作者明确授权真重构后先 storymap-rebuild-start,再由 dsh 整体创作并以 propose storymap --rebuild-direct 保存完整候选,正式替换仍单独人审。分阶段重建只在超长作品按需选用,不强迫作者逐格回填。",
|
|
1454
1455
|
"规划三件套(story_cores / blueprint / storymap)回填优先:默认由 Agent 本地生成后 propose 回填为候选,再经 planning-quality 质量门禁后采纳。平台端 generate 仅作后备,不依赖、不鼓励——不要把平台生成当作首选路径。StoryMap 不是只有 episode/scene 或 volume/chapter 容器:**集纲/章纲写成一段整段叙事**(剧本 episodes[].summary;小说 chapter.outline.summary)——谁要什么 / 卡在哪 / 怎么翻 / 翻完局面变成什么,写在同一段里;分栏字段(logline/active_goal/conflict/turn/state_changes)仍可读写但不是必填。anchor_ids 是**机器索引**(剧本 episodes[].anchor_ids 或该集场节拍;小说 outline.anchor_ids 或 beat),必需。集纲/章纲随 StoryMap 一体交付:新章节在 propose/append 时必须带**可读**的集纲/章纲,经 planning-quality 与采纳后逐章写作;历史章节(已有正文)可读可写,不受章纲字段缺失影响,无需批量迁移。提交章纲前可用 chapter outline-check 自查结构,chapter outline-example 查看平台结构示范。",
|
|
1455
1456
|
"改编项目的来源画像同样**回填优先**:Agent 本地读完原著 → `scriptnow interpret propose <作品号> --spec` 取回填规范 → `scriptnow interpret propose <作品号> --profile @profile.json` 回填「来源画像 + 锚点自证」(原文不出本地,平台只校验与采纳,**不调模型、不阻塞**)→ 作者复核锚点后 `scriptnow interpret decide <作品号> <profile-id> --approve`。平台通读(`interpret go` / `interpret create` + `interpret read`)是**辅助路径且同步阻塞到读完**(大作品数分钟起,宿主工具轮候窗口常撑不住),不要当默认入口、也不要在其中干等。改编项目在**来源画像获批之前**不得生成任何规划或正文候选 —— 这条门禁不因来源来自本地而放松:回填产出的是候选,不是免批后门;锚点为空或画像缺 story_core/characters/central_conflict 会被平台直接拒收(422)。",
|
|
@@ -1521,7 +1522,7 @@ _AGENT_CONTRACT = {
|
|
|
1521
1522
|
# available through `--full` for a human or a deliberate deep inspection.
|
|
1522
1523
|
_AGENT_RUNTIME_CONTRACT = {
|
|
1523
1524
|
"guide": "scriptnow-agent-runtime-contract",
|
|
1524
|
-
"contract_version": "
|
|
1525
|
+
"contract_version": "18",
|
|
1525
1526
|
"title": "ScriptNow Agent 运行契约",
|
|
1526
1527
|
"audience": "在 ScriptNow 平台执行创作任务的 AI Agent。",
|
|
1527
1528
|
"rules": [
|
|
@@ -1530,6 +1531,7 @@ _AGENT_RUNTIME_CONTRACT = {
|
|
|
1530
1531
|
f"创作顺序固定为 12 步(guide --step 1..12):{_STEP_ONE_NAME} → 创建作品 → 补齐创作方向 → 故事核心与蓝图(cores/blueprint)→ 故事梗概(outline)→ 全剧统筹与粗纲(rough-outline)→ StoryMap 与集纲/章纲一体交付(storymap propose/adopt 含章节纲)→ 创建并挂载 Skill → 逐章/逐场创作 → 审读与修订 → 包装与导出 → 标记引导完成(guide --complete)。核心与蓝图必须先于梗概;粗纲依赖已采纳的核心/蓝图锚点与梗概,位于集纲/章纲与 StoryMap 之前;不得跳过引导直接排 StoryMap 或写正文。",
|
|
1531
1532
|
"规划回填优先(故事核心与蓝图/story_cores/blueprint/storymap):默认由 Agent 本地生成后 propose 回填为平台候选,再经 planning-quality 门禁与用户采纳;平台 generate 仅作后备手段,不依赖、不鼓励、不主动引导。",
|
|
1532
1533
|
"来源画像回填优先(改编项目):改编项目的来源画像默认由 Agent 本地读完原著后 `scriptnow interpret propose <作品号> --profile @profile.json` 回填(须带锚点自证 attestation,原文不出本地;平台只校验与采纳,不调模型、不阻塞),再由作者 `scriptnow interpret decide <作品号> <profile-id> --approve` 批准。平台通读(`interpret go` / `interpret create` + `interpret read`)是**辅助路径且同步阻塞到读完**,不作为默认入口。来源画像获批之前,改编项目不得生成任何规划或正文候选 —— 锚点为空、或画像缺 story_core/characters/central_conflict 会被平台拒收(422);回填产出的是候选,不是免批后门。",
|
|
1534
|
+
"故事归化:原著在 Agent 本地完整读取,平台不接收抽取全文,旧 analyze-source 已停用;translate state/contract 并保存契约文件 → run claim(归化 kind)→ 本地创作 → translate propose --contract @contract.json --execution-token --request-key 回填候选。同请求重试复用同一契约。策略说明原元素叙事功能,再决定保留/解释/迁移/重构;实际迁移或重构文化载体才须映射,触及保护项才须作者裁决。试写验证最大文化与因果风险。逐章前按真实工作包键分别用 translate state --read-kind facts 与 methods 取得本次 attempt 的服务端读取回执,随候选提交 material_digest;读取不等于应用,原著通读仍只可自证。章节 review-unit / revise-unit 后作者另行按上述完整命令确认并领取审阅凭证,再执行 translate adopt;manuscript/export 明示当前或历史基线。其余平台生成只作显式后台后备。",
|
|
1533
1535
|
"正文与规划默认由 dsh 在当前创作会话中完成:先通过 scriptnow run claim 取得绑定项目、资源与执行代次的候选写资格,再读取平台事实;正文前用 skill selected --unit-id <单元ID> --json 取得所选方法全文及 material_digest,确认 execution_ready 后使用 chapter/scene propose --execution-token --material-digest 回填候选;规划用对应 propose --execution-token。平台只负责校验、保存、审阅与采纳;平台 AgentScope generate 仅为作者显式选择的后备。作者对 dsh 的委托绝不自动扩大为采纳、结构覆盖、删除或发布。候选写资格不等于采纳授权:作者看到平台回读的完整候选并明确决定后,才运行 confirm/claim 和 adopt。旧执行被撤销或接管后不能写新候选;取消写资格不冒充引擎已停止。",
|
|
1534
1536
|
"授权统一走对话审阅通道 `scriptnow review confirm <packet_id> --decision retain --evidence \"<用户明确决定原话>\" --json`(原样登记用户明确决定)→ `scriptnow review claim <packet_id> --json`(取一次性凭证)→ 带 --review-token 的目标采纳命令;authorize 与旧版决策令牌通道已弃用,不再引导使用。",
|
|
1535
1537
|
"平台是唯一项目事实源:所有创建、回传、采纳、生成、导出都只能通过 scriptnow CLI。",
|
|
@@ -2647,6 +2649,8 @@ def run_events(ctx: click.Context, run_id: str, last_event_id: str | None, json_
|
|
|
2647
2649
|
@click.argument("project_id")
|
|
2648
2650
|
@click.argument("resource_kind", type=click.Choice([
|
|
2649
2651
|
"scene", "chapter", "blueprint", "story_cores", "synopsis", "rough_outline", "storymap", "bible", "episode_outline", "chapter_outline",
|
|
2652
|
+
"source_story_model", "target_story_contract", "recreation_strategy",
|
|
2653
|
+
"cultural_mapping_set", "protection_conflict_decision", "pilot", "scale_plan", "recreation_unit",
|
|
2650
2654
|
]))
|
|
2651
2655
|
@click.argument("resource_id")
|
|
2652
2656
|
@click.option("--domain", type=click.Choice(["script", "novel"]), default=None,
|
|
@@ -2662,7 +2666,10 @@ def run_claim(
|
|
|
2662
2666
|
task_key: str, attempt_key: str, takeover_generation: int | None, json_output: bool,
|
|
2663
2667
|
) -> None:
|
|
2664
2668
|
"""Claim one scoped dsh candidate-writing attempt; adoption is separate."""
|
|
2665
|
-
inferred = {"scene": "script", "chapter": "novel"
|
|
2669
|
+
inferred = {"scene": "script", "chapter": "novel", **{kind: "novel" for kind in (
|
|
2670
|
+
"source_story_model", "target_story_contract", "recreation_strategy",
|
|
2671
|
+
"cultural_mapping_set", "protection_conflict_decision", "pilot", "scale_plan", "recreation_unit",
|
|
2672
|
+
)}}.get(resource_kind)
|
|
2666
2673
|
if inferred is not None and domain is not None and domain != inferred:
|
|
2667
2674
|
raise click.ClickException("resource_kind 与 --domain 不匹配")
|
|
2668
2675
|
if inferred is None and domain is None:
|
|
@@ -9796,7 +9803,192 @@ def script_scene_diff(
|
|
|
9796
9803
|
@main.group("translate")
|
|
9797
9804
|
@click.pass_context
|
|
9798
9805
|
def translate_group(ctx: click.Context) -> None:
|
|
9799
|
-
"""
|
|
9806
|
+
"""故事归化:Agent 本地细读原著、文化重构、候选回填与人审。"""
|
|
9807
|
+
|
|
9808
|
+
|
|
9809
|
+
_RECREATION_KINDS = [
|
|
9810
|
+
"source_story_model", "target_story_contract", "recreation_strategy",
|
|
9811
|
+
"cultural_mapping_set", "protection_conflict_decision", "pilot",
|
|
9812
|
+
"scale_plan", "recreation_unit",
|
|
9813
|
+
]
|
|
9814
|
+
|
|
9815
|
+
|
|
9816
|
+
@translate_group.command("state")
|
|
9817
|
+
@click.argument("project_id")
|
|
9818
|
+
@click.option("--unit-key", default=None, help="按归化工作包键读取本次正文事实或方法")
|
|
9819
|
+
@click.option("--read-kind", type=click.Choice(["facts", "methods"]), default=None)
|
|
9820
|
+
@click.option("--execution-token", envvar="SCRIPTNOW_CREATIVE_ATTEMPT", default=None)
|
|
9821
|
+
@click.option("--json", "json_output", is_flag=True)
|
|
9822
|
+
@click.pass_context
|
|
9823
|
+
def translate_state(ctx: click.Context, project_id: str, unit_key: str | None,
|
|
9824
|
+
read_kind: str | None, execution_token: str | None,
|
|
9825
|
+
json_output: bool) -> None:
|
|
9826
|
+
"""Read adopted baseline, candidates and dependency freshness."""
|
|
9827
|
+
if unit_key or read_kind:
|
|
9828
|
+
if not unit_key or not read_kind or not execution_token:
|
|
9829
|
+
raise click.ClickException("单元读取须同时提供 --unit-key、--read-kind 和 --execution-token")
|
|
9830
|
+
_emit(_session(ctx).request(
|
|
9831
|
+
"POST", f"/cross-cultural-recreations/by-project/{project_id}/work-packages/{unit_key}/reads/{read_kind}",
|
|
9832
|
+
headers={"X-Creative-Attempt": execution_token}, write=True,
|
|
9833
|
+
), json_output)
|
|
9834
|
+
return
|
|
9835
|
+
_emit(_session(ctx).request("GET", f"/cross-cultural-recreations/by-project/{project_id}"), json_output)
|
|
9836
|
+
|
|
9837
|
+
|
|
9838
|
+
@translate_group.command("contract")
|
|
9839
|
+
@click.argument("project_id")
|
|
9840
|
+
@click.argument("kind", type=click.Choice(_RECREATION_KINDS))
|
|
9841
|
+
@click.option("--work-package-key", default=None, help="recreation_unit 的工作包键")
|
|
9842
|
+
@click.option("--json", "json_output", is_flag=True)
|
|
9843
|
+
@click.pass_context
|
|
9844
|
+
def translate_contract(ctx: click.Context, project_id: str, kind: str,
|
|
9845
|
+
work_package_key: str | None, json_output: bool) -> None:
|
|
9846
|
+
"""Read current dependency versions before local creation."""
|
|
9847
|
+
_emit(_session(ctx).request("GET", f"/cross-cultural-recreations/by-project/{project_id}/contract/{kind}",
|
|
9848
|
+
params={"work_package_key": work_package_key} if work_package_key else None), json_output)
|
|
9849
|
+
|
|
9850
|
+
|
|
9851
|
+
@translate_group.command("propose")
|
|
9852
|
+
@click.argument("project_id")
|
|
9853
|
+
@click.argument("kind", type=click.Choice(_RECREATION_KINDS))
|
|
9854
|
+
@click.argument("file_path")
|
|
9855
|
+
@click.option("--contract", "contract_path", required=True, help="保存的 translate contract --json 回执文件;重试须复用同一份")
|
|
9856
|
+
@click.option("--execution-token", envvar="SCRIPTNOW_CREATIVE_ATTEMPT", required=True)
|
|
9857
|
+
@click.option("--request-key", required=True)
|
|
9858
|
+
@click.option("--work-package-key", default=None, help="仅 recreation_unit 需要")
|
|
9859
|
+
@click.option("--material-digest", default=None, help="recreation_unit 的服务端选中方法回执摘要")
|
|
9860
|
+
@click.option("--json", "json_output", is_flag=True)
|
|
9861
|
+
@click.pass_context
|
|
9862
|
+
def translate_propose(
|
|
9863
|
+
ctx: click.Context, project_id: str, kind: str, file_path: str,
|
|
9864
|
+
contract_path: str,
|
|
9865
|
+
execution_token: str, request_key: str, work_package_key: str | None,
|
|
9866
|
+
material_digest: str | None,
|
|
9867
|
+
json_output: bool,
|
|
9868
|
+
) -> None:
|
|
9869
|
+
"""Submit one local-Agent result as a candidate; never adopts it."""
|
|
9870
|
+
payload = read_json_object(file_path)
|
|
9871
|
+
contract = read_json_object(contract_path)
|
|
9872
|
+
if contract.get("project_id") != project_id or contract.get("kind") != kind:
|
|
9873
|
+
raise click.ClickException("归化契约的项目或候选种类与本次提交不一致")
|
|
9874
|
+
if contract.get("missing_prerequisites") or contract.get("missing_prior_units") or contract.get("stale_prerequisites"):
|
|
9875
|
+
raise click.ClickException("归化契约尚未就绪,请先处理前置与需复核项")
|
|
9876
|
+
if kind == "recreation_unit" and not work_package_key:
|
|
9877
|
+
raise click.ClickException("recreation_unit 必须指定 --work-package-key")
|
|
9878
|
+
if kind == "recreation_unit" and not material_digest:
|
|
9879
|
+
raise click.ClickException("recreation_unit 必须先读取方法并提供 --material-digest")
|
|
9880
|
+
if kind == "recreation_unit" and contract.get("resource_id") != work_package_key:
|
|
9881
|
+
raise click.ClickException("归化契约工作包键与本次提交不一致")
|
|
9882
|
+
result = _session(ctx).request(
|
|
9883
|
+
"POST", f"/cross-cultural-recreations/by-project/{project_id}/candidates/{kind}",
|
|
9884
|
+
json_body={"payload": payload, "expected_dependencies": contract["dependency_versions"],
|
|
9885
|
+
"expected_prior_units": contract.get("prior_units") or {},
|
|
9886
|
+
"material_digest": material_digest,
|
|
9887
|
+
"request_key": request_key, "work_package_key": work_package_key},
|
|
9888
|
+
headers={"X-Creative-Attempt": execution_token}, write=True,
|
|
9889
|
+
)
|
|
9890
|
+
_emit(result, json_output)
|
|
9891
|
+
|
|
9892
|
+
|
|
9893
|
+
@translate_group.command("adopt")
|
|
9894
|
+
@click.argument("project_id")
|
|
9895
|
+
@click.argument("candidate_id")
|
|
9896
|
+
@click.option("--kind", type=click.Choice(["artifact", "unit"]), required=True)
|
|
9897
|
+
@click.option("--review-token", required=True)
|
|
9898
|
+
@click.option("--json", "json_output", is_flag=True)
|
|
9899
|
+
@click.pass_context
|
|
9900
|
+
def translate_adopt(
|
|
9901
|
+
ctx: click.Context, project_id: str, candidate_id: str, kind: str,
|
|
9902
|
+
review_token: str, json_output: bool,
|
|
9903
|
+
) -> None:
|
|
9904
|
+
"""Adopt a saved candidate after separate human review."""
|
|
9905
|
+
path = (f"/cross-cultural-recreations/by-project/{project_id}/artifacts/{candidate_id}/adopt"
|
|
9906
|
+
if kind == "artifact" else
|
|
9907
|
+
f"/cross-cultural-recreations/by-project/{project_id}/production-units/{candidate_id}/adopt")
|
|
9908
|
+
_emit(_session(ctx).request("POST", path, headers={"X-Review-Token": review_token}, write=True), json_output)
|
|
9909
|
+
|
|
9910
|
+
|
|
9911
|
+
@translate_group.command("review-unit")
|
|
9912
|
+
@click.argument("project_id")
|
|
9913
|
+
@click.argument("unit_id")
|
|
9914
|
+
@click.option("--json", "json_output", is_flag=True)
|
|
9915
|
+
@click.pass_context
|
|
9916
|
+
def translate_review_unit(ctx: click.Context, project_id: str, unit_id: str, json_output: bool) -> None:
|
|
9917
|
+
"""Run the platform's deterministic review on a saved recreation unit."""
|
|
9918
|
+
_emit(_session(ctx).request(
|
|
9919
|
+
"POST", f"/cross-cultural-recreations/by-project/{project_id}/production-units/{unit_id}/review",
|
|
9920
|
+
write=True,
|
|
9921
|
+
), json_output)
|
|
9922
|
+
|
|
9923
|
+
|
|
9924
|
+
@translate_group.command("revise-unit")
|
|
9925
|
+
@click.argument("project_id")
|
|
9926
|
+
@click.argument("unit_id")
|
|
9927
|
+
@click.argument("file_path")
|
|
9928
|
+
@click.option("--request-key", required=True)
|
|
9929
|
+
@click.option("--json", "json_output", is_flag=True)
|
|
9930
|
+
@click.pass_context
|
|
9931
|
+
def translate_revise_unit(ctx: click.Context, project_id: str, unit_id: str,
|
|
9932
|
+
file_path: str, request_key: str, json_output: bool) -> None:
|
|
9933
|
+
"""Save an author-edited title and draft as a new candidate version."""
|
|
9934
|
+
payload = read_json_object(file_path)
|
|
9935
|
+
if not isinstance(payload.get("title"), str) or not isinstance(payload.get("target_language_draft"), str):
|
|
9936
|
+
raise click.ClickException("人工修订文件须包含 title 与 target_language_draft")
|
|
9937
|
+
_emit(_session(ctx).request(
|
|
9938
|
+
"POST", f"/cross-cultural-recreations/by-project/{project_id}/production-units/{unit_id}/revisions",
|
|
9939
|
+
json_body={"title": payload["title"], "target_language_draft": payload["target_language_draft"],
|
|
9940
|
+
"idempotency_key": request_key}, write=True,
|
|
9941
|
+
), json_output)
|
|
9942
|
+
|
|
9943
|
+
|
|
9944
|
+
@translate_group.command("manuscript")
|
|
9945
|
+
@click.argument("project_id")
|
|
9946
|
+
@click.option("--work-package-key", "work_package_keys", multiple=True)
|
|
9947
|
+
@click.option("--scale-plan-id", default=None, help="历史稿的整书方案 ID")
|
|
9948
|
+
@click.option("--json", "json_output", is_flag=True)
|
|
9949
|
+
@click.pass_context
|
|
9950
|
+
def translate_manuscript(ctx: click.Context, project_id: str,
|
|
9951
|
+
work_package_keys: tuple[str, ...], scale_plan_id: str | None,
|
|
9952
|
+
json_output: bool) -> None:
|
|
9953
|
+
"""Read adopted recreation prose with its exact baseline status."""
|
|
9954
|
+
params: dict[str, Any] = {}
|
|
9955
|
+
if work_package_keys:
|
|
9956
|
+
params["work_package_keys"] = list(work_package_keys)
|
|
9957
|
+
if scale_plan_id:
|
|
9958
|
+
params["scale_plan_id"] = scale_plan_id
|
|
9959
|
+
_emit(_session(ctx).request(
|
|
9960
|
+
"GET", f"/cross-cultural-recreations/by-project/{project_id}/manuscript",
|
|
9961
|
+
params=params or None,
|
|
9962
|
+
), json_output)
|
|
9963
|
+
|
|
9964
|
+
|
|
9965
|
+
@translate_group.command("export")
|
|
9966
|
+
@click.argument("project_id")
|
|
9967
|
+
@click.option("--work-package-key", "work_package_keys", multiple=True)
|
|
9968
|
+
@click.option("--scale-plan-id", default=None, help="历史稿的整书方案 ID")
|
|
9969
|
+
@click.option("--output", "-o", required=True, type=click.Path(dir_okay=False))
|
|
9970
|
+
@click.option("--json", "json_output", is_flag=True)
|
|
9971
|
+
@click.pass_context
|
|
9972
|
+
def translate_export(ctx: click.Context, project_id: str,
|
|
9973
|
+
work_package_keys: tuple[str, ...], scale_plan_id: str | None,
|
|
9974
|
+
output: str, json_output: bool) -> None:
|
|
9975
|
+
"""Download the adopted recreation DOCX for a declared baseline."""
|
|
9976
|
+
params: dict[str, Any] = {}
|
|
9977
|
+
if work_package_keys:
|
|
9978
|
+
params["work_package_keys"] = list(work_package_keys)
|
|
9979
|
+
if scale_plan_id:
|
|
9980
|
+
params["scale_plan_id"] = scale_plan_id
|
|
9981
|
+
response = _session(ctx).request(
|
|
9982
|
+
"GET", f"/cross-cultural-recreations/by-project/{project_id}/export.docx",
|
|
9983
|
+
params=params or None, raw=True, timeout=300,
|
|
9984
|
+
)
|
|
9985
|
+
if not response.content.startswith(b"PK"):
|
|
9986
|
+
raise click.ClickException("平台返回的归化稿不是 DOCX 文件")
|
|
9987
|
+
destination = Path(output)
|
|
9988
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
9989
|
+
destination.write_bytes(response.content)
|
|
9990
|
+
_emit({"path": str(destination), "bytes": len(response.content),
|
|
9991
|
+
"baseline": response.headers.get("X-ScriptNow-Baseline", "unverified")}, json_output)
|
|
9800
9992
|
|
|
9801
9993
|
|
|
9802
9994
|
@translate_group.command("create")
|
|
@@ -9840,11 +10032,11 @@ def translate_create(
|
|
|
9840
10032
|
@click.option("--json", "json_output", is_flag=True)
|
|
9841
10033
|
@click.pass_context
|
|
9842
10034
|
def translate_analyze_source(ctx: click.Context, project_id: str, json_output: bool) -> None:
|
|
9843
|
-
"""
|
|
9844
|
-
|
|
9845
|
-
"
|
|
10035
|
+
"""Legacy entry: read the source locally and propose its story model."""
|
|
10036
|
+
raise click.ClickException(
|
|
10037
|
+
"请在 Agent 本地完整读取原著,再用 translate contract/source_story_model "
|
|
10038
|
+
"与 run claim + translate propose 回填来源模型候选;平台不代读原文。"
|
|
9846
10039
|
)
|
|
9847
|
-
_emit(result, json_output)
|
|
9848
10040
|
|
|
9849
10041
|
|
|
9850
10042
|
@translate_group.command("target-contract")
|
|
@@ -9862,20 +10054,10 @@ def translate_target_contract(
|
|
|
9862
10054
|
cultural_distance: str,
|
|
9863
10055
|
json_output: bool,
|
|
9864
10056
|
) -> None:
|
|
9865
|
-
"""
|
|
9866
|
-
|
|
9867
|
-
"
|
|
9868
|
-
"
|
|
9869
|
-
"cultural_distance": cultural_distance,
|
|
9870
|
-
}
|
|
9871
|
-
_emit(
|
|
9872
|
-
_session(ctx).request(
|
|
9873
|
-
"POST",
|
|
9874
|
-
f"/cross-cultural-recreations/by-project/{project_id}/target-contract",
|
|
9875
|
-
json_body=body,
|
|
9876
|
-
write=True,
|
|
9877
|
-
),
|
|
9878
|
-
json_output,
|
|
10057
|
+
"""Legacy entry: use a reviewed target-intent candidate."""
|
|
10058
|
+
raise click.ClickException(
|
|
10059
|
+
"旧 target-contract 参数不能表达完整归化边界,且旧接口会直接采纳。"
|
|
10060
|
+
"请用 translate contract target_story_contract、run claim 与 translate propose 回填候选。"
|
|
9879
10061
|
)
|
|
9880
10062
|
|
|
9881
10063
|
|
|
@@ -9884,11 +10066,11 @@ def translate_target_contract(
|
|
|
9884
10066
|
@click.option("--json", "json_output", is_flag=True)
|
|
9885
10067
|
@click.pass_context
|
|
9886
10068
|
def translate_strategies(ctx: click.Context, project_id: str, json_output: bool) -> None:
|
|
9887
|
-
"""
|
|
9888
|
-
|
|
9889
|
-
"
|
|
10069
|
+
"""Legacy entry: create a cultural-reconstruction strategy locally."""
|
|
10070
|
+
raise click.ClickException(
|
|
10071
|
+
"请在 Agent 中构思故事归化方案,并通过 translate contract/recreation_strategy "
|
|
10072
|
+
"与 run claim + translate propose 保存候选。"
|
|
9890
10073
|
)
|
|
9891
|
-
_emit(result, json_output)
|
|
9892
10074
|
|
|
9893
10075
|
|
|
9894
10076
|
@translate_group.command("mappings")
|
|
@@ -9896,11 +10078,11 @@ def translate_strategies(ctx: click.Context, project_id: str, json_output: bool)
|
|
|
9896
10078
|
@click.option("--json", "json_output", is_flag=True)
|
|
9897
10079
|
@click.pass_context
|
|
9898
10080
|
def translate_mappings(ctx: click.Context, project_id: str, json_output: bool) -> None:
|
|
9899
|
-
"""
|
|
9900
|
-
|
|
9901
|
-
"
|
|
10081
|
+
"""Legacy entry: submit only mappings needed by the chosen strategy."""
|
|
10082
|
+
raise click.ClickException(
|
|
10083
|
+
"请仅对实际迁移或重构的文化载体写明叙事功能与因果理由,"
|
|
10084
|
+
"再经 translate contract/cultural_mapping_set 与 translate propose 保存候选。"
|
|
9902
10085
|
)
|
|
9903
|
-
_emit(result, json_output)
|
|
9904
10086
|
|
|
9905
10087
|
|
|
9906
10088
|
# -------------------------------------------------------------------- storyboard
|
|
@@ -81,6 +81,7 @@ CLI 是执行工具;本 Skill 是协作入口;平台是项目事实源。
|
|
|
81
81
|
| 选择写作方法、挂载 Skill、剧本格式与 Method DNA | [methods](references/methods.md) |
|
|
82
82
|
| dsh 逐章或逐场正文、执行权领取与续租、候选回填 | [writing](references/writing.md) |
|
|
83
83
|
| 用户明确要求分镜与制作交付 | [storyboard](references/storyboard.md) |
|
|
84
|
+
| 小说故事归化、本地原著分析、文化重构与试写 | [recreation](references/recreation.md) |
|
|
84
85
|
|
|
85
86
|
## 每次执行都要守住
|
|
86
87
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# 故事归化:本地细读、文化重构、候选回填
|
|
2
|
+
|
|
3
|
+
只用于小说归化项目。原著文件、抽取全文、扫描图像、章节切分和逐页阅读记录留在当前 Agent 环境;平台只保存有边界的源身份、覆盖自证、故事分析、文化决策和创作候选。`scriptnow_read_document` 返回 `truncated` 时继续按 offset 读取;扫描无文本层、缺页或读取失败必须如实列在自证里,不能把读到首页称为通读。平台只能检查自证形状,不能替作者证明已读完。
|
|
4
|
+
|
|
5
|
+
先把原作里的关键元素写成“它在故事中做什么”:谁因什么制度、关系或期待受阻,采取什么行动,改变谁的处境。再与作者确定目标读者、类型承诺、发行场景和背景边界。目标语言不自动决定背景地点。对每个真正需要处理的文化载体,选择保留、解释、迁移或重构;迁移或重构须写明新载体和人物动机、因果变化。触及作者保护项时先提交冲突决策候选,等作者明确采纳。不要凑满类别或固定国家、章节数、字数、评分轮次。
|
|
6
|
+
|
|
7
|
+
执行顺序:`translate state <作品号> --json` 看当前已采纳基线;`translate contract <作品号> <kind> --json` 读必需依赖与作用域并原样保存为 `@contract.json`;`run claim <作品号> <kind> <资源号> --domain novel --task-key ... --attempt-key ... --json` 领取本次候选写资格;Agent 本地创作 `@file.json`;`translate propose <作品号> <kind> @file.json --contract @contract.json --execution-token ... --request-key ... --json` 回填;再次 `translate state` 回读候选。`recreation_unit` 的资源号和 `--work-package-key` 都是已采纳方案中的工作包键,其契约用 `translate contract <作品号> recreation_unit --work-package-key <键> --json` 取得。重试同一请求须保留同一契约文件、请求键、凭据和内容;候选回执只证明已保存,不证明已采纳。
|
|
8
|
+
|
|
9
|
+
成果依故事需要推进:源故事模型候选(`source_identity` 含 title 与 `sha256:<64位十六进制>` 指纹;`coverage_attestation.units[]` 写本地 unit_id/length,read_ranges[] 写 unit_id/start/end,anchor_refs[] 写 unit_id/start/end/digest/summary,并如实写 complete/truncated/unread_ranges;连贯叙事写进 `story_summary`)→ 作者采纳 → 目标意图候选(`target_intent` 连贯叙述)→ 策略候选(`story_proposal` 连贯叙述,可附 `transformations`)→ 对实际迁移/重构的载体提交映射候选 → 对实际触碰的保护项提交决策候选 → 选文化或因果风险最高的片段试写(`unit_title`、`rationale`、`target_language_draft`)→ 整书方案(`target_story_bible`、有序 `work_packages`)→ 串行逐章候选。每个 transformation 需要 `source_element`、`narrative_function`、`treatment`、`causal_reason`;relocate/reconstruct 还需 `target_carrier`。映射须解释旧元素的叙事功能、目标承载和因果理由。试写是可修改的实验,不把模拟审读称为真人读者验证。
|
|
10
|
+
|
|
11
|
+
逐章前用同一 `recreation_unit` 执行凭据分别调用 `translate state <作品号> --unit-key <键> --read-kind facts --execution-token ... --json` 和 `--read-kind methods`;服务端回执证明本次 attempt 真正读取了已采纳事实、前序单元和所选方法全文。`material_digest` 来自 methods 回执,随 `translate propose ... --material-digest ...` 提交。归化工作包不是普通 novel chapter ID,方法选择按项目 scope 解析;读取并不证明模型实际应用方法。上一工作包未采纳、修订后版本已变、方法未就绪或未取得两种读取回执,正式章节候选被拒绝。
|
|
12
|
+
|
|
13
|
+
采纳前用 `translate state` 找到候选号与完整内容;向作者展示原文分析、目标方案、试写或章节候选的完整版本及受影响依赖。章节候选先 `translate review-unit <作品号> <候选号>`,需要人工改稿可用 `translate revise-unit <作品号> <候选号> @revision.json --request-key ...` 另存候选。作者明确保留时走 review preview→confirm→claim,再 `translate adopt <作品号> <候选号> --kind artifact|unit --review-token ...`。写资格绝不自动采纳。上游改变后查看 `stale_dependencies`,旧候选不能当作当前版本采纳;`translate manuscript` 和 `translate export -o 稿.docx` 可按指定基线交付历史稿,并明确需复核状态。旧 `/analyze-source` 已停用;其余平台生成只作作者显式选择的后台后备,仍产候选并走同一人审。
|
|
@@ -14,6 +14,7 @@ cli_anything/scriptnow/skills/agents/openai.yaml
|
|
|
14
14
|
cli_anything/scriptnow/skills/references/methods.md
|
|
15
15
|
cli_anything/scriptnow/skills/references/operations.md
|
|
16
16
|
cli_anything/scriptnow/skills/references/planning.md
|
|
17
|
+
cli_anything/scriptnow/skills/references/recreation.md
|
|
17
18
|
cli_anything/scriptnow/skills/references/review.md
|
|
18
19
|
cli_anything/scriptnow/skills/references/setup.md
|
|
19
20
|
cli_anything/scriptnow/skills/references/storyboard.md
|
|
@@ -57,5 +58,6 @@ tests/test_session.py
|
|
|
57
58
|
tests/test_session_isolation.py
|
|
58
59
|
tests/test_skill_bundle.py
|
|
59
60
|
tests/test_storyboard_commands.py
|
|
61
|
+
tests/test_translate_local_commands.py
|
|
60
62
|
tests/test_unbound_aliases.py
|
|
61
63
|
tests/test_upgrade.py
|
|
@@ -120,7 +120,7 @@ def test_runtime_contract_has_dsh_default_and_order() -> None:
|
|
|
120
120
|
rc = _AGENT_RUNTIME_CONTRACT
|
|
121
121
|
# 契约版本写死以迫使行为变更时同步更新此测试。16 要求
|
|
122
122
|
# dsh 正文读取选中方法并携带内容摘要,候选仍独立于采纳。
|
|
123
|
-
assert rc["contract_version"] == "
|
|
123
|
+
assert rc["contract_version"] == "18"
|
|
124
124
|
rules = NL.join(rc["rules"])
|
|
125
125
|
assert "创作顺序固定为 12 步" in rules
|
|
126
126
|
assert "规划回填优先" in rules
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from types import SimpleNamespace
|
|
3
|
+
|
|
4
|
+
from click.testing import CliRunner
|
|
5
|
+
|
|
6
|
+
from cli_anything.scriptnow import scriptnow_cli as cli
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FakeSession:
|
|
10
|
+
def __init__(self):
|
|
11
|
+
self.calls = []
|
|
12
|
+
|
|
13
|
+
def request(self, method, path, **kwargs):
|
|
14
|
+
self.calls.append((method, path, kwargs))
|
|
15
|
+
if kwargs.get("raw"):
|
|
16
|
+
return SimpleNamespace(content=b"PKsynthetic-docx", headers={"X-ScriptNow-Baseline": "current"})
|
|
17
|
+
return {"id": "candidate-1", "status": "candidate"}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_translate_propose_sends_frozen_contract_and_attempt(tmp_path, monkeypatch):
|
|
21
|
+
payload = tmp_path / "source.json"
|
|
22
|
+
payload.write_text(json.dumps({"story_summary": "A promise changes a family."}), encoding="utf-8")
|
|
23
|
+
contract = tmp_path / "contract.json"
|
|
24
|
+
contract.write_text(json.dumps({
|
|
25
|
+
"project_id": "project-1", "kind": "source_story_model",
|
|
26
|
+
"dependency_versions": {}, "missing_prerequisites": [],
|
|
27
|
+
}), encoding="utf-8")
|
|
28
|
+
session = FakeSession()
|
|
29
|
+
monkeypatch.setattr(cli, "_session", lambda _ctx: session)
|
|
30
|
+
result = CliRunner().invoke(cli.main, [
|
|
31
|
+
"translate", "propose", "project-1", "source_story_model", f"@{payload}",
|
|
32
|
+
"--contract", f"@{contract}", "--execution-token", "attempt-1",
|
|
33
|
+
"--request-key", "save-1", "--json",
|
|
34
|
+
])
|
|
35
|
+
assert result.exit_code == 0, result.output
|
|
36
|
+
assert len(session.calls) == 1
|
|
37
|
+
method, path, options = session.calls[0]
|
|
38
|
+
assert method == "POST"
|
|
39
|
+
assert path == "/cross-cultural-recreations/by-project/project-1/candidates/source_story_model"
|
|
40
|
+
assert options["headers"]["X-Creative-Attempt"] == "attempt-1"
|
|
41
|
+
assert options["json_body"]["expected_dependencies"] == {}
|
|
42
|
+
assert options["json_body"]["request_key"] == "save-1"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_translate_legacy_command_explains_local_delivery(monkeypatch):
|
|
46
|
+
session = FakeSession()
|
|
47
|
+
monkeypatch.setattr(cli, "_session", lambda _ctx: session)
|
|
48
|
+
result = CliRunner().invoke(cli.main, ["translate", "analyze-source", "project-1", "--json"])
|
|
49
|
+
assert result.exit_code != 0
|
|
50
|
+
assert "本地" in result.output
|
|
51
|
+
assert session.calls == []
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_translate_state_stays_read_only_when_attempt_env_is_present(monkeypatch):
|
|
55
|
+
session = FakeSession()
|
|
56
|
+
monkeypatch.setattr(cli, "_session", lambda _ctx: session)
|
|
57
|
+
result = CliRunner().invoke(
|
|
58
|
+
cli.main, ["translate", "state", "project-1", "--json"],
|
|
59
|
+
env={"SCRIPTNOW_CREATIVE_ATTEMPT": "ea1.synthetic.token"},
|
|
60
|
+
)
|
|
61
|
+
assert result.exit_code == 0, result.output
|
|
62
|
+
assert session.calls == [("GET", "/cross-cultural-recreations/by-project/project-1", {})]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_translate_unit_review_revision_manuscript_and_export(tmp_path, monkeypatch):
|
|
66
|
+
session = FakeSession()
|
|
67
|
+
monkeypatch.setattr(cli, "_session", lambda _ctx: session)
|
|
68
|
+
runner = CliRunner()
|
|
69
|
+
revision = tmp_path / "revision.json"
|
|
70
|
+
revision.write_text(json.dumps({"title": "Revised", "target_language_draft": "New prose"}), encoding="utf-8")
|
|
71
|
+
for args in (
|
|
72
|
+
["translate", "state", "project-1", "--json"],
|
|
73
|
+
["translate", "contract", "project-1", "source_story_model", "--json"],
|
|
74
|
+
["translate", "review-unit", "project-1", "unit-1", "--json"],
|
|
75
|
+
["translate", "adopt", "project-1", "unit-1", "--kind", "unit",
|
|
76
|
+
"--review-token", "human-token", "--json"],
|
|
77
|
+
["translate", "revise-unit", "project-1", "unit-1", f"@{revision}", "--request-key", "revision-1", "--json"],
|
|
78
|
+
["translate", "manuscript", "project-1", "--work-package-key", "1", "--scale-plan-id", "plan-1", "--json"],
|
|
79
|
+
):
|
|
80
|
+
result = runner.invoke(cli.main, args)
|
|
81
|
+
assert result.exit_code == 0, result.output
|
|
82
|
+
assert session.calls[0][0] == "GET" and session.calls[0][1].endswith("/by-project/project-1")
|
|
83
|
+
assert session.calls[1][1].endswith("/contract/source_story_model")
|
|
84
|
+
assert session.calls[2][1].endswith("/production-units/unit-1/review")
|
|
85
|
+
assert session.calls[3][2]["headers"]["X-Review-Token"] == "human-token"
|
|
86
|
+
assert session.calls[4][2]["json_body"]["idempotency_key"] == "revision-1"
|
|
87
|
+
assert session.calls[5][2]["params"] == {"work_package_keys": ["1"], "scale_plan_id": "plan-1"}
|
|
88
|
+
target = tmp_path / "recreation.docx"
|
|
89
|
+
exported = runner.invoke(cli.main, ["translate", "export", "project-1", "-o", str(target), "--json"])
|
|
90
|
+
assert exported.exit_code == 0, exported.output
|
|
91
|
+
assert target.read_bytes() == b"PKsynthetic-docx"
|
|
92
|
+
assert json.loads(exported.output)["baseline"] == "current"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/agents/openai.yaml
RENAMED
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/methods.md
RENAMED
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/operations.md
RENAMED
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/planning.md
RENAMED
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/review.md
RENAMED
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/setup.md
RENAMED
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/storyboard.md
RENAMED
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/skills/references/writing.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scriptnow_cli-0.4.14 → scriptnow_cli-0.4.19}/cli_anything/scriptnow/utils/request_identity.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|