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.
- package/README.md +3 -3
- package/dist/index.js +78 -6
- package/package.json +1 -1
- package/dist/skillpacks/geo/scaffold/AGENTS.md +0 -38
- package/dist/skillpacks/geo/scaffold/CLAUDE.md +0 -33
- package/dist/skillpacks/geo/shared/evidence-principles.md +0 -35
- package/dist/skillpacks/geo/shared/geo-principles.md +0 -281
- package/dist/skillpacks/geo/shared/vertical-playbooks/beauty.md +0 -65
- package/dist/skillpacks/geo/shared/vertical-playbooks/commerce.md +0 -65
- package/dist/skillpacks/geo/shared/vertical-playbooks/ota.md +0 -62
- package/dist/skillpacks/geo/shared/vertical-playbooks/saas.md +0 -64
- package/dist/skillpacks/geo/skills/brand-owned-diagnosis/SKILL.md +0 -54
- package/dist/skillpacks/geo/skills/brand-owned-diagnosis/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/brand-owned-diagnosis/references/diagnosis-contract.md +0 -95
- package/dist/skillpacks/geo/skills/brand-owned-diagnosis/references/workflow.md +0 -194
- package/dist/skillpacks/geo/skills/geo-generating-actions/SKILL.md +0 -188
- package/dist/skillpacks/geo/skills/geo-generating-actions/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/geo-generating-actions/references/orchestrator.workflow.md +0 -440
- package/dist/skillpacks/geo/skills/geo-generating-actions/scripts/geo-scaffold.mjs +0 -358
- package/dist/skillpacks/geo/skills/geo-generating-actions/scripts/geo.mjs +0 -66
- package/dist/skillpacks/geo/skills/geo-initializing-strategy/SKILL.md +0 -50
- package/dist/skillpacks/geo/skills/geo-initializing-strategy/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/external-authority-diagnosis.md +0 -66
- package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/foundation-diagnosis.md +0 -86
- package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/memory-contract.md +0 -15
- package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/semantic-clusters-diagnosis.md +0 -58
- package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/strategy-map-contract.md +0 -26
- package/dist/skillpacks/geo/skills/geo-initializing-strategy/references/visibility-diagnosis.md +0 -50
- package/dist/skillpacks/geo/skills/geo-local-setup/SKILL.md +0 -66
- package/dist/skillpacks/geo/skills/geo-local-setup/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/geo-page-writer/SKILL.md +0 -81
- package/dist/skillpacks/geo/skills/geo-page-writer/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/geo-page-writer/references/research.md +0 -61
- package/dist/skillpacks/geo/skills/geo-page-writer/references/validation.md +0 -59
- package/dist/skillpacks/geo/skills/geo-page-writer/references/writing.md +0 -55
- package/dist/skillpacks/geo/skills/geo-page-writer/scripts/check-page-mdx.mjs +0 -210
- package/dist/skillpacks/geo/skills/geo-page-writer/scripts/collect-page-sources.mjs +0 -303
- package/dist/skillpacks/geo/skills/geo-pages-diagnosis/SKILL.md +0 -51
- package/dist/skillpacks/geo/skills/geo-pages-diagnosis/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/geo-pages-diagnosis/references/diagnosis-contract.md +0 -125
- package/dist/skillpacks/geo/skills/geo-pages-diagnosis/references/workflow.md +0 -269
- package/dist/skillpacks/geo/skills/geo-writer/SKILL.md +0 -234
- package/dist/skillpacks/geo/skills/geo-writer/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/geo-writer/references/content-writer-contract.md +0 -316
- package/dist/skillpacks/geo/skills/geo-writer/references/direct-sql.md +0 -187
- package/dist/skillpacks/geo/skills/geo-writer/references/seo-geo-insights.md +0 -269
- package/dist/skillpacks/geo/skills/seo-ecommerce-opportunity/SKILL.md +0 -82
- package/dist/skillpacks/geo/skills/seo-ecommerce-opportunity/agents/openai.yaml +0 -5
- package/dist/skillpacks/geo/skills/seo-ecommerce-opportunity/references/ecommerce-rules.md +0 -31
- package/dist/skillpacks/geo/skills/seo-internal-link-opportunity/SKILL.md +0 -57
- package/dist/skillpacks/geo/skills/seo-internal-link-opportunity/agents/openai.yaml +0 -5
- package/dist/skillpacks/geo/skills/seo-internal-link-opportunity/references/link-rules.md +0 -28
- package/dist/skillpacks/geo/skills/seo-opportunity-audit/SKILL.md +0 -141
- package/dist/skillpacks/geo/skills/seo-opportunity-audit/agents/openai.yaml +0 -5
- package/dist/skillpacks/geo/skills/seo-opportunity-audit/references/action-contract.md +0 -62
- package/dist/skillpacks/geo/skills/seo-opportunity-audit/scripts/seo-toolkit.mjs +0 -248
- package/dist/skillpacks/geo/skills/seo-page-diagnosis/SKILL.md +0 -56
- package/dist/skillpacks/geo/skills/seo-page-diagnosis/agents/openai.yaml +0 -5
- package/dist/skillpacks/geo/skills/seo-page-diagnosis/references/page-checks.md +0 -38
- package/dist/skillpacks/geo/skills/seo-serp-opportunity-research/SKILL.md +0 -66
- package/dist/skillpacks/geo/skills/seo-serp-opportunity-research/agents/openai.yaml +0 -5
- package/dist/skillpacks/geo/skills/seo-serp-opportunity-research/references/page-type-taxonomy.md +0 -40
- package/dist/skillpacks/geo/skills/seo-serp-opportunity-research/references/serp-methodology.md +0 -38
- package/dist/skillpacks/geo/skills/seo-technical-diagnosis/SKILL.md +0 -64
- package/dist/skillpacks/geo/skills/seo-technical-diagnosis/agents/openai.yaml +0 -5
- package/dist/skillpacks/geo/skills/seo-technical-diagnosis/references/checks.md +0 -58
- package/dist/skillpacks/geo/skills/third-party-diagnosis/SKILL.md +0 -54
- package/dist/skillpacks/geo/skills/third-party-diagnosis/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/third-party-diagnosis/references/diagnosis-contract.md +0 -111
- package/dist/skillpacks/geo/skills/third-party-diagnosis/references/workflow.md +0 -174
- package/dist/skillpacks/geo/skills/third-party-execution-planning/SKILL.md +0 -64
- package/dist/skillpacks/geo/skills/third-party-execution-planning/agents/openai.yaml +0 -4
- package/dist/skillpacks/geo/skills/third-party-execution-planning/references/execution-contract.md +0 -90
- package/dist/skillpacks/geo/skills/third-party-execution-planning/references/non-social-surface-playbooks.md +0 -123
- package/dist/skillpacks/geo/skills/third-party-execution-planning/references/reddit-rules.md +0 -69
- package/dist/skillpacks/geo/skills/third-party-execution-planning/references/social-platform-playbooks.md +0 -59
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: geo-generating-actions
|
|
3
|
-
description: Use when generating recurring or on-demand GEO strategy actions from tenant memory, run context, channel diagnoses, and evidence-backed opportunity candidates.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# GEO Generating Actions
|
|
7
|
-
|
|
8
|
-
Use this skill to orchestrate GEO action generation.
|
|
9
|
-
|
|
10
|
-
This skill owns the final decision. Channel diagnosis should be handled by product diagnosis skills, then merged and judged here.
|
|
11
|
-
|
|
12
|
-
## Channel Skills
|
|
13
|
-
|
|
14
|
-
Use these skills for channel-specific diagnosis:
|
|
15
|
-
|
|
16
|
-
- `$brand-owned-diagnosis` for customer-owned pages.
|
|
17
|
-
- `$geo-pages-diagnosis` for generated GEO pages.
|
|
18
|
-
- `$third-party-diagnosis` for Earn and external authority work.
|
|
19
|
-
- `$third-party-execution-planning` for selected third-party Earn actions that need human-executable social, directory, review, listing, marketplace, partner, or editorial plans.
|
|
20
|
-
- `$seo-opportunity-audit` for a full SEO opportunity pass when technical, page, SERP, internal-link, or ecommerce SEO evidence is needed.
|
|
21
|
-
- Focused SEO skills for narrow SEO evidence: `$seo-technical-diagnosis`, `$seo-page-diagnosis`, `$seo-serp-opportunity-research`, `$seo-internal-link-opportunity`, and `$seo-ecommerce-opportunity`.
|
|
22
|
-
|
|
23
|
-
## Required Reference
|
|
24
|
-
|
|
25
|
-
Read `references/orchestrator.workflow.md` before final action selection. It contains the full production workflow: context construction, channel invocation order, proposal merge rules, conflict resolution, no-action discipline, and final artifact contract.
|
|
26
|
-
|
|
27
|
-
Also read shared references when relevant:
|
|
28
|
-
|
|
29
|
-
- `../../shared/evidence-principles.md` before accepting claim-sensitive,
|
|
30
|
-
freshness-sensitive, schema/feed, product/SKU, comparison, review, or
|
|
31
|
-
compliance-sensitive proposals.
|
|
32
|
-
- `../../shared/vertical-playbooks/{vertical}.md` when the tenant vertical is
|
|
33
|
-
known. Load only matching playbooks, such as `beauty.md`, `saas.md`,
|
|
34
|
-
`ota.md`, or `commerce.md`; use them as vertical heuristics, not as proof.
|
|
35
|
-
Tenant-specific strategy in `agent/STRATEGY.md` overrides generic playbooks.
|
|
36
|
-
|
|
37
|
-
## Workflow
|
|
38
|
-
|
|
39
|
-
1. Read host-created run files and stable tenant memory.
|
|
40
|
-
2. Load relevant shared evidence and vertical references only when they affect
|
|
41
|
-
judgment.
|
|
42
|
-
3. Build one compact shared run context.
|
|
43
|
-
4. Invoke or apply the three channel diagnosis skills.
|
|
44
|
-
5. For selected third-party proposals, invoke or apply `$third-party-execution-planning` before writing final actions.
|
|
45
|
-
6. Persist each channel diagnosis under `agent/runs/{runId}/subagents/` as JSON plus compact `*.rationale.md`.
|
|
46
|
-
7. When SEO evidence is needed, persist SEO skill artifacts under `agent/seo/{skillName}/{runId}/` and reference them from final proposals.
|
|
47
|
-
8. Read channel outputs and reject weak, duplicate, or conflicting proposals.
|
|
48
|
-
9. Prefer no action over low-evidence action.
|
|
49
|
-
10. In hosted remote mode, submit the final artifact with the provided runtime artifact tool. In local mode only, write `agent/runs/{runId}/actions.json` directly.
|
|
50
|
-
11. Write rationale and status files only under the current run path.
|
|
51
|
-
12. Update durable tenant memory only when the run changes stable strategy or repeated learnings.
|
|
52
|
-
|
|
53
|
-
## Local Skillpack Mode
|
|
54
|
-
|
|
55
|
-
When running inside a tenant repo, this skill expects a prepared run directory.
|
|
56
|
-
Do not invent a `runId` or create fake input files.
|
|
57
|
-
|
|
58
|
-
Use the top-level `anymorph` CLI to prepare the same filesystem contract that
|
|
59
|
-
remote runners use. For first-time setup or repair, use `$geo-local-setup`.
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
anymorph status
|
|
63
|
-
anymorph login
|
|
64
|
-
anymorph init
|
|
65
|
-
anymorph doctor
|
|
66
|
-
anymorph prepare <workspaceId>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
`init` installs or syncs the managed skills and local memory scaffold. It does
|
|
70
|
-
not create a strategy run.
|
|
71
|
-
`prepare` fetches the workspace run package from the backend and creates the
|
|
72
|
-
run files.
|
|
73
|
-
|
|
74
|
-
`prepare` creates:
|
|
75
|
-
|
|
76
|
-
- `agent/runs/{runId}/manifest.json`
|
|
77
|
-
- `agent/runs/{runId}/context.json`
|
|
78
|
-
- `agent/runs/{runId}/policy.json`
|
|
79
|
-
- `agent/runs/{runId}/intents.json`
|
|
80
|
-
- `agent/runs/{runId}/products.json`
|
|
81
|
-
- `agent/runs/{runId}/intent_products.json`
|
|
82
|
-
- `agent/runs/{runId}/crawl_logs.json`
|
|
83
|
-
- `agent/runs/{runId}/status.json`
|
|
84
|
-
|
|
85
|
-
`intents.json` comes from `signals.intents` in the backend prepare response.
|
|
86
|
-
It is the same source used by the remote GEO strategy runner.
|
|
87
|
-
For commerce workspaces, `products.json` and `intent_products.json` come from
|
|
88
|
-
the active Product Catalog and IntentProduct mappings.
|
|
89
|
-
|
|
90
|
-
Inspect prepared intents when needed:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
anymorph intents {runId}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Then run this skill against that `runId`. Use MCP tools only to enrich the
|
|
97
|
-
prepared context or inspect deeper evidence. Do not use MCP calls to replace
|
|
98
|
-
the run package.
|
|
99
|
-
|
|
100
|
-
For local runs, there is no hosted runtime artifact submission tool. The final
|
|
101
|
-
artifact contract is the same JSON object shape the remote submit tool accepts,
|
|
102
|
-
but persisted through the filesystem:
|
|
103
|
-
|
|
104
|
-
- write `agent/runs/{runId}/subagents/brand_owned.json`
|
|
105
|
-
- write `agent/runs/{runId}/subagents/brand_owned.rationale.md`
|
|
106
|
-
- write `agent/runs/{runId}/subagents/geo_pages.json`
|
|
107
|
-
- write `agent/runs/{runId}/subagents/geo_pages.rationale.md`
|
|
108
|
-
- write `agent/runs/{runId}/subagents/third_party.json`
|
|
109
|
-
- write `agent/runs/{runId}/subagents/third_party.rationale.md`
|
|
110
|
-
- write `agent/runs/{runId}/actions.json`
|
|
111
|
-
- write `agent/runs/{runId}/rationale.md`
|
|
112
|
-
- update `agent/runs/{runId}/status.json`
|
|
113
|
-
|
|
114
|
-
After writing artifacts, validate them with:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
anymorph validate {runId}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
Then commit and push the tenant repo artifacts, and submit the run to backend:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
git add agent/runs/{runId} agent/STRATEGY.md agent/LEARNINGS.md
|
|
124
|
-
git commit -m "chore: add geo strategy run {runId}"
|
|
125
|
-
git push origin main
|
|
126
|
-
anymorph submit {runId}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
`submit` registers or updates the backend run as `proposed`, reads
|
|
130
|
-
`agent/runs/{runId}/actions.json` from the tenant repo, and immediately
|
|
131
|
-
materializes it in Dashboard. There is no separate approve step.
|
|
132
|
-
|
|
133
|
-
### Adding Actions After a Run Is Submitted
|
|
134
|
-
|
|
135
|
-
A submitted run is immutable. Once `submit` succeeds the backend locks the run
|
|
136
|
-
as `executed`, so re-submitting the same `runId` — even after editing
|
|
137
|
-
`actions.json` and pushing again — is a silent no-op: it returns `executed`
|
|
138
|
-
without re-reading the file or materializing anything.
|
|
139
|
-
|
|
140
|
-
To add or change actions, do not edit an executed run. Run a fresh `prepare` to
|
|
141
|
-
get a new `runId`, write the actions under that new run directory, then
|
|
142
|
-
`validate`, commit, push, and `submit` the new run.
|
|
143
|
-
|
|
144
|
-
Put only the new actions in the new run unless you intend to re-materialize the
|
|
145
|
-
prior set. Materialize is additive, not a declarative replace: `third_party` and
|
|
146
|
-
`brand_owned` actions create new rows on every run (the prior run's rows stay
|
|
147
|
-
`open`), while `geo_page` actions upsert by slug (the same slug is re-queued for
|
|
148
|
-
generation).
|
|
149
|
-
|
|
150
|
-
Only use runtime artifact tools when the host environment explicitly provides
|
|
151
|
-
them. In ordinary local tenant repo work, the filesystem artifacts above are the
|
|
152
|
-
source of truth.
|
|
153
|
-
|
|
154
|
-
## Contract Guardrails
|
|
155
|
-
|
|
156
|
-
Write `agent/runs/{runId}/actions.json` exactly to the production contract in
|
|
157
|
-
`apps/shared-contracts/src/index.cjs` plus the backend business rules in
|
|
158
|
-
`apps/backend/src/modules/geo-strategy/geo-strategy-action.schema.ts`.
|
|
159
|
-
|
|
160
|
-
- The artifact root is strict. Use only `schemaVersion`, `runId`, `policy`, and `actions`. Never add `artifactPaths` to `actions.json`; that belongs only to submit transport.
|
|
161
|
-
- Each action is strict. Include `id`, `operation`, `surface`, `assetType`, `intentId`, `target`, `objective`, `changeBrief`, `reason`, `expectedOutcome`, `evidence`, `priority`, and `confidence`; do not add extra keys.
|
|
162
|
-
- Each `evidence[]` item is strict: `{ "type": "signal" | "workspace" | "source" | "research", "ref": "...", "summary": "..." }`.
|
|
163
|
-
- `target` is strict. Allowed keys are only `pageId`, `url`, `title`, `description`, `queryCluster`, `sourceDomain`, `suggestedSlug`, `pageRole`, and `targetProductIds`. Never use `target.domain`; use `target.sourceDomain` for third-party domains.
|
|
164
|
-
- `brand_owned` target may use `pageId` or `url`; do not include `pageRole`, `suggestedSlug`, `sourceDomain`, or `targetProductIds`.
|
|
165
|
-
- `geo_page` create target must use root-relative `suggestedSlug` or `url` plus `title`; do not include `pageId` or `sourceDomain`.
|
|
166
|
-
- `geo_page` update target may use `pageId` or `url`; do not include `pageRole`, `suggestedSlug`, `sourceDomain`, or `targetProductIds`.
|
|
167
|
-
- `third_party` target must use `sourceDomain` or absolute http(s) `url`; do not include `pageId`, `pageRole`, `suggestedSlug`, or `targetProductIds`.
|
|
168
|
-
|
|
169
|
-
## Final Decision Rules
|
|
170
|
-
|
|
171
|
-
- Emit at most 20 actions.
|
|
172
|
-
- Use only `create` or `update` operations.
|
|
173
|
-
- Use `surface: "on_page"` for `brand_owned` and `geo_page`.
|
|
174
|
-
- Use `surface: "off_page"` for `third_party`.
|
|
175
|
-
- Use `brand_owned` only for customer-owned discovered pages.
|
|
176
|
-
- Use `brand_owned` only with `operation: "update"`.
|
|
177
|
-
- Use `geo_page` only for generated or managed GEO page work.
|
|
178
|
-
- Use `third_party` only for off-page Earn work.
|
|
179
|
-
- Every action must include either an existing `intentId` or a non-null `proposedIntent`.
|
|
180
|
-
- If `intentId` is a string, omit `proposedIntent`; do not set it to null.
|
|
181
|
-
- `geo_page` create actions must include a root-relative `target.suggestedSlug` or `target.url` and `target.title`.
|
|
182
|
-
- For commerce workspace `geo_page` create actions, include 1-5 `target.targetProductIds` from `products.json` or `intent_products.json`.
|
|
183
|
-
- Do not emit commerce `geo_page` create actions when no catalog product evidence fits the intent.
|
|
184
|
-
- Third-party actions must name the exact domain and, when known, the exact publish surface.
|
|
185
|
-
- Third-party `changeBrief` must include the surface, format, angle, and concrete execution steps.
|
|
186
|
-
- Third-party actions for directory, review, listing, marketplace, partner, open-listicle, social, or owned-profile work should be based on `$third-party-execution-planning` output when the diagnosis proposal is selected.
|
|
187
|
-
- When using `$third-party-execution-planning`, derive the final action from its work-order fields: `executionType`, `surfaces`, `requiredAssets`, `policyChecks`, `executionSteps`, `completionSignal`, `impactSignal`, and `fallback`.
|
|
188
|
-
- For third-party final actions, fold `executionType`, required assets, policy checks, operator steps, and fallback into `changeBrief`; use `completionSignal` and `impactSignal` to write `expectedOutcome`.
|
package/dist/skillpacks/geo/skills/geo-generating-actions/references/orchestrator.workflow.md
DELETED
|
@@ -1,440 +0,0 @@
|
|
|
1
|
-
# Orchestrator Workflow
|
|
2
|
-
|
|
3
|
-
## Role
|
|
4
|
-
|
|
5
|
-
The orchestrator owns the weekly GEO strategy run.
|
|
6
|
-
|
|
7
|
-
It does four things:
|
|
8
|
-
|
|
9
|
-
1. Analyze last week's performance.
|
|
10
|
-
2. Combine performance with tenant strategy into one common run context.
|
|
11
|
-
3. Run all three channel diagnoses with that common context.
|
|
12
|
-
4. Judge the returned proposals and write the final action list.
|
|
13
|
-
|
|
14
|
-
The orchestrator is not just a router.
|
|
15
|
-
|
|
16
|
-
It is the final decision-maker for the run.
|
|
17
|
-
|
|
18
|
-
## Inputs
|
|
19
|
-
|
|
20
|
-
- `agent/runs/{runId}/context.json`
|
|
21
|
-
- `agent/runs/{runId}/manifest.json`
|
|
22
|
-
- `agent/runs/{runId}/policy.json`
|
|
23
|
-
- `agent/runs/{runId}/intents.json`
|
|
24
|
-
- `agent/BRAND.md`
|
|
25
|
-
- `agent/STRATEGY.md`
|
|
26
|
-
- `agent/LEARNINGS.md`
|
|
27
|
-
- prior `agent/runs/*` summaries when useful
|
|
28
|
-
- `schemaCatalog`
|
|
29
|
-
- `signals`
|
|
30
|
-
- `geo_*` query surface
|
|
31
|
-
|
|
32
|
-
## Required Views
|
|
33
|
-
|
|
34
|
-
Use these views when available:
|
|
35
|
-
|
|
36
|
-
- `geo_intent_coverage`
|
|
37
|
-
- `geo_recommendation_quadrants`
|
|
38
|
-
- `geo_page_intent_visibility_gaps`
|
|
39
|
-
- `geo_page_performance`
|
|
40
|
-
- `geo_strategy_actions_recent`
|
|
41
|
-
- `geo_pages`
|
|
42
|
-
- `geo_intents`
|
|
43
|
-
|
|
44
|
-
Use these when third-party analysis is enabled:
|
|
45
|
-
|
|
46
|
-
- `geo_intent_citations`
|
|
47
|
-
- `geo_third_party_domains`
|
|
48
|
-
- `geo_competitor_citations`
|
|
49
|
-
- `geo_third_party_sentiment`
|
|
50
|
-
|
|
51
|
-
If a view is unavailable, continue with lower confidence and record the missing view in `rationale.md`.
|
|
52
|
-
|
|
53
|
-
## Workflow
|
|
54
|
-
|
|
55
|
-
### 1. Load Stable Tenant Context
|
|
56
|
-
|
|
57
|
-
Read:
|
|
58
|
-
|
|
59
|
-
- `agent/BRAND.md`
|
|
60
|
-
- `agent/STRATEGY.md`
|
|
61
|
-
- `agent/LEARNINGS.md`
|
|
62
|
-
- recent prior run artifacts
|
|
63
|
-
|
|
64
|
-
Extract:
|
|
65
|
-
|
|
66
|
-
- current tenant priorities
|
|
67
|
-
- explicit channel preferences
|
|
68
|
-
- forbidden actions
|
|
69
|
-
- recent bets
|
|
70
|
-
- repeated learnings
|
|
71
|
-
- open questions
|
|
72
|
-
|
|
73
|
-
Do not rewrite tenant memory in this phase.
|
|
74
|
-
|
|
75
|
-
### 2. Analyze Last Week's Performance
|
|
76
|
-
|
|
77
|
-
Build a concise performance summary for the run.
|
|
78
|
-
|
|
79
|
-
Use:
|
|
80
|
-
|
|
81
|
-
- visibility changes
|
|
82
|
-
- weak intents
|
|
83
|
-
- covered-but-weak intents
|
|
84
|
-
- recommendation quadrant changes
|
|
85
|
-
- page performance changes
|
|
86
|
-
- citation/domain changes
|
|
87
|
-
- prior action outcomes when available
|
|
88
|
-
|
|
89
|
-
The summary should answer:
|
|
90
|
-
|
|
91
|
-
- What improved?
|
|
92
|
-
- What regressed?
|
|
93
|
-
- Which intents remain weak?
|
|
94
|
-
- Which existing pages are underperforming?
|
|
95
|
-
- Which pages or intents look healthy enough to avoid touching?
|
|
96
|
-
- Which prior actions should suppress repeats?
|
|
97
|
-
|
|
98
|
-
### 3. Build Common Run Context
|
|
99
|
-
|
|
100
|
-
Create one shared context object for all channel diagnoses.
|
|
101
|
-
|
|
102
|
-
It should include:
|
|
103
|
-
|
|
104
|
-
- tenant objective for this run
|
|
105
|
-
- relevant brand constraints
|
|
106
|
-
- strategy priorities from `STRATEGY.md`
|
|
107
|
-
- last-week performance summary
|
|
108
|
-
- recent action exclusion mask (derived from `signals.priorDecisions` — see below)
|
|
109
|
-
- candidate intent/page/domain slices
|
|
110
|
-
- evidence budget
|
|
111
|
-
- output schema
|
|
112
|
-
|
|
113
|
-
#### Building the exclusion mask
|
|
114
|
-
|
|
115
|
-
The authoritative source is the top-level `signals.priorDecisions[]` array — it holds every active decision (intent-anchored, url-anchored, AND sourceDomain-anchored, including domain-only third-party rejections that have no intent/page to attach to). Match candidates against this array.
|
|
116
|
-
|
|
117
|
-
`signals.intents[].priorDecisions` and `signals.pages[].priorDecisions` are a pre-grouped convenience mirror (the same decisions, attached to the intent/page they anchor on) — use them as a shortcut, but do not rely on them as the only source, since domain-only decisions appear only in the top-level array.
|
|
118
|
-
|
|
119
|
-
A prior decision is a match when its `match` object aligns with the candidate on all present fields:
|
|
120
|
-
|
|
121
|
-
```
|
|
122
|
-
match key = { intentId, assetType, operation, target }
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
For each candidate, look up matches in `signals.priorDecisions[]` by comparing:
|
|
126
|
-
|
|
127
|
-
- the candidate's resolved `intentId` against the intent the decision is attached to (via `signals.intents[].priorDecisions`), and
|
|
128
|
-
- the decision's `match` fields against the candidate: `assetType`, `operation`, and the `target` fields `url`, `queryCluster`, `sourceDomain`, or `suggestedSlug`.
|
|
129
|
-
|
|
130
|
-
Match on any non-null subset (a domain-level third-party decision matches a candidate that targets the same `sourceDomain`).
|
|
131
|
-
|
|
132
|
-
Apply the mask as follows:
|
|
133
|
-
|
|
134
|
-
- **`reasonClass: "durable_exclusion"` with `n ≥ 2`** — suppress the candidate entirely.
|
|
135
|
-
Do not pass it to any channel diagnosis.
|
|
136
|
-
Record in `rationale.md`: the intentId/target, `reasonClass`, `reasonTags`, the human `reason` text (if present), and `n` (number of times dismissed/rejected).
|
|
137
|
-
|
|
138
|
-
- **`reasonClass: "fixable_critique"` (any `n`)** — keep the candidate but pass the prior critique to the channel diagnosis as a constraint.
|
|
139
|
-
The diagnosis must address the critique (e.g. revise tone, adjust value proposition, change timing) rather than reproducing the previously rejected form.
|
|
140
|
-
Record in the channel rationale that the candidate was revised to address a prior critique, citing `reasonTags` and `reason`.
|
|
141
|
-
|
|
142
|
-
- **`reasonClass: "durable_exclusion"` with `n = 1`** — treat as a soft signal.
|
|
143
|
-
Pass the candidate with a note that it was dismissed once; the channel diagnosis may still include it if evidence is strong, but must acknowledge the prior dismissal in its rationale.
|
|
144
|
-
|
|
145
|
-
If `priorDecisions` is absent or empty for an intent, proceed normally.
|
|
146
|
-
|
|
147
|
-
This context is shared by all three channel diagnoses.
|
|
148
|
-
|
|
149
|
-
Channel diagnoses may receive channel-specific candidate slices, but they should share the same strategic baseline.
|
|
150
|
-
|
|
151
|
-
### 4. Run Three Channel Diagnoses
|
|
152
|
-
|
|
153
|
-
Apply these channel skills directly:
|
|
154
|
-
|
|
155
|
-
- `brand-owned-diagnosis`
|
|
156
|
-
- `geo-pages-diagnosis`
|
|
157
|
-
- `third-party-diagnosis`
|
|
158
|
-
- `third-party-execution-planning`
|
|
159
|
-
- `seo-opportunity-audit`
|
|
160
|
-
- `seo-technical-diagnosis`
|
|
161
|
-
- `seo-page-diagnosis`
|
|
162
|
-
- `seo-serp-opportunity-research`
|
|
163
|
-
- `seo-internal-link-opportunity`
|
|
164
|
-
- `seo-ecommerce-opportunity`
|
|
165
|
-
|
|
166
|
-
Each channel diagnosis returns one compact proposal set to the lead agent.
|
|
167
|
-
SEO diagnosis skills return supporting evidence and action candidates under
|
|
168
|
-
`agent/seo/{skillName}/{runId}/`. Use those artifacts to support final GEO
|
|
169
|
-
actions, but the lead agent still owns final action selection and submission.
|
|
170
|
-
Persist every channel diagnosis before final judging:
|
|
171
|
-
|
|
172
|
-
- `agent/runs/{runId}/subagents/brand_owned.json`
|
|
173
|
-
- `agent/runs/{runId}/subagents/brand_owned.rationale.md`
|
|
174
|
-
- `agent/runs/{runId}/subagents/geo_pages.json`
|
|
175
|
-
- `agent/runs/{runId}/subagents/geo_pages.rationale.md`
|
|
176
|
-
- `agent/runs/{runId}/subagents/third_party.json`
|
|
177
|
-
- `agent/runs/{runId}/subagents/third_party.rationale.md`
|
|
178
|
-
|
|
179
|
-
The JSON files are the mergeable source of truth. The rationale files should be compact decision logs: accepted, rejected, uncertain, missing evidence, and cross-channel concerns. Do not paste raw transcripts.
|
|
180
|
-
|
|
181
|
-
Expected channel diagnosis output:
|
|
182
|
-
|
|
183
|
-
```json
|
|
184
|
-
{
|
|
185
|
-
"summary": "Short channel-level diagnosis.",
|
|
186
|
-
"proposals": [
|
|
187
|
-
{
|
|
188
|
-
"intentId": "intent_123",
|
|
189
|
-
"candidateType": "page_exists_low_visibility",
|
|
190
|
-
"target": {
|
|
191
|
-
"pageId": "page_123",
|
|
192
|
-
"url": "https://example.com/page"
|
|
193
|
-
},
|
|
194
|
-
"rootCauses": [
|
|
195
|
-
{
|
|
196
|
-
"bucket": "proof_gap",
|
|
197
|
-
"confidence": 0.72,
|
|
198
|
-
"evidence": ["Evidence summary"]
|
|
199
|
-
}
|
|
200
|
-
],
|
|
201
|
-
"actionFamily": "update_existing_page",
|
|
202
|
-
"operations": ["Add proof section"],
|
|
203
|
-
"priority": "high",
|
|
204
|
-
"confidence": "medium",
|
|
205
|
-
"evidence": [
|
|
206
|
-
{
|
|
207
|
-
"type": "signal",
|
|
208
|
-
"ref": "geo_recommendation_quadrants:intent_123",
|
|
209
|
-
"summary": "mentioned_not_recommended_rate is high"
|
|
210
|
-
}
|
|
211
|
-
],
|
|
212
|
-
"whyNow": "Why this should be considered this week.",
|
|
213
|
-
"risks": ["Possible risk or uncertainty"]
|
|
214
|
-
}
|
|
215
|
-
],
|
|
216
|
-
"rejected": [
|
|
217
|
-
{
|
|
218
|
-
"ref": "intent_456",
|
|
219
|
-
"reason": "Suppressed by recent action mask"
|
|
220
|
-
}
|
|
221
|
-
],
|
|
222
|
-
"noActionRationale": "Optional. Use when proposals is empty."
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
Channel diagnoses must not include `workspaceId`, `runId`, `channel`, final action id, final `assetType`, or final URL.
|
|
227
|
-
The orchestrator derives final action ids, channel-to-asset mapping, and executable action shape.
|
|
228
|
-
|
|
229
|
-
For selected `third_party` proposals, apply `third-party-execution-planning`
|
|
230
|
-
before final action writing. Diagnosis decides whether an external opportunity
|
|
231
|
-
is worth considering; execution planning turns the selected opportunity into a
|
|
232
|
-
human-executable plan for social surfaces and non-social surfaces such as
|
|
233
|
-
directories, review sites, marketplaces, partner pages, open listicles,
|
|
234
|
-
editorial inclusion pages, and owned third-party profiles.
|
|
235
|
-
|
|
236
|
-
### 5. Judge Channel Outputs
|
|
237
|
-
|
|
238
|
-
The orchestrator reads the three persisted channel JSON files and rationale files, then reviews all proposals.
|
|
239
|
-
|
|
240
|
-
It should ask:
|
|
241
|
-
|
|
242
|
-
- Does this proposal match tenant strategy?
|
|
243
|
-
- Is the evidence strong enough?
|
|
244
|
-
- Is it redundant with another channel's proposal?
|
|
245
|
-
- Is it suppressed by recent actions? (see priorDecision check below)
|
|
246
|
-
- Is the action executable by the current product surface?
|
|
247
|
-
- Is it more important than competing proposals this week?
|
|
248
|
-
- For generated-page updates, is the page old enough to evaluate, indexed, or backed by a concrete non-performance defect?
|
|
249
|
-
|
|
250
|
-
#### priorDecision check (per proposal)
|
|
251
|
-
|
|
252
|
-
For each proposal returned by a channel diagnosis, derive its match key:
|
|
253
|
-
|
|
254
|
-
```
|
|
255
|
-
{ intentId, assetType, operation, target: { url?, queryCluster?, sourceDomain?, suggestedSlug? } }
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
Look up matching entries in the authoritative top-level `signals.priorDecisions[]` array. A decision matches when its `match` object aligns with the proposal on all present fields — `assetType`, `operation`, and the `target` fields `url`, `queryCluster`, `sourceDomain`, or `suggestedSlug` (a domain-only third-party decision matches a proposal targeting the same `sourceDomain`), plus the `intentId` the decision is attached to (via `signals.intents[].priorDecisions`). The `signals.intents[].priorDecisions` and `signals.pages[].priorDecisions` attachments are a convenience shortcut for intent- and url-anchored proposals; the top-level array is the source of truth and the only place domain-only decisions appear.
|
|
259
|
-
|
|
260
|
-
Apply the following rules and record the outcome in `rationale.md`:
|
|
261
|
-
|
|
262
|
-
1. **Suppress** — if any matching prior decision has `reasonClass: "durable_exclusion"` and `n ≥ 2`:
|
|
263
|
-
reject the proposal; do not emit it as a final action.
|
|
264
|
-
In `rationale.md` write: `SUPPRESSED — durable exclusion: <reasonTags> (n=<n>). Prior reason: "<reason>".`
|
|
265
|
-
|
|
266
|
-
2. **Revise** — if any matching prior decision has `reasonClass: "fixable_critique"`:
|
|
267
|
-
keep the proposal but require that the final action explicitly addresses the critique.
|
|
268
|
-
Update `changeBrief` and `objective` to reflect the correction.
|
|
269
|
-
In `rationale.md` write: `REVISED — fixable critique: <reasonTags>. Addressed by: <description of correction>.`
|
|
270
|
-
|
|
271
|
-
3. **Soft flag** — if any matching prior decision has `reasonClass: "durable_exclusion"` and `n = 1`:
|
|
272
|
-
the proposal may proceed, but record: `SOFT FLAG — dismissed once: <reasonTags>. Proceeding because <reason for override>.`
|
|
273
|
-
|
|
274
|
-
4. **No prior decisions** — proceed normally; no rationale entry required for this check.
|
|
275
|
-
|
|
276
|
-
Fresh generated-page guard:
|
|
277
|
-
|
|
278
|
-
- If a generated page was published less than 7 days ago, do not emit a `geo_page` update based only on low visibility, zero traffic, zero GSC impressions, or zero AI citations.
|
|
279
|
-
- For fresh generated pages, accept an update only when the proposal identifies a concrete non-performance defect: wrong intent, broken route, crawl/indexation blocker, duplicate/cannibalization, missing brand/entity clarity, or factual/product-claim defect.
|
|
280
|
-
- If a generated page is not indexed after 7 days, keep the issue in analysis and flag it as indexation/technical evidence. Prefer a technical follow-up or monitor note over a content update unless the content itself is also defective.
|
|
281
|
-
- When rejecting a premature generated-page update, record the page id/URL and the next reasonable evaluation window in `rationale.md` or the channel rationale.
|
|
282
|
-
|
|
283
|
-
The orchestrator may:
|
|
284
|
-
|
|
285
|
-
- accept
|
|
286
|
-
- merge
|
|
287
|
-
- downgrade
|
|
288
|
-
- reject
|
|
289
|
-
- move to `rationale.md` only
|
|
290
|
-
|
|
291
|
-
### 6. Resolve Cross-Channel Conflicts
|
|
292
|
-
|
|
293
|
-
Common conflicts:
|
|
294
|
-
|
|
295
|
-
- `brand_owned` proposes refreshing a page while `geo_pages` proposes creating a new page for the same intent.
|
|
296
|
-
- `geo_pages` proposes iteration while `third_party` argues authority is the bottleneck.
|
|
297
|
-
- `third_party` proposes outreach but owned page coverage is clearly weak.
|
|
298
|
-
|
|
299
|
-
Default resolution:
|
|
300
|
-
|
|
301
|
-
1. If an existing page clearly owns the intent and content gaps are fixable, prefer updating it.
|
|
302
|
-
2. If no page exists, prefer GEO page generation unless tenant strategy says customer-site page first.
|
|
303
|
-
3. If page content is strong but external validation is the bottleneck, keep third-party as a candidate.
|
|
304
|
-
4. If evidence is weak, do not emit an action; record the uncertainty.
|
|
305
|
-
|
|
306
|
-
### 7. Build Final Action List
|
|
307
|
-
|
|
308
|
-
Select at most 20 final actions.
|
|
309
|
-
|
|
310
|
-
Prefer:
|
|
311
|
-
|
|
312
|
-
1. high-confidence fixes for existing important pages
|
|
313
|
-
2. high-confidence generated GEO page iteration
|
|
314
|
-
3. high-confidence net-new page generation
|
|
315
|
-
4. third-party actions only when actionability is clear
|
|
316
|
-
|
|
317
|
-
Low-confidence findings go to `rationale.md`.
|
|
318
|
-
|
|
319
|
-
Guardrail:
|
|
320
|
-
|
|
321
|
-
- `brand_owned` is only for customer-owned discovered pages.
|
|
322
|
-
- Do not send Anymorph-generated, recommended, preview-only, or unpublished GEO pages to Fix.
|
|
323
|
-
- Existing generated page work must stay `assetType: "geo_page"` even when the proposed operation is a technical fix or content iteration.
|
|
324
|
-
- Do not emit a `geo_page` update for a generated page published less than 7 days ago unless there is a concrete non-performance defect.
|
|
325
|
-
- Do not treat missing performance data on a fresh generated page as proof of weakness.
|
|
326
|
-
- Do flag a generated page that is not indexed after 7 days, but keep indexation analysis separate from content iteration unless both are supported by evidence.
|
|
327
|
-
|
|
328
|
-
### 8. Write Artifacts
|
|
329
|
-
|
|
330
|
-
Write:
|
|
331
|
-
|
|
332
|
-
- `agent/runs/{runId}/subagents/brand_owned.json`
|
|
333
|
-
- `agent/runs/{runId}/subagents/brand_owned.rationale.md`
|
|
334
|
-
- `agent/runs/{runId}/subagents/geo_pages.json`
|
|
335
|
-
- `agent/runs/{runId}/subagents/geo_pages.rationale.md`
|
|
336
|
-
- `agent/runs/{runId}/subagents/third_party.json`
|
|
337
|
-
- `agent/runs/{runId}/subagents/third_party.rationale.md`
|
|
338
|
-
- `agent/runs/{runId}/actions.json`
|
|
339
|
-
- `agent/runs/{runId}/rationale.md`
|
|
340
|
-
- `agent/runs/{runId}/status.json`
|
|
341
|
-
|
|
342
|
-
Optionally archive compact observations in:
|
|
343
|
-
|
|
344
|
-
- `agent/archive/{time5}-{slug}.json`
|
|
345
|
-
|
|
346
|
-
Update stable memory only when the run changes durable tenant strategy.
|
|
347
|
-
On bootstrap runs, also update stable memory when `agent/STRATEGY.md` or
|
|
348
|
-
`agent/LEARNINGS.md` is missing, blank, or still scaffold-only.
|
|
349
|
-
|
|
350
|
-
`agent/BRAND.md` is backend-managed. It is regenerated from the workspace
|
|
351
|
-
brand record whenever the `brandHash` frontmatter drifts, and the agent
|
|
352
|
-
must not edit it. If a brand fact looks wrong, raise it in
|
|
353
|
-
`rationale.md` rather than editing the file.
|
|
354
|
-
|
|
355
|
-
## Final Action Contract
|
|
356
|
-
|
|
357
|
-
Write `agent/runs/{runId}/actions.json` to the exact production contract.
|
|
358
|
-
The Zod source of truth is `apps/shared-contracts/src/index.cjs`; the
|
|
359
|
-
asset-type target business rules are in
|
|
360
|
-
`apps/backend/src/modules/geo-strategy/geo-strategy-action.schema.ts`.
|
|
361
|
-
|
|
362
|
-
The artifact root is strict. It must contain only:
|
|
363
|
-
|
|
364
|
-
- `schemaVersion: 1`
|
|
365
|
-
- `runId`
|
|
366
|
-
- `policy`, matching `agent/runs/{runId}/policy.json`
|
|
367
|
-
- `actions`, with at most 20 items
|
|
368
|
-
|
|
369
|
-
Do not add root-level helper fields such as `artifactPaths`. `artifactPaths`
|
|
370
|
-
belongs only to submit transport, never to `actions.json`.
|
|
371
|
-
|
|
372
|
-
Each final action is strict. It must contain only:
|
|
373
|
-
|
|
374
|
-
- `id`
|
|
375
|
-
- `operation`
|
|
376
|
-
- `surface`
|
|
377
|
-
- `assetType`
|
|
378
|
-
- `intentId`
|
|
379
|
-
- `proposedIntent`, only when `intentId` is null
|
|
380
|
-
- `target`
|
|
381
|
-
- `objective`
|
|
382
|
-
- `changeBrief`
|
|
383
|
-
- `reason`
|
|
384
|
-
- `expectedOutcome`
|
|
385
|
-
- `evidence`
|
|
386
|
-
- `priority`
|
|
387
|
-
- `confidence`
|
|
388
|
-
|
|
389
|
-
Each `evidence[]` item is strict:
|
|
390
|
-
|
|
391
|
-
- `type`: one of `signal`, `workspace`, `source`, `research`
|
|
392
|
-
- `ref`: non-empty string
|
|
393
|
-
- `summary`: non-empty string
|
|
394
|
-
|
|
395
|
-
`target` is strict. Allowed target keys are only:
|
|
396
|
-
|
|
397
|
-
- `pageId`
|
|
398
|
-
- `url`
|
|
399
|
-
- `title`
|
|
400
|
-
- `description`
|
|
401
|
-
- `queryCluster`
|
|
402
|
-
- `sourceDomain`
|
|
403
|
-
- `suggestedSlug`
|
|
404
|
-
- `pageRole`
|
|
405
|
-
- `targetProductIds`
|
|
406
|
-
|
|
407
|
-
Never use `target.domain`. For external domains, use `target.sourceDomain`.
|
|
408
|
-
|
|
409
|
-
Additional action rules:
|
|
410
|
-
|
|
411
|
-
- `brand_owned` uses `operation: "update"` and `surface: "on_page"`.
|
|
412
|
-
- `brand_owned` target must include `pageId` or `url`; do not include `pageRole`, `suggestedSlug`, `sourceDomain`, or `targetProductIds`.
|
|
413
|
-
- `geo_page` uses `surface: "on_page"`.
|
|
414
|
-
- `third_party` uses `surface: "off_page"`.
|
|
415
|
-
- If `intentId` is a string, omit `proposedIntent`.
|
|
416
|
-
- If `intentId` is null, include `proposedIntent.name` and `proposedIntent.reason`.
|
|
417
|
-
- `geo_page` create actions must include a root-relative `target.suggestedSlug` or `target.url`, plus `target.title`.
|
|
418
|
-
- `geo_page` create target must not include `pageId` or `sourceDomain`.
|
|
419
|
-
- `geo_page` update target must include `pageId` or `url`; do not include `pageRole`, `suggestedSlug`, `sourceDomain`, or `targetProductIds`.
|
|
420
|
-
- For commerce `geo_page` create actions, use `target.targetProductIds` only from product evidence in `products.json`, `intent_products.json`, or `get_intent_products`.
|
|
421
|
-
- Third-party `changeBrief` must name the publish surface, content format, content angle, and concrete execution steps.
|
|
422
|
-
- Third-party target must include `sourceDomain` or absolute http(s) `url`; do not include `pageId`, `pageRole`, `suggestedSlug`, or `targetProductIds`.
|
|
423
|
-
- Third-party `target.url` should be the exact execution surface when known: social thread/channel/profile, directory listing or submission page, review profile/category page, marketplace or partner page, open listicle/editorial page, or owned third-party profile.
|
|
424
|
-
- Third-party `operation` should be `create` for new external presence, inclusion requests, review collection motions, or owned-channel content; use `update` for existing listing/profile refreshes or factual corrections.
|
|
425
|
-
- Third-party `expectedOutcome` should name one observable result: listing/profile update, submission acknowledgement, review motion launched, editorial acknowledgement/update, creator mention, indexed post, or citation movement.
|
|
426
|
-
- When a `third_party` action uses `third-party-execution-planning`, derive final fields from the work order:
|
|
427
|
-
- `target.url` from the most actionable `surfaces[].url`.
|
|
428
|
-
- `target.sourceDomain` from that surface URL's domain.
|
|
429
|
-
- `operation` from `executionType` and the decision matrix.
|
|
430
|
-
- `changeBrief` from `executionType`, `whyThisSurface`, `requiredAssets`, `policyChecks`, `executionSteps`, and `fallback`.
|
|
431
|
-
- `expectedOutcome` from `completionSignal` plus `impactSignal`.
|
|
432
|
-
|
|
433
|
-
## Guardrails
|
|
434
|
-
|
|
435
|
-
- Do not let a channel diagnosis proposal pass through automatically.
|
|
436
|
-
- Do not choose duplicate actions for the same intent unless they are clearly complementary.
|
|
437
|
-
- Do not invent final routes for create actions.
|
|
438
|
-
- Do not treat missing data as proof.
|
|
439
|
-
- Do not diagnose authority from low visibility alone.
|
|
440
|
-
- Do not update tenant memory with generic SEO/GEO advice.
|