@filmwhisper/mcp-server 0.1.0

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 (126) hide show
  1. package/LICENSE +21 -0
  2. package/dist/__tests__/data-integrity.test.d.ts +2 -0
  3. package/dist/__tests__/data-integrity.test.d.ts.map +1 -0
  4. package/dist/__tests__/data-integrity.test.js +171 -0
  5. package/dist/__tests__/data-integrity.test.js.map +1 -0
  6. package/dist/__tests__/engine/ipc-contract.test.d.ts +2 -0
  7. package/dist/__tests__/engine/ipc-contract.test.d.ts.map +1 -0
  8. package/dist/__tests__/engine/ipc-contract.test.js +122 -0
  9. package/dist/__tests__/engine/ipc-contract.test.js.map +1 -0
  10. package/dist/__tests__/fw-project-init.test.d.ts +2 -0
  11. package/dist/__tests__/fw-project-init.test.d.ts.map +1 -0
  12. package/dist/__tests__/fw-project-init.test.js +96 -0
  13. package/dist/__tests__/fw-project-init.test.js.map +1 -0
  14. package/dist/__tests__/helpers/mock-engine.d.ts +2 -0
  15. package/dist/__tests__/helpers/mock-engine.d.ts.map +1 -0
  16. package/dist/__tests__/helpers/mock-engine.js +81 -0
  17. package/dist/__tests__/helpers/mock-engine.js.map +1 -0
  18. package/dist/__tests__/r1-quality.test.d.ts +2 -0
  19. package/dist/__tests__/r1-quality.test.d.ts.map +1 -0
  20. package/dist/__tests__/r1-quality.test.js +539 -0
  21. package/dist/__tests__/r1-quality.test.js.map +1 -0
  22. package/dist/__tests__/search-fts5.test.d.ts +2 -0
  23. package/dist/__tests__/search-fts5.test.d.ts.map +1 -0
  24. package/dist/__tests__/search-fts5.test.js +135 -0
  25. package/dist/__tests__/search-fts5.test.js.map +1 -0
  26. package/dist/__tests__/tools/assemble.test.d.ts +2 -0
  27. package/dist/__tests__/tools/assemble.test.d.ts.map +1 -0
  28. package/dist/__tests__/tools/assemble.test.js +203 -0
  29. package/dist/__tests__/tools/assemble.test.js.map +1 -0
  30. package/dist/__tests__/tools/export.test.d.ts +2 -0
  31. package/dist/__tests__/tools/export.test.d.ts.map +1 -0
  32. package/dist/__tests__/tools/export.test.js +126 -0
  33. package/dist/__tests__/tools/export.test.js.map +1 -0
  34. package/dist/__tests__/tools/integration.test.d.ts +2 -0
  35. package/dist/__tests__/tools/integration.test.d.ts.map +1 -0
  36. package/dist/__tests__/tools/integration.test.js +707 -0
  37. package/dist/__tests__/tools/integration.test.js.map +1 -0
  38. package/dist/__tests__/tools/relink.test.d.ts +2 -0
  39. package/dist/__tests__/tools/relink.test.d.ts.map +1 -0
  40. package/dist/__tests__/tools/relink.test.js +107 -0
  41. package/dist/__tests__/tools/relink.test.js.map +1 -0
  42. package/dist/__tests__/tools/render-preview.test.d.ts +2 -0
  43. package/dist/__tests__/tools/render-preview.test.d.ts.map +1 -0
  44. package/dist/__tests__/tools/render-preview.test.js +99 -0
  45. package/dist/__tests__/tools/render-preview.test.js.map +1 -0
  46. package/dist/engine/engine-client.d.ts +29 -0
  47. package/dist/engine/engine-client.d.ts.map +1 -0
  48. package/dist/engine/engine-client.js +211 -0
  49. package/dist/engine/engine-client.js.map +1 -0
  50. package/dist/engine/engine-manager.d.ts +31 -0
  51. package/dist/engine/engine-manager.d.ts.map +1 -0
  52. package/dist/engine/engine-manager.js +144 -0
  53. package/dist/engine/engine-manager.js.map +1 -0
  54. package/dist/engine/types.d.ts +6 -0
  55. package/dist/engine/types.d.ts.map +1 -0
  56. package/dist/engine/types.js +2 -0
  57. package/dist/engine/types.js.map +1 -0
  58. package/dist/helpers/errors.d.ts +13 -0
  59. package/dist/helpers/errors.d.ts.map +1 -0
  60. package/dist/helpers/errors.js +14 -0
  61. package/dist/helpers/errors.js.map +1 -0
  62. package/dist/helpers/media-extensions.d.ts +8 -0
  63. package/dist/helpers/media-extensions.d.ts.map +1 -0
  64. package/dist/helpers/media-extensions.js +39 -0
  65. package/dist/helpers/media-extensions.js.map +1 -0
  66. package/dist/helpers/undo.d.ts +55 -0
  67. package/dist/helpers/undo.d.ts.map +1 -0
  68. package/dist/helpers/undo.js +142 -0
  69. package/dist/helpers/undo.js.map +1 -0
  70. package/dist/index.d.ts +7 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +108 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/prompts.d.ts +6 -0
  75. package/dist/prompts.d.ts.map +1 -0
  76. package/dist/prompts.js +62 -0
  77. package/dist/prompts.js.map +1 -0
  78. package/dist/resources.d.ts +7 -0
  79. package/dist/resources.d.ts.map +1 -0
  80. package/dist/resources.js +59 -0
  81. package/dist/resources.js.map +1 -0
  82. package/dist/server.d.ts +19 -0
  83. package/dist/server.d.ts.map +1 -0
  84. package/dist/server.js +33 -0
  85. package/dist/server.js.map +1 -0
  86. package/dist/storage/project-store.d.ts +92 -0
  87. package/dist/storage/project-store.d.ts.map +1 -0
  88. package/dist/storage/project-store.js +399 -0
  89. package/dist/storage/project-store.js.map +1 -0
  90. package/dist/storage/sqlite-store.d.ts +207 -0
  91. package/dist/storage/sqlite-store.d.ts.map +1 -0
  92. package/dist/storage/sqlite-store.js +983 -0
  93. package/dist/storage/sqlite-store.js.map +1 -0
  94. package/dist/tools/assemble.d.ts +17 -0
  95. package/dist/tools/assemble.d.ts.map +1 -0
  96. package/dist/tools/assemble.js +237 -0
  97. package/dist/tools/assemble.js.map +1 -0
  98. package/dist/tools/edit.d.ts +7 -0
  99. package/dist/tools/edit.d.ts.map +1 -0
  100. package/dist/tools/edit.js +159 -0
  101. package/dist/tools/edit.js.map +1 -0
  102. package/dist/tools/export.d.ts +7 -0
  103. package/dist/tools/export.d.ts.map +1 -0
  104. package/dist/tools/export.js +108 -0
  105. package/dist/tools/export.js.map +1 -0
  106. package/dist/tools/inspect.d.ts +7 -0
  107. package/dist/tools/inspect.d.ts.map +1 -0
  108. package/dist/tools/inspect.js +238 -0
  109. package/dist/tools/inspect.js.map +1 -0
  110. package/dist/tools/process.d.ts +7 -0
  111. package/dist/tools/process.d.ts.map +1 -0
  112. package/dist/tools/process.js +211 -0
  113. package/dist/tools/process.js.map +1 -0
  114. package/dist/tools/project.d.ts +7 -0
  115. package/dist/tools/project.d.ts.map +1 -0
  116. package/dist/tools/project.js +178 -0
  117. package/dist/tools/project.js.map +1 -0
  118. package/dist/tools/search.d.ts +7 -0
  119. package/dist/tools/search.d.ts.map +1 -0
  120. package/dist/tools/search.js +75 -0
  121. package/dist/tools/search.js.map +1 -0
  122. package/dist/tools/utility.d.ts +7 -0
  123. package/dist/tools/utility.d.ts.map +1 -0
  124. package/dist/tools/utility.js +108 -0
  125. package/dist/tools/utility.js.map +1 -0
  126. package/package.json +40 -0
