anymorph 0.4.0 → 0.6.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 +79 -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,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`.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "GEO Generating Actions"
3
- short_description: "Generate final GEO strategy actions from channel diagnoses."
4
- default_prompt: "Use $geo-generating-actions to generate final GEO strategy actions for this workspace."
@@ -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.