anymorph 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +3 -3
  2. package/dist/index.js +78 -6
  3. package/package.json +1 -1
  4. package/dist/skillpacks/geo/scaffold/AGENTS.md +0 -38
  5. package/dist/skillpacks/geo/scaffold/CLAUDE.md +0 -33
  6. package/dist/skillpacks/geo/shared/evidence-principles.md +0 -35
  7. package/dist/skillpacks/geo/shared/geo-principles.md +0 -281
  8. package/dist/skillpacks/geo/shared/vertical-playbooks/beauty.md +0 -65
  9. package/dist/skillpacks/geo/shared/vertical-playbooks/commerce.md +0 -65
  10. package/dist/skillpacks/geo/shared/vertical-playbooks/ota.md +0 -62
  11. package/dist/skillpacks/geo/shared/vertical-playbooks/saas.md +0 -64
  12. package/dist/skillpacks/geo/skills/brand-owned-diagnosis/SKILL.md +0 -54
  13. package/dist/skillpacks/geo/skills/brand-owned-diagnosis/agents/openai.yaml +0 -4
  14. package/dist/skillpacks/geo/skills/brand-owned-diagnosis/references/diagnosis-contract.md +0 -95
  15. package/dist/skillpacks/geo/skills/brand-owned-diagnosis/references/workflow.md +0 -194
  16. package/dist/skillpacks/geo/skills/geo-generating-actions/SKILL.md +0 -188
  17. package/dist/skillpacks/geo/skills/geo-generating-actions/agents/openai.yaml +0 -4
  18. package/dist/skillpacks/geo/skills/geo-generating-actions/references/orchestrator.workflow.md +0 -440
  19. package/dist/skillpacks/geo/skills/geo-generating-actions/scripts/geo-scaffold.mjs +0 -358
  20. package/dist/skillpacks/geo/skills/geo-generating-actions/scripts/geo.mjs +0 -66
  21. package/dist/skillpacks/geo/skills/geo-initializing-strategy/SKILL.md +0 -50
  22. package/dist/skillpacks/geo/skills/geo-initializing-strategy/agents/openai.yaml +0 -4
  23. package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/external-authority-diagnosis.md +0 -66
  24. package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/foundation-diagnosis.md +0 -86
  25. package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/memory-contract.md +0 -15
  26. package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/semantic-clusters-diagnosis.md +0 -58
  27. package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/strategy-map-contract.md +0 -26
  28. package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/visibility-diagnosis.md +0 -50
  29. package/dist/skillpacks/geo/skills/geo-local-setup/SKILL.md +0 -66
  30. package/dist/skillpacks/geo/skills/geo-local-setup/agents/openai.yaml +0 -4
  31. package/dist/skillpacks/geo/skills/geo-page-writer/SKILL.md +0 -81
  32. package/dist/skillpacks/geo/skills/geo-page-writer/agents/openai.yaml +0 -4
  33. package/dist/skillpacks/geo/skills/geo-page-writer/references/research.md +0 -61
  34. package/dist/skillpacks/geo/skills/geo-page-writer/references/validation.md +0 -59
  35. package/dist/skillpacks/geo/skills/geo-page-writer/references/writing.md +0 -55
  36. package/dist/skillpacks/geo/skills/geo-page-writer/scripts/check-page-mdx.mjs +0 -210
  37. package/dist/skillpacks/geo/skills/geo-page-writer/scripts/collect-page-sources.mjs +0 -303
  38. package/dist/skillpacks/geo/skills/geo-pages-diagnosis/SKILL.md +0 -51
  39. package/dist/skillpacks/geo/skills/geo-pages-diagnosis/agents/openai.yaml +0 -4
  40. package/dist/skillpacks/geo/skills/geo-pages-diagnosis/references/diagnosis-contract.md +0 -125
  41. package/dist/skillpacks/geo/skills/geo-pages-diagnosis/references/workflow.md +0 -269
  42. package/dist/skillpacks/geo/skills/geo-writer/SKILL.md +0 -234
  43. package/dist/skillpacks/geo/skills/geo-writer/agents/openai.yaml +0 -4
  44. package/dist/skillpacks/geo/skills/geo-writer/references/content-writer-contract.md +0 -316
  45. package/dist/skillpacks/geo/skills/geo-writer/references/direct-sql.md +0 -187
  46. package/dist/skillpacks/geo/skills/geo-writer/references/seo-geo-insights.md +0 -269
  47. package/dist/skillpacks/geo/skills/seo-ecommerce-opportunity/SKILL.md +0 -82
  48. package/dist/skillpacks/geo/skills/seo-ecommerce-opportunity/agents/openai.yaml +0 -5
  49. package/dist/skillpacks/geo/skills/seo-ecommerce-opportunity/references/ecommerce-rules.md +0 -31
  50. package/dist/skillpacks/geo/skills/seo-internal-link-opportunity/SKILL.md +0 -57
  51. package/dist/skillpacks/geo/skills/seo-internal-link-opportunity/agents/openai.yaml +0 -5
  52. package/dist/skillpacks/geo/skills/seo-internal-link-opportunity/references/link-rules.md +0 -28
  53. package/dist/skillpacks/geo/skills/seo-opportunity-audit/SKILL.md +0 -141
  54. package/dist/skillpacks/geo/skills/seo-opportunity-audit/agents/openai.yaml +0 -5
  55. package/dist/skillpacks/geo/skills/seo-opportunity-audit/references/action-contract.md +0 -62
  56. package/dist/skillpacks/geo/skills/seo-opportunity-audit/scripts/seo-toolkit.mjs +0 -248
  57. package/dist/skillpacks/geo/skills/seo-page-diagnosis/SKILL.md +0 -56
  58. package/dist/skillpacks/geo/skills/seo-page-diagnosis/agents/openai.yaml +0 -5
  59. package/dist/skillpacks/geo/skills/seo-page-diagnosis/references/page-checks.md +0 -38
  60. package/dist/skillpacks/geo/skills/seo-serp-opportunity-research/SKILL.md +0 -66
  61. package/dist/skillpacks/geo/skills/seo-serp-opportunity-research/agents/openai.yaml +0 -5
  62. package/dist/skillpacks/geo/skills/seo-serp-opportunity-research/references/page-type-taxonomy.md +0 -40
  63. package/dist/skillpacks/geo/skills/seo-serp-opportunity-research/references/serp-methodology.md +0 -38
  64. package/dist/skillpacks/geo/skills/seo-technical-diagnosis/SKILL.md +0 -64
  65. package/dist/skillpacks/geo/skills/seo-technical-diagnosis/agents/openai.yaml +0 -5
  66. package/dist/skillpacks/geo/skills/seo-technical-diagnosis/references/checks.md +0 -58
  67. package/dist/skillpacks/geo/skills/third-party-diagnosis/SKILL.md +0 -54
  68. package/dist/skillpacks/geo/skills/third-party-diagnosis/agents/openai.yaml +0 -4
  69. package/dist/skillpacks/geo/skills/third-party-diagnosis/references/diagnosis-contract.md +0 -111
  70. package/dist/skillpacks/geo/skills/third-party-diagnosis/references/workflow.md +0 -174
  71. package/dist/skillpacks/geo/skills/third-party-execution-planning/SKILL.md +0 -64
  72. package/dist/skillpacks/geo/skills/third-party-execution-planning/agents/openai.yaml +0 -4
  73. package/dist/skillpacks/geo/skills/third-party-execution-planning/references/execution-contract.md +0 -90
  74. package/dist/skillpacks/geo/skills/third-party-execution-planning/references/non-social-surface-playbooks.md +0 -123
  75. package/dist/skillpacks/geo/skills/third-party-execution-planning/references/reddit-rules.md +0 -69
  76. package/dist/skillpacks/geo/skills/third-party-execution-planning/references/social-platform-playbooks.md +0 -59
