gooseworks 0.3.16 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.claude-plugin/marketplace.json +27 -0
  2. package/.claude-plugin/plugin.json +3 -0
  3. package/README.md +9 -9
  4. package/dist/agents/claude.js +1 -1
  5. package/dist/agents/claude.js.map +1 -1
  6. package/dist/agents/codex.js +1 -1
  7. package/dist/agents/codex.js.map +1 -1
  8. package/dist/agents/skill-links.d.ts +7 -2
  9. package/dist/agents/skill-links.d.ts.map +1 -1
  10. package/dist/agents/skill-links.js +10 -5
  11. package/dist/agents/skill-links.js.map +1 -1
  12. package/dist/commands/install.d.ts.map +1 -1
  13. package/dist/commands/install.js +11 -6
  14. package/dist/commands/install.js.map +1 -1
  15. package/dist/commands/login.d.ts.map +1 -1
  16. package/dist/commands/login.js +4 -23
  17. package/dist/commands/login.js.map +1 -1
  18. package/dist/config.d.ts +1 -1
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/config.js +6 -2
  21. package/dist/config.js.map +1 -1
  22. package/dist/skills/installer.d.ts +9 -0
  23. package/dist/skills/installer.d.ts.map +1 -1
  24. package/dist/skills/installer.js +20 -6
  25. package/dist/skills/installer.js.map +1 -1
  26. package/dist/skills/master-skill.d.ts +24 -22
  27. package/dist/skills/master-skill.d.ts.map +1 -1
  28. package/dist/skills/master-skill.js +251 -66
  29. package/dist/skills/master-skill.js.map +1 -1
  30. package/dist/skills/names.d.ts +53 -1
  31. package/dist/skills/names.d.ts.map +1 -1
  32. package/dist/skills/names.js +107 -7
  33. package/dist/skills/names.js.map +1 -1
  34. package/dist/skills/routes.d.ts +68 -0
  35. package/dist/skills/routes.d.ts.map +1 -0
  36. package/dist/skills/routes.js +124 -0
  37. package/dist/skills/routes.js.map +1 -0
  38. package/package.json +1 -1
  39. package/skills/goose-ads/SKILL.md +23 -3
  40. package/skills/goose-product-photos/SKILL.md +27 -3
  41. package/skills/gooseworks/SKILL.md +50 -49
  42. package/skills/routes.json +157 -0
@@ -1,12 +1,112 @@
1
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
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.LEGACY_ENTRY_SKILL_NAMES = exports.STAMP_FILE = void 0;
37
+ exports.getManagedEntrySkillNames = getManagedEntrySkillNames;
38
+ exports.isManagedEntrySkillName = isManagedEntrySkillName;
39
+ exports.hasGooseworksStamp = hasGooseworksStamp;
3
40
  exports.isManagedGooseworksSkill = isManagedGooseworksSkill;
