dsh-novel-write-engine 0.2.6 → 0.2.8
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/CHANGELOG.md +58 -5
- package/README.md +411 -982
- package/briefs/P2.md +1 -1
- package/briefs/P8.md +4 -4
- package/lib/client.js +15 -10
- package/lib/index.d.ts +69 -3
- package/lib/index.js +284 -69
- package/lib/types/client/dto.d.ts +20 -0
- package/lib/types/client/viewmodel.d.ts +2 -0
- package/lib/types/types.d.ts +37 -1
- package/package.json +1 -1
package/briefs/P2.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|---|---|
|
|
20
20
|
| `title` | 不带「第N章」前缀;长度读 rulepack 的 `format.title.min_chars/max_chars`,引擎会拼前缀并校验 |
|
|
21
21
|
| `scene_type` | 四选一:战斗/动作章、日常过渡章、情感爆发章、纯叙事章 |
|
|
22
|
-
| `narrator` | 视角人物,必须在本章出场;第一人称写成
|
|
22
|
+
| `narrator` | 视角人物,必须在本章出场;第一人称写成 `主角(第一人称「我」)`,引擎接受括号/引号里的正文别名 |
|
|
23
23
|
| `beats` | 5~8 个节拍,每个是一句话的可检验动作 |
|
|
24
24
|
| `opening` | 前两段打算怎么写(场景 + 动作 + 一个钩子) |
|
|
25
25
|
| `ending` | 断章点,必须是新信息或新麻烦 |
|
package/briefs/P8.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
- `timeline` 的键是 `summary.events` 的下标(字符串)。
|
|
29
29
|
- `relationships` 的键是 `"甲|乙"`;每项至少 `{ "action": "created", "type": "关系类型", "description": "..." }`,缺 `type` 会被拒绝。
|
|
30
30
|
- `characters` 的键是人物名;`world` 的键是新地点/能力/物品名;`foreshadows` 的键是 summary 里的 planted key 或已分配的 `FS-xxx`。
|
|
31
|
-
- `foreshadows` 的 `summary.foreshadows.resolved` 里列出的 key,delta 必须写 `action: "updated"`;引擎会把 `resolved_at` 写成当前章,并把 `note`/`new_info` 追加到 `advance_log`。示例:`"FS-002": {"action":"updated","note":"
|
|
31
|
+
- `foreshadows` 的 `summary.foreshadows.resolved` 里列出的 key,delta 必须写 `action: "updated"`;引擎会把 `resolved_at` 写成当前章,并把 `note`/`new_info` 追加到 `advance_log`。示例:`"FS-002": {"action":"updated","note":"债务已结清","new_info":true}`。
|
|
32
32
|
|
|
33
33
|
## 最小 schema
|
|
34
34
|
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
}
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
错误会带上 `expected` 形态和收到的字段值,例如 `characters
|
|
84
|
+
错误会带上 `expected` 形态和收到的字段值,例如 `characters.主角.current_state must be an object; expected {"resources":{"资源名":3},...}`。不要猜字段名,按报错补齐即可。`current_state.resources` 会与旧余额深合并,余额必须是有限非负整数。
|
|
85
85
|
|
|
86
86
|
## summary 与 delta 的联动(归档前必核)
|
|
87
87
|
|
|
@@ -95,9 +95,9 @@
|
|
|
95
95
|
|
|
96
96
|
如果 summary 与本章事实不符,先走 **summary-only** 修复:`novel_revise {chapter, summary}`(不带 content/patch/proof)只更新 draft.summary,不消耗 revise 轮次、不改正文,然后按当前阶段继续;只有正文需要改时才走 P5 全文修订。
|
|
97
97
|
|
|
98
|
-
- **伏笔的 title 是可读标签,anchor 才是校验证据**:`title`
|
|
98
|
+
- **伏笔的 title 是可读标签,anchor 才是校验证据**:`title` 可以写「欠款」这样的短语;要归档,请把正文原句放进 `anchor`(summary 的 planted 项或 delta 项都行,至少 8 个字符)。没有 `anchor` 时,`title` 必须逐字出现在正文里,否则 `ENGINE_DELTA_UNVERIFIED`。示例:`{"action":"created","title":"欠款","anchor":"那笔欠款还没有还清","description":"欠款未清"}`。
|
|
99
99
|
- 归档失败的报错会指出字段、值和缺失的锚点;不要把 title 改成碎片来“凑命中”,补 `anchor` 即可。
|
|
100
|
-
- 第一人称的叙述者若在 `narrator` 里声明为
|
|
100
|
+
- 第一人称的叙述者若在 `narrator` 里声明为 `主角(第一人称「我」)`,正文用「我」也视为出现,但角色键仍写 `主角`。
|
|
101
101
|
- 每个新实体写 `action: "created"`(正文出现、kind 可确定);已存在实体写 `updated` 或 `no_change`,引擎会按台账归一化冲突并给 warning。
|
|
102
102
|
- `world` 新实体还要写 `kind: "location"|"ability"|"artifact"|"faction"|"rule"` 和 `description`。
|
|
103
103
|
- `state_delta` 可以是对象,也可以是 JSON 字符串;引擎两者都接受。
|
package/lib/client.js
CHANGED
|
@@ -50,9 +50,9 @@ window.__ModuleLoader__.load({
|
|
|
50
50
|
P4: "评审",
|
|
51
51
|
P5: "修订",
|
|
52
52
|
P6: "一致性",
|
|
53
|
-
P7: "
|
|
54
|
-
P8: "
|
|
55
|
-
P9: "
|
|
53
|
+
P7: "状态同步",
|
|
54
|
+
P8: "终审",
|
|
55
|
+
P9: "归档"
|
|
56
56
|
};
|
|
57
57
|
const STAGE_LABELS = {
|
|
58
58
|
idle: "待开始",
|
|
@@ -332,8 +332,10 @@ window.__ModuleLoader__.load({
|
|
|
332
332
|
const rowAverage = scored.length === 0 ? 0 : scored.reduce((sum, row) => sum + row.scoreValue, 0) / scored.length;
|
|
333
333
|
const average = summary.averageScore !== void 0 && Number.isFinite(summary.averageScore) ? summary.averageScore : rowAverage;
|
|
334
334
|
const next = summary.next;
|
|
335
|
-
const
|
|
335
|
+
const progress = summary.progress;
|
|
336
|
+
const finished = progress?.finished ?? summary.finished === true;
|
|
336
337
|
const doneLabel = summary.stage === "done" ? finished ? "全书完成" : "本章已归档" : stageLabel(summary.stage);
|
|
338
|
+
const progressLine = progress?.label ?? (summary.stage === "done" ? finished ? `共 ${summary.totalChapters} 章` : `下一章 第 ${summary.chapter} 章` : `第 ${summary.chapter} 章`);
|
|
337
339
|
const selected = base.projects.find((project) => project.selected);
|
|
338
340
|
return {
|
|
339
341
|
...base,
|
|
@@ -343,7 +345,7 @@ window.__ModuleLoader__.load({
|
|
|
343
345
|
damaged: selected?.state === "damaged",
|
|
344
346
|
resumeText: payload.resume?.text ?? "",
|
|
345
347
|
volumeNumber: summary.volume,
|
|
346
|
-
subtitle:
|
|
348
|
+
subtitle: `${summary.genre} · ${platformLabel(summary.platform)} · ${progressLine}${volumeLabel(summary)}`,
|
|
347
349
|
stageLabel: doneLabel,
|
|
348
350
|
finished,
|
|
349
351
|
revisionLabel: `第 ${summary.bookData?.current.rounds.revise ?? summary.revision} 次修订`,
|
|
@@ -357,6 +359,8 @@ window.__ModuleLoader__.load({
|
|
|
357
359
|
stats: {
|
|
358
360
|
chapters: summary.totalChapters,
|
|
359
361
|
words: summary.totalWords,
|
|
362
|
+
...summary.archivedWords === void 0 ? {} : { archivedWords: summary.archivedWords },
|
|
363
|
+
...summary.draftWords === void 0 ? {} : { draftWords: summary.draftWords },
|
|
360
364
|
averageScore: Math.round(average * 10) / 10,
|
|
361
365
|
blocking: blocking.length
|
|
362
366
|
},
|
|
@@ -1146,7 +1150,7 @@ window.__ModuleLoader__.load({
|
|
|
1146
1150
|
title: "写书级蓝图与卷结构",
|
|
1147
1151
|
tool: "novel_blueprint",
|
|
1148
1152
|
body: "让模型先定 premise(故事前提)、logline(一句话卖点)、themes(主题)、tone(基调)、pov(视角)、audience(读者)、selling_points(卖点)、ending(结局方向)和 volumes(每卷起止章、目标、弧线、高潮)。",
|
|
1149
|
-
note: "
|
|
1153
|
+
note: "蓝图不是正文,可以后补。首次提交章卡时 strict 默认开启;要宽松写作可在蓝图里显式 strict:false 关闭。strict 开启后每章必须先有章卡;章卡一旦存在,标题、场景、目标字数和 cast 仍会校验。"
|
|
1150
1154
|
},
|
|
1151
1155
|
{
|
|
1152
1156
|
title: "排章卡,或导入现成大纲",
|
|
@@ -1219,7 +1223,7 @@ brief P6 → check → brief P8 → archive 的顺序推进。
|
|
|
1219
1223
|
每次提交前先领取当前阶段任务书,失败时按返回的 code 和 blocking 一次改完。`;
|
|
1220
1224
|
const TUTORIAL_NEXT_PROMPT = `继续写当前项目的下一章。先调用 novel_pipeline(或 novel_status)确认当前阶段、项目根目录和下一步工具,不要猜阶段。
|
|
1221
1225
|
如果当前会话还没绑定或不确定是哪本书:先用 /novel current 看会话绑定,再调用 novel_status 看 selection;需要切换时用 /novel use <路径|书名|.>,不要靠 active 猜。
|
|
1222
|
-
|
|
1226
|
+
第一次带 project_root 的项目调用会成为当前会话的持久绑定;后续无 root 调用会继续这本书。纯文本的 novel_word_count 和 novel_diff 不读取项目,也不会建立绑定。
|
|
1223
1227
|
|
|
1224
1228
|
如果下一章还没有章卡:用 novel_outline 只提交下一章的卡(按 num upsert),省略的已有卡会保持不动;不要重交全量,也不要用空数组清空。要删卡必须显式传 remove。
|
|
1225
1229
|
如果 targets.total_chapters 已经写满:先用 novel_amend 把 total_chapters 调到至少包含下一章,不能低于已归档章数。
|
|
@@ -1515,7 +1519,7 @@ brief P6 → check → brief P8 → archive 的顺序推进。
|
|
|
1515
1519
|
ref: closeRef,
|
|
1516
1520
|
onClick: onClose,
|
|
1517
1521
|
"aria-label": "关闭使用教程"
|
|
1518
|
-
}, (0, react.createElement)("span", { "aria-hidden": "true" }, "×"))), (0, react.createElement)("div", { className: "nwe-modal-body" }, (0, react.createElement)("div", { className: "nwe-tutorial-intro" }, (0, react.createElement)("p", null, "网文工坊不是一个“帮你想剧情”的按钮,而是一台有状态的写作引擎:你提供内容,引擎负责阶段、字数、门控、评审、归档和文件。"), (0, react.createElement)("p", null, "每一步都先领取当前阶段的任务书,再提交;提交后看引擎返回的 blocking 与下一步。面板只读,真正的写操作都在对话里的工具调用中。")), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "开始前:记住三件事"), (0, react.createElement)("div", { className: "nwe-tutorial-cards" }, (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "只用引擎入口写"), (0, react.createElement)("span", null, "正文只走 novel_write_draft / novel_revise;状态只走工具。手改 chapters/、state/、outline/ 会破坏事务与校验。")), (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "每一步先领 brief"), (0, react.createElement)("span", null, "任务书携带当前上下文和 digest;跳过它会撞 PG-01。任务书过期就重新领取,不要复用旧上下文。")), (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "失败先读 code"), (0, react.createElement)("span", null, "参数错改参数,门控没过改正文,系统故障查目录/稍后重试。blocking 会一次列全,一次改完再交。"))), (0, react.createElement)("p", { className: "nwe-tutorial-note" }, (0, react.createElement)("strong", null, "用哪个会话:"), " 想获得完整的引擎保证,请新开一个「网文工坊」预设会话;普通会话里模型可能还挂着文件工具,能绕过引擎直接改稿。")), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "一本书的完整流程"), (0, react.createElement)("p", null, "前四步是开书准备,后面是每章循环。第一次先按顺序走完一章,熟悉后再批量推进整本。"), (0, react.createElement)("ol", { className: "nwe-steps" }, ...TUTORIAL_STEPS.map((step, index) => tutorialStep(step, index)))), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "面板怎么看"), (0, react.createElement)("div", { className: "nwe-tutorial-cards" }, (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "顶部统计"), (0, react.createElement)("span", null, "已归档章、总字数、平均分、待处理门控。数字来自引擎,不是正文估算。")), (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "九阶段轨与下一步"), (0, react.createElement)("span", null, "亮起的阶段是当前进度,“下一步”卡会直接给出该调用的工具名。")), (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "章节与门控"), (0, react.createElement)("span", null, "章节卡展开可看字数、评分与状态;门控区按 code/detail/hint 列出所有阻塞。"))), (0, react.createElement)("p", { className: "nwe-tutorial-note" }, (0, react.createElement)("strong", null, "刷新:"), " 面板每 15 秒静默同步一次,也可以点右上角刷新。它是只读投影;不会替你改稿、归档或修状态。"), (0, react.createElement)("p", { className: "nwe-tutorial-note" }, (0, react.createElement)("strong", null, "项目状态:"), "选择器里 choose 表示发现多本书、还没选;项目不在了表示目录缺失,绑定仍会保留;不是项目表示目录还在但没有 novel.yaml 或项目状态;项目不可读表示权限或 IO 错误,先修权限或换一本。面板选择只影响查看,不改变任何会话的写作绑定。")), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "卡住时先看这里"), (0, react.createElement)("ul", { className: "nwe-faq" }, (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "为什么一直让我先领 brief?"), (0, react.createElement)("p", null, "这是正常门控。任务书决定当前阶段可用的字段与上下文 digest;先按返回值调用 novel_brief,再继续。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "门控失败,改一条还是全改?"), (0, react.createElement)("p", null, "一次看完所有 blocking,再一起改。逐条试会反复烧掉阶段轮次;错误里的 code 会告诉你属于参数、门控还是系统故障。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "字数和评分为什么对不上?"), (0, react.createElement)("p", null, "字数以 engine 返回为准,可用 novel_word_count 核对;review 的 total 必须等于 150 减全部扣分,不能另算一套。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "P4/P6 过不去怎么办?"), (0, react.createElement)("p", null, "P4 有 blocker 就领 P5 任务书修订,再回 P4 重评;P6 失败同样回修订。不要 waive blocker,也不要只跑半个 scope 就归档。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "想改已经归档的章节?"), (0, react.createElement)("p", null, "先 novel_reopen,带非空 reason。它会从归档备份恢复,重开后重新走 P3→P8;不要直接编辑归档卡或正文文件。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "状态文档坏了能手工修吗?"), (0, react.createElement)("p", null, "先用 novel_state 看 raw 和 next;需要修复时用 novel_amend,并在 reason 写清原因。手改 YAML 会丢失事务保护。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "有多个项目,面板看的是哪本?"), (0, react.createElement)("p", null, "面板用顶部项目选择器切换查看对象;选择只改 ?root= 和浏览器 localStorage,不调用 activate、不写会话绑定。写作项目请用 /novel use 或显式 project_root。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "选错书、想清掉绑定怎么办?"), (0, react.createElement)("p", null, "先用 /novel current 看当前会话绑定;要换书用 /novel use <路径|书名|.>,要清掉只影响当前会话的绑定用 /novel unbind。不要靠 active 猜,也不要手改 state/session-bindings.yaml。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "扫描到了,为什么还没切过去?"), (0, react.createElement)("p", null, "scan 只读发现;scan --register 只登记项目,不选择、不改 active、不绑会话。真正切换写作项目要用 /novel use,或第一次调用显式传 project_root。")))), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "可以直接复制给模型的起手话术"), (0, react.createElement)("pre", { className: "nwe-prompt" }, TUTORIAL_PROMPT)), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "续写下一章时,直接复制这段给 Agent"), (0, react.createElement)("p", null, "这段会先确认状态,再处理缺章卡和目标章数已满,最后按 P1→P8 推进;归档前会要求你确认 state_delta。"), (0, react.createElement)("pre", { className: "nwe-prompt" }, TUTORIAL_NEXT_PROMPT)), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "一章完成检查清单"), (0, react.createElement)("ul", { className: "nwe-checklist" }, (0, react.createElement)("li", null, "本章 P1/P2 计划已提交,P3 正文已通过格式与字数门控。"), (0, react.createElement)("li", null, "P4 评审 total 对账无误,没有未修 blocker。"), (0, react.createElement)("li", null, "P6 五个语义项都有不同句子的正文引用,完整 scope 通过。"), (0, react.createElement)("li", null, "P8 任务书当前,novel_archive 带完整 state_delta 成功。"), (0, react.createElement)("li", null, "面板出现已归档章节,门控区没有新的阻塞。")))), (0, react.createElement)("div", { className: "nwe-modal-foot" }, "教程基于 0.2.
|
|
1522
|
+
}, (0, react.createElement)("span", { "aria-hidden": "true" }, "×"))), (0, react.createElement)("div", { className: "nwe-modal-body" }, (0, react.createElement)("div", { className: "nwe-tutorial-intro" }, (0, react.createElement)("p", null, "网文工坊不是一个“帮你想剧情”的按钮,而是一台有状态的写作引擎:你提供内容,引擎负责阶段、字数、门控、评审、归档和文件。"), (0, react.createElement)("p", null, "每一步都先领取当前阶段的任务书,再提交;提交后看引擎返回的 blocking 与下一步。面板只读,真正的写操作都在对话里的工具调用中。")), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "开始前:记住三件事"), (0, react.createElement)("div", { className: "nwe-tutorial-cards" }, (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "只用引擎入口写"), (0, react.createElement)("span", null, "正文只走 novel_write_draft / novel_revise;状态只走工具。手改 chapters/、state/、outline/ 会破坏事务与校验。")), (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "每一步先领 brief"), (0, react.createElement)("span", null, "任务书携带当前上下文和 digest;跳过它会撞 PG-01。任务书过期就重新领取,不要复用旧上下文。")), (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "失败先读 code"), (0, react.createElement)("span", null, "参数错改参数,门控没过改正文,系统故障查目录/稍后重试。blocking 会一次列全,一次改完再交。"))), (0, react.createElement)("p", { className: "nwe-tutorial-note" }, (0, react.createElement)("strong", null, "用哪个会话:"), " 想获得完整的引擎保证,请新开一个「网文工坊」预设会话;普通会话里模型可能还挂着文件工具,能绕过引擎直接改稿。")), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "一本书的完整流程"), (0, react.createElement)("p", null, "前四步是开书准备,后面是每章循环。第一次先按顺序走完一章,熟悉后再批量推进整本。"), (0, react.createElement)("ol", { className: "nwe-steps" }, ...TUTORIAL_STEPS.map((step, index) => tutorialStep(step, index)))), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "面板怎么看"), (0, react.createElement)("div", { className: "nwe-tutorial-cards" }, (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "顶部统计"), (0, react.createElement)("span", null, "已归档章、总字数、平均分、待处理门控。数字来自引擎,不是正文估算。")), (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "九阶段轨与下一步"), (0, react.createElement)("span", null, "亮起的阶段是当前进度,“下一步”卡会直接给出该调用的工具名。")), (0, react.createElement)("div", { className: "nwe-tutorial-card" }, (0, react.createElement)("strong", null, "章节与门控"), (0, react.createElement)("span", null, "章节卡展开可看字数、评分与状态;门控区按 code/detail/hint 列出所有阻塞。"))), (0, react.createElement)("p", { className: "nwe-tutorial-note" }, (0, react.createElement)("strong", null, "刷新:"), " 面板每 15 秒静默同步一次,也可以点右上角刷新。它是只读投影;不会替你改稿、归档或修状态。"), (0, react.createElement)("p", { className: "nwe-tutorial-note" }, (0, react.createElement)("strong", null, "项目状态:"), "选择器里 choose 表示发现多本书、还没选;项目不在了表示目录缺失,绑定仍会保留;不是项目表示目录还在但没有 novel.yaml 或项目状态;项目不可读表示权限或 IO 错误,先修权限或换一本。面板选择只影响查看,不改变任何会话的写作绑定。")), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "卡住时先看这里"), (0, react.createElement)("ul", { className: "nwe-faq" }, (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "为什么一直让我先领 brief?"), (0, react.createElement)("p", null, "这是正常门控。任务书决定当前阶段可用的字段与上下文 digest;先按返回值调用 novel_brief,再继续。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "门控失败,改一条还是全改?"), (0, react.createElement)("p", null, "一次看完所有 blocking,再一起改。逐条试会反复烧掉阶段轮次;错误里的 code 会告诉你属于参数、门控还是系统故障。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "字数和评分为什么对不上?"), (0, react.createElement)("p", null, "字数以 engine 返回为准,可用 novel_word_count 核对;review 的 total 必须等于 150 减全部扣分,不能另算一套。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "P4/P6 过不去怎么办?"), (0, react.createElement)("p", null, "P4 有 blocker 就领 P5 任务书修订,再回 P4 重评;P6 失败同样回修订。不要 waive blocker,也不要只跑半个 scope 就归档。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "想改已经归档的章节?"), (0, react.createElement)("p", null, "先 novel_reopen,带非空 reason。它会从归档备份恢复,重开后重新走 P3→P8;不要直接编辑归档卡或正文文件。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "状态文档坏了能手工修吗?"), (0, react.createElement)("p", null, "先用 novel_state 看 raw 和 next;需要修复时用 novel_amend,并在 reason 写清原因。手改 YAML 会丢失事务保护。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "有多个项目,面板看的是哪本?"), (0, react.createElement)("p", null, "面板用顶部项目选择器切换查看对象;选择只改 ?root= 和浏览器 localStorage,不调用 activate、不写会话绑定。写作项目请用 /novel use 或显式 project_root。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "选错书、想清掉绑定怎么办?"), (0, react.createElement)("p", null, "先用 /novel current 看当前会话绑定;要换书用 /novel use <路径|书名|.>,要清掉只影响当前会话的绑定用 /novel unbind。不要靠 active 猜,也不要手改 state/session-bindings.yaml。")), (0, react.createElement)("li", null, (0, react.createElement)("strong", null, "扫描到了,为什么还没切过去?"), (0, react.createElement)("p", null, "scan 只读发现;scan --register 只登记项目,不选择、不改 active、不绑会话。真正切换写作项目要用 /novel use,或第一次调用显式传 project_root。")))), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "可以直接复制给模型的起手话术"), (0, react.createElement)("pre", { className: "nwe-prompt" }, TUTORIAL_PROMPT)), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "续写下一章时,直接复制这段给 Agent"), (0, react.createElement)("p", null, "这段会先确认状态,再处理缺章卡和目标章数已满,最后按 P1→P8 推进;归档前会要求你确认 state_delta。"), (0, react.createElement)("pre", { className: "nwe-prompt" }, TUTORIAL_NEXT_PROMPT)), (0, react.createElement)("section", { className: "nwe-tutorial-block" }, (0, react.createElement)("h3", null, "一章完成检查清单"), (0, react.createElement)("ul", { className: "nwe-checklist" }, (0, react.createElement)("li", null, "本章 P1/P2 计划已提交,P3 正文已通过格式与字数门控。"), (0, react.createElement)("li", null, "P4 评审 total 对账无误,没有未修 blocker。"), (0, react.createElement)("li", null, "P6 五个语义项都有不同句子的正文引用,完整 scope 通过。"), (0, react.createElement)("li", null, "P8 任务书当前,novel_archive 带完整 state_delta 成功。"), (0, react.createElement)("li", null, "面板出现已归档章节,门控区没有新的阻塞。")))), (0, react.createElement)("div", { className: "nwe-modal-foot" }, "教程基于 0.2.8 · 具体字段以当前任务书和工具返回为准 · 面板只读")));
|
|
1519
1523
|
const NovelHelp = () => {
|
|
1520
1524
|
const [open, setOpen] = (0, react.useState)(false);
|
|
1521
1525
|
const triggerRef = (0, react.useRef)(null);
|
|
@@ -1592,6 +1596,7 @@ brief P6 → check → brief P8 → archive 的顺序推进。
|
|
|
1592
1596
|
const bookDataSection = (view) => {
|
|
1593
1597
|
const data = view.bookData;
|
|
1594
1598
|
if (data === null) return null;
|
|
1599
|
+
const currentLabel = data.current.stage === "done" ? data.progress.target !== null && data.progress.archived >= data.progress.target ? "全书完成" : `下一章 ${data.current.chapter} · 未开始` : `${data.current.chapter} · ${data.current.stage}`;
|
|
1595
1600
|
const dims = data.quality.dimensions.map((dimension) => (0, react.createElement)("div", {
|
|
1596
1601
|
className: "nwe-v6-bar",
|
|
1597
1602
|
key: dimension.id
|
|
@@ -1613,7 +1618,7 @@ brief P6 → check → brief P8 → archive 的顺序推进。
|
|
|
1613
1618
|
["已归档", `${data.progress.archived} / ${data.progress.target ?? "不限"} 章`],
|
|
1614
1619
|
["字数", `归档 ${data.progress.words_archived} · 含草稿 ${data.progress.words_with_draft}`],
|
|
1615
1620
|
["剩余", data.progress.remaining_words === null ? "—" : `${data.progress.remaining_words} 字(${data.progress.remaining_words_basis})`],
|
|
1616
|
-
["当前章", `${
|
|
1621
|
+
["当前章", `${currentLabel} · ${data.current.card?.title ?? "无章卡"}`],
|
|
1617
1622
|
["轮次", `评 ${data.current.rounds.review} / 修 ${data.current.rounds.revise} / 检 ${data.current.rounds.check}`],
|
|
1618
1623
|
["正文 hash", data.current.manuscript_hash ?? "—"],
|
|
1619
1624
|
["当前字数", data.current.metrics === null ? "—" : String(data.current.metrics.total_word_count)]
|
|
@@ -1685,7 +1690,7 @@ brief P6 → check → brief P8 → archive 的顺序推进。
|
|
|
1685
1690
|
className: "nwe-stats",
|
|
1686
1691
|
role: "group",
|
|
1687
1692
|
"aria-label": "项目统计"
|
|
1688
|
-
}, stat("已归档", String(view.stats.chapters), "章"), stat("总字数", view.stats.words.toLocaleString("zh-CN"), "字"), stat("全书均分", view.stats.chapters === 0 ? "—" : String(view.stats.averageScore), "/150"), stat("待处理", String(view.stats.blocking), "项")) : null, ready ? bookDataSection(view) : null, view.state === "loading" ? loadingState() : null, view.state === "choose" ? choosePanel(view, onSelectProject) : null, view.state === "missing" ? missingPanel(view) : null, view.state === "error" || view.state === "empty" || view.state === "outdated" ? statePanel(view.state, view, loading, onRefresh) : null, ready ? (0, react.createElement)("div", { className: "nwe-desk" }, (0, react.createElement)("div", { className: "nwe-desk-main" }, (0, react.createElement)("div", { className: "nwe-desk-heading" }, (0, react.createElement)("span", { className: "nwe-desk-kicker" }, "当前一章"), (0, react.createElement)("span", { className: "nwe-desk-note" }, view.stageLabel)), phases(view), blockingSection(view), advisoriesSection(view), pendingSection(view), legacySection(view), chaptersSection(view)), (0, react.createElement)("aside", {
|
|
1693
|
+
}, stat("已归档", String(view.stats.chapters), "章"), stat("总字数", view.stats.words.toLocaleString("zh-CN"), (view.stats.draftWords ?? 0) > 0 ? `字(归档 ${(view.stats.archivedWords ?? 0).toLocaleString("zh-CN")} + 草稿 ${view.stats.draftWords.toLocaleString("zh-CN")})` : "字"), stat("全书均分", view.stats.chapters === 0 ? "—" : String(view.stats.averageScore), "/150"), stat("待处理", String(view.stats.blocking), "项")) : null, ready ? bookDataSection(view) : null, view.state === "loading" ? loadingState() : null, view.state === "choose" ? choosePanel(view, onSelectProject) : null, view.state === "missing" ? missingPanel(view) : null, view.state === "error" || view.state === "empty" || view.state === "outdated" ? statePanel(view.state, view, loading, onRefresh) : null, ready ? (0, react.createElement)("div", { className: "nwe-desk" }, (0, react.createElement)("div", { className: "nwe-desk-main" }, (0, react.createElement)("div", { className: "nwe-desk-heading" }, (0, react.createElement)("span", { className: "nwe-desk-kicker" }, "当前一章"), (0, react.createElement)("span", { className: "nwe-desk-note" }, view.stageLabel)), phases(view), blockingSection(view), advisoriesSection(view), pendingSection(view), legacySection(view), chaptersSection(view)), (0, react.createElement)("aside", {
|
|
1689
1694
|
className: "nwe-desk-side",
|
|
1690
1695
|
"aria-label": "全书与活动"
|
|
1691
1696
|
}, bookSection(view), activitySection(view))) : null, footer());
|
package/lib/index.d.ts
CHANGED
|
@@ -301,8 +301,8 @@ interface CharacterDelta {
|
|
|
301
301
|
role?: string;
|
|
302
302
|
profile?: Record<string, unknown>;
|
|
303
303
|
current_state?: Record<string, unknown>;
|
|
304
|
+
/** Chapter is engine-assigned from the archive transaction, not caller-supplied. */
|
|
304
305
|
growth?: {
|
|
305
|
-
chapter: number;
|
|
306
306
|
change: string;
|
|
307
307
|
status_change: string;
|
|
308
308
|
};
|
|
@@ -972,6 +972,8 @@ interface GateInput {
|
|
|
972
972
|
briefStage: BriefStage | null;
|
|
973
973
|
draftTitle: string | null;
|
|
974
974
|
sceneType: SceneType | null;
|
|
975
|
+
/** The submitted/active plan narrator; PG-05 uses it before a draft exists. */
|
|
976
|
+
narrator?: string | null;
|
|
975
977
|
summary: ChapterSummary | null;
|
|
976
978
|
/** P5 may omit `summary`; when omitted, the previous plan summary is reused. */
|
|
977
979
|
summaryProvided?: boolean;
|
|
@@ -1034,6 +1036,36 @@ interface Selection {
|
|
|
1034
1036
|
title?: string;
|
|
1035
1037
|
created_at?: string;
|
|
1036
1038
|
}
|
|
1039
|
+
/**
|
|
1040
|
+
* One human-readable projection of the pipeline's chapter boundary.
|
|
1041
|
+
*
|
|
1042
|
+
* `pipeline.chapter`/`stage` are protocol values: after archiving chapter N the
|
|
1043
|
+
* pipeline points at N+1 and still says `done` because `done` describes the
|
|
1044
|
+
* chapter that was just archived. This projection is the only place that turns
|
|
1045
|
+
* those values into "chapter N archived; chapter N+1 starts at P1".
|
|
1046
|
+
*/
|
|
1047
|
+
interface ChapterProgress {
|
|
1048
|
+
active_chapter: number;
|
|
1049
|
+
stage: Stage;
|
|
1050
|
+
/** The chapter currently being written; null while `stage === 'done'`. */
|
|
1051
|
+
current: {
|
|
1052
|
+
chapter: number;
|
|
1053
|
+
stage: Stage;
|
|
1054
|
+
} | null;
|
|
1055
|
+
/** Highest archived chapter, or null before the first archive. */
|
|
1056
|
+
last_archived: number | null;
|
|
1057
|
+
/** Next chapter to start at P1; null while writing or after the book is finished. */
|
|
1058
|
+
next: {
|
|
1059
|
+
chapter: number;
|
|
1060
|
+
stage: 'P1';
|
|
1061
|
+
} | null;
|
|
1062
|
+
/** True only when the configured target has been reached at `stage === 'done'`. */
|
|
1063
|
+
finished: boolean;
|
|
1064
|
+
/** One line for status cards, commands and the panel. */
|
|
1065
|
+
label: string;
|
|
1066
|
+
/** Sentence used by the resume prompt instead of "当前第 N 章,阶段 done". */
|
|
1067
|
+
resume: string;
|
|
1068
|
+
}
|
|
1037
1069
|
/** The `getStatus` payload. */
|
|
1038
1070
|
interface StatusReport {
|
|
1039
1071
|
project: {
|
|
@@ -1054,6 +1086,8 @@ interface StatusReport {
|
|
|
1054
1086
|
/** SHA-256 of the active manuscript, or null when the stage has no draft. */
|
|
1055
1087
|
manuscript_hash: string | null;
|
|
1056
1088
|
stage: Stage;
|
|
1089
|
+
/** Chapter-boundary projection shared by every human-readable surface. */
|
|
1090
|
+
progress?: ChapterProgress;
|
|
1057
1091
|
rounds: RoundCounters;
|
|
1058
1092
|
blocking: BlockingItem[];
|
|
1059
1093
|
/** Non-blocking recovery notes, e.g. a recoverable pending transaction. */
|
|
@@ -1106,6 +1140,8 @@ interface StatusReport {
|
|
|
1106
1140
|
interface AdviceReport {
|
|
1107
1141
|
stage: Stage;
|
|
1108
1142
|
chapter: number;
|
|
1143
|
+
/** Same chapter-boundary projection as getStatus. */
|
|
1144
|
+
progress?: ChapterProgress;
|
|
1109
1145
|
tool: string;
|
|
1110
1146
|
args: Record<string, unknown>;
|
|
1111
1147
|
reason: string;
|
|
@@ -1577,6 +1613,8 @@ interface PanelSnapshot {
|
|
|
1577
1613
|
platform: string;
|
|
1578
1614
|
chapter: number;
|
|
1579
1615
|
stage: Stage;
|
|
1616
|
+
/** Chapter-boundary projection; `chapter`/`stage` stay as the protocol pair. */
|
|
1617
|
+
progress?: ChapterProgress;
|
|
1580
1618
|
revision: number;
|
|
1581
1619
|
rounds: {
|
|
1582
1620
|
review: number;
|
|
@@ -1595,8 +1633,12 @@ interface PanelSnapshot {
|
|
|
1595
1633
|
chapters: ChapterRecord[];
|
|
1596
1634
|
/** The active, not-yet-archived chapter; archived rows come from `chapters`. */
|
|
1597
1635
|
draft?: PanelDraft | null;
|
|
1598
|
-
/**
|
|
1636
|
+
/** Archived words plus the active draft; the header shows this total. */
|
|
1599
1637
|
totalWords: number;
|
|
1638
|
+
/** Words in archived chapters only. */
|
|
1639
|
+
archivedWords?: number;
|
|
1640
|
+
/** Active draft words, zero when no draft exists. */
|
|
1641
|
+
draftWords?: number;
|
|
1600
1642
|
/** Book-wide archived average, not just the panel's capped rows. */
|
|
1601
1643
|
averageScore?: number;
|
|
1602
1644
|
/** The nine-phase strip state, derived from the pipeline stage. */
|
|
@@ -1694,8 +1736,14 @@ interface PanelSummaryDto {
|
|
|
1694
1736
|
platform: string;
|
|
1695
1737
|
chapter: number;
|
|
1696
1738
|
stage: Stage;
|
|
1739
|
+
/** Chapter-boundary projection; absent on older payloads. */
|
|
1740
|
+
progress?: ChapterProgress;
|
|
1697
1741
|
revision: number;
|
|
1698
1742
|
totalWords: number;
|
|
1743
|
+
/** Words in archived chapters only; `totalWords` also counts the active draft. */
|
|
1744
|
+
archivedWords?: number;
|
|
1745
|
+
/** Active draft words, zero when no draft exists. */
|
|
1746
|
+
draftWords?: number;
|
|
1699
1747
|
totalChapters: number;
|
|
1700
1748
|
/** Book-wide archived average; absent on older payloads. */
|
|
1701
1749
|
averageScore?: number;
|
|
@@ -1825,12 +1873,27 @@ interface PanelBundle {
|
|
|
1825
1873
|
empty?: true;
|
|
1826
1874
|
error?: string;
|
|
1827
1875
|
}
|
|
1876
|
+
interface ChapterProgressInput {
|
|
1877
|
+
activeChapter: number;
|
|
1878
|
+
stage: Stage;
|
|
1879
|
+
archived: readonly number[];
|
|
1880
|
+
target: number | null;
|
|
1881
|
+
}
|
|
1882
|
+
/**
|
|
1883
|
+
* Turn the protocol pair (`chapter` + `stage`) into the only human-readable
|
|
1884
|
+
* chapter boundary. After archiving chapter N the protocol intentionally keeps
|
|
1885
|
+
* `stage: 'done'` and advances `chapter` to N+1; `done` describes chapter N,
|
|
1886
|
+
* not the chapter the pipeline now points at.
|
|
1887
|
+
*/
|
|
1888
|
+
declare function projectChapterProgress(input: ChapterProgressInput): ChapterProgress;
|
|
1828
1889
|
interface ResumePromptInput {
|
|
1829
1890
|
title: string;
|
|
1830
1891
|
root: string;
|
|
1831
1892
|
chapter: number | string;
|
|
1832
1893
|
stage: string;
|
|
1833
1894
|
nextTool: string;
|
|
1895
|
+
/** When supplied, replaces the protocol pair with the chapter boundary text. */
|
|
1896
|
+
progress?: ChapterProgress;
|
|
1834
1897
|
}
|
|
1835
1898
|
/** One shared prompt template for `/novel resume` and the panel copy button. */
|
|
1836
1899
|
declare function formatResumePrompt(input: ResumePromptInput): string;
|
|
@@ -2298,6 +2361,7 @@ declare class EngineService {
|
|
|
2298
2361
|
}): Promise<OpResult<{
|
|
2299
2362
|
stage: Stage;
|
|
2300
2363
|
chapter: number;
|
|
2364
|
+
progress: ChapterProgress;
|
|
2301
2365
|
tool: string;
|
|
2302
2366
|
args: Record<string, unknown>;
|
|
2303
2367
|
reason: string;
|
|
@@ -2419,6 +2483,8 @@ declare class EngineService {
|
|
|
2419
2483
|
root?: string;
|
|
2420
2484
|
}): Promise<{
|
|
2421
2485
|
totalWords: number;
|
|
2486
|
+
archivedWords: number;
|
|
2487
|
+
draftWords: number;
|
|
2422
2488
|
chapters: number;
|
|
2423
2489
|
revision: number;
|
|
2424
2490
|
rulepack: string;
|
|
@@ -2805,4 +2871,4 @@ declare const Config: Schema<Config>;
|
|
|
2805
2871
|
* created lazily per project root.
|
|
2806
2872
|
*/
|
|
2807
2873
|
declare function apply(ctx: Context, config: Config): void;
|
|
2808
|
-
export { ARCHIVE_DIGESTS_FILE, AdviceReport, ArchiveHandoff, AuditRow, BACKUP_DIR, BRIEF_RECEIPTS_FILE, BlockingItem, BookPlan, BookReport, BriefDocument, BriefLibrary, BriefReceipt, BriefReceiptsDocument, BriefStage, CHAPTERS_DIR, CHECK_DIR, CORE_TOOLS, ChapterCastMember, ChapterPlanInput, ChapterRecord, ChapterStatusRow, ChapterSummary, ChaptersDocument, CharacterDelta, CharactersDocument, CheckDocument, Config, DEFAULT_GENRE, DEFAULT_PLATFORM, Deduction, DeltaAction, DiffReport, DoctorCheck, DoctorReport, DraftInput, DraftState, ERROR_CODES, EXPORT_DIR, EngineBlockedError, EngineError, EngineFaultError, EngineInputError, EngineService, ErrorCode, ExportChapter, ExportKind, ForeshadowDelta, ForeshadowsDocument, GENRES, GateInput, GateOptions, GateResult, Genre, GuideReport, GuideStep, HISTORY_DIR, HISTORY_KINDS, HandoffDocument, HistoryKind, INITIAL_STAGE, LIMITS, LOCK_FILE, LocksDocument, METADATA_LOCK_FILE, MachineMetrics, NovelProject, OPERATIONS, OUTLINE_DEPRECATED_FILE, OUTLINE_DIR, OUTLINE_FILE, OpResult, Operation, OutlineChapter, OutlineDocument, OutlineProgress, OutlineVolume, PANEL_CHAPTER_LIMIT, PANEL_ID, PANEL_ROUTE, PHASE_STRIP, PLAN_DIR, PLATFORMS, PLUGIN_NAME, PROJECT_FILE, PanelBook, PanelBundle, PanelChapterRow, PanelChaptersDto, PanelDraft, PanelGatesDto, PanelMissing, PanelProjectOption, PanelSelection, PanelSnapshot, PanelSummaryDto, PipelineState, Platform, REGISTRY_FILE, REMOTE_VERSION, REVIEW_DIR, ReadingProof, ReadingProofReference, RelationshipDelta, RelationshipsDocument, ResumePromptInput, ReviewDocument, ReviewInput, ReviewIssue, RevisionEdit, RevisionInput, RevisionPatch, RoundCounters, SCENE_TYPES, SCENE_TYPE_DEFAULT, SCHEMA_VERSION, SESSION_BINDINGS_FILE, SKILL_NAME, STAGING_DIR, STATE_DIR, STATE_FILES, SceneType, ScoreDimension, SearchReport, SearchResultItem, Selection, SelectionSource, SemanticItem, Severity, Stage, StateDelta, StateError, StateErrorCode, StatusReport, TOOL_NAMES, TimelineDelta, TimelineDocument, ToolName, Violation, WORLDBOOK_FILE, Warning, WordMetrics, WorldDelta, WorldDocument, WorldPlanInput, WorldbookBackstory, WorldbookCharacter, WorldbookDocument, WorldbookFact, WorldbookFaction, WorldbookGlossary, WorldbookLocation, WorldbookRule, applicableGates, apply, blockedError, briefStageFor, chapterFile, chapterHeading, chapterHistoryFile, checkFile, checkHistoryFile, deprecatedChapterFile, deprecatedHistoryFile, evaluateGates, faultError, formatResumePrompt, gateName, inject, inputError, loadRulepack, name, parseParagraphLocation, phaseStrip, planChapterFile, planHistoryFile, planWorldFile, projectChapter, projectChapters, projectGates, projectSummary, renderBlurb, renderCover, renderEpubChapter, renderMarkdown, renderPlainText, renderProposal, reviewFile, reviewHistoryFile, verifyReference };
|
|
2874
|
+
export { ARCHIVE_DIGESTS_FILE, AdviceReport, ArchiveHandoff, AuditRow, BACKUP_DIR, BRIEF_RECEIPTS_FILE, BlockingItem, BookPlan, BookReport, BriefDocument, BriefLibrary, BriefReceipt, BriefReceiptsDocument, BriefStage, CHAPTERS_DIR, CHECK_DIR, CORE_TOOLS, ChapterCastMember, ChapterPlanInput, ChapterProgress, ChapterProgressInput, ChapterRecord, ChapterStatusRow, ChapterSummary, ChaptersDocument, CharacterDelta, CharactersDocument, CheckDocument, Config, DEFAULT_GENRE, DEFAULT_PLATFORM, Deduction, DeltaAction, DiffReport, DoctorCheck, DoctorReport, DraftInput, DraftState, ERROR_CODES, EXPORT_DIR, EngineBlockedError, EngineError, EngineFaultError, EngineInputError, EngineService, ErrorCode, ExportChapter, ExportKind, ForeshadowDelta, ForeshadowsDocument, GENRES, GateInput, GateOptions, GateResult, Genre, GuideReport, GuideStep, HISTORY_DIR, HISTORY_KINDS, HandoffDocument, HistoryKind, INITIAL_STAGE, LIMITS, LOCK_FILE, LocksDocument, METADATA_LOCK_FILE, MachineMetrics, NovelProject, OPERATIONS, OUTLINE_DEPRECATED_FILE, OUTLINE_DIR, OUTLINE_FILE, OpResult, Operation, OutlineChapter, OutlineDocument, OutlineProgress, OutlineVolume, PANEL_CHAPTER_LIMIT, PANEL_ID, PANEL_ROUTE, PHASE_STRIP, PLAN_DIR, PLATFORMS, PLUGIN_NAME, PROJECT_FILE, PanelBook, PanelBundle, PanelChapterRow, PanelChaptersDto, PanelDraft, PanelGatesDto, PanelMissing, PanelProjectOption, PanelSelection, PanelSnapshot, PanelSummaryDto, PipelineState, Platform, REGISTRY_FILE, REMOTE_VERSION, REVIEW_DIR, ReadingProof, ReadingProofReference, RelationshipDelta, RelationshipsDocument, ResumePromptInput, ReviewDocument, ReviewInput, ReviewIssue, RevisionEdit, RevisionInput, RevisionPatch, RoundCounters, SCENE_TYPES, SCENE_TYPE_DEFAULT, SCHEMA_VERSION, SESSION_BINDINGS_FILE, SKILL_NAME, STAGING_DIR, STATE_DIR, STATE_FILES, SceneType, ScoreDimension, SearchReport, SearchResultItem, Selection, SelectionSource, SemanticItem, Severity, Stage, StateDelta, StateError, StateErrorCode, StatusReport, TOOL_NAMES, TimelineDelta, TimelineDocument, ToolName, Violation, WORLDBOOK_FILE, Warning, WordMetrics, WorldDelta, WorldDocument, WorldPlanInput, WorldbookBackstory, WorldbookCharacter, WorldbookDocument, WorldbookFact, WorldbookFaction, WorldbookGlossary, WorldbookLocation, WorldbookRule, applicableGates, apply, blockedError, briefStageFor, chapterFile, chapterHeading, chapterHistoryFile, checkFile, checkHistoryFile, deprecatedChapterFile, deprecatedHistoryFile, evaluateGates, faultError, formatResumePrompt, gateName, inject, inputError, loadRulepack, name, parseParagraphLocation, phaseStrip, planChapterFile, planHistoryFile, planWorldFile, projectChapter, projectChapterProgress, projectChapters, projectGates, projectSummary, renderBlurb, renderCover, renderEpubChapter, renderMarkdown, renderPlainText, renderProposal, reviewFile, reviewHistoryFile, verifyReference };
|