dsh-novel-write-engine 0.0.0-stage → 0.1.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.
- package/CHANGELOG.md +44 -0
- package/LICENSE +21 -0
- package/README.md +1167 -2
- package/briefs/P1.md +29 -0
- package/briefs/P2.md +34 -0
- package/briefs/P3.md +56 -0
- package/briefs/P4.md +74 -0
- package/briefs/P5.md +26 -0
- package/briefs/P6.md +42 -0
- package/briefs/P8.md +41 -0
- package/cordis.patch.yml +6 -0
- package/lib/client.js +694 -0
- package/lib/index.d.ts +1345 -0
- package/lib/index.js +7469 -0
- package/lib/types/client/dto.d.ts +61 -0
- package/lib/types/client/index.d.ts +17 -0
- package/lib/types/client/panel.d.ts +14 -0
- package/lib/types/client/viewmodel.d.ts +66 -0
- package/lib/types/constants.d.ts +64 -0
- package/lib/types/types.d.ts +650 -0
- package/package.json +135 -4
- package/presets/novel-write-engine.patch.yml +56 -0
- package/rulepacks/default.yaml +231 -0
- package/skills/entry.md +68 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** Wire DTOs of the panel route. Versioned so a stale tab can say "refresh". */
|
|
2
|
+
export interface PhaseDto {
|
|
3
|
+
id: string;
|
|
4
|
+
done: boolean;
|
|
5
|
+
active: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface BlockingDto {
|
|
8
|
+
code: string;
|
|
9
|
+
scope?: string;
|
|
10
|
+
detail: string;
|
|
11
|
+
hint?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SummaryDto {
|
|
14
|
+
schemaVersion: number;
|
|
15
|
+
panelId: string;
|
|
16
|
+
title: string;
|
|
17
|
+
genre: string;
|
|
18
|
+
platform: string;
|
|
19
|
+
chapter: number;
|
|
20
|
+
stage: string;
|
|
21
|
+
revision: number;
|
|
22
|
+
totalWords: number;
|
|
23
|
+
totalChapters: number;
|
|
24
|
+
phases: PhaseDto[];
|
|
25
|
+
blocking: BlockingDto[];
|
|
26
|
+
next?: {
|
|
27
|
+
tool: string;
|
|
28
|
+
reason: string;
|
|
29
|
+
};
|
|
30
|
+
/** True only when the book target is reached; done alone means the chapter is archived. */
|
|
31
|
+
finished?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface ChapterRowDto {
|
|
34
|
+
num: number;
|
|
35
|
+
title: string;
|
|
36
|
+
wordCount: number;
|
|
37
|
+
score: number;
|
|
38
|
+
stage: string;
|
|
39
|
+
status: 'passed' | 'blocked' | 'draft';
|
|
40
|
+
details?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ChaptersDto {
|
|
43
|
+
schemaVersion: number;
|
|
44
|
+
panelId: string;
|
|
45
|
+
rows: ChapterRowDto[];
|
|
46
|
+
}
|
|
47
|
+
export interface GatesDto {
|
|
48
|
+
schemaVersion: number;
|
|
49
|
+
panelId: string;
|
|
50
|
+
stage: string;
|
|
51
|
+
blocking: BlockingDto[];
|
|
52
|
+
explanations: string[];
|
|
53
|
+
}
|
|
54
|
+
export interface PanelPayloadDto {
|
|
55
|
+
schemaVersion: number;
|
|
56
|
+
summary: SummaryDto;
|
|
57
|
+
chapters: ChaptersDto;
|
|
58
|
+
gates: GatesDto;
|
|
59
|
+
error?: string;
|
|
60
|
+
empty?: true;
|
|
61
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NovelIcon, NovelPanel } from './panel.js';
|
|
2
|
+
/** The subset of the browser context this half needs; kept structural on purpose. */
|
|
3
|
+
export interface ClientContext {
|
|
4
|
+
effect?: (body: () => undefined | (() => void), label?: string) => void;
|
|
5
|
+
slots: {
|
|
6
|
+
inject: (name: string, body: () => unknown) => unknown;
|
|
7
|
+
register: (options: Record<string, unknown>, component: (props: never) => unknown) => unknown;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export declare const name = "dsh-novel-write-engine";
|
|
11
|
+
export declare const inject: string[];
|
|
12
|
+
/**
|
|
13
|
+
* Register the sidebar entry and the main page. The sidebar id must equal the
|
|
14
|
+
* `main` key; that pairing is what makes the icon open this page.
|
|
15
|
+
*/
|
|
16
|
+
export declare function apply(ctx: ClientContext): void;
|
|
17
|
+
export { NovelPanel, NovelIcon };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import { buildView, type PanelView } from './viewmodel.js';
|
|
3
|
+
/**
|
|
4
|
+
* Pure view: given a view model, return the element tree. Keeping the hooks in
|
|
5
|
+
* `NovelPanel` makes every visual state renderable without a browser.
|
|
6
|
+
*/
|
|
7
|
+
export declare function panelElement(view: PanelView, loading: boolean, onRefresh: () => void): ReactElement;
|
|
8
|
+
/** Stateful wrapper: fetch once, refresh on demand and after returning to the tab. */
|
|
9
|
+
export declare function NovelPanel(): ReactElement;
|
|
10
|
+
/** Sidebar icon: a small book mark, inheriting the current text colour. */
|
|
11
|
+
export declare function NovelIcon({ size }: {
|
|
12
|
+
size?: number;
|
|
13
|
+
}): ReactElement;
|
|
14
|
+
export { buildView };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { PanelPayloadDto } from './dto.js';
|
|
2
|
+
/** One human-facing progress step. */
|
|
3
|
+
export interface PanelPhase {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
done: boolean;
|
|
7
|
+
active: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** One archived or active chapter, projected for a card rather than a raw table row. */
|
|
10
|
+
export interface PanelChapter {
|
|
11
|
+
num: string;
|
|
12
|
+
title: string;
|
|
13
|
+
words: string;
|
|
14
|
+
wordCount: number;
|
|
15
|
+
score: string;
|
|
16
|
+
scoreValue: number;
|
|
17
|
+
scorePercent: number;
|
|
18
|
+
badge: string;
|
|
19
|
+
tone: 'ok' | 'bad' | 'muted';
|
|
20
|
+
details: string;
|
|
21
|
+
stageLabel: string;
|
|
22
|
+
}
|
|
23
|
+
/** Everything the panel renders, derived from the wire payload alone. */
|
|
24
|
+
export interface PanelView {
|
|
25
|
+
state: 'ready' | 'loading' | 'empty' | 'error' | 'outdated';
|
|
26
|
+
title: string;
|
|
27
|
+
subtitle: string;
|
|
28
|
+
stageLabel: string;
|
|
29
|
+
/** The whole book reached its configured target; stage `done` alone is only one chapter. */
|
|
30
|
+
finished: boolean;
|
|
31
|
+
revisionLabel: string;
|
|
32
|
+
phases: PanelPhase[];
|
|
33
|
+
rows: PanelChapter[];
|
|
34
|
+
blocking: Array<{
|
|
35
|
+
code: string;
|
|
36
|
+
scope: string;
|
|
37
|
+
detail: string;
|
|
38
|
+
hint: string;
|
|
39
|
+
}>;
|
|
40
|
+
blockingTitle: string;
|
|
41
|
+
stats: {
|
|
42
|
+
chapters: number;
|
|
43
|
+
words: number;
|
|
44
|
+
averageScore: number;
|
|
45
|
+
blocking: number;
|
|
46
|
+
};
|
|
47
|
+
nextTitle: string;
|
|
48
|
+
nextDetail: string;
|
|
49
|
+
nextTool: string;
|
|
50
|
+
emptyCommand: string;
|
|
51
|
+
/** Compatibility fields used by older cards and tests. */
|
|
52
|
+
revision: string;
|
|
53
|
+
next: string;
|
|
54
|
+
}
|
|
55
|
+
export declare const PANEL_SCHEMA_VERSION = 1;
|
|
56
|
+
/**
|
|
57
|
+
* Project the wire payload into strings. Version mismatch wins over everything
|
|
58
|
+
* else: a stale panel must never render data from another schema as if it were
|
|
59
|
+
* current.
|
|
60
|
+
*/
|
|
61
|
+
export declare function buildView(payload: PanelPayloadDto | null, error?: string | null): PanelView;
|
|
62
|
+
/** Fetch the panel payload; failures become a plain message, never a throw. */
|
|
63
|
+
export declare function fetchPanel(fetcher: typeof fetch, path: string, signal?: AbortSignal): Promise<{
|
|
64
|
+
payload: PanelPayloadDto | null;
|
|
65
|
+
error: string | null;
|
|
66
|
+
}>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Genre, Platform, SceneType, Stage } from './types.js';
|
|
2
|
+
/** Panel and session identifiers. */
|
|
3
|
+
export declare const PLUGIN_NAME = "dsh-novel-write-engine";
|
|
4
|
+
export declare const PANEL_ID = "novel-workshop";
|
|
5
|
+
export declare const PANEL_ROUTE = "/api/novel-write-engine/panel";
|
|
6
|
+
export declare const SKILL_NAME = "novel-write-engine";
|
|
7
|
+
export declare const REMOTE_VERSION = 1;
|
|
8
|
+
/** Project-relative locations. Every write goes through these constants. */
|
|
9
|
+
export declare const PROJECT_FILE = "novel.yaml";
|
|
10
|
+
export declare const STATE_DIR = "state";
|
|
11
|
+
export declare const CHAPTERS_DIR = "chapters";
|
|
12
|
+
export declare const PLAN_DIR = "plans";
|
|
13
|
+
export declare const REVIEW_DIR = "reviews";
|
|
14
|
+
export declare const CHECK_DIR = "checks";
|
|
15
|
+
export declare const EXPORT_DIR = "exports";
|
|
16
|
+
export declare const BACKUP_DIR = "backups";
|
|
17
|
+
export declare const OUTLINE_DIR = "outline";
|
|
18
|
+
export declare const LOCK_FILE = ".engine.lock";
|
|
19
|
+
export declare const STAGING_DIR = ".staging";
|
|
20
|
+
export declare const REGISTRY_FILE = "projects.yaml";
|
|
21
|
+
/** Files owned by the engine under `state/`. */
|
|
22
|
+
export declare const STATE_FILES: {
|
|
23
|
+
readonly pipeline: "pipeline.yaml";
|
|
24
|
+
readonly chapters: "chapters.yaml";
|
|
25
|
+
readonly characters: "characters.yaml";
|
|
26
|
+
readonly world: "world.yaml";
|
|
27
|
+
readonly locks: "locks.yaml";
|
|
28
|
+
readonly timeline: "timeline.yaml";
|
|
29
|
+
readonly foreshadows: "foreshadows.yaml";
|
|
30
|
+
readonly relationships: "relationships.yaml";
|
|
31
|
+
readonly handoff: "handoff.yaml";
|
|
32
|
+
readonly journal: "journal.jsonl";
|
|
33
|
+
};
|
|
34
|
+
/** Chapter file name, zero padded to three digits. */
|
|
35
|
+
export declare const chapterFile: (chapter: number) => string;
|
|
36
|
+
/** Kept for reference when a rollback discards the current draft. */
|
|
37
|
+
export declare const deprecatedChapterFile: (chapter: number) => string;
|
|
38
|
+
export declare const planWorldFile: (chapter: number) => string;
|
|
39
|
+
export declare const planChapterFile: (chapter: number) => string;
|
|
40
|
+
export declare const reviewFile: (chapter: number) => string;
|
|
41
|
+
export declare const checkFile: (chapter: number) => string;
|
|
42
|
+
/** Limits that are structural, not taste. */
|
|
43
|
+
export declare const LIMITS: {
|
|
44
|
+
/** P4 <-> P5/P6 retries before a forced rollback. */
|
|
45
|
+
maxRounds: number;
|
|
46
|
+
/** Lock staleness in milliseconds. */
|
|
47
|
+
lockStaleMs: number;
|
|
48
|
+
/** How long a writer waits for the keyed mutex before failing. */
|
|
49
|
+
lockWaitMs: number;
|
|
50
|
+
/** Reading proofs shorter than this cannot be verified. */
|
|
51
|
+
minQuoteChars: number;
|
|
52
|
+
};
|
|
53
|
+
/** Re-exported enums make adapter code readable without importing types twice. */
|
|
54
|
+
export declare const SCENE_TYPE_DEFAULT: SceneType;
|
|
55
|
+
export declare const DEFAULT_GENRE: Genre;
|
|
56
|
+
export declare const DEFAULT_PLATFORM: Platform;
|
|
57
|
+
export declare const INITIAL_STAGE: Stage;
|
|
58
|
+
/** The order used to render the nine-phase progress strip. */
|
|
59
|
+
export declare const PHASE_STRIP: readonly ["P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9"];
|
|
60
|
+
/** Tool names, kept here so the arch test can assert one namespace. */
|
|
61
|
+
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"];
|
|
62
|
+
export type ToolName = (typeof TOOL_NAMES)[number];
|
|
63
|
+
/** The eight high-frequency tools kept when `tools.mode = core`. */
|
|
64
|
+
export declare const CORE_TOOLS: readonly ToolName[];
|