feat(skill): scope narrative lens to first-party entities, gate on fetched positioning
The lens criterion is now explicit: an identifiable first party with a fetchable public pitch - companies, products, services. People NEVER qualify, even founders whose companies would (MrBeast the company can get the lens; Jimmy Donaldson the person cannot; "Garry Tan vs Sam Altman" gets N/A across the row). Ownerless topics (Bitcoin) fail the same test - a foundation or fan site is not an authoritative first party. Comparison-row verdicts are also artifact-gated to match the single-entity beat: a verdict requires positioning fetched THIS run; if item 6 couldn't run (no WebSearch), the cell is Unclear - the pitch is never supplied from memory.
This commit is contained in:
@@ -641,7 +641,7 @@ Topic A (the main topic, first in the vs-string) uses outer `--x-handle`, `--x-r
|
||||
|
||||
**Then do WebSearch supplements** for: `{TOPIC_A} vs {TOPIC_B} comparison {YEAR}` and `{TOPIC_A} vs {TOPIC_B} which is better` — these catch rivalry articles that per-entity passes might not surface.
|
||||
|
||||
**Fill the `Setting the narrative?` row using `RESOLVED_POSITIONING` + the community evidence.** Run Step 0.55 item 6 (first-party positioning) per entity - it gives you each entity's CURRENT stated pitch, fetched fresh, not from memory. Then judge: is the community conversation actually ABOUT what the entity pitches, or about something else (pricing, rivals, an incident, a ToS change)? Start the cell with **Yes / Partly / No / Unclear**, then name the topic the community is really on, anchored to a real item with its engagement (e.g. "No - pitches uptime, but the top thread is friendly-fraud, 323pt HN"). The mismatch is the signal: companies usually don't control their own conversation. Use **Unclear** when the evidence is thin or polluted with unrelated brand-name matches (e.g. someone's `.vercel.app` app, an exam "calc") - do NOT infer a verdict from vibes. Write N/A for entities with no public pitch (people, abstract concepts).
|
||||
**Fill the `Setting the narrative?` row using `RESOLVED_POSITIONING` + the community evidence.** Run Step 0.55 item 6 (first-party positioning) per entity - it gives you each entity's CURRENT stated pitch, fetched fresh, not from memory. Then judge: is the community conversation actually ABOUT what the entity pitches, or about something else (pricing, rivals, an incident, a ToS change)? Start the cell with **Yes / Partly / No / Unclear**, then name the topic the community is really on, anchored to a real item with its engagement (e.g. "No - pitches uptime, but the top thread is friendly-fraud, 323pt HN"). The mismatch is the signal: companies usually don't control their own conversation. Use **Unclear** when the evidence is thin or polluted with unrelated brand-name matches (e.g. someone's `.vercel.app` app, an exam "calc") - do NOT infer a verdict from vibes. Write N/A for entities with no public pitch: people (ALWAYS, even founders/CEOs whose companies would qualify - "Garry Tan vs Sam Altman" gets N/A across the row), events, abstract concepts, and ownerless topics (Bitcoin - a foundation or fan site is not an authoritative first party). And only write a verdict when positioning was actually FETCHED this run: if item 6 could not run (e.g. no WebSearch), write Unclear - never supply the pitch from memory.
|
||||
|
||||
**Skip the normal Step 1 below** - go directly to the comparison synthesis format (see "If QUERY_TYPE = COMPARISON" in the synthesis section).
|
||||
|
||||
@@ -750,7 +750,7 @@ Store as `RESOLVED_IG_CREATORS`.
|
||||
|
||||
Store as `RESOLVED_YT_QUERIES`.
|
||||
|
||||
**6. First-party positioning** - **MANDATORY when WebSearch is available, for company / product / service topics.** If the topic (or, in a vs-run, an entity) is a company, product, or service with a public presence, fetch its CURRENT stated positioning. Do **NOT** rely on memory - homepages and positioning go stale as companies rewrite copy and pivot, and a stale claim produces a false gap. Anchor on first-party sources: the homepage tagline, docs, pricing, or a "compare/why-us" page. Fold this into the per-entity passes above where you can (e.g. add `official site` to a query); otherwise run one focused search per entity (`{TOPIC} official site`, `{TOPIC} pricing`). Capture the one-line value prop and any explicit claims ("zero-config", "fastest", "open source"). Store as `RESOLVED_POSITIONING`. This is what the entity *pitches*; the engine's community data is what people *actually talk about*. Whether those two line up feeds the `Setting the narrative?` synthesis (the conversation is often on a different topic than the pitch - that mismatch is the signal). Skip (and omit `RESOLVED_POSITIONING`) for people, events, or abstract concepts - they make no comparable public claim.
|
||||
**6. First-party positioning** - **MANDATORY when WebSearch is available, for company / product / service topics.** If the topic (or, in a vs-run, an entity) is a company, product, or service with a public presence, fetch its CURRENT stated positioning. Do **NOT** rely on memory - homepages and positioning go stale as companies rewrite copy and pivot, and a stale claim produces a false gap. Anchor on first-party sources: the homepage tagline, docs, pricing, or a "compare/why-us" page. Fold this into the per-entity passes above where you can (e.g. add `official site` to a query); otherwise run one focused search per entity (`{TOPIC} official site`, `{TOPIC} pricing`). Capture the one-line value prop and any explicit claims ("zero-config", "fastest", "open source"). Store as `RESOLVED_POSITIONING`. This is what the entity *pitches*; the engine's community data is what people *actually talk about*. Whether those two line up feeds the `Setting the narrative?` synthesis (the conversation is often on a different topic than the pitch - that mismatch is the signal). Skip (and omit `RESOLVED_POSITIONING`) for people, events, abstract concepts, and ownerless topics - they make no comparable public claim. The test is an identifiable first party with a fetchable pitch, and people NEVER pass it - not even founders/creators whose companies would qualify. The lens can apply to MrBeast (a company) but never to Jimmy Donaldson (a person); a person-vs-person run ("Garry Tan vs Sam Altman") gets no positioning research at all. Ownerless topics fail the same test: Bitcoin has no authoritative first party, and a foundation or fan site does not count.
|
||||
|
||||
**Concrete examples:**
|
||||
|
||||
@@ -807,7 +807,7 @@ Resolved:
|
||||
- Positioning: "{one-line stated value prop}" (first-party)
|
||||
```
|
||||
|
||||
Only show lines for platforms where something was resolved. Skip empty lines. On the Reddit line, the trailing `(+ {category_id} peers)` annotation appears when Step 0.55 Section 2a added category-peer subs. Omit the annotation when the topic had no matching category. The `Positioning:` line appears for company / product / service topics (from Step 0.55 item 6); omit it for people, events, and abstract concepts. This display replaces the old "Parsed intent" block with something more useful.
|
||||
Only show lines for platforms where something was resolved. Skip empty lines. On the Reddit line, the trailing `(+ {category_id} peers)` annotation appears when Step 0.55 Section 2a added category-peer subs. Omit the annotation when the topic had no matching category. The `Positioning:` line appears for company / product / service topics (from Step 0.55 item 6); omit it for people, events, abstract concepts, and ownerless topics. This display replaces the old "Parsed intent" block with something more useful.
|
||||
|
||||
---
|
||||
|
||||
@@ -1305,7 +1305,7 @@ Voice contract LAWs 1, 3, 5 apply to comparisons unchanged (no `Sources:` block,
|
||||
| Best for | ... | ... | ... |
|
||||
| Install | ... | ... | ... |
|
||||
|
||||
(Engine emits this scaffold; fill the cells with 5-15 words each. If an axis does not apply to the topic class, write "N/A" or a topic-appropriate substitute rather than inventing data. For the `Setting the narrative?` row, judge whether each entity's community conversation is about what the entity itself pitches: start the cell with **Yes / Partly / No / Unclear**, then name the topic the community is ACTUALLY on, anchored to a real item with engagement, e.g. "No - pitches uptime, but the top thread is friendly-fraud (323pt HN)". The mismatch is the signal - companies usually don't control their own conversation. Use "Unclear" when evidence is thin or polluted with unrelated brand-name matches; write N/A for entities with no public pitch, like people or abstract concepts. Do NOT infer a verdict from vibes.)
|
||||
(Engine emits this scaffold; fill the cells with 5-15 words each. If an axis does not apply to the topic class, write "N/A" or a topic-appropriate substitute rather than inventing data. For the `Setting the narrative?` row, judge whether each entity's community conversation is about what the entity itself pitches: start the cell with **Yes / Partly / No / Unclear**, then name the topic the community is ACTUALLY on, anchored to a real item with engagement, e.g. "No - pitches uptime, but the top thread is friendly-fraud (323pt HN)". The mismatch is the signal - companies usually don't control their own conversation. Use "Unclear" when evidence is thin or polluted with unrelated brand-name matches; write N/A for entities with no public pitch - people (even famous founders), events, abstract concepts, and ownerless topics like Bitcoin. Verdicts require positioning fetched THIS run; if it wasn't fetched, write Unclear rather than pitching from memory. Do NOT infer a verdict from vibes.)
|
||||
|
||||
## The Bottom Line
|
||||
|
||||
@@ -1447,7 +1447,7 @@ At render time the `@handle`, `r/sub`, and publication-name placeholders become
|
||||
|
||||
Headlines should be specific and newsy ("BULLY dropped and it's dominating", "Europe is banning him one country at a time"), not generic ("Album release", "Tour updates").
|
||||
|
||||
**Narrative-check beat (company / product / service topics).** If the topic is a company, product, or service and you captured `RESOLVED_POSITIONING` in Step 0.55, work in ONE bold-lead-in paragraph on whether the entity is setting its own narrative - i.e. is the community actually talking about what it pitches, or about something else (pricing, rivals, an incident, a ToS change)? Anchor the verdict to the real top-discussed item with its engagement - e.g. `**Vercel is losing the narrative to its pricing** - it still sells "the AI Cloud" and zero-overhead speed, but the loudest community thread this month is about cost and a June 1 ToS change, not performance`. When the conversation DOES track the pitch, say so (that is the "Yes" case, equally worth stating). Keep it a normal newsy bold-lead-in paragraph with a specific headline (per the rule above), NOT a new `##` section (LAW 4 still holds). Skip it silently for people, events, and abstract concepts, or when the evidence is too thin or noise-polluted to tell - do not manufacture a verdict.
|
||||
**Narrative-check beat (company / product / service topics).** If the topic is a company, product, or service and you captured `RESOLVED_POSITIONING` in Step 0.55, work in ONE bold-lead-in paragraph on whether the entity is setting its own narrative - i.e. is the community actually talking about what it pitches, or about something else (pricing, rivals, an incident, a ToS change)? Anchor the verdict to the real top-discussed item with its engagement - e.g. `**Vercel is losing the narrative to its pricing** - it still sells "the AI Cloud" and zero-overhead speed, but the loudest community thread this month is about cost and a June 1 ToS change, not performance`. When the conversation DOES track the pitch, say so (that is the "Yes" case, equally worth stating). Keep it a normal newsy bold-lead-in paragraph with a specific headline (per the rule above), NOT a new `##` section (LAW 4 still holds). Skip it silently for people (always - the beat can cover MrBeast the company, never Jimmy Donaldson the person), events, abstract concepts, and ownerless topics (Bitcoin), or when the evidence is too thin or noise-polluted to tell - do not manufacture a verdict.
|
||||
|
||||
**THEN - Quality Nudge (if present in the output):**
|
||||
|
||||
|
||||
@@ -571,8 +571,12 @@ def _render_comparison_scaffold(topic: str) -> list[str]:
|
||||
"what the entity itself pitches: start the cell with Yes / Partly / No / Unclear, then name the topic "
|
||||
"the community is ACTUALLY on, anchored to a real item (e.g. \"No - pitches uptime, but the top thread "
|
||||
"is friendly-fraud (323pt HN)\"). Use Unclear when evidence is thin or polluted with unrelated "
|
||||
"brand-name matches; do NOT infer a verdict from vibes. Write N/A for entities with no public pitch "
|
||||
"(people, abstract concepts). This scaffold matches the April 9 launch-video exemplar shape."
|
||||
"brand-name matches; do NOT infer a verdict from vibes. Write N/A for entities with no public pitch: "
|
||||
"people (always, even famous founders - the lens applies to companies and products, never persons), "
|
||||
"events, abstract concepts, and ownerless topics with no authoritative first party (e.g. Bitcoin). "
|
||||
"Only fill a verdict when the entity's first-party positioning was actually fetched during this "
|
||||
"run's research; if it was not, write Unclear - never supply the pitch from memory. "
|
||||
"This scaffold matches the April 9 launch-video exemplar shape."
|
||||
)
|
||||
|
||||
return [
|
||||
|
||||
Reference in New Issue
Block a user