gooseworks 0.4.2 → 0.4.4

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 (84) hide show
  1. package/README.md +42 -11
  2. package/dist/commands/doctor.d.ts +29 -5
  3. package/dist/commands/doctor.d.ts.map +1 -1
  4. package/dist/commands/doctor.js +107 -63
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/fetch.d.ts +1 -0
  7. package/dist/commands/fetch.d.ts.map +1 -1
  8. package/dist/commands/fetch.js +64 -29
  9. package/dist/commands/fetch.js.map +1 -1
  10. package/dist/commands/install.d.ts.map +1 -1
  11. package/dist/commands/install.js +37 -4
  12. package/dist/commands/install.js.map +1 -1
  13. package/dist/commands/login.d.ts.map +1 -1
  14. package/dist/commands/login.js +8 -3
  15. package/dist/commands/login.js.map +1 -1
  16. package/dist/commands/skills.d.ts +34 -0
  17. package/dist/commands/skills.d.ts.map +1 -0
  18. package/dist/commands/skills.js +109 -0
  19. package/dist/commands/skills.js.map +1 -0
  20. package/dist/commands/update.d.ts.map +1 -1
  21. package/dist/commands/update.js +17 -6
  22. package/dist/commands/update.js.map +1 -1
  23. package/dist/commands/video-local.d.ts +9 -0
  24. package/dist/commands/video-local.d.ts.map +1 -0
  25. package/dist/commands/video-local.js +83 -0
  26. package/dist/commands/video-local.js.map +1 -0
  27. package/dist/commands/video-save.d.ts +3 -0
  28. package/dist/commands/video-save.d.ts.map +1 -0
  29. package/dist/commands/video-save.js +83 -0
  30. package/dist/commands/video-save.js.map +1 -0
  31. package/dist/index.js +7 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/lib/video-local-captions.d.ts +83 -0
  34. package/dist/lib/video-local-captions.d.ts.map +1 -0
  35. package/dist/lib/video-local-captions.js +261 -0
  36. package/dist/lib/video-local-captions.js.map +1 -0
  37. package/dist/lib/video-local-runtime.d.ts +8 -0
  38. package/dist/lib/video-local-runtime.d.ts.map +1 -0
  39. package/dist/lib/video-local-runtime.js +201 -0
  40. package/dist/lib/video-local-runtime.js.map +1 -0
  41. package/dist/lib/video-save-mcp.d.ts +9 -0
  42. package/dist/lib/video-save-mcp.d.ts.map +1 -0
  43. package/dist/lib/video-save-mcp.js +162 -0
  44. package/dist/lib/video-save-mcp.js.map +1 -0
  45. package/dist/lib/video-save.d.ts +77 -0
  46. package/dist/lib/video-save.d.ts.map +1 -0
  47. package/dist/lib/video-save.js +440 -0
  48. package/dist/lib/video-save.js.map +1 -0
  49. package/dist/skills/custom-video-skill.d.ts +3 -0
  50. package/dist/skills/custom-video-skill.d.ts.map +1 -0
  51. package/dist/skills/custom-video-skill.js +6 -0
  52. package/dist/skills/custom-video-skill.js.map +1 -0
  53. package/dist/skills/installer.d.ts +12 -6
  54. package/dist/skills/installer.d.ts.map +1 -1
  55. package/dist/skills/installer.js +41 -15
  56. package/dist/skills/installer.js.map +1 -1
  57. package/dist/skills/master-skill.d.ts +22 -19
  58. package/dist/skills/master-skill.d.ts.map +1 -1
  59. package/dist/skills/master-skill.js +1472 -551
  60. package/dist/skills/master-skill.js.map +1 -1
  61. package/dist/skills/package-freshness.d.ts +16 -0
  62. package/dist/skills/package-freshness.d.ts.map +1 -0
  63. package/dist/skills/package-freshness.js +36 -0
  64. package/dist/skills/package-freshness.js.map +1 -0
  65. package/dist/skills/releases.d.ts +12 -0
  66. package/dist/skills/releases.d.ts.map +1 -0
  67. package/dist/skills/releases.js +152 -0
  68. package/dist/skills/releases.js.map +1 -0
  69. package/dist/skills/routes.d.ts.map +1 -1
  70. package/dist/skills/routes.js +7 -1
  71. package/dist/skills/routes.js.map +1 -1
  72. package/dist/utils/browser-preflight.d.ts +29 -0
  73. package/dist/utils/browser-preflight.d.ts.map +1 -0
  74. package/dist/utils/browser-preflight.js +338 -0
  75. package/dist/utils/browser-preflight.js.map +1 -0
  76. package/package.json +2 -2
  77. package/skills/goose-ads/SKILL.md +124 -16
  78. package/skills/goose-product-photos/SKILL.md +55 -3
  79. package/skills/goose-video/SKILL.md +322 -253
  80. package/skills/goose-video-local/SKILL.md +1199 -234
  81. package/skills/gooseworks/SKILL.md +199 -13
  82. package/skills/make-custom-video/SKILL.md +490 -0
  83. package/skills/manifest.json +12 -0
  84. package/skills/routes.json +8 -1
