/03-gap
Translate the visibility baseline + brand context into a ranked list of content actions that should move the needle. Identifies absent queries, contested queries, and competitor-displacement opportunities. Outputs content_priorities.json validated against schema. Use after
> /plugin marketplace add ViryaZheng/recomby-geo > /plugin install recomby-geo@recomby-geo
How it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/03-gap
Context preview
What this command does when you run it.
Translate the visibility baseline + brand context into a ranked list of content actions that should move the needle. Identifies absent queries, contested queries, and competitor-displacement opportunities. Outputs content_priorities.json validated against schema. Use after
Command definition
03-gap.mddescription: Translate the visibility baseline + brand context into a ranked list of content actions that should move the needle. Identifies absent queries, contested queries, and competitor-displacement opportunities. Outputs content_priorities.json validated against schema. Use after 02-audit; consumed by 04-content-brief.
argument-hint: "<client-folder, e.g. clients/acme>"
03 · Gap & Opportunity — Prioritize What to Build
The decision skill. Takes raw baseline data + business context and returns: "these are the N content pieces, in this order, with this expected impact, because of this reason."
The framework: **CITE × CORE-EEAT** (borrowed from `aaron-he-zhu/seo-geo-claude-skills` taxonomy):
- **C**itability — can we be cited as a primary source?
- **I**ntent match — does our angle match the searcher's job-to-be-done?
- **T**rustworthiness — do we have E-E-A-T signals (experience, expertise,
authority, trust)?
- **E**xpansion — is this query a wedge into a larger query cluster?
---
Inputs
- `clients/<slug>/brand_context.json`
- `clients/<slug>/visibility_baseline.json`
Output
- `clients/<slug>/content_priorities.json` — validates against
`schemas/content_priorities.schema.json`.
---
Procedure
Step 1 — Build the candidate set
Every `target_query` from brand_context becomes a candidate. Augment with:
- Queries surfaced in `layer_2_market_reality.real_user_questions` that
weren't in `target_queries`.
- Queries from `layer_3_value_gaps[*].opportunity` if phrased as a question.
Step 2 — Score each candidate (CITE × CORE-EEAT)
For each candidate, compute:
| Dimension | How to score | |-----------|--------------| | **Citability** | Does brand_context have first-party data, expert POV, or unique methodology that can be cited? +1 to +3. | | **Intent match** | Does the brand's product directly serve the JTBD behind this query? +1 to +3. | | **Trustworthiness** | Does the brand have E-E-A-T signals (author bios, credentials, citations elsewhere) for this topic? +0 to +3. | | **Expansion** | Does winning this query wedge open a cluster (5+ adjacent queries)? +0 to +3. | | **Current pain** | From baseline: absent (+3), contested (+2), winning-but-fragile (+1), winning-stable (0). | | **Difficulty (penalty)** | Strong incumbent (-2), generic category leader entrenched (-3), policy-restricted topic (-3). |
Sum → `expected_impact.score` (clamp to 1–10).
Step 3 — Determine `opportunity_type`
Pick the dominant move per query:
- `fill-absence` — query has mention_rate=0 AND brand has direct authority.
- `displace-competitor` — competitor wins this query but we have stronger
E-E-A-T or fresher data.
- `deepen-existing` — we partially win but content is thin or outdated.
- `freshness-update` — we own a piece but freshness < 6 months stale.
- `claim-comparison` — comparison query where neither we nor competitors
have a strong neutral comparison page.
- `first-party-data` — we have proprietary data nobody else has.
- `expert-pov` — our founder/team has unique POV; topic rewards expertise
over data.
Step 4 — Determine `recommended_format`
Map opportunity_type + intent to format:
| opportunity_type | intent | format | |------------------|--------|--------| | fill-absence | informational | `definition-page` or `deep-guide` | | fill-absence | comparison | `comparison-page` | | displace-competitor | comparison | `comparison-page` | | deepen-existing | informational | `deep-guide` | | first-party-data | * | `data-report` | | expert-pov | * | `expert-essay` | | freshness-update | * | (same as original format) | | claim-comparison | comparison | `comparison-page` |
Step 5 — Identify `required_assets`
For each priority, list the real-world inputs the human-in-loop step (04-content-brief) must collect from the founder/expert:
- `original-data` — proprietary numbers
- `expert-quote` — founder/team POV
- `customer-case` — real customer story (with permission)
- `screenshots` — UI / product / methodology evidence
- `pricing-table` — current pricing
- `methodology-detail` — how exactly the product/service works
A priority that requires none of these is suspicious — it means we're producing generic content that AI can already auto-generate, which won't get cited. Flag it and reduce its expected_impact score.
Hard Rule 2 requires at least one asset of type `original-data`, `expert-quote`, `customer-case`, or `methodology-detail` per priority. If a candidate genuinely has none: either sharpen the angle until one becomes possible, or DROP the candidate to `rejected_alternatives[]` with reason `no-defensible-asset`. Do not write it into `priorities[]` anyway — 04 would build a brief with no real slots and the gate degrades into paperwork.
Step 6 — Rank and trim
Sort by expected_impact.score DESC, then by difficulty ASC (low first). Take top 12–20 unless the user specifies otherwise.
For each rejected candidate that scored ≥6, list it under `rejected_alternatives[]` on its closest sibling priority, with reason — this gives 04-content-brief authors fallback ammunition.
Step 7 — Write & validate
Write `clients/<slug>/content_priorities.json`, then run BOTH gates. If either fails, fix the data (drop offenders to `rejected_alternatives[]`) and rewrite — do not hand off a file that failed a gate.
Gate 1 — Hard Rule 2 (defensible asset per priority):
python3 -c "
import json, sys
d = json.load(open('clients/<slug>/content_priorities.json'))
HARD = {'original-data', 'expert-quote', 'customer-case', 'methodology-detail'}
bad = [p.get('id') or p['query'] for p in d['priorities']
if not HARD & set(p.get('required_assets', []))]
if bad:
print(f'REFUSE: priorities without a defensible asset: {bad}'); sys.exit(1)
print('asset gate OK')"Gate 2 — schema:
python3 -c "import json,jsonschema; \
s=json.load(open('plugins/recomby-geo/schemas/content_priorities.schema.json')); \
d=json.load(open('clients/<slug>/contentRead more
description: Translate the visibility baseline + brand context into a ranked list of content actions that should move the needle. Identifies absent queries, contested queries, and competitor-displacement opportunities. Outputs content_priorities.json validated against schema. Use after 02-audit; consumed by 04-content-brief. argument-hint: "<client-folder, e.g. clients/acme>"
03 · Gap & Opportunity — Prioritize What to Build
The decision skill. Takes raw baseline data + business context and returns: "these are the N content pieces, in this order, with this expected impact, because of this reason."
The framework: **CITE × CORE-EEAT** (borrowed from `aaron-he-zhu/seo-geo-claude-skills` taxonomy):
- **C**itability — can we be cited as a primary source?
- **I**ntent match — does our angle match the searcher's job-to-be-done?
- **T**rustworthiness — do we have E-E-A-T signals (experience, expertise,
authority, trust)?
- **E**xpansion — is this query a wedge into a larger query cluster?
---
Inputs
- `clients/<slug>/brand_context.json`
- `clients/<slug>/visibility_baseline.json`
Output
- `clients/<slug>/content_priorities.json` — validates against
`schemas/content_priorities.schema.json`.
---
Procedure
Step 1 — Build the candidate set
Every `target_query` from brand_context becomes a candidate. Augment with:
- Queries surfaced in `layer_2_market_reality.real_user_questions` that
weren't in `target_queries`.
- Queries from `layer_3_value_gaps[*].opportunity` if phrased as a question.
Step 2 — Score each candidate (CITE × CORE-EEAT)
For each candidate, compute:
| Dimension | How to score | |-----------|--------------| | **Citability** | Does brand_context have first-party data, expert POV, or unique methodology that can be cited? +1 to +3. | | **Intent match** | Does the brand's product directly serve the JTBD behind this query? +1 to +3. | | **Trustworthiness** | Does the brand have E-E-A-T signals (author bios, credentials, citations elsewhere) for this topic? +0 to +3. | | **Expansion** | Does winning this query wedge open a cluster (5+ adjacent queries)? +0 to +3. | | **Current pain** | From baseline: absent (+3), contested (+2), winning-but-fragile (+1), winning-stable (0). | | **Difficulty (penalty)** | Strong incumbent (-2), generic category leader entrenched (-3), policy-restricted topic (-3). |
Sum → `expected_impact.score` (clamp to 1–10).
Step 3 — Determine `opportunity_type`
Pick the dominant move per query:
- `fill-absence` — query has mention_rate=0 AND brand has direct authority.
- `displace-competitor` — competitor wins this query but we have stronger
E-E-A-T or fresher data.
- `deepen-existing` — we partially win but content is thin or outdated.
- `freshness-update` — we own a piece but freshness < 6 months stale.
- `claim-comparison` — comparison query where neither we nor competitors
have a strong neutral comparison page.
- `first-party-data` — we have proprietary data nobody else has.
- `expert-pov` — our founder/team has unique POV; topic rewards expertise
over data.
Step 4 — Determine `recommended_format`
Map opportunity_type + intent to format:
| opportunity_type | intent | format | |------------------|--------|--------| | fill-absence | informational | `definition-page` or `deep-guide` | | fill-absence | comparison | `comparison-page` | | displace-competitor | comparison | `comparison-page` | | deepen-existing | informational | `deep-guide` | | first-party-data | * | `data-report` | | expert-pov | * | `expert-essay` | | freshness-update | * | (same as original format) | | claim-comparison | comparison | `comparison-page` |
Step 5 — Identify `required_assets`
For each priority, list the real-world inputs the human-in-loop step (04-content-brief) must collect from the founder/expert:
- `original-data` — proprietary numbers
- `expert-quote` — founder/team POV
- `customer-case` — real customer story (with permission)
- `screenshots` — UI / product / methodology evidence
- `pricing-table` — current pricing
- `methodology-detail` — how exactly the product/service works
A priority that requires none of these is suspicious — it means we're producing generic content that AI can already auto-generate, which won't get cited. Flag it and reduce its expected_impact score.
Hard Rule 2 requires at least one asset of type `original-data`, `expert-quote`, `customer-case`, or `methodology-detail` per priority. If a candidate genuinely has none: either sharpen the angle until one becomes possible, or DROP the candidate to `rejected_alternatives[]` with reason `no-defensible-asset`. Do not write it into `priorities[]` anyway — 04 would build a brief with no real slots and the gate degrades into paperwork.
Step 6 — Rank and trim
Sort by expected_impact.score DESC, then by difficulty ASC (low first). Take top 12–20 unless the user specifies otherwise.
For each rejected candidate that scored ≥6, list it under `rejected_alternatives[]` on its closest sibling priority, with reason — this gives 04-content-brief authors fallback ammunition.
Step 7 — Write & validate
Write `clients/<slug>/content_priorities.json`, then run BOTH gates. If either fails, fix the data (drop offenders to `rejected_alternatives[]`) and rewrite — do not hand off a file that failed a gate.
Gate 1 — Hard Rule 2 (defensible asset per priority):
python3 -c "
import json, sys
d = json.load(open('clients/<slug>/content_priorities.json'))
HARD = {'original-data', 'expert-quote', 'customer-case', 'methodology-detail'}
bad = [p.get('id') or p['query'] for p in d['priorities']
if not HARD & set(p.get('required_assets', []))]
if bad:
print(f'REFUSE: priorities without a defensible asset: {bad}'); sys.exit(1)
print('asset gate OK')"Gate 2 — schema:
python3 -c "import json,jsonschema; \
s=json.load(open('plugins/recomby-geo/schemas/content_priorities.schema.json')); \
d=json.load(open('clients/<slug>/contentGEO 领域 AI 员工开源方案 · Open-source GEO AI-employee solution (MIT). GEO Skills package + curated lists of agents and office CLIs that make up the AI-employee stack.
Other commands on recomby-geo.
- /01-intake
Build the GEO brand context for a client by ingesting provided materials (PDF/DOCX/PPTX/XLSX, URLs, raw notes) and conducting structured AI-perception + competitor + community research. Writes brand_context.json validated against schemas/brand_context.schema.json. Use when
Open command - /02-audit
Run a Claude-native visibility audit. For each query in brand_context.target_queries, ask Claude to answer the query as a real user would (using WebSearch + WebFetch), then record whether the client brand is mentioned, at what position, and which URLs were cited. Outputs
Open command - /04-content-brief
For one priority from content_priorities.json, generate a content brief with explicit slots for the human expert (founder/domain specialist) to fill with real cases, real data, and real opinions. This is the human-in-loop checkpoint — the moat that prevents the entire workflow
Open command - /05-production
Convert an expert-filled brief into a publishable draft. Applies Princeton KDD 2024 GEO techniques (statistics, quotations, citations, authoritative language) to maximize AI citation likelihood. Refuses to run on briefs that haven't been filled by the expert. Outputs
Open command - /06-distribution
For a published-ready draft, generate JSON-LD schema markup, internal linking suggestions, third-party distribution targets, and llms.txt block. Outputs distribution/<id>.json and distribution/<id>.publish-bundle.md. Use after 05-production; consumed by 07-reaudit (records
Open command - /07-reaudit
Re-run 02-audit, diff against the previous baseline, attribute movement to specific content/distribution actions. Outputs reaudit/round-N.json validated against attribution_diff.schema.json. This is the closing-of- loop artifact that proves (or disproves) what's actually
Open command

