holonovel 2026.8.22 → 2026.8.24
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/dist/core/anchors.d.ts +1 -0
- package/dist/core/anchors.js +35 -0
- package/dist/core/anchors.js.map +1 -0
- package/dist/core/server.js +4 -0
- package/dist/core/server.js.map +1 -1
- package/dist/core/state.d.ts +160 -3
- package/dist/core/state.js +432 -72
- package/dist/core/state.js.map +1 -1
- package/dist/index.js +2921 -269
- package/dist/index.js.map +1 -1
- package/dist/rulesets.js +4 -0
- package/dist/rulesets.js.map +1 -1
- package/dist/world/parser.js +47 -2
- package/dist/world/parser.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function deriveAnchor(heading: string, explicitId?: string, existing?: Set<string>): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// REQ-194 — deterministic anchor derivation. Anchors are derived from heading
|
|
2
|
+
// text: lowercase, strip `[\p{P}\p{S}]`, collapse whitespace/hyphen runs to a
|
|
3
|
+
// single hyphen, trim leading/trailing hyphens. Explicit `{#id}` takes
|
|
4
|
+
// precedence; role-scoping markers (`*Keeper only*`, `*Player only*`) are
|
|
5
|
+
// stripped before derivation; duplicate anchors within a file append `-1`,
|
|
6
|
+
// `-2`, … per GFM convention. CJK and non-ASCII word characters are preserved.
|
|
7
|
+
// Re-deriving the same source reproduces identical anchors (determinism).
|
|
8
|
+
export function deriveAnchor(heading, explicitId, existing) {
|
|
9
|
+
// Explicit `{#id}` takes precedence over derived anchors (REQ-194a).
|
|
10
|
+
const inlineId = String(heading).match(/\{#([^}]+)\}/)?.[1];
|
|
11
|
+
if (explicitId)
|
|
12
|
+
return explicitId;
|
|
13
|
+
if (inlineId)
|
|
14
|
+
return inlineId;
|
|
15
|
+
let text = heading
|
|
16
|
+
.replace(/\*[^*]+\*/g, "")
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.replace(/[\p{P}\p{S}]/gu, "")
|
|
19
|
+
.replace(/[\s\u00a0]+/g, "-")
|
|
20
|
+
.replace(/-+/g, "-")
|
|
21
|
+
.replace(/^-+|-+$/g, "");
|
|
22
|
+
if (!text)
|
|
23
|
+
text = "section";
|
|
24
|
+
if (existing) {
|
|
25
|
+
if (existing.has(text)) {
|
|
26
|
+
let n = 1;
|
|
27
|
+
while (existing.has(`${text}-${n}`))
|
|
28
|
+
n++;
|
|
29
|
+
text = `${text}-${n}`;
|
|
30
|
+
}
|
|
31
|
+
existing.add(text);
|
|
32
|
+
}
|
|
33
|
+
return text;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=anchors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchors.js","sourceRoot":"","sources":["../../src/core/anchors.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,8EAA8E;AAC9E,uEAAuE;AACvE,0EAA0E;AAC1E,2EAA2E;AAC3E,+EAA+E;AAC/E,0EAA0E;AAE1E,MAAM,UAAU,YAAY,CAC1B,OAAe,EACf,UAAmB,EACnB,QAAsB;IAEtB,qEAAqE;IACrE,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,IAAI,GAAG,OAAO;SACf,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,WAAW,EAAE;SACb,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,IAAI,CAAC,IAAI;QAAE,IAAI,GAAG,SAAS,CAAC;IAC5B,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,CAAC;YACV,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;gBAAE,CAAC,EAAE,CAAC;YACzC,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;QACxB,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/core/server.js
CHANGED
|
@@ -25,6 +25,10 @@ export function novelSnapshot() {
|
|
|
25
25
|
_state.snapshot(novel, getBadge());
|
|
26
26
|
}
|
|
27
27
|
export function withForbiddenAudit(handler, toolName) {
|
|
28
|
+
// REQ-133 — forbidden-call audit: every [FORBIDDEN] is recorded with the
|
|
29
|
+
// active badge, tool name, and arguments, tagged `violation_type: boundary`
|
|
30
|
+
// (see StateManager.auditForbidden) and surfaced with a [BOUNDARY_VIOLATION]
|
|
31
|
+
// marker in compress_audit / audit://novel.
|
|
28
32
|
return async (args, ctx) => {
|
|
29
33
|
try {
|
|
30
34
|
return await handler(args, ctx);
|
package/dist/core/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/core/server.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,gFAAgF;AAUhF,IAAI,MAAoB,CAAC;AAEzB,MAAM,UAAU,UAAU,CAAC,KAAmB;IAC5C,MAAM,GAAG,KAAK,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,MAAM,CAAC,WAAW,EAAE,KAAK,IAAI,MAAM,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,YAAY,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;IACjC,IAAI,KAAK;QAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,OAAoB,EACpB,QAAgB;IAEhB,OAAO,KAAK,EAAE,IAAS,EAAE,GAAY,EAAE,EAAE;QACvC,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBACzC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACnD,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/core/server.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,gFAAgF;AAUhF,IAAI,MAAoB,CAAC;AAEzB,MAAM,UAAU,UAAU,CAAC,KAAmB;IAC5C,MAAM,GAAG,KAAK,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,MAAM,CAAC,WAAW,EAAE,KAAK,IAAI,MAAM,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,YAAY,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;IACjC,IAAI,KAAK;QAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,OAAoB,EACpB,QAAgB;IAEhB,yEAAyE;IACzE,4EAA4E;IAC5E,6EAA6E;IAC7E,4CAA4C;IAC5C,OAAO,KAAK,EAAE,IAAS,EAAE,GAAY,EAAE,EAAE;QACvC,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBACzC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACnD,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/core/state.d.ts
CHANGED
|
@@ -21,6 +21,19 @@ export interface NovelEntity {
|
|
|
21
21
|
conditions: string[];
|
|
22
22
|
condition_rounds: Record<string, number>;
|
|
23
23
|
stats?: Record<string, any>;
|
|
24
|
+
knowledge?: {
|
|
25
|
+
explored?: Array<{
|
|
26
|
+
type: "room" | "thing";
|
|
27
|
+
name: string;
|
|
28
|
+
at: string;
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
codex_source?: {
|
|
32
|
+
id: string;
|
|
33
|
+
kind: string;
|
|
34
|
+
imported_at: string;
|
|
35
|
+
codex_modified_at: string;
|
|
36
|
+
};
|
|
24
37
|
}
|
|
25
38
|
export interface NpcState {
|
|
26
39
|
id: string;
|
|
@@ -28,6 +41,7 @@ export interface NpcState {
|
|
|
28
41
|
description?: string;
|
|
29
42
|
disposition?: string;
|
|
30
43
|
location?: string;
|
|
44
|
+
room_id?: string;
|
|
31
45
|
personality?: {
|
|
32
46
|
description?: string;
|
|
33
47
|
voice?: string;
|
|
@@ -41,6 +55,26 @@ export interface NpcState {
|
|
|
41
55
|
}[];
|
|
42
56
|
conditions: string[];
|
|
43
57
|
condition_rounds: Record<string, number>;
|
|
58
|
+
memory?: {
|
|
59
|
+
witnessed_events: Array<{
|
|
60
|
+
event: string;
|
|
61
|
+
at: string;
|
|
62
|
+
}>;
|
|
63
|
+
contacts: Record<string, {
|
|
64
|
+
encounters: number;
|
|
65
|
+
first_contact: string;
|
|
66
|
+
last_contact: string;
|
|
67
|
+
last_disposition: string;
|
|
68
|
+
prior_dispositions: string[];
|
|
69
|
+
}>;
|
|
70
|
+
stress_markers: string[];
|
|
71
|
+
goals?: string[];
|
|
72
|
+
last_3_interactions: Array<{
|
|
73
|
+
entity: string;
|
|
74
|
+
summary: string;
|
|
75
|
+
at: string;
|
|
76
|
+
}>;
|
|
77
|
+
};
|
|
44
78
|
}
|
|
45
79
|
export interface LoreEntry {
|
|
46
80
|
key: string;
|
|
@@ -52,6 +86,8 @@ export interface LoreEntry {
|
|
|
52
86
|
sticky_remaining: number;
|
|
53
87
|
enabled: boolean;
|
|
54
88
|
group?: string;
|
|
89
|
+
source?: string;
|
|
90
|
+
world_target?: string;
|
|
55
91
|
}
|
|
56
92
|
export interface Countdown {
|
|
57
93
|
name: string;
|
|
@@ -62,6 +98,15 @@ export interface Countdown {
|
|
|
62
98
|
direction?: string;
|
|
63
99
|
clock_type?: "danger" | "racing" | "linked" | "tug_of_war" | "faction" | "mission";
|
|
64
100
|
on_scene_transition?: boolean;
|
|
101
|
+
triggers?: string[];
|
|
102
|
+
world_effect?: {
|
|
103
|
+
type: "describe" | "property" | "exit";
|
|
104
|
+
target: string;
|
|
105
|
+
direction?: string;
|
|
106
|
+
destination?: string;
|
|
107
|
+
property?: string;
|
|
108
|
+
value?: string;
|
|
109
|
+
};
|
|
65
110
|
}
|
|
66
111
|
export interface CombatState {
|
|
67
112
|
participants: string[];
|
|
@@ -92,6 +137,8 @@ export interface StoryEntry {
|
|
|
92
137
|
scene_anchor: string;
|
|
93
138
|
entity_ids: string[];
|
|
94
139
|
timestamp: string;
|
|
140
|
+
discovered?: boolean;
|
|
141
|
+
room_id?: string;
|
|
95
142
|
}
|
|
96
143
|
export interface FactionState {
|
|
97
144
|
id: string;
|
|
@@ -102,6 +149,23 @@ export interface FactionState {
|
|
|
102
149
|
clock: number;
|
|
103
150
|
clock_max: number;
|
|
104
151
|
status: string;
|
|
152
|
+
territory?: string[];
|
|
153
|
+
}
|
|
154
|
+
export interface StoryBeat {
|
|
155
|
+
beat: string;
|
|
156
|
+
scene_preview: string;
|
|
157
|
+
source?: "adventure-scaffold" | "gm";
|
|
158
|
+
codex_source?: {
|
|
159
|
+
id: string;
|
|
160
|
+
kind: string;
|
|
161
|
+
imported_at: string;
|
|
162
|
+
codex_modified_at: string;
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
export interface GoalSuggestion {
|
|
166
|
+
npc_id: string;
|
|
167
|
+
text: string;
|
|
168
|
+
state: "pending" | "deferred" | "dismissed" | "accepted";
|
|
105
169
|
}
|
|
106
170
|
export interface SecretState {
|
|
107
171
|
key: string;
|
|
@@ -109,6 +173,7 @@ export interface SecretState {
|
|
|
109
173
|
triggers: string[];
|
|
110
174
|
badge_scope: "game_master" | "shared";
|
|
111
175
|
known_by: string[];
|
|
176
|
+
world_target?: string;
|
|
112
177
|
}
|
|
113
178
|
export interface Relationship {
|
|
114
179
|
entity_a: string;
|
|
@@ -194,6 +259,10 @@ export interface ConditionState {
|
|
|
194
259
|
conditions: string[];
|
|
195
260
|
condition_rounds: Record<string, number>;
|
|
196
261
|
}
|
|
262
|
+
export interface WorkflowSnapshot {
|
|
263
|
+
timestamp: string;
|
|
264
|
+
state: any;
|
|
265
|
+
}
|
|
197
266
|
export interface AutonomyState {
|
|
198
267
|
level: "full" | "mechanical_prompt" | "manual";
|
|
199
268
|
confirmation: "auto" | "confirm" | "prompt";
|
|
@@ -223,7 +292,9 @@ export interface NovelState {
|
|
|
223
292
|
location?: string;
|
|
224
293
|
time_of_day?: string;
|
|
225
294
|
atmosphere?: string;
|
|
295
|
+
beat?: string;
|
|
226
296
|
}[];
|
|
297
|
+
scene_beat: string;
|
|
227
298
|
scene_type: ("combat" | "social" | "exploration" | "neutral")[];
|
|
228
299
|
narrative_directive: string;
|
|
229
300
|
combat: CombatState | null;
|
|
@@ -244,11 +315,13 @@ export interface NovelState {
|
|
|
244
315
|
adventure_set: boolean;
|
|
245
316
|
pending_workflow: {
|
|
246
317
|
decision: string;
|
|
247
|
-
snapshot:
|
|
318
|
+
snapshot: WorkflowSnapshot | null;
|
|
319
|
+
payload?: any;
|
|
248
320
|
} | {
|
|
249
321
|
decision: string;
|
|
250
|
-
snapshot:
|
|
322
|
+
snapshot: WorkflowSnapshot | null;
|
|
251
323
|
creation?: import("./character-creation.js").CreationWorkflowState;
|
|
324
|
+
payload?: any;
|
|
252
325
|
} | null;
|
|
253
326
|
connection_counter: number;
|
|
254
327
|
pending_staleness_counter: number;
|
|
@@ -270,6 +343,20 @@ export interface NovelState {
|
|
|
270
343
|
}[];
|
|
271
344
|
synthesis_activated: Record<string, number>;
|
|
272
345
|
synthesis_module_enabled: Record<string, boolean>;
|
|
346
|
+
player_synthesis: Record<string, Array<{
|
|
347
|
+
key: string;
|
|
348
|
+
content: string;
|
|
349
|
+
triggers?: string[];
|
|
350
|
+
badge_scope: string;
|
|
351
|
+
created_at: string;
|
|
352
|
+
}>>;
|
|
353
|
+
campaign_memory: Array<{
|
|
354
|
+
category: "npcs" | "threads" | "locations";
|
|
355
|
+
text: string;
|
|
356
|
+
at: string;
|
|
357
|
+
badge_scope: "gm" | "shared" | "discovered";
|
|
358
|
+
scene: string;
|
|
359
|
+
}>;
|
|
273
360
|
notes: NoteEntry[];
|
|
274
361
|
vows: VowState[];
|
|
275
362
|
checkpoints: Checkpoint[];
|
|
@@ -290,19 +377,63 @@ export interface NovelState {
|
|
|
290
377
|
}>;
|
|
291
378
|
premise: string;
|
|
292
379
|
hooks: string[];
|
|
380
|
+
scene_count?: number;
|
|
293
381
|
} | null;
|
|
294
382
|
adventure_scene_waypoint: {
|
|
295
383
|
anchor: string;
|
|
296
384
|
description: string;
|
|
297
385
|
} | null;
|
|
298
386
|
world: WorldModel;
|
|
387
|
+
story_beats: StoryBeat[];
|
|
388
|
+
pacing_counter: number;
|
|
389
|
+
pacing_autonomy_fired: boolean;
|
|
390
|
+
scene_transition_count: number;
|
|
391
|
+
faction_autonomous_ticks: Record<string, number>;
|
|
392
|
+
npc_goal_suggestions: GoalSuggestion[];
|
|
393
|
+
voice_corrections_this_session: number;
|
|
394
|
+
auto_record: boolean;
|
|
395
|
+
session_no_mutation_windows: string[];
|
|
396
|
+
state_regression: {
|
|
397
|
+
audit_gap: number;
|
|
398
|
+
timestamp_gap_ms: number;
|
|
399
|
+
recorded_at: string;
|
|
400
|
+
} | null;
|
|
401
|
+
last_mutation_at: string | null;
|
|
402
|
+
mutation_counts_by_group: Record<string, number>;
|
|
403
|
+
uncommitted_rolls: Array<{
|
|
404
|
+
roll: string;
|
|
405
|
+
suggested_tool: string;
|
|
406
|
+
at: string;
|
|
407
|
+
}>;
|
|
299
408
|
metadata: {
|
|
300
409
|
created: string;
|
|
301
410
|
modified: string;
|
|
302
411
|
session_count: number;
|
|
303
412
|
total_combat_rounds: number;
|
|
304
413
|
last_scene_anchor: string;
|
|
414
|
+
sessions: Array<{
|
|
415
|
+
session_id: string;
|
|
416
|
+
entry_count: number;
|
|
417
|
+
timespan_start: string;
|
|
418
|
+
timespan_end: string | null;
|
|
419
|
+
combat_rounds: number;
|
|
420
|
+
significant_roll_count: number;
|
|
421
|
+
scene_transitions: number;
|
|
422
|
+
}>;
|
|
305
423
|
};
|
|
424
|
+
active_session_id: string | null;
|
|
425
|
+
pending_vow_countdown_suggestion: {
|
|
426
|
+
vow_name: string;
|
|
427
|
+
countdown_name: string;
|
|
428
|
+
tick_count: number;
|
|
429
|
+
scope: string;
|
|
430
|
+
} | null;
|
|
431
|
+
codex_sources: Array<{
|
|
432
|
+
id: string;
|
|
433
|
+
kind: string;
|
|
434
|
+
imported_at: string;
|
|
435
|
+
codex_modified_at: string;
|
|
436
|
+
}>;
|
|
306
437
|
}
|
|
307
438
|
export interface RosterEntity extends NovelEntity {
|
|
308
439
|
}
|
|
@@ -323,7 +454,10 @@ export declare class StateManager {
|
|
|
323
454
|
enriched: boolean;
|
|
324
455
|
enrichmentManifest: any;
|
|
325
456
|
maxLoreTokens: number | null;
|
|
326
|
-
serverNotes: Map<string,
|
|
457
|
+
serverNotes: Map<string, {
|
|
458
|
+
content: string;
|
|
459
|
+
narrative_tag?: string;
|
|
460
|
+
}>;
|
|
327
461
|
codex: Map<string, CodexEntry>;
|
|
328
462
|
private npcCounter;
|
|
329
463
|
private entityCounter;
|
|
@@ -342,10 +476,25 @@ export declare class StateManager {
|
|
|
342
476
|
resumeNovel(slug: string): NovelState;
|
|
343
477
|
private loadNovelFromData;
|
|
344
478
|
switchNovel(slug: string): NovelState;
|
|
479
|
+
renameNovel(novel: NovelState, newSlug: string): NovelState;
|
|
345
480
|
endNovel(novel: NovelState, dispose: "yes" | "cancel"): {
|
|
346
481
|
removed: boolean;
|
|
347
482
|
};
|
|
483
|
+
archiveNovel(slug: string): {
|
|
484
|
+
archived: boolean;
|
|
485
|
+
at: string;
|
|
486
|
+
};
|
|
487
|
+
unarchiveNovel(slug: string): NovelState;
|
|
488
|
+
archivedNovels(): Array<{
|
|
489
|
+
slug: string;
|
|
490
|
+
archived_at: string;
|
|
491
|
+
}>;
|
|
348
492
|
cleanupExpiredTrash(): void;
|
|
493
|
+
captureWorkflowSnapshot(novel: NovelState): WorkflowSnapshot;
|
|
494
|
+
restoreFromSnapshot(novel: NovelState, snapshot: WorkflowSnapshot | null): {
|
|
495
|
+
timestamp: string;
|
|
496
|
+
};
|
|
497
|
+
checkWorkflowStaleness(novel: NovelState): string | null;
|
|
349
498
|
snapshot(novel: NovelState, badge: Badge): void;
|
|
350
499
|
undo(novel: NovelState, badge: Badge): {
|
|
351
500
|
data: any;
|
|
@@ -355,6 +504,11 @@ export declare class StateManager {
|
|
|
355
504
|
} | null;
|
|
356
505
|
audit(novel: NovelState, badge: Badge, tool: string, args: any, output_prefix?: string): void;
|
|
357
506
|
auditForbidden(badge: Badge, tool: string, args: any): void;
|
|
507
|
+
recordMutation(novel: NovelState, tool: string, group: string): void;
|
|
508
|
+
closeSessionWindow(novel: NovelState, sessionId: string): void;
|
|
509
|
+
stateGate(): "off" | "warn" | "block";
|
|
510
|
+
stateDriftActive(novel: NovelState): boolean;
|
|
511
|
+
markStateRegression(novel: NovelState, auditEntryCountGap: number, timestampGapMs: number): void;
|
|
358
512
|
verifyAuditChain(novel: NovelState): {
|
|
359
513
|
valid: boolean;
|
|
360
514
|
entries: number;
|
|
@@ -394,3 +548,6 @@ export declare class StateManager {
|
|
|
394
548
|
}, stats?: Record<string, any>): NovelEntity;
|
|
395
549
|
addEntity(novel: NovelState, entity: NovelEntity): void;
|
|
396
550
|
}
|
|
551
|
+
export declare function exportNovelJSON(novel: NovelState): any;
|
|
552
|
+
export declare function importNovelJSON(data: any): NovelState;
|
|
553
|
+
export declare function applyNovelState(target: NovelState, source: NovelState): void;
|