4
- function isManagedGooseworksSkill(name) {
5
- return (name === 'gooseworks' ||
6
- // `ads-remix` was renamed to `goose-ads`; keep it managed so a stale
7
- // ads-remix dir from an older install is cleaned up on the next install.
8
- name === 'ads-remix' ||
9
- name.startsWith('gooseworks-') ||
10
- name.startsWith('goose-'));
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const master_skill_1 = require("./master-skill");
44
+ /**
45
+ * Which directories under ~/.agents/skills/ the CLI is allowed to DELETE.
46
+ *
47
+ * GOOSE-3191 (data loss): this predicate used to match ANY directory whose name
48
+ * started with `goose-` or `gooseworks-`. `gooseworks install` calls
49
+ * `removeAllSkills()` on every install / update / login-refresh, so a user's own
50
+ * unrelated third-party skill — `goose-notes`, `goose-jira`, anything they wrote
51
+ * themselves — was silently destroyed. A name prefix is NOT ownership.
52
+ *
53
+ * The rule now, in order of authority:
54
+ *
55
+ * 1. **Known entry-skill slugs** (`gooseworks`, `goose-ads`, `goose-video`,
56
+ * `goose-product-photos`, plus the legacy `ads-remix` name) are ours by
57
+ * definition — they are the dirs the CLI itself writes on every install, so
58
+ * we delete them regardless of whether they carry a stamp. This is what
59
+ * keeps upgrades from an old CLI working.
60
+ * 2. **A `.gooseworks-version` stamp** marks a directory the installer wrote.
61
+ * It is a SECONDARY signal, used to recognise standalone skills installed
62
+ * with `--with <slug>` (whose slugs we can't enumerate ahead of time).
63
+ * 3. **Anything else is the user's.** An unstamped directory that is not a
64
+ * known entry slug is NEVER deleted, no matter what it's called.
65
+ *
66
+ * Deliberate, documented trade-off: a standalone skill installed by an OLDER CLI
67
+ * (before `installStandaloneSkill` wrote a stamp) is unstamped and therefore no
68
+ * longer removed by `removeAllSkills()`. That is the safe direction to be wrong —
69
+ * it leaves a stale-but-working copy on disk instead of deleting a stranger's
70
+ * work — and it self-heals: re-running `gooseworks install --with <slug>`
71
+ * replaces the directory in place and stamps it.
72
+ */
73
+ /** The stamp file `installEntrySkill` / `installStandaloneSkill` write. */
74
+ exports.STAMP_FILE = '.gooseworks-version';
75
+ /**
76
+ * Entry-skill dir names the CLI no longer writes but must still clean up.
77
+ * `ads-remix` was renamed to `goose-ads`.
78
+ */
79
+ exports.LEGACY_ENTRY_SKILL_NAMES = ['ads-remix'];
80
+ /**
81
+ * Every skill directory name the CLI itself owns and writes. Derived from
82
+ * `getEntrySkills()` so the registry stays the single source (GOOSE-3190).
83
+ */
84
+ function getManagedEntrySkillNames() {
85
+ return [...(0, master_skill_1.getEntrySkillNames)(), ...exports.LEGACY_ENTRY_SKILL_NAMES];
86
+ }
87
+ /** True when `name` is a skill directory the CLI itself installs. */
88
+ function isManagedEntrySkillName(name) {
89
+ return getManagedEntrySkillNames().includes(name);
90
+ }
91
+ /** True when `<skillsBase>/<name>/.gooseworks-version` exists. */
92
+ function hasGooseworksStamp(skillsBase, name) {
93
+ try {
94
+ return fs.existsSync(path.join(skillsBase, name, exports.STAMP_FILE));
95
+ }
96
+ catch {
97
+ return false;
98
+ }
99
+ }
100
+ /**
101
+ * True when the CLI may manage (link, list, and DELETE) `<skillsBase>/<name>/`.
102
+ *
103
+ * `skillsBase` is required: ownership is a property of what's ON DISK, not of
104
+ * the name. Callers that only have a name (e.g. pruning symlinks in
105
+ * ~/.claude/skills) pass the skills base the links point into.
106
+ */
107
+ function isManagedGooseworksSkill(name, skillsBase) {
108
+ if (isManagedEntrySkillName(name))
109
+ return true;
110
+ return hasGooseworksStamp(skillsBase, name);
11
111
  }
12
112
  //# sourceMappingURL=names.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/skills/names.ts"],"names":[],"mappings":";;AAAA,4DASC;AATD,SAAgB,wBAAwB,CAAC,IAAY;IACnD,OAAO,CACL,IAAI,KAAK,YAAY;QACrB,qEAAqE;QACrE,yEAAyE;QACzE,IAAI,KAAK,WAAW;QACpB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAC1B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/skills/names.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,8DAEC;AAGD,0DAEC;AAGD,gDAMC;AASD,4DAGC;AA3ED,uCAAyB;AACzB,2CAA6B;AAC7B,iDAAoD;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,2EAA2E;AAC9D,QAAA,UAAU,GAAG,qBAAqB,CAAC;AAEhD;;;GAGG;AACU,QAAA,wBAAwB,GAAG,CAAC,WAAW,CAAU,CAAC;AAE/D;;;GAGG;AACH,SAAgB,yBAAyB;IACvC,OAAO,CAAC,GAAG,IAAA,iCAAkB,GAAE,EAAE,GAAG,gCAAwB,CAAC,CAAC;AAChE,CAAC;AAED,qEAAqE;AACrE,SAAgB,uBAAuB,CAAC,IAAY;IAClD,OAAO,yBAAyB,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,kEAAkE;AAClE,SAAgB,kBAAkB,CAAC,UAAkB,EAAE,IAAY;IACjE,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,kBAAU,CAAC,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,wBAAwB,CAAC,IAAY,EAAE,UAAkB;IACvE,IAAI,uBAAuB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * THE routing table for the GooseWorks skill family (GOOSE-3190).
3
+ *
4
+ * Routing used to be written out by hand in THREE places that drifted apart:
5
+ * 1. this CLI's `gooseworks` router SKILL.md (`master-skill.ts`),
6
+ * 2. the backend's hosted-connector pointer
7
+ * (`gooseworks-app/backend/src/app-mcp-server/lib/ads-skill.ts`),
8
+ * 3. the public skills repo's `collections/brand-growth`.
9
+ *
10
+ * This file is now the SINGLE SOURCE. `master-skill.ts` renders its markdown
11
+ * tables from here (no hand-written route rows), `npm run generate:skills`
12
+ * emits the machine-readable copy to `skills/routes.json` for the other two
13
+ * repos to derive from, and `tests/skills/route-drift.test.ts` fails when any
14
+ * of the three names a skill the others don't.
15
+ *
16
+ * The two consumers we cannot edit from this repo are represented by checked-in
17
+ * snapshots under `tests/fixtures/`; each snapshot names the file to update when
18
+ * the drift test fires.
19
+ */
20
+ /** How a routed skill reaches the agent. */
21
+ export type RouteDelivery =
22
+ /** Vendored by this CLI and installed to ~/.agents/skills/. */
23
+ 'entry'
24
+ /** Lives in goose-skills; fetched on demand with `gooseworks fetch <slug>`. */
25
+ | 'fetch';
26
+ export interface DomainRoute {
27
+ /** The skill slug to route to. */
28
+ skill: string;
29
+ /** When this route applies — the left column of the router table. */
30
+ when: string;
31
+ /** How the agent gets the skill — the right column of the router table. */
32
+ how: string;
33
+ delivery: RouteDelivery;
34
+ }
35
+ export interface BrandGrowthRoute {
36
+ /** The job to be done. */
37
+ job: string;
38
+ /** The skill slug(s) that do it, in order. */
39
+ skills: string[];
40
+ }
41
+ /**
42
+ * Domain routes — the "Route to the right skill FIRST" table. These are the
43
+ * specialist skills the `gooseworks` router hands whole tasks to.
44
+ */
45
+ export declare const DOMAIN_ROUTES: DomainRoute[];
46
+ /**
47
+ * Brand Growth routes — the outcome skills in the `brand-growth` collection.
48
+ * Must stay in sync with `goose-skills/collections/brand-growth/routes.json`,
49
+ * which is derived from this list.
50
+ */
51
+ export declare const BRAND_GROWTH_ROUTES: BrandGrowthRoute[];
52
+ /** Every skill slug named by any route, deduped and sorted. */
53
+ export declare function getRoutedSkillSlugs(): string[];
54
+ /** Brand Growth slugs only (the ones the goose-skills collection must contain). */
55
+ export declare function getBrandGrowthSkillSlugs(): string[];
56
+ /** The machine-readable route table emitted to `skills/routes.json`. */
57
+ export declare function getRouteManifest(): {
58
+ $comment: string;
59
+ version: number;
60
+ domain_routes: DomainRoute[];
61
+ brand_growth_routes: BrandGrowthRoute[];
62
+ skills: string[];
63
+ };
64
+ /** Render the domain route table as the router SKILL.md markdown table body. */
65
+ export declare function renderDomainRouteTable(): string;
66
+ /** Render the Brand Growth job→skill table body. */
67
+ export declare function renderBrandGrowthTable(): string;
68
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/skills/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,4CAA4C;AAC5C,MAAM,MAAM,aAAa;AACvB,+DAA+D;AAC7D,OAAO;AACT,+EAA+E;GAC7E,OAAO,CAAC;AAEZ,MAAM,WAAW,WAAW;IAC1B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,WAAW,EA+BtC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,gBAAgB,EAkBjD,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAK9C;AAED,mFAAmF;AACnF,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAInD;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,IAAI;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,mBAAmB,EAAE,gBAAgB,EAAE,CAAC;IACxC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CASA;AAED,gFAAgF;AAChF,wBAAgB,sBAAsB,IAAI,MAAM,CAI/C;AAED,oDAAoD;AACpD,wBAAgB,sBAAsB,IAAI,MAAM,CAI/C"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ /**
3
+ * THE routing table for the GooseWorks skill family (GOOSE-3190).
4
+ *
5
+ * Routing used to be written out by hand in THREE places that drifted apart:
6
+ * 1. this CLI's `gooseworks` router SKILL.md (`master-skill.ts`),
7
+ * 2. the backend's hosted-connector pointer
8
+ * (`gooseworks-app/backend/src/app-mcp-server/lib/ads-skill.ts`),
9
+ * 3. the public skills repo's `collections/brand-growth`.
10
+ *
11
+ * This file is now the SINGLE SOURCE. `master-skill.ts` renders its markdown
12
+ * tables from here (no hand-written route rows), `npm run generate:skills`
13
+ * emits the machine-readable copy to `skills/routes.json` for the other two
14
+ * repos to derive from, and `tests/skills/route-drift.test.ts` fails when any
15
+ * of the three names a skill the others don't.
16
+ *
17
+ * The two consumers we cannot edit from this repo are represented by checked-in
18
+ * snapshots under `tests/fixtures/`; each snapshot names the file to update when
19
+ * the drift test fires.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.BRAND_GROWTH_ROUTES = exports.DOMAIN_ROUTES = void 0;
23
+ exports.getRoutedSkillSlugs = getRoutedSkillSlugs;
24
+ exports.getBrandGrowthSkillSlugs = getBrandGrowthSkillSlugs;
25
+ exports.getRouteManifest = getRouteManifest;
26
+ exports.renderDomainRouteTable = renderDomainRouteTable;
27
+ exports.renderBrandGrowthTable = renderBrandGrowthTable;
28
+ /**
29
+ * Domain routes — the "Route to the right skill FIRST" table. These are the
30
+ * specialist skills the `gooseworks` router hands whole tasks to.
31
+ */
32
+ exports.DOMAIN_ROUTES = [
33
+ {
34
+ skill: 'goose-ads',
35
+ when: 'Remix/make an ad, research a brand for ads, OR analyze ad performance — Meta/Google ad campaigns, creative fatigue, CAC/lead quality, competitor ad intel, ad angles & hooks',
36
+ how: 'Installed locally as an entry skill. Just use it. If unavailable, run `gooseworks install --claude`.',
37
+ delivery: 'entry',
38
+ },
39
+ {
40
+ skill: 'goose-graphics',
41
+ when: 'Charts, infographics, slides, social graphics, branded visual designs from a style/format',
42
+ how: 'If installed locally, use it. Otherwise `gooseworks fetch goose-graphics` (or `gooseworks install --claude --with goose-graphics`).',
43
+ delivery: 'fetch',
44
+ },
45
+ {
46
+ skill: 'goose-video',
47
+ when: 'Make a **video** ad — remix a video ad template (e.g. iMessage chat-reveal), or "make the video for project <id>"',
48
+ how: 'Installed locally as an entry skill. Just use it. If unavailable, run `gooseworks install --claude`.',
49
+ delivery: 'entry',
50
+ },
51
+ {
52
+ skill: 'goose-product-photos',
53
+ when: 'Make **product photos** — studio, lifestyle, marketplace, social, or on-model product photography',
54
+ how: 'Installed locally as an entry skill. Just use it. If unavailable, run `gooseworks install --claude`.',
55
+ delivery: 'entry',
56
+ },
57
+ {
58
+ skill: 'animate-image',
59
+ when: 'Animate an approved static ad or product image',
60
+ how: 'Fetch with `gooseworks fetch animate-image` and follow its GooseWorks MCP workflow.',
61
+ delivery: 'fetch',
62
+ },
63
+ ];
64
+ /**
65
+ * Brand Growth routes — the outcome skills in the `brand-growth` collection.
66
+ * Must stay in sync with `goose-skills/collections/brand-growth/routes.json`,
67
+ * which is derived from this list.
68
+ */
69
+ exports.BRAND_GROWTH_ROUTES = [
70
+ { job: 'Brand foundation', skills: ['brand-research'] },
71
+ { job: 'Competitor ads', skills: ['competitor-ad-intelligence'] },
72
+ { job: 'Customer language and angles', skills: ['comment-mining', 'ad-angle-miner'] },
73
+ { job: 'Competitor social content', skills: ['competitor-social-research'] },
74
+ { job: 'Audience definition', skills: ['audience-research'] },
75
+ { job: 'Creator discovery and evaluation', skills: ['influencer-prospecting', 'creator-profile-teardown'] },
76
+ { job: 'Trends and outlier posts', skills: ['trend-discovery', 'outlier-post-finder'] },
77
+ { job: 'Social listening and product demand', skills: ['social-listening-brief', 'product-demand-research'] },
78
+ { job: 'Long-form source material (calls, podcasts, videos)', skills: ['transcript-intelligence'] },
79
+ {
80
+ job: 'Meta performance, policy, and landing-page match',
81
+ skills: ['meta-ads-analyzer', 'meta-ad-policy-checker', 'ad-to-landing-page-auditor'],
82
+ },
83
+ { job: 'Static ads', skills: ['goose-ads', 'remix-graphic-ad-from-reference'] },
84
+ { job: 'Product photos', skills: ['goose-product-photos', 'product-photoshoot'] },
85
+ { job: 'Written content and repurposing', skills: ['content-repurposing'] },
86
+ { job: 'Graphics and animation', skills: ['goose-graphics', 'animate-image'] },
87
+ ];
88
+ /** Every skill slug named by any route, deduped and sorted. */
89
+ function getRoutedSkillSlugs() {
90
+ const slugs = new Set();
91
+ for (const r of exports.DOMAIN_ROUTES)
92
+ slugs.add(r.skill);
93
+ for (const r of exports.BRAND_GROWTH_ROUTES)
94
+ for (const s of r.skills)
95
+ slugs.add(s);
96
+ return [...slugs].sort();
97
+ }
98
+ /** Brand Growth slugs only (the ones the goose-skills collection must contain). */
99
+ function getBrandGrowthSkillSlugs() {
100
+ const slugs = new Set();
101
+ for (const r of exports.BRAND_GROWTH_ROUTES)
102
+ for (const s of r.skills)
103
+ slugs.add(s);
104
+ return [...slugs].sort();
105
+ }
106
+ /** The machine-readable route table emitted to `skills/routes.json`. */
107
+ function getRouteManifest() {
108
+ return {
109
+ $comment: 'Generated by `npm run generate:skills` from gooseworks/src/skills/routes.ts — the single source for GooseWorks skill routing (GOOSE-3190). Do not hand-edit. Consumers: goose-skills/collections/brand-growth/routes.json and gooseworks-app/backend/src/app-mcp-server/lib/ads-skill.ts.',
110
+ version: 1,
111
+ domain_routes: exports.DOMAIN_ROUTES,
112
+ brand_growth_routes: exports.BRAND_GROWTH_ROUTES,
113
+ skills: getRoutedSkillSlugs(),
114
+ };
115
+ }
116
+ /** Render the domain route table as the router SKILL.md markdown table body. */
117
+ function renderDomainRouteTable() {
118
+ return exports.DOMAIN_ROUTES.map((r) => `| ${r.when} | **\`${r.skill}\`** | ${r.how} |`).join('\n');
119
+ }
120
+ /** Render the Brand Growth job→skill table body. */
121
+ function renderBrandGrowthTable() {
122
+ return exports.BRAND_GROWTH_ROUTES.map((r) => `| ${r.job} | ${r.skills.map((s) => `\`${s}\``).join(', ')} |`).join('\n');
123
+ }
124
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/skills/routes.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;AAyFH,kDAKC;AAGD,4DAIC;AAGD,4CAeC;AAGD,wDAIC;AAGD,wDAIC;AA3GD;;;GAGG;AACU,QAAA,aAAa,GAAkB;IAC1C;QACE,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,8KAA8K;QACpL,GAAG,EAAE,sGAAsG;QAC3G,QAAQ,EAAE,OAAO;KAClB;IACD;QACE,KAAK,EAAE,gBAAgB;QACvB,IAAI,EAAE,2FAA2F;QACjG,GAAG,EAAE,qIAAqI;QAC1I,QAAQ,EAAE,OAAO;KAClB;IACD;QACE,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,mHAAmH;QACzH,GAAG,EAAE,sGAAsG;QAC3G,QAAQ,EAAE,OAAO;KAClB;IACD;QACE,KAAK,EAAE,sBAAsB;QAC7B,IAAI,EAAE,mGAAmG;QACzG,GAAG,EAAE,sGAAsG;QAC3G,QAAQ,EAAE,OAAO;KAClB;IACD;QACE,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE,gDAAgD;QACtD,GAAG,EAAE,qFAAqF;QAC1F,QAAQ,EAAE,OAAO;KAClB;CACF,CAAC;AAEF;;;;GAIG;AACU,QAAA,mBAAmB,GAAuB;IACrD,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE;IACvD,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC,4BAA4B,CAAC,EAAE;IACjE,EAAE,GAAG,EAAE,8BAA8B,EAAE,MAAM,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,EAAE;IACrF,EAAE,GAAG,EAAE,2BAA2B,EAAE,MAAM,EAAE,CAAC,4BAA4B,CAAC,EAAE;IAC5E,EAAE,GAAG,EAAE,qBAAqB,EAAE,MAAM,EAAE,CAAC,mBAAmB,CAAC,EAAE;IAC7D,EAAE,GAAG,EAAE,kCAAkC,EAAE,MAAM,EAAE,CAAC,wBAAwB,EAAE,0BAA0B,CAAC,EAAE;IAC3G,EAAE,GAAG,EAAE,0BAA0B,EAAE,MAAM,EAAE,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,EAAE;IACvF,EAAE,GAAG,EAAE,qCAAqC,EAAE,MAAM,EAAE,CAAC,wBAAwB,EAAE,yBAAyB,CAAC,EAAE;IAC7G,EAAE,GAAG,EAAE,qDAAqD,EAAE,MAAM,EAAE,CAAC,yBAAyB,CAAC,EAAE;IACnG;QACE,GAAG,EAAE,kDAAkD;QACvD,MAAM,EAAE,CAAC,mBAAmB,EAAE,wBAAwB,EAAE,4BAA4B,CAAC;KACtF;IACD,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,WAAW,EAAE,iCAAiC,CAAC,EAAE;IAC/E,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC,sBAAsB,EAAE,oBAAoB,CAAC,EAAE;IACjF,EAAE,GAAG,EAAE,iCAAiC,EAAE,MAAM,EAAE,CAAC,qBAAqB,CAAC,EAAE;IAC3E,EAAE,GAAG,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,gBAAgB,EAAE,eAAe,CAAC,EAAE;CAC/E,CAAC;AAEF,+DAA+D;AAC/D,SAAgB,mBAAmB;IACjC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,qBAAa;QAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,2BAAmB;QAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,mFAAmF;AACnF,SAAgB,wBAAwB;IACtC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,2BAAmB;QAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,wEAAwE;AACxE,SAAgB,gBAAgB;IAO9B,OAAO;QACL,QAAQ,EACN,2RAA2R;QAC7R,OAAO,EAAE,CAAC;QACV,aAAa,EAAE,qBAAa;QAC5B,mBAAmB,EAAE,2BAAmB;QACxC,MAAM,EAAE,mBAAmB,EAAE;KAC9B,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,SAAgB,sBAAsB;IACpC,OAAO,qBAAa,CAAC,GAAG,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,GAAG,IAAI,CACvD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,oDAAoD;AACpD,SAAgB,sBAAsB;IACpC,OAAO,2BAAmB,CAAC,GAAG,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CACtE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gooseworks",
3
- "version": "0.3.16",
3
+ "version": "0.4.1",
4
4
  "description": "GooseWorks CLI — give your coding agent real data tools",
5
5
  "bin": {
6
6
  "gooseworks": "./dist/index.js"
@@ -36,6 +36,24 @@ Everything goes through the `mcp__gooseworks__*` tools. If they are not availabl
36
36
  tell the user to run `gooseworks install --claude --mcp`** (and restart Claude Code). There is
37
37
  no HTTP/file fallback — the REST ad endpoints are session-cookie-only and reject your token.
38
38
 
39
+ ## Start from the brand context — don't re-ask what it already answers
40
+
41
+ If the `gooseworks` router handed you brand context, USE IT. If you were invoked directly, call
42
+ `brand_get_context` first (falling back to `get_brand_kit` for the selected brand). It already
43
+ answers most of what the flows below would otherwise ask the user:
44
+
45
+ - **Which product to feature** → `products[]`. Offer the real catalog entries; never guess a
46
+ product name and never ask the user to list their products.
47
+ - **The vibe / tone of the copy** → the brand's **voice**. Use it; don't ask "what tone?".
48
+ - **Who the ad is for** → the brand's **audience**. Don't ask "who's the target?".
49
+ - **The angle, offer framing, and what to claim** → **positioning**, value props, proof points.
50
+ - **Logo, colors, fonts** → owned by the backend research pass. **Never re-derive them.**
51
+ - **Whether the facts are trustworthy yet** → **research status**. If it isn't complete, say so in
52
+ one line and continue; the batch queues and runs when research finishes.
53
+
54
+ Ask only for what the context genuinely doesn't answer: the specific campaign intent (season,
55
+ promo, which of several angles), the source ad, and anything the user must consent to.
56
+
39
57
  ## Identity & credits
40
58
 
41
59
  - One agent-scoped token authenticates the `gooseworks` MCP tools. Never print it. The tools
@@ -161,9 +179,11 @@ When the user wants to make ads but has NOT named a specific template (id/slug/C
161
179
  ad/upload), do NOT silently browse the raw catalog and hand-pick for them. Instead run this
162
180
  short ask flow — it mirrors the web app and keeps the human in the loop:
163
181
 
164
- 1. **Ask what kind of ads they want** — the angle/offer/theme/season, the vibe, and which
165
- product from the brand kit to feature. This shapes both the source choice and your steering
166
- `prompt`. Keep it to one or two quick questions.
182
+ 1. **Ask what kind of ads they want** — the angle/offer/theme/season. **The brand context already
183
+ gives you the vibe (voice), the audience, and the product catalog — do NOT ask for those.**
184
+ Offer the real `products[]` to pick from rather than asking "which product?", and derive the
185
+ tone from the brand's voice. This shapes both the source choice and your steering `prompt`.
186
+ Keep it to one quick question about campaign intent.
167
187
  2. **Ask how to pick a source: their own ads, Community, upload, or "Surprise me".**
168
188
  - **Their own ads** → use `list_user_ad_templates` to load the active brand's own sources and
169
189
  let them choose from the results.
@@ -11,7 +11,7 @@ description: >
11
11
  references a product to photograph. Unlike goose-ads (ad creative) this produces clean PRODUCT
12
12
  photos that can then feed the ad workflow.
13
13
  category: ads
14
- version: 0.1.0
14
+ version: 0.2.0
15
15
  author: GooseWorks
16
16
  tags: [gooseworks, ads, product-photos, photoshoot, product, ecommerce, studio, lifestyle, on-model]
17
17
  ---
@@ -32,6 +32,24 @@ Everything goes through the `mcp__gooseworks__*` tools. If they are not availabl
32
32
  tell the user to run `gooseworks install --claude --mcp`** (and restart Claude Code). There is no
33
33
  HTTP/file fallback.
34
34
 
35
+ ## Start from the brand context — don't re-ask what it already answers
36
+
37
+ If the `gooseworks` router handed you brand context, USE IT. If you were invoked directly, call
38
+ `brand_get_context` yourself first. It answers most of the setup questions below, so **do not ask
39
+ the user for them**:
40
+
41
+ - **Which product?** — the context's `products[]` are the real catalog entries. Offer them; never
42
+ invent a product or ask the user to describe one you can already see.
43
+ - **What does it look like / what is it made of?** — grounded in the product's stored images and
44
+ description. Never guess a material, colorway, or silhouette.
45
+ - **What vibe / who is it for?** — the context's voice, positioning, and audience already say. Let
46
+ them shape the scene and styling instead of asking "what mood do you want?".
47
+ - **Brand look** — logo, colors, and fonts are owned by the backend research pass. Read them, never
48
+ re-derive them.
49
+
50
+ Ask only for the genuinely open choices: the shot `category`, how many photos, quality, and
51
+ whether a human model is wanted (which needs explicit consent — see the rules).
52
+
35
53
  ## Identity & credits
36
54
 
37
55
  - One agent-scoped token authenticates the tools; they resolve your org automatically. Never
@@ -81,10 +99,13 @@ HTTP/file fallback.
81
99
 
82
100
  ## Workflow — shoot a product
83
101
 
84
- 1. **Resolve the brand + product.** `list_ad_brands` → `brand_id`. `list_brand_products` → pick a
85
- `product_id`. If the product isn't there, `import_product` (poll `get_product_import`).
102
+ 1. **Load the brand context** (`brand_get_context`, or reuse what the router passed you) and
103
+ **resolve the brand + product.** `list_ad_brands` → `brand_id`. `list_brand_products` → pick a
104
+ `product_id` from the catalog you already know about. If the product genuinely isn't there,
105
+ `import_product` (poll `get_product_import`).
86
106
  2. **Quote the cost.** `estimate_product_photos { count, quality }` → tell the user credits.
87
107
  3. **Generate.** `generate_product_photos { brand_id, product_id, category, count, quality, prompt? }`.
108
+ Build `prompt` from the brand's voice/positioning you already have — don't interview the user for it.
88
109
  Returns a generation `id` right away.
89
110
  4. **Poll.** `get_product_photo_generation { generation_id }` until terminal; hand back each
90
111
  `final_image_url`.
@@ -95,6 +116,9 @@ HTTP/file fallback.
95
116
 
96
117
  - **Never invent product facts.** The backend grounds the shot on the product's real images; don't
97
118
  describe a product you can't see.
119
+ - **Use the brand context instead of interviewing the user.** Product, audience, voice, positioning,
120
+ logo/colors/fonts all come from `brand_get_context` / the brand kit. Ask only for the shot
121
+ category, count, quality, and model consent.
98
122
  - **Ask before spending.** Quote the estimate and confirm `count` / `quality` before
99
123
  `generate_product_photos` — it reserves credits.
100
124
  - **Poll, don't re-submit.** A generation that's still `running` is not stuck; re-submitting
@@ -20,7 +20,7 @@ This skill is also the **parent router** for the GooseWorks family. Data/GTM wor
20
20
 
21
21
  ## Route to the right skill FIRST
22
22
 
23
- Before anything else, check whether the request belongs to a specialized domain. If so, **switch to that skill** instead of the data flow below:
23
+ First apply the **Common company onboarding** gate below. Preserve the user's original request while onboarding, then continue with it as soon as onboarding is complete. Then load the brand context (**"Load the brand context FIRST"**, immediately below). After that, check whether the request belongs to a specialized domain. If so, **switch to that skill** instead of the data flow below:
24
24
 
25
25
  | If the user wants… | Route to | How |
26
26
  | --- | --- | --- |
@@ -33,6 +33,28 @@ Before anything else, check whether the request belongs to a specialized domain.
33
33
 
34
34
  Examples — all of these route to `goose-ads`, not the data flow: "remix this ad with project id 123", "make an ad for my product", "research my brand", "why is my Meta campaign underperforming", "which creatives should I cut".
35
35
 
36
+ ## Load the brand context FIRST (mandatory — before you route, and before you ask anything)
37
+
38
+ **Call `brand_get_context` before the first substantive step of ANY task**, and before you route to a specialist skill. It is a cheap, read-only call that returns the brand's canonical facts:
39
+
40
+ | It returns | Use it for |
41
+ | --- | --- |
42
+ | **voice** — tone, style, banned phrasing | Any copy, script, caption, hook, or headline. Don't ask "what tone?" |
43
+ | **products** — names, descriptions, pricing, links, imagery | Picking the product to feature. Don't ask "which product?" — offer the list. |
44
+ | **audience** — segments, demographics, jobs-to-be-done | Targeting, angles, creator fit. Don't ask "who is this for?" |
45
+ | **positioning** — category, value props, proof points, tagline | Angles, offers, competitive framing. Don't ask "what makes you different?" |
46
+ | **research status** — whether the brand's research pass has completed | Whether the facts are trustworthy yet, or still being filled in. |
47
+
48
+ Then:
49
+
50
+ 1. **Pass what it returned INTO the routed skill.** When you hand off to `goose-ads`, `goose-video`, `goose-product-photos`, `goose-graphics`, or a fetched Brand Growth recipe, carry the voice / products / audience / positioning with you. Do **not** make the routed skill re-derive them, and do **not** re-run brand research when the context is already there.
51
+ 2. **Never re-ask the user for something the brand context already answers.** If a routed skill's own prose asks a question the context answers, the context wins — answer it yourself and move on. Ask only for what is genuinely missing or ambiguous.
52
+ 3. **If research status is not complete**, say so in one line, use what you have, and continue. Only run brand research when the context comes back empty or the user asks for it.
53
+ 4. **If `brand_get_context` is unavailable** (no MCP connection), fall back to `get_brand_kit` for the selected brand and treat its fields the same way. If neither is available, tell the user the GooseWorks MCP connection is needed rather than guessing brand facts.
54
+ 5. **Treat it as read-only.** Writing brand facts back is the reconciliation flow in `goose-ads` (ask first, then `update_brand_kit`) — not something this router does.
55
+
56
+ Never invent a brand fact. If it isn't in the brand context and the user hasn't said it, ask.
57
+
36
58
  ## Setup
37
59
 
38
60
  All commands below auto-load credentials from `~/.gooseworks/credentials.json`. If a command exits with "Not logged in", tell the user to run: `npx gooseworks login`. To log out: `npx gooseworks logout`.
@@ -69,57 +91,32 @@ gooseworks credits
69
91
 
70
92
  ## Common company onboarding
71
93
 
72
- Onboarding is voluntary and happens inside the current coding agent. Run it when the user explicitly says **`/gooseworks onboard me`**, or ask for one missing answer when it is necessary for the task in front of you. **Never force an existing user through onboarding after an update.**
73
-
74
- The CLI and GooseWorks Ads share one brand-scoped questionnaire through these MCP tools:
75
-
76
- - `list_ad_brands` and `create_ad_brand` — select or create the company/brand.
77
- - `get_brand_onboarding { brand_id }` — load completed answers and `missing_fields` before asking anything.
78
- - `update_brand_onboarding { brand_id, ...answers }` — save each group of answers and the final first-task choice.
79
-
80
- If these tools are unavailable, tell the user that onboarding needs the GooseWorks MCP connection. Do not send them to another UI and do not fall back to a separate context record.
81
-
82
- ### Resume rules
83
-
84
- 1. Run `list_ad_brands`. If there are multiple brands, ask which one to use.
85
- 2. If there is no brand, ask for the company or brand website, research it, and use `create_ad_brand { name, website_url }`. If the domain matches an existing brand, reuse it.
86
- 3. Call `get_brand_onboarding` and ask only the returned missing questions.
87
- 4. Save after each small group so an interrupted interview can resume.
88
- 5. If the record is complete, confirm the brand and continue; do not repeat the interview.
89
-
90
- ### Shared questions and answer values
91
-
92
- Use the host's native question controls. Keep the labels below; the values in backticks are the stable values accepted by `update_brand_onboarding`.
93
-
94
- 1. **What is your role?** Founder / Business Owner · C-Suite · VP / Director · Performance / Growth Marketing · Brand / Content Marketing · Creative / Design · Agency · Consultant / Freelancer · Other.
95
- 2. **How much do you spend on paid ads right now?** `zero` · `under_10k` · `10k_30k` · `30k_100k` · `100k_plus`.
96
- 3. **What are your goals?** Multi-select: create ads `make_creatives` · analyze ads `analyze_ads` · manage/optimize ads `ai_manage` · competitor or customer research `research_competitors` · creators and social trends `creators_trends` · content `content_growth` · lead generation `lead_generation` · data work `data_work` · work with an expert team `expert_team`.
97
- 4. **Who makes your ad creatives right now?** and **Who manages your ads right now?** Use the shared values returned in the tool schema. Skip both when ad spend is `zero` and no advertising goal was selected.
98
- 5. **Which platforms or channels do you use or want help with?** Multi-select: `meta` · `tiktok` · `google` · `chatgpt` · `x` · `linkedin` · `reddit` · `other`.
99
- 6. **Where did you find GooseWorks?** Use the shared discovery-source values returned in the tool schema.
94
+ Onboarding happens inside the current agent and is the first-run gate for every GooseWorks task. It uses the exact same saved state and step order as the web onboarding. The user does not need to type **`/gooseworks onboard me`**; that explicit command only starts or resumes the same flow.
100
95
 
101
- Do not add CLI-only questions about business type, products, or audience. Infer them from the website and ask one clarification only when the research is materially uncertain.
96
+ Keep the user's original task pending. Call **`brand_onboarding { action: "status" }`** before routing or executing it, then:
102
97
 
103
- ### Research while onboarding
98
+ - follow only the returned `next_step`;
99
+ - save each answer immediately with `brand_onboarding` so web, Claude, Codex, ChatGPT, and Cowork can resume one another;
100
+ - continue the original request immediately when `onboarding_completed` is true.
104
101
 
105
- Do useful setup work, not only form collection:
102
+ If `brand_onboarding` is unavailable, explain that the GooseWorks MCP connection must be enabled. Do not write a parallel local profile and do not run the retired role / discovery-source / ad-owner questionnaire.
106
103
 
107
- 1. Fetch `brand-research` and research the website, products/services, audiences, competitors, offers, and messaging evidence.
108
- 2. Reuse existing Brand Kit/Core data. For an ecommerce store, import the relevant catalog with `import_product` and poll `get_product_import` rather than submitting duplicates.
109
- 3. When ads are relevant, offer to import existing creative. This is optional.
110
- 4. Suggest evidence-backed messaging angles. Approval is optional and never blocks completion.
111
- 5. Show the researched profile for confirmation: products/services, audience, competitors, imported ads, and suggested angles. Clearly label uncertainty.
104
+ When onboarding returns a review link, show that single link and ask the user to review the creatives and reply `done`. When they reply `done`, do not restart onboarding: continue the task they originally asked for. If there was no earlier task, ask: **“Let’s start your next campaign. What are you promoting, and what result do you want?”** Use the same preserved-task-or-campaign handoff if onboarding completes while the creatives are still being prepared or could not be generated.
112
105
 
113
- ### First task
106
+ ### Shared flow
114
107
 
115
- Finish with **What do you want to do first?**
108
+ Use the host's native question controls. Ask one short group at a time and rely on the live tool schema for accepted values.
116
109
 
117
- - Connect my tools and data — `connect_tools`
118
- - Research customers, competitors, creators, or trends — `research`
119
- - Analyze ads, content, landing pages, or performance — `analyze`
120
- - Create ads, product images, or social content — `create`
110
+ 1. **Start** — If status returns `start`, ask for the company website or Apple App Store URL. Also offer the optional hero product URL and “Where do you do your work?” choices: Slack, WhatsApp, iMessage, Claude Code, Claude, Codex, and ChatGPT. Call `action: "start"`; server-side research begins immediately. If status returns `select_brand`, ask which company/client to use. Otherwise reuse the only brand automatically.
111
+ 2. **Your coworker** — Ask what they want to name their Growth Coworker. A text-only client may keep the default avatar; do not block on an image. Save with `action: "save_coworker"`.
112
+ 3. **Your company** — Use the returned `company_draft` as the starting point and ask the user to verify or edit: what they sell (`marketCategory`), where people buy (`appPlatforms`), primary customer, customer problem, promised outcome, and optional differentiator. Save with `action: "save_company"`.
113
+ 4. **Your taste** — In a terminal or CLI host, use the returned `taste_url`: open it when the host supports opening links and always show one clickable **Choose your taste in GooseWorks** link. Ask the user to heart or skip ads on that page, click **Continue** or **Skip this**, return to the agent, and reply `done`. Do not print, enumerate, or summarize `taste_deck` in the terminal. After `done`, call `brand_onboarding { action: "status" }` again and follow the refreshed `next_step`. In a chat host that renders images, show only the one image attached by the tool and save each Love/Skip decision with `action: "save_taste"`; send `complete: true` after three hearts or an explicit skip.
114
+ 5. **First campaign** — Ask **“What’s happening right now?”**: launch `launch`, promotion `promo`, seasonal moment `seasonal`, or nothing special `nothing`, plus an optional note. Call `action: "propose_campaign"`, show the returned editable card (name, objective, offer, audience, 2–3 angles, CTA, and product URL), and save edits with `action: "save_campaign"`. Send `accept: true` only after approval; acceptance can start the complimentary first creatives.
115
+ 6. **Where you are** — Ask monthly ad spend (`none`, `under_1k`, `1k_5k`, `5k_25k`, `25k_plus`), annual revenue (`under_1m`, `1m_10m`, `10m_100m`, `100m_plus`), the 90-day goal, current channels (an empty list is a valid “nothing yet”), and at least one channel they are willing to use. Channel values: `paid_social`, `search_ads`, `content`, `creators`, `seo`, `communities`, `referrals`, `partnerships`, `outbound`, `app_stores`, `other`. Save with `action: "save_progress"`.
116
+ 7. **Review** — Show the returned founder, researched, and inferred facts with their provenance. The user may correct positioning, audience, voice, value propositions, proof points, or competitors through `action: "review_research"`. Complete the review even when research is still running, failed, or sparse; never trap the user waiting for it.
117
+ 8. **Channels** — If `channel_connected` is already true, this is complete automatically. Otherwise ask whether they want to connect Slack, WhatsApp, or iMessage later, or skip for now. An explicit skip is valid; call `action: "complete_channels"`.
121
118
 
122
- Save the choice as `first_task`, then start that job. If the user already stated a concrete job, save the matching value and start without showing the menu.
119
+ Do not ask for role, discovery source, who makes creatives, who manages ads, or a separate “what do you want to do first?” menu. Those belonged to the retired CLI questionnaire. The task the user already asked for is their first task.
123
120
 
124
121
  ## Brand Growth discovery
125
122
 
@@ -129,17 +126,20 @@ Brand Growth is a collection inside the normal skill catalog, not a command or i
129
126
  | --- | --- |
130
127
  | Brand foundation | `brand-research` |
131
128
  | Competitor ads | `competitor-ad-intelligence` |
132
- | Customer language and angles | `comment-mining` → `ad-angle-miner` |
129
+ | Customer language and angles | `comment-mining`, `ad-angle-miner` |
133
130
  | Competitor social content | `competitor-social-research` |
134
- | Creator discovery and evaluation | `influencer-prospecting` |
131
+ | Audience definition | `audience-research` |
132
+ | Creator discovery and evaluation | `influencer-prospecting`, `creator-profile-teardown` |
135
133
  | Trends and outlier posts | `trend-discovery`, `outlier-post-finder` |
136
134
  | Social listening and product demand | `social-listening-brief`, `product-demand-research` |
135
+ | Long-form source material (calls, podcasts, videos) | `transcript-intelligence` |
137
136
  | Meta performance, policy, and landing-page match | `meta-ads-analyzer`, `meta-ad-policy-checker`, `ad-to-landing-page-auditor` |
138
- | Static ads | `goose-ads` / `remix-graphic-ad-from-reference` |
139
- | Product photos | `goose-product-photos` |
137
+ | Static ads | `goose-ads`, `remix-graphic-ad-from-reference` |
138
+ | Product photos | `goose-product-photos`, `product-photoshoot` |
139
+ | Written content and repurposing | `content-repurposing` |
140
140
  | Graphics and animation | `goose-graphics`, `animate-image` |
141
141
 
142
- Fetch the named public skill before following it. Provider helpers such as `scrapecreators-api` and `transcript-intelligence` are dependencies, not user-facing results.
142
+ Fetch the named public skill before following it. You already called `brand_get_context` — hand the brand's voice, products, audience, and positioning to the fetched skill instead of letting it re-derive or re-ask them. Provider helpers such as `scrapecreators-api` and `transcript-intelligence` are dependencies, not user-facing results.
143
143
 
144
144
  For a multi-part request, repeat this routing check before each new job. Fetch and follow the
145
145
  closest outcome skill first (for example, `comment-mining`, `creator-profile-teardown`, or
@@ -269,6 +269,7 @@ The `gooseworks` CLI sends authenticated requests (Bearer `GOOSEWORKS_API_KEY`)
269
269
 
270
270
  ## Rules
271
271
 
272
+ 0. **Call `brand_get_context` before anything else**, pass what it returns into whatever skill you route to, and never re-ask the user for a fact it already answers (see "Load the brand context FIRST").
272
273
  1. **Consider a GooseWorks skill when it fits the task** — scraping, research, lead gen, enrichment, especially at scale, behind auth, or from a specific source. For a quick lookup your built-in tools are fine; use your judgement and pick the best tool for the user.
273
274
  2. **Before paid operations**, tell the user the estimated credit cost
274
275
  3. **If a `gooseworks` command exits with "Not logged in"**: tell the user to run `npx gooseworks login`