gooseworks 0.3.11 → 0.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/commands/whoami.d.ts +11 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +84 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/skills/master-skill.d.ts.map +1 -1
- package/dist/skills/master-skill.js +107 -48
- package/dist/skills/master-skill.js.map +1 -1
- package/package.json +1 -1
- package/skills/goose-video/SKILL.md +107 -48
package/README.md
CHANGED
|
@@ -93,6 +93,31 @@ npx gooseworks logout
|
|
|
93
93
|
|
|
94
94
|
Deletes `~/.gooseworks/credentials.json`.
|
|
95
95
|
|
|
96
|
+
### `whoami`
|
|
97
|
+
|
|
98
|
+
Show which account you're currently signed in as. Handy when you have multiple
|
|
99
|
+
GooseWorks accounts and need to confirm the active one before running a command.
|
|
100
|
+
Reads local credentials only — no network call.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npx gooseworks whoami
|
|
104
|
+
npx gooseworks whoami --json # machine-readable output
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Output:
|
|
108
|
+
```
|
|
109
|
+
Signed in as you@example.com
|
|
110
|
+
Scope: user
|
|
111
|
+
Agent: 2e32bd49-…
|
|
112
|
+
API base: https://api.gooseworks.ai
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
To switch accounts, run `gooseworks logout` then `gooseworks login`.
|
|
116
|
+
|
|
117
|
+
> The GooseWorks MCP server exposes the same identity check as the `whoami` tool
|
|
118
|
+
> (email + the exact agent/org the token is pinned to), separate from
|
|
119
|
+
> `list_accessible_scopes`, which lists *every* workspace you can reach.
|
|
120
|
+
|
|
96
121
|
### `search`
|
|
97
122
|
|
|
98
123
|
Search the GooseWorks skill catalog.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* `gooseworks whoami` — show which account the CLI is currently signed in as.
|
|
4
|
+
*
|
|
5
|
+
* Reads `~/.gooseworks/credentials.json` only (no network call), so it works
|
|
6
|
+
* offline and reflects exactly what the CLI + its MCP registration will
|
|
7
|
+
* authenticate as. This is the answer to "I have multiple accounts — which one
|
|
8
|
+
* is active right now?"; use `gooseworks login` / `logout` to switch.
|
|
9
|
+
*/
|
|
10
|
+
export declare const whoamiCommand: Command;
|
|
11
|
+
//# sourceMappingURL=whoami.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,SA0CtB,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
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.whoamiCommand = void 0;
|
|
37
|
+
const commander_1 = require("commander");
|
|
38
|
+
const credentials_1 = require("../auth/credentials");
|
|
39
|
+
const logger = __importStar(require("../utils/logger"));
|
|
40
|
+
/**
|
|
41
|
+
* `gooseworks whoami` — show which account the CLI is currently signed in as.
|
|
42
|
+
*
|
|
43
|
+
* Reads `~/.gooseworks/credentials.json` only (no network call), so it works
|
|
44
|
+
* offline and reflects exactly what the CLI + its MCP registration will
|
|
45
|
+
* authenticate as. This is the answer to "I have multiple accounts — which one
|
|
46
|
+
* is active right now?"; use `gooseworks login` / `logout` to switch.
|
|
47
|
+
*/
|
|
48
|
+
exports.whoamiCommand = new commander_1.Command('whoami')
|
|
49
|
+
.description('Show which GooseWorks account you are signed in as')
|
|
50
|
+
.option('--json', 'Output raw JSON')
|
|
51
|
+
.action((opts) => {
|
|
52
|
+
const creds = (0, credentials_1.getCredentials)();
|
|
53
|
+
if (!creds) {
|
|
54
|
+
if (opts.json) {
|
|
55
|
+
console.log(JSON.stringify({ logged_in: false }, null, 2));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
logger.error('Not logged in. Run "gooseworks login" first.');
|
|
59
|
+
}
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const scope = creds.scope_type ?? 'agent';
|
|
63
|
+
if (opts.json) {
|
|
64
|
+
console.log(JSON.stringify({
|
|
65
|
+
logged_in: true,
|
|
66
|
+
email: creds.email,
|
|
67
|
+
scope_type: scope,
|
|
68
|
+
agent_id: creds.agent_id,
|
|
69
|
+
default_agent_id: creds.default_agent_id ?? creds.agent_id,
|
|
70
|
+
api_base: creds.api_base,
|
|
71
|
+
mcp_server_url: creds.mcp_server_url ?? null,
|
|
72
|
+
}, null, 2));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
logger.success(`Signed in as ${creds.email}`);
|
|
76
|
+
logger.info(`Scope: ${scope}`);
|
|
77
|
+
logger.info(`Agent: ${creds.agent_id}`);
|
|
78
|
+
logger.info(`API base: ${creds.api_base}`);
|
|
79
|
+
if (creds.mcp_server_url) {
|
|
80
|
+
logger.info(`MCP server: ${creds.mcp_server_url}`);
|
|
81
|
+
}
|
|
82
|
+
logger.info('Run "gooseworks logout" then "gooseworks login" to switch accounts.');
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=whoami.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,qDAAqD;AACrD,wDAA0C;AAE1C;;;;;;;GAOG;AACU,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,oDAAoD,CAAC;KACjE,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC;KACnC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IACf,MAAM,KAAK,GAAG,IAAA,4BAAc,GAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,IAAI,OAAO,CAAC;IAC1C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ;YACE,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,QAAQ;YAC1D,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,cAAc,EAAE,KAAK,CAAC,cAAc,IAAI,IAAI;SAC7C,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,gBAAgB,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9C,MAAM,CAAC,IAAI,CAAC,eAAe,KAAK,EAAE,CAAC,CAAC;IACpC,MAAM,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,MAAM,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;AACrF,CAAC,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const commander_1 = require("commander");
|
|
|
5
5
|
const install_1 = require("./commands/install");
|
|
6
6
|
const login_1 = require("./commands/login");
|
|
7
7
|
const logout_1 = require("./commands/logout");
|
|
8
|
+
const whoami_1 = require("./commands/whoami");
|
|
8
9
|
const update_1 = require("./commands/update");
|
|
9
10
|
const credits_1 = require("./commands/credits");
|
|
10
11
|
const search_1 = require("./commands/search");
|
|
@@ -24,6 +25,7 @@ program
|
|
|
24
25
|
program.addCommand(install_1.installCommand);
|
|
25
26
|
program.addCommand(login_1.loginCommand);
|
|
26
27
|
program.addCommand(logout_1.logoutCommand);
|
|
28
|
+
program.addCommand(whoami_1.whoamiCommand);
|
|
27
29
|
program.addCommand(update_1.updateCommand);
|
|
28
30
|
program.addCommand(credits_1.creditsCommand);
|
|
29
31
|
program.addCommand(search_1.searchCommand);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,gDAAoD;AACpD,4CAAgD;AAChD,8CAAkD;AAClD,8CAAkD;AAClD,gDAAoD;AACpD,8CAAkD;AAClD,4CAAgD;AAChD,wCAA4C;AAC5C,0CAA8C;AAC9C,sDAA0D;AAC1D,8CAAkD;AAClD,gDAAoD;AACpD,8CAAkD;AAClD,uCAAuC;AAEvC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,IAAA,oBAAU,GAAE,CAAC,CAAC;AAEzB,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,gBAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,kBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,8BAAiB,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,gDAAoD;AACpD,4CAAgD;AAChD,8CAAkD;AAClD,8CAAkD;AAClD,8CAAkD;AAClD,gDAAoD;AACpD,8CAAkD;AAClD,4CAAgD;AAChD,wCAA4C;AAC5C,0CAA8C;AAC9C,sDAA0D;AAC1D,8CAAkD;AAClD,gDAAoD;AACpD,8CAAkD;AAClD,uCAAuC;AAEvC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,IAAA,oBAAU,GAAE,CAAC,CAAC;AAEzB,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,gBAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,kBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,8BAAiB,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-skill.d.ts","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oDAAoD;AACpD,wBAAgB,cAAc,IAAI,UAAU,EAAE,CAM7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA0L9C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAsUhD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"master-skill.d.ts","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oDAAoD;AACpD,wBAAgB,cAAc,IAAI,UAAU,EAAE,CAM7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA0L9C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAsUhD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CA8WlD"}
|
|
@@ -583,8 +583,17 @@ tags: [gooseworks, ads, video, remix, imessage, local-render, byoa]
|
|
|
583
583
|
|
|
584
584
|
You produce **video** ad creative on the user's OWN machine and sync the result back to the
|
|
585
585
|
GooseWorks app over MCP. This document is the **runtime contract** (auth, credits, the media
|
|
586
|
-
proxies, data I/O, the review gate). A separate **recipe skill** — fetched per format — tells
|
|
587
|
-
|
|
586
|
+
proxies, data I/O, the review gate). A separate **recipe skill** — fetched per format — tells you
|
|
587
|
+
*what to make* (the pieces, prompts, models, order of assembly).
|
|
588
|
+
|
|
589
|
+
**Division of authority — read both, but when they disagree THIS doc wins on the environment AND the
|
|
590
|
+
review/approval flow.** The recipe governs WHAT to make; this doc governs WHEN you pause, generate,
|
|
591
|
+
and spend. In particular: a recipe may spell out a **multi-phase, multi-gate** flow — "generate the
|
|
592
|
+
still [GATE] → approve → author the prompt [GATE] → approve → render [GATE] → approve", several
|
|
593
|
+
separate pauses. **Do NOT run it that way.** Collapse every one of those gates into the single
|
|
594
|
+
**review-once** flow below: one review set, one approval (Step 3). Take the recipe's pieces, prompts
|
|
595
|
+
and models; ignore its intermediate pauses. This is the exact contradiction that confused past runs
|
|
596
|
+
(GOOSE-2542) — there is no ambiguity: review-once wins.
|
|
588
597
|
|
|
589
598
|
You run inside the user's own Claude Code session (they pasted an instruction with a project
|
|
590
599
|
id). The app NEVER runs you — it is the viewer + review surface; you are the renderer.
|
|
@@ -653,14 +662,18 @@ says to shell out, use the MCP equivalent:
|
|
|
653
662
|
stays the project-relative \`...render-file?path=working/final.mp4\` — the route re-prepends the
|
|
654
663
|
prefix itself. Always verify with \`get_download_url\` on the FULL \`agent-config/...\` path (must
|
|
655
664
|
be non-empty; curl it for HTTP 200) BEFORE marking the render complete.
|
|
656
|
-
- Media generation (FAL / ElevenLabs)
|
|
657
|
-
\`submit_render { kind: "full" }\`
|
|
658
|
-
|
|
659
|
-
|
|
665
|
+
- Media generation (FAL / ElevenLabs) through the GooseWorks proxies is the **REAL spend** — billed
|
|
666
|
+
to the agent per call as you generate (Step 4). \`submit_render { kind: "full" }\` additionally
|
|
667
|
+
debits **1 nominal ad credit when the render ROW is opened** (a bookkeeping fee, NOT the render's
|
|
668
|
+
true cost) — so open it only once you actually have a rendered master (Step 4.1/4.2), and never
|
|
669
|
+
re-submit on a guess (that double-bills). The final-video QC gate (Step 4.3) then sits between
|
|
670
|
+
that master and PINNING it. Call \`get_ad_credits\` first; the user can check \`gooseworks credits\`.
|
|
660
671
|
|
|
661
672
|
## Step 1 — resolve the project, source, brand
|
|
662
673
|
|
|
663
|
-
1. \`get_ad_project { project_id }\` → keep \`brand_id\`, \`source_sample_id\`, \`name\`, \`status
|
|
674
|
+
1. \`get_ad_project { project_id }\` → keep \`brand_id\`, \`source_sample_id\`, \`name\`, \`status\`, and
|
|
675
|
+
the **top-level** \`app_url\` + \`brand_url\` (returned alongside \`project\`, NOT inside it) — these
|
|
676
|
+
are the links you hand the user for the in-app review (Step 3) and the final delivery (Step 5).
|
|
664
677
|
2. \`get_ad_template { template_id: source_sample_id }\` → the source video: \`media_url\`,
|
|
665
678
|
\`recipe\`, \`format\` (e.g. "imessage"), \`extracted_script\`, \`how_to\`, \`remix_spec\`.
|
|
666
679
|
3. Brand gate: \`get_brand_kit { brand_id }\`. If \`researchStatus\` is \`complete\`, REUSE it —
|
|
@@ -696,32 +709,55 @@ Playwright resolve, and point the recorder's \`NODE_PATH\` at it.
|
|
|
696
709
|
> recipe does not yet carry \`atoms\` / \`instructions\` still hold the legacy \`recipe.thread\` payload;
|
|
697
710
|
> migrate them to this shape (capabilities + instructions in the DB) — do not reintroduce a CLI map.
|
|
698
711
|
|
|
699
|
-
## Step 3 —
|
|
700
|
-
|
|
701
|
-
This is a **review-once** flow:
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
**
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
712
|
+
## Step 3 — assemble the review set, then get ONE approval in the app (before the expensive render)
|
|
713
|
+
|
|
714
|
+
This is a **review-once** flow: put the whole review set in the app, get ONE approval, then run the
|
|
715
|
+
expensive render + any remaining paid work end-to-end. Never spend on the expensive render before
|
|
716
|
+
approval, and don't drip pieces out one at a time and re-pause.
|
|
717
|
+
|
|
718
|
+
**What goes in the review — show the REAL cheap pieces, PROMPT only the expensive render.** Split
|
|
719
|
+
every piece three ways by cost, NOT just "free vs paid":
|
|
720
|
+
- **FREE** (an iMessage / Apple-Notes HTML mockup, a text/CTA line — rendered locally, no proxy
|
|
721
|
+
call) → generate NOW and mirror the real asset.
|
|
722
|
+
- **CHEAP paid** — a single still/image, the creator/avatar frame, the end card, a short voiceover
|
|
723
|
+
or music bed (each costs cents → roughly **≤ 100 credits**) → **generate these NOW too** and
|
|
724
|
+
mirror the real asset. The few credits buy a real review: the user SEES the actual creator face
|
|
725
|
+
and end card and HEARS the VO, instead of judging a prompt. **This OVERRIDES any recipe rule that
|
|
726
|
+
says to gate ALL paid calls** — only the expensive render below is gated.
|
|
727
|
+
- **EXPENSIVE paid** — the video take / final AI render (hundreds of credits) → do NOT generate.
|
|
728
|
+
Put its **exact prompt/spec** (+ ref image URLs) in the tile. This is the ONE thing approved as a
|
|
729
|
+
prompt (you can't preview a hundreds-of-credits video for free); it's generated only in Step 4.
|
|
730
|
+
|
|
731
|
+
**The expensive render's exact prompt must be in the panel BEFORE you ask for approval** — so a
|
|
732
|
+
single "go" runs it (plus any remaining paid work) without re-pausing mid-run.
|
|
733
|
+
|
|
734
|
+
**Show every cost in CREDITS, never dollars.** 1 credit = $0.01 and media generations bill at
|
|
735
|
+
provider-cost × 1.2, so **credits ≈ round-up(provider-$ × 120)** per generation, plus a flat
|
|
736
|
+
**200-credit base per video**. Convert any $ figures to credits and show ONLY credits to the user —
|
|
737
|
+
never print a "$…" amount.
|
|
738
|
+
|
|
739
|
+
**Never assemble/stitch the finished video for review.** The review is of the individual pieces (or
|
|
740
|
+
their prompts) — never a "full cascade" / "approved cut" clip. Building the whole video before
|
|
741
|
+
approval defeats the gate (the user opens the review to an already-finished video) and wastes the
|
|
742
|
+
render (GOOSE-2542). The full video is assembled ONLY in Step 4, after approval. A \`video\`
|
|
743
|
+
ingredient here is only a genuinely separate SOURCE clip the format needs (e.g. supplied b-roll).
|
|
744
|
+
|
|
745
|
+
1. **Assemble every piece the format needs — not just the script.** Read the recipe for the exact
|
|
746
|
+
list. For an iMessage video that's the **script** (bubble thread), the **conversation image(s)**,
|
|
747
|
+
and the **end card**; richer templates add a hook frame, background, product shots, music bed, a
|
|
748
|
+
creator/avatar, a voiceover… For each piece, decide FREE / CHEAP-paid / EXPENSIVE-paid (above):
|
|
749
|
+
- **FREE or CHEAP paid** (≤ ~100 credits — HTML mockups, a still, the creator frame, the end
|
|
750
|
+
card, a short VO/music bed) → generate it now and \`get_upload_url\` the asset to the project
|
|
751
|
+
folder \`agent-config/brands/<brand_slug>/projects/<project_id>/working/review/<name>\` (same
|
|
752
|
+
path-prefix rule as final publish — a bare \`working/review/<name>\` won't render in the panel);
|
|
753
|
+
set that piece's \`path\` in \`script_drafts\` to the project-relative \`working/review/<name>\`.
|
|
754
|
+
- **EXPENSIVE paid** (the video take / final render, hundreds of credits) → do NOT generate. Put
|
|
755
|
+
the **exact prompt/spec** (and any ref image URLs) in the tile's \`text\` / \`subtitle\` so the
|
|
756
|
+
user reviews what will be spent on. No \`path\` yet — it's generated in Step 4.
|
|
757
|
+
Include the **estimated cost in CREDITS** (never dollars) of the cheap pieces already generated +
|
|
758
|
+
the pending render, so the user approves knowing the total spend. You may batch a couple of
|
|
759
|
+
clarifying questions first if the recipe calls for it (angle, which product, offer/code), then
|
|
760
|
+
assemble everything.
|
|
725
761
|
2. **Mirror the whole ingredient set for review** — \`update_ad_project_script { project_id,
|
|
726
762
|
script_drafts, script }\`. \`script_drafts\` is a structured payload of **container-tagged
|
|
727
763
|
ingredients** so the app renders each piece the right way:
|
|
@@ -736,21 +772,34 @@ assembled output.
|
|
|
736
772
|
for the podcast shape, or pass the readable \`script\` string).
|
|
737
773
|
\`path\` = \`working/review/<name>\` (upload the preview asset first via \`get_upload_url\`); \`url\`
|
|
738
774
|
works too. **Label every ingredient** ("Hook image", "End card", "Voiceover", "Background
|
|
739
|
-
music", "HER").
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
775
|
+
music", "HER"). The \`update_ad_project_script\` call itself writes no render and costs no credits
|
|
776
|
+
(the cheap pieces you already generated above have their own small cost) — it just populates the
|
|
777
|
+
review panel.
|
|
778
|
+
3. **STOP — the review happens in the APP's review panel, NOT in this chat.** You've mirrored the
|
|
779
|
+
ingredients (3.2); now hand the user the project's \`app_url\` (from \`get_ad_project\`) and tell
|
|
780
|
+
them to review the pieces there and hit **"Approve & render"**. That button gives them a short
|
|
781
|
+
message to paste back into this session — THAT is your go-ahead. Do NOT paste the
|
|
782
|
+
script/ingredients into the chat for a thumbs-up, and do NOT render until that approval comes
|
|
783
|
+
back from the app. If they want changes (via the app's comments or here), regenerate the
|
|
784
|
+
affected ingredient, call \`update_ad_project_script\` again, tell them it's refreshed in the
|
|
785
|
+
app, and wait for a fresh approval. Only AFTER the app approval do Step 4. A single approval
|
|
786
|
+
authorises the WHOLE remaining chain — generate every paid piece, render, self-QC, publish —
|
|
787
|
+
with NO further pauses (that is exactly why every paid prompt must already be in the panel).
|
|
743
788
|
|
|
744
789
|
## Step 4 — render locally, report stages, publish
|
|
745
790
|
|
|
746
|
-
1.
|
|
747
|
-
|
|
791
|
+
1. Now generate every PAID piece you showed as a prompt in Step 3 — the AI stills/video, voice,
|
|
792
|
+
music, the end-card render — through the media proxies (below), each from its approved prompt.
|
|
793
|
+
Then assemble per the recipe (Playwright record where needed → ffmpeg stitch → \`mix-master\`
|
|
794
|
+
audio).
|
|
748
795
|
2. Open the row LAST: \`submit_render { project_id, kind: "full" }\` → keep \`render_id\`, then
|
|
749
796
|
\`update_render_status { render_id, status: "running" }\`. The render row tracks status only
|
|
750
797
|
(queued / running / complete / failed) — narrate fine-grained progress with
|
|
751
798
|
\`append_project_message\` instead.
|
|
752
|
-
3. **MANDATORY final-video
|
|
753
|
-
whatever the format (UGC or not).**
|
|
799
|
+
3. **MANDATORY final-video QC gate — YOU review EVERY finished master before \`set_final_render\`,
|
|
800
|
+
whatever the format (UGC or not).** This is your own automated quality check, separate from the
|
|
801
|
+
user's Step-3 approval — it does not go back to the user. The render row is already open (its
|
|
802
|
+
nominal credit spent, \`submit_render\` in 4.2);
|
|
754
803
|
this gate stands between a rendered master and PINNING/publishing it, so a bad render never gets
|
|
755
804
|
set as final. A master that looks fine on a still can still have a mis-voiced word, a caption
|
|
756
805
|
drifting off its line, a beat out of order, or a deformation — review the actual VIDEO, not
|
|
@@ -854,13 +903,23 @@ path. (\`fal-storage-proxy\` may 404 depending on the install; don't block on it
|
|
|
854
903
|
|
|
855
904
|
- **MCP + ffmpeg + Playwright required** — run \`gooseworks doctor\` in Phase 0; stop with the
|
|
856
905
|
exact fix it prints if anything is ✗.
|
|
857
|
-
- **
|
|
858
|
-
the
|
|
859
|
-
|
|
860
|
-
- **
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
906
|
+
- **Assemble the whole review set first**, mirror it with \`update_ad_project_script\`, and get the
|
|
907
|
+
user's approval **in the app's review panel** (the "Approve & render" button) BEFORE the expensive
|
|
908
|
+
render — never ask for a thumbs-up in this chat (review-once, in-app).
|
|
909
|
+
- **Show the REAL cheap pieces; PROMPT only the expensive render.** Generate the FREE + CHEAP-paid
|
|
910
|
+
pieces (≤ ~100 credits — stills, creator frame, end card, short VO/music) and mirror the real
|
|
911
|
+
assets; put ONLY the expensive video take/render in the panel as its exact prompt. That prompt
|
|
912
|
+
must be in the panel before you ask to approve, so a single "go" runs the render + any remaining
|
|
913
|
+
paid work (→ QC → publish) with no re-pausing.
|
|
914
|
+
- **Costs in CREDITS, never dollars.** credits ≈ round-up(provider-$ × 120) per generation + a flat
|
|
915
|
+
200-credit base per video; never show a "$…" figure to the user.
|
|
916
|
+
- **Never assemble the full video before approval.** The review shows the
|
|
917
|
+
individual PIECES, never the finished cut (or their prompts) — not a
|
|
918
|
+
stitched/composited cut; do not add a "full cascade" / finished-video clip
|
|
919
|
+
as a review ingredient (GOOSE-2542). The assembled video is produced only in
|
|
920
|
+
Step 4.
|
|
921
|
+
- **submit_render only after the master is rendered** (Step 4.2), never on a guess; \`output_url\` =
|
|
922
|
+
the durable render-file URL, never a CDN URL.
|
|
864
923
|
- **Always pass \`project_id\` on media-proxy calls** (fal / ElevenLabs) so the credits attribute
|
|
865
924
|
to this ad project — that's what lets the user see per-project spend in the app.
|
|
866
925
|
- **Verify a real, non-empty MP4** (watch it) before marking the render complete.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;AA4BA,wCAMC;AAWD,sDA0LC;AAiBD,0DAsUC;AAcD,
|
|
1
|
+
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;AA4BA,wCAMC;AAWD,sDA0LC;AAiBD,0DAsUC;AAcD,8DA8WC;AA/5BD,oDAAoD;AACpD,SAAgB,cAAc;IAC5B,OAAO;QACL,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAE;QACxD,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,uBAAuB,EAAE,EAAE;QACzD,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE;KAC9D,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwLR,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoUR,CAAC;AACF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,yBAAyB;IACvC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4WR,CAAC;AACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -18,8 +18,17 @@ tags: [gooseworks, ads, video, remix, imessage, local-render, byoa]
|
|
|
18
18
|
|
|
19
19
|
You produce **video** ad creative on the user's OWN machine and sync the result back to the
|
|
20
20
|
GooseWorks app over MCP. This document is the **runtime contract** (auth, credits, the media
|
|
21
|
-
proxies, data I/O, the review gate). A separate **recipe skill** — fetched per format — tells
|
|
22
|
-
|
|
21
|
+
proxies, data I/O, the review gate). A separate **recipe skill** — fetched per format — tells you
|
|
22
|
+
*what to make* (the pieces, prompts, models, order of assembly).
|
|
23
|
+
|
|
24
|
+
**Division of authority — read both, but when they disagree THIS doc wins on the environment AND the
|
|
25
|
+
review/approval flow.** The recipe governs WHAT to make; this doc governs WHEN you pause, generate,
|
|
26
|
+
and spend. In particular: a recipe may spell out a **multi-phase, multi-gate** flow — "generate the
|
|
27
|
+
still [GATE] → approve → author the prompt [GATE] → approve → render [GATE] → approve", several
|
|
28
|
+
separate pauses. **Do NOT run it that way.** Collapse every one of those gates into the single
|
|
29
|
+
**review-once** flow below: one review set, one approval (Step 3). Take the recipe's pieces, prompts
|
|
30
|
+
and models; ignore its intermediate pauses. This is the exact contradiction that confused past runs
|
|
31
|
+
(GOOSE-2542) — there is no ambiguity: review-once wins.
|
|
23
32
|
|
|
24
33
|
You run inside the user's own Claude Code session (they pasted an instruction with a project
|
|
25
34
|
id). The app NEVER runs you — it is the viewer + review surface; you are the renderer.
|
|
@@ -88,14 +97,18 @@ says to shell out, use the MCP equivalent:
|
|
|
88
97
|
stays the project-relative `...render-file?path=working/final.mp4` — the route re-prepends the
|
|
89
98
|
prefix itself. Always verify with `get_download_url` on the FULL `agent-config/...` path (must
|
|
90
99
|
be non-empty; curl it for HTTP 200) BEFORE marking the render complete.
|
|
91
|
-
- Media generation (FAL / ElevenLabs)
|
|
92
|
-
`submit_render { kind: "full" }`
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
- Media generation (FAL / ElevenLabs) through the GooseWorks proxies is the **REAL spend** — billed
|
|
101
|
+
to the agent per call as you generate (Step 4). `submit_render { kind: "full" }` additionally
|
|
102
|
+
debits **1 nominal ad credit when the render ROW is opened** (a bookkeeping fee, NOT the render's
|
|
103
|
+
true cost) — so open it only once you actually have a rendered master (Step 4.1/4.2), and never
|
|
104
|
+
re-submit on a guess (that double-bills). The final-video QC gate (Step 4.3) then sits between
|
|
105
|
+
that master and PINNING it. Call `get_ad_credits` first; the user can check `gooseworks credits`.
|
|
95
106
|
|
|
96
107
|
## Step 1 — resolve the project, source, brand
|
|
97
108
|
|
|
98
|
-
1. `get_ad_project { project_id }` → keep `brand_id`, `source_sample_id`, `name`, `status
|
|
109
|
+
1. `get_ad_project { project_id }` → keep `brand_id`, `source_sample_id`, `name`, `status`, and
|
|
110
|
+
the **top-level** `app_url` + `brand_url` (returned alongside `project`, NOT inside it) — these
|
|
111
|
+
are the links you hand the user for the in-app review (Step 3) and the final delivery (Step 5).
|
|
99
112
|
2. `get_ad_template { template_id: source_sample_id }` → the source video: `media_url`,
|
|
100
113
|
`recipe`, `format` (e.g. "imessage"), `extracted_script`, `how_to`, `remix_spec`.
|
|
101
114
|
3. Brand gate: `get_brand_kit { brand_id }`. If `researchStatus` is `complete`, REUSE it —
|
|
@@ -131,32 +144,55 @@ Playwright resolve, and point the recorder's `NODE_PATH` at it.
|
|
|
131
144
|
> recipe does not yet carry `atoms` / `instructions` still hold the legacy `recipe.thread` payload;
|
|
132
145
|
> migrate them to this shape (capabilities + instructions in the DB) — do not reintroduce a CLI map.
|
|
133
146
|
|
|
134
|
-
## Step 3 —
|
|
135
|
-
|
|
136
|
-
This is a **review-once** flow:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
**
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
147
|
+
## Step 3 — assemble the review set, then get ONE approval in the app (before the expensive render)
|
|
148
|
+
|
|
149
|
+
This is a **review-once** flow: put the whole review set in the app, get ONE approval, then run the
|
|
150
|
+
expensive render + any remaining paid work end-to-end. Never spend on the expensive render before
|
|
151
|
+
approval, and don't drip pieces out one at a time and re-pause.
|
|
152
|
+
|
|
153
|
+
**What goes in the review — show the REAL cheap pieces, PROMPT only the expensive render.** Split
|
|
154
|
+
every piece three ways by cost, NOT just "free vs paid":
|
|
155
|
+
- **FREE** (an iMessage / Apple-Notes HTML mockup, a text/CTA line — rendered locally, no proxy
|
|
156
|
+
call) → generate NOW and mirror the real asset.
|
|
157
|
+
- **CHEAP paid** — a single still/image, the creator/avatar frame, the end card, a short voiceover
|
|
158
|
+
or music bed (each costs cents → roughly **≤ 100 credits**) → **generate these NOW too** and
|
|
159
|
+
mirror the real asset. The few credits buy a real review: the user SEES the actual creator face
|
|
160
|
+
and end card and HEARS the VO, instead of judging a prompt. **This OVERRIDES any recipe rule that
|
|
161
|
+
says to gate ALL paid calls** — only the expensive render below is gated.
|
|
162
|
+
- **EXPENSIVE paid** — the video take / final AI render (hundreds of credits) → do NOT generate.
|
|
163
|
+
Put its **exact prompt/spec** (+ ref image URLs) in the tile. This is the ONE thing approved as a
|
|
164
|
+
prompt (you can't preview a hundreds-of-credits video for free); it's generated only in Step 4.
|
|
165
|
+
|
|
166
|
+
**The expensive render's exact prompt must be in the panel BEFORE you ask for approval** — so a
|
|
167
|
+
single "go" runs it (plus any remaining paid work) without re-pausing mid-run.
|
|
168
|
+
|
|
169
|
+
**Show every cost in CREDITS, never dollars.** 1 credit = $0.01 and media generations bill at
|
|
170
|
+
provider-cost × 1.2, so **credits ≈ round-up(provider-$ × 120)** per generation, plus a flat
|
|
171
|
+
**200-credit base per video**. Convert any $ figures to credits and show ONLY credits to the user —
|
|
172
|
+
never print a "$…" amount.
|
|
173
|
+
|
|
174
|
+
**Never assemble/stitch the finished video for review.** The review is of the individual pieces (or
|
|
175
|
+
their prompts) — never a "full cascade" / "approved cut" clip. Building the whole video before
|
|
176
|
+
approval defeats the gate (the user opens the review to an already-finished video) and wastes the
|
|
177
|
+
render (GOOSE-2542). The full video is assembled ONLY in Step 4, after approval. A `video`
|
|
178
|
+
ingredient here is only a genuinely separate SOURCE clip the format needs (e.g. supplied b-roll).
|
|
179
|
+
|
|
180
|
+
1. **Assemble every piece the format needs — not just the script.** Read the recipe for the exact
|
|
181
|
+
list. For an iMessage video that's the **script** (bubble thread), the **conversation image(s)**,
|
|
182
|
+
and the **end card**; richer templates add a hook frame, background, product shots, music bed, a
|
|
183
|
+
creator/avatar, a voiceover… For each piece, decide FREE / CHEAP-paid / EXPENSIVE-paid (above):
|
|
184
|
+
- **FREE or CHEAP paid** (≤ ~100 credits — HTML mockups, a still, the creator frame, the end
|
|
185
|
+
card, a short VO/music bed) → generate it now and `get_upload_url` the asset to the project
|
|
186
|
+
folder `agent-config/brands/<brand_slug>/projects/<project_id>/working/review/<name>` (same
|
|
187
|
+
path-prefix rule as final publish — a bare `working/review/<name>` won't render in the panel);
|
|
188
|
+
set that piece's `path` in `script_drafts` to the project-relative `working/review/<name>`.
|
|
189
|
+
- **EXPENSIVE paid** (the video take / final render, hundreds of credits) → do NOT generate. Put
|
|
190
|
+
the **exact prompt/spec** (and any ref image URLs) in the tile's `text` / `subtitle` so the
|
|
191
|
+
user reviews what will be spent on. No `path` yet — it's generated in Step 4.
|
|
192
|
+
Include the **estimated cost in CREDITS** (never dollars) of the cheap pieces already generated +
|
|
193
|
+
the pending render, so the user approves knowing the total spend. You may batch a couple of
|
|
194
|
+
clarifying questions first if the recipe calls for it (angle, which product, offer/code), then
|
|
195
|
+
assemble everything.
|
|
160
196
|
2. **Mirror the whole ingredient set for review** — `update_ad_project_script { project_id,
|
|
161
197
|
script_drafts, script }`. `script_drafts` is a structured payload of **container-tagged
|
|
162
198
|
ingredients** so the app renders each piece the right way:
|
|
@@ -171,21 +207,34 @@ assembled output.
|
|
|
171
207
|
for the podcast shape, or pass the readable `script` string).
|
|
172
208
|
`path` = `working/review/<name>` (upload the preview asset first via `get_upload_url`); `url`
|
|
173
209
|
works too. **Label every ingredient** ("Hook image", "End card", "Voiceover", "Background
|
|
174
|
-
music", "HER").
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
210
|
+
music", "HER"). The `update_ad_project_script` call itself writes no render and costs no credits
|
|
211
|
+
(the cheap pieces you already generated above have their own small cost) — it just populates the
|
|
212
|
+
review panel.
|
|
213
|
+
3. **STOP — the review happens in the APP's review panel, NOT in this chat.** You've mirrored the
|
|
214
|
+
ingredients (3.2); now hand the user the project's `app_url` (from `get_ad_project`) and tell
|
|
215
|
+
them to review the pieces there and hit **"Approve & render"**. That button gives them a short
|
|
216
|
+
message to paste back into this session — THAT is your go-ahead. Do NOT paste the
|
|
217
|
+
script/ingredients into the chat for a thumbs-up, and do NOT render until that approval comes
|
|
218
|
+
back from the app. If they want changes (via the app's comments or here), regenerate the
|
|
219
|
+
affected ingredient, call `update_ad_project_script` again, tell them it's refreshed in the
|
|
220
|
+
app, and wait for a fresh approval. Only AFTER the app approval do Step 4. A single approval
|
|
221
|
+
authorises the WHOLE remaining chain — generate every paid piece, render, self-QC, publish —
|
|
222
|
+
with NO further pauses (that is exactly why every paid prompt must already be in the panel).
|
|
178
223
|
|
|
179
224
|
## Step 4 — render locally, report stages, publish
|
|
180
225
|
|
|
181
|
-
1.
|
|
182
|
-
|
|
226
|
+
1. Now generate every PAID piece you showed as a prompt in Step 3 — the AI stills/video, voice,
|
|
227
|
+
music, the end-card render — through the media proxies (below), each from its approved prompt.
|
|
228
|
+
Then assemble per the recipe (Playwright record where needed → ffmpeg stitch → `mix-master`
|
|
229
|
+
audio).
|
|
183
230
|
2. Open the row LAST: `submit_render { project_id, kind: "full" }` → keep `render_id`, then
|
|
184
231
|
`update_render_status { render_id, status: "running" }`. The render row tracks status only
|
|
185
232
|
(queued / running / complete / failed) — narrate fine-grained progress with
|
|
186
233
|
`append_project_message` instead.
|
|
187
|
-
3. **MANDATORY final-video
|
|
188
|
-
whatever the format (UGC or not).**
|
|
234
|
+
3. **MANDATORY final-video QC gate — YOU review EVERY finished master before `set_final_render`,
|
|
235
|
+
whatever the format (UGC or not).** This is your own automated quality check, separate from the
|
|
236
|
+
user's Step-3 approval — it does not go back to the user. The render row is already open (its
|
|
237
|
+
nominal credit spent, `submit_render` in 4.2);
|
|
189
238
|
this gate stands between a rendered master and PINNING/publishing it, so a bad render never gets
|
|
190
239
|
set as final. A master that looks fine on a still can still have a mis-voiced word, a caption
|
|
191
240
|
drifting off its line, a beat out of order, or a deformation — review the actual VIDEO, not
|
|
@@ -289,13 +338,23 @@ path. (`fal-storage-proxy` may 404 depending on the install; don't block on it
|
|
|
289
338
|
|
|
290
339
|
- **MCP + ffmpeg + Playwright required** — run `gooseworks doctor` in Phase 0; stop with the
|
|
291
340
|
exact fix it prints if anything is ✗.
|
|
292
|
-
- **
|
|
293
|
-
the
|
|
294
|
-
|
|
295
|
-
- **
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
341
|
+
- **Assemble the whole review set first**, mirror it with `update_ad_project_script`, and get the
|
|
342
|
+
user's approval **in the app's review panel** (the "Approve & render" button) BEFORE the expensive
|
|
343
|
+
render — never ask for a thumbs-up in this chat (review-once, in-app).
|
|
344
|
+
- **Show the REAL cheap pieces; PROMPT only the expensive render.** Generate the FREE + CHEAP-paid
|
|
345
|
+
pieces (≤ ~100 credits — stills, creator frame, end card, short VO/music) and mirror the real
|
|
346
|
+
assets; put ONLY the expensive video take/render in the panel as its exact prompt. That prompt
|
|
347
|
+
must be in the panel before you ask to approve, so a single "go" runs the render + any remaining
|
|
348
|
+
paid work (→ QC → publish) with no re-pausing.
|
|
349
|
+
- **Costs in CREDITS, never dollars.** credits ≈ round-up(provider-$ × 120) per generation + a flat
|
|
350
|
+
200-credit base per video; never show a "$…" figure to the user.
|
|
351
|
+
- **Never assemble the full video before approval.** The review shows the
|
|
352
|
+
individual PIECES, never the finished cut (or their prompts) — not a
|
|
353
|
+
stitched/composited cut; do not add a "full cascade" / finished-video clip
|
|
354
|
+
as a review ingredient (GOOSE-2542). The assembled video is produced only in
|
|
355
|
+
Step 4.
|
|
356
|
+
- **submit_render only after the master is rendered** (Step 4.2), never on a guess; `output_url` =
|
|
357
|
+
the durable render-file URL, never a CDN URL.
|
|
299
358
|
- **Always pass `project_id` on media-proxy calls** (fal / ElevenLabs) so the credits attribute
|
|
300
359
|
to this ad project — that's what lets the user see per-project spend in the app.
|
|
301
360
|
- **Verify a real, non-empty MP4** (watch it) before marking the render complete.
|