@@ -0,0 +1,539 @@
1
+ /**
2
+ * R1 Quality Verification Test — fw_auto_assemble
3
+ *
4
+ * Comprehensive tests using synthetic segments and a style-aware mock engine.
5
+ * Tests all 4 styles (documentary/highlight/story/montage), editorial ranking,
6
+ * duration trimming, and gap_fill strategy.
7
+ *
8
+ * R1 Metrics:
9
+ * - Duration Error ≤ 10%: |total_duration_ms - target| / target ≤ 0.10
10
+ * - Rationale Coverage = 100%: every clip has editorial_rationale
11
+ * - Clips ≥ 1: at least one clip in the assembled timeline
12
+ * - Style Differentiation: different styles produce different rankings
13
+ */
14
+ import { describe, it, expect, beforeAll, afterAll } from "vitest";
15
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
16
+ import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
17
+ import * as fs from "node:fs/promises";
18
+ import * as os from "node:os";
19
+ import * as path from "node:path";
20
+ import { createServer } from "../server.js";
21
+ import { ProjectStore, atomicWrite } from "../storage/project-store.js";
22
+ // ─────────────────────────────────────────────────────────────
23
+ // Style-aware Mock Engine
24
+ // ─────────────────────────────────────────────────────────────
25
+ function createStyleAwareMockEngine() {
26
+ const STYLE_WEIGHTS = {
27
+ documentary: {
28
+ energy_w: 0.2, story_w: 0.8,
29
+ role_bonus: { interview: 0.3, "b-roll": 0.0, narration: 0.2, montage: -0.1 },
30
+ },
31
+ highlight: {
32
+ energy_w: 0.8, story_w: 0.2,
33
+ role_bonus: { interview: -0.1, "b-roll": 0.2, montage: 0.3, narration: -0.2 },
34
+ },
35
+ story: {
36
+ energy_w: 0.4, story_w: 0.6,
37
+ role_bonus: { interview: 0.2, "b-roll": 0.1, narration: 0.15, montage: 0.0 },
38
+ },
39
+ montage: {
40
+ energy_w: 0.6, story_w: 0.1,
41
+ role_bonus: { interview: -0.2, "b-roll": 0.3, montage: 0.4, narration: -0.3 },
42
+ },
43
+ };
44
+ return {
45
+ async request(method, params, _timeout) {
46
+ switch (method) {
47
+ case "editorial_rank": {
48
+ const p = params;
49
+ const weights = STYLE_WEIGHTS[p.style] ?? STYLE_WEIGHTS.story;
50
+ const scored = p.segments.map((s) => {
51
+ const roleBonus = weights.role_bonus[s.editorial_role] ?? 0;
52
+ const score = Math.max(0, Math.min(1, weights.energy_w * s.energy + weights.story_w * s.story_value + roleBonus));
53
+ return {
54
+ asset_hash: s.asset_hash, segment_index: s.segment_index, score,
55
+ role: s.editorial_role,
56
+ selection_reason: `${p.style}: energy=${s.energy.toFixed(2)}, story=${s.story_value.toFixed(2)}, role_bonus=${roleBonus.toFixed(2)}`,
57
+ };
58
+ });
59
+ scored.sort((a, b) => b.score - a.score);
60
+ return { ranked_clips: scored };
61
+ }
62
+ case "duration_trim": {
63
+ const p = params;
64
+ const targetMs = p.target_duration_seconds * 1000;
65
+ let accMs = 0;
66
+ const trimmed = [];
67
+ for (const clip of p.clips) {
68
+ const dur = clip.end_ms - clip.start_ms;
69
+ const remaining = targetMs - accMs;
70
+ if (remaining <= 0)
71
+ break;
72
+ if (accMs + dur <= targetMs) {
73
+ trimmed.push({ asset_hash: clip.asset_hash, segment_index: clip.segment_index, in_point_ms: clip.start_ms, out_point_ms: clip.end_ms, trimmed: false });
74
+ accMs += dur;
75
+ }
76
+ else {
77
+ const end = clip.start_ms + remaining;
78
+ trimmed.push({ asset_hash: clip.asset_hash, segment_index: clip.segment_index, in_point_ms: clip.start_ms, out_point_ms: end, trimmed: true });
79
+ accMs += remaining;
80
+ }
81
+ }
82
+ return {
83
+ trimmed_clips: trimmed, total_duration_ms: accMs,
84
+ rationale: trimmed.map((c, i) => ({
85
+ clip_index: i, role: "segment",
86
+ selection_reason: c.trimmed ? "trimmed to fit target duration" : "included at full length",
87
+ })),
88
+ };
89
+ }
90
+ case "gap_fill": {
91
+ const p = params;
92
+ const targetMs = p.target_duration_seconds * 1000;
93
+ const bbDur = p.backbone_clips.reduce((s, c) => s + (c.end_ms - c.start_ms), 0);
94
+ const filled = p.backbone_clips.map((c) => ({
95
+ asset_hash: c.asset_hash, segment_index: c.segment_index,
96
+ in_point_ms: c.start_ms, out_point_ms: c.end_ms, is_gap_fill: false,
97
+ }));
98
+ let gap = targetMs - bbDur;
99
+ if (gap > 0) {
100
+ for (const cand of p.candidate_segments) {
101
+ if (gap <= 0)
102
+ break;
103
+ const d = Math.min(cand.end_ms - cand.start_ms, gap);
104
+ filled.push({
105
+ asset_hash: cand.asset_hash, segment_index: cand.segment_index,
106
+ in_point_ms: cand.start_ms, out_point_ms: cand.start_ms + d,
107
+ is_gap_fill: true, gap_strategy: "context",
108
+ });
109
+ gap -= d;
110
+ }
111
+ }
112
+ const totalMs = filled.reduce((s, c) => s + (c.out_point_ms - c.in_point_ms), 0);
113
+ return {
114
+ filled_clips: filled, total_duration_ms: totalMs,
115
+ rationale: filled.map((c, i) => ({
116
+ clip_index: i, role: c.is_gap_fill ? "gap-fill" : "backbone",
117
+ selection_reason: c.is_gap_fill ? `gap fill (${c.gap_strategy})` : "backbone clip retained",
118
+ speaker_continuity: !c.is_gap_fill, gap_strategy: c.gap_strategy,
119
+ })),
120
+ };
121
+ }
122
+ case "export":
123
+ return { output_path: params.output_path };
124
+ default:
125
+ throw new Error(`Mock: unknown method ${method}`);
126
+ }
127
+ },
128
+ async ensureRunning() { },
129
+ get isRunning() { return true; },
130
+ async shutdown() { },
131
+ };
132
+ }
133
+ // ─────────────────────────────────────────────────────────────
134
+ // Segment definitions (used after we discover real asset hashes)
135
+ // ─────────────────────────────────────────────────────────────
136
+ /** Segments keyed by file index (0=interview, 1=broll, 2=detail) */
137
+ const SEGMENT_DEFS = [
138
+ // Asset 0: interview-heavy, high story value
139
+ [
140
+ { segment_index: 0, start_ms: 0, end_ms: 8000, editorial_role: "interview", energy: 0.3, story_value: 0.9, summary: "Subject introduces the main topic" },
141
+ { segment_index: 1, start_ms: 8000, end_ms: 16000, editorial_role: "interview", energy: 0.5, story_value: 0.85, summary: "Key revelation about the central conflict" },
142
+ { segment_index: 2, start_ms: 16000, end_ms: 24000, editorial_role: "narration", energy: 0.2, story_value: 0.7, summary: "Narrator provides historical context" },
143
+ { segment_index: 3, start_ms: 24000, end_ms: 30000, editorial_role: "interview", energy: 0.4, story_value: 0.6, summary: "Subject reflects on personal impact" },
144
+ ],
145
+ // Asset 1: b-roll/montage-heavy, high energy
146
+ [
147
+ { segment_index: 0, start_ms: 0, end_ms: 10000, editorial_role: "b-roll", energy: 0.7, story_value: 0.3, summary: "Dynamic cityscape aerial shot" },
148
+ { segment_index: 1, start_ms: 10000, end_ms: 25000, editorial_role: "b-roll", energy: 0.9, story_value: 0.2, summary: "Fast-paced montage of urban activity" },
149
+ { segment_index: 2, start_ms: 25000, end_ms: 40000, editorial_role: "montage", energy: 0.95, story_value: 0.15, summary: "High-energy action sequence" },
150
+ { segment_index: 3, start_ms: 40000, end_ms: 50000, editorial_role: "b-roll", energy: 0.6, story_value: 0.4, summary: "Sunset transition" },
151
+ { segment_index: 4, start_ms: 50000, end_ms: 60000, editorial_role: "montage", energy: 0.85, story_value: 0.1, summary: "Night city lights timelapse" },
152
+ ],
153
+ // Asset 2: mixed
154
+ [
155
+ { segment_index: 0, start_ms: 0, end_ms: 10000, editorial_role: "b-roll", energy: 0.4, story_value: 0.5, summary: "Close-up of artifact" },
156
+ { segment_index: 1, start_ms: 10000, end_ms: 20000, editorial_role: "interview", energy: 0.6, story_value: 0.75, summary: "Expert explains significance" },
157
+ { segment_index: 2, start_ms: 20000, end_ms: 30000, editorial_role: "narration", energy: 0.3, story_value: 0.65, summary: "Concluding narration" },
158
+ ],
159
+ ];
160
+ const FILE_CONTENTS = [
161
+ "fake-video-interview-main-content",
162
+ "fake-video-broll-cityscape-content",
163
+ "fake-video-closeup-details-content",
164
+ ];
165
+ const FILE_NAMES = [
166
+ "interview-main.mp4",
167
+ "broll-cityscape.mp4",
168
+ "closeup-details.mp4",
169
+ ];
170
+ // ─────────────────────────────────────────────────────────────
171
+ // Helpers
172
+ // ─────────────────────────────────────────────────────────────
173
+ function parseResult(result) {
174
+ const r = result;
175
+ return JSON.parse(r.content[0].text);
176
+ }
177
+ const ALL_STYLES = ["documentary", "highlight", "story", "montage"];
178
+ const TARGET_DURATION_S = 30;
179
+ const DURATION_ERROR_THRESHOLD = 0.10;
180
+ // ─────────────────────────────────────────────────────────────
181
+ // Tests: Synthetic R1 Quality (CI-friendly, no Python engine)
182
+ // ─────────────────────────────────────────────────────────────
183
+ describe("R1 Quality: fw_auto_assemble with synthetic segments", () => {
184
+ let client;
185
+ let server;
186
+ let deps;
187
+ let tmpDir;
188
+ let projectId;
189
+ let assetHashes; // real hashes discovered after init
190
+ beforeAll(async () => {
191
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "fw-r1-synthetic-"));
192
+ for (let i = 0; i < FILE_NAMES.length; i++) {
193
+ await fs.writeFile(path.join(tmpDir, FILE_NAMES[i]), FILE_CONTENTS[i]);
194
+ }
195
+ deps = {
196
+ projectStore: new ProjectStore(),
197
+ projects: new Map(),
198
+ engineManager: createStyleAwareMockEngine(),
199
+ };
200
+ server = createServer(deps);
201
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
202
+ await server.connect(serverTransport);
203
+ client = new Client({ name: "r1-synthetic-client", version: "1.0.0" });
204
+ await client.connect(clientTransport);
205
+ // 1. Initialize project
206
+ const initResult = await client.callTool({
207
+ name: "fw_project_init",
208
+ arguments: { name: "R1 Synthetic Quality Test", source_path: tmpDir },
209
+ });
210
+ expect(initResult.isError).toBeFalsy();
211
+ const initData = parseResult(initResult);
212
+ projectId = initData.project_id;
213
+ const ctx = deps.projects.get(projectId);
214
+ // 2. Discover real asset hashes
215
+ const listResult = await client.callTool({
216
+ name: "fw_list_assets",
217
+ arguments: { project_id: projectId },
218
+ });
219
+ const { assets } = parseResult(listResult);
220
+ // Map hashes back to our file order by matching filename
221
+ assetHashes = FILE_NAMES.map((name) => {
222
+ const found = assets.find((a) => a.filename === name);
223
+ if (!found)
224
+ throw new Error(`Asset not found for ${name}`);
225
+ return found.asset_hash;
226
+ });
227
+ // 3. Write segments directly into asset JSON files (like assemble.test.ts pattern)
228
+ for (let i = 0; i < assetHashes.length; i++) {
229
+ const hash = assetHashes[i];
230
+ const assetFilePath = path.join(ctx.projectPath, ".fw", "assets", `${hash}.fw.json`);
231
+ const rawAsset = JSON.parse(await fs.readFile(assetFilePath, "utf-8"));
232
+ rawAsset.analysis = {
233
+ ...rawAsset.analysis,
234
+ segments: SEGMENT_DEFS[i],
235
+ };
236
+ await atomicWrite(assetFilePath, JSON.stringify(rawAsset, null, 2));
237
+ }
238
+ // 4. Call fw_set_analysis to populate FTS5
239
+ const analyses = assetHashes.map((hash, i) => ({
240
+ asset_id: hash,
241
+ analysis: {
242
+ subject: FILE_NAMES[i].replace(".mp4", ""),
243
+ editorial_role: SEGMENT_DEFS[i][0].editorial_role,
244
+ energy: 5,
245
+ shot_type: "medium",
246
+ story_value: 7,
247
+ summary: `Synthetic asset: ${FILE_NAMES[i]}`,
248
+ },
249
+ segments: SEGMENT_DEFS[i],
250
+ }));
251
+ const setResult = await client.callTool({
252
+ name: "fw_set_analysis",
253
+ arguments: { project_id: projectId, analyses },
254
+ });
255
+ expect(setResult.isError).toBeFalsy();
256
+ }, 30_000);
257
+ afterAll(async () => {
258
+ await client?.close();
259
+ await server?.close();
260
+ for (const ctx of deps.projects.values()) {
261
+ try {
262
+ ctx.sqliteStore.close();
263
+ }
264
+ catch { /* cleanup */ }
265
+ }
266
+ await fs.rm(tmpDir, { recursive: true, force: true });
267
+ });
268
+ // ── R1-1: Basic assembly produces clips ──────────────────
269
+ it("R1-1: fw_auto_assemble returns at least 1 clip for each style", async () => {
270
+ for (const style of ALL_STYLES) {
271
+ const result = await client.callTool({
272
+ name: "fw_auto_assemble",
273
+ arguments: { project_id: projectId, mode: "auto", style, target_duration_seconds: TARGET_DURATION_S },
274
+ });
275
+ expect(result.isError, `${style} should not error`).toBeFalsy();
276
+ const data = parseResult(result);
277
+ expect(data.clips.length, `${style} should have ≥ 1 clip`).toBeGreaterThanOrEqual(1);
278
+ }
279
+ });
280
+ // ── R1-2: Duration error ≤ 10% ──────────────────────────
281
+ it("R1-2: Duration Error ≤ 10% for all styles", async () => {
282
+ const targetMs = TARGET_DURATION_S * 1000;
283
+ for (const style of ALL_STYLES) {
284
+ const result = await client.callTool({
285
+ name: "fw_auto_assemble",
286
+ arguments: { project_id: projectId, mode: "auto", style, target_duration_seconds: TARGET_DURATION_S },
287
+ });
288
+ expect(result.isError).toBeFalsy();
289
+ const data = parseResult(result);
290
+ const durationError = Math.abs(data.total_duration_ms - targetMs) / targetMs;
291
+ expect(durationError, `${style}: duration error ${(durationError * 100).toFixed(1)}% (actual=${data.total_duration_ms}ms, target=${targetMs}ms)`).toBeLessThanOrEqual(DURATION_ERROR_THRESHOLD);
292
+ }
293
+ });
294
+ // ── R1-3: Rationale coverage = 100% ─────────────────────
295
+ it("R1-3: every clip has editorial_rationale with selection_reason", async () => {
296
+ for (const style of ALL_STYLES) {
297
+ const result = await client.callTool({
298
+ name: "fw_auto_assemble",
299
+ arguments: { project_id: projectId, mode: "auto", style, target_duration_seconds: TARGET_DURATION_S },
300
+ });
301
+ expect(result.isError).toBeFalsy();
302
+ const data = parseResult(result);
303
+ const clipCount = data.clips?.length ?? 0;
304
+ const rationaleCount = data.editorial_rationale?.length ?? 0;
305
+ expect(clipCount, `${style}: should have clips`).toBeGreaterThanOrEqual(1);
306
+ expect(rationaleCount, `${style}: rationale count should match clip count`).toBe(clipCount);
307
+ for (const r of data.editorial_rationale ?? []) {
308
+ expect(r.selection_reason, `${style}: each rationale must have selection_reason`).toBeTruthy();
309
+ }
310
+ }
311
+ });
312
+ // ── R1-4: Style differentiation ─────────────────────────
313
+ it("R1-4: different styles produce different ranking orders", async () => {
314
+ const clipsByStyle = {};
315
+ for (const style of ALL_STYLES) {
316
+ const result = await client.callTool({
317
+ name: "fw_auto_assemble",
318
+ arguments: { project_id: projectId, mode: "auto", style, target_duration_seconds: 120 },
319
+ });
320
+ expect(result.isError).toBeFalsy();
321
+ const data = parseResult(result);
322
+ clipsByStyle[style] = data.clips.map((c) => `${c.asset_hash}:${c.clip_index}`);
323
+ }
324
+ // documentary (story-heavy) should differ from highlight (energy-heavy)
325
+ expect(JSON.stringify(clipsByStyle.documentary), "documentary and highlight should produce different orderings").not.toBe(JSON.stringify(clipsByStyle.highlight));
326
+ // montage should differ from documentary
327
+ expect(JSON.stringify(clipsByStyle.documentary), "documentary and montage should produce different orderings").not.toBe(JSON.stringify(clipsByStyle.montage));
328
+ });
329
+ // ── R1-5: Duration trim does not exceed target ──────────
330
+ it("R1-5: trimmed clips do not exceed target duration", async () => {
331
+ for (const style of ALL_STYLES) {
332
+ const result = await client.callTool({
333
+ name: "fw_auto_assemble",
334
+ arguments: { project_id: projectId, mode: "auto", style, target_duration_seconds: TARGET_DURATION_S },
335
+ });
336
+ expect(result.isError).toBeFalsy();
337
+ const data = parseResult(result);
338
+ const totalMs = data.clips.reduce((sum, c) => sum + (c.out_point_ms - c.in_point_ms), 0);
339
+ const maxAllowed = TARGET_DURATION_S * 1000 * (1 + DURATION_ERROR_THRESHOLD);
340
+ expect(totalMs, `${style}: total ${totalMs}ms should not exceed ${maxAllowed}ms`).toBeLessThanOrEqual(maxAllowed);
341
+ }
342
+ });
343
+ // ── R1-6: Clip in/out points are valid ──────────────────
344
+ it("R1-6: all clips have valid in/out points (in < out, non-negative)", async () => {
345
+ for (const style of ALL_STYLES) {
346
+ const result = await client.callTool({
347
+ name: "fw_auto_assemble",
348
+ arguments: { project_id: projectId, mode: "auto", style, target_duration_seconds: TARGET_DURATION_S },
349
+ });
350
+ expect(result.isError).toBeFalsy();
351
+ const data = parseResult(result);
352
+ for (const clip of data.clips) {
353
+ expect(clip.in_point_ms).toBeGreaterThanOrEqual(0);
354
+ expect(clip.out_point_ms).toBeGreaterThan(clip.in_point_ms);
355
+ }
356
+ }
357
+ });
358
+ // ── R1-7: Revision tracking ─────────────────────────────
359
+ it("R1-7: assembly returns a valid revision number", async () => {
360
+ const result = await client.callTool({
361
+ name: "fw_auto_assemble",
362
+ arguments: { project_id: projectId, mode: "auto", style: "story", target_duration_seconds: TARGET_DURATION_S },
363
+ });
364
+ expect(result.isError).toBeFalsy();
365
+ const data = parseResult(result);
366
+ expect(data.revision).toBeDefined();
367
+ expect(typeof data.revision).toBe("number");
368
+ expect(data.revision).toBeGreaterThanOrEqual(1);
369
+ });
370
+ // ── R1-8: Documentary prefers high story_value ──────────
371
+ it("R1-8: documentary style ranks interview/high-story segments in top half", async () => {
372
+ const result = await client.callTool({
373
+ name: "fw_auto_assemble",
374
+ arguments: { project_id: projectId, mode: "auto", style: "documentary", target_duration_seconds: 120 },
375
+ });
376
+ expect(result.isError).toBeFalsy();
377
+ const data = parseResult(result);
378
+ // Top half of clips should be dominated by interview-heavy assets (asset 0 and 2)
379
+ // not by the b-roll/montage asset (asset 1)
380
+ const topHalf = data.clips.slice(0, Math.ceil(data.clips.length / 2));
381
+ const interviewAssetHashes = new Set([assetHashes[0], assetHashes[2]]);
382
+ const interviewCount = topHalf.filter((c) => interviewAssetHashes.has(c.asset_hash)).length;
383
+ expect(interviewCount, "documentary top half should be mostly interview assets").toBeGreaterThan(topHalf.length / 2);
384
+ });
385
+ // ── R1-9: Highlight prefers high energy ─────────────────
386
+ it("R1-9: highlight style ranks high-energy segments first", async () => {
387
+ const result = await client.callTool({
388
+ name: "fw_auto_assemble",
389
+ arguments: { project_id: projectId, mode: "auto", style: "highlight", target_duration_seconds: 120 },
390
+ });
391
+ expect(result.isError).toBeFalsy();
392
+ const data = parseResult(result);
393
+ // First clip should be from the b-roll/montage asset (highest energy)
394
+ const firstClip = data.clips[0];
395
+ expect(firstClip).toBeDefined();
396
+ expect(firstClip.asset_hash).toBe(assetHashes[1]); // broll-cityscape
397
+ });
398
+ // ── R1-10: Target duration variety ──────────────────────
399
+ it("R1-10: longer target produces more total duration", async () => {
400
+ const shortResult = await client.callTool({
401
+ name: "fw_auto_assemble",
402
+ arguments: { project_id: projectId, mode: "auto", style: "story", target_duration_seconds: 10 },
403
+ });
404
+ expect(shortResult.isError).toBeFalsy();
405
+ const shortData = parseResult(shortResult);
406
+ const longResult = await client.callTool({
407
+ name: "fw_auto_assemble",
408
+ arguments: { project_id: projectId, mode: "auto", style: "story", target_duration_seconds: 60 },
409
+ });
410
+ expect(longResult.isError).toBeFalsy();
411
+ const longData = parseResult(longResult);
412
+ expect(shortData.clips.length).toBeGreaterThanOrEqual(1);
413
+ expect(longData.clips.length).toBeGreaterThanOrEqual(shortData.clips.length);
414
+ expect(longData.total_duration_ms).toBeGreaterThan(shortData.total_duration_ms);
415
+ });
416
+ });
417
+ // ─────────────────────────────────────────────────────────────
418
+ // Tests: Guided mode (gap_fill) and Reviewed mode
419
+ // ─────────────────────────────────────────────────────────────
420
+ describe("R1 Quality: guided and reviewed modes", () => {
421
+ let client;
422
+ let server;
423
+ let deps;
424
+ let tmpDir;
425
+ let projectId;
426
+ let assetHashes;
427
+ beforeAll(async () => {
428
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "fw-r1-guided-"));
429
+ for (let i = 0; i < FILE_NAMES.length; i++) {
430
+ await fs.writeFile(path.join(tmpDir, FILE_NAMES[i]), FILE_CONTENTS[i]);
431
+ }
432
+ deps = {
433
+ projectStore: new ProjectStore(),
434
+ projects: new Map(),
435
+ engineManager: createStyleAwareMockEngine(),
436
+ };
437
+ server = createServer(deps);
438
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
439
+ await server.connect(serverTransport);
440
+ client = new Client({ name: "r1-guided-client", version: "1.0.0" });
441
+ await client.connect(clientTransport);
442
+ // Init project
443
+ const initResult = await client.callTool({
444
+ name: "fw_project_init",
445
+ arguments: { name: "R1 Guided Test", source_path: tmpDir },
446
+ });
447
+ const initData = parseResult(initResult);
448
+ projectId = initData.project_id;
449
+ const ctx = deps.projects.get(projectId);
450
+ // Discover real hashes
451
+ const listResult = await client.callTool({
452
+ name: "fw_list_assets",
453
+ arguments: { project_id: projectId },
454
+ });
455
+ const { assets } = parseResult(listResult);
456
+ assetHashes = FILE_NAMES.map((name) => {
457
+ const found = assets.find((a) => a.filename === name);
458
+ if (!found)
459
+ throw new Error(`Asset not found for ${name}`);
460
+ return found.asset_hash;
461
+ });
462
+ // Write segments into asset JSON
463
+ for (let i = 0; i < assetHashes.length; i++) {
464
+ const hash = assetHashes[i];
465
+ const assetFilePath = path.join(ctx.projectPath, ".fw", "assets", `${hash}.fw.json`);
466
+ const rawAsset = JSON.parse(await fs.readFile(assetFilePath, "utf-8"));
467
+ rawAsset.analysis = { ...rawAsset.analysis, segments: SEGMENT_DEFS[i] };
468
+ await atomicWrite(assetFilePath, JSON.stringify(rawAsset, null, 2));
469
+ }
470
+ // Populate FTS5
471
+ const analyses = assetHashes.map((hash, i) => ({
472
+ asset_id: hash,
473
+ analysis: {
474
+ subject: FILE_NAMES[i].replace(".mp4", ""),
475
+ editorial_role: SEGMENT_DEFS[i][0].editorial_role,
476
+ energy: 5, shot_type: "medium", story_value: 7,
477
+ summary: `Synthetic asset: ${FILE_NAMES[i]}`,
478
+ },
479
+ segments: SEGMENT_DEFS[i],
480
+ }));
481
+ await client.callTool({
482
+ name: "fw_set_analysis",
483
+ arguments: { project_id: projectId, analyses },
484
+ });
485
+ // Mark some segments as kept
486
+ for (const review of [
487
+ { asset_hash: assetHashes[0], segment_index: 0, status: "keep" },
488
+ { asset_hash: assetHashes[0], segment_index: 1, status: "keep" },
489
+ { asset_hash: assetHashes[2], segment_index: 1, status: "keep" },
490
+ ]) {
491
+ await client.callTool({
492
+ name: "fw_review_set",
493
+ arguments: { project_id: projectId, ...review, reviewer: "test" },
494
+ });
495
+ }
496
+ }, 30_000);
497
+ afterAll(async () => {
498
+ await client?.close();
499
+ await server?.close();
500
+ for (const ctx of deps.projects.values()) {
501
+ try {
502
+ ctx.sqliteStore.close();
503
+ }
504
+ catch { /* cleanup */ }
505
+ }
506
+ await fs.rm(tmpDir, { recursive: true, force: true });
507
+ });
508
+ it("guided mode uses backbone + gap fill", async () => {
509
+ const result = await client.callTool({
510
+ name: "fw_auto_assemble",
511
+ arguments: { project_id: projectId, mode: "guided", style: "story", target_duration_seconds: 60 },
512
+ });
513
+ expect(result.isError).toBeFalsy();
514
+ const data = parseResult(result);
515
+ expect(data.clips.length).toBeGreaterThanOrEqual(3);
516
+ expect(data.editorial_rationale.length).toBe(data.clips.length);
517
+ const roles = data.editorial_rationale.map((r) => r.role);
518
+ expect(roles).toContain("backbone");
519
+ });
520
+ it("reviewed mode uses only kept segments", async () => {
521
+ const result = await client.callTool({
522
+ name: "fw_auto_assemble",
523
+ arguments: { project_id: projectId, mode: "reviewed", style: "story", target_duration_seconds: 60 },
524
+ });
525
+ expect(result.isError).toBeFalsy();
526
+ const data = parseResult(result);
527
+ expect(data.clips.length).toBeLessThanOrEqual(3);
528
+ expect(data.clips.length).toBeGreaterThanOrEqual(1);
529
+ });
530
+ });
531
+ // ─────────────────────────────────────────────────────────────
532
+ // Legacy: R1 with real video files (manual only)
533
+ // ─────────────────────────────────────────────────────────────
534
+ describe.skip("R1 Quality: fw_auto_assemble with real video files", () => {
535
+ it("placeholder for manual testing", () => {
536
+ expect(true).toBe(true);
537
+ });
538
+ });
539
+ //# sourceMappingURL=r1-quality.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r1-quality.test.js","sourceRoot":"","sources":["../../src/__tests__/r1-quality.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=search-fts5.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-fts5.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/search-fts5.test.ts"],"names":[],"mappings":""}