@cloud411716/fancy-webnovel 3.0.3 → 4.0.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/docs/material-library/README.md +6 -5
- package/docs/material-library/prompt.md +3 -2
- package/docs/workspace-mcp.md +2 -2
- package/lib/material-topic.js +248 -0
- package/lib/topic-candidates.js +157 -0
- package/package.json +4 -2
- package/plugins/fancy-analyze/analyze-definitions.md +35 -35
- package/plugins/fancy-analyze/templates.js +3 -3
- package/plugins/fancy-import/prompts/01-import-prompt.md +20 -20
- package/plugins/fancy-material/genres.js +4 -36
- package/plugins/fancy-material/index.js +18 -32
- package/plugins/fancy-material/templates.js +11 -3
- package/plugins/fancy-scan/prompts/01-analysis-prompt.md +16 -23
- package/plugins/fancy-scan/scripts/report-validate.js +39 -76
- package/plugins/fancy-scan/templates/report-schema.js +11 -8
- package/plugins/fancy-scan/templates.js +2 -2
- package/plugins/fancy-story-builder/prompts/01-skeleton-prompt.md +40 -28
- package/plugins/fancy-story-builder/prompts/02-flesh-prompt.md +28 -10
- package/plugins/fancy-story-builder/prompts/03-rhythm-prompt.md +21 -9
- package/plugins/fancy-story-builder/prompts/04-writing-prompt.md +15 -15
- package/plugins/fancy-story-builder/prompts/05-deslop-prompt.md +18 -18
- package/plugins/fancy-story-builder/purpose-template.md +1 -1
- package/plugins/fancy-story-builder/references/glossary.md +8 -8
- package/plugins/fancy-story-builder/references/index.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/00-index.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/01-scene.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/02-chapter-workflow.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/03-opening-chapter.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/04-dialogue-mastery.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/05-genre-formulas.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/06-tone-ensemble.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/07-ledger-audit.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/08-diagnosis-revision.md +2 -2
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/09-reading-power.md +7 -7
- package/plugins/fancy-story-builder/references//345/206/231/344/275/234/346/214/207/345/257/274/10-deslop.md +6 -6
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/00-index.md +2 -2
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/01-upgrade-rhythm.md +2 -2
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/02-arc-rhythm.md +2 -2
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/03-highpoint-hooks.md +2 -2
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/04-satisfaction.md +2 -2
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/05-foreshadow-density.md +5 -5
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/06-chapter-outline.md +2 -2
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/07-audit.md +1 -1
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/00-index.md +2 -2
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/01-character.md +2 -2
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/02-worldbuilding.md +5 -5
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/03-relations.md +3 -3
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/04-emotion-methods.md +3 -3
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/05-audit.md +1 -1
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/00-index.md +2 -2
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/01-positioning.md +1 -1
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/02-packaging.md +3 -3
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/03-entities.md +2 -2
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/04-conflict.md +2 -2
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/05-quota.md +2 -2
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/06-audit.md +1 -1
- package/plugins/fancy-story-builder/storydb/README.md +4 -4
- package/plugins/fancy-story-builder/storydb/prompts.js +1 -1
- package/plugins/fancy-topic/index.js +216 -546
- package/plugins/fancy-topic/prompts/01-exploration-prompt.md +6 -5
- package/plugins/fancy-topic/prompts/02-setup-prompt.md +112 -0
- package/plugins/fancy-topic/scripts/save-minimal-topic.js +97 -0
- package/plugins/fancy-topic/templates.js +104 -6
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
TABLE_SEP_RE,
|
|
28
28
|
DIRECTION_RE,
|
|
29
29
|
DIRECTION_LABELS,
|
|
30
|
+
CANDIDATE_LABELS,
|
|
30
31
|
} from '../templates/report-schema.js';
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -352,29 +353,56 @@ export function validateReportBody(body, opts = {}) {
|
|
|
352
353
|
+ ' —— 必须写成 `### 方向 N:名称`(N 是连续数字)');
|
|
353
354
|
}
|
|
354
355
|
|
|
355
|
-
// ── 3.
|
|
356
|
+
// ── 3. 每个方向的标签 ─────────────────────────────────────────
|
|
357
|
+
// 新格式只查 4 项;旧报告仍兼容 11 项。
|
|
356
358
|
const tagStats = [];
|
|
357
359
|
dirPos.forEach((start, k) => {
|
|
358
360
|
const end = k + 1 < dirPos.length ? dirPos[k + 1] : lines.length;
|
|
359
361
|
const section = lines.slice(start, end);
|
|
360
|
-
|
|
361
|
-
for (const lab of DIRECTION_LABELS) {
|
|
362
|
+
const findLabel = (label) => {
|
|
362
363
|
const re = new RegExp(
|
|
363
|
-
'^\\s*[-*+]?\\s*\\*\\*' +
|
|
364
|
+
'^\\s*[-*+]?\\s*\\*\\*' + label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\*\\*\\s*[::]\\s*(.+)$'
|
|
364
365
|
);
|
|
365
|
-
|
|
366
|
+
return section.map(l => re.exec(l)).find(Boolean);
|
|
367
|
+
};
|
|
368
|
+
const newHits = CANDIDATE_LABELS.map(findLabel);
|
|
369
|
+
const oldHits = DIRECTION_LABELS.map(findLabel);
|
|
370
|
+
const isNew = newHits.every(Boolean);
|
|
371
|
+
const isOld = oldHits.every(Boolean);
|
|
372
|
+
if (!isNew && !isOld) {
|
|
373
|
+
const missing = CANDIDATE_LABELS.filter((_, i) => !newHits[i]);
|
|
374
|
+
errors.push(`方向 ${k + 1} 缺标签:${missing.map(l => `「${l}」`).join('、')}`
|
|
375
|
+
+ '(新格式要求 题材 / 一句话定位 / 市场评分 / 推荐理由 四项齐全)');
|
|
376
|
+
}
|
|
377
|
+
const labels = isNew ? CANDIDATE_LABELS : DIRECTION_LABELS;
|
|
378
|
+
let okTags = 0;
|
|
379
|
+
for (let i = 0; i < labels.length; i += 1) {
|
|
380
|
+
const lab = labels[i];
|
|
381
|
+
const hit = (isNew ? newHits : oldHits)[i];
|
|
366
382
|
if (!hit) {
|
|
367
|
-
errors.push(`方向 ${k + 1} 缺标签「${lab}
|
|
383
|
+
errors.push(`方向 ${k + 1} 缺标签「${lab}」(格式 \`- **${lab}**:内容\`)`);
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
const value = hit[1].trim();
|
|
387
|
+
if (lab === '市场评分') {
|
|
388
|
+
if (!/^\d+(?:\.\d+)?(?:\s*\/\s*10)?$/.test(value)) {
|
|
389
|
+
errors.push(`方向 ${k + 1} 的「市场评分」必须是 1-10 的数字(如 8.5 或 8.5/10)`);
|
|
390
|
+
} else {
|
|
391
|
+
okTags++;
|
|
392
|
+
}
|
|
368
393
|
continue;
|
|
369
394
|
}
|
|
370
|
-
const chars = cjkCount(
|
|
371
|
-
|
|
372
|
-
|
|
395
|
+
const chars = cjkCount(value);
|
|
396
|
+
const minChars = isNew
|
|
397
|
+
? (lab === '题材' ? 2 : (lab === '一句话定位' || lab === '推荐理由' ? 10 : R.minTagChars))
|
|
398
|
+
: 20;
|
|
399
|
+
if (chars < minChars) {
|
|
400
|
+
errors.push(`方向 ${k + 1} 的「${lab}」只有 ${chars} 个汉字(要求 ≥${minChars},不能只写个标签名充数)`);
|
|
373
401
|
} else {
|
|
374
402
|
okTags++;
|
|
375
403
|
}
|
|
376
404
|
}
|
|
377
|
-
tagStats.push({ direction: k + 1, okTags, total:
|
|
405
|
+
tagStats.push({ direction: k + 1, okTags, total: labels.length });
|
|
378
406
|
});
|
|
379
407
|
|
|
380
408
|
// ── 4. 字数 ────────────────────────────────────────────────────
|
|
@@ -603,72 +631,7 @@ export function validateReportBody(body, opts = {}) {
|
|
|
603
631
|
});
|
|
604
632
|
}
|
|
605
633
|
|
|
606
|
-
//
|
|
607
|
-
// 不是加权总分。之前模型在列里填 4.44 / 3.83,读者无法一眼看出排名。
|
|
608
|
-
if (choiceTableRows.length) {
|
|
609
|
-
const nums = choiceTableRows.map(row => {
|
|
610
|
-
const cells = row.split('|').map(s => s.trim());
|
|
611
|
-
return Number(cells[cells.length - 1]);
|
|
612
|
-
});
|
|
613
|
-
const valid = nums.every((p, i) => Number.isInteger(p) && p === i + 1);
|
|
614
|
-
if (!valid) {
|
|
615
|
-
errors.push(`选题对比表的“优先级”列必须是 1–${choiceTableRows.length} 的名次`
|
|
616
|
-
+ `(从上到下递增),当前是 ${nums.map(x => Number.isFinite(x) ? x : '空').join('/')}`);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
// 优先级打分是自由文本,但常见写法是
|
|
621
|
-
// "方向 N ... a/b/c/待确认,加权后为 X"。
|
|
622
|
-
// 能解析就核对算术与排序;解析不到就跳过(不因为写法不同而误报)。
|
|
623
|
-
const scoreRows = [];
|
|
624
|
-
for (const chunk of text.split(/[;;\n]/)) {
|
|
625
|
-
const m = chunk.match(
|
|
626
|
-
/方向\s*(\d+)[^。;\n]{0,60}?(\d+)\s*\/\s*(\d+)\s*\/\s*(\d+)[^。;\n]{0,60}?加权后为\s*(\d+(?:\.\d+)?)/
|
|
627
|
-
);
|
|
628
|
-
if (!m) continue;
|
|
629
|
-
const scores = [Number(m[2]), Number(m[3]), Number(m[4])];
|
|
630
|
-
const expected = Math.round(
|
|
631
|
-
((scores[0] * 40 + scores[1] * 25 + scores[2] * 25) / 90) * 100
|
|
632
|
-
) / 100;
|
|
633
|
-
scoreRows.push({
|
|
634
|
-
direction: Number(m[1]),
|
|
635
|
-
scores,
|
|
636
|
-
stated: Number(m[5]),
|
|
637
|
-
expected,
|
|
638
|
-
});
|
|
639
|
-
}
|
|
640
|
-
for (const r of scoreRows) {
|
|
641
|
-
if (Math.abs(r.expected - r.stated) > 0.011) {
|
|
642
|
-
warnings.push(`优先级打分算术不一致:方向 ${r.direction} 的 ${r.scores.join('/')}`
|
|
643
|
-
+ ` 按 90% 归一化应为 ${r.expected.toFixed(2)},正文写 ${r.stated.toFixed(2)}`);
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
if (scoreRows.length > 1 && choiceTableRows.length) {
|
|
647
|
-
const priorityByDir = new Map();
|
|
648
|
-
for (const row of choiceTableRows) {
|
|
649
|
-
const cells = row.split('|').map(s => s.trim());
|
|
650
|
-
if (cells.length < 2) continue;
|
|
651
|
-
const dm = /^方向\s*(\d+)/.exec(cells[0]);
|
|
652
|
-
const p = Number(cells[cells.length - 1]);
|
|
653
|
-
if (dm && Number.isFinite(p)) priorityByDir.set(Number(dm[1]), p);
|
|
654
|
-
}
|
|
655
|
-
for (let i = 0; i < scoreRows.length; i++) {
|
|
656
|
-
for (let j = i + 1; j < scoreRows.length; j++) {
|
|
657
|
-
const a = scoreRows[i];
|
|
658
|
-
const b = scoreRows[j];
|
|
659
|
-
const pa = priorityByDir.get(a.direction);
|
|
660
|
-
const pb = priorityByDir.get(b.direction);
|
|
661
|
-
if (!pa || !pb || Math.abs(a.expected - b.expected) < 0.005) continue;
|
|
662
|
-
const wrong = (a.expected > b.expected && pa > pb)
|
|
663
|
-
|| (b.expected > a.expected && pb > pa);
|
|
664
|
-
if (wrong) {
|
|
665
|
-
warnings.push(`选题对比表的优先级与加权总分不一致:方向 ${a.direction}`
|
|
666
|
-
+ `(${a.expected.toFixed(2)})与方向 ${b.direction}(${b.expected.toFixed(2)})`
|
|
667
|
-
+ ` 的顺序对不上(表里优先级 ${pa} vs ${pb})`);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
}
|
|
634
|
+
// 新格式不再要求“优先级”列;方向的市场评分在第四节逐项校验。
|
|
672
635
|
|
|
673
636
|
// ── 6. 引用(书名 + 指标) ──────────────────────────────────────
|
|
674
637
|
// 数的是**出现次数**,不是行数 —— 一行里写了两本书的两条佐证也算两处。
|
|
@@ -41,19 +41,22 @@ export const SECTION_TITLES = [
|
|
|
41
41
|
* - 表格数用**分隔行**数(`| --- | --- |` 那种),不是"看起来像表格的行";
|
|
42
42
|
* - 标签要求"加粗 + 全角冒号 + 正文 ≥20 汉字",避免"写个标题充数"。
|
|
43
43
|
*/
|
|
44
|
+
/** 新格式每个方向只要求四项 */
|
|
45
|
+
export const CANDIDATE_LABELS = ['题材', '一句话定位', '市场评分', '推荐理由'];
|
|
46
|
+
|
|
44
47
|
export const REPORT_RULES = {
|
|
45
48
|
/** 方向个数 */
|
|
46
49
|
minDirections: 3,
|
|
47
|
-
maxDirections:
|
|
48
|
-
/**
|
|
49
|
-
minTagsPerDirection:
|
|
50
|
+
maxDirections: 5,
|
|
51
|
+
/** 新格式每个方向的 4 个标签 */
|
|
52
|
+
minTagsPerDirection: CANDIDATE_LABELS.length,
|
|
50
53
|
/** 每个标签后面的正文汉字数下限(防止"写个标签名充数") */
|
|
51
|
-
minTagChars:
|
|
52
|
-
/**
|
|
53
|
-
minCjkTotal:
|
|
54
|
+
minTagChars: 4,
|
|
55
|
+
/** 全文汉字数区间(只保留市场分析,不再展开 11 项设计) */
|
|
56
|
+
minCjkTotal: 3000,
|
|
54
57
|
maxCjkTotal: 15000,
|
|
55
58
|
/** 纯正文汉字数下限(排除表格行、标题行、标签行之后的正文量) */
|
|
56
|
-
minPureCjk:
|
|
59
|
+
minPureCjk: 2200,
|
|
57
60
|
/** 表格张数 */
|
|
58
61
|
minTables: 3,
|
|
59
62
|
/** 至少几处"《书名》…月票 N 张"式的引用 */
|
|
@@ -74,7 +77,7 @@ export function tableHeaders(metricLabel, grouped) {
|
|
|
74
77
|
return {
|
|
75
78
|
topic: `题材 | 书目数 | ${metricLabel}总量 | 均值 | 中位数 | ${share}`,
|
|
76
79
|
competition: `题材 | ${share} | 头部集中度 | 同质化程度 | 差异化空间 | 判断`,
|
|
77
|
-
choice: '方向 | 题材 |
|
|
80
|
+
choice: '方向 | 题材 | 一句话定位 | 市场评分 | 推荐理由',
|
|
78
81
|
};
|
|
79
82
|
}
|
|
80
83
|
|
|
@@ -598,7 +598,7 @@ export const scan = {
|
|
|
598
598
|
`- **辅助指标(${aux.map(a => a.label).join(' / ')})只作交叉验证,不进上面三项公式** ——`,
|
|
599
599
|
` 它们的口径和量级都与${h.label}不同(见 2.3),代入占比或相加都得出没有意义的数。用法:`,
|
|
600
600
|
...aux.map(a => ` - ${a.usage}`),
|
|
601
|
-
` 以上都是**同一天、同一批书的横向比较** ——
|
|
601
|
+
` 以上都是**同一天、同一批书的横向比较** —— 不能写成“正在上升、持续走高”。`,
|
|
602
602
|
]
|
|
603
603
|
: [];
|
|
604
604
|
|
|
@@ -613,7 +613,7 @@ export const scan = {
|
|
|
613
613
|
? [
|
|
614
614
|
`- **数据文件里有 \`**排名变动:**\` 行时**,它说明"名次较上次有变动"(上升/下降 N 名/持平)——`,
|
|
615
615
|
` 这可以写进结论,但**只能写这一次的变动**:"名次较上次上升 N 位";`,
|
|
616
|
-
`
|
|
616
|
+
` **不能**由它推断连续走势(“连续上升、一路走高”)—— 它是单个变化值,不是历史序列。`,
|
|
617
617
|
]
|
|
618
618
|
: [];
|
|
619
619
|
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
# 01 骨架阶段产物契约
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
本文件是骨架阶段的**产物契约**:每个文件长什么样、哪些规则不能破。
|
|
4
|
+
|
|
5
|
+
怎么派活、怎么校验、错了怎么改、下一批做什么,全部由插件负责:
|
|
6
|
+
插件按批次把活派给你,校验脚本判定通过与否,
|
|
7
|
+
错误清单由插件整理后回喂给你。**你只负责按指令生成文件。**
|
|
8
|
+
|
|
9
|
+
本阶段是第一层,无上游依赖。
|
|
10
10
|
|
|
11
11
|
@meta-only
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<!-- contract:overview -->
|
|
16
|
+
|
|
16
17
|
## 一、本阶段目标
|
|
17
18
|
|
|
18
19
|
产出 4 个 JSON 文件到 `设定/raw/sources/骨架/`:
|
|
@@ -39,10 +40,11 @@
|
|
|
39
40
|
---
|
|
40
41
|
|
|
41
42
|
<!-- contract:input -->
|
|
43
|
+
|
|
42
44
|
## 二、任务输入
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
本节由插件注入,只读,不得修改。
|
|
47
|
+
骨架阶段没有上游,这输入就是选题时的原始输入。
|
|
46
48
|
|
|
47
49
|
${input_snapshot_block}
|
|
48
50
|
|
|
@@ -56,6 +58,7 @@ ${input_snapshot_block}
|
|
|
56
58
|
---
|
|
57
59
|
|
|
58
60
|
<!-- contract:output-list -->
|
|
61
|
+
|
|
59
62
|
## 三、本阶段产出清单
|
|
60
63
|
|
|
61
64
|
| # | 文件 | 路径 | 前置依赖 |
|
|
@@ -68,27 +71,29 @@ ${input_snapshot_block}
|
|
|
68
71
|
---
|
|
69
72
|
|
|
70
73
|
<!-- contract:rules -->
|
|
74
|
+
|
|
71
75
|
## 四、核心铁律(违反任意一条都会校验失败)
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
77
|
+
1. **不得出现任何章节号**(`chapter` / `ch` / `start` / `end` / `appearance_chapters` / `chapter_range` / `buried_chapter` / `recovered_chapter` / `key_nodes` 等,完整清单见 glossary 第六节)。骨架脚本会拦截 `SKELETON_CHAPTER_FORBIDDEN`。
|
|
78
|
+
|
|
79
|
+
2. **常规实体的枚举必须遵守 glossary**。例如 `character_type` 只允许"主角/贯穿级核心配角/卷级重要配角/贯穿级核心反派/卷级反派",不能自创。题材特有存在不要硬塞进 `characters`,改写进可选的 `other_entities`(`kind` 是自由文本,如 灵魂/神魂/器灵/妖灵/概念体)。ENUM 校验会拦截常规枚举。
|
|
80
|
+
|
|
81
|
+
3. **引用关系只允许 id,不允许编名字**。关系.json 的 `from`/`to`/`character`/`faction`/`item`/`location`/`ending`/`main_line`/`branch` 必须是 `C001`/`X001`/`F001` 这种 id,不是名字。`SKELETON_REF_MISSING` 会拦截。
|
|
82
|
+
|
|
83
|
+
4. **不得自创字段**。每个文件的字段必须严格在 `模板/骨架/<文件名>模板.json` 的 `structure.properties` 中定义。`EXTRA_FIELD` 会拦截。
|
|
84
|
+
|
|
85
|
+
5. **公式推导(`derivations`)必须 30 条齐全**,每条 `{formula, range_low, range_high, note}`,且 `formula` 逐字与 `formulas-skeleton.json` 一致。`DERIVATION_MISSING` / `DERIVATION_RANGE_MISMATCH` 会拦截。
|
|
86
|
+
|
|
87
|
+
6. **关系类型只能取第 8.2 节各自那套词表**。`character_relations[].relation_kind` 取 13 值(血缘/师徒/雇佣/服从/提携/合作/利益交换/利用/对立/敌对/竞争/中立/其他);用 `其他` 时必须填 `relation_label` 写清具体关系(如 附身/寄生/契约/共生)。非人物实体的关系写 `other_relations`;`faction_membership[].member_relation` 取 8 值(利益交换/合作/对立/利用/师徒/雇佣/血亲/无);`faction_relations[].relation_type` 取 4 值(合作/对立/利用/中立);`main_line_branch_relation[].relation_kind` 取 6 值(促成/阻碍/并行/揭示/收束/依存)。不要写“盟友、对手、上下级、血亲”——它们不在对应词表里,ENUM 会拦截。
|
|
88
|
+
|
|
89
|
+
7. **实体名要是真名字,内容要是真内容**。名字写"陆子仲"而不是"主角1";`input_snapshot` 的 `positioning` / `core_conflict` 要写清一个具体处境,而不是"核心概述。"。`NAME_PLACEHOLDER` / `TEXT_TOO_SHORT` / `TEXT_PLACEHOLDER` 会拦截。
|
|
90
|
+
|
|
91
|
+
8. **实体条数必须与框架的 quota 完全一致**。框架里声明 `character_counts.protagonist = 2`,实体清单里就恰好要有 2 个 `type=主角` 的角色;多一个少一个都会报 `QUOTA_MISMATCH`。
|
|
88
92
|
|
|
89
93
|
---
|
|
90
94
|
|
|
91
95
|
<!-- contract:refs -->
|
|
96
|
+
|
|
92
97
|
## 五、参考文件
|
|
93
98
|
|
|
94
99
|
### 必读(每次任务开始时读一次,之后不再重读)
|
|
@@ -118,6 +123,7 @@ ${benchmark_refs_block}
|
|
|
118
123
|
---
|
|
119
124
|
|
|
120
125
|
<!-- contract:file:框架 -->
|
|
126
|
+
|
|
121
127
|
## 六、框架.json 的字段契约
|
|
122
128
|
|
|
123
129
|
**顶层**:纯对象(没有顶层数组) **模板**:`模板/骨架/框架模板.json`
|
|
@@ -277,6 +283,7 @@ Level 3(依赖实体数):
|
|
|
277
283
|
---
|
|
278
284
|
|
|
279
285
|
<!-- contract:file:实体 -->
|
|
286
|
+
|
|
280
287
|
## 七、实体.json 的字段契约
|
|
281
288
|
|
|
282
289
|
**顶层**:12 个常规数组 + 可选的 `other_entities` **模板**:`模板/骨架/实体模板.json`
|
|
@@ -341,6 +348,7 @@ Level 3(依赖实体数):
|
|
|
341
348
|
---
|
|
342
349
|
|
|
343
350
|
<!-- contract:file:关系 -->
|
|
351
|
+
|
|
344
352
|
## 八、关系.json 的字段契约
|
|
345
353
|
|
|
346
354
|
**顶层**:9 个常规数组 + 可选的 `other_relations` **模板**:`模板/骨架/关系模板.json`
|
|
@@ -390,10 +398,10 @@ Level 3(依赖实体数):
|
|
|
390
398
|
|
|
391
399
|
**`faction_relations[].relation_type`** —— 只从这 4 个值里选:`合作` / `对立` / `利用` / `中立`。
|
|
392
400
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
401
|
+
⚠️ **这是四套互不相同的词表,别串用**:
|
|
402
|
+
`relation_kind`(角色关系,13 值,含扩展出口 `其他`)/ `member_relation`(成员关系,8 值)/ `relation_type`(势力关系,4 值)/ `main_line_branch_relation[].relation_kind`(支线挂主线,6 值)。
|
|
403
|
+
拿 `relation_kind` 的值去填 `member_relation` 或 `relation_type` 一律报 ENUM
|
|
404
|
+
(tt5 实测 2026-10-27:9 条 ENUM 错误,2 个批次重写,理由全是"从角色关系词表里取值")。
|
|
397
405
|
|
|
398
406
|
### 8.3 关键约束
|
|
399
407
|
|
|
@@ -411,6 +419,7 @@ Level 3(依赖实体数):
|
|
|
411
419
|
---
|
|
412
420
|
|
|
413
421
|
<!-- contract:file:层级 -->
|
|
422
|
+
|
|
414
423
|
## 九、层级.json 的字段契约
|
|
415
424
|
|
|
416
425
|
**顶层**:4 个数组 **模板**:`模板/骨架/层级模板.json`
|
|
@@ -436,6 +445,7 @@ Level 3(依赖实体数):
|
|
|
436
445
|
---
|
|
437
446
|
|
|
438
447
|
<!-- contract:consistency -->
|
|
448
|
+
|
|
439
449
|
## 十、本阶段全量校验清单
|
|
440
450
|
|
|
441
451
|
全量模式(插件在四个文件都产出后跑一次)检查以下项目:
|
|
@@ -477,6 +487,7 @@ Level 3(依赖实体数):
|
|
|
477
487
|
---
|
|
478
488
|
|
|
479
489
|
<!-- contract:errors -->
|
|
490
|
+
|
|
480
491
|
## 十一、常见错误代码速查(详见 glossary 与脚本)
|
|
481
492
|
|
|
482
493
|
| code | 含义 | 修复方向 |
|
|
@@ -534,6 +545,7 @@ Level 3(依赖实体数):
|
|
|
534
545
|
---
|
|
535
546
|
|
|
536
547
|
<!-- contract:forbidden -->
|
|
548
|
+
|
|
537
549
|
## 十二、本阶段禁令(13 条)
|
|
538
550
|
|
|
539
551
|
1. **不得出现任何章节号**(`chapter` / `ch` / `start` / `end` / `appearance_chapters` / `chapter_range` / `buried_chapter` / `recovered_chapter` / `key_nodes` 等,完整清单见 glossary 第六节)。骨架脚本会报 `SKELETON_CHAPTER_FORBIDDEN`。
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
# 02 血肉阶段产物契约
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
本文件是血肉阶段的**产物契约**:它定义每个文件长什么样、哪些写法会被判错。
|
|
4
|
+
|
|
5
|
+
**流程由插件驱动**:插件会分批派活,每轮告诉你写哪个文件、哪些条目、写到哪里;
|
|
6
|
+
插件自己跑校验脚本、判定通过与否,并把判定出来的错误清单回喂给你。
|
|
7
|
+
你**不需要**自己调校验脚本,**不要**自己判断"通过没通过",**不要**输出"已完成"之类的结论。
|
|
8
8
|
|
|
9
9
|
@meta-only
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
<!-- contract:overview -->
|
|
14
|
+
|
|
14
15
|
## 你的职责
|
|
15
16
|
|
|
16
17
|
你只做一件事:**按插件每轮给的指令,把指定的条目写成指定格式的 JSON**。
|
|
@@ -30,11 +31,12 @@
|
|
|
30
31
|
---
|
|
31
32
|
|
|
32
33
|
<!-- contract:input -->
|
|
34
|
+
|
|
33
35
|
## 一、任务输入
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
本节由插件注入,只读,不得修改。
|
|
38
|
+
数据源:骨架阶段 `设定/raw/sources/骨架/框架.json` 的 `input_snapshot`(目标章节/目标字数取自同文件的 `capacity`)。
|
|
39
|
+
骨架阶段已经把这次选题的完整输入固化成了这份快照,血肉阶段直接用它,不要另做推测或改写。
|
|
38
40
|
|
|
39
41
|
${input_snapshot_block}
|
|
40
42
|
|
|
@@ -49,6 +51,7 @@ ${input_snapshot_block}
|
|
|
49
51
|
---
|
|
50
52
|
|
|
51
53
|
<!-- contract:output-list -->
|
|
54
|
+
|
|
52
55
|
## 二、本阶段产出清单
|
|
53
56
|
|
|
54
57
|
| # | 文件 | 路径 | 顶层数组 |
|
|
@@ -70,6 +73,7 @@ ${input_snapshot_block}
|
|
|
70
73
|
---
|
|
71
74
|
|
|
72
75
|
<!-- contract:rules -->
|
|
76
|
+
|
|
73
77
|
## 三、核心铁律(7 条,违反任意一条都会被判错)
|
|
74
78
|
|
|
75
79
|
1. **不得出现任何章节号**——单章号字段(`chapter` / `ch` / `start` / `end` / `turning` / `midpoint` / `resolution` / `resolution_chapter` / `appear_start` / `appear_end` / `exit_chapter` / `buried_chapter` / `recovered_chapter` / `hook_chapter` / `climax_chapter` / `pleasure_chapter`)、区间字段(`appearance_chapters` / `chapter_range`)、嵌套形式(`escalation_nodes[].chapter` / `info_gaps[].created` / `key_nodes[].chapter` / `arc_stages[].chapter` / `interweaves[].chapter` / `foreshadow_recovery[].chapter`)**全部禁止**;完整清单见 glossary 第六节(脚本按它判定,别自己猜字段名)。血肉脚本会拦截 `FLESH_CHAPTER_FORBIDDEN`。
|
|
@@ -84,11 +88,12 @@ ${input_snapshot_block}
|
|
|
84
88
|
|
|
85
89
|
6. **关系类型必须与骨架完全一致**。`relationships[].relationship_type` 只能取 glossary 第五节 `relation_kind` 的 13 个值(血缘/师徒/雇佣/服从/提携/合作/利益交换/利用/对立/敌对/竞争/中立/其他),而且**必须等于骨架里同一对角色的关系类型**。骨架写"A 服从 B",这里就不能写"上下级"或"盟友";用 `其他` 时必须同时填 `relation_label`(如 附身/寄生/契约)。非人物实体参与的关系在骨架 `other_relations`,本项目不写进 `relationships[]`。`REL_TYPE_MISMATCH` / `REL_LABEL_REQUIRED` / `ENUM` 会拦截。
|
|
86
90
|
|
|
87
|
-
7. **描述要写实,不能写空话**。`description` / `core_flaw` / `goals.*`
|
|
91
|
+
7. **描述要写实,不能写空话**。`description` / `core_flaw` / `goals.*` 这类叙述字段要写出一个具体事实,而不是“很好、详细设定”这类空话。`TEXT_TOO_SHORT` / `TEXT_PLACEHOLDER` 会拦截;不同角色不能共用同一段话(`TEXT_DUPLICATE`)。
|
|
88
92
|
|
|
89
93
|
---
|
|
90
94
|
|
|
91
95
|
<!-- contract:refs -->
|
|
96
|
+
|
|
92
97
|
## 四、参考文件
|
|
93
98
|
|
|
94
99
|
### 4.1 必读
|
|
@@ -143,6 +148,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
143
148
|
---
|
|
144
149
|
|
|
145
150
|
<!-- contract:file:角色 -->
|
|
151
|
+
|
|
146
152
|
## 五、角色.json 的字段契约
|
|
147
153
|
|
|
148
154
|
**顶层数组**:`characters` **模板**:`模板/血肉/角色模板.json`
|
|
@@ -176,7 +182,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
176
182
|
| `language_profile.personality_tone` | 性格基调(冷硬/温和/尖刻/木讷) |
|
|
177
183
|
| `language_profile.relationship_stage_tone` | 对不同关系的人说话语气怎么变 |
|
|
178
184
|
| `behavior_repeat_points` | 反复出现的小动作或口头习惯,字符串数组 |
|
|
179
|
-
| `traits` | **必填 3-5
|
|
185
|
+
| `traits` | **必填 3-5 条**独有特征/习惯/感官锚点。每条都要能在场景里演出来,不要写“善良、勇敢”这类评价词 |
|
|
180
186
|
| `extensions` | 题材特有的扩展设定;键用中文,值用字符串/数组。不要塞章节号 |
|
|
181
187
|
| `mirror_type` | 反派专用:与主角互为镜像的类型,取 glossary `mirror_type` 词表。非反派不填 |
|
|
182
188
|
| `relationships[]` | 关系条目,见下 |
|
|
@@ -209,6 +215,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
209
215
|
---
|
|
210
216
|
|
|
211
217
|
<!-- contract:file:冲突 -->
|
|
218
|
+
|
|
212
219
|
## 六、冲突.json 的字段契约
|
|
213
220
|
|
|
214
221
|
**顶层数组**:`conflicts` **模板**:`模板/血肉/冲突模板.json`
|
|
@@ -239,6 +246,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
239
246
|
---
|
|
240
247
|
|
|
241
248
|
<!-- contract:file:势力 -->
|
|
249
|
+
|
|
242
250
|
## 七、势力.json 的字段契约
|
|
243
251
|
|
|
244
252
|
**顶层数组**:`factions` **模板**:`模板/血肉/势力模板.json`
|
|
@@ -267,6 +275,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
267
275
|
---
|
|
268
276
|
|
|
269
277
|
<!-- contract:file:剧情 -->
|
|
278
|
+
|
|
270
279
|
## 八、剧情.json 的字段契约
|
|
271
280
|
|
|
272
281
|
**顶层数组**:`main_lines` + `branches` **模板**:`模板/血肉/剧情模板.json`
|
|
@@ -298,6 +307,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
298
307
|
---
|
|
299
308
|
|
|
300
309
|
<!-- contract:file:地点 -->
|
|
310
|
+
|
|
301
311
|
## 九、地点.json 的字段契约
|
|
302
312
|
|
|
303
313
|
**顶层数组**:`locations` **模板**:`模板/血肉/地点模板.json`
|
|
@@ -321,6 +331,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
321
331
|
---
|
|
322
332
|
|
|
323
333
|
<!-- contract:file:结局 -->
|
|
334
|
+
|
|
324
335
|
## 十、结局.json 的字段契约
|
|
325
336
|
|
|
326
337
|
**顶层数组**:`endings` **模板**:`模板/血肉/结局模板.json`
|
|
@@ -356,6 +367,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
356
367
|
---
|
|
357
368
|
|
|
358
369
|
<!-- contract:file:世界观规则 -->
|
|
370
|
+
|
|
359
371
|
## 十一、世界观规则.json 的字段契约
|
|
360
372
|
|
|
361
373
|
**顶层数组**:`core_rules` + `information_rules` + `social_rules` + `rule_conflict_plan`
|
|
@@ -396,6 +408,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
396
408
|
---
|
|
397
409
|
|
|
398
410
|
<!-- contract:file:关键道具 -->
|
|
411
|
+
|
|
399
412
|
## 十二、关键道具.json 的字段契约
|
|
400
413
|
|
|
401
414
|
**顶层数组**:`core_items` + `branch_items` + `symbolic_items` + `details`
|
|
@@ -445,6 +458,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
445
458
|
---
|
|
446
459
|
|
|
447
460
|
<!-- contract:file:其他实体 -->
|
|
461
|
+
|
|
448
462
|
## 十三、其他实体.json 的字段契约(按需)
|
|
449
463
|
|
|
450
464
|
**顶层数组**:`other_entities` **模板**:`模板/血肉/其他实体模板.json`
|
|
@@ -471,6 +485,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
471
485
|
---
|
|
472
486
|
|
|
473
487
|
<!-- contract:quality -->
|
|
488
|
+
|
|
474
489
|
## 十四、关系类型与内容质量(照着正例写)
|
|
475
490
|
|
|
476
491
|
脚本不只查结构,也查"写的东西是不是真的"、"两个阶段说的是不是同一件事"。
|
|
@@ -514,6 +529,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
514
529
|
---
|
|
515
530
|
|
|
516
531
|
<!-- contract:errors -->
|
|
532
|
+
|
|
517
533
|
## 十五、常见错误代码速查
|
|
518
534
|
|
|
519
535
|
插件回喂给你的错误清单里的 `code` 对应下表。**只改被点名的字段**,其余不要动。
|
|
@@ -558,6 +574,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
558
574
|
---
|
|
559
575
|
|
|
560
576
|
<!-- contract:forbidden -->
|
|
577
|
+
|
|
561
578
|
## 十六、本阶段禁令(12 条)
|
|
562
579
|
|
|
563
580
|
1. **不得出现任何章节号**——单章号字段(`chapter` / `ch` / `start` / `end` / `turning` / `midpoint` / `resolution` / `resolution_chapter` / `appear_start` / `appear_end` / `exit_chapter` / `buried_chapter` / `recovered_chapter` / `hook_chapter` / `climax_chapter` / `pleasure_chapter`)、区间字段(`appearance_chapters` / `chapter_range`)、嵌套形式(`escalation_nodes[].chapter` / `info_gaps[].created` / `key_nodes[].chapter` / `arc_stages[].chapter` / `interweaves[].chapter` / `foreshadow_recovery[].chapter`)**全部禁止**;完整清单见 glossary 第六节(脚本按它判定,别自己猜字段名)。
|
|
@@ -587,6 +604,7 @@ node references/upstream-query.js --stage=骨架 --file=关系 --list #
|
|
|
587
604
|
---
|
|
588
605
|
|
|
589
606
|
<!-- contract:semantic -->
|
|
607
|
+
|
|
590
608
|
## 十七、语义检查(可选,由用户显式开启)
|
|
591
609
|
|
|
592
610
|
上面的校验全是**确定性脚本**:id 在不在、名字对不对、枚举合不合法、配额对不对得上、关系有没有声明。凡是脚本能判死的问题,都已经被判死了。
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
# 03 节奏阶段产物契约
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
本文件是节奏阶段的**产物契约**:它定义每个文件长什么样、哪些写法会被判错。
|
|
4
|
+
|
|
5
|
+
**流程由插件驱动**:插件会分批派活,每轮告诉你写哪个文件、哪些章/哪些条目、
|
|
6
|
+
写到哪里;插件自己跑校验脚本、判定通过与否,并把判定出来的错误清单回喂给你。
|
|
7
|
+
你**不需要**自己调校验脚本,**不要**自己判断"通过没通过",**不要**输出"已完成"之类的结论。
|
|
8
|
+
|
|
9
|
+
本阶段依赖骨架 + 血肉两个上游,任一未完成不得启动。
|
|
10
10
|
|
|
11
11
|
@meta-only
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<!-- contract:overview -->
|
|
16
|
+
|
|
16
17
|
## 你的职责
|
|
17
18
|
|
|
18
19
|
你只做一件事:**按插件每轮给的指令,把指定的条目写成指定格式的 JSON**。
|
|
@@ -32,10 +33,11 @@
|
|
|
32
33
|
---
|
|
33
34
|
|
|
34
35
|
<!-- contract:input -->
|
|
36
|
+
|
|
35
37
|
## 一、任务输入
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
本节由插件注入,只读,不得修改。
|
|
40
|
+
数据源:骨架阶段 `设定/raw/sources/骨架/框架.json` 的 `input_snapshot`(目标章节/目标字数取自同文件的 `capacity`)。
|
|
39
41
|
|
|
40
42
|
${input_snapshot_block}
|
|
41
43
|
|
|
@@ -50,6 +52,7 @@ ${input_snapshot_block}
|
|
|
50
52
|
---
|
|
51
53
|
|
|
52
54
|
<!-- contract:output-list -->
|
|
55
|
+
|
|
53
56
|
## 二、本阶段产出清单
|
|
54
57
|
|
|
55
58
|
| # | 文件 | 路径 | 顶层键 |
|
|
@@ -70,6 +73,7 @@ ${input_snapshot_block}
|
|
|
70
73
|
---
|
|
71
74
|
|
|
72
75
|
<!-- contract:rules -->
|
|
76
|
+
|
|
73
77
|
## 三、核心铁律(6 条,违反任意一条都会校验失败)
|
|
74
78
|
|
|
75
79
|
1. **章节号必须在 `[1, T]` 内**(`T = target_chapters`)。`RHYTHM_CHAP_RANGE` 会拦截越界。
|
|
@@ -87,6 +91,7 @@ ${input_snapshot_block}
|
|
|
87
91
|
---
|
|
88
92
|
|
|
89
93
|
<!-- contract:refs -->
|
|
94
|
+
|
|
90
95
|
## 四、参考文件
|
|
91
96
|
|
|
92
97
|
### 4.1 必读
|
|
@@ -136,6 +141,7 @@ node references/upstream-query.js --stage=血肉 --file=角色 --id=C001
|
|
|
136
141
|
---
|
|
137
142
|
|
|
138
143
|
<!-- contract:file:章节规划 -->
|
|
144
|
+
|
|
139
145
|
## 五、章节规划.json 的字段契约
|
|
140
146
|
|
|
141
147
|
**顶层数组**:`chapters` **模板**:`模板/节奏/章节规划模板.json`
|
|
@@ -179,6 +185,7 @@ node references/upstream-query.js --stage=血肉 --file=角色 --id=C001
|
|
|
179
185
|
---
|
|
180
186
|
|
|
181
187
|
<!-- contract:file:节奏参数 -->
|
|
188
|
+
|
|
182
189
|
## 六、节奏参数.json 的字段契约
|
|
183
190
|
|
|
184
191
|
**顶层**:纯对象(没有顶层数组) **模板**:`模板/节奏/节奏参数模板.json`
|
|
@@ -280,6 +287,7 @@ main_progress_chapter_count = T - branch_chapter_total + overlap_chapter_count
|
|
|
280
287
|
---
|
|
281
288
|
|
|
282
289
|
<!-- contract:file:时序映射 -->
|
|
290
|
+
|
|
283
291
|
## 七、时序映射.json 的字段契约
|
|
284
292
|
|
|
285
293
|
**顶层**:13 个 `*_timeline` 数组 **模板**:`模板/节奏/时序映射模板.json`
|
|
@@ -394,6 +402,7 @@ main_progress_chapter_count = T - branch_chapter_total + overlap_chapter_count
|
|
|
394
402
|
---
|
|
395
403
|
|
|
396
404
|
<!-- contract:file:章节细纲 -->
|
|
405
|
+
|
|
397
406
|
## 八、章节细纲.json 的字段契约
|
|
398
407
|
|
|
399
408
|
**顶层数组**:`outlines` **模板**:`模板/节奏/章节细纲模板.json`
|
|
@@ -431,6 +440,7 @@ main_progress_chapter_count = T - branch_chapter_total + overlap_chapter_count
|
|
|
431
440
|
---
|
|
432
441
|
|
|
433
442
|
<!-- contract:consistency -->
|
|
443
|
+
|
|
434
444
|
## 九、跨文件一致性(本阶段最容易翻车的地方)
|
|
435
445
|
|
|
436
446
|
节奏阶段的多数校验是**全量口径**的——单看一个文件查不出来,必须四个文件对得上。
|
|
@@ -469,6 +479,7 @@ main_progress_chapter_count = T - branch_chapter_total + overlap_chapter_count
|
|
|
469
479
|
---
|
|
470
480
|
|
|
471
481
|
<!-- contract:errors -->
|
|
482
|
+
|
|
472
483
|
## 十、常见错误代码速查
|
|
473
484
|
|
|
474
485
|
插件回喂给你的错误清单里的 `code` 对应下表。**只改被点名的字段**,其余不要动。
|
|
@@ -514,6 +525,7 @@ main_progress_chapter_count = T - branch_chapter_total + overlap_chapter_count
|
|
|
514
525
|
---
|
|
515
526
|
|
|
516
527
|
<!-- contract:forbidden -->
|
|
528
|
+
|
|
517
529
|
## 十一、本阶段禁令(11 条)
|
|
518
530
|
|
|
519
531
|
1. **章节号必须在 `[1, T]` 内**。`RHYTHM_CHAP_RANGE` 会拦截越界。
|