Generate Newspaper Front Page
Produce a complete edition of The Gradient News & Observer for a requested time window: digest → markdown stories → image.
Parameters
/news-front-page [duration]
- duration (optional, default
24h): time window. Accepts 90m, 1h, 6h, 24h, 7d — anything news-digest --duration understands.
- env (optional, default
cloud): cloud → .env.cloud, local → .env.supabase. Production data lives in cloud; local is mostly empty unless the user is testing.
- skip-image (optional flag): only run steps 1–3, skip image rendering. Useful for iterating on copy.
If duration is missing, default to 24h and proceed — do not ask.
Output files
All under artifacts/. Use the digest's end timestamp formatted as YYYYMMDD-HHMMSSZ UTC for the stem, and past-<duration> as the suffix:
- Digest JSON:
artifacts/news-digest-<stem>-past-<duration>.json
- Front-page Markdown:
artifacts/gradient-news-observer-front-page-<stem>-past-<duration>.md
- Image PNG: the image script computes the path from the Markdown filename. The default renderer writes a regional composite under
artifacts/gradient-news-observer-regions/.
Steps
1. Generate the digest JSON
Run news-digest to pull events for the requested window into a structured JSON file. Use the entry-point script (registered in pyproject.toml):
uv run news-digest \
--env-file .env.cloud \
--duration <duration> \
--format json \
--output artifacts/news-digest-<stem>-past-<duration>.json
- The script connects read-only to Postgres, pulls all events in the window, dedupes recipient fan-out, and writes a JSON object with
global_stats, players, leaderboard_ranks, period_ranks, and warnings.
- For a 24-hour window the JSON is large (multi-MB). Don't
cat it. Use python3 -c or targeted Read calls.
2. Mine the digest for storylines
Read the JSON with small Python scripts (via Bash) to surface the angles. Useful queries:
- Top by activity / wealth / trade volume / sectors visited / combat wins / messages / sessions. Print rank tables with name + key counters for the top 15–25.
- Notable garrison events. For each player with
garrison_events, show the lines containing placed, collected, mode_changed, or disbanded (these are the real deployments — the rest are passers-through).
- Combat events. For each player with
combat_wins > 0 or destroyed_ships > 0, dump the combat log; look for back-to-back attacks on garrisons, defeated targets, multi-round skirmishes, and named opponents.
- All public chat. Dedupe broadcasts and direct messages by sender+text and sort by timestamp. Broadcasts are the strongest signal for story angles — pilots announcing intent (toll lanes, recruitment, accusations, public notices of kills).
- Ship purchases / sales / trade-ins. Five-or-fewer transactions per day, easy to enumerate.
- Corporation events.
corporation.created and corporation.disbanded counts; cross-reference with chat broadcasts that mention a corp name.
- Leaderboard top 10 for wealth, trading, territory, exploration. Sort by
rank ascending; show name + score.
You don't need TaskCreate for the mining — it's all read-only Python. Spawn a single Explore agent only if the JSON exceeds ~10MB and you want a focused report.
Pick 9 storylines from what you find. Mix should match the structure below: 7 grounded news beats + 2 dishy gossip angles. Lean toward conflict, status changes, public statements, and surprising aggregates.
3. Write the front-page Markdown
Write to artifacts/gradient-news-observer-front-page-<stem>-past-<duration>.md using the structure below verbatim. The image generator's prompt template assumes this exact section count and ordering.
Structure (10 sections, in order)
| # |
Type |
Length |
Section tag |
| 1 |
Straight news (lead) |
Two paragraphs |
Story-specific newspaper section — see tagging guide below |
| 2 |
Straight news |
Two paragraphs |
Story-specific newspaper section |
| 3 |
Straight news |
One short paragraph |
Story-specific newspaper section |
| 4 |
Straight news |
One short paragraph |
Story-specific newspaper section |
| 5 |
Straight news |
One short paragraph |
Story-specific newspaper section |
| 6 |
Straight news |
One short paragraph |
Story-specific newspaper section |
| 7 |
Straight news |
One short paragraph |
Story-specific newspaper section |
| 8 |
Gossip |
2–3 punchy sentences |
Oblique, catty, insider-y tag |
| 9 |
Gossip |
2–3 punchy sentences |
Oblique, catty, insider-y tag |
| 10 |
Market Update |
Two markdown tables + footnote |
Literally *Market Update* |
File template
# THE GRADIENT NEWS & OBSERVER
**Front-Page Edition — <window length> ending <YYYY-MM-DD HH:MM> UTC**
*"All the news the void allows."*
---
## 1. <Headline>
*<Story-specific section tag — e.g. Combat Wire, Trade & Lanes, Open Channel>*
<Lede paragraph — the strongest single fact or scene.>
<Second paragraph — context, quoted broadcasts, supporting numbers.>
---
## 2. <Headline>
*<Story-specific section tag>*
<Two paragraphs, same shape as story 1.>
---
## 3–7. <Headlines>
*<Story-specific section tag — different per story>*
<One short paragraph each — three to five sentences.>
---
## 8. <Headline>
*<Oblique, catty, insider-y tag — e.g. Salvage Talk>*
<Two or three short, punchy sentences. Vary the opening — see persona guide.>
---
## 9. <Headline>
*<Different oblique, catty, insider-y tag — e.g. The Mega-Port Set>*
<Two or three short, punchy sentences. Different opening from story 8.>
---
## 10. Market Update — <Window> Galactic Index
*Market Update*
| Measure | Value |
| --- | ---: |
| Gross trade volume | $... |
| ... |
| Top of the Boards | Pilot | Score |
| --- | --- | ---: |
| Wealth (lifetime) | ... | ... |
| ... |
---
*All sector numbers used appear in the period's open broadcasts; private direct messages and non-public sector references have been withheld.*
The closing italic footnote is required — the image template renders it as a footnote.
4. Render the front-page image
Unless skip-image was passed, run:
uv run news-front-page-image \
--front-page-md artifacts/gradient-news-observer-front-page-<stem>-past-<duration>.md
- Defaults to the
composited-regions renderer, which generates each story region separately and composites them — better text fidelity than the older one-shot renderer.
- Defaults to linotype light mode (black ink on white paper, character/ship names bolded). To render the original dark mode (cyan and chartreuse on dark paper, names highlighted in cyan), append
--dark-mode. Dark mode writes its output dir and composite filename with a -dark suffix to keep light and dark renders side by side.
- For comparison or quick iteration, append
--renderer one-shot to render the whole page in a single image-edit call.
- The script writes the final PNG, per-region prompt text, region PNGs, and metadata JSON. Composited-regions output lives under
artifacts/gradient-news-observer-regions/<stem>/; one-shot output lives under artifacts/gradient-news-observer-images/.
- Composited-regions takes several minutes (one image-edit call per region, run in sequence). One-shot finishes in 30–90 seconds. Stream stdout — both print final paths on success.
- If
OPENAI_API_KEY isn't in the environment, the script reads it from .env.
5. Report
Print the three artifact paths (digest JSON, front-page Markdown, image PNG) and the headline of story 1 so the user can open the right files.
Personas — write in these voices
Straight news — New York Times house style
- Lede paragraph carries the strongest factual beat. Date, place, actor, action.
- Past tense. Third person. Active voice.
- Quote public broadcasts with attribution: "…", the pilot declared on the open channel.
- Numbers spelled out under ten in body prose, numerals for stats and credits ($12,533,985).
- No hype, no exclamation points, no scare quotes. The tone is measured even when the facts are dramatic.
- One non-headline-grabbing fact per story is welcome — context that situates the day.
Gossip — dishy, varied openings
- 2–3 short, punchy sentences. No paragraphs.
- Vary the opening every time. "A little kestrel told this columnist…" is one option. Others:
- "Word from the trading docks…"
- "Overheard on the open channel at HH:MM UTC…"
- "Whispers in the wardroom suggest…"
- "One of your columnist's more reliable informants…"
- "Spotted at a mega-port this cycle…"
- "The rumor on the long-range channels…"
- First-person columnist voice ("your columnist," "this column") is fine and characterful.
- Wry, observational, never mean. Tease, don't accuse.
Section tags
Each story carries a single italic line directly under its headline that names the newspaper section it belongs to. These tags are part of the look — they make the page feel like an actual newspaper instead of a numbered list of stories. Write a fresh tag for every story; never re-use one.
Tags for straight news (stories 1–7)
Pick a section name that fits the story. Real-newspaper analogues are great when they're the obvious fit (Markets, Corporate Affairs, Cartography). Lean into the retro-space-game theme when there's room to be a little playful (Combat Wire, Trade & Lanes, Open Channel, Shipyard). Keep them short — two or three words, title-cased, no punctuation. A few worked examples for reference:
- A combat-heavy day with named pilots → Combat Wire (or Hostilities, Casualty Desk)
- A toll lane / mega-port / trade-route story → Trade & Lanes (or Public Affairs if it leans policy)
- An exchange of public broadcasts → Open Channel (or Frontier Justice if it's spicy)
- A new corporation, recruiting drive, member moves → Corporate Affairs
- An exploration / survey / probe record → Cartography (or The Survey Desk)
- Ship purchases, sales, trade-ins → Shipyard (or Off the Lot)
- Trade volume, port flow, leaderboard movement → Markets (or The Ledger)
- Chat broadcasts that read more like commentary than news → Frontier Justice (reserve Open Channel for the strongest broadcast-driven beat on the page)
If two stories would land on the same tag — adjacent or not — change one. Each tag must be unique on the page; visual rhythm and section variety depend on it. If a straight-news story and a gossip beat both spring from open-channel chatter, give the gossip the Open-Channel Confidential variant and keep the news as Open Channel.
Tags for gossip (stories 8–9)
Oblique. Catty. Insider-y. The reader should feel they've stumbled into the back room of a yacht club. Two or three words, title-cased; "The X Set" / "On the X Beat" / "X Talk" patterns work. Worked examples:
- Wreckage / destroyed ships / escape pods → Salvage Talk, From the Insurance Wing, Recovery Notes
- Mega-port socialites, traders, anyone seen at the dock → The Mega-Port Set, Concourse Whispers, Heard on the Promenade
- Corp politics, recruitment, defections → The Member Lounge, From the Boardroom Door
- A pilot's unguarded chatter on the open channel → Open-Channel Confidential
The tag should hint at the gist of the gossip without naming it outright. If your tag basically restates the headline, it's too literal — make it more sideways.
Tag for the market box (story 10)
Always literally *Market Update*. No variants. The image template expects this string.
Privacy and content rules — non-negotiable
These constraints flow into the image prompt verbatim. Violating them in the markdown means a wrong front page.
- Direct messages are private. Never quote, paraphrase, or imply contents of any DM. Players cannot see other players' DMs in-game; the newspaper can't either. Broadcasts are public — quote them freely.
- Sector numbers are restricted. Use a sector number only if (a) it appears in a public broadcast inside the window, OR (b) it is a Federation Space sector (the meta-defined fedspace list, 200 sectors by default). When in doubt, omit the number and use a generic phrase like "the borderlands beyond Federation Space" or "a contested sector outside Fed."
- No invented facts. Headlines, ledes, quotes, percentages, ship classes, credit amounts, sector numbers — every readable claim must be grounded in the digest. If a stat is interesting but unverifiable, leave it out.
- No fabricated player names. Only use names that appear in
players[].name or in the leaderboard ranks of the digest.
- No invite codes unless they were broadcast publicly.
- Aggregate counts are always public. Total sectors visited, total trade volume, ships destroyed, corporations created — all fair game for ledes and the market box.
Story-mining heuristics
Strong story signals, in roughly decreasing order of front-page value:
- A public broadcast that announces intent — toll lanes, recruitment, accusations, "public notice" kill claims, declarations of war. These almost always lead the page.
- An exchange of broadcasts between two pilots — accusation + denial, ultimatum + response. Story 2 territory.
- A new corporation with a public manifesto broadcast in the window.
- A combat day above baseline — count
ship.destroyed and combat.ended. Fourteen ship destructions is a lot; one is a footnote.
- A leaderboard sweep — same name in #1 across multiple boards, or three sister ships in the top three of one board.
- A run of ship purchases with a clear narrative (e.g., a pilot who lost a hull and re-bought).
- An autonomous-fleet survey record — "468 sectors in 24 hours" is a clean explorer beat.
- Garrison drama in or near Fed Space. Garrisons placed close to fedspace, especially if destroyed within hours, are reliable conflict copy.
Weak signals — generally skip:
- Quiet trading sessions with no anchoring narrative.
- Movement totals without a name attached.
- Errors, session counts, or other infra signals.
Things this skill does NOT do
- Does not edit code, deploy, or run migrations. Read-only digest + write artifacts under
artifacts/.
- Does not commit anything. The user reviews the markdown and image first.
- Does not push the image anywhere. It writes to disk; sharing is the user's call.
- Does not invent storylines to pad to 9. If the window is genuinely quiet (e.g., an off-hour 1h slice), say so plainly in the lede and reduce gossip items to one. Better a thin honest page than a fabricated one.
1---2name: news-front-page3description: Generate a Gradient News & Observer newspaper front page for a time window. Pulls game events into a structured digest, writes ten illustrated story ledes (7 straight news + 2 gossip + 1 market box) into a markdown file, then renders a 2160x3840 newspaper front-page PNG. Usage `/news-front-page [duration]` (default `24h`; e.g. `1h`, `6h`, `7d`).4---56# Generate Newspaper Front Page78Produce a complete edition of *The Gradient News & Observer* for a requested time window: digest → markdown stories → image.910## Parameters1112`/news-front-page [duration]`1314- **duration** (optional, default `24h`): time window. Accepts `90m`, `1h`, `6h`, `24h`, `7d` — anything `news-digest --duration` understands.15- **env** (optional, default `cloud`): `cloud` → `.env.cloud`, `local` → `.env.supabase`. Production data lives in cloud; local is mostly empty unless the user is testing.16- **skip-image** (optional flag): only run steps 1–3, skip image rendering. Useful for iterating on copy.1718If duration is missing, default to `24h` and proceed — do not ask.1920## Output files2122All under `artifacts/`. Use the digest's `end` timestamp formatted as `YYYYMMDD-HHMMSSZ` UTC for the stem, and `past-<duration>` as the suffix:2324- Digest JSON: `artifacts/news-digest-<stem>-past-<duration>.json`25- Front-page Markdown: `artifacts/gradient-news-observer-front-page-<stem>-past-<duration>.md`26- Image PNG: the image script computes the path from the Markdown filename. The default renderer writes a regional composite under `artifacts/gradient-news-observer-regions/`.2728## Steps2930### 1. Generate the digest JSON3132Run `news-digest` to pull events for the requested window into a structured JSON file. Use the entry-point script (registered in `pyproject.toml`):3334```bash35uv run news-digest \36 --env-file .env.cloud \37 --duration <duration> \38 --format json \39 --output artifacts/news-digest-<stem>-past-<duration>.json40```4142- The script connects read-only to Postgres, pulls all events in the window, dedupes recipient fan-out, and writes a JSON object with `global_stats`, `players`, `leaderboard_ranks`, `period_ranks`, and `warnings`.43- For a 24-hour window the JSON is large (multi-MB). Don't `cat` it. Use `python3 -c` or targeted `Read` calls.4445### 2. Mine the digest for storylines4647Read the JSON with small Python scripts (via `Bash`) to surface the angles. Useful queries:4849- **Top by activity / wealth / trade volume / sectors visited / combat wins / messages / sessions.** Print rank tables with name + key counters for the top 15–25.50- **Notable garrison events.** For each player with `garrison_events`, show the lines containing `placed`, `collected`, `mode_changed`, or `disbanded` (these are the real deployments — the rest are passers-through).51- **Combat events.** For each player with `combat_wins > 0` or `destroyed_ships > 0`, dump the combat log; look for back-to-back attacks on garrisons, defeated targets, multi-round skirmishes, and named opponents.52- **All public chat.** Dedupe broadcasts and direct messages by sender+text and sort by timestamp. Broadcasts are the strongest signal for story angles — pilots announcing intent (toll lanes, recruitment, accusations, public notices of kills).53- **Ship purchases / sales / trade-ins.** Five-or-fewer transactions per day, easy to enumerate.54- **Corporation events.** `corporation.created` and `corporation.disbanded` counts; cross-reference with chat broadcasts that mention a corp name.55- **Leaderboard top 10** for wealth, trading, territory, exploration. Sort by `rank` ascending; show name + score.5657You don't need TaskCreate for the mining — it's all read-only Python. Spawn a single `Explore` agent only if the JSON exceeds ~10MB and you want a focused report.5859Pick **9 storylines** from what you find. Mix should match the structure below: 7 grounded news beats + 2 dishy gossip angles. Lean toward conflict, status changes, public statements, and surprising aggregates.6061### 3. Write the front-page Markdown6263Write to `artifacts/gradient-news-observer-front-page-<stem>-past-<duration>.md` using the structure below verbatim. The image generator's prompt template assumes this exact section count and ordering.6465#### Structure (10 sections, in order)6667| # | Type | Length | Section tag |68|---|---|---|---|69| 1 | Straight news (lead) | Two paragraphs | Story-specific newspaper section — see tagging guide below |70| 2 | Straight news | Two paragraphs | Story-specific newspaper section |71| 3 | Straight news | One short paragraph | Story-specific newspaper section |72| 4 | Straight news | One short paragraph | Story-specific newspaper section |73| 5 | Straight news | One short paragraph | Story-specific newspaper section |74| 6 | Straight news | One short paragraph | Story-specific newspaper section |75| 7 | Straight news | One short paragraph | Story-specific newspaper section |76| 8 | Gossip | 2–3 punchy sentences | Oblique, catty, insider-y tag |77| 9 | Gossip | 2–3 punchy sentences | Oblique, catty, insider-y tag |78| 10 | Market Update | Two markdown tables + footnote | Literally `*Market Update*` |7980#### File template8182```markdown83# THE GRADIENT NEWS & OBSERVER8485**Front-Page Edition — <window length> ending <YYYY-MM-DD HH:MM> UTC**8687*"All the news the void allows."*8889---9091## 1. <Headline>9293*<Story-specific section tag — e.g. Combat Wire, Trade & Lanes, Open Channel>*9495<Lede paragraph — the strongest single fact or scene.>9697<Second paragraph — context, quoted broadcasts, supporting numbers.>9899---100101## 2. <Headline>102103*<Story-specific section tag>*104105<Two paragraphs, same shape as story 1.>106107---108109## 3–7. <Headlines>110111*<Story-specific section tag — different per story>*112113<One short paragraph each — three to five sentences.>114115---116117## 8. <Headline>118119*<Oblique, catty, insider-y tag — e.g. Salvage Talk>*120121<Two or three short, punchy sentences. Vary the opening — see persona guide.>122123---124125## 9. <Headline>126127*<Different oblique, catty, insider-y tag — e.g. The Mega-Port Set>*128129<Two or three short, punchy sentences. Different opening from story 8.>130131---132133## 10. Market Update — <Window> Galactic Index134135*Market Update*136137| Measure | Value |138| --- | ---: |139| Gross trade volume | $... |140| ... |141142| Top of the Boards | Pilot | Score |143| --- | --- | ---: |144| Wealth (lifetime) | ... | ... |145| ... |146147---148149*All sector numbers used appear in the period's open broadcasts; private direct messages and non-public sector references have been withheld.*150```151152The closing italic footnote is required — the image template renders it as a footnote.153154### 4. Render the front-page image155156Unless `skip-image` was passed, run:157158```bash159uv run news-front-page-image \160 --front-page-md artifacts/gradient-news-observer-front-page-<stem>-past-<duration>.md161```162163- Defaults to the `composited-regions` renderer, which generates each story region separately and composites them — better text fidelity than the older `one-shot` renderer.164- Defaults to linotype light mode (black ink on white paper, character/ship names bolded). To render the original dark mode (cyan and chartreuse on dark paper, names highlighted in cyan), append `--dark-mode`. Dark mode writes its output dir and composite filename with a `-dark` suffix to keep light and dark renders side by side.165- For comparison or quick iteration, append `--renderer one-shot` to render the whole page in a single image-edit call.166- The script writes the final PNG, per-region prompt text, region PNGs, and metadata JSON. Composited-regions output lives under `artifacts/gradient-news-observer-regions/<stem>/`; one-shot output lives under `artifacts/gradient-news-observer-images/`.167- Composited-regions takes several minutes (one image-edit call per region, run in sequence). One-shot finishes in 30–90 seconds. Stream stdout — both print final paths on success.168- If `OPENAI_API_KEY` isn't in the environment, the script reads it from `.env`.169170### 5. Report171172Print the three artifact paths (digest JSON, front-page Markdown, image PNG) and the headline of story 1 so the user can open the right files.173174## Personas — write in these voices175176### Straight news — *New York Times* house style177178- Lede paragraph carries the strongest factual beat. Date, place, actor, action.179- Past tense. Third person. Active voice.180- Quote public broadcasts with attribution: *"…", the pilot declared on the open channel.*181- Numbers spelled out under ten in body prose, numerals for stats and credits ($12,533,985).182- No hype, no exclamation points, no scare quotes. The tone is measured even when the facts are dramatic.183- One non-headline-grabbing fact per story is welcome — context that situates the day.184185### Gossip — dishy, varied openings186187- 2–3 short, punchy sentences. No paragraphs.188- **Vary the opening every time.** "A little kestrel told this columnist…" is one option. Others:189 - "Word from the trading docks…"190 - "Overheard on the open channel at HH:MM UTC…"191 - "Whispers in the wardroom suggest…"192 - "One of your columnist's more reliable informants…"193 - "Spotted at a mega-port this cycle…"194 - "The rumor on the long-range channels…"195- First-person columnist voice ("your columnist," "this column") is fine and characterful.196- Wry, observational, never mean. Tease, don't accuse.197198## Section tags199200Each story carries a single italic line directly under its headline that names the newspaper section it belongs to. These tags are part of the look — they make the page feel like an actual newspaper instead of a numbered list of stories. Write a fresh tag for every story; never re-use one.201202### Tags for straight news (stories 1–7)203204Pick a section name that fits the story. Real-newspaper analogues are great when they're the obvious fit (Markets, Corporate Affairs, Cartography). Lean into the retro-space-game theme when there's room to be a little playful (Combat Wire, Trade & Lanes, Open Channel, Shipyard). Keep them short — two or three words, title-cased, no punctuation. A few worked examples for reference:205206- A combat-heavy day with named pilots → **Combat Wire** (or **Hostilities**, **Casualty Desk**)207- A toll lane / mega-port / trade-route story → **Trade & Lanes** (or **Public Affairs** if it leans policy)208- An exchange of public broadcasts → **Open Channel** (or **Frontier Justice** if it's spicy)209- A new corporation, recruiting drive, member moves → **Corporate Affairs**210- An exploration / survey / probe record → **Cartography** (or **The Survey Desk**)211- Ship purchases, sales, trade-ins → **Shipyard** (or **Off the Lot**)212- Trade volume, port flow, leaderboard movement → **Markets** (or **The Ledger**)213- Chat broadcasts that read more like commentary than news → **Frontier Justice** (reserve **Open Channel** for the strongest broadcast-driven beat on the page)214215If two stories would land on the same tag — adjacent or not — change one. Each tag must be unique on the page; visual rhythm and section variety depend on it. If a straight-news story and a gossip beat both spring from open-channel chatter, give the gossip the **Open-Channel Confidential** variant and keep the news as **Open Channel**.216217### Tags for gossip (stories 8–9)218219Oblique. Catty. Insider-y. The reader should feel they've stumbled into the back room of a yacht club. Two or three words, title-cased; "The X Set" / "On the X Beat" / "X Talk" patterns work. Worked examples:220221- Wreckage / destroyed ships / escape pods → **Salvage Talk**, **From the Insurance Wing**, **Recovery Notes**222- Mega-port socialites, traders, anyone seen at the dock → **The Mega-Port Set**, **Concourse Whispers**, **Heard on the Promenade**223- Corp politics, recruitment, defections → **The Member Lounge**, **From the Boardroom Door**224- A pilot's unguarded chatter on the open channel → **Open-Channel Confidential**225226The tag should hint at the gist of the gossip without naming it outright. If your tag basically restates the headline, it's too literal — make it more sideways.227228### Tag for the market box (story 10)229230Always literally `*Market Update*`. No variants. The image template expects this string.231232## Privacy and content rules — non-negotiable233234These constraints flow into the image prompt verbatim. Violating them in the markdown means a wrong front page.235236- **Direct messages are private.** Never quote, paraphrase, or imply contents of any DM. Players cannot see other players' DMs in-game; the newspaper can't either. *Broadcasts are public — quote them freely.*237- **Sector numbers are restricted.** Use a sector number only if (a) it appears in a public broadcast inside the window, OR (b) it is a Federation Space sector (the meta-defined fedspace list, 200 sectors by default). When in doubt, omit the number and use a generic phrase like "the borderlands beyond Federation Space" or "a contested sector outside Fed."238- **No invented facts.** Headlines, ledes, quotes, percentages, ship classes, credit amounts, sector numbers — every readable claim must be grounded in the digest. If a stat is interesting but unverifiable, leave it out.239- **No fabricated player names.** Only use names that appear in `players[].name` or in the leaderboard ranks of the digest.240- **No invite codes** unless they were broadcast publicly.241- **Aggregate counts are always public.** Total sectors visited, total trade volume, ships destroyed, corporations created — all fair game for ledes and the market box.242243## Story-mining heuristics244245Strong story signals, in roughly decreasing order of front-page value:2462471. **A public broadcast that announces intent** — toll lanes, recruitment, accusations, "public notice" kill claims, declarations of war. These almost always lead the page.2482. **An exchange of broadcasts between two pilots** — accusation + denial, ultimatum + response. Story 2 territory.2493. **A new corporation with a public manifesto** broadcast in the window.2504. **A combat day above baseline** — count `ship.destroyed` and `combat.ended`. Fourteen ship destructions is a lot; one is a footnote.2515. **A leaderboard sweep** — same name in #1 across multiple boards, or three sister ships in the top three of one board.2526. **A run of ship purchases** with a clear narrative (e.g., a pilot who lost a hull and re-bought).2537. **An autonomous-fleet survey record** — "468 sectors in 24 hours" is a clean explorer beat.2548. **Garrison drama in or near Fed Space.** Garrisons placed close to fedspace, especially if destroyed within hours, are reliable conflict copy.255256Weak signals — generally skip:257258- Quiet trading sessions with no anchoring narrative.259- Movement totals without a name attached.260- Errors, session counts, or other infra signals.261262## Things this skill does NOT do263264- **Does not edit code, deploy, or run migrations.** Read-only digest + write artifacts under `artifacts/`.265- **Does not commit anything.** The user reviews the markdown and image first.266- **Does not push the image anywhere.** It writes to disk; sharing is the user's call.267- **Does not invent storylines to pad to 9.** If the window is genuinely quiet (e.g., an off-hour 1h slice), say so plainly in the lede and reduce gossip items to one. Better a thin honest page than a fabricated one.