dsh-novel-write-engine 0.2.4 → 0.2.6
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 +51 -0
- package/README.md +25 -18
- package/briefs/P3.md +2 -0
- package/briefs/P5.md +2 -0
- package/briefs/P6.md +3 -2
- package/briefs/P8.md +5 -4
- package/lib/client.js +148 -16
- package/lib/index.d.ts +244 -4
- package/lib/index.js +1608 -311
- package/lib/types/client/dto.d.ts +19 -0
- package/lib/types/client/viewmodel.d.ts +30 -1
- package/lib/types/constants.d.ts +1 -1
- package/lib/types/panel-contract.d.ts +125 -0
- package/lib/types/types.d.ts +29 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -68,6 +68,9 @@ declare const ERROR_CODES: {
|
|
|
68
68
|
/** The exact same keyed submission already failed in the same context. */
|
|
69
69
|
readonly RETRY_UNCHANGED: "ENGINE_RETRY_UNCHANGED";
|
|
70
70
|
readonly GATE_BLOCKED: "ENGINE_GATE_BLOCKED";
|
|
71
|
+
readonly CHECK_SUBMISSION_INVALID: "ENGINE_CHECK_SUBMISSION_INVALID";
|
|
72
|
+
readonly PENDING_PARTIAL: "ENGINE_PENDING_PARTIAL";
|
|
73
|
+
readonly IO_PERMISSION: "ENGINE_IO_PERMISSION";
|
|
71
74
|
readonly READING_PROOF_INVALID: "ENGINE_READING_PROOF_INVALID";
|
|
72
75
|
readonly SCORE_MISMATCH: "ENGINE_SCORE_MISMATCH";
|
|
73
76
|
/** A revision tried to rewrite reviewer-owned issue fields. */
|
|
@@ -178,13 +181,18 @@ interface CheckDocument {
|
|
|
178
181
|
evidence: string;
|
|
179
182
|
note: string;
|
|
180
183
|
}>;
|
|
184
|
+
/** 0.2.5: explain a persisted content failure; historical checks omit it. */
|
|
185
|
+
findings?: BlockingItem[];
|
|
181
186
|
};
|
|
182
187
|
/** Advisory codes the author has explicitly acknowledged for this content. */
|
|
183
188
|
acknowledged?: string[];
|
|
189
|
+
/** 0.2.5: content failures consume the check budget; submission errors never persist. */
|
|
190
|
+
failure_class?: 'submission' | 'content';
|
|
191
|
+
counted?: boolean;
|
|
184
192
|
verdict: 'pass' | 'fail';
|
|
185
193
|
}
|
|
186
194
|
/** Every persisted document whose damage status/panel can report. */
|
|
187
|
-
type StateErrorCode = 'PROJECT_UNREADABLE' | 'PLAN_UNREADABLE' | 'WORLD_PLAN_UNREADABLE' | 'REVIEW_UNREADABLE' | 'CHECK_UNREADABLE' | 'CHAPTERS_UNREADABLE' | 'CHARACTERS_UNREADABLE' | 'WORLD_UNREADABLE' | 'LOCKS_UNREADABLE' | 'TIMELINE_UNREADABLE' | 'FORESHADOWS_UNREADABLE' | 'RELATIONSHIPS_UNREADABLE' | 'HANDOFF_UNREADABLE' | 'OUTLINE_UNREADABLE' | 'WORLDBOOK_UNREADABLE';
|
|
195
|
+
type StateErrorCode = 'PROJECT_UNREADABLE' | 'PIPELINE_UNREADABLE' | 'PLAN_UNREADABLE' | 'WORLD_PLAN_UNREADABLE' | 'REVIEW_UNREADABLE' | 'CHECK_UNREADABLE' | 'CHAPTERS_UNREADABLE' | 'CHARACTERS_UNREADABLE' | 'WORLD_UNREADABLE' | 'LOCKS_UNREADABLE' | 'TIMELINE_UNREADABLE' | 'FORESHADOWS_UNREADABLE' | 'RELATIONSHIPS_UNREADABLE' | 'HANDOFF_UNREADABLE' | 'OUTLINE_UNREADABLE' | 'WORLDBOOK_UNREADABLE';
|
|
188
196
|
/** A state document that exists but cannot be read safely. */
|
|
189
197
|
interface StateError {
|
|
190
198
|
path: string;
|
|
@@ -255,6 +263,12 @@ interface ChapterSummary {
|
|
|
255
263
|
abilities: string[];
|
|
256
264
|
artifacts: string[];
|
|
257
265
|
};
|
|
266
|
+
/** Optional P3/P5 verbatim manuscript anchors for readable entity names. */
|
|
267
|
+
new_element_anchors?: {
|
|
268
|
+
locations?: Record<string, string[]>;
|
|
269
|
+
abilities?: Record<string, string[]>;
|
|
270
|
+
artifacts?: Record<string, string[]>;
|
|
271
|
+
};
|
|
258
272
|
resource_changes: Array<{
|
|
259
273
|
character: string;
|
|
260
274
|
resource: string;
|
|
@@ -423,6 +437,8 @@ interface WorldDocument {
|
|
|
423
437
|
schema_version: 1;
|
|
424
438
|
locations: Array<{
|
|
425
439
|
name: string;
|
|
440
|
+
/** 0.2.6 additive: readable-name anchors; old ledgers omit this. */
|
|
441
|
+
anchors?: string[];
|
|
426
442
|
first_appearance: number;
|
|
427
443
|
locked: boolean;
|
|
428
444
|
description: string;
|
|
@@ -785,6 +801,12 @@ interface BookReport {
|
|
|
785
801
|
glossary: number;
|
|
786
802
|
backstory: number;
|
|
787
803
|
facts?: number;
|
|
804
|
+
/** 0.2.6 persisted world-ledger anchors, capped for report payloads. */
|
|
805
|
+
anchors?: Array<{
|
|
806
|
+
name: string;
|
|
807
|
+
kind: string;
|
|
808
|
+
anchors: string[];
|
|
809
|
+
}>;
|
|
788
810
|
};
|
|
789
811
|
quality: {
|
|
790
812
|
average: number;
|
|
@@ -953,6 +975,10 @@ interface GateInput {
|
|
|
953
975
|
summary: ChapterSummary | null;
|
|
954
976
|
/** P5 may omit `summary`; when omitted, the previous plan summary is reused. */
|
|
955
977
|
summaryProvided?: boolean;
|
|
978
|
+
/** Summary-only repair: no manuscript change, no P4/P6 proof requirement. */
|
|
979
|
+
summaryOnly?: boolean;
|
|
980
|
+
/** The last write was a summary-only repair; P6 may continue without a new brief. */
|
|
981
|
+
summaryOnlyRevision?: boolean;
|
|
956
982
|
review: ReviewDocument | null;
|
|
957
983
|
check: CheckDocument | null;
|
|
958
984
|
/** When set, result-bearing gates run only the named check scopes. */
|
|
@@ -1030,6 +1056,8 @@ interface StatusReport {
|
|
|
1030
1056
|
stage: Stage;
|
|
1031
1057
|
rounds: RoundCounters;
|
|
1032
1058
|
blocking: BlockingItem[];
|
|
1059
|
+
/** Non-blocking recovery notes, e.g. a recoverable pending transaction. */
|
|
1060
|
+
warnings?: Warning[];
|
|
1033
1061
|
/** plan/review/check/ledger files that exist but cannot be read safely. */
|
|
1034
1062
|
state_errors: StateError[];
|
|
1035
1063
|
metrics: WordMetrics | null;
|
|
@@ -1122,6 +1150,39 @@ interface DiffReport {
|
|
|
1122
1150
|
}
|
|
1123
1151
|
/** Export capabilities; the last three are book-planning deliverables. */
|
|
1124
1152
|
type ExportKind = 'md' | 'txt' | 'epub' | 'outline' | 'worldbook' | 'proposal';
|
|
1153
|
+
type SemanticItemState = 'pass' | 'fail' | 'missing' | 'invalid' | 'not_found' | 'too_short' | 'duplicate' | 'overlap' | 'same_sentence' | 'boundary';
|
|
1154
|
+
type SemanticConflictKind = 'duplicate' | 'same_sentence' | 'interval_overlap';
|
|
1155
|
+
interface SemanticConflict {
|
|
1156
|
+
kind: SemanticConflictKind;
|
|
1157
|
+
other_id: string;
|
|
1158
|
+
/** Only for interval_overlap; a verbatim excerpt, capped at 120 characters. */
|
|
1159
|
+
overlap_text?: string;
|
|
1160
|
+
overlap_chars?: number;
|
|
1161
|
+
/** overlap_chars / min(quoteA, quoteB), 0..1. */
|
|
1162
|
+
overlap_ratio?: number;
|
|
1163
|
+
paragraphs?: number[];
|
|
1164
|
+
/** Only for same_sentence. */
|
|
1165
|
+
sentence?: {
|
|
1166
|
+
id: number;
|
|
1167
|
+
text: string;
|
|
1168
|
+
paragraph: number;
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
interface SemanticNearest {
|
|
1172
|
+
paragraph: number;
|
|
1173
|
+
quote: string;
|
|
1174
|
+
score: number;
|
|
1175
|
+
}
|
|
1176
|
+
interface SemanticItemResult {
|
|
1177
|
+
id: string;
|
|
1178
|
+
state: SemanticItemState;
|
|
1179
|
+
quote?: string;
|
|
1180
|
+
detail?: string;
|
|
1181
|
+
nearest?: SemanticNearest;
|
|
1182
|
+
/** Kept for older adapters; the full pair is in `conflicts`. */
|
|
1183
|
+
conflict_with?: string;
|
|
1184
|
+
conflicts?: SemanticConflict[];
|
|
1185
|
+
}
|
|
1125
1186
|
/** One blacklisted word. */
|
|
1126
1187
|
interface TermEntry {
|
|
1127
1188
|
term: string;
|
|
@@ -1376,6 +1437,130 @@ declare function applicableGates(input: GateInput): GateId[];
|
|
|
1376
1437
|
declare function gateName(id: GateId): string;
|
|
1377
1438
|
/** Which brief stage an operation requires; `null` means no brief gate. */
|
|
1378
1439
|
declare function briefStageFor(operation: GateInput['operation'], stage: Stage): GateInput['briefStage'];
|
|
1440
|
+
/** v6 read-only book data. All windows are explicit in the field names. */
|
|
1441
|
+
interface PanelCardData {
|
|
1442
|
+
num: number;
|
|
1443
|
+
title: string;
|
|
1444
|
+
scene_type: string;
|
|
1445
|
+
goal: string;
|
|
1446
|
+
conflict: string;
|
|
1447
|
+
hook: string;
|
|
1448
|
+
cast: string[];
|
|
1449
|
+
target_words: [number, number];
|
|
1450
|
+
status: 'planned' | 'archived';
|
|
1451
|
+
}
|
|
1452
|
+
interface PanelWorldEntry {
|
|
1453
|
+
name: string;
|
|
1454
|
+
description: string;
|
|
1455
|
+
anchors?: string[];
|
|
1456
|
+
}
|
|
1457
|
+
interface PanelBookData {
|
|
1458
|
+
identity: {
|
|
1459
|
+
author: string;
|
|
1460
|
+
description: string;
|
|
1461
|
+
created_at: string;
|
|
1462
|
+
targets: {
|
|
1463
|
+
words_per_chapter: [number, number];
|
|
1464
|
+
total_chapters: number | null;
|
|
1465
|
+
dialogue_ratio: [number, number];
|
|
1466
|
+
};
|
|
1467
|
+
};
|
|
1468
|
+
blueprint: {
|
|
1469
|
+
premise: string;
|
|
1470
|
+
logline: string;
|
|
1471
|
+
themes: string[];
|
|
1472
|
+
tone: string;
|
|
1473
|
+
pov: string;
|
|
1474
|
+
audience: string;
|
|
1475
|
+
selling_points: string[];
|
|
1476
|
+
ending: string;
|
|
1477
|
+
};
|
|
1478
|
+
progress: {
|
|
1479
|
+
archived: number;
|
|
1480
|
+
target: number | null;
|
|
1481
|
+
words_archived: number;
|
|
1482
|
+
words_with_draft: number;
|
|
1483
|
+
average_words: number;
|
|
1484
|
+
remaining_words: number | null;
|
|
1485
|
+
remaining_words_basis: 'actual_average' | 'minimum_target' | 'none';
|
|
1486
|
+
percent: number;
|
|
1487
|
+
};
|
|
1488
|
+
current: {
|
|
1489
|
+
card: PanelCardData | null;
|
|
1490
|
+
chapter: number;
|
|
1491
|
+
stage: Stage;
|
|
1492
|
+
rounds: {
|
|
1493
|
+
review: number;
|
|
1494
|
+
revise: number;
|
|
1495
|
+
check: number;
|
|
1496
|
+
};
|
|
1497
|
+
manuscript_hash: string | null;
|
|
1498
|
+
metrics: WordMetrics | null;
|
|
1499
|
+
};
|
|
1500
|
+
worldbook: {
|
|
1501
|
+
counts: Omit<BookReport['worldbook'], 'anchors'>;
|
|
1502
|
+
locations: PanelWorldEntry[];
|
|
1503
|
+
factions: PanelWorldEntry[];
|
|
1504
|
+
rules: PanelWorldEntry[];
|
|
1505
|
+
facts: Array<{
|
|
1506
|
+
alias: string;
|
|
1507
|
+
value: number;
|
|
1508
|
+
unit: string;
|
|
1509
|
+
}>;
|
|
1510
|
+
};
|
|
1511
|
+
cast: {
|
|
1512
|
+
total: number;
|
|
1513
|
+
top: Array<{
|
|
1514
|
+
name: string;
|
|
1515
|
+
role: string;
|
|
1516
|
+
appearances: number;
|
|
1517
|
+
last_seen: number;
|
|
1518
|
+
}>;
|
|
1519
|
+
};
|
|
1520
|
+
relationships: {
|
|
1521
|
+
total: number;
|
|
1522
|
+
types: Record<string, number>;
|
|
1523
|
+
};
|
|
1524
|
+
foreshadows: BookReport['foreshadows'];
|
|
1525
|
+
timeline: BookReport['timeline'];
|
|
1526
|
+
outline: {
|
|
1527
|
+
drift: BookReport['outline']['drift'];
|
|
1528
|
+
};
|
|
1529
|
+
quality: {
|
|
1530
|
+
average: number;
|
|
1531
|
+
median: number;
|
|
1532
|
+
min: number;
|
|
1533
|
+
max: number;
|
|
1534
|
+
last_ten_average: number;
|
|
1535
|
+
trend: number | null;
|
|
1536
|
+
trend_basis: BookReport['quality']['trend_basis'];
|
|
1537
|
+
samples: number;
|
|
1538
|
+
attempts: number;
|
|
1539
|
+
dimensions: BookReport['quality']['dimensions'];
|
|
1540
|
+
};
|
|
1541
|
+
pacing: BookReport['pacing'];
|
|
1542
|
+
effort: BookReport['effort'];
|
|
1543
|
+
health: {
|
|
1544
|
+
state_errors: Array<{
|
|
1545
|
+
path: string;
|
|
1546
|
+
code: string;
|
|
1547
|
+
message: string;
|
|
1548
|
+
}>;
|
|
1549
|
+
outline: {
|
|
1550
|
+
present: boolean;
|
|
1551
|
+
error: string | null;
|
|
1552
|
+
};
|
|
1553
|
+
worldbook: {
|
|
1554
|
+
present: boolean;
|
|
1555
|
+
error: string | null;
|
|
1556
|
+
};
|
|
1557
|
+
pending: {
|
|
1558
|
+
state: string;
|
|
1559
|
+
txid: string;
|
|
1560
|
+
detail: string;
|
|
1561
|
+
} | null;
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1379
1564
|
/** The shared read model: everything the panel, status and commands render. */
|
|
1380
1565
|
interface PanelDraft {
|
|
1381
1566
|
num: number;
|
|
@@ -1434,6 +1619,7 @@ interface PanelSnapshot {
|
|
|
1434
1619
|
ok: boolean;
|
|
1435
1620
|
blocking: number;
|
|
1436
1621
|
stateErrors: number;
|
|
1622
|
+
pending?: boolean;
|
|
1437
1623
|
};
|
|
1438
1624
|
activity?: Array<{
|
|
1439
1625
|
at: string;
|
|
@@ -1454,6 +1640,14 @@ interface PanelSnapshot {
|
|
|
1454
1640
|
code: string;
|
|
1455
1641
|
detail: string;
|
|
1456
1642
|
}>;
|
|
1643
|
+
/** Crash-left pending transaction; complete/untouched are warnings. */
|
|
1644
|
+
pending?: {
|
|
1645
|
+
state: string;
|
|
1646
|
+
txid: string;
|
|
1647
|
+
detail: string;
|
|
1648
|
+
};
|
|
1649
|
+
/** v6 read-only book data; v5 payloads omit it. */
|
|
1650
|
+
bookData?: PanelBookData;
|
|
1457
1651
|
}
|
|
1458
1652
|
interface PanelBook {
|
|
1459
1653
|
premise: string;
|
|
@@ -1535,6 +1729,7 @@ interface PanelSummaryDto {
|
|
|
1535
1729
|
ok: boolean;
|
|
1536
1730
|
blocking: number;
|
|
1537
1731
|
stateErrors: number;
|
|
1732
|
+
pending?: boolean;
|
|
1538
1733
|
};
|
|
1539
1734
|
activity?: Array<{
|
|
1540
1735
|
at: string;
|
|
@@ -1555,6 +1750,14 @@ interface PanelSummaryDto {
|
|
|
1555
1750
|
code: string;
|
|
1556
1751
|
detail: string;
|
|
1557
1752
|
}>;
|
|
1753
|
+
/** Crash-left pending transaction; complete/untouched are warnings. */
|
|
1754
|
+
pending?: {
|
|
1755
|
+
state: string;
|
|
1756
|
+
txid: string;
|
|
1757
|
+
detail: string;
|
|
1758
|
+
};
|
|
1759
|
+
/** v6 read-only book data; v5 payloads omit it. */
|
|
1760
|
+
bookData?: PanelBookData;
|
|
1558
1761
|
}
|
|
1559
1762
|
interface PanelChapterRow {
|
|
1560
1763
|
num: number;
|
|
@@ -1565,6 +1768,15 @@ interface PanelChapterRow {
|
|
|
1565
1768
|
status: 'passed' | 'blocked' | 'draft';
|
|
1566
1769
|
/** One-line summary shown when the row is expanded. */
|
|
1567
1770
|
details: string;
|
|
1771
|
+
sceneType?: string;
|
|
1772
|
+
dialogueRatio?: number;
|
|
1773
|
+
hookStrength?: number;
|
|
1774
|
+
finalCheck?: 'pass' | 'fail' | null;
|
|
1775
|
+
reviews?: number;
|
|
1776
|
+
revisions?: number;
|
|
1777
|
+
checks?: number;
|
|
1778
|
+
rollbacks?: number;
|
|
1779
|
+
archivedAt?: string | null;
|
|
1568
1780
|
}
|
|
1569
1781
|
interface PanelChaptersDto {
|
|
1570
1782
|
schemaVersion: number;
|
|
@@ -1784,8 +1996,8 @@ interface RevisionSubmission extends Omit<RevisionInput, 'summary'> {
|
|
|
1784
1996
|
summary?: ChapterSummary;
|
|
1785
1997
|
/** Updated issue statuses/evidence; the review document is patched in place. */
|
|
1786
1998
|
issues?: ReviewDocument['issues'];
|
|
1787
|
-
/** Proof that the revised text was read;
|
|
1788
|
-
proof
|
|
1999
|
+
/** Proof that the revised text was read; required for content/patch revisions. */
|
|
2000
|
+
proof?: ReadingProof;
|
|
1789
2001
|
root?: string;
|
|
1790
2002
|
}
|
|
1791
2003
|
interface CheckSubmission {
|
|
@@ -1875,6 +2087,7 @@ interface OutlineMutationResult {
|
|
|
1875
2087
|
volumes: number;
|
|
1876
2088
|
added: number[];
|
|
1877
2089
|
updated: number[];
|
|
2090
|
+
reindexed: number[];
|
|
1878
2091
|
removed: number[];
|
|
1879
2092
|
volumes_added: string[];
|
|
1880
2093
|
volumes_updated: string[];
|
|
@@ -1882,6 +2095,7 @@ interface OutlineMutationResult {
|
|
|
1882
2095
|
dry_run?: boolean;
|
|
1883
2096
|
would_add?: number[];
|
|
1884
2097
|
would_update?: number[];
|
|
2098
|
+
would_reindex?: number[];
|
|
1885
2099
|
would_remove?: number[];
|
|
1886
2100
|
}
|
|
1887
2101
|
interface OutlineSubmission extends OutlineInput {
|
|
@@ -1931,8 +2145,12 @@ declare class EngineService {
|
|
|
1931
2145
|
private readonly stores;
|
|
1932
2146
|
private readonly mutex;
|
|
1933
2147
|
private readonly replay;
|
|
2148
|
+
/** Bumped when an export artifact disappeared; makes the replay key miss. */
|
|
2149
|
+
private readonly exportArtifactEpoch;
|
|
1934
2150
|
/** Status, panel and gates ask for the same stage context repeatedly. */
|
|
1935
2151
|
private readonly briefContextCache;
|
|
2152
|
+
/** The 15s panel poll reuses the heavy book projection until revision/damage changes. */
|
|
2153
|
+
private readonly panelCache;
|
|
1936
2154
|
private readonly briefs;
|
|
1937
2155
|
private readonly now;
|
|
1938
2156
|
private readonly metadataMutex;
|
|
@@ -2126,6 +2344,8 @@ declare class EngineService {
|
|
|
2126
2344
|
chapter: number;
|
|
2127
2345
|
stage: Stage;
|
|
2128
2346
|
metrics: WordMetrics;
|
|
2347
|
+
summary_only?: boolean;
|
|
2348
|
+
rounds_consumed?: 0 | 1;
|
|
2129
2349
|
}>>;
|
|
2130
2350
|
runCheck(input: CheckSubmission): Promise<OpResult<{
|
|
2131
2351
|
chapter: number;
|
|
@@ -2136,12 +2356,26 @@ declare class EngineService {
|
|
|
2136
2356
|
acknowledged: string[];
|
|
2137
2357
|
metrics: WordMetrics;
|
|
2138
2358
|
stage: Stage;
|
|
2359
|
+
semantic: {
|
|
2360
|
+
items: SemanticItemResult[];
|
|
2361
|
+
findings: BlockingItem[];
|
|
2362
|
+
};
|
|
2363
|
+
rounds: {
|
|
2364
|
+
check: number;
|
|
2365
|
+
};
|
|
2366
|
+
counted: boolean;
|
|
2139
2367
|
}>>;
|
|
2140
2368
|
archiveChapter(input: ArchiveSubmission): Promise<OpResult<{
|
|
2141
2369
|
chapter: number;
|
|
2142
2370
|
assigned_ids: Record<string, string>;
|
|
2143
2371
|
metrics: WordMetrics;
|
|
2144
2372
|
score: number;
|
|
2373
|
+
delta_warnings?: Warning[];
|
|
2374
|
+
normalized_world?: Record<string, {
|
|
2375
|
+
from: 'created' | 'updated' | 'no_change';
|
|
2376
|
+
to: 'created' | 'updated' | 'no_change';
|
|
2377
|
+
reason: 'existing-created-as-updated' | 'missing-updated-as-created' | 'missing-no-change-as-created';
|
|
2378
|
+
}>;
|
|
2145
2379
|
}>>;
|
|
2146
2380
|
amend(input: AmendSubmission): Promise<OpResult<{
|
|
2147
2381
|
path: string;
|
|
@@ -2320,6 +2554,12 @@ declare class EngineService {
|
|
|
2320
2554
|
* could not read.
|
|
2321
2555
|
*/
|
|
2322
2556
|
private assertPlanningDocumentReadable;
|
|
2557
|
+
/**
|
|
2558
|
+
* `strict_explicit` is an internal provenance bit, not an author choice.
|
|
2559
|
+
* Exposing it lets a caller forge "the author chose strict:false" without
|
|
2560
|
+
* going through the strict option. Stored documents may still contain it.
|
|
2561
|
+
*/
|
|
2562
|
+
private assertPublicBookHasNoStrictExplicit;
|
|
2323
2563
|
/**
|
|
2324
2564
|
* An import is a full replacement, unlike novel_outline's keyed upsert. It
|
|
2325
2565
|
* must not silently lose the active card while strict mode still requires it.
|
|
@@ -2432,7 +2672,7 @@ declare const PLUGIN_NAME = "dsh-novel-write-engine";
|
|
|
2432
2672
|
declare const PANEL_ID = "novel-workshop";
|
|
2433
2673
|
declare const PANEL_ROUTE = "/api/novel-write-engine/panel";
|
|
2434
2674
|
declare const SKILL_NAME = "novel-write-engine";
|
|
2435
|
-
declare const REMOTE_VERSION =
|
|
2675
|
+
declare const REMOTE_VERSION = 6;
|
|
2436
2676
|
/** The panel is a recent-history view; the wire payload and UI use one cap. */
|
|
2437
2677
|
declare const PANEL_CHAPTER_LIMIT = 30;
|
|
2438
2678
|
/** Project-relative locations. Every write goes through these constants. */
|