feat(analysis): lead weekly article with a narrative story arc (#576)

The weekly article opened straight into item-by-item trend enumeration, so the story was only hinted at in the subtitle. Rework the weekly analysis prompt so the article LEADS with a compelling narrative lede (2-4 paragraphs, no heading) that summarizes what happened this period and frames it within the current MONTH and YEAR arc — themes, momentum, and what it means — with the enumeration sections following after. - prompts/analyze-weekly.md: add a "Lead with the story" narrative-first section, a {{CURRENT_MONTH}} {{CURRENT_YEAR}} framing input, and update the hard rules, output template, and working method so the lede precedes ## This Week's Trends. Keeps the required section order and grounding-in-sources / no-invention constraints intact. - scripts/analyze_fallback.py: inject {{CURRENT_MONTH}} (month name derived from the run datetime) into the rendered prompt. - scripts/lint_prompts.py: register {{CURRENT_MONTH}} as a trusted var. Does not weaken the self-score quality gate or any test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Juan Manuel Servera committed Jul 18, 2026 at 00:06 UTC 45ddf7208c6031ca6ab7d0b81fbb9649cb0ddb4d
3 files changed +43 -1
prompts/analyze-weekly.md
+34 -1
@@ -7,6 +7,7 @@ Your job is to turn one weekly crawler artifact into a structured editorial summ
7 ## Inputs
8
9 - Current datetime: `{{CURRENT_DATETIME}}`
10 +- Current month and year: `{{CURRENT_MONTH}} {{CURRENT_YEAR}}`
11 - Raw weekly JSON path: `{{RAW_JSON_PATH}}`
12 - Output path: `{{OUTPUT_PATH}}`
13 - Previous summary path: `{{PREVIOUS_SUMMARY_PATH_OR_NONE}}`
@@ -100,6 +101,27 @@ Be critical, selective, and opinionated.
101 - Do **call out** noise, weak substance, exploit-heavy churn, and missing categories.
102 - Do **explain why** the week matters.
103
104 +## Lead with the story (narrative-first)
105 +
106 +The article must **open with a compelling narrative lede** — 2-4 short paragraphs of
107 +editorial prose that appear **before** the first `## This Week's Trends` heading. This lede
108 +is the story of the period, not a list.
109 +
110 +- Open with the single most important thing that happened this period and the tension or
111 + momentum behind it. Hook the reader in the first sentence.
112 +- Frame the arc using the current month and year (`{{CURRENT_MONTH}} {{CURRENT_YEAR}}`):
113 + what theme is building, what shifted, what it means for where the ecosystem is heading.
114 + Treat the week as one beat in the larger `{{CURRENT_MONTH}}` story, not an isolated dump.
115 +- Synthesize across repos and press into a coherent throughline — name the throughline.
116 +- Keep it grounded: every claim must trace to the crawled raw JSON or provided press data.
117 + Do **not** invent facts, numbers, momentum, or events that are not in the sources. If the
118 + evidence is thin, tell that story honestly (a quiet week is still a story).
119 +- Any repository named in the lede must use the link format `[owner/repo](https://github.com/owner/repo)`.
120 +- The **item-by-item enumeration comes AFTER** the lede, inside the sections below. Do not
121 + open the article with a list of trends or repos.
122 +- Keep the lede tight (~120-220 words). Do not add an `##` heading for the lede — it is the
123 + standfirst that precedes `## This Week's Trends`.
124 +
125 ## Analysis dimensions to apply
126
127 1. **Importance Assessment** — identify what solves real problems or signals durable technical movement.
@@ -139,9 +161,12 @@ Be critical, selective, and opinionated.
161 12. `top_repo` should be the repo that best anchors the editorial narrative, not automatically the most-starred repo.
162 13. `quality_score` must be an honest 0-100 self-assessment; publishable work is `>= 60`. The `summary` field must be ≤155 characters, a complete sentence crafted as the meta description for search engines and social sharing. Do not let it exceed 155 characters.
163 14. If you include `predictions`, each entry must be `{repo, claim_type, direction, confidence}` with `claim_type` in `signal|noise|gap`, `direction` in `up|flat|down`, and `confidence` from `0` to `1`.
142 -15. Include all required sections in this exact order:
164 +15. Open with a narrative lede (2-4 paragraphs, ~120-220 words, no heading) as described in
165 + "Lead with the story", then include all required sections in this exact order:
166
167 ```md
168 +[narrative lede paragraphs — no heading, before the first H2]
169 +
170 ## This Week's Trends
171
172 ## Where Industry Meets Code
@@ -184,6 +209,7 @@ Be critical, selective, and opinionated.
209 7. Apply relevant wisdom and skills where they clarify the call, but overrule them when the raw evidence says they do not fit this week.
210 8. Select 5-10 most important repos for Key References; select 3-5 most important press items.
211 9. Produce a brief, forward-looking close that reads like the last paragraph of a Gartner insight brief.
212 +10. Only after the analysis above is settled, write the narrative lede last: distill the whole week into a story arc framed by {{CURRENT_MONTH}} {{CURRENT_YEAR}} and place it at the very top, before `## This Week's Trends`. The lede must summarize — never introduce claims the sections below do not support.
213
214 ## Output template
215
@@ -207,6 +233,13 @@ predictions:
233 confidence: 0.72
234 ---
235
236 +Open here with the narrative lede: 2-4 short paragraphs (~120-220 words) that tell the story
237 +of this period. Lead with the most important development and the momentum behind it, frame it
238 +within the {{CURRENT_MONTH}} {{CURRENT_YEAR}} arc (what is building, what shifted, what it
239 +means), and name the throughline that connects the week's activity. Keep every claim grounded
240 +in the crawled sources — do not invent facts. Use `[owner/repo](https://github.com/owner/repo)`
241 +for any repo you name. Do not put a heading on this lede; the enumeration begins below.
242 +
243 ## This Week's Trends
244
245 Name and explain 3-5 macro trends. For each trend: give it a clear name (bold or inline is fine), explain what is driving it, and state its significance to practitioners. Use specific repos as evidence — e.g., [owner/repo](https://github.com/owner/repo) — rather than abstract claims. Keep each trend to 2-4 sentences. The goal is for a reader to scan this section and immediately understand what the week's dominant technical movements were.
scripts/analyze_fallback.py
+8
@@ -10,6 +10,7 @@ import secrets
10 import sys
11 import time
12 from dataclasses import asdict, dataclass
13 +from datetime import datetime
14 from pathlib import Path
15 from typing import Any
16 from urllib import error, parse, request
@@ -1248,10 +1249,17 @@ def _build_prompt(
1249 else "Week NN, YYYY Analysis"
1250 )
1251 prompt = prompt_template_path.read_text(encoding="utf-8")
1252 + try:
1253 + current_month = datetime.fromisoformat(
1254 + current_datetime.strip().replace("Z", "+00:00")
1255 + ).strftime("%B")
1256 + except (ValueError, TypeError):
1257 + current_month = ""
1258 replacements = {
1259 "{{CURRENT_DATETIME}}": current_datetime,
1260 "{{CURRENT_WEEK}}": current_week,
1261 "{{CURRENT_YEAR}}": current_year,
1262 + "{{CURRENT_MONTH}}": current_month,
1263 "{{TITLE_TEMPLATE_HINT}}": (
1264 f"Specific editorial headline about {current_week}'s dominant themes "
1265 f'(not "{generic_title_example}")'
scripts/lint_prompts.py
+1
@@ -22,6 +22,7 @@ TRUSTED_VARIABLES = frozenset(
22 "{{CURRENT_DATETIME}}",
23 "{{CURRENT_WEEK}}",
24 "{{CURRENT_YEAR}}",
25 + "{{CURRENT_MONTH}}",
26 "{{OUTPUT_PATH}}",
27 "{{RAW_JSON_PATH}}",
28 "{{PREVIOUS_SUMMARY_PATH_OR_NONE}}",