@@ -1,358 +0,0 @@
1
- #!/usr/bin/env node
2
- import { execFile } from "node:child_process";
3
- import { createHash } from "node:crypto";
4
- import {
5
- cp,
6
- mkdir,
7
- readdir,
8
- readFile,
9
- rm,
10
- stat,
11
- writeFile,
12
- } from "node:fs/promises";
13
- import { dirname, join, relative, resolve } from "node:path";
14
- import { fileURLToPath } from "node:url";
15
- import { promisify } from "node:util";
16
-
17
- const execFileAsync = promisify(execFile);
18
- const MANAGED_PATHS = [".claude/skills", ".agents/skills", "agent/contracts"];
19
- const ACTIONS_SCHEMA = {
20
- $schema: "https://json-schema.org/draft/2020-12/schema",
21
- title: "Anymorph GEO actions artifact",
22
- type: "object",
23
- required: ["runId", "actions"],
24
- properties: {
25
- runId: { type: "string" },
26
- actions: { type: "array", items: { type: "object" } },
27
- artifactPaths: { type: "array", items: { type: "string" } },
28
- },
29
- };
30
-
31
- const MEMORY_ITEM_SCHEMA = {
32
- $schema: "https://json-schema.org/draft/2020-12/schema",
33
- title: "Anymorph GEO memory item",
34
- type: "object",
35
- required: ["summary"],
36
- properties: {
37
- summary: { type: "string" },
38
- evidence: { type: "array", items: { type: "string" } },
39
- },
40
- };
41
-
42
- const mode = process.argv[2];
43
- const args = parseArgs(process.argv.slice(3));
44
-
45
- if (!["init", "sync", "doctor"].includes(mode)) {
46
- console.error("Usage: geo-scaffold.mjs <init|sync|doctor> --repo <path> [--skills-source <path>] [--ref <ref>] [--json]");
47
- process.exit(2);
48
- }
49
-
50
- try {
51
- const result =
52
- mode === "doctor"
53
- ? await doctorGeoScaffold(args)
54
- : await applyGeoScaffold(args, { createMemory: mode === "init" });
55
-
56
- if (args.json) {
57
- console.log(JSON.stringify(result, null, 2));
58
- } else if (result.ok) {
59
- console.log(`${mode} ok: ${result.repoPath}`);
60
- for (const item of result.changed) console.log(`changed: ${item}`);
61
- } else {
62
- console.error(`${mode} failed: ${result.repoPath}`);
63
- for (const problem of result.problems) console.error(`problem: ${problem}`);
64
- }
65
- process.exit(args.json ? 0 : result.ok ? 0 : 1);
66
- } catch (err) {
67
- const message = err instanceof Error ? err.message : String(err);
68
- if (args.json) {
69
- console.log(
70
- JSON.stringify(
71
- {
72
- ok: false,
73
- repoPath: resolve(args.repo ?? "."),
74
- skillsSourceDir: args.skillsSource ? resolve(args.skillsSource) : defaultSkillsSourceDir(),
75
- changed: [],
76
- problems: [message],
77
- manifestHash: null,
78
- },
79
- null,
80
- 2,
81
- ),
82
- );
83
- } else {
84
- console.error(message);
85
- }
86
- process.exit(1);
87
- }
88
-
89
- function parseArgs(argv) {
90
- const parsed = { repo: ".", ref: "local", json: false };
91
- for (let i = 0; i < argv.length; i += 1) {
92
- const arg = argv[i];
93
- if (arg === "--json") parsed.json = true;
94
- else if (arg === "--repo") parsed.repo = requireValue(argv, ++i, arg);
95
- else if (arg === "--skills-source") parsed.skillsSource = requireValue(argv, ++i, arg);
96
- else if (arg === "--ref") parsed.ref = requireValue(argv, ++i, arg);
97
- else if (arg === "--script-version") parsed.scriptVersion = requireValue(argv, ++i, arg);
98
- else if (arg === "--cli-version") parsed.scriptVersion = requireValue(argv, ++i, arg);
99
- else throw new Error(`Unknown argument: ${arg}`);
100
- }
101
- return parsed;
102
- }
103
-
104
- function requireValue(argv, index, flag) {
105
- const value = argv[index];
106
- if (!value || value.startsWith("--")) throw new Error(`${flag} requires a value`);
107
- return value;
108
- }
109
-
110
- async function applyGeoScaffold(input, options) {
111
- const repoPath = resolve(input.repo ?? ".");
112
- const skillsSourceDir = resolveSkillsSourceDir(input.skillsSource);
113
- await ensureDirectory(skillsSourceDir);
114
- await mkdir(repoPath, { recursive: true });
115
-
116
- const changed = [];
117
- const problems = [];
118
- const manifestHash = await hashDirectory(skillsSourceDir);
119
-
120
- await syncManagedDirectory(skillsSourceDir, join(repoPath, ".claude", "skills"), changed);
121
- await syncManagedDirectory(skillsSourceDir, join(repoPath, ".agents", "skills"), changed);
122
- await syncContracts(repoPath, changed);
123
- await ensureRunDirs(repoPath, changed);
124
- if (options.createMemory) await ensureMemoryFiles(repoPath, changed);
125
- await writeSkillpackLock(
126
- {
127
- repoPath,
128
- skillsSourceDir,
129
- ref: input.ref ?? "local",
130
- manifestHash,
131
- scriptVersion: input.scriptVersion ?? null,
132
- },
133
- changed,
134
- );
135
-
136
- return {
137
- ok: problems.length === 0,
138
- repoPath,
139
- skillsSourceDir,
140
- changed,
141
- problems,
142
- manifestHash,
143
- };
144
- }
145
-
146
- async function doctorGeoScaffold(input) {
147
- const repoPath = resolve(input.repo ?? ".");
148
- const skillsSourceDir = resolveSkillsSourceDir(input.skillsSource);
149
- await ensureDirectory(skillsSourceDir);
150
- const manifestHash = await hashDirectory(skillsSourceDir);
151
- const problems = [];
152
-
153
- for (const target of [".claude/skills", ".agents/skills"]) {
154
- await compareDirectories(skillsSourceDir, join(repoPath, target), target, problems);
155
- }
156
- for (const path of [
157
- "agent/BRAND.md",
158
- "agent/STRATEGY.md",
159
- "agent/LEARNINGS.md",
160
- "agent/runs/.gitkeep",
161
- "agent/archive/.gitkeep",
162
- "agent/skillpack.json",
163
- ]) {
164
- if (!(await exists(join(repoPath, path)))) problems.push(`Missing ${path}`);
165
- }
166
-
167
- const lock = await readJson(join(repoPath, "agent", "skillpack.json"));
168
- if (lock && typeof lock === "object" && lock.manifestHash !== manifestHash) {
169
- problems.push("agent/skillpack.json manifestHash does not match current skillpack");
170
- }
171
-
172
- return {
173
- ok: problems.length === 0,
174
- repoPath,
175
- skillsSourceDir,
176
- changed: [],
177
- problems,
178
- manifestHash,
179
- };
180
- }
181
-
182
- function resolveSkillsSourceDir(explicit) {
183
- if (explicit) return resolve(explicit);
184
- return defaultSkillsSourceDir();
185
- }
186
-
187
- function defaultSkillsSourceDir() {
188
- const scriptDir = dirname(fileURLToPath(import.meta.url));
189
- return resolve(scriptDir, "..", "..");
190
- }
191
-
192
- async function syncManagedDirectory(sourceDir, targetDir, changed) {
193
- const source = resolve(sourceDir);
194
- const target = resolve(targetDir);
195
- if (source === target) {
196
- return;
197
- }
198
- if (source.startsWith(`${target}/`)) {
199
- throw new Error(`Refusing to sync ${source} into itself at ${target}`);
200
- }
201
- await rm(target, { recursive: true, force: true });
202
- await mkdir(dirname(target), { recursive: true });
203
- await cp(source, target, { recursive: true });
204
- changed.push(relative(process.cwd(), target) || target);
205
- }
206
-
207
- async function syncContracts(repoPath, changed) {
208
- const contractsDir = join(repoPath, "agent", "contracts");
209
- await mkdir(contractsDir, { recursive: true });
210
- await writeIfChanged(
211
- join(contractsDir, "actions.schema.json"),
212
- `${JSON.stringify(ACTIONS_SCHEMA, null, 2)}\n`,
213
- changed,
214
- );
215
- await writeIfChanged(
216
- join(contractsDir, "memory-item.schema.json"),
217
- `${JSON.stringify(MEMORY_ITEM_SCHEMA, null, 2)}\n`,
218
- changed,
219
- );
220
- }
221
-
222
- async function ensureRunDirs(repoPath, changed) {
223
- for (const path of [join(repoPath, "agent", "runs"), join(repoPath, "agent", "archive")]) {
224
- await mkdir(path, { recursive: true });
225
- await writeIfMissing(join(path, ".gitkeep"), "", changed);
226
- }
227
- }
228
-
229
- async function ensureMemoryFiles(repoPath, changed) {
230
- await mkdir(join(repoPath, "agent"), { recursive: true });
231
- await writeIfMissing(
232
- join(repoPath, "agent", "BRAND.md"),
233
- "# Brand\n\nInitial local scaffold. Replace with workspace brand context before serious runs.\n",
234
- changed,
235
- );
236
- await writeIfMissing(
237
- join(repoPath, "agent", "STRATEGY.md"),
238
- "# GEO Strategy\n\n## Current Priorities\n\n- Initial local scaffold.\n",
239
- changed,
240
- );
241
- await writeIfMissing(
242
- join(repoPath, "agent", "LEARNINGS.md"),
243
- "# Learnings\n\n## Stable Learnings\n\n- Initial local scaffold.\n",
244
- changed,
245
- );
246
- }
247
-
248
- async function writeSkillpackLock(input, changed) {
249
- const sourceCommit = await gitOutput(input.skillsSourceDir, ["rev-parse", "HEAD"]);
250
- const lock = {
251
- name: "anymorph-geo",
252
- source: input.skillsSourceDir,
253
- sourceRepo: "opactor-dev/anymorph-geo-skills",
254
- requestedRef: input.ref,
255
- resolvedCommit: sourceCommit,
256
- scriptVersion: input.scriptVersion,
257
- manifestHash: input.manifestHash,
258
- installedAt: new Date().toISOString(),
259
- managedPaths: MANAGED_PATHS,
260
- };
261
- await writeIfChanged(
262
- join(input.repoPath, "agent", "skillpack.json"),
263
- `${JSON.stringify(lock, null, 2)}\n`,
264
- changed,
265
- );
266
- }
267
-
268
- async function compareDirectories(sourceDir, targetDir, displayPrefix, problems) {
269
- const sourceFiles = await listFiles(sourceDir);
270
- const targetFiles = await listFiles(targetDir);
271
- const targetSet = new Set(targetFiles);
272
- for (const file of sourceFiles) {
273
- const source = await readFile(join(sourceDir, file), "utf8");
274
- const targetPath = join(targetDir, file);
275
- if (!(await exists(targetPath))) {
276
- problems.push(`Missing ${displayPrefix}/${file}`);
277
- continue;
278
- }
279
- const target = await readFile(targetPath, "utf8");
280
- if (source !== target) problems.push(`Drifted ${displayPrefix}/${file}`);
281
- targetSet.delete(file);
282
- }
283
- for (const extra of targetSet) problems.push(`Extra managed file ${displayPrefix}/${extra}`);
284
- }
285
-
286
- async function hashDirectory(dir) {
287
- const files = await listFiles(dir);
288
- const hash = createHash("sha256");
289
- for (const file of files) {
290
- hash.update(file);
291
- hash.update("\0");
292
- hash.update(await readFile(join(dir, file)));
293
- hash.update("\0");
294
- }
295
- return `sha256:${hash.digest("hex")}`;
296
- }
297
-
298
- async function listFiles(dir, base = "") {
299
- let entries;
300
- try {
301
- entries = await readdir(join(dir, base), { withFileTypes: true });
302
- } catch {
303
- return [];
304
- }
305
- const files = [];
306
- for (const entry of entries) {
307
- const name = String(entry.name);
308
- const path = base ? `${base}/${name}` : name;
309
- if (entry.isDirectory()) files.push(...(await listFiles(dir, path)));
310
- else if (entry.isFile()) files.push(path);
311
- }
312
- return files.sort();
313
- }
314
-
315
- async function writeIfMissing(path, content, changed) {
316
- if (await exists(path)) return;
317
- await mkdir(dirname(path), { recursive: true });
318
- await writeFile(path, content);
319
- changed.push(relative(process.cwd(), path) || path);
320
- }
321
-
322
- async function writeIfChanged(path, content, changed) {
323
- const current = await readFile(path, "utf8").catch(() => null);
324
- if (current === content) return;
325
- await mkdir(dirname(path), { recursive: true });
326
- await writeFile(path, content);
327
- changed.push(relative(process.cwd(), path) || path);
328
- }
329
-
330
- async function readJson(path) {
331
- const raw = await readFile(path, "utf8").catch(() => null);
332
- if (!raw) return null;
333
- try {
334
- return JSON.parse(raw);
335
- } catch {
336
- return null;
337
- }
338
- }
339
-
340
- async function gitOutput(cwd, args) {
341
- try {
342
- const { stdout } = await execFileAsync("git", args, { cwd });
343
- return stdout.trim() || null;
344
- } catch {
345
- return null;
346
- }
347
- }
348
-
349
- async function ensureDirectory(path) {
350
- const s = await stat(path);
351
- if (!s.isDirectory()) throw new Error(`${path} is not a directory`);
352
- }
353
-
354
- async function exists(path) {
355
- return stat(path)
356
- .then(() => true)
357
- .catch(() => false);
358
- }
@@ -1,66 +0,0 @@
1
- #!/usr/bin/env node
2
- import { spawn } from "node:child_process";
3
-
4
- const legacyCommand = process.argv[2];
5
- const legacyArgs = process.argv.slice(3);
6
-
7
- const commandMap = new Map([
8
- ["materialize", "submit"],
9
- ["check", "doctor"],
10
- ["sync", "doctor"],
11
- ]);
12
-
13
- if (!legacyCommand || ["-h", "--help", "help"].includes(legacyCommand)) {
14
- usage();
15
- process.exit(0);
16
- }
17
-
18
- if (legacyArgs.includes("--repo")) {
19
- console.error(
20
- "`--repo` is no longer supported. Run `anymorph` from the tenant repo root instead.",
21
- );
22
- process.exit(2);
23
- }
24
-
25
- const command = commandMap.get(legacyCommand) ?? legacyCommand;
26
- const args = legacyArgs.filter((arg) => !arg.startsWith("--repo="));
27
- if (legacyCommand === "sync") args.unshift("--fix");
28
-
29
- console.error(
30
- "`geo.mjs` is deprecated. Use the top-level Anymorph CLI: " +
31
- `anymorph ${[command, ...args].join(" ")}`.trim(),
32
- );
33
-
34
- const child = spawn("anymorph", [command, ...args], {
35
- stdio: "inherit",
36
- env: process.env,
37
- });
38
-
39
- child.on("exit", (code, signal) => {
40
- if (signal) {
41
- process.kill(process.pid, signal);
42
- return;
43
- }
44
- process.exit(code ?? 1);
45
- });
46
-
47
- child.on("error", (err) => {
48
- console.error(`Could not run \`anymorph\`: ${err.message}`);
49
- process.exit(1);
50
- });
51
-
52
- function usage() {
53
- console.error(`Usage:
54
- anymorph login
55
- anymorph logout
56
- anymorph status
57
- anymorph workspaces
58
- anymorph init
59
- anymorph doctor
60
- anymorph doctor --fix
61
- anymorph prepare <workspaceId>
62
- anymorph validate <runId>
63
- anymorph submit <runId>
64
- anymorph intents <runId>
65
- anymorph run-status <runId>`);
66
- }
@@ -1,50 +0,0 @@
1
- ---
2
- name: geo-initializing-strategy
3
- description: Use when creating or repairing the initial Strategy Map baseline for an Anymorph workspace before recurring GEO action generation begins.
4
- ---
5
-
6
- # GEO Initializing Strategy
7
-
8
- Use this skill to create the first durable Strategy Map for a tenant.
9
-
10
- This is a baseline skill, not an action-generation skill. It diagnoses the workspace's owned-site foundation, visibility state, semantic clusters, and external authority so later GEO loops have a stable operating plan.
11
-
12
- ## Required Inputs
13
-
14
- - Tenant repository path.
15
- - `workspaceId` for internal MCP calls.
16
- - Host-created Strategy Map context and manifest files.
17
- - Existing tenant memory files when present:
18
- - `agent/BRAND.md`
19
- - `agent/STRATEGY.md`
20
- - `agent/LEARNINGS.md`
21
-
22
- ## Workflow
23
-
24
- 1. Read the host context and manifest first.
25
- 2. Read existing tenant memory before using external evidence.
26
- 3. Use Strategy Map diagnoses for foundation, visibility, semantic clusters, and external authority.
27
- 4. Treat diagnosis section JSON files as the source of truth after they are submitted.
28
- 5. Synthesize a long-term strategy with investment mix, active bets, guardrails, and open strategic questions.
29
- 6. Rewrite `agent/STRATEGY.md` as the canonical human-readable Strategy Map.
30
- 7. Submit structured Strategy Map artifacts through the runtime artifact tools; do not write structured JSON artifacts directly.
31
-
32
- ## Contracts
33
-
34
- Read these references only when needed:
35
-
36
- - `references/memory-contract.md` for tenant memory file requirements.
37
- - `references/strategy-map-contract.md` for output boundaries and quality bar.
38
- - `references/foundation-diagnosis.md` for owned-site foundation diagnosis.
39
- - `references/visibility-diagnosis.md` for AI visibility baseline diagnosis.
40
- - `references/semantic-clusters-diagnosis.md` for semantic cluster diagnosis.
41
- - `references/external-authority-diagnosis.md` for external authority diagnosis.
42
-
43
- ## Guardrails
44
-
45
- - Preserve YAML frontmatter on existing tenant memory files.
46
- - Never write empty frontmatter.
47
- - Do not generate weekly actions, page briefs, outreach tasks, or execution steps.
48
- - Prefer `unknown` or omitted optional fields over invented certainty.
49
- - Exclude Anymorph-generated GEO pages from owned-site foundation evidence.
50
- - Do not edit `agent/BRAND.md`; raise brand drift in rationale instead.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "GEO Initializing Strategy"
3
- short_description: "Create the initial Strategy Map baseline for a workspace."
4
- default_prompt: "Use $geo-initializing-strategy to create the initial Strategy Map baseline for this workspace."
@@ -1,66 +0,0 @@
1
- # Strategy Map: External Authority Diagnosis
2
-
3
- Summarize external authority by surface class:
4
-
5
- - Reddit
6
- - YouTube
7
- - Wikipedia/Wikidata
8
- - review platforms
9
- - directories
10
- - publications
11
- - forums
12
- - podcasts
13
- - newsletters
14
- - social
15
- - other
16
-
17
- Capture tenant presence, competitor presence, relevance, actionability, and strategic implication.
18
-
19
- Do not include outreach copy, posts, scripts, or tactical execution steps.
20
-
21
- Use DataForSEO as the primary paid source for backlink and referring-domain evidence. Prefer `mcp__anymorph__dataforseo_research` for:
22
-
23
- - `/v3/backlinks/summary/live`
24
- - `/v3/backlinks/referring_domains/live`
25
- - `/v3/backlinks/backlinks/live`
26
- - `/v3/dataforseo_labs/google/domain_rank_overview/live`
27
-
28
- Ahrefs is not required for this section.
29
-
30
- Keep web research bounded:
31
-
32
- - Use at most 6 `mcp__anymorph__web_search` calls.
33
- - Use `mcp__anymorph__summarized_web_scrape` only for the highest-signal pages that change the diagnosis.
34
- - Prefer citation tools before broad web search.
35
-
36
- Never emit `null`. Omit optional fields when unknown. Required unknown enum fields must use `unknown`.
37
-
38
- Submit exactly one section artifact with `mcp__strategy_map_artifacts__submit_strategy_map_section`.
39
-
40
- ```json
41
- {
42
- "section": "externalAuthority",
43
- "artifact": [
44
- {
45
- "id": "auth-short-stable-id",
46
- "surfaceClass": "reddit | youtube | wikipedia_wikidata | review_platform | directory | publication | forum | podcast | newsletter | social | other",
47
- "relevance": "high | medium | low | unknown",
48
- "tenantPresence": "strong | medium | weak | absent | unknown",
49
- "competitorPresence": "strong | medium | weak | absent | unknown",
50
- "actionability": "high | medium | low | none | unknown",
51
- "strategicImplication": "What this authority state means for the roadmap.",
52
- "evidenceRefs": ["ev-authority-1"]
53
- }
54
- ],
55
- "evidence": [
56
- {
57
- "id": "ev-authority-1",
58
- "type": "signal | workspace | source | research",
59
- "ref": "tool or source reference",
60
- "summary": "Specific evidence summary."
61
- }
62
- ]
63
- }
64
- ```
65
-
66
- Final response: one short sentence naming the saved section.
@@ -1,86 +0,0 @@
1
- # Strategy Map: Foundation Diagnosis
2
-
3
- Diagnose the technical SEO/GEO foundation.
4
-
5
- Focus only on durable strategic signals:
6
-
7
- - indexability
8
- - crawlability
9
- - schema/content parity
10
- - AI crawler access
11
- - internal linking
12
- - page experience
13
-
14
- Do not emit page-level fixes, implementation briefs, or action lists.
15
-
16
- Use `mcp__anymorph__dataforseo_onpage` as the primary owned-site crawl and internal-link evidence source.
17
-
18
- Baseline rule:
19
-
20
- - Foundation is the existing brand-owned site baseline.
21
- - Exclude Anymorph-generated GEO pages from owned-page, internal-link hub, inbound-link, orphan-page, and crawl-state judgments.
22
- - Pass `workspaceId` to `dataforseo_onpage`; backend will remove generated GEO pages from DFS pages/links results.
23
- - Generated GEO pages may be mentioned only as strategy execution surfaces in semantic/visibility synthesis, not as Foundation evidence.
24
-
25
- Expected DataForSEO On-Page flow:
26
-
27
- 1. `action=start_crawl`, `target=<workspace domain>`, `workspaceId=<workspace id>`, `maxCrawlPages` around 100.
28
- 2. `action=summary` with the returned `taskId`, `workspaceId=<workspace id>`.
29
- 3. If the crawl is finished, call `action=pages` ordered by `meta.inbound_links_count,desc`, with `workspaceId=<workspace id>`.
30
- 4. Call `action=links` with `direction=internal`, `dofollowOnly=true`, `workspaceId=<workspace id>`.
31
-
32
- Use these DFS fields:
33
-
34
- - `status_code` and `page_to_status_code` for crawl/indexability evidence.
35
- - `meta.internal_links_count`, `meta.inbound_links_count`, and `checks.is_orphan_page` for internal-link topology.
36
- - `page_from`, `page_to`, `link_from`, `link_to`, and `dofollow` for edge evidence.
37
-
38
- Do not use DataForSEO Backlinks API as a substitute for owned-site internal-link evidence. Use DataForSEO On-Page only.
39
-
40
- Do not claim a page is an in-content hub from DFS alone. DFS On-Page can show internal edges and target status, but not guaranteed nav/footer/content placement. For true in-content hub claims, corroborate with page content or page HTML via `get_page_content` or summarized scrape.
41
-
42
- Use Ahrefs only as optional enrichment for crawl and in-content internal-link evidence. For internal-link hubs, filter to in-content, dofollow links when the endpoint supports it. If Ahrefs returns "API units limit reached", times out, fails auth, or is unavailable, stop calling Ahrefs and continue with DataForSEO On-Page + owned-source evidence.
43
-
44
- Use `mcp__anymorph__summarized_web_scrape` by its full tool name. Do not call a bare `mcp__summarized_web_scrape`.
45
-
46
- Never emit `null`. Omit optional fields when unknown. Required unknown enum fields must use `unknown`.
47
-
48
- Submit exactly one section artifact with `mcp__strategy_map_artifacts__submit_strategy_map_section`.
49
-
50
- ```json
51
- {
52
- "section": "foundation",
53
- "artifact": {
54
- "status": "strong | medium | weak | unknown",
55
- "signals": {
56
- "indexability": "strong | medium | weak | unknown",
57
- "crawlability": "strong | medium | weak | unknown",
58
- "schemaParity": "strong | medium | weak | unknown",
59
- "aiCrawlerAccess": "strong | medium | weak | unknown",
60
- "internalLinking": "strong | medium | weak | unknown",
61
- "pageExperience": "strong | medium | weak | unknown"
62
- },
63
- "blockers": [
64
- {
65
- "id": "blk-short-stable-id",
66
- "type": "indexability | crawlability | schema_parity | ai_crawler_access | internal_linking | page_experience | faceted_navigation | duplicate_content | rendering | other",
67
- "severity": "high | medium | low",
68
- "summary": "Strategic blocker, not a page-level fix brief.",
69
- "evidenceRefs": ["ev-foundation-1"]
70
- }
71
- ],
72
- "strategicImplication": "What this foundation state means for long-term investment mix.",
73
- "evidenceRefs": ["ev-foundation-1"]
74
- },
75
- "evidence": [
76
- {
77
- "id": "ev-foundation-1",
78
- "type": "signal | workspace | source | research",
79
- "ref": "tool or source reference",
80
- "summary": "Specific evidence summary."
81
- }
82
- ]
83
- }
84
- ```
85
-
86
- Final response: one short sentence naming the saved section.
@@ -1,15 +0,0 @@
1
- # Tenant Memory Contract
2
-
3
- Durable tenant memory lives in the tenant repository.
4
-
5
- - `agent/BRAND.md`: brand facts regenerated by backend; read-only during Strategy Map runs.
6
- - `agent/STRATEGY.md`: canonical human-readable Strategy Map.
7
- - `agent/LEARNINGS.md`: stable repeated observations only.
8
-
9
- Rules:
10
-
11
- - Keep frontmatter present and non-empty.
12
- - Preserve existing frontmatter keys unless the run has explicit reason to update them.
13
- - Keep memory concise.
14
- - Do not paste raw evidence, generic SEO advice, or long research transcripts.
15
- - Put run-specific details under `agent/strategy-map/runs/{runId}/`.