@@ -0,0 +1,440 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.digest = digest;
37
+ exports.writeCheckpoint = writeCheckpoint;
38
+ exports.loadCheckpoint = loadCheckpoint;
39
+ exports.prepareSave = prepareSave;
40
+ exports.resumeSave = resumeSave;
41
+ /** Finished-video recovery. No render-open, provider, or authentication operations. */
42
+ const crypto_1 = require("crypto");
43
+ const promises_1 = require("fs/promises");
44
+ const path = __importStar(require("path"));
45
+ const video_save_mcp_1 = require("./video-save-mcp");
46
+ const HASH = /^[a-f0-9]{64}$/;
47
+ const ID = /^[A-Za-z0-9_-]{1,160}$/;
48
+ const MAX_BYTES = 200 * 1024 * 1024;
49
+ const CHECKS = ['source', 'brand', 'product', 'hook_and_scene_order', 'voice_and_script',
50
+ 'captions', 'endcard_and_cta', 'duration_and_ratio', 'visual_artifacts'];
51
+ function fail(message) { throw new Error(message); }
52
+ function object(value) { return !!value && typeof value === 'object' && !Array.isArray(value); }
53
+ function keys(value, allowed) {
54
+ if (Object.keys(value).some(key => !allowed.includes(key)))
55
+ fail('Unexpected checkpoint or quality field');
56
+ }
57
+ function stable(value) {
58
+ if (Array.isArray(value))
59
+ return `[${value.map(stable).join(',')}]`;
60
+ if (object(value))
61
+ return `{${Object.keys(value).sort().map(k => `${JSON.stringify(k)}:${stable(value[k])}`).join(',')}}`;
62
+ return JSON.stringify(value);
63
+ }
64
+ function digest(value) { return (0, crypto_1.createHash)('sha256').update(stable(value)).digest('hex'); }
65
+ function sha(bytes) { return (0, crypto_1.createHash)('sha256').update(bytes).digest('hex'); }
66
+ function origin(value) {
67
+ if (typeof value !== 'string')
68
+ fail('Missing environment origin');
69
+ const url = new URL(value);
70
+ if (url.username || url.password || url.search || url.hash || url.pathname !== '/' ||
71
+ !['https:', 'http:'].includes(url.protocol))
72
+ fail('Invalid public environment origin');
73
+ if (url.protocol === 'http:' && !['127.0.0.1', 'localhost', '[::1]'].includes(url.hostname))
74
+ fail('Environment requires HTTPS');
75
+ return url.origin;
76
+ }
77
+ function identity(account) {
78
+ if (!object(account.environment) || !['production', 'staging', 'local'].includes(account.environment.name) ||
79
+ typeof account.user?.id !== 'string' || typeof account.organization?.id !== 'string' ||
80
+ !ID.test(account.user.id) || !ID.test(account.organization.id))
81
+ fail('Unknown account/environment; reconnect on the original connection');
82
+ return { environment: { name: account.environment.name, api_origin: origin(account.environment.api_origin) },
83
+ user_id: account.user.id, organization_id: account.organization.id };
84
+ }
85
+ function quality(report) {
86
+ if (!object(report))
87
+ fail('Missing quality report');
88
+ keys(report, ['version', 'summary', 'checks', 'detected_issues', 'repair_actions', 'checked_at']);
89
+ if (report.version !== 1 || typeof report.summary !== 'string' || !report.summary.trim() || report.summary.length > 2000 ||
90
+ !object(report.checks) || Object.keys(report.checks).length !== CHECKS.length)
91
+ fail('Invalid structured quality report');
92
+ for (const name of CHECKS) {
93
+ const check = report.checks[name];
94
+ if (!object(check))
95
+ fail(`Missing quality check: ${name}`);
96
+ keys(check, ['status', 'note']);
97
+ if (!['pass', 'not_applicable'].includes(check.status) ||
98
+ (check.note !== undefined && (typeof check.note !== 'string' || check.note.length > 1000)) ||
99
+ (check.status === 'not_applicable' && !check.note?.trim()))
100
+ fail(`Quality check has not passed: ${name}`);
101
+ }
102
+ for (const name of ['source', 'brand', 'hook_and_scene_order', 'endcard_and_cta', 'duration_and_ratio', 'visual_artifacts']) {
103
+ if (report.checks[name].status !== 'pass')
104
+ fail(`Always-required quality check has not passed: ${name}`);
105
+ }
106
+ for (const [key, limit] of [['detected_issues', 25], ['repair_actions', 10]]) {
107
+ if (report[key] !== undefined && (!Array.isArray(report[key]) || report[key].length > limit ||
108
+ report[key].some((v) => typeof v !== 'string' || v.length > 1000)))
109
+ fail('Invalid quality issue/action list');
110
+ }
111
+ if (report.checked_at !== undefined && (typeof report.checked_at !== 'string' ||
112
+ !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/.test(report.checked_at) ||
113
+ !Number.isFinite(Date.parse(report.checked_at))))
114
+ fail('Invalid quality timestamp');
115
+ if (JSON.stringify(report).length > 32 * 1024)
116
+ fail('Quality report is too large');
117
+ return { ...report, detected_issues: report.detected_issues ?? [], repair_actions: report.repair_actions ?? [] };
118
+ }
119
+ async function file(filePath) {
120
+ if (typeof filePath !== 'string' || !path.isAbsolute(filePath))
121
+ fail('Use absolute local file paths');
122
+ const info = await (0, promises_1.stat)(filePath);
123
+ if (!info.isFile() || info.size < 1 || info.size > MAX_BYTES)
124
+ fail('Missing/empty/oversized finished file or quality evidence');
125
+ const bytes = await (0, promises_1.readFile)(filePath);
126
+ return { path: filePath, sha256: sha(bytes), bytes: bytes.length };
127
+ }
128
+ function validFile(value, saved = false) {
129
+ if (!object(value))
130
+ fail('Invalid file binding');
131
+ keys(value, ['path', 'sha256', 'bytes', ...(saved ? ['upload_path', 'ingredient_key', 'kind', 'mime'] : [])]);
132
+ if (typeof value.path !== 'string' || !path.isAbsolute(value.path) || !HASH.test(value.sha256) ||
133
+ !Number.isInteger(value.bytes) || value.bytes < 1 || value.bytes > MAX_BYTES)
134
+ fail('Invalid file fingerprint');
135
+ }
136
+ function validate(checkpoint) {
137
+ if (!object(checkpoint))
138
+ fail('Malformed save checkpoint');
139
+ // Report notes are free text. Do not let a copied auth error turn the otherwise
140
+ // credential-free checkpoint into a token or reusable signed-URL store.
141
+ if (/\bBearer\s+\S+|\bcal_[A-Za-z0-9_-]{16,}\b|[?&](?:X-Amz-(?:Signature|Credential|Security-Token)|token|api_key)=/i.test(JSON.stringify(checkpoint))) {
142
+ fail('Remove authorization or signed-URL material from checkpoint inputs; no credentials may be saved');
143
+ }
144
+ keys(checkpoint, ['version', 'binding', 'binding_sha256', 'progress']);
145
+ const b = checkpoint.binding;
146
+ if (checkpoint.version !== 1 || !object(b) || !object(checkpoint.progress) || digest(b) !== checkpoint.binding_sha256)
147
+ fail('Malformed or changed save checkpoint');
148
+ keys(b, ['environment', 'user_id', 'organization_id', 'brand_id', 'project_id', 'project_organization_id', 'render_id', 'input_digest',
149
+ 'final', 'poster', 'report', 'evidence', 'quality_report', 'review_digest', 'initial_final_render_id']);
150
+ identity({ environment: b.environment, user: { id: b.user_id }, organization: { id: b.organization_id } });
151
+ keys(b.environment, ['name', 'api_origin']);
152
+ if (![b.brand_id, b.project_id, b.project_organization_id, b.render_id].every(id => typeof id === 'string' && ID.test(id)) ||
153
+ !/^[a-f0-9]{8,128}$/.test(b.input_digest) || !HASH.test(b.review_digest) ||
154
+ !(b.initial_final_render_id === null || (typeof b.initial_final_render_id === 'string' && ID.test(b.initial_final_render_id))))
155
+ fail('Invalid render binding');
156
+ validFile(b.final, true);
157
+ validFile(b.poster, true);
158
+ validFile(b.report);
159
+ if (!Array.isArray(b.evidence) || b.evidence.length < 1 || b.evidence.length > 25)
160
+ fail('Missing quality evidence');
161
+ b.evidence.forEach((v) => validFile(v));
162
+ quality(b.quality_report);
163
+ for (const role of ['final', 'poster']) {
164
+ const f = b[role];
165
+ if (f.upload_path !== `working/final-${b.render_id}${role === 'final' ? '.mp4' : '-thumb.jpg'}` ||
166
+ f.ingredient_key !== (role === 'final' ? 'final' : 'final-thumb') ||
167
+ f.kind !== (role === 'final' ? 'render' : 'thumbnail') || f.mime !== (role === 'final' ? 'video/mp4' : 'image/jpeg'))
168
+ fail('Changed upload destination');
169
+ const receipt = checkpoint.progress[role];
170
+ if (receipt !== undefined) {
171
+ if (!object(receipt))
172
+ fail('Invalid stage receipt');
173
+ keys(receipt, ['media_id', 'stage']);
174
+ if (typeof receipt.media_id !== 'string' || !ID.test(receipt.media_id) || !['requested', 'put', 'confirmed'].includes(receipt.stage))
175
+ fail('Invalid stage receipt');
176
+ }
177
+ }
178
+ keys(checkpoint.progress, ['final', 'poster', 'completion', 'selection']);
179
+ if (!['pending', 'unknown', 'complete'].includes(checkpoint.progress.completion) ||
180
+ !['pending', 'unknown', 'selected'].includes(checkpoint.progress.selection))
181
+ fail('Invalid saving stage');
182
+ }
183
+ /** Same-directory rename + fsync: a process interruption leaves either full old or full new JSON. */
184
+ async function writeCheckpoint(target, checkpoint) {
185
+ validate(checkpoint);
186
+ await (0, promises_1.mkdir)(path.dirname(target), { recursive: true, mode: 0o700 });
187
+ const temp = `${target}.${(0, crypto_1.randomUUID)()}.pending`;
188
+ const handle = await (0, promises_1.open)(temp, 'wx', 0o600);
189
+ try {
190
+ await handle.writeFile(JSON.stringify(checkpoint, null, 2) + '\n');
191
+ await handle.sync();
192
+ }
193
+ finally {
194
+ await handle.close();
195
+ }
196
+ try {
197
+ await (0, promises_1.rename)(temp, target);
198
+ const directory = await (0, promises_1.open)(path.dirname(target), 'r');
199
+ try {
200
+ await directory.sync();
201
+ }
202
+ finally {
203
+ await directory.close();
204
+ }
205
+ }
206
+ finally {
207
+ await (0, promises_1.unlink)(temp).catch(() => undefined);
208
+ }
209
+ }
210
+ async function loadCheckpoint(target) {
211
+ const info = await (0, promises_1.stat)(target);
212
+ if (!info.isFile() || info.size > 1024 * 1024)
213
+ fail('Malformed save checkpoint');
214
+ const checkpoint = JSON.parse(await (0, promises_1.readFile)(target, 'utf8'));
215
+ validate(checkpoint);
216
+ return checkpoint;
217
+ }
218
+ function reviewDigest(p) { return digest({ script: p.script ?? null, script_drafts: p.script_drafts ?? null }); }
219
+ function inspectProject(state, ids) {
220
+ const project = state.project;
221
+ const render = Array.isArray(state.renders) && state.renders.find((r) => r.id === ids.render_id);
222
+ if (!object(project) || project.id !== ids.project_id || project.brand_id !== ids.brand_id ||
223
+ !object(render) || render.project_id !== ids.project_id)
224
+ fail('Project/render identity mismatch or missing render; no new render was opened');
225
+ if (state.order || state.creative_plan || project.custom_video_state?.mode === 'generate')
226
+ fail('This is not a client-side recipe render; use its existing order workflow');
227
+ if (!['queued', 'running', 'complete'].includes(render.status) || render.stop_requested_at ||
228
+ project.stop_requested_at || project.plan_status === 'stopped' || ['stopped', 'capped'].includes(project.status) ||
229
+ render.workflow_stage === 'blocked' || render.quality_status === 'blocked')
230
+ fail('Render is stopped, capped, failed or blocked; save-only recovery cannot reopen it');
231
+ return { project, render };
232
+ }
233
+ async function projectRead(transport, ids) {
234
+ return inspectProject(await transport.call('video_project_read', {
235
+ brand_id: ids.brand_id, project_id: ids.project_id, include: ['renders'],
236
+ }), ids);
237
+ }
238
+ async function prepareSave(target, manifest, transport) {
239
+ await (0, promises_1.mkdir)(path.dirname(target), { recursive: true, mode: 0o700 });
240
+ const lock = await (0, promises_1.open)(`${target}.lock`, 'wx', 0o600).catch(() => fail('Save checkpoint is locked by another process'));
241
+ try {
242
+ if (await (0, promises_1.stat)(target).catch(() => null))
243
+ fail('Checkpoint already exists; resume it instead of replacing finished-video evidence');
244
+ if (!manifest || ![manifest.brand_id, manifest.project_id, manifest.render_id].every(v => typeof v === 'string' && ID.test(v)) ||
245
+ !/^[a-f0-9]{8,128}$/.test(manifest.input_digest) || !object(manifest.qc) ||
246
+ !Array.isArray(manifest.qc.evidence_paths) || manifest.qc.evidence_paths.length < 1 || manifest.qc.evidence_paths.length > 25)
247
+ fail('Invalid finished-video manifest');
248
+ const owner = identity(await transport.call('account_whoami', {}));
249
+ const { project } = await projectRead(transport, manifest);
250
+ if (typeof project.organization_id !== 'string' || !ID.test(project.organization_id))
251
+ fail('Unknown project ownership');
252
+ const final = await file(manifest.final_path);
253
+ const poster = await file(manifest.poster_path);
254
+ if (final.sha256 !== manifest.qc.final_sha256 || poster.sha256 !== manifest.qc.poster_sha256)
255
+ fail('Finished bytes differ from the quality check; review these exact files first');
256
+ const report = await file(manifest.qc.report_path);
257
+ const qualityReport = quality(JSON.parse(await (0, promises_1.readFile)(report.path, 'utf8')));
258
+ const checkpoint = {
259
+ version: 1, binding: { ...owner, brand_id: manifest.brand_id, project_id: manifest.project_id, project_organization_id: project.organization_id,
260
+ render_id: manifest.render_id, input_digest: manifest.input_digest,
261
+ final: { ...final, upload_path: `working/final-${manifest.render_id}.mp4`, ingredient_key: 'final', kind: 'render', mime: 'video/mp4' },
262
+ poster: { ...poster, upload_path: `working/final-${manifest.render_id}-thumb.jpg`, ingredient_key: 'final-thumb', kind: 'thumbnail', mime: 'image/jpeg' },
263
+ report, evidence: await Promise.all(manifest.qc.evidence_paths.map(file)), quality_report: qualityReport,
264
+ review_digest: reviewDigest(project), initial_final_render_id: project.final_render_id ?? null,
265
+ }, binding_sha256: '', progress: { completion: 'pending', selection: 'pending' },
266
+ };
267
+ checkpoint.binding_sha256 = digest(checkpoint.binding);
268
+ await writeCheckpoint(target, checkpoint);
269
+ return checkpoint;
270
+ }
271
+ finally {
272
+ await lock.close();
273
+ await (0, promises_1.unlink)(`${target}.lock`);
274
+ }
275
+ }
276
+ function durableUrl(b, f) {
277
+ return `/api/ads/projects/${b.project_id}/render-file?path=${encodeURIComponent(f.upload_path)}`;
278
+ }
279
+ function sameUrl(actual, expected) {
280
+ if (typeof actual !== 'string' || !actual.startsWith('/'))
281
+ return false;
282
+ const a = new URL(actual, 'https://local.invalid');
283
+ const e = new URL(expected, 'https://local.invalid');
284
+ return a.origin === e.origin && !a.hash && a.pathname === e.pathname && a.searchParams.getAll('path').length === 1 && a.searchParams.get('path') === e.searchParams.get('path') &&
285
+ [...a.searchParams.keys()].every(k => k === 'path');
286
+ }
287
+ async function resumeSave(target, transport) {
288
+ // Exclusive local writer. A stale lock is reported, never silently stolen.
289
+ const lock = await (0, promises_1.open)(`${target}.lock`, 'wx', 0o600).catch(() => fail('Save checkpoint is locked; verify the prior process exited before removing its .lock file'));
290
+ try {
291
+ const checkpoint = await loadCheckpoint(target);
292
+ const b = checkpoint.binding;
293
+ const owner = identity(await transport.call('account_whoami', {}));
294
+ if (stable(owner) !== stable({ environment: b.environment, user_id: b.user_id, organization_id: b.organization_id }))
295
+ fail('Account/environment mismatch; reconnect to the original connection');
296
+ for (const expected of [b.final, b.poster, b.report, ...b.evidence]) {
297
+ const actual = await file(expected.path);
298
+ if (actual.sha256 !== expected.sha256 || actual.bytes !== expected.bytes)
299
+ fail('Finished file or quality evidence changed; saving stopped without generation');
300
+ }
301
+ if (digest(quality(JSON.parse(await (0, promises_1.readFile)(b.report.path, 'utf8')))) !== digest(b.quality_report))
302
+ fail('Quality report mismatch');
303
+ const read = async () => {
304
+ const state = await projectRead(transport, b);
305
+ if (state.project.organization_id !== b.project_organization_id)
306
+ fail('Project ownership changed');
307
+ if (reviewDigest(state.project) !== b.review_digest)
308
+ fail('The saved review set changed; diagnose before selecting this video');
309
+ const pin = state.project.final_render_id ?? null;
310
+ if (pin !== b.initial_final_render_id && pin !== b.render_id)
311
+ fail('Another version was selected; recovery will not overwrite that choice');
312
+ return state;
313
+ };
314
+ await read();
315
+ for (const role of ['final', 'poster']) {
316
+ const f = b[role];
317
+ const listed = await transport.call('media_list', { brand_id: b.brand_id, scope: 'video_project', scope_id: b.project_id,
318
+ ingredient_key: f.ingredient_key, input_digest: b.input_digest, limit: 100 });
319
+ if (!Array.isArray(listed.items) || listed.next_cursor)
320
+ fail('Uncertain media lookup; no upload was attempted');
321
+ let media = listed.items.find((m) => m.path === f.upload_path && m.input_digest === b.input_digest && m.ingredient_key === f.ingredient_key);
322
+ const receipt = checkpoint.progress[role];
323
+ if (receipt && (!media || media.id !== receipt.media_id))
324
+ fail('Saved media identity changed or disappeared; no upload was attempted');
325
+ if (media && (!ID.test(media.id) || !['pending', 'approved'].includes(media.status) || media.kind !== f.kind))
326
+ fail('Unexpected saved-media state');
327
+ if (media?.status === 'pending') {
328
+ // A PUT/confirm reply may have been lost. Inspect stored bytes first; a missing object
329
+ // is the only reason to request a fresh PUT. Never infer success from a local receipt.
330
+ const pendingId = media.id;
331
+ await read();
332
+ try {
333
+ const result = await transport.call('media_confirm', { brand_id: b.brand_id, media_id: pendingId });
334
+ if (result.media?.id !== pendingId || result.media?.status !== 'approved')
335
+ fail('Upload confirmation is incomplete');
336
+ }
337
+ catch (error) {
338
+ if (!(error instanceof video_save_mcp_1.SaveToolError) || error.code !== 'not_found')
339
+ throw error;
340
+ const again = await transport.call('media_list', { brand_id: b.brand_id, scope: 'video_project', scope_id: b.project_id,
341
+ ingredient_key: f.ingredient_key, input_digest: b.input_digest, limit: 100 });
342
+ if (again.next_cursor || !again.items?.some((m) => m.id === pendingId && m.path === f.upload_path && m.status === 'pending'))
343
+ fail('Pending media disappeared; diagnose before refreshing its upload');
344
+ // The scoped pending row still exists and storage has no object. A fresh URL/row
345
+ // at the identical render path is safe; this does not generate a replacement.
346
+ media = undefined;
347
+ delete checkpoint.progress[role];
348
+ await writeCheckpoint(target, checkpoint);
349
+ }
350
+ if (media) {
351
+ const refreshed = await transport.call('media_list', { brand_id: b.brand_id, scope: 'video_project', scope_id: b.project_id,
352
+ ingredient_key: f.ingredient_key, input_digest: b.input_digest, limit: 100 });
353
+ if (refreshed.next_cursor)
354
+ fail('Uncertain confirmed-media lookup');
355
+ media = refreshed.items?.find((m) => m.id === pendingId);
356
+ if (!media)
357
+ fail('Confirmed media disappeared');
358
+ }
359
+ }
360
+ if (!media) {
361
+ const state = await read();
362
+ if (state.render.status === 'complete')
363
+ fail('Completed render has missing media; diagnose without replacing its files');
364
+ const result = await transport.call('media_upload', { brand_id: b.brand_id, scope: 'video_project', scope_id: b.project_id,
365
+ kind: f.kind, path: f.upload_path, ingredient_key: f.ingredient_key, input_digest: b.input_digest,
366
+ source: { type: 'file', filename: path.basename(f.upload_path), content_type: f.mime } });
367
+ if (typeof result.media?.id !== 'string' || !ID.test(result.media.id) || result.upload?.method !== 'PUT' ||
368
+ !sameUrl(result.upload.render_file_url, durableUrl(b, f)) || !object(result.upload.required_headers))
369
+ fail('Invalid upload receipt');
370
+ checkpoint.progress[role] = { media_id: result.media.id, stage: 'requested' };
371
+ await writeCheckpoint(target, checkpoint);
372
+ const bytes = await (0, promises_1.readFile)(f.path);
373
+ if (bytes.length !== f.bytes || sha(bytes) !== f.sha256)
374
+ fail('Finished file changed before upload');
375
+ await read();
376
+ await transport.put(result.upload.url, result.upload.required_headers, bytes);
377
+ checkpoint.progress[role].stage = 'put';
378
+ await writeCheckpoint(target, checkpoint);
379
+ await read();
380
+ const confirmed = await transport.call('media_confirm', { brand_id: b.brand_id, media_id: result.media.id });
381
+ if (confirmed.media?.id !== result.media.id || confirmed.media?.status !== 'approved')
382
+ fail('Upload confirmation is incomplete');
383
+ const refreshed = await transport.call('media_list', { brand_id: b.brand_id, scope: 'video_project', scope_id: b.project_id,
384
+ ingredient_key: f.ingredient_key, input_digest: b.input_digest, limit: 100 });
385
+ if (refreshed.next_cursor)
386
+ fail('Uncertain confirmed-media lookup');
387
+ media = refreshed.items?.find((m) => m.id === result.media.id);
388
+ }
389
+ if (!media || media.status !== 'approved' || media.path !== f.upload_path || media.kind !== f.kind ||
390
+ media.input_digest !== b.input_digest || media.ingredient_key !== f.ingredient_key ||
391
+ media.bytes !== f.bytes || sha(await transport.download(media.url, MAX_BYTES)) !== f.sha256)
392
+ fail('Stored bytes do not match the quality-checked final/poster');
393
+ checkpoint.progress[role] = { media_id: media.id, stage: 'confirmed' };
394
+ await writeCheckpoint(target, checkpoint);
395
+ }
396
+ let state = await read();
397
+ if (state.render.status !== 'complete') {
398
+ checkpoint.progress.completion = 'unknown';
399
+ await writeCheckpoint(target, checkpoint);
400
+ await transport.call('video_render_run', { brand_id: b.brand_id, project_id: b.project_id,
401
+ render: { render_id: b.render_id, status: 'complete', workflow_stage: 'ready', quality_status: 'passed',
402
+ quality_report: b.quality_report, output_url: durableUrl(b, b.final), thumbnail_url: durableUrl(b, b.poster) } });
403
+ state = await read();
404
+ }
405
+ if (state.render.status !== 'complete' || state.render.quality_status !== 'passed' ||
406
+ digest(quality(state.render.quality_report)) !== digest(b.quality_report) ||
407
+ !sameUrl(state.render.render_file_path ?? state.render.output_url, durableUrl(b, b.final)) ||
408
+ !sameUrl(state.render.thumbnail_file_path ?? state.render.thumbnail_url, durableUrl(b, b.poster)))
409
+ fail('Completed render does not match this checkpoint');
410
+ checkpoint.progress.completion = 'complete';
411
+ await writeCheckpoint(target, checkpoint);
412
+ if (state.project.final_render_id !== b.render_id) {
413
+ checkpoint.progress.selection = 'unknown';
414
+ await writeCheckpoint(target, checkpoint);
415
+ try {
416
+ await transport.call('video_project_upsert', { brand_id: b.brand_id, project_id: b.project_id,
417
+ patch: { final_render_id: b.render_id, final_selection_guard: {
418
+ expected_final_render_id: state.project.final_render_id ?? null, expected_review_digest: b.review_digest,
419
+ } } });
420
+ }
421
+ catch (error) {
422
+ if (error instanceof video_save_mcp_1.SaveToolError && error.code === 'final_selection_conflict') {
423
+ fail('Another version was selected or the saved review changed; recovery stopped without overwriting that choice. Read the current project before continuing.');
424
+ }
425
+ throw error;
426
+ }
427
+ state = await read();
428
+ }
429
+ if (state.project.final_render_id !== b.render_id)
430
+ fail('Final selection was not saved; reconnect and resume the same checkpoint');
431
+ checkpoint.progress.selection = 'selected';
432
+ await writeCheckpoint(target, checkpoint);
433
+ return checkpoint;
434
+ }
435
+ finally {
436
+ await lock.close();
437
+ await (0, promises_1.unlink)(`${target}.lock`);
438
+ }
439
+ }
440
+ //# sourceMappingURL=video-save.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-save.js","sourceRoot":"","sources":["../../src/lib/video-save.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** GooseWorks host binding only. Production instructions are fetched from the shared catalog. */
2
+ export declare const CUSTOM_VIDEO_ADAPTER_CONTENT = "---\nname: make-custom-video\nslug: make-custom-video\ndescription: Connect the shared video production harness to GooseWorks projects, script and ingredient approvals, managed media generation, budgets and final delivery. Use for original briefs, Instagram/video references and resumed custom projects.\ncategory: ads\nversion: 2.2.0\nauthor: GooseWorks\nrequires_skills: [video-production-harness]\nharness_binding: gooseworks/v2\n---\n\n# Human version\n\nThis adapter connects the production playbook and specialist skill catalog to GooseWorks. It matches each scene to existing creator, footage, graphics, audio and review tools. Customers review and approve their script, actual ingredients and budget in the same chat. Studio is an optional review surface. The agent saves the checked final video to the same project.\n\n---\n\n# Agent version\n\n## Make Custom Video\n\nThe generic production phases run in the Growth sandbox or a connected agent with a shell. GooseWorks owns the project, approvals, budget, uploads and final selection. This adapter replaces Studio desktop files and Tauri approval events with the product contract below.\n\n## Check the connected tool contract first\n\nInspect the tool parameters exposed by the selected connection before creating or changing a custom project. catalog_fetch returns skill packages, not tool schemas. Use the host's registered tool definitions (MCP tools/list when available); do not assume that fetching a newer skill updates a connector's saved schema.\n\nvideo_project_upsert must expose custom_mode and idempotency_key for creation, reference_url when a reference is requested, and patch.script.expected_plan_revision for review saves. Before approvals, require patch.approve fields user_quote, total_credits, phase and review_token, plus custom_review.approval_quote in video_project_read. Before later writes, check that the connected tool exposes every field required by that action, including production clip checks and final quality evidence. If a required field is missing, stop before project writes or paid calls and report that the connected tools and custom-video skill are out of sync. Keep any proposed script in chat and label it as an unsaved, unapproved proposal. Do not drop required fields, switch environments, import the reference as a finished file, or create an HTML review page to work around the mismatch.\n\nThe environment owner must confirm the app-MCP service rollout and refresh the connector's discovered tool schemas. Resume only when the required parameters are visible on the same selected connection. Review and approval stay in the current chat; the Studio creative page is optional. Custom generation requires separate authenticated script and ingredient approvals with their current review tokens and cumulative budgets. Template skills' one-approval instructions do not replace either custom gate. A missing approval field is a tool rollout mismatch, not a reason to require Chrome.\n\n## Load the shared production harness first\n\nThis entry contains only the GooseWorks connection. Production sequencing, creative craft, reviews and repair loops are maintained in video-production-harness, published from the existing Studio harness. Do not invent a shorter local workflow.\n\nFor a new run, use the video-production-harness dependency returned by catalog_fetch or fetch_skill. If absent, fetch catalog_fetch {type:\"skill\",slug:\"video-production-harness\"}; CLI users can use gooseworks fetch video-production-harness. Require nonempty content, scripts, files, version and contentHash. If unavailable, stop before generation; never fall back to a vendored playbook.\n\nRead the returned content, orchestrator.md, capabilities.md and every detailed step invoked by the orchestrator. Materialize every returned script and file at its package-relative path in a run-specific video-production-harness folder. scripts are relative to its scripts directory; files are relative to the package root. Reject paths outside the package. Save the exact bundle only in the run's persistent workspace. Store only {slug,version,content_hash,package_path} as script_drafts.harness in the saved project; never inline the package content, files or scripts into the review draft. The review payload must stay below its 256,000-character limit. Keep the saved package in this run's durable folder, not a shared mutable installation.\n\nOn resume, read video_project_read and use the saved package matching script_drafts.harness.content_hash. Do not refetch latest or overwrite this run's package. If the package is missing, stop and restore that version before continuing; fetching today's release does not restore it. New projects load the current catalog release. This is an agent-held saved package, not a server-enforced immutable registry.\n\n## Discover specialists for the actual scenes\n\nCustom means composing available capabilities around the brief. Before the design/tool plan,\nmatch each scene and finishing step to the current skill catalog. Repeat this check when a\nnew requirement or repair appears, before writing a helper or making a provider call. The\nshared harness owns the sequence; specialist skills supply implementations inside its phases.\n\nUse the known routes below as starting points. Fetch the relevant skill, read its instructions\nand failure modes, and inspect its returned scripts/files/dependencies before choosing it.\nFor an unmatched need, use the advertised catalog_search {type:\"skill\",query:\"<capability>\"},\nor search_skills on a connection exposing that alias; CLI: gooseworks search \"<capability>\".\nUse short separate queries such as \"creator\", \"footage\", \"motion\" or \"captions\": search words\nare ANDed. Do not restrict discovery to category \"ads\"; video helpers also live under\n\"general\" and \"content\". Follow returned pagination when relevant results are not on the\nfirst page. Fetch by returned slug with catalog_fetch {type:\"skill\",slug:\"<slug>\"}, fetch_skill,\nor gooseworks fetch <slug>. Inspect the selected connection's advertised schemas first.\n\n| Scene or operation | Specialist to fetch | How it fits custom production |\n| --- | --- | --- |\n| Evidence-backed hook, script or script rewrite | [[composes::write-video-ad-script]] | Supply the actual custom scene/tool plan and brand evidence in place of a fixed template recipe. Keep the harness script review and lock. |\n| Generated creator saying an exact script across takes | [[composes::create-creator-takes-h3]] | Plan on line boundaries, preserve approved face/room/dialogue, review the first take alone and carry its native voice to later takes. |\n| Real product footage, screen recordings or screenshots | [[composes::footage-cutlist]] | Inspect source windows, map each proof shot to its line, review the cut list and render the product layer. |\n| Creator beside, over or between product footage | [[composes::compose-creator-layer]] | Combine the inspected creator track and product layer per beat. Preserve the creator's dialogue as the master audio. |\n| Native multi-cut performance or general generated B-roll | [[composes::create-video-seedance-2-fal]] or [[composes::create-video-fal]] | Choose from the actual supported endpoint/schema and quoted operations; use H3 when a continuous exact-script creator track is the better fit. |\n| Character anchors, grounded product edits or scene stills | [[composes::create-image-fal]] or [[composes::create-image-gpt-image-fal]] | Reuse approved identity and real product references. Check preview eligibility and bounded pricing for the exact endpoint. |\n| Separate narrator or voice audition | [[composes::create-vo-elevenlabs]] | Use the host-approved voice and locked copy. Do not add a second narration over native creator speech. |\n| Music bed or song | [[composes::create-music-elevenlabs]] | Include its actual quote in the phase budget; preserve the approved audio strategy and lyric/beat timing. |\n| Branded text cards, graphics or end card | [[composes::goose-graphics]] | Start from a fitting layout/style and real logo. It produces graphics; animation still requires an actual local renderer. |\n| Narration-led zoom/pan on an existing demo | [[composes::video-polish]] | Use its measured zoom targets only with the installed Remotion/transcription capabilities required by this route. |\n| Conventional clip stitching or overlays | [[composes::stitch-videos-ffmpeg]] | Use its local implementation when it fits the edit; the shared harness assembly helper remains available for ordinary concat/mix. |\n| Word timing and final caption treatment | [[composes::caption-burn]] | Inspect the actual transcript against locked copy. Caption only after picture and mix polish, then repeat final review. |\n| Replace a defective silent B-roll window in a UGC master | [[composes::ugc-fixloop]] | Keep the original continuous dialogue; this repair does not fix a talking shot's lips or voice. |\n| Complete-video observation and finished-ad checks | [[composes::watch]] and [[composes::review-finished-ad]] | Supply real frames/audio, brand assets and timestamps. Their results support the shared final QC; they do not grant approval. |\n\nFor format-specific motion, chat, podcast, product or music layouts, search the catalog for\nthe matching render-* capability and inspect its config and inputs. Reuse a compatible\nrenderer or phase implementation without changing the custom project into a fixed template.\nDo not call a template's one-shot driver, create a second project, or replace the shared\nproduction sequence just to use one of its helpers. The table is a starting map, not an\nexhaustive catalog or a promise that every published skill is executable on this connection.\n\n## Bind and retain the selected specialists\n\nA fetched package proves that instructions exist; it does not prove that its provider,\npricing, dependencies or local renderer are available. Check each selected route before\nspending. Materialize all returned scripts, files and dependency packages in separate,\nrun-specific package folders, preserving relative paths and rejecting paths outside the\npackage. Do not save several skills into one scripts folder: helpers with the same filename\nwould overwrite each other. Read the installed media-proxy dependency before running any\npaid helper. Every paid submit must propagate this project's project_id / GW_PROJECT_ID\nthrough the managed transport on the selected connection and pass the normal quote and\napproval checks. A helper that cannot carry that context is unavailable for paid custom work.\nNever run its direct-key path or substitute a guessed endpoint or price.\n\nUse specialist craft and executable helpers inside the corresponding shared phase. This\nadapter's project state, supported providers, authenticated script/ingredient gates and\nbudget override a specialist's legacy setup, dollar estimate or standalone approval flow.\nCaptions remain last even if a renderer normally burns them earlier: choose its uncaptioned\noutput or use another compatible implementation. Verify the returned scripts implement any\nrequested setting; prose alone is not an executable capability.\n\nFor H3, the creator still is a script-approved image preview, while the first native-speaking\ntake is a video and requires ingredient approval and its quoted budget. Review that take's\nvoice before the remaining takes; do not spend on it as an image/voice audition. Native H3\nspeech is not a selected ElevenLabs voice: do not invent a voice_id or replace its audio with\nseparate TTS. Save the actual audio strategy and take/reference provenance in extra draft\nfields. Use selected voice roles and playable auditions when the route actually uses them.\n\nSave a compact script_drafts.capability_plan with each selected operation's purpose,\nscene numbers (or \"final\"), skill_slug, version, content_hash, package_path, dependency\nidentities, inputs, expected outputs and supported execution route. Keep full packages in the\nrun's durable workspace, outside the 256 KB review payload. On resume, reuse the recorded\npackages and existing jobs; do not silently fetch latest over an approved run. A missing\npackage must be restored, and a changed route/model/input must be quoted and reviewed through\nthe affected custom gate before spending. If a required capability is unavailable, record\nthe limitation and propose a supported revision instead of improvising a bypass.\n\n## Carry the sourced brief and verify the handoff\n\nBefore script writing, save the writer's documented creative-brief.json from the current brand/product evidence and project directions. Include exact product/variant, buyer situation, supported mechanism/claims, offer/CTA, constraints, delivery intent, locked copy, applicable prior decisions and explicit unknowns with source references. Use the fetched write-video-ad-script preparation command with --brief working/script/creative-brief.json and its documented bank/brand/product/template arguments; set the new shape.requires_creative_brief to true. The writer and critic consume that same angle-context. Save only the concise brief/revision and workspace reference in script_drafts extra fields, never full research/package contents. A missing required brief fails the script check; do not rerun known research or rewrite user-locked wording silently.\n\nRead references/specialist-handoff.md from the saved shared harness. For each selected UGC, product/demo or motion operation, extend the existing script_drafts.capability_plan entry with the exact approved brief/script revisions, mapped scene/beat numbers and timing, selected product/reference/source IDs and excerpt ranges, audio/performance choice, package/version/hash and expected returned artifact roles. These are existing extra draft/project artifacts, not new API parameters. Preserve the distinction between numeric script_drafts.scenes[].scene and string production scene IDs.\n\nCheck the actual returned package before executing: H3 plan_takes uses beats id/start/end/vo and character image/identity/environment/delivery; footage-cutlist uses sources and per-beat source/in/out/fit/why; goose-graphics returns static composition/PNG and still needs an actual motion renderer. Do not replace an unsupported helper with a guessed tool name. Preflight the real binary/import/browser and a free dry run, not just its presence. Existing-file skip behavior is not validity: probe saved media and verify fingerprints/approval/job results first, then reuse approved media on resume without new generation.\n\nValidate returned media and provenance against the handoff before clip checks/assembly: exact scene/source revision, words/product/variant, visible proof, measured duration/ratio, selected voice/native speech and neighboring continuity. All speech requires actual isolated performance listening and full mixed-output listening; transcript/word timing only supports that judgment. Audition representative unresolved material and reuse valid approved takes. No mandatory faster delivery or louder climax.\n\n## Hook changes and editorial review\n\nRead references/hook-compatibility.md and references/editorial-review.md from this run's saved harness. Resolve the exact watched source/render and classify same-promise hook versus a new promise requiring different body/proof/payoff. Every changed opening gets new image/action/audio/text review, including visual-only restyles with unchanged words. Shortlist cheap ideas before media spend; keep a broader recut distinct from an isolated opening test.\n\nFor an isolated hook replacement, fetch the existing render-hook-replacement package and inspect its real preflight/config contract. A not-found/empty catalog response blocks that route before paid generation; an open source change is not proof of served availability. Preserve source/body/ending using its own verification, then play/listen to the complete candidates and register each separately. Recommendations are creative judgments, never unmeasured performance winners.\n\nRun rough/fine/final review questions through the current Studio surfaces. First save what the actual cut communicates, then compare with the brief; concept review has no watched-cut verdict. Route unsupported promise to script/concept, missing proof to production, sequence problems to edit and local defects to repair. Unavailable required playback/listening is incomplete and cannot become quality_status passed.\n\nKeep exact feedback text/source/time, intended effect and acceptance condition. Consolidate duplicate notes and record conflicting intentions plus the authorized owner's decision. Preserve changed versus verified dispositions in existing feedback/production metadata or linked project artifacts; executing a fix does not resolve it. Invalidate only affected script/assets/timings/captions/mix/approvals/derivatives, retain valid unrelated work, and rewatch each actual delivered file. Preserve editable timeline, stems, caption sources, selected/candidate versions, rejected options with reasons and scoped pronunciation/delivery history for the next run. Approval and model scores are not audience performance.\n\n## GooseWorks capability binding\n\nRead capabilities.md to bind shared instructions. GooseWorks is authoritative for project state and approvals; local working artifacts grant no spending permission.\n\n- Brand facts and product assets: brand_get_context plus the saved brief/reference analysis.\n- Durable state, concept/design/script/scene/continuity records and feedback: video_project_read and video_project_upsert. Save shared artifact roles in script_drafts extra fields and production metadata; translate spoken lines, captions and scenes into the review schema below.\n- Human gates: discuss free creative choices in chat. Persist concept/design/script before authenticated script approval. Selected storyboard, playable voice auditions, characters, worlds and end card become actual ingredients. Stop for authenticated ingredient approval before any paid clip or preview video. Record the customer's explicit chat approval through patch.approve with the current phase, review token and cumulative budget; a reply alone, local artifact or shared auto mode does not record approval. A handed-off coworker cannot approve its own work. Changes require renewed approval.\n- Provider access, bounded pricing and spend: managed fal/ElevenLabs tools and currently supported endpoints only. Do not switch to direct provider keys, Higgsfield or an unpriced fallback. A missing capability blocks its state until a supported equivalent is reviewed and quoted.\n- Storage: media_upload and media_confirm with exact project ownership; use durable previews in ingredients.\n- Assembly, probes, frame extraction, transcript comparison and continuous inspection: shared package scripts, FFmpeg/FFprobe/Python and available media review tools. A thumbnail or text description cannot satisfy video review.\n- Render attempts, QC, history and promotion: video_render_run and video_project_upsert using the backend contract below. Shared QC still applies; the backend checklist is a minimum.\n\nGrowth and connected coding agents supply local execution. A terminal-free MCP client can prepare/review with connected tools, but must stop or continue through the project's Growth session when required local capabilities are absent. Never claim a render ran without execution.\n\n## Start and resume\n\nAfter the connected tool contract passes the checks above, for a new brief call video_project_upsert with brand_id, name, format:\"custom\", custom_mode:\"generate\", brief:{prompt, audience, objective, product_name, cta, ratio, duration_seconds}, optional reference_url and a stable idempotency_key. Use only brief fields present in the schema. Instagram references have a metered public-data lookup; direct files are downloaded, probed and stored. generated_video_url and media_id mean finished-file imports, never references. Do not use import mode to bypass a generation project's review gates.\n\nRead video_project_read on every resume. When it returns remix.direction for this generated custom project, use remix.direction.implementation as the production starting point: keep the pipeline, full prompts and guards, timings, assembly settings and fixes. Watch the reference. Rewrite all spoken lines and bind products, claims, images and CTA to the target brand. Stay on this same custom project; obtain fresh approvals for its own script/ingredients and budget before any paid call. A source approval or source voice recording never authorizes this new run.\n\nRead video_project_read on every resume. Its project and custom_review are authoritative. Growth creates and retains origin_session_id from trusted chat context. Show the saved review in this conversation and record the customer's explicit approval through the authenticated customer-facing connection as described below. Studio remains available when the customer wants it; never require Chrome to approve. Continue in Growth resumes the bound conversation. A handed-off production coworker prepares the review, ends its turn and waits for the customer-facing connection to record approval before it resumes the same project.\n\nIf reference preparation failed, explain custom_review.reference.error. Continue from the brief if requested, or retry with patch:{retry_reference:true}. A live preparation claim is protected for twenty minutes; after interruption an explicit retry reuses a saved resolved URL when possible. Never invent a reference analysis when no reference was viewed.\n\n## Saved review schema\n\nSave through video_project_upsert {brand_id,project_id,patch:{script:{script_drafts,script,expected_plan_revision}}}. script_drafts contains format:\"custom\", title, duration_target_sec (<=180), aspect_ratio, scenes:[{scene:1,time:\"0\u20135s\",text,caption,direction}], preview_estimate:{total_credits,basis,operations:[\"Describe each priced operation as a string\"]}, optional render_estimate in the same shape, voices:{narrator:{voice_id,name}} and ingredients:[{container,label,subtitle,url,text,note,pending}]. script_drafts.scenes[].scene is a positive integer such as 1; production scene IDs use the separate string shape described below. The plain script is joined spoken copy. Read project.plan_revision and pass it as expected_plan_revision on every existing-draft save; a stale write is refused. Store concept, reference_analysis, continuity, planned operations and job/asset provenance as extra draft fields; keep the review set under 256 KB.\n\nEach estimate requires total_credits (a nonnegative number, at most 3,000), basis (a nonempty string) and operations (1\u2013100 nonempty strings, each at most 500 characters). Do not put operation objects in either estimate. Keep detailed model/settings/cost rows in a separate extra field such as planned_operations. voices is an optional object keyed by role, never an array; each selected role is {voice_id, name?}. Keep unselected audition candidates in a separate extra field. Copy actual catalog voice IDs into the selected roles; every selected role later needs a matching playable voice ingredient.\n\nFor example, a narrator selection is voices:{narrator:{voice_id:\"<actual catalog ID>\",name:\"<catalog name>\"}}. A preview estimate is preview_estimate:{total_credits:100,basis:\"One presenter image and two voice auditions\",operations:[\"Presenter image: fixed-price supported model\",\"Two voice auditions: the saved script\"]}. These values illustrate the shape; quote the actual supported operations for the run.\n\nBefore saving either preview_estimate or render_estimate, quote each remaining paid media operation through data_post_provider with its exact supported path, body and project_id plus query:{quote_only:true}. Before sending this flag, read a fresh data_post_provider tool description from the selected connection. It must explicitly advertise query:{quote_only:true}, maximum_credits and no generation, reservation or debit. Alternatively, require explicit environment-owner evidence that this same selected app-MCP runtime has deployed free quote support. An extensible query schema or a newer fetched skill is not evidence. If the description is old and no verified runtime evidence exists, stop before the call and request the backend rollout and connector refresh; an older server can treat this flag as a paid generation request. The quote requires no approval and generates no media. This mode is MCP-only; do not send quote_only to an HTTP generation proxy.\n\n```json\n{\n \"provider\": \"fal\",\n \"path\": \"fal-ai/kling-video/v3/standard/image-to-video\",\n \"body\": {\n \"image_url\": \"https://example.com/approved-anchor.png\",\n \"duration\": \"5\",\n \"generate_audio\": false\n },\n \"project_id\": \"<this project ID>\",\n \"query\": {\n \"quote_only\": true\n }\n}\n```\n\nRequire quote_only:true, a finite positive maximum_credits and cost.credits:0 in the result. If the server returns a job, audio, a charge or any non-quote result, stop and report the tool/runtime mismatch; never retry it as a quote. Unknown or unbounded prices block planning. Do not substitute public unit prices or guessed billed discounts for maximum_credits: the custom reservation includes conservative quantity, size, audio and preset bounds, while actual settlement can be lower.\n\nSum maximum_credits for all remaining operations in the phase into that estimate's total_credits, including every concurrently planned job. Keep local free assembly/QC operations at zero. The approved project cap includes custom_review.committed_credits plus the remaining quoted estimate; committed includes both settled spend and outstanding reservations. Read the current review again before approval, avoid counting an already reserved job twice, and quote any changed model/body before seeking revised approval. Quotes are not approval tokens or locked prices; real submission rechecks its current conservative bound and the approved budget.\n\nBefore script approval, only plan/save free text. preview_estimate quotes future storyboard images and voice auditions. custom_review.script_approved permits priced image previews on supported fal image endpoints and ElevenLabs text-to-speech auditions. Unknown endpoints require ingredient approval. Use catalog voice previews when possible; do not silently select a paid model outside the preview allowlist.\n\nUpload actual previews with media_upload/media_confirm. Put public/durable URLs on image/avatar/background/endcard/voice/audio/video ingredients. Text containers can carry inline text; a voice or image description cannot replace its preview. Save a render_estimate for remaining clips/assembly and show the complete ingredients. Stop until custom_review.ingredients_approved. Script and ingredient tokens are independent; do not infer approval from project.status.\n\n## Record each approval in this chat\n\nThere are two independent gates. Script approval permits the quoted image/voice previews. Ingredient approval permits the quoted clips and finishing work after the actual review set is ready. Keep both gates even when the customer prefers chat to Studio.\n\n1. Read video_project_read. Show the current saved script or actual playable ingredients, the changes since any previous approval and the cumulative credit limit in custom_review.approval_quote. Explain that the limit includes custom_review.committed_credits plus the remaining quoted operations. An old estimate, approval from a previous revision or remaining-only amount is not the current budget.\n2. Ask for the customer's explicit approval of that phase and amount in this conversation. Copy their actual words as user_quote; never invent consent or interpret a pricing-error complaint as approval of a changed creative plan or larger budget.\n3. Read video_project_read again before recording the yes. Require the same review token, phase and total shown to the customer. If any changed, show the changed review and ask for approval of it; never silently attach the earlier yes to a newer token or amount.\n4. Through the authenticated customer-facing connection call video_project_upsert {brand_id,project_id,patch:{approve:{user_quote:\"<the customer's actual words>\",phase:custom_review.approval_quote.phase,review_token:custom_review.approval_quote.review_token,total_credits:custom_review.approval_quote.total_credits}}}. This is the custom contract; template approvals without phase and review_token cannot authorize custom production. Do not combine this approval with a script edit.\n5. Read back custom_review. For phase:\"script\", require script_approved:true and the matching script_token. For phase:\"ingredients\", require ingredients_approved:true and the matching ingredient_token. Check the approved max_credits covers the current cumulative total before dispatch. A tool error or merely sending patch.approve is not approval.\n\nThe approval_quote.phase is \"script\" or \"ingredients\". Its review_token is the matching custom_review.script_token or custom_review.ingredient_token from that saved snapshot. If approval_quote is missing or the requested phase's review is not ready, finish the free preparation or resolve the returned blocker; never guess a token, reuse the other phase's token or change the budget to force approval.\n\nOnly the authenticated customer-facing connection can record the customer's approval. A handed-off coworker with a production task prepares and displays the review, ends its turn, and waits. It cannot call patch.approve to approve its own work, forward a fabricated user_quote or treat the original brief as approval. After the customer-facing connection records and verifies approval, resume that same task/project with goose_run_task when required. Studio can record the same authenticated approvals if the customer chooses it; do not require Chrome, browser unlocks or Studio access just to approve in chat.\n\n## Paid execution and resume\n\nEvery managed media call carries project_id (GW_PROJECT_ID in scripts) and a stable input fingerprint. Use the managed fal/ElevenLabs endpoints and credentials supplied by Growth; never request customer provider keys. Do not expose those credentials in logs. Recheck custom_review before dispatch. The backend reserves estimated outstanding costs atomically, enforces the approved total (maximum3,000 credits) and prevents duplicate submissions. At most a20% overrun can be newly approved; this is not automatic permission to spend above the customer's selected limit.\n\nPreview eligibility and price support are separate checks. Use an exact endpoint permitted by the backend preview policy and confirm its current request schema and server quote. Model discovery and provider pricing can change: use the selected connection's actual quote, including supported provider estimates, instead of a skill-maintained priced-model list. A model-family name does not make every route eligible for script previews. Do not move a preview to another phase to bypass its approval gate. If pricing cannot be established, keep the saved request and report a system pricing blocker; do not ask the customer to choose when their choices are already approved. Final clip models require ingredient approval. Existing-job polls remain permitted after edits; retrieval does not authorize new media.\n\nSave provider request IDs and actual uploaded URLs promptly. Custom operations with known rejection can retry safely; ambiguous timeouts keep their authorization until reconciled. Media spend is metered through the shared gateway. Custom videos have no extra template base render fee. Imported finished files still file for zero credits.\n\n## Clips, assembly and quality\n\nUse the selected packages in script_drafts.capability_plan for each scene and operation. Recheck specialist discovery for new requirements or repairs before improvising a helper. Keep anchors and exact lines fixed. Use the Python assembly helper returned in the shared harness scripts for actual existing clips. It needs only Python, FFmpeg and FFprobe; it does not call a provider or require Chromium. Inspect generated clips before assembly, and watch the final export after assembly/captions.\n\nOpen a render with video_render_run {brand_id,project_id,kind:\"full\"}; executor:\"cloud_agent\" for Growth when exposed by the current schema. Report live workflow_stage/progress_note/progress_percent while producing it. Upload the final file to scope:\"video_project\", scope_id:project_id. The tool opens/reports a client-executed render; fixed server orders remain paused.\n\nAfter each accepted generation or deterministic edit, update patch.production with the steps and settings that actually ran. Save and read back the actual candidate recipe before showing its preview or pausing for review, so an interrupted or waiting run does not leave only an early plan in the backend. Partial progress is allowed; pending creative approval or QC must stay explicit and must never be converted into passing clip evidence.\n\nBefore completing or pinning a candidate, replace the early planning manifest with the actual production recipe. Record every current script scene using its string scene number, exact current spoken line, measured duration and full generation prompts or deterministic rendering instructions. Record the actual pipeline/model settings, assembly/captions/audio settings, and repairs in fixes. Never leave blocked/pending planning statuses in a completed recipe. Preserve full prompts and guards; do not reduce them to summaries. Save partial progress while working, but an unfinished recipe is not a reusable final.\n\nSave the final recipe through patch.production, then read video_project_read and compare production_manifest with what you just saved, including all scene IDs and spoken lines. If the save fails or the read-back is stale/incomplete, repair it before completion; do not describe the run as finished or remixable. Final completion freezes the actual recipe and reviewed script together for the next agent.\n\nSave patch.production as a production manifest with version:1 and a nonempty pipeline array. Each pipeline item requires step and model; purpose and settings are optional. production.characters is an optional array, never a record/object: each entry requires both name and prompt strings. Store anchor media IDs, URLs, actual appearance and other extra provenance in script_drafts; character entries accept name and the full design prompt.\n\nproduction.scenes[].id is a string containing the corresponding script scene number, for example \"1\". script_drafts.scenes[].scene and production.clips[].scene remain positive integers, for example 1. Map production scene IDs with String(scriptScene.scene); do not convert clip.scene or script scene IDs to strings. Each scene can also carry line, still_prompt, motion_prompt, duration_s and notes. style is an object; voice and music are objects when present; assembly is an object; fixes is an array of {problem,fix}.\n\nEach clip requires a numeric scene, a stored URL and exactly one of each named check: visual_artifacts, brand, product, voice_and_script, duration_and_ratio. Each clip check is {check,status:\"pass\"|\"fail\",note?}; not_applicable is not valid for clip checks. Save exactly one checked clip per approved script scene before final completion, with every check passing. Before clips exist, omit clips from an ingredient-preparation save.\n\nThe following is a one-scene JSON shape example. Replace all placeholders with actual saved values. Its failed QC statuses are deliberately unapproved; never copy a passing status without performing the shared review.\n\n```json\n{\n \"patch\": {\n \"production\": {\n \"version\": 1,\n \"pipeline\": [\n {\n \"step\": \"Scene clips\",\n \"model\": \"<actual supported model>\",\n \"settings\": {}\n }\n ],\n \"style\": {\n \"prompt\": \"<shared visual direction>\",\n \"negative\": \"<shared guards>\"\n },\n \"characters\": [\n {\n \"name\": \"Presenter\",\n \"prompt\": \"<exact full character design prompt>\"\n }\n ],\n \"scenes\": [\n {\n \"id\": \"1\",\n \"line\": \"<approved spoken line>\",\n \"still_prompt\": \"<exact full still prompt>\",\n \"motion_prompt\": \"<exact full motion prompt and guards>\",\n \"duration_s\": 5\n }\n ],\n \"voice\": {\n \"voice_id\": \"<selected catalog voice ID>\",\n \"name\": \"<selected voice name>\",\n \"model\": \"<actual voice model>\",\n \"settings\": {}\n },\n \"assembly\": {\n \"ratio\": \"9:16\",\n \"fps\": 30\n },\n \"fixes\": [],\n \"clips\": [\n {\n \"scene\": 1,\n \"url\": \"https://example.com/confirmed-scene-1.mp4\",\n \"checks\": [\n {\n \"check\": \"visual_artifacts\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"brand\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"product\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"voice_and_script\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"duration_and_ratio\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n }\n ]\n }\n ]\n }\n }\n}\n```\n\nComplete with video_render_run {brand_id,project_id,render:{render_id,status:\"complete\",output_url,quality_status:\"passed\",quality_report:{version:1,summary,checks:{source,brand,product,hook_and_scene_order,voice_and_script,captions,endcard_and_cta,duration_and_ratio,visual_artifacts},detected_issues:[],repair_actions:[],checked_at}}}. Each final check is {status:\"pass\"|\"fail\"|\"not_applicable\",note}; brand/product/scene order/duration/visual artifacts must pass. Save a failed candidate as blocked/failed with its issue, not complete. Final completion binds approval revisions, output and quality evidence to the render; pin with patch.final_render_id only after passing.\n\nAll nine named final checks above are required, including source, voice_and_script, captions and endcard_and_cta when they are not applicable. A final check uses status:\"pass\"|\"fail\"|\"not_applicable\" and an optional note. The five mandatory passing checks are brand, product, hook_and_scene_order, duration_and_ratio and visual_artifacts; no final check may fail and detected_issues must be empty to complete. Record why a permitted check is not_applicable. Keep actual repair_actions and use the actual ISO 8601 checked_at time. The backend report is a minimum; it does not replace the full shared watch, claim verification or craft review.\n\nThis blocked report illustrates every required field. Replace its findings and example timestamp with actual evidence. Only after repairs and the shared final review pass may the render be reported complete with quality_status:\"passed\", its confirmed output_url and no unresolved issues.\n\n```json\n{\n \"render\": {\n \"render_id\": \"<existing render ID>\",\n \"status\": \"failed\",\n \"quality_status\": \"blocked\",\n \"error_message\": \"<actual unresolved issue>\",\n \"quality_report\": {\n \"version\": 1,\n \"summary\": \"<actual full-video review summary>\",\n \"checks\": {\n \"source\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"brand\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"product\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"hook_and_scene_order\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"voice_and_script\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"captions\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"endcard_and_cta\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"duration_and_ratio\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"visual_artifacts\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n }\n },\n \"detected_issues\": [\n \"<actual unresolved issue>\"\n ],\n \"repair_actions\": [],\n \"checked_at\": \"2026-10-03T00:00:00Z\"\n }\n }\n}\n```\n\n## Feedback and delivery\n\nSave customer script/ingredient/video feedback through the connected project tools before continuation; affected creative edits invalidate their approvals. Read custom_review.feedback on every turn, preserving the original watched render/time and text when provided. A selected final change never relocates an earlier note. Resolve only after the candidate satisfies the original intended effect and full-output recheck; keep incomplete or conflicting notes open. Replace only the affected assets; save revised estimates and show the changed review and cumulative budget in the same chat before recording renewed approval. Deliver the playable current_render_url with render_artifact kind:\"video\" in Growth and actual project spend. Include the Studio app_url when a text host or the customer needs it; do not require it for approval. Keep final history; never create another project just because an agent restarted.\n\n## Reviewed snapshot, voices and supported pricing\n\ncustom_review returns script_drafts and plan_revision from the same saved snapshot as its tokens. Show that snapshot in chat; Studio can also render it. Use the revision for edits and the current approval_quote for each approval. Spoken copy (text) and on-screen copy (caption) are separate fields. Voice audition ingredients carry role and voice_id; script_drafts.voices maps each role to its selected voice_id/name. Every selected role needs an actual matching playable preview before approval.\n\nA pending/processing/failed reference blocks script approval. If the customer explicitly chooses to continue from the brief without the reference, save that choice through the connected reference-review tool when exposed, or offer Studio's Continue from brief action when needed. This is a reference decision, not a requirement to approve in Chrome. Do not silently replace a requested reference with brief-only production.\n\nCustom provider submits require a positive server quote, including quantity, supported dimensions/audio and any provider estimate. The server must establish source duration for audio/video-driven routes from authorized media metadata or a bounded probe; do not add invented duration fields to the provider body to force a quote. A provider estimate permits production within the approved budget even when exact final billing is unavailable. Missing source duration or an unavailable provider estimate is a system blocker to resolve on the saved project, not a model allowlist or a new creative choice. A conservative reservation is released to actual charged spend when the provider result settles. Final output must be a confirmed, stored video_asset in this exact organization/project, and completion binds its media_id to the render. External hotlinks cannot be pinned as generated custom finals. The portable helper checks FFmpeg's libass capability before local captions, rejects clips shorter than their timeline and validates video-stream duration.\n";
3
+ //# sourceMappingURL=custom-video-skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-video-skill.d.ts","sourceRoot":"","sources":["../../src/skills/custom-video-skill.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,eAAO,MAAM,4BAA4B,yi3CAA+h3C,CAAC"}