@gordon.gan/specflow 1.7.0-beta → 1.8.0-alpha

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.
Files changed (151) hide show
  1. package/README.md +4 -4
  2. package/dist/cli/commands/document-run.d.ts +84 -0
  3. package/dist/cli/commands/document-run.js +539 -0
  4. package/dist/cli/index.js +2 -2
  5. package/dist/core/artifact-language.js +11 -1
  6. package/dist/core/document/chapters.d.ts +6 -0
  7. package/dist/core/document/chapters.js +21 -0
  8. package/dist/core/document/coverage.d.ts +25 -0
  9. package/dist/core/document/coverage.js +49 -0
  10. package/dist/core/document/digests.d.ts +41 -0
  11. package/dist/core/document/digests.js +136 -0
  12. package/dist/core/document/engine.d.ts +92 -0
  13. package/dist/core/document/engine.js +487 -0
  14. package/dist/core/{approval → document}/forbidden-patterns.d.ts +4 -2
  15. package/dist/core/document/forbidden-patterns.js +33 -0
  16. package/dist/core/document/gates.d.ts +27 -0
  17. package/dist/core/document/gates.js +33 -0
  18. package/dist/core/document/index.d.ts +7 -0
  19. package/dist/core/document/index.js +7 -0
  20. package/dist/core/document/input-digest.d.ts +55 -0
  21. package/dist/core/document/input-digest.js +121 -0
  22. package/dist/core/document/input-features.d.ts +24 -0
  23. package/dist/core/document/input-features.js +112 -0
  24. package/dist/core/document/lint.d.ts +22 -0
  25. package/dist/core/document/lint.js +29 -0
  26. package/dist/core/document/llm.d.ts +35 -0
  27. package/dist/core/document/llm.js +27 -0
  28. package/dist/core/document/map.d.ts +46 -0
  29. package/dist/core/document/map.js +212 -0
  30. package/dist/core/document/outline.d.ts +26 -0
  31. package/dist/core/document/outline.js +128 -0
  32. package/dist/core/document/paths.d.ts +23 -0
  33. package/dist/core/document/paths.js +31 -0
  34. package/dist/core/document/profile-validator.d.ts +23 -0
  35. package/dist/core/document/profile-validator.js +127 -0
  36. package/dist/core/document/profiles.d.ts +23 -0
  37. package/dist/core/document/profiles.js +69 -0
  38. package/dist/core/document/render.d.ts +19 -0
  39. package/dist/core/document/render.js +97 -0
  40. package/dist/core/document/review.d.ts +42 -0
  41. package/dist/core/document/review.js +157 -0
  42. package/dist/core/document/scene-detect.d.ts +25 -0
  43. package/dist/core/document/scene-detect.js +121 -0
  44. package/dist/core/document/schemas.d.ts +949 -0
  45. package/dist/core/document/schemas.js +158 -0
  46. package/dist/integrations/shared/capability-evidence.js +4 -8
  47. package/dist/integrations/shared/command-catalog.js +1 -1
  48. package/dist/integrations/shared/parity-manifest.js +4 -8
  49. package/package.json +1 -1
  50. package/prompts/apply/phase-a-plan.md +1 -1
  51. package/prompts/document/map/acceptance.md +8 -0
  52. package/prompts/document/map/api-design.md +17 -0
  53. package/prompts/document/map/architecture.md +7 -0
  54. package/prompts/document/map/closed-loop.md +8 -0
  55. package/prompts/document/map/compat-migration.md +8 -0
  56. package/prompts/document/map/config-runtime.md +8 -0
  57. package/prompts/document/map/core-logic.md +8 -0
  58. package/prompts/document/map/data-model.md +17 -0
  59. package/prompts/document/map/deploy.md +8 -0
  60. package/prompts/document/map/fix.md +7 -0
  61. package/prompts/document/map/goal.md +7 -0
  62. package/prompts/document/map/impact.md +7 -0
  63. package/prompts/document/map/implementability.md +8 -0
  64. package/prompts/document/map/mvp-boundary.md +7 -0
  65. package/prompts/document/map/non-goals.md +7 -0
  66. package/prompts/document/map/regression.md +7 -0
  67. package/prompts/document/map/reproduce.md +7 -0
  68. package/prompts/document/map/requirement.md +7 -0
  69. package/prompts/document/map/root-cause.md +7 -0
  70. package/prompts/document/map/signoff.md +8 -0
  71. package/prompts/document/map/tech-selection.md +17 -0
  72. package/prompts/document/map/test-strategy.md +7 -0
  73. package/prompts/document/map/ui-design.md +18 -0
  74. package/prompts/document/outline/general.md +37 -0
  75. package/prompts/document/review/ai-review.md +56 -0
  76. package/prompts/explore/explore-session.md +1 -1
  77. package/prompts/propose/design-draft.md +1 -1
  78. package/prompts/propose/proposal.md +1 -1
  79. package/prompts/propose/specs.md +1 -1
  80. package/prompts/propose/tasks-draft.md +1 -1
  81. package/prompts/refine/design-output.md +1 -1
  82. package/prompts/refine/update-artifacts.md +2 -0
  83. package/prompts/shared/artifact-language.md +13 -0
  84. package/skills/specflow-document/SKILL.md +124 -0
  85. package/templates/document/chapters/acceptance.yaml +16 -0
  86. package/templates/document/chapters/api-design.yaml +24 -0
  87. package/templates/document/chapters/architecture.yaml +18 -0
  88. package/templates/document/chapters/closed-loop.yaml +22 -0
  89. package/templates/document/chapters/compat-migration.yaml +17 -0
  90. package/templates/document/chapters/config-runtime.yaml +16 -0
  91. package/templates/document/chapters/core-logic.yaml +16 -0
  92. package/templates/document/chapters/data-model.yaml +25 -0
  93. package/templates/document/chapters/deploy.yaml +18 -0
  94. package/templates/document/chapters/fix.yaml +18 -0
  95. package/templates/document/chapters/goal.yaml +17 -0
  96. package/templates/document/chapters/impact.yaml +16 -0
  97. package/templates/document/chapters/implementability.yaml +22 -0
  98. package/templates/document/chapters/mvp-boundary.yaml +20 -0
  99. package/templates/document/chapters/non-goals.yaml +17 -0
  100. package/templates/document/chapters/regression.yaml +16 -0
  101. package/templates/document/chapters/reproduce.yaml +16 -0
  102. package/templates/document/chapters/requirement.yaml +18 -0
  103. package/templates/document/chapters/root-cause.yaml +18 -0
  104. package/templates/document/chapters/signoff.yaml +15 -0
  105. package/templates/document/chapters/tech-selection.yaml +20 -0
  106. package/templates/document/chapters/test-strategy.yaml +20 -0
  107. package/templates/document/chapters/ui-design.yaml +22 -0
  108. package/templates/document/profiles/0to1.yaml +12 -0
  109. package/templates/document/profiles/approve.yaml +22 -0
  110. package/templates/document/profiles/bugfix.yaml +10 -0
  111. package/templates/document/profiles/feature.yaml +11 -0
  112. package/dist/cli/commands/approval-assemble.d.ts +0 -64
  113. package/dist/cli/commands/approval-assemble.js +0 -408
  114. package/dist/core/approval/assemble.d.ts +0 -10
  115. package/dist/core/approval/assemble.js +0 -384
  116. package/dist/core/approval/bundle.d.ts +0 -9
  117. package/dist/core/approval/bundle.js +0 -172
  118. package/dist/core/approval/forbidden-patterns.js +0 -37
  119. package/dist/core/approval/index-schema.d.ts +0 -676
  120. package/dist/core/approval/index-schema.js +0 -193
  121. package/dist/core/approval/index.d.ts +0 -12
  122. package/dist/core/approval/index.js +0 -9
  123. package/dist/core/approval/lint.d.ts +0 -10
  124. package/dist/core/approval/lint.js +0 -302
  125. package/dist/core/approval/paths.d.ts +0 -13
  126. package/dist/core/approval/paths.js +0 -43
  127. package/dist/core/approval/pipeline.d.ts +0 -28
  128. package/dist/core/approval/pipeline.js +0 -146
  129. package/dist/core/approval/playbook-schema.d.ts +0 -182
  130. package/dist/core/approval/playbook-schema.js +0 -51
  131. package/dist/core/approval/render.d.ts +0 -20
  132. package/dist/core/approval/render.js +0 -210
  133. package/dist/core/approval/review-pack.d.ts +0 -26
  134. package/dist/core/approval/review-pack.js +0 -205
  135. package/dist/core/approval/types.d.ts +0 -223
  136. package/dist/core/approval/types.js +0 -1
  137. package/prompts/approval/acp-pipeline.md +0 -104
  138. package/prompts/approval/ai-review.md +0 -145
  139. package/prompts/approval/api-guidance.md +0 -179
  140. package/prompts/approval/database-guidance.md +0 -105
  141. package/prompts/approval/frontend-guidance.md +0 -249
  142. package/prompts/approval/generate.md +0 -1583
  143. package/prompts/approval/multi-repo-guidance.md +0 -238
  144. package/prompts/approval/project-conventions-guidance.md +0 -171
  145. package/prompts/approval/runtime-guidance.md +0 -64
  146. package/prompts/approval/segmented-generation.md +0 -157
  147. package/skills/specflow-approval/SKILL.md +0 -663
  148. package/templates/approval-index.yaml +0 -93
  149. package/templates/approval-part.md +0 -15
  150. package/templates/approval-playbook.yaml +0 -28
  151. package/templates/approval.md +0 -261
