dsh-novel-write-engine 0.2.1 → 0.2.3
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 +60 -1
- package/README.md +124 -57
- package/briefs/P5.md +22 -1
- package/briefs/P8.md +67 -1
- package/lib/client.js +591 -55
- package/lib/index.d.ts +393 -37
- package/lib/index.js +4039 -1997
- package/lib/types/client/dto.d.ts +45 -4
- package/lib/types/client/panel.d.ts +1 -1
- package/lib/types/client/viewmodel.d.ts +50 -3
- package/lib/types/constants.d.ts +4 -1
- package/lib/types/types.d.ts +37 -2
- package/package.json +1 -1
- package/rulepacks/default.yaml +4 -2
- package/skills/entry.md +7 -0
package/lib/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ declare const SCENE_TYPES: readonly ["战斗/动作章", "日常过渡章", "情
|
|
|
22
22
|
type SceneType = (typeof SCENE_TYPES)[number];
|
|
23
23
|
/** A violation is blocking unless the rule pack declares it advisory. */
|
|
24
24
|
type Severity = 'blocker' | 'advisory';
|
|
25
|
-
/** All thirty-
|
|
25
|
+
/** All thirty-two service operations (22 inherited + 9 book-level + restoreBackup). */
|
|
26
26
|
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"];
|
|
27
27
|
type Operation = (typeof OPERATIONS)[number];
|
|
28
28
|
/** Structured, non-fatal note attached to a successful result. */
|
|
@@ -60,11 +60,18 @@ interface ReadingProof {
|
|
|
60
60
|
/** Error families map one-to-one to the three repair actions a caller can take. */
|
|
61
61
|
declare const ERROR_CODES: {
|
|
62
62
|
readonly PROJECT_NOT_FOUND: "ENGINE_PROJECT_NOT_FOUND";
|
|
63
|
+
readonly PROJECT_AMBIGUOUS: "ENGINE_PROJECT_AMBIGUOUS";
|
|
64
|
+
readonly PROJECT_MISSING: "ENGINE_PROJECT_MISSING";
|
|
65
|
+
readonly PROJECT_IDENTITY_MISMATCH: "ENGINE_PROJECT_IDENTITY_MISMATCH";
|
|
63
66
|
readonly PROJECT_EXISTS: "ENGINE_PROJECT_EXISTS";
|
|
64
67
|
readonly STAGE_ORDER: "ENGINE_STAGE_ORDER";
|
|
68
|
+
/** The exact same keyed submission already failed in the same context. */
|
|
69
|
+
readonly RETRY_UNCHANGED: "ENGINE_RETRY_UNCHANGED";
|
|
65
70
|
readonly GATE_BLOCKED: "ENGINE_GATE_BLOCKED";
|
|
66
71
|
readonly READING_PROOF_INVALID: "ENGINE_READING_PROOF_INVALID";
|
|
67
72
|
readonly SCORE_MISMATCH: "ENGINE_SCORE_MISMATCH";
|
|
73
|
+
/** A revision tried to rewrite reviewer-owned issue fields. */
|
|
74
|
+
readonly ISSUE_IMMUTABLE: "ENGINE_ISSUE_IMMUTABLE";
|
|
68
75
|
readonly DELTA_UNVERIFIED: "ENGINE_DELTA_UNVERIFIED";
|
|
69
76
|
readonly RESOURCE_NEGATIVE_BALANCE: "ENGINE_RESOURCE_NEGATIVE_BALANCE";
|
|
70
77
|
readonly SCHEMA_TOO_NEW: "ENGINE_SCHEMA_TOO_NEW";
|
|
@@ -461,6 +468,8 @@ interface ForeshadowsDocument {
|
|
|
461
468
|
resolved_at: number | null;
|
|
462
469
|
description: string;
|
|
463
470
|
anchor?: string;
|
|
471
|
+
/** New 0.2.3 writes are distinguishable from pre-0.2.3 rows by this marker. */
|
|
472
|
+
format_version?: 1;
|
|
464
473
|
advance_log: Array<{
|
|
465
474
|
chapter: number;
|
|
466
475
|
note: string;
|
|
@@ -783,7 +792,13 @@ interface BookReport {
|
|
|
783
792
|
min: number;
|
|
784
793
|
max: number;
|
|
785
794
|
last_five: number[];
|
|
786
|
-
|
|
795
|
+
/** Null when there are not enough distinct chapter reviews to compare. */
|
|
796
|
+
trend: number | null;
|
|
797
|
+
trend_basis: 'last_five_vs_previous_five' | 'insufficient_samples' | 'insufficient_history';
|
|
798
|
+
/** Number of chapters represented by a final review. */
|
|
799
|
+
samples: number;
|
|
800
|
+
/** Committed review rounds for this report, including history. */
|
|
801
|
+
attempts: number;
|
|
787
802
|
dimensions: Array<{
|
|
788
803
|
id: string;
|
|
789
804
|
average: number;
|
|
@@ -984,6 +999,15 @@ interface ChapterStatusRow {
|
|
|
984
999
|
stage: Stage;
|
|
985
1000
|
passed: boolean;
|
|
986
1001
|
}
|
|
1002
|
+
/** Where an omitted project root came from. */
|
|
1003
|
+
type SelectionSource = 'explicit' | 'session' | 'workspace' | 'active' | 'config' | 'single';
|
|
1004
|
+
/** One resolved project choice, before the project is loaded. */
|
|
1005
|
+
interface Selection {
|
|
1006
|
+
root: string;
|
|
1007
|
+
source: SelectionSource;
|
|
1008
|
+
title?: string;
|
|
1009
|
+
created_at?: string;
|
|
1010
|
+
}
|
|
987
1011
|
/** The `getStatus` payload. */
|
|
988
1012
|
interface StatusReport {
|
|
989
1013
|
project: {
|
|
@@ -992,10 +1016,17 @@ interface StatusReport {
|
|
|
992
1016
|
platform: Platform;
|
|
993
1017
|
root: string;
|
|
994
1018
|
};
|
|
1019
|
+
/** Why this project was chosen; lets the model notice a wrong book. */
|
|
1020
|
+
selection?: {
|
|
1021
|
+
source: SelectionSource;
|
|
1022
|
+
root: string;
|
|
1023
|
+
};
|
|
995
1024
|
/** The chapter requested for metrics; may be historical. */
|
|
996
1025
|
chapter: number;
|
|
997
1026
|
/** The chapter the pipeline is currently working on. */
|
|
998
1027
|
active_chapter: number;
|
|
1028
|
+
/** SHA-256 of the active manuscript, or null when the stage has no draft. */
|
|
1029
|
+
manuscript_hash: string | null;
|
|
999
1030
|
stage: Stage;
|
|
1000
1031
|
rounds: RoundCounters;
|
|
1001
1032
|
blocking: BlockingItem[];
|
|
@@ -1072,6 +1103,10 @@ interface AuditRow {
|
|
|
1072
1103
|
/** True when no transaction started: the gate/input refused the call. */
|
|
1073
1104
|
attempt?: boolean;
|
|
1074
1105
|
blocking?: BlockingItem[];
|
|
1106
|
+
/** Keyed operation fingerprint; lets an identical failed retry be refused. */
|
|
1107
|
+
retry_key?: string;
|
|
1108
|
+
/** Brief/stage/revision context for `retry_key`. */
|
|
1109
|
+
retry_context?: string;
|
|
1075
1110
|
}
|
|
1076
1111
|
/** One diff hunk between two revisions of a chapter. */
|
|
1077
1112
|
interface DiffReport {
|
|
@@ -1219,6 +1254,8 @@ type DocKind = 'project' | 'pipeline' | 'chapters' | 'characters' | 'world' | 'l
|
|
|
1219
1254
|
interface RegistryEntry {
|
|
1220
1255
|
root: string;
|
|
1221
1256
|
title: string;
|
|
1257
|
+
/** Project identity; absent on registries written by 0.2.1 and earlier. */
|
|
1258
|
+
created_at?: string;
|
|
1222
1259
|
updated_at: string;
|
|
1223
1260
|
}
|
|
1224
1261
|
interface BookPatch {
|
|
@@ -1382,7 +1419,10 @@ interface PanelSnapshot {
|
|
|
1382
1419
|
quality?: {
|
|
1383
1420
|
averageScore: number;
|
|
1384
1421
|
scores: number[];
|
|
1385
|
-
trend: number;
|
|
1422
|
+
trend: number | null;
|
|
1423
|
+
trend_basis?: 'last_five_vs_previous_five' | 'insufficient_samples' | 'insufficient_history';
|
|
1424
|
+
samples?: number;
|
|
1425
|
+
attempts?: number;
|
|
1386
1426
|
};
|
|
1387
1427
|
health?: {
|
|
1388
1428
|
ok: boolean;
|
|
@@ -1395,6 +1435,19 @@ interface PanelSnapshot {
|
|
|
1395
1435
|
chapter: number;
|
|
1396
1436
|
status: string;
|
|
1397
1437
|
}>;
|
|
1438
|
+
/** Unacknowledged machine advisories; never mixed into `blocking`. */
|
|
1439
|
+
advisories?: Array<{
|
|
1440
|
+
code: string;
|
|
1441
|
+
detail: string;
|
|
1442
|
+
hint?: string;
|
|
1443
|
+
}>;
|
|
1444
|
+
/** Number of advisory codes already acknowledged for the current check. */
|
|
1445
|
+
acknowledgedAdvisories?: number;
|
|
1446
|
+
/** Read-only upgrade findings; null when the project needs no explanation. */
|
|
1447
|
+
legacy?: Array<{
|
|
1448
|
+
code: string;
|
|
1449
|
+
detail: string;
|
|
1450
|
+
}>;
|
|
1398
1451
|
}
|
|
1399
1452
|
interface PanelBook {
|
|
1400
1453
|
premise: string;
|
|
@@ -1434,6 +1487,8 @@ interface PanelBook {
|
|
|
1434
1487
|
interface PanelSummaryDto {
|
|
1435
1488
|
schemaVersion: number;
|
|
1436
1489
|
panelId: string;
|
|
1490
|
+
/** Absolute project root, so a stale title cannot hide a wrong book. */
|
|
1491
|
+
root: string;
|
|
1437
1492
|
title: string;
|
|
1438
1493
|
genre: string;
|
|
1439
1494
|
platform: string;
|
|
@@ -1465,7 +1520,10 @@ interface PanelSummaryDto {
|
|
|
1465
1520
|
quality?: {
|
|
1466
1521
|
averageScore: number;
|
|
1467
1522
|
scores: number[];
|
|
1468
|
-
trend: number;
|
|
1523
|
+
trend: number | null;
|
|
1524
|
+
trend_basis?: 'last_five_vs_previous_five' | 'insufficient_samples' | 'insufficient_history';
|
|
1525
|
+
samples?: number;
|
|
1526
|
+
attempts?: number;
|
|
1469
1527
|
};
|
|
1470
1528
|
health?: {
|
|
1471
1529
|
ok: boolean;
|
|
@@ -1478,6 +1536,19 @@ interface PanelSummaryDto {
|
|
|
1478
1536
|
chapter: number;
|
|
1479
1537
|
status: string;
|
|
1480
1538
|
}>;
|
|
1539
|
+
/** Unacknowledged machine advisories; never mixed into `blocking`. */
|
|
1540
|
+
advisories?: Array<{
|
|
1541
|
+
code: string;
|
|
1542
|
+
detail: string;
|
|
1543
|
+
hint?: string;
|
|
1544
|
+
}>;
|
|
1545
|
+
/** Number of advisory codes already acknowledged for the current check. */
|
|
1546
|
+
acknowledgedAdvisories?: number;
|
|
1547
|
+
/** Read-only upgrade findings; null when the project needs no explanation. */
|
|
1548
|
+
legacy?: Array<{
|
|
1549
|
+
code: string;
|
|
1550
|
+
detail: string;
|
|
1551
|
+
}>;
|
|
1481
1552
|
}
|
|
1482
1553
|
interface PanelChapterRow {
|
|
1483
1554
|
num: number;
|
|
@@ -1502,6 +1573,49 @@ interface PanelGatesDto {
|
|
|
1502
1573
|
/** Human-facing one-liner per blocking item. */
|
|
1503
1574
|
explanations: string[];
|
|
1504
1575
|
}
|
|
1576
|
+
/** One selectable project in the panel; state is cheap, not a full load. */
|
|
1577
|
+
interface PanelProjectOption {
|
|
1578
|
+
root: string;
|
|
1579
|
+
title: string;
|
|
1580
|
+
active: boolean;
|
|
1581
|
+
registered: boolean;
|
|
1582
|
+
state: 'ok' | 'damaged' | 'missing' | 'not-project' | 'unreadable';
|
|
1583
|
+
/** The path now holds a different project identity; writes will fail closed. */
|
|
1584
|
+
identity_changed?: boolean;
|
|
1585
|
+
}
|
|
1586
|
+
interface PanelSelection {
|
|
1587
|
+
root: string | null;
|
|
1588
|
+
source: 'query' | 'active' | 'single' | 'config' | 'none';
|
|
1589
|
+
}
|
|
1590
|
+
interface PanelMissing {
|
|
1591
|
+
root: string;
|
|
1592
|
+
title: string;
|
|
1593
|
+
code: 'ENGINE_PROJECT_MISSING' | 'ENGINE_PROJECT_NOT_FOUND' | 'ENGINE_TXN_IN_PROGRESS';
|
|
1594
|
+
reason: 'missing' | 'not-project' | 'damaged' | 'not_registered' | 'unreadable' | 'busy';
|
|
1595
|
+
hint: string;
|
|
1596
|
+
}
|
|
1597
|
+
interface PanelBundle {
|
|
1598
|
+
projects: PanelProjectOption[];
|
|
1599
|
+
selection: PanelSelection;
|
|
1600
|
+
summary?: PanelSummaryDto;
|
|
1601
|
+
chapters?: PanelChaptersDto;
|
|
1602
|
+
gates?: PanelGatesDto;
|
|
1603
|
+
resume?: {
|
|
1604
|
+
text: string;
|
|
1605
|
+
};
|
|
1606
|
+
missing?: PanelMissing;
|
|
1607
|
+
empty?: true;
|
|
1608
|
+
error?: string;
|
|
1609
|
+
}
|
|
1610
|
+
interface ResumePromptInput {
|
|
1611
|
+
title: string;
|
|
1612
|
+
root: string;
|
|
1613
|
+
chapter: number | string;
|
|
1614
|
+
stage: string;
|
|
1615
|
+
nextTool: string;
|
|
1616
|
+
}
|
|
1617
|
+
/** One shared prompt template for `/novel resume` and the panel copy button. */
|
|
1618
|
+
declare function formatResumePrompt(input: ResumePromptInput): string;
|
|
1505
1619
|
/** The nine-phase progress strip: phases before the active one are done. */
|
|
1506
1620
|
declare function phaseStrip(stage: Stage, finished?: boolean): Array<{
|
|
1507
1621
|
id: string;
|
|
@@ -1513,6 +1627,15 @@ declare function projectChapter(record: ChapterRecord): PanelChapterRow;
|
|
|
1513
1627
|
declare function projectSummary(snapshot: PanelSnapshot): PanelSummaryDto;
|
|
1514
1628
|
declare function projectChapters(snapshot: PanelSnapshot): PanelChaptersDto;
|
|
1515
1629
|
declare function projectGates(snapshot: PanelSnapshot): PanelGatesDto;
|
|
1630
|
+
/** How much of a candidate project can be inspected without loading a snapshot. */
|
|
1631
|
+
type ProjectState = 'ok' | 'damaged' | 'not-project' | 'missing' | 'unreadable';
|
|
1632
|
+
interface ProjectInspection {
|
|
1633
|
+
root: string;
|
|
1634
|
+
state: ProjectState;
|
|
1635
|
+
title: string;
|
|
1636
|
+
created_at?: string;
|
|
1637
|
+
error?: string;
|
|
1638
|
+
}
|
|
1516
1639
|
/** Plugin configuration, mapped from `Config` in `src/index.ts`. */
|
|
1517
1640
|
interface EngineConfig {
|
|
1518
1641
|
projectRoot: string;
|
|
@@ -1623,6 +1746,16 @@ interface BriefInput {
|
|
|
1623
1746
|
chapter?: number;
|
|
1624
1747
|
root?: string;
|
|
1625
1748
|
}
|
|
1749
|
+
type BriefPayload = {
|
|
1750
|
+
stage: BriefStage;
|
|
1751
|
+
chapter: number;
|
|
1752
|
+
digest: string;
|
|
1753
|
+
title: string;
|
|
1754
|
+
content: string;
|
|
1755
|
+
content_hash: string;
|
|
1756
|
+
fields: Record<string, unknown>;
|
|
1757
|
+
context: Record<string, unknown>;
|
|
1758
|
+
};
|
|
1626
1759
|
interface WorldPlanSubmission extends WorldPlanInput {
|
|
1627
1760
|
root?: string;
|
|
1628
1761
|
}
|
|
@@ -1759,6 +1892,11 @@ interface ReportSubmission {
|
|
|
1759
1892
|
interface GuideInput {
|
|
1760
1893
|
root?: string;
|
|
1761
1894
|
}
|
|
1895
|
+
/** Session/workspace context of one tool or command call. */
|
|
1896
|
+
interface EngineCaller {
|
|
1897
|
+
sessionId?: string;
|
|
1898
|
+
cwd?: string;
|
|
1899
|
+
}
|
|
1762
1900
|
/**
|
|
1763
1901
|
* The single write authority. Tools, commands, the panel and task books never
|
|
1764
1902
|
* touch a file; every mutation is one of these operations.
|
|
@@ -1772,8 +1910,8 @@ declare class EngineService {
|
|
|
1772
1910
|
private readonly briefContextCache;
|
|
1773
1911
|
private readonly briefs;
|
|
1774
1912
|
private readonly now;
|
|
1775
|
-
|
|
1776
|
-
private
|
|
1913
|
+
private readonly metadataMutex;
|
|
1914
|
+
private readonly callerContext;
|
|
1777
1915
|
constructor(config: EngineConfig, rulepack: Rulepack | (() => Rulepack), options?: {
|
|
1778
1916
|
briefs?: BriefLibrary;
|
|
1779
1917
|
now?: () => Date;
|
|
@@ -1794,15 +1932,52 @@ declare class EngineService {
|
|
|
1794
1932
|
private readonly signalContext;
|
|
1795
1933
|
/** Bind the host cancellation signal to the engine work of one tool call. */
|
|
1796
1934
|
withSignal<T>(signal: AbortSignal | undefined, task: () => Promise<T>): Promise<T>;
|
|
1935
|
+
/** Bind the calling Agent session and cwd to every engine operation in `task`. */
|
|
1936
|
+
withCaller<T>(caller: EngineCaller | undefined, task: () => Promise<T>): Promise<T>;
|
|
1937
|
+
private caller;
|
|
1797
1938
|
/** The configured default project root. */
|
|
1798
1939
|
defaultRoot(): string;
|
|
1940
|
+
/** Resolve a caller-supplied root against the session cwd, like /novel use. */
|
|
1941
|
+
private resolveProjectPath;
|
|
1942
|
+
/** The resolved metadata directory; resolves relative config once per call. */
|
|
1943
|
+
private stateRoot;
|
|
1944
|
+
private stateStore;
|
|
1945
|
+
private bindings;
|
|
1799
1946
|
/**
|
|
1800
|
-
*
|
|
1801
|
-
*
|
|
1802
|
-
*
|
|
1947
|
+
* Serialize metadata read-modify-write across sessions and processes. The
|
|
1948
|
+
* project manuscript lock is a different lock; a slow write never blocks a
|
|
1949
|
+
* registry update.
|
|
1803
1950
|
*/
|
|
1951
|
+
withMetadataLock<T>(task: () => Promise<T>): Promise<T>;
|
|
1952
|
+
private inspectConfigRoot;
|
|
1953
|
+
/**
|
|
1954
|
+
* Resolve the four-layer choice: explicit, session binding, bounded workspace
|
|
1955
|
+
* discovery, then registry/config defaults. There is deliberately no
|
|
1956
|
+
* process-global "last project" layer.
|
|
1957
|
+
*/
|
|
1958
|
+
/** Doctor/guide may run before any project exists; that is not a failure. */
|
|
1959
|
+
private resolveRootForInspection;
|
|
1804
1960
|
private resolveRoot;
|
|
1805
1961
|
private storeFor;
|
|
1962
|
+
/** Persist one explicit choice for this DSH session. */
|
|
1963
|
+
private bindSelection;
|
|
1964
|
+
/**
|
|
1965
|
+
* Best-effort discovery bookkeeping. A metadata failure must never turn a
|
|
1966
|
+
* successful project read/write into a failure; the registry is convenience.
|
|
1967
|
+
*/
|
|
1968
|
+
private autoRegister;
|
|
1969
|
+
/** Record the session binding/registration implied by a successful selection. */
|
|
1970
|
+
private recordSelection;
|
|
1971
|
+
/**
|
|
1972
|
+
* Read paths may record convenience metadata, but a corrupt or read-only
|
|
1973
|
+
* state directory must not turn a successful explicit-root read into a
|
|
1974
|
+
* failure. Resolution without an explicit root still reads the binding
|
|
1975
|
+
* fail-closed; writes use recordSelection directly and report a committed
|
|
1976
|
+
* mutation with a warning if its metadata update fails.
|
|
1977
|
+
*/
|
|
1978
|
+
private recordSelectionBestEffort;
|
|
1979
|
+
/** Registration/activation/use need a readable project identity. */
|
|
1980
|
+
private assertProjectHealthy;
|
|
1806
1981
|
initProject(input: InitProjectInput): Promise<OpResult<{
|
|
1807
1982
|
root: string;
|
|
1808
1983
|
title: string;
|
|
@@ -1858,6 +2033,13 @@ declare class EngineService {
|
|
|
1858
2033
|
* the model only learns about the mismatch when that write aborts.
|
|
1859
2034
|
*/
|
|
1860
2035
|
private journalBlocking;
|
|
2036
|
+
/**
|
|
2037
|
+
* Count review attempts per archived chapter. The journal is authoritative;
|
|
2038
|
+
* history fills any per-chapter gap where it has more distinct historical
|
|
2039
|
+
* reviews than committed journal rows (legacy or a truncated upgrade). A
|
|
2040
|
+
* chapter can never report fewer attempts than readable current reviews.
|
|
2041
|
+
*/
|
|
2042
|
+
private reviewAttemptsByChapter;
|
|
1861
2043
|
/**
|
|
1862
2044
|
* Count every committed attempt for one chapter, not just the loop since the
|
|
1863
2045
|
* last rollback. `pipeline.rounds` is deliberately reset by rollback to keep
|
|
@@ -1865,6 +2047,12 @@ declare class EngineService {
|
|
|
1865
2047
|
*/
|
|
1866
2048
|
private lifetimeRounds;
|
|
1867
2049
|
getStatus(input?: StatusInput): Promise<OpResult<StatusReport>>;
|
|
2050
|
+
/**
|
|
2051
|
+
* Build a status report from an already-loaded snapshot. This deliberately
|
|
2052
|
+
* has no selection side effect: read-only callers such as /novel resume must
|
|
2053
|
+
* not register or bind the project just by reading it.
|
|
2054
|
+
*/
|
|
2055
|
+
private statusFor;
|
|
1868
2056
|
countWords(input?: WordCountInput): Promise<OpResult<WordMetrics>>;
|
|
1869
2057
|
queryState(input: StateQueryInput): Promise<OpResult<unknown>>;
|
|
1870
2058
|
advise(input?: {
|
|
@@ -1879,20 +2067,18 @@ declare class EngineService {
|
|
|
1879
2067
|
state_errors: StateError[];
|
|
1880
2068
|
}>>;
|
|
1881
2069
|
search(input: SearchInput): Promise<OpResult<SearchReport>>;
|
|
2070
|
+
/**
|
|
2071
|
+
* Read-only upgrade audit. It never edits a legacy document: the point is to
|
|
2072
|
+
* explain why an old project's numbers look different, not to rewrite history.
|
|
2073
|
+
*/
|
|
2074
|
+
private legacyIssues;
|
|
1882
2075
|
doctor(input?: DoctorInput): Promise<OpResult<DoctorReport>>;
|
|
1883
2076
|
private recoveryForSafe;
|
|
1884
2077
|
report(input?: ReportSubmission): Promise<OpResult<BookReport>>;
|
|
1885
2078
|
guide(input?: GuideInput): Promise<OpResult<GuideReport>>;
|
|
1886
|
-
getBrief(input: BriefInput): Promise<OpResult<
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
digest: string;
|
|
1890
|
-
title: string;
|
|
1891
|
-
content: string;
|
|
1892
|
-
content_hash: string;
|
|
1893
|
-
fields: Record<string, unknown>;
|
|
1894
|
-
context: Record<string, unknown>;
|
|
1895
|
-
}>>;
|
|
2079
|
+
getBrief(input: BriefInput): Promise<OpResult<BriefPayload>>;
|
|
2080
|
+
private assertBriefChapter;
|
|
2081
|
+
private briefPayload;
|
|
1896
2082
|
submitWorldPlan(input: WorldPlanSubmission): Promise<OpResult<{
|
|
1897
2083
|
chapter: number;
|
|
1898
2084
|
stage: Stage;
|
|
@@ -1960,14 +2146,21 @@ declare class EngineService {
|
|
|
1960
2146
|
panelGates(input?: {
|
|
1961
2147
|
root?: string;
|
|
1962
2148
|
}): Promise<PanelGatesDto>;
|
|
1963
|
-
/**
|
|
2149
|
+
/**
|
|
2150
|
+
* Build the read-only panel payload. The query root is accepted only when it
|
|
2151
|
+
* is registered, active or the configured root; arbitrary paths never reach
|
|
2152
|
+
* the filesystem from the panel route.
|
|
2153
|
+
*/
|
|
1964
2154
|
panelBundle(input?: {
|
|
1965
2155
|
root?: string;
|
|
1966
|
-
}): Promise<
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
}
|
|
2156
|
+
}): Promise<PanelBundle>;
|
|
2157
|
+
/** Read-only resume text shared with the panel copy button. */
|
|
2158
|
+
resumePrompt(input?: {
|
|
2159
|
+
root?: string;
|
|
2160
|
+
}): Promise<OpResult<{
|
|
2161
|
+
text: string | null;
|
|
2162
|
+
selection: StatusReport['selection'];
|
|
2163
|
+
}>>;
|
|
1971
2164
|
stats(input?: {
|
|
1972
2165
|
root?: string;
|
|
1973
2166
|
}): Promise<{
|
|
@@ -1989,31 +2182,97 @@ declare class EngineService {
|
|
|
1989
2182
|
targetChapters: number | null;
|
|
1990
2183
|
}>;
|
|
1991
2184
|
private registry;
|
|
1992
|
-
/** List known projects
|
|
2185
|
+
/** List known projects with a cheap directory state for the panel/command. */
|
|
1993
2186
|
listProjects(): Promise<{
|
|
1994
2187
|
active: string | null;
|
|
1995
|
-
projects: RegistryEntry
|
|
2188
|
+
projects: Array<RegistryEntry & {
|
|
2189
|
+
state: ProjectState;
|
|
2190
|
+
identity_changed?: boolean;
|
|
2191
|
+
}>;
|
|
1996
2192
|
}>;
|
|
1997
|
-
/**
|
|
2193
|
+
/**
|
|
2194
|
+
* Record an explicit project row. An unchanged duplicate is a no-op; a path
|
|
2195
|
+
* reused by another project updates the row and reports `replaced`.
|
|
2196
|
+
*/
|
|
1998
2197
|
registerProject(input?: {
|
|
1999
2198
|
root?: string;
|
|
2000
2199
|
}): Promise<{
|
|
2001
2200
|
active: string | null;
|
|
2002
2201
|
projects: RegistryEntry[];
|
|
2202
|
+
replaced: boolean;
|
|
2003
2203
|
}>;
|
|
2004
|
-
/** Choose the default project
|
|
2204
|
+
/** Choose the panel/default project. This never binds the current session. */
|
|
2005
2205
|
setActiveProject(input: {
|
|
2006
2206
|
root: string;
|
|
2007
2207
|
}): Promise<{
|
|
2008
2208
|
active: string | null;
|
|
2209
|
+
replaced: boolean;
|
|
2009
2210
|
}>;
|
|
2010
|
-
/** Forget a registry row; the project directory
|
|
2211
|
+
/** Forget a registry row; the project directory and bindings are never touched. */
|
|
2011
2212
|
forgetProject(input: {
|
|
2012
2213
|
root: string;
|
|
2013
2214
|
}): Promise<{
|
|
2014
2215
|
active: string | null;
|
|
2015
2216
|
projects: RegistryEntry[];
|
|
2016
2217
|
}>;
|
|
2218
|
+
/**
|
|
2219
|
+
* Remove only registry rows whose directories are missing, not a project, or
|
|
2220
|
+
* unreadable. The default is a dry run; project files and session bindings are
|
|
2221
|
+
* never touched, and `--yes` is required at the command layer.
|
|
2222
|
+
*/
|
|
2223
|
+
pruneProjects(input?: {
|
|
2224
|
+
apply?: boolean;
|
|
2225
|
+
}): Promise<{
|
|
2226
|
+
candidates: Array<{
|
|
2227
|
+
root: string;
|
|
2228
|
+
title: string;
|
|
2229
|
+
state: ProjectState;
|
|
2230
|
+
}>;
|
|
2231
|
+
removed: string[];
|
|
2232
|
+
active: string | null;
|
|
2233
|
+
}>;
|
|
2234
|
+
/**
|
|
2235
|
+
* Bounded workspace scan. Normal mode is read-only; `register` updates only
|
|
2236
|
+
* healthy, newly discovered rows, never active or session bindings.
|
|
2237
|
+
*/
|
|
2238
|
+
scanProjects(input: {
|
|
2239
|
+
cwd: string;
|
|
2240
|
+
register?: boolean;
|
|
2241
|
+
}): Promise<{
|
|
2242
|
+
cwd: string;
|
|
2243
|
+
candidates: Array<ProjectInspection & {
|
|
2244
|
+
registered: boolean;
|
|
2245
|
+
identity_changed?: boolean;
|
|
2246
|
+
reason?: string;
|
|
2247
|
+
}>;
|
|
2248
|
+
truncated: boolean;
|
|
2249
|
+
added: string[];
|
|
2250
|
+
already: string[];
|
|
2251
|
+
skipped: Array<{
|
|
2252
|
+
root: string;
|
|
2253
|
+
reason: string;
|
|
2254
|
+
}>;
|
|
2255
|
+
identity_changed: string[];
|
|
2256
|
+
}>;
|
|
2257
|
+
/** Current session binding, or the inferred fallback when none is set. */
|
|
2258
|
+
currentProject(): Promise<{
|
|
2259
|
+
selection: Selection | null;
|
|
2260
|
+
bound: boolean;
|
|
2261
|
+
state?: ProjectState;
|
|
2262
|
+
error?: string;
|
|
2263
|
+
}>;
|
|
2264
|
+
/** Explicitly switch this session; failure leaves the old binding untouched. */
|
|
2265
|
+
useProject(input: {
|
|
2266
|
+
target: string;
|
|
2267
|
+
}): Promise<{
|
|
2268
|
+
selection: Selection;
|
|
2269
|
+
title: string;
|
|
2270
|
+
created_at: string;
|
|
2271
|
+
}>;
|
|
2272
|
+
/** Clear only this session's choice; never touches a project or registry row. */
|
|
2273
|
+
unbindProject(): Promise<{
|
|
2274
|
+
cleared: boolean;
|
|
2275
|
+
}>;
|
|
2017
2276
|
/**
|
|
2018
2277
|
* Import one ledger from a settings pack. Always previews with a diff; a
|
|
2019
2278
|
* dry run never writes, and an apply is a normal transaction.
|
|
@@ -2071,10 +2330,10 @@ declare class EngineService {
|
|
|
2071
2330
|
private bookStatus;
|
|
2072
2331
|
private panelSnapshot;
|
|
2073
2332
|
/**
|
|
2074
|
-
* The archive stage
|
|
2075
|
-
*
|
|
2076
|
-
*
|
|
2077
|
-
*
|
|
2333
|
+
* The archive stage can be left by a direct revision (the 0.2.3 workflow) or
|
|
2334
|
+
* by rollback. Evaluate the same gates as archive so status/panel do not
|
|
2335
|
+
* recommend an operation that will immediately fail; when the failure is
|
|
2336
|
+
* prose-level, `nextStep` recommends the direct P5 revision instead.
|
|
2078
2337
|
*/
|
|
2079
2338
|
private archivePreflight;
|
|
2080
2339
|
private nextStep;
|
|
@@ -2100,6 +2359,7 @@ declare class EngineService {
|
|
|
2100
2359
|
private stateGateBlock;
|
|
2101
2360
|
/** Whether the stored brief still signs the current snapshot. */
|
|
2102
2361
|
private readBriefReceipts;
|
|
2362
|
+
private assertBriefReceiptsWritable;
|
|
2103
2363
|
private briefIsCurrent;
|
|
2104
2364
|
/** Arguments valid for the tool `STAGE_NEXT` recommends at this stage. */
|
|
2105
2365
|
private nextArgs;
|
|
@@ -2132,11 +2392,13 @@ declare class EngineService {
|
|
|
2132
2392
|
private assertGates;
|
|
2133
2393
|
private assertChapterParameter;
|
|
2134
2394
|
private assertChapter;
|
|
2135
|
-
/** True when anything survives in the project directory besides novel.yaml. */
|
|
2136
|
-
private projectStateExists;
|
|
2137
2395
|
/** A live writer lock makes a read-only snapshot potentially torn. */
|
|
2138
2396
|
private lockIsLive;
|
|
2397
|
+
/** Resolve a selection, load it, then persist the explicit choice (best effort). */
|
|
2139
2398
|
private load;
|
|
2399
|
+
/** Load exactly one already-resolved selection; never writes a binding. */
|
|
2400
|
+
private movedProjectHint;
|
|
2401
|
+
private loadAt;
|
|
2140
2402
|
/** A repair may bypass the journal hash only when the document is unreadable. */
|
|
2141
2403
|
private stateDocIsUnreadable;
|
|
2142
2404
|
/** Read a review/check without letting one corrupt file wedge every read. */
|
|
@@ -2147,6 +2409,100 @@ declare class EngineService {
|
|
|
2147
2409
|
}
|
|
2148
2410
|
/** Read, compile and freeze a pack. Runtime callers always use the bundled default. */
|
|
2149
2411
|
declare function loadRulepack(path?: string): Rulepack;
|
|
2412
|
+
/** Panel and session identifiers. */
|
|
2413
|
+
declare const PLUGIN_NAME = "dsh-novel-write-engine";
|
|
2414
|
+
declare const PANEL_ID = "novel-workshop";
|
|
2415
|
+
declare const PANEL_ROUTE = "/api/novel-write-engine/panel";
|
|
2416
|
+
declare const SKILL_NAME = "novel-write-engine";
|
|
2417
|
+
declare const REMOTE_VERSION = 5;
|
|
2418
|
+
/** The panel is a recent-history view; the wire payload and UI use one cap. */
|
|
2419
|
+
declare const PANEL_CHAPTER_LIMIT = 30;
|
|
2420
|
+
/** Project-relative locations. Every write goes through these constants. */
|
|
2421
|
+
declare const PROJECT_FILE = "novel.yaml";
|
|
2422
|
+
declare const OUTLINE_FILE = "outline/outline.yaml";
|
|
2423
|
+
declare const WORLDBOOK_FILE = "outline/worldbook.yaml";
|
|
2424
|
+
declare const STATE_DIR = "state";
|
|
2425
|
+
declare const CHAPTERS_DIR = "chapters";
|
|
2426
|
+
declare const PLAN_DIR = "plans";
|
|
2427
|
+
declare const REVIEW_DIR = "reviews";
|
|
2428
|
+
declare const CHECK_DIR = "checks";
|
|
2429
|
+
declare const EXPORT_DIR = "exports";
|
|
2430
|
+
declare const BACKUP_DIR = "backups";
|
|
2431
|
+
declare const HISTORY_DIR = "history";
|
|
2432
|
+
/** Brief receipts are append-only evidence, separate from content transactions. */
|
|
2433
|
+
declare const BRIEF_RECEIPTS_FILE = "state/briefs.yaml";
|
|
2434
|
+
declare const OUTLINE_DIR = "outline";
|
|
2435
|
+
declare const LOCK_FILE = ".engine.lock";
|
|
2436
|
+
declare const STAGING_DIR = ".staging";
|
|
2437
|
+
declare const REGISTRY_FILE = "projects.yaml";
|
|
2438
|
+
declare const SESSION_BINDINGS_FILE = "session-bindings.yaml";
|
|
2439
|
+
declare const METADATA_LOCK_FILE = ".metadata.lock";
|
|
2440
|
+
declare const ARCHIVE_DIGESTS_FILE = "state/archive-digests.json";
|
|
2441
|
+
/** Files owned by the engine under `state/`. */
|
|
2442
|
+
declare const STATE_FILES: {
|
|
2443
|
+
readonly pipeline: "pipeline.yaml";
|
|
2444
|
+
readonly chapters: "chapters.yaml";
|
|
2445
|
+
readonly characters: "characters.yaml";
|
|
2446
|
+
readonly world: "world.yaml";
|
|
2447
|
+
readonly locks: "locks.yaml";
|
|
2448
|
+
readonly timeline: "timeline.yaml";
|
|
2449
|
+
readonly foreshadows: "foreshadows.yaml";
|
|
2450
|
+
readonly relationships: "relationships.yaml";
|
|
2451
|
+
readonly handoff: "handoff.yaml";
|
|
2452
|
+
readonly journal: "journal.jsonl";
|
|
2453
|
+
};
|
|
2454
|
+
/** Chapter file name, zero padded to three digits. */
|
|
2455
|
+
declare const chapterFile: (chapter: number) => string;
|
|
2456
|
+
/** Kept for reference when a rollback discards the current draft. */
|
|
2457
|
+
declare const deprecatedChapterFile: (chapter: number) => string;
|
|
2458
|
+
declare const planWorldFile: (chapter: number) => string;
|
|
2459
|
+
declare const planChapterFile: (chapter: number) => string;
|
|
2460
|
+
declare const reviewFile: (chapter: number) => string;
|
|
2461
|
+
declare const checkFile: (chapter: number) => string;
|
|
2462
|
+
declare const reviewHistoryFile: (chapter: number, revision: number) => string;
|
|
2463
|
+
declare const checkHistoryFile: (chapter: number, revision: number) => string;
|
|
2464
|
+
declare const chapterHistoryFile: (chapter: number, revision: number) => string;
|
|
2465
|
+
declare const deprecatedHistoryFile: (chapter: number, revision: number) => string;
|
|
2466
|
+
declare const planHistoryFile: (chapter: number, revision: number) => string;
|
|
2467
|
+
declare const HISTORY_KINDS: readonly ["reviews", "checks", "chapters", "deprecated", "plans"];
|
|
2468
|
+
type HistoryKind = (typeof HISTORY_KINDS)[number];
|
|
2469
|
+
/** Limits that are structural, not taste. */
|
|
2470
|
+
declare const LIMITS: {
|
|
2471
|
+
/** P4 <-> P5/P6 retries before a forced rollback. */
|
|
2472
|
+
maxRounds: number;
|
|
2473
|
+
/** Lock staleness in milliseconds. */
|
|
2474
|
+
lockStaleMs: number;
|
|
2475
|
+
/** How long a writer waits for the keyed mutex before failing. */
|
|
2476
|
+
lockWaitMs: number;
|
|
2477
|
+
/** Reading proofs shorter than this cannot be verified. */
|
|
2478
|
+
minQuoteChars: number;
|
|
2479
|
+
/** World-plan text fields are protected context, so they need a hard bound. */
|
|
2480
|
+
maxWorldPlanItems: number;
|
|
2481
|
+
maxWorldPlanTextChars: number;
|
|
2482
|
+
maxWorldPlanObjectiveChars: number;
|
|
2483
|
+
/** Cast plus summary may exceed eight, but not without a bound. */
|
|
2484
|
+
maxActiveCast: number;
|
|
2485
|
+
/** Outline and worldbook are protected context, so they need hard bounds. */
|
|
2486
|
+
maxOutlineChapters: number;
|
|
2487
|
+
maxOutlineVolumes: number;
|
|
2488
|
+
maxOutlineTextFieldChars: number;
|
|
2489
|
+
maxOutlineNotesChars: number;
|
|
2490
|
+
maxWorldbookEntries: number;
|
|
2491
|
+
maxWorldbookTextChars: number;
|
|
2492
|
+
maxSearchQueryChars: number;
|
|
2493
|
+
};
|
|
2494
|
+
/** Re-exported enums make adapter code readable without importing types twice. */
|
|
2495
|
+
declare const SCENE_TYPE_DEFAULT: SceneType;
|
|
2496
|
+
declare const DEFAULT_GENRE: Genre;
|
|
2497
|
+
declare const DEFAULT_PLATFORM: Platform;
|
|
2498
|
+
declare const INITIAL_STAGE: Stage;
|
|
2499
|
+
/** The order used to render the nine-phase progress strip. */
|
|
2500
|
+
declare const PHASE_STRIP: readonly ["P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9"];
|
|
2501
|
+
/** Tool names, kept here so the arch test can assert one namespace. */
|
|
2502
|
+
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"];
|
|
2503
|
+
type ToolName = (typeof TOOL_NAMES)[number];
|
|
2504
|
+
/** The ten high-frequency tools kept when `tools.mode = core`. */
|
|
2505
|
+
declare const CORE_TOOLS: readonly ToolName[];
|
|
2150
2506
|
/** One rendered chapter, assembled by the engine before rendering. */
|
|
2151
2507
|
interface ExportChapter {
|
|
2152
2508
|
num: number;
|
|
@@ -2189,4 +2545,4 @@ declare const Config: Schema<Config>;
|
|
|
2189
2545
|
* created lazily per project root.
|
|
2190
2546
|
*/
|
|
2191
2547
|
declare function apply(ctx: Context, config: Config): void;
|
|
2192
|
-
export { AdviceReport, ArchiveHandoff, AuditRow, BlockingItem, BookPlan, BookReport, BriefDocument, BriefLibrary, BriefReceipt, BriefReceiptsDocument, BriefStage, ChapterCastMember, ChapterPlanInput, ChapterRecord, ChapterStatusRow, ChapterSummary, ChaptersDocument, CharacterDelta, CharactersDocument, CheckDocument, Config, Deduction, DeltaAction, DiffReport, DoctorCheck, DoctorReport, DraftInput, DraftState, ERROR_CODES, EngineBlockedError, EngineError, EngineFaultError, EngineInputError, EngineService, ErrorCode, ExportChapter, ExportKind, ForeshadowDelta, ForeshadowsDocument, GENRES, GateInput, GateOptions, GateResult, Genre, GuideReport, GuideStep, HandoffDocument, LocksDocument, MachineMetrics, NovelProject, OPERATIONS, OpResult, Operation, OutlineChapter, OutlineDocument, OutlineProgress, OutlineVolume, PLATFORMS, PanelBook, PanelChapterRow, PanelChaptersDto, PanelDraft, PanelGatesDto, PanelSnapshot, PanelSummaryDto, PipelineState, Platform, ReadingProof, ReadingProofReference, RelationshipDelta, RelationshipsDocument, ReviewDocument, ReviewInput, ReviewIssue, RevisionEdit, RevisionInput, RevisionPatch, RoundCounters, SCENE_TYPES, SCHEMA_VERSION, SceneType, ScoreDimension, SearchReport, SearchResultItem, SemanticItem, Severity, Stage, StateDelta, StateError, StateErrorCode, StatusReport, TimelineDelta, TimelineDocument, Violation, Warning, WordMetrics, WorldDelta, WorldDocument, WorldPlanInput, WorldbookBackstory, WorldbookCharacter, WorldbookDocument, WorldbookFact, WorldbookFaction, WorldbookGlossary, WorldbookLocation, WorldbookRule, applicableGates, apply, blockedError, briefStageFor, chapterHeading, evaluateGates, faultError, gateName, inject, inputError, loadRulepack, name, parseParagraphLocation, phaseStrip, projectChapter, projectChapters, projectGates, projectSummary, renderBlurb, renderCover, renderEpubChapter, renderMarkdown, renderPlainText, renderProposal, verifyReference };
|
|
2548
|
+
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_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 };
|