The real failure mode is 0-1 images (wall of text); two heroes read
fine on the 1-2 column layouts. Keep ~4 as the aim — prefer
hero-bearing candidates among equal fits, more images for bigger
bundles — since 2 among 8 items still looks thin on the wide
4-column grid. Restores the 3-item minimum bundle size.
Claude-Session: https://claude.ai/code/session_01WZaczDJjL3xZ3u5spsN5AL
@@ -14,11 +14,11 @@ Invoke from inside the `unique.rzen.dev` repo.
- **Interactive (default when a user is present)**: propose the cluster, wait for sign-off (step 2), then write.
- **Interactive (default when a user is present)**: propose the cluster, wait for sign-off (step 2), then write.
- **Autonomous (`auto` argument, or when running unattended — e.g. invoked by `/daily-pipeline`, a scheduled run, or any headless session)**: skip the confirmation gate. Apply the same quality bar, write directly, and record the would-have-been proposal in the log so the user can veto after the fact. Prefer the *tighter* theme when torn — an unattended run should err conservative.
- **Autonomous (`auto` argument, or when running unattended — e.g. invoked by `/daily-pipeline`, a scheduled run, or any headless session)**: skip the confirmation gate. Apply the same quality bar, write directly, and record the would-have-been proposal in the log so the user can veto after the fact. Prefer the *tighter* theme when torn — an unattended run should err conservative.
- **Weekly catch (`weekly` argument)**: a date-based safety valve, not a themed bundle. Collect every `shortlist: true` find from the last 7 days that appears in **no** existing bundle's `items[]`; if fewer than 3, widen to all unbundled finds from the window. Title: "The week's catch — <Month D–D>". Blurb names the week, not a theme. Cap at 8 by shortlist rank. The hero floor (see below) applies here too, but widen rather than hold: if the window yields fewer than 4 hero-bearing items, pull in older unbundled hero-bearing finds until the floor is met — the weekly exists so finds don't stay invisible, so holding it defeats the point. Only if the *entire* unbundled pool can't muster 4 heroes, skip and report. If nothing qualifies, do nothing and report that. Purpose: no shortlisted find stays invisible for weeks awaiting a theme (finds are only reachable through bundles).
- **Weekly catch (`weekly` argument)**: a date-based safety valve, not a themed bundle. Collect every `shortlist: true` find from the last 7 days that appears in **no** existing bundle's `items[]`; if fewer than 3, widen to all unbundled finds from the window. Title: "The week's catch — <Month D–D>". Blurb names the week, not a theme. Cap at 8 by shortlist rank. The hero floor (see below) applies here too, but widen rather than hold: if the window yields fewer than 2 hero-bearing items, pull in older unbundled hero-bearing finds until the floor is met — the weekly exists so finds don't stay invisible, so holding it defeats the point. Only if the *entire* unbundled pool can't muster 2 heroes, skip and report. If nothing qualifies, do nothing and report that. Purpose: no shortlisted find stays invisible for weeks awaiting a theme (finds are only reachable through bundles).
## Hero floor (applies to every bundle)
## Hero floor (applies to every bundle)
A bundle must contain **at least 4 items that have a hero image** (`hero.<ext>` next to the find's `index.mdx` — check with `ls src/content/find/<y>/<m>/<slug>/hero.*`). This is purely aesthetic: the grid looks broken with fewer than four image cards. Hero-less finds may still ride along beyond the four. If a proposed cluster can't meet the floor, **hold the bundle back** — don't pad with weak fits and don't write it anyway; the theme waits until a fourth hero-bearing find emerges. In autonomous mode, log the held-back cluster (theme + items + which lack heroes) so the next run can revisit it.
A bundle must contain **at least 2 items that have a hero image** (`hero.<ext>` next to the find's `index.mdx` — check with `ls src/content/find/<y>/<m>/<slug>/hero.*`). This is purely aesthetic: with 0–1 images the grid reads as a wall of text. Hero-less finds may still ride along freely — only the floor counts. Beyond the floor, **aim for ~4 heroes**: when choosing among equally good theme fits, prefer hero-bearing ones, and let bigger bundles (7–8 items) carry proportionally more images — 2 heroes in an 8-item grid still looks thin on the wide 4-column layout. If a proposed cluster can't meet even the floor of 2, **hold the bundle back** — don't pad with weak fits and don't write it anyway; the theme waits until enough hero-bearing finds emerge. In autonomous mode, log the held-back cluster (theme + items + which lack heroes) so the next run can revisit it.
## Inputs
## Inputs
@@ -37,7 +37,7 @@ A bundle must contain **at least 4 items that have a hero image** (`hero.<ext>`
3. Compute the **unbundled pool**: every find that does NOT appear in the `items[]` array of any existing `src/content/bundles/*.mdx` bundle. The seed slugs may or may not be in this pool — they're the seed regardless.
3. Compute the **unbundled pool**: every find that does NOT appear in the `items[]` array of any existing `src/content/bundles/*.mdx` bundle. The seed slugs may or may not be in this pool — they're the seed regardless.
4. From the unbundled pool, find every entry that fits the inferred theme. Use frontmatter signals (tags, topics, subtitle) and body content. Don't reach: three weakly-fitting items is worse than zero. If a candidate's fit feels strained, drop it.
4. From the unbundled pool, find every entry that fits the inferred theme. Use frontmatter signals (tags, topics, subtitle) and body content. Don't reach: three weakly-fitting items is worse than zero. If a candidate's fit feels strained, drop it.
5. Combine `seed + qualifying unbundled matches`, deduped. Cap at **8 total** (per sizing notes below). If the combined list exceeds 8, drop the weakest fits — never drop a seed slug; if the seed itself is more than 8, ask the user which to drop.
5. Combine `seed + qualifying unbundled matches`, deduped. Cap at **8 total** (per sizing notes below). If the combined list exceeds 8, drop the weakest fits — never drop a seed slug; if the seed itself is more than 8, ask the user which to drop.
6. Check the hero floor: if fewer than 4 items in the final list have a `hero.*` file, prefer swapping in hero-bearing theme matches; if the floor still can't be met, report that the bundle is held back (interactive: tell the user and let them decide; auto: hold and log).
6. Check the hero floor: if fewer than 2 items in the final list have a `hero.*` file, prefer swapping in hero-bearing theme matches; if the floor still can't be met, report that the bundle is held back (interactive: tell the user and let them decide; auto: hold and log).
7. Produce one cluster (theme phrase + final items list). Continue to step 2 to confirm before writing.
7. Produce one cluster (theme phrase + final items list). Continue to step 2 to confirm before writing.
- **If the user provided a theme phrase only:** scan all finds, surface the 8–12 that best fit the theme.
- **If the user provided a theme phrase only:** scan all finds, surface the 8–12 that best fit the theme.
@@ -113,7 +113,7 @@ Example body:
### 4. Verify
### 4. Verify
- Confirm every slug in `items[]` exists at `src/content/find/<year>/<month>/<slug>/index.mdx` (use `find src/content/find -type d -name "<slug>"` to locate). If any is missing, abort and report — never reference a non-existent find.
- Confirm every slug in `items[]` exists at `src/content/find/<year>/<month>/<slug>/index.mdx` (use `find src/content/find -type d -name "<slug>"` to locate). If any is missing, abort and report — never reference a non-existent find.
- Confirm the hero floor: at least 4 of the `items[]` folders contain a `hero.*` file.
- Confirm the hero floor: at least 2 of the `items[]` folders contain a `hero.*` file.
- Run `npm run build` to confirm the new bundle compiles.
- Run `npm run build` to confirm the new bundle compiles.
### 5. Update the log
### 5. Update the log
@@ -132,7 +132,7 @@ Items referenced:
## Notes
## Notes
- Default to 5 finds per bundle, up to 8 if the theme really supports it. Beyond 8 the grid stops being scannable. The effective minimum is 4 (the hero floor) — a tight 3-item theme waits until a fourth hero-bearing fit emerges.
- Default to 5 finds per bundle. Use 3 for tighter themes, up to 8 if the theme really supports it. Beyond 8 the grid stops being scannable. Whatever the size, the hero floor (≥2 hero-bearing items, aim for ~4) applies.
- The body is for the audience, not the user. Never write "pick one", "candidates", "today's pick" — those are internal terms.
- The body is for the audience, not the user. Never write "pick one", "candidates", "today's pick" — those are internal terms.
- Never edit existing find files when building a bundle. The find body and metadata are stable; the bundle only references them.
- Never edit existing find files when building a bundle. The find body and metadata are stable; the bundle only references them.
- If a find that's referenced has been graduated to a review (its frontmatter has `promotedTo`), it can still appear in the bundle — the grid card simply links to the find page, which itself links forward to the review.
- If a find that's referenced has been graduated to a review (its frontmatter has `promotedTo`), it can still appear in the bundle — the grid card simply links to the find page, which itself links forward to the review.
@@ -30,10 +30,10 @@ Also read every existing bundle's `items[]` array — these are pre-clustered an
Aim for 4-7 clusters. Each cluster should:
Aim for 4-7 clusters. Each cluster should:
- Hang off **one specific editorial angle**, phrasable in 4-8 words ("Pocket carry", "The morning kitchen ritual", "Travel as a kind of attention"). Avoid generic buckets ("Tools", "Apps") — those are tag pages.
- Hang off **one specific editorial angle**, phrasable in 4-8 words ("Pocket carry", "The morning kitchen ritual", "Travel as a kind of attention"). Avoid generic buckets ("Tools", "Apps") — those are tag pages.
- Hold **4-8 items**, of which **at least 4 have a hero image** (`hero.<ext>` next to the find's `index.mdx`) — the grid looks broken with fewer than four image cards. Hero-less finds may ride along beyond the four. Above 8 the grid stops being scannable.
- Hold **3-8 items**, of which **at least 2 have a hero image** (`hero.<ext>` next to the find's `index.mdx`) — with 0–1 images the grid reads as a wall of text. Hero-less finds ride along freely; beyond the floor, aim for ~4 heroes, and give bigger clusters (7–8 items) proportionally more. Above 8 the grid stops being scannable.
- Be **distinct from existing bundles** in angle, even if a couple of items repeat.
- Be **distinct from existing bundles** in angle, even if a couple of items repeat.
If a cluster can't meet the hero floor, **hold it back** rather than pad it with misfits or write it thin — record it as deferred (theme + items + which lack heroes) and revisit when a fourth hero-bearing find emerges.
If a cluster can't meet the hero floor, **hold it back** rather than pad it with misfits or write it thin — record it as deferred (theme + items + which lack heroes) and revisit when enough hero-bearing finds emerge.
Coverage check: after partitioning, every find should appear in at least one cluster (existing or new). If a find genuinely fits no theme, leave it uncovered and report it — don't pad a cluster with a misfit. Finds left homeless only because their cluster was deferred for the hero floor count as covered-pending — list them under the deferred cluster, not as uncovered.
Coverage check: after partitioning, every find should appear in at least one cluster (existing or new). If a find genuinely fits no theme, leave it uncovered and report it — don't pad a cluster with a misfit. Finds left homeless only because their cluster was deferred for the hero floor count as covered-pending — list them under the deferred cluster, not as uncovered.
@@ -94,7 +94,7 @@ Body rules (same as `build-bundle`):
### 6. Verify
### 6. Verify
- Every slug in every `items[]` must exist at `src/content/find/<year>/<month>/<slug>/index.mdx` (locate with `find src/content/find -type d -name "<slug>"`). Confirm before declaring done.
- Every slug in every `items[]` must exist at `src/content/find/<year>/<month>/<slug>/index.mdx` (locate with `find src/content/find -type d -name "<slug>"`). Confirm before declaring done.
- Every bundle meets the hero floor: at least 4 of its `items[]` folders contain a `hero.*` file.
- Every bundle meets the hero floor: at least 2 of its `items[]` folders contain a `hero.*` file.
- Run `npm run build`. If any bundle fails to compile, fix and re-run.
- Run `npm run build`. If any bundle fails to compile, fix and re-run.
@@ -65,7 +65,7 @@ If `link` for a Reddit-discovered item points at a v.redd.it / i.redd.it URL, fe
#### Supporting media
#### Supporting media
For every find, try to retrieve a single representative image from the linked page so the find has visual support if it later graduates to a review (or gets surfaced on a tile). Heroes also gate bundling — a bundle needs at least 4 hero-bearing items before it can ship — so a find without a hero can hold a whole theme back: try a second source (developer site, App Store, Wikimedia) before giving up. The quality bar below still wins, though — a bad image is worse than none.
For every find, try to retrieve a single representative image from the linked page so the find has visual support if it later graduates to a review (or gets surfaced on a tile). Heroes also gate bundling — a bundle needs at least 2 hero-bearing items (aiming for ~4) before it can ship — so a find without a hero can hold a whole theme back: try a second source (developer site, App Store, Wikimedia) before giving up. The quality bar below still wins, though — a bad image is worse than none.
- **Where to look (in priority order):** `og:image` meta tag → JSON-LD `image` field → main product photo / hero image markup → first article image.
- **Where to look (in priority order):** `og:image` meta tag → JSON-LD `image` field → main product photo / hero image markup → first article image.
- **Where to save:** `src/content/find/<year>/<month>/<slug>/hero.<ext>` — colocated next to `index.mdx`. Preserve the original extension (`.jpg`, `.png`, `.webp`, `.gif`, `.avif`). One file per find — `hero` is the canonical name.
- **Where to save:** `src/content/find/<year>/<month>/<slug>/hero.<ext>` — colocated next to `index.mdx`. Preserve the original extension (`.jpg`, `.png`, `.webp`, `.gif`, `.avif`). One file per find — `hero` is the canonical name.
@@ -28,7 +28,7 @@ Stage: the new find folders, `daily-finds.log.md`, `candidate-sources.md`, and `
### 2. Bundle — run `build-bundle` in auto mode
### 2. Bundle — run `build-bundle` in auto mode
- Default: one themed bundle drawn from the unbundled shortlist pool (auto mode picks the strongest cluster itself). If the day's shortlist supports no honest theme, or no cluster meets the hero floor (≥4 items with hero images — see build-bundle), skip — don't force one; note the held-back theme in the digest.
- Default: one themed bundle drawn from the unbundled shortlist pool (auto mode picks the strongest cluster itself). If the day's shortlist supports no honest theme, or no cluster meets the hero floor (≥2 items with hero images, aim for ~4 — see build-bundle), skip — don't force one; note the held-back theme in the digest.
- **Weekly catch check**: if no "week's catch" bundle exists for the trailing 7 days and unbundled shortlisted finds are accumulating, also run `build-bundle weekly`.
- **Weekly catch check**: if no "week's catch" bundle exists for the trailing 7 days and unbundled shortlisted finds are accumulating, also run `build-bundle weekly`.
- **Backlog check**: if the unbundled pool has grown past ~25 shortlisted finds, run `cluster-bundles` in auto mode instead of a single bundle this run.
- **Backlog check**: if the unbundled pool has grown past ~25 shortlisted finds, run `cluster-bundles` in auto mode instead of a single bundle this run.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.