@@ -18,13 +18,23 @@ export function requireArtifactLanguage(value) {
18
18
  }
19
19
  export function renderArtifactLanguageGuidance(language) {
20
20
  const narrativeLanguage = language === 'zh-CN' ? 'Simplified Chinese' : 'English';
21
+ const styleLines = language === 'zh-CN'
22
+ ? [
23
+ 'Chinese narrative must be brief: one idea per sentence; no filler.',
24
+ 'Write how-to / process / handling as numbered 1. 2. 3. steps (one sentence each).',
25
+ 'Do not collapse multi-step flows into a paragraph.',
26
+ 'Leave tables, Mermaid, DDL, HTTP examples, and protocol markers unchanged.',
27
+ ]
28
+ : ['Keep narrative concise. Use numbered steps for how-to. Leave tables and diagrams unchanged.'];
21
29
  return [
22
30
  '## Artifact language policy',
23
31
  '',
24
32
  `Write all non-protocol business content in ${narrativeLanguage}.`,
25
- 'This includes proposal narrative, requirement and scenario descriptions, text after WHEN/THEN, design rationale, and task descriptions.',
33
+ 'This includes proposal narrative, requirement and scenario descriptions, text after WHEN/THEN, design rationale, task descriptions, explore, and approval.',
26
34
  'Do not mix narrative languages in the same artifact.',
27
35
  '',
36
+ ...styleLines,
37
+ '',
28
38
  'Keep SpecFlow protocol markers unchanged, including:',
29
39
  '- `ADDED Requirements`, `MODIFIED Requirements`, `REMOVED Requirements`, and `RENAMED Requirements`',
30
40
  '- `Requirement:`, `Scenario:`, `WHEN`, and `THEN`',
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Document Engine — chapter component library loader.
3
+ * Loads templates/document/chapters/*.yaml, validates each parses, returns a Map.
4
+ */
5
+ import { ChapterComponent } from './schemas.js';
6
+ export declare function loadChapterLibrary(dir?: string): Promise<Map<string, ChapterComponent>>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Document Engine — chapter component library loader.
3
+ * Loads templates/document/chapters/*.yaml, validates each parses, returns a Map.
4
+ */
5
+ import { promises as fs } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import yaml from 'js-yaml';
8
+ import { parseChapterComponent } from './schemas.js';
9
+ const DEFAULT_CHAPTERS_DIR = join(process.cwd(), 'templates', 'document', 'chapters');
10
+ export async function loadChapterLibrary(dir = DEFAULT_CHAPTERS_DIR) {
11
+ const entries = await fs.readdir(dir);
12
+ const lib = new Map();
13
+ for (const file of entries) {
14
+ if (!file.endsWith('.yaml') && !file.endsWith('.yml'))
15
+ continue;
16
+ const raw = yaml.load(await fs.readFile(join(dir, file), 'utf-8'));
17
+ const ch = parseChapterComponent(raw);
18
+ lib.set(ch.id, ch);
19
+ }
20
+ return lib;
21
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Document Engine — coverage completeness (decision 8·P1-B + decision 9·kind).
3
+ *
4
+ * Two channels:
5
+ * - Structured (at generation): for kind=entity|mixed points, referenced entity ids must appear
6
+ * in the chapter's structured entity contribution.
7
+ * - Semantic (at review R14): for kind=narrative|mixed points, produces a checklist consumed by
8
+ * the reviewer to verify the corresponding section exists and is non-stub.
9
+ */
10
+ import { Outline, Entities } from './schemas.js';
11
+ export interface CoverageDiagnostic {
12
+ code: string;
13
+ severity: 'error' | 'warning';
14
+ message: string;
15
+ chapter?: string;
16
+ point?: string;
17
+ }
18
+ /** Structured channel: verify referenced entities are present in the chapter's entity contribution. */
19
+ export declare function checkStructuredCoverage(outline: Outline, chapterEntities: Map<string, Entities>): CoverageDiagnostic[];
20
+ /** Semantic checklist for reviewer (R14): narrative|mixed points → must have a non-stub section. */
21
+ export declare function semanticCoverageChecklist(outline: Outline): Array<{
22
+ chapter: string;
23
+ pointId: string;
24
+ text: string;
25
+ }>;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Document Engine — coverage completeness (decision 8·P1-B + decision 9·kind).
3
+ *
4
+ * Two channels:
5
+ * - Structured (at generation): for kind=entity|mixed points, referenced entity ids must appear
6
+ * in the chapter's structured entity contribution.
7
+ * - Semantic (at review R14): for kind=narrative|mixed points, produces a checklist consumed by
8
+ * the reviewer to verify the corresponding section exists and is non-stub.
9
+ */
10
+ /** Structured channel: verify referenced entities are present in the chapter's entity contribution. */
11
+ export function checkStructuredCoverage(outline, chapterEntities) {
12
+ const diags = [];
13
+ for (const ch of outline.chapters) {
14
+ const ents = chapterEntities.get(ch.id) ?? { interfaces: [], tables: [], decisions: [] };
15
+ const present = new Set([
16
+ ...ents.interfaces.map((i) => i.id),
17
+ ...ents.tables.map((t) => t.id),
18
+ ...ents.decisions.map((d) => d.id),
19
+ ]);
20
+ for (const p of ch.points) {
21
+ if (p.kind === 'narrative')
22
+ continue; // narrative → semantic channel only
23
+ for (const ref of p.references ?? []) {
24
+ if (!present.has(ref)) {
25
+ diags.push({
26
+ code: 'entity_not_filled',
27
+ severity: 'error',
28
+ chapter: ch.id,
29
+ point: p.id,
30
+ message: `Point "${p.id}" references entity "${ref}" but chapter "${ch.id}" has no such entity`,
31
+ });
32
+ }
33
+ }
34
+ }
35
+ }
36
+ return diags;
37
+ }
38
+ /** Semantic checklist for reviewer (R14): narrative|mixed points → must have a non-stub section. */
39
+ export function semanticCoverageChecklist(outline) {
40
+ const list = [];
41
+ for (const ch of outline.chapters) {
42
+ for (const p of ch.points) {
43
+ if (p.kind === 'narrative' || p.kind === 'mixed') {
44
+ list.push({ chapter: ch.id, pointId: p.id, text: p.text });
45
+ }
46
+ }
47
+ }
48
+ return list;
49
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Document Engine — dependency digests (decisions 2 + 8·P1-D + 9).
3
+ *
4
+ * - extractConstraintList: deterministic constraint items (entity/decision/point ids) that a
5
+ * chapter's digest MUST preserve (decision 8).
6
+ * - generateDigest: bounded LLM summary carrying the constraint list; deterministic fallback.
7
+ * - lintDigest: bidirectional lint — forward (digest ids exist in source) + reverse (constraint
8
+ * items present in digest).
9
+ * - recordDigestSources / affectedDownstream: invalidation propagation (decision 9).
10
+ */
11
+ import { OutlineChapter, ConstraintItem, Entities } from './schemas.js';
12
+ import type { DocumentLLM } from './llm.js';
13
+ export declare const DIGEST_BUDGET_TOKENS = 1000;
14
+ export declare function extractConstraintList(chapter: OutlineChapter, entities: Entities): ConstraintItem[];
15
+ export interface DigestInput {
16
+ chapterId: string;
17
+ chapterTitle: string;
18
+ source: string;
19
+ constraints: ConstraintItem[];
20
+ }
21
+ export declare function generateDigest(llm: DocumentLLM, input: DigestInput): Promise<string>;
22
+ /** Deterministic fallback: render entity registry as a one-line digest. */
23
+ export declare function deterministicDigest(entities: Entities, ids: string[]): string;
24
+ export interface DigestLintDiagnostic {
25
+ code: string;
26
+ severity: 'error' | 'warning';
27
+ message: string;
28
+ }
29
+ export declare function lintDigest(digest: string, constraints: ConstraintItem[], knownEntityIds: Set<string>): DigestLintDiagnostic[];
30
+ export interface DigestSource {
31
+ chapterId: string;
32
+ /** entity ids this digest depends on (for granular invalidation). */
33
+ entityIds: string[];
34
+ }
35
+ export declare function recordDigestSources(chapter: OutlineChapter, sourceEntities: Entities): DigestSource;
36
+ /**
37
+ * Given a changed chapter, return the set of downstream chapters whose digests are invalidated.
38
+ * (decision 9): only direct dependents whose digest references one of the changed entities are
39
+ * invalidated. Outline change → caller passes allDownstream (full invalidation).
40
+ */
41
+ export declare function affectedDownstream(changedChapterId: string, changedEntityIds: string[], downstreamSources: DigestSource[]): string[];
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Document Engine — dependency digests (decisions 2 + 8·P1-D + 9).
3
+ *
4
+ * - extractConstraintList: deterministic constraint items (entity/decision/point ids) that a
5
+ * chapter's digest MUST preserve (decision 8).
6
+ * - generateDigest: bounded LLM summary carrying the constraint list; deterministic fallback.
7
+ * - lintDigest: bidirectional lint — forward (digest ids exist in source) + reverse (constraint
8
+ * items present in digest).
9
+ * - recordDigestSources / affectedDownstream: invalidation propagation (decision 9).
10
+ */
11
+ export const DIGEST_BUDGET_TOKENS = 1000;
12
+ // ============= Constraint extraction (T7.1) =============
13
+ export function extractConstraintList(chapter, entities) {
14
+ const items = [];
15
+ for (const p of chapter.points) {
16
+ items.push({ kind: 'point', id: p.id, label: p.text.slice(0, 40) });
17
+ for (const ref of p.references ?? []) {
18
+ items.push({ kind: 'entity', id: ref, label: ref });
19
+ }
20
+ }
21
+ for (const d of entities.decisions) {
22
+ if (chapter.points.some((p) => (p.references ?? []).includes(d.id)) || true) {
23
+ // decisions referenced anywhere are preserved if they relate to this chapter's points
24
+ if (chapter.points.some((p) => p.text.includes(d.text.slice(0, 20)) || (p.references ?? []).includes(d.id))) {
25
+ items.push({ kind: 'decision', id: d.id, label: d.text.slice(0, 40) });
26
+ }
27
+ }
28
+ }
29
+ // dedupe by kind+id
30
+ const seen = new Set();
31
+ return items.filter((it) => {
32
+ const k = `${it.kind}:${it.id}`;
33
+ if (seen.has(k))
34
+ return false;
35
+ seen.add(k);
36
+ return true;
37
+ });
38
+ }
39
+ // ============= Digest generation (T7.2) =============
40
+ const DIGEST_SYSTEM = '你是依赖摘要生成器。为下游章节生成上游章节的紧凑摘要,必须逐项保留约束清单中的每一项(实体 id / 决策 id / 要点 id 及其一句话含义)。禁止引入上游没有的实体。';
41
+ export async function generateDigest(llm, input) {
42
+ const constraintText = input.constraints.map((c) => `- ${c.kind} ${c.id}: ${c.label}`).join('\n');
43
+ const llmInput = {
44
+ system: DIGEST_SYSTEM,
45
+ messages: [
46
+ {
47
+ role: 'user',
48
+ content: `上游章节 ${input.chapterId}(${input.chapterTitle}):\n${input.source.slice(0, 6000)}\n\n必须保留的约束清单:\n${constraintText}`,
49
+ },
50
+ ],
51
+ };
52
+ const res = await llm.complete(llmInput);
53
+ return res.content.trim();
54
+ }
55
+ /** Deterministic fallback: render entity registry as a one-line digest. */
56
+ export function deterministicDigest(entities, ids) {
57
+ const lines = [];
58
+ for (const it of entities.interfaces) {
59
+ if (ids.length === 0 || ids.includes(it.id)) {
60
+ lines.push(`I ${it.id}: ${it.name} ${it.method} ${it.path}`);
61
+ }
62
+ }
63
+ for (const t of entities.tables) {
64
+ if (ids.length === 0 || ids.includes(t.id)) {
65
+ lines.push(`T ${t.id}: ${t.name}`);
66
+ }
67
+ }
68
+ for (const d of entities.decisions) {
69
+ if (ids.length === 0 || ids.includes(d.id)) {
70
+ lines.push(`D ${d.id}: ${d.text}`);
71
+ }
72
+ }
73
+ return lines.join('\n');
74
+ }
75
+ export function lintDigest(digest, constraints, knownEntityIds) {
76
+ const diags = [];
77
+ // Reverse: every constraint item must appear in digest (decision 8).
78
+ for (const c of constraints) {
79
+ if (!digest.includes(c.id)) {
80
+ diags.push({
81
+ code: 'constraint_missing',
82
+ severity: 'error',
83
+ message: `Digest missing constraint ${c.kind} ${c.id} (${c.label})`,
84
+ });
85
+ }
86
+ }
87
+ // Forward: any entity id mentioned in digest that we can detect must exist in known set.
88
+ // (Heuristic: backtick-quoted tokens + bare I\d+/T\d+ ids.)
89
+ const mentioned = new Set();
90
+ for (const m of digest.matchAll(/`([A-Za-z0-9_.]+)`/g))
91
+ mentioned.add(m[1]);
92
+ for (const m of digest.matchAll(/\b(I\d+|T\d+)\b/g))
93
+ mentioned.add(m[1]);
94
+ for (const id of mentioned) {
95
+ if (knownEntityIds.size > 0 && !knownEntityIds.has(id) && !/^I\d+$/.test(id) && !/^T\d+$/.test(id)) {
96
+ diags.push({
97
+ code: 'digest_hallucinated_entity',
98
+ severity: 'warning',
99
+ message: `Digest mentions unknown entity "${id}"`,
100
+ });
101
+ }
102
+ }
103
+ return diags;
104
+ }
105
+ export function recordDigestSources(chapter, sourceEntities) {
106
+ const entityIds = new Set();
107
+ for (const p of chapter.points) {
108
+ for (const ref of p.references ?? [])
109
+ entityIds.add(ref);
110
+ }
111
+ // Include referenced entity ids that actually exist in source entities.
112
+ const known = new Set([
113
+ ...sourceEntities.interfaces.map((i) => i.id),
114
+ ...sourceEntities.tables.map((t) => t.id),
115
+ ]);
116
+ return {
117
+ chapterId: chapter.id,
118
+ entityIds: [...entityIds].filter((id) => known.has(id)),
119
+ };
120
+ }
121
+ /**
122
+ * Given a changed chapter, return the set of downstream chapters whose digests are invalidated.
123
+ * (decision 9): only direct dependents whose digest references one of the changed entities are
124
+ * invalidated. Outline change → caller passes allDownstream (full invalidation).
125
+ */
126
+ export function affectedDownstream(changedChapterId, changedEntityIds, downstreamSources) {
127
+ const changed = new Set(changedEntityIds);
128
+ const affected = new Set();
129
+ for (const ds of downstreamSources) {
130
+ if (ds.chapterId === changedChapterId)
131
+ continue;
132
+ if (ds.entityIds.some((id) => changed.has(id)))
133
+ affected.add(ds.chapterId);
134
+ }
135
+ return [...affected];
136
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Document Engine — unified orchestration entry (T11.2).
3
+ *
4
+ * runDocument wires Pass 0.5 → 1 → 2 → 3 → 4 + gates. Consumers inject the LLM,
5
+ * the work root, and the input. An `outlineOnly` mode stops after Pass 1 (for user gate).
6
+ */
7
+ import { ScenarioProfile, ChapterComponent, Outline } from './schemas.js';
8
+ import type { DocumentLLM } from './llm.js';
9
+ import { SegmentableInput } from './input-digest.js';
10
+ import { expandProfile } from './profiles.js';
11
+ import { GateDiagnostic } from './gates.js';
12
+ export interface RunDocumentOptions {
13
+ llm: DocumentLLM;
14
+ workRoot: string;
15
+ profile: ScenarioProfile;
16
+ library: Map<string, ChapterComponent>;
17
+ inputs: SegmentableInput[];
18
+ inputFeatures: Record<string, boolean>;
19
+ change: string;
20
+ outlineOnly?: boolean;
21
+ /** Skip Pass 3 AI review entirely (fast path; no findings applied, no review-result written). */
22
+ skipReview?: boolean;
23
+ /** User confirmation gate for the generated outline (T5.4). If absent, outline is auto-accepted
24
+ * (non-interactive / test path). Return true to accept, false to reject (→ regenerate). */
25
+ outlineConfirmer?: (outline: Outline) => Promise<boolean>;
26
+ /** Incremental refill (decision 9 · invalidation propagation). When a chapter/entity changed,
27
+ * only downstream chapters whose digests reference the changed entities are refilled; unaffected
28
+ * chapters are reused from persisted `chapters/<id>.md` when present. Default: full refill. */
29
+ incremental?: {
30
+ changedChapterId?: string;
31
+ changedEntityIds?: string[];
32
+ };
33
+ maxRounds?: number;
34
+ renderHtmlOutput?: boolean;
35
+ outlinePrompt?: string;
36
+ reviewPrompt?: string;
37
+ /** Persist per-chapter files/entities to workRoot (default true). */
38
+ persist?: boolean;
39
+ }
40
+ export interface RunDocumentResult {
41
+ ok: boolean;
42
+ stage: string;
43
+ outline?: Outline;
44
+ documentMd?: string;
45
+ documentHtml?: string;
46
+ diagnostics: GateDiagnostic[];
47
+ tokenEstimate?: number;
48
+ }
49
+ export declare function runDocument(options: RunDocumentOptions): Promise<RunDocumentResult>;
50
+ export interface AgentStep {
51
+ /** stable id: 'input-summary' | 'outline' | 'chapter:<id>' | 'review' */
52
+ id: string;
53
+ phase: 'prep' | 'outline' | 'fill' | 'review';
54
+ title: string;
55
+ description: string;
56
+ prompt: string;
57
+ inputFiles: string[];
58
+ outputFile: string;
59
+ required: boolean;
60
+ }
61
+ export interface PlanStepsInput {
62
+ profile: ScenarioProfile;
63
+ library: Map<string, ChapterComponent>;
64
+ inputFeatures: Record<string, boolean>;
65
+ inputs: SegmentableInput[];
66
+ workRoot: string;
67
+ /** Project root to resolve project conventions / IDE rules & skills (approval-era behaviour). */
68
+ projectRoot?: string;
69
+ }
70
+ /** Map a scene profile to the project-convention topics it should read (approval-era: 项目约定 > guidance > LLM). */
71
+ export declare function sceneTopics(profileId: string): string[];
72
+ export interface PlanStepsResult {
73
+ steps: AgentStep[];
74
+ chapters: string[];
75
+ }
76
+ /** Emit the Agent-executable step list (no LLM call — the Agent's IDE model does the work). */
77
+ export declare function planSteps(options: PlanStepsInput): PlanStepsResult;
78
+ export interface ValidateWorkInput {
79
+ profile: ScenarioProfile;
80
+ library: Map<string, ChapterComponent>;
81
+ workRoot: string;
82
+ renderHtmlOutput?: boolean;
83
+ }
84
+ export interface ValidateWorkResult {
85
+ ok: boolean;
86
+ diagnostics: GateDiagnostic[];
87
+ documentMd?: string;
88
+ documentHtml?: string;
89
+ }
90
+ /** Read Agent-written artifacts from workRoot, validate (lint/coverage/zod) and render. No LLM. */
91
+ export declare function validateWork(options: ValidateWorkInput): Promise<ValidateWorkResult>;
92
+ export { expandProfile };