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.
- package/.claude-plugin/marketplace.json +27 -0
- package/.claude-plugin/plugin.json +3 -0
- package/README.md +9 -9
- package/dist/agents/claude.js +1 -1
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/codex.js +1 -1
- package/dist/agents/codex.js.map +1 -1
- package/dist/agents/skill-links.d.ts +7 -2
- package/dist/agents/skill-links.d.ts.map +1 -1
- package/dist/agents/skill-links.js +10 -5
- package/dist/agents/skill-links.js.map +1 -1
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +11 -6
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +4 -23
- package/dist/commands/login.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -2
- package/dist/config.js.map +1 -1
- package/dist/skills/installer.d.ts +9 -0
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +20 -6
- package/dist/skills/installer.js.map +1 -1
- package/dist/skills/master-skill.d.ts +24 -22
- package/dist/skills/master-skill.d.ts.map +1 -1
- package/dist/skills/master-skill.js +251 -66
- package/dist/skills/master-skill.js.map +1 -1
- package/dist/skills/names.d.ts +53 -1
- package/dist/skills/names.d.ts.map +1 -1
- package/dist/skills/names.js +107 -7
- package/dist/skills/names.js.map +1 -1
- package/dist/skills/routes.d.ts +68 -0
- package/dist/skills/routes.d.ts.map +1 -0
- package/dist/skills/routes.js +124 -0
- package/dist/skills/routes.js.map +1 -0
- package/package.json +1 -1
- package/skills/goose-ads/SKILL.md +23 -3
- package/skills/goose-product-photos/SKILL.md +27 -3
- package/skills/gooseworks/SKILL.md +50 -49
- package/skills/routes.json +157 -0
package/dist/skills/names.js
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
package/dist/skills/names.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/skills/names.ts"],"names":[],"mappings":"
|
|
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":"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"}
|
package/package.json
CHANGED
|
@@ -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
|
|
165
|
-
|
|
166
|
-
|
|
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.
|
|
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. **
|
|
85
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
96
|
+
Keep the user's original task pending. Call **`brand_onboarding { action: "status" }`** before routing or executing it, then:
|
|
102
97
|
|
|
103
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
106
|
+
### Shared flow
|
|
114
107
|
|
|
115
|
-
|
|
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
|
-
|
|
118
|
-
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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
|
|
129
|
+
| Customer language and angles | `comment-mining`, `ad-angle-miner` |
|
|
133
130
|
| Competitor social content | `competitor-social-research` |
|
|
134
|
-
|
|
|
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
|
|
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`
|