dsh-novel-write-engine 0.2.0 → 0.2.1

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.
@@ -45,7 +45,12 @@ export interface SummaryDto {
45
45
  total: number;
46
46
  planned: number;
47
47
  archived: number;
48
+ target?: number | null;
49
+ missing_cards?: number;
50
+ planned_coverage?: number | null;
51
+ archived_coverage?: number | null;
48
52
  coverage: number;
53
+ card_coverage?: number;
49
54
  volumes: Array<{
50
55
  title: string;
51
56
  start: number;
@@ -62,6 +67,7 @@ export interface SummaryDto {
62
67
  rules: number;
63
68
  glossary: number;
64
69
  backstory: number;
70
+ facts?: number;
65
71
  };
66
72
  };
67
73
  quality?: {
@@ -53,6 +53,10 @@ export interface PanelView {
53
53
  outlineTotal: number;
54
54
  archivedCards: number;
55
55
  coverage: number;
56
+ missingCards: number;
57
+ plannedCoverage: number | null;
58
+ archivedCoverage: number | null;
59
+ cardCoverage: number;
56
60
  volumes: Array<{
57
61
  title: string;
58
62
  range: string;
@@ -66,6 +70,7 @@ export interface PanelView {
66
70
  rules: number;
67
71
  glossary: number;
68
72
  backstory: number;
73
+ facts?: number;
69
74
  };
70
75
  };
71
76
  quality: {
@@ -92,7 +97,7 @@ export interface PanelView {
92
97
  revision: string;
93
98
  next: string;
94
99
  }
95
- export declare const PANEL_SCHEMA_VERSION = 2;
100
+ export declare const PANEL_SCHEMA_VERSION = 3;
96
101
  /**
97
102
  * Project the wire payload into strings. Version mismatch wins over everything
98
103
  * else: a stale panel must never render data from another schema as if it were
@@ -4,7 +4,7 @@ export declare const PLUGIN_NAME = "dsh-novel-write-engine";
4
4
  export declare const PANEL_ID = "novel-workshop";
5
5
  export declare const PANEL_ROUTE = "/api/novel-write-engine/panel";
6
6
  export declare const SKILL_NAME = "novel-write-engine";
7
- export declare const REMOTE_VERSION = 2;
7
+ export declare const REMOTE_VERSION = 3;
8
8
  /** The panel is a recent-history view; the wire payload and UI use one cap. */
9
9
  export declare const PANEL_CHAPTER_LIMIT = 30;
10
10
  /** Project-relative locations. Every write goes through these constants. */
@@ -18,6 +18,9 @@ export declare const REVIEW_DIR = "reviews";
18
18
  export declare const CHECK_DIR = "checks";
19
19
  export declare const EXPORT_DIR = "exports";
20
20
  export declare const BACKUP_DIR = "backups";
21
+ export declare const HISTORY_DIR = "history";
22
+ /** Brief receipts are append-only evidence, separate from content transactions. */
23
+ export declare const BRIEF_RECEIPTS_FILE = "state/briefs.yaml";
21
24
  export declare const OUTLINE_DIR = "outline";
22
25
  export declare const LOCK_FILE = ".engine.lock";
23
26
  export declare const STAGING_DIR = ".staging";
@@ -43,6 +46,13 @@ export declare const planWorldFile: (chapter: number) => string;
43
46
  export declare const planChapterFile: (chapter: number) => string;
44
47
  export declare const reviewFile: (chapter: number) => string;
45
48
  export declare const checkFile: (chapter: number) => string;
49
+ export declare const reviewHistoryFile: (chapter: number, revision: number) => string;
50
+ export declare const checkHistoryFile: (chapter: number, revision: number) => string;
51
+ export declare const chapterHistoryFile: (chapter: number, revision: number) => string;
52
+ export declare const deprecatedHistoryFile: (chapter: number, revision: number) => string;
53
+ export declare const planHistoryFile: (chapter: number, revision: number) => string;
54
+ export declare const HISTORY_KINDS: readonly ["reviews", "checks", "chapters", "deprecated", "plans"];
55
+ export type HistoryKind = (typeof HISTORY_KINDS)[number];
46
56
  /** Limits that are structural, not taste. */
47
57
  export declare const LIMITS: {
48
58
  /** P4 <-> P5/P6 retries before a forced rollback. */
@@ -76,7 +86,7 @@ export declare const INITIAL_STAGE: Stage;
76
86
  /** The order used to render the nine-phase progress strip. */
77
87
  export declare const PHASE_STRIP: readonly ["P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9"];
78
88
  /** Tool names, kept here so the arch test can assert one namespace. */
79
- export declare const TOOL_NAMES: readonly ["novel_init", "novel_status", "novel_brief", "novel_plan_world", "novel_plan_chapter", "novel_write_draft", "novel_review", "novel_revise", "novel_check", "novel_archive", "novel_word_count", "novel_state", "novel_amend", "novel_rollback", "novel_diff", "novel_export", "novel_audit", "novel_pipeline", "novel_blueprint", "novel_outline", "novel_outline_import", "novel_worldbook", "novel_search", "novel_doctor", "novel_report", "novel_guide", "novel_reopen"];
89
+ export declare const TOOL_NAMES: readonly ["novel_init", "novel_status", "novel_brief", "novel_plan_world", "novel_plan_chapter", "novel_write_draft", "novel_review", "novel_revise", "novel_check", "novel_archive", "novel_word_count", "novel_state", "novel_amend", "novel_rollback", "novel_diff", "novel_export", "novel_audit", "novel_pipeline", "novel_blueprint", "novel_outline", "novel_outline_import", "novel_worldbook", "novel_search", "novel_doctor", "novel_report", "novel_guide", "novel_reopen", "novel_restore"];
80
90
  export type ToolName = (typeof TOOL_NAMES)[number];
81
91
  /** The ten high-frequency tools kept when `tools.mode = core`. */
82
92
  export declare const CORE_TOOLS: readonly ToolName[];
@@ -21,7 +21,7 @@ export type SceneType = (typeof SCENE_TYPES)[number];
21
21
  /** A violation is blocking unless the rule pack declares it advisory. */
22
22
  export type Severity = 'blocker' | 'advisory';
23
23
  /** All thirty-one service operations (22 inherited from 0.1.x, 9 book-level). */
24
- export declare const OPERATIONS: readonly ["initProject", "archiveChapter", "amend", "rollback", "reopenChapter", "submitWorldPlan", "submitChapterPlan", "submitDraft", "submitReview", "submitRevision", "runCheck", "submitBookPlan", "submitOutline", "importOutline", "submitWorldbook", "getStatus", "getBrief", "countWords", "queryState", "diff", "auditHistory", "advise", "search", "doctor", "report", "guide", "export", "panelSummary", "panelChapters", "panelGates", "stats"];
24
+ export declare const OPERATIONS: readonly ["initProject", "archiveChapter", "amend", "rollback", "reopenChapter", "submitWorldPlan", "submitChapterPlan", "submitDraft", "submitReview", "submitRevision", "runCheck", "submitBookPlan", "submitOutline", "importOutline", "submitWorldbook", "getStatus", "getBrief", "countWords", "queryState", "diff", "auditHistory", "advise", "search", "doctor", "report", "guide", "export", "panelSummary", "panelChapters", "panelGates", "stats", "restoreBackup"];
25
25
  export type Operation = (typeof OPERATIONS)[number];
26
26
  /** Structured, non-fatal note attached to a successful result. */
27
27
  export interface Warning {
@@ -161,6 +161,7 @@ export interface CheckDocument {
161
161
  content_hash: string;
162
162
  machine: {
163
163
  violations: Violation[];
164
+ advisories?: Violation[];
164
165
  metrics: WordMetrics;
165
166
  };
166
167
  semantic: {
@@ -171,6 +172,8 @@ export interface CheckDocument {
171
172
  note: string;
172
173
  }>;
173
174
  };
175
+ /** Advisory codes the author has explicitly acknowledged for this content. */
176
+ acknowledged?: string[];
174
177
  verdict: 'pass' | 'fail';
175
178
  }
176
179
  /** Every persisted document whose damage status/panel can report. */
@@ -189,6 +192,8 @@ export interface WordMetrics {
189
192
  numbers: number;
190
193
  chinese_punct: number;
191
194
  english_punct: number;
195
+ /** All punctuation counted by the engine; total = cjk + words + numbers + punctuation. */
196
+ punctuation_chars: number;
192
197
  non_ws_chars: number;
193
198
  total_lines: number;
194
199
  non_empty_lines: number;
@@ -211,6 +216,10 @@ export interface ChapterRecord {
211
216
  status: 'draft' | 'reviewed';
212
217
  content_hash: string;
213
218
  summary: ChapterSummary;
219
+ /** How hard this chapter was before it was archived. */
220
+ rounds?: RoundCounters;
221
+ final_check?: 'pass' | 'fail';
222
+ archived_at?: string;
214
223
  /** Keys allocated by the archive transaction; lets a cross-process retry replay. */
215
224
  assigned_ids?: Record<string, string>;
216
225
  /** Digest of the archive request that produced this row. */
@@ -225,6 +234,7 @@ export interface ChapterSummary {
225
234
  key: string;
226
235
  title: string;
227
236
  description: string;
237
+ anchor?: string;
228
238
  }>;
229
239
  advanced: Array<{
230
240
  key: string;
@@ -258,6 +268,8 @@ export interface RoundCounters {
258
268
  review: number;
259
269
  revise: number;
260
270
  check: number;
271
+ /** Lifetime rollback count on a chapter record; never stored in the live pipeline. */
272
+ rollbacks?: number;
261
273
  }
262
274
  /** How one ledger entity changed in this chapter. */
263
275
  export type DeltaAction = 'created' | 'updated' | 'no_change';
@@ -289,6 +301,8 @@ export interface ForeshadowDelta {
289
301
  action: DeltaAction;
290
302
  reason?: string;
291
303
  title?: string;
304
+ /** Verbatim manuscript quote used for verification; title stays a readable label. */
305
+ anchor?: string;
292
306
  description?: string;
293
307
  note?: string;
294
308
  new_info?: boolean;
@@ -331,6 +345,28 @@ export interface ArchiveHandoff {
331
345
  act?: string;
332
346
  act_progress?: string;
333
347
  }
348
+ /** One issued task-book receipt; the brief itself is rendered on demand. */
349
+ export interface BriefReceipt {
350
+ chapter: number;
351
+ stage: BriefStage;
352
+ digest: string;
353
+ issued_at: string;
354
+ }
355
+ /** `state/briefs.yaml`: append-only task-book evidence outside content transactions. */
356
+ export interface BriefReceiptsDocument {
357
+ schema_version: 1;
358
+ receipts: BriefReceipt[];
359
+ }
360
+ /** The active draft's own metadata; P2 plan stays immutable after submission. */
361
+ export interface DraftState {
362
+ chapter: number;
363
+ title: string;
364
+ scene_type: SceneType;
365
+ narrator: string;
366
+ summary: ChapterSummary;
367
+ content_hash: string;
368
+ updated_at: string;
369
+ }
334
370
  /** Pipeline document (`state/pipeline.yaml`). */
335
371
  export interface PipelineState {
336
372
  schema_version: 1;
@@ -343,6 +379,8 @@ export interface PipelineState {
343
379
  digest: string;
344
380
  }>;
345
381
  blocking: BlockingItem[];
382
+ /** Current draft summary/title; never written into the P2 plan file. */
383
+ draft?: DraftState;
346
384
  /** Hash of the review document last written by submitReview/submitRevision. */
347
385
  review_digest?: string;
348
386
  last_action: {
@@ -422,6 +460,7 @@ export interface ForeshadowsDocument {
422
460
  status: 'planted' | 'dormant' | 'advanced' | 'resolved';
423
461
  resolved_at: number | null;
424
462
  description: string;
463
+ anchor?: string;
425
464
  advance_log: Array<{
426
465
  chapter: number;
427
466
  note: string;
@@ -614,6 +653,14 @@ export interface WorldbookBackstory {
614
653
  time: string;
615
654
  event: string;
616
655
  }
656
+ /** One declared numeric canon, checked against the manuscript on request. */
657
+ export interface WorldbookFact {
658
+ alias: string;
659
+ value: number;
660
+ unit: string;
661
+ tolerance?: number;
662
+ note?: string;
663
+ }
617
664
  /** Worldbuilding plan, persisted in `outline/worldbook.yaml`. */
618
665
  export interface WorldbookDocument {
619
666
  schema_version: 1;
@@ -626,6 +673,8 @@ export interface WorldbookDocument {
626
673
  characters: WorldbookCharacter[];
627
674
  glossary: WorldbookGlossary[];
628
675
  backstory: WorldbookBackstory[];
676
+ /** Optional numeric canon; old documents omit it. */
677
+ facts?: WorldbookFact[];
629
678
  themes: string[];
630
679
  }
631
680
  /** One hit from `novel_search`; the scope names the source family. */
@@ -663,6 +712,22 @@ export interface DoctorReport {
663
712
  infos: number;
664
713
  };
665
714
  }
715
+ /** One canonical outline-progress calculation shared by every adapter. */
716
+ export interface OutlineProgress {
717
+ present: boolean;
718
+ target: number | null;
719
+ total: number;
720
+ planned: number;
721
+ archived: number;
722
+ missingCards: number;
723
+ plannedCoverage: number | null;
724
+ archivedCoverage: number | null;
725
+ /** Compatibility alias: planned coverage when a target exists, otherwise card coverage. */
726
+ coverage: number;
727
+ /** Fraction of archived chapters that have a matching archived card. */
728
+ cardCoverage: number;
729
+ volumes: number;
730
+ }
666
731
  /** Book-wide quality, outline, cast and pacing aggregates. */
667
732
  export interface BookReport {
668
733
  progress: {
@@ -672,13 +737,22 @@ export interface BookReport {
672
737
  average_words: number;
673
738
  percent: number;
674
739
  remaining_words: number | null;
740
+ remaining_words_min: number | null;
741
+ remaining_words_average: number | null;
742
+ remaining_words_basis: 'actual_average' | 'minimum_target' | 'none';
675
743
  };
676
744
  outline: {
677
745
  present: boolean;
678
746
  strict: boolean;
747
+ target: number | null;
748
+ total: number;
679
749
  planned: number;
680
750
  archived: number;
751
+ missing_cards: number;
752
+ planned_coverage: number | null;
753
+ archived_coverage: number | null;
681
754
  coverage: number;
755
+ card_coverage: number;
682
756
  volumes: Array<{
683
757
  title: string;
684
758
  start: number;
@@ -701,6 +775,7 @@ export interface BookReport {
701
775
  rules: number;
702
776
  glossary: number;
703
777
  backstory: number;
778
+ facts?: number;
704
779
  };
705
780
  quality: {
706
781
  average: number;
@@ -715,6 +790,22 @@ export interface BookReport {
715
790
  samples: number;
716
791
  }>;
717
792
  };
793
+ /** Per-chapter effort survives archive (pipeline rounds are reset). */
794
+ effort: {
795
+ reviews: number;
796
+ revisions: number;
797
+ checks: number;
798
+ rollbacks: number;
799
+ chapters: Array<{
800
+ num: number;
801
+ reviews: number;
802
+ revisions: number;
803
+ checks: number;
804
+ rollbacks: number;
805
+ final_check: 'pass' | 'fail' | null;
806
+ archived_at: string | null;
807
+ }>;
808
+ };
718
809
  pacing: {
719
810
  scene_types: Record<string, number>;
720
811
  hook_strength: Record<string, number>;
@@ -805,10 +896,23 @@ export interface ReviewInput {
805
896
  total: number;
806
897
  proof: ReadingProof;
807
898
  }
899
+ /** One exact, unique replacement used by patch-mode revisions. */
900
+ export interface RevisionEdit {
901
+ old_text: string;
902
+ new_text: string;
903
+ /** 1-based occurrence; defaults to requiring exactly one match. */
904
+ occurrence?: number;
905
+ }
906
+ /** Patch-mode revision; content and patch are mutually exclusive. */
907
+ export interface RevisionPatch {
908
+ expected_hash: string;
909
+ edits: RevisionEdit[];
910
+ }
808
911
  /** Revision submission payload. */
809
912
  export interface RevisionInput {
810
913
  chapter: number;
811
- content: string;
914
+ content?: string;
915
+ patch?: RevisionPatch;
812
916
  summary: ChapterSummary;
813
917
  }
814
918
  /** Semantic check items supplied by the model. */
@@ -910,10 +1014,15 @@ export interface StatusReport {
910
1014
  strict: boolean;
911
1015
  outline: {
912
1016
  present: boolean;
1017
+ target: number | null;
913
1018
  total: number;
914
1019
  planned: number;
915
1020
  archived: number;
1021
+ missing_cards: number;
1022
+ planned_coverage: number | null;
1023
+ archived_coverage: number | null;
916
1024
  coverage: number;
1025
+ card_coverage: number;
917
1026
  volumes: number;
918
1027
  current: OutlineChapter | null;
919
1028
  };
@@ -925,6 +1034,7 @@ export interface StatusReport {
925
1034
  rules: number;
926
1035
  glossary: number;
927
1036
  backstory: number;
1037
+ facts?: number;
928
1038
  };
929
1039
  };
930
1040
  next: {
@@ -945,6 +1055,8 @@ export interface AdviceReport {
945
1055
  }
946
1056
  /** One history row derived from the journal. */
947
1057
  export interface AuditRow {
1058
+ /** Stable chronological cursor; absent only on hand-built test rows. */
1059
+ seq?: number;
948
1060
  at: string;
949
1061
  op: string;
950
1062
  chapter: number;
@@ -952,6 +1064,14 @@ export interface AuditRow {
952
1064
  txid: string;
953
1065
  status: 'committed' | 'aborted';
954
1066
  files: string[];
1067
+ /** Machine code and human reason for a refused attempt. */
1068
+ code?: string;
1069
+ reason?: string;
1070
+ hint?: string;
1071
+ stage?: string;
1072
+ /** True when no transaction started: the gate/input refused the call. */
1073
+ attempt?: boolean;
1074
+ blocking?: BlockingItem[];
955
1075
  }
956
1076
  /** One diff hunk between two revisions of a chapter. */
957
1077
  export interface DiffReport {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-novel-write-engine",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Novel writing engine for DeepSeek Harness: state machine, gates, rulepacks and ledgers moved from prompts into code.",
5
5
  "keywords": [
6
6
  "dsh-plugin",
@@ -4,7 +4,7 @@
4
4
  config:
5
5
  id: novel-write-engine
6
6
  name: 网文工坊
7
- description: 网文创作专用会话:27 个小说工具全开,无文件写权限,门控与字数由引擎裁决。
7
+ description: 网文创作专用会话:28 个小说工具全开,无文件写权限,门控与字数由引擎裁决。
8
8
  order: 20
9
9
  plugins:
10
10
  - id: persona
package/skills/entry.md CHANGED
@@ -50,21 +50,22 @@ description: 引擎版小说创作流程——状态、门控、字数与写盘
50
50
  | `novel_report` | 全书报告 |
51
51
  | `novel_guide` | 上手引导与下一步 |
52
52
  | `novel_reopen` | 从归档备份重开紧邻的上一章 |
53
+ | `novel_restore` | 从标记备份恢复活动章 |
53
54
  | `novel_brief` | 取阶段任务书与上下文 |
54
55
  | `novel_plan_world` | P1 世界观计划 |
55
56
  | `novel_plan_chapter` | P2 章节计划 |
56
57
  | `novel_write_draft` | P3 初稿 |
57
58
  | `novel_review` | P4 十五维评分 |
58
- | `novel_revise` | P5 修订 |
59
- | `novel_check` | P6 一致性校验 |
59
+ | `novel_revise` | P5 修订(支持 exact patch) |
60
+ | `novel_check` | P6 一致性校验(advisory 可 acknowledge) |
60
61
  | `novel_archive` | 归档事务 |
61
62
  | `novel_word_count` | 字数口径 |
62
- | `novel_state` | 只读台账/计划/评审 |
63
+ | `novel_state` | 只读台账/计划/评审/history/backups/briefs |
63
64
  | `novel_amend` | 受控改状态文档 |
64
65
  | `novel_rollback` | 回退阶段 |
65
66
  | `novel_diff` | 与备份/文本对比 |
66
67
  | `novel_export` | md/txt/epub/outline/worldbook/proposal |
67
- | `novel_audit` | 事务审计 |
68
+ | `novel_audit` | 事务与失败 attempt 审计 |
68
69
  | `novel_pipeline` | 推荐下一步与参数 |
69
70
 
70
71
  ## 工具怎么用