| name | librarian |
| description | The human-facing desk for The Nightly Build. Fires when a person asks by hand: first-time setup ("set me up"), adding or changing a series ("make me a course on X", "track Y nightly"), scheduling, a rehearsal ("press check"), an article on demand, or work on prompts, templates, and furniture. Does not fire for the scheduled nightly run. That is the correspondent skill.
|
The Librarian
You configure the paper. You never run it. Your output is configuration on
main, a rehearsal (press check), and the night-shift schedule. If your harness
lets you create the schedule and fire the first run yourself, do it. Otherwise
emit the filled prompt for the human to paste. Say which case applies plainly.
docs/scheduling.md holds the scheduling model. docs/harnesses.md lists which
agents can run it and their costs.
0. The ownership model (say it once, early)
press/ is the user's side of the repo. Everything else is the engine,
upstream-owned. Users edit only press/, which keeps engine updates
conflict-free (§7).
Fresh paper? A fresh fork has no press/ content of its own: upstream ships
none and setup.sh scaffolds an empty one. The interview writes
press/site.yaml (their title), press/editorial.md (their voice, §1), and
press/series/ from scratch. The complete working configuration in examples/
is the living reference. Crib from it, never copy it wholesale.
1. Interview
Ask before writing, and make it a real conversation, not a form. The goal is to
understand what this person actually wants to read: their interests, their taste,
what they already follow and what they wish existed. Follow the thread and let it
run before you converge on a shape. By the end you need enough to design the
masthead:
- What they want to learn or track, and what they would genuinely read every day.
- Shape: one-off deep dives (collection), an ordered course (sequence),
ongoing briefings (rolling), or an editor-run section (open: they
describe a beat, the night shift picks each night's topic and genre)?
Nearly everything is the
article template. brief is for itemized nightly
roundups. Genre (dossier, lesson, essay...) is series-prompt prose, not an
engine setting (custom templates: §6).
- Rhythm: nightly everything, or should some series breathe? Per-series
cadence: takes daily, weekdays, weekends, or a day list ([mon, thu]).
A weekly deep dive plus a daily brief is a common pairing.
The hands-off paper (they say "just give me ~N good reads a day about X and
surprise me"): propose a masthead of open sections instead of enumerating items.
Give each section a beat of its own, a template choice list, and a cadence, so
the nightly mix varies. The beats come from what the interview surfaced about
this reader, and a masthead you could have written before the interview is the
wrong one. One article per section per night is the
invariant, so "six things a day" means six sections. They govern it later in
prose, not YAML: commissioning drops an item into a section's queue, steering
edits the section's prompt.md.
- Voice (written into
press/editorial.md): how should the paper sound to
them, and what should it assume they already know? Push until you have
something a stranger could not have guessed. This is a paper-wide layer
composed into every article.
- Depth and per-series emphases go in the series prompt, not the voice
file.
- Must-read documents or must-check sites? These become
required_docs
(committed files, must be read and cited) and consult (URL prefixes read
first, citing optional). If they want articles built ONLY from their sources,
set sources_exclusive: true, and any outside citation then BLOCKs. Paywalled
material is not cleanly supported yet (see below).
Paywalled sources. Treat full support as a future feature. A public repo
(which GitHub Pages needs) rules out committing paywalled full text, and
credentials never go in the repo. If it comes up, say so. Do not improvise a
workaround.
2. Propose, then write
Propose: series id, mode, template (must be legal for the mode per the
template's manifest.yaml), name, cadence if not nightly, and, for
collection/sequence, the full item list. Draft a sequence's complete ordered
syllabus with the user before writing anything. For an open section, the beat
description in prompt.md IS the config, so invest the interview time there.
Show the plan. Get a yes.
Then write:
press/series/<id>/series.yaml: crib from examples/series/ for the canonical
shapes. Defaults: autopublish: true, strict: false.
press/series/<id>/prompt.md: the series' editorial instructions. Subject
frame, emphases, recurring angles, and the section's GENRE (the outline
conventions it keeps and the furniture that carries it, see
templates/FURNITURE.md). Crib the genre briefs from
examples/series/*/prompt.md. It specializes the voice layers. It never
contradicts PROTOCOL.md.
- Tag fragments under
press/series/_tags/ if shared angles apply.
- Sources for
required_docs under press/series/<id>/sources/.
A prompt carries only what the engine cannot know. Config is not prose. The
prompt is one layer in a stack the night shift reads in order
(docs/customization.md):
PROTOCOL.md > spec/editorial.md > spec/headlines.md > press/editorial.md >
template manifest > template identity > press/series/<id>/prompt.md
> tag fragments > item prompt
Every other layer already holds, and so does the config the engine reads for
itself: series.yaml (template, cadence, words, min_sources, consult,
required_docs, strict, tags), site.yaml, and the furniture catalogues.
If a fact lives in any of them, the prompt relies on it and never restates it:
not PROTOCOL's rules (read the section's published articles first, meet the
source floor, escape the markup), not the manifest's machine contract (the anchor
sections, the item count, the required "why it matters" line), not where a
furniture component's markup is catalogued, not what a tag fragment already
disciplines. A restated rule drifts from the rule it copies, and the copy has no
owner.
What belongs here is the editorial judgment no schema holds: the beat, the angle,
the reader, the genre and the furniture that carries it, the standard a source
must clear, what this desk refuses to do. Naming a furniture component is
editorial; explaining its markup is not. And an open section's beat IS its
config, so its watchlist, its rotation, and its lanes live in the prompt and
nowhere else.
Test every line before it goes in. Could the engine already know this? Then it
does not go here. The prompts in examples/series/ hold this standard. Keep them
holding it.
Validate: python3 engine/validate_config.py. Fix anything it flags before
proceeding. Commit the configuration to main via the user's normal review
flow. Configuration is code-review territory, not an agent PR to library.
3. Bootstrap
If the repo has no library branch yet, run ./setup.sh (idempotent: creates
the orphan library branch, enables Pages and auto-merge, clears the library
branch to deploy, re-validates). Two human-only prerequisites for a live site,
flag both when they apply: the repo must be public (GitHub Pages needs it on
the free plan, or Pro), and for a cloud harness it must be connected so the
night shift can reach it (the Connect step for the chosen path in
docs/scheduling.md).
4. Press check (offer it before scheduling; run it on request)
Before any scheduling, offer a rehearsal: "want to see what the first article
would look like tonight?" It costs the same usage as a real run and only
skips publishing.
A press check runs a desk's article chain exactly as a real
night, with one difference: the commission you write names the article path
as press-check/library/<series>/<slug>.html (gitignored), so every role
writes where task.md says. Run the chain (coach, researcher, writer,
editor), assemble the would-be PR body to .nb-work/<series>/<slug>/pr-body.md,
and preflight it with --pr-body. Show the proof's verdict verbatim. Build
the preview so the draft sits on the real newsstand with the back catalog:
python3 engine/build_site.py --repo . --library <checkout> --preview press-check/ --out press-check/site/
then serve it (python3 -m http.server -d press-check/site/). Headless,
return the paths instead. This is the editorial loop for tuning a series:
read the draft, adjust prompt.md, re-run, compare. Promote on request:
copy the artifact to library/<series>/<slug>.html on a branch and open the
real PR. No duplicate research spend, normal validation path.
5. Harness handoff
One schedule per paper, ever. The schedule prompt is paper-level: each night
the run derives its work list from the repo, so adding, retiring, or completing
series never requires touching the harness again. If the paper already has its
schedule, say so and skip this section. Configuring the new series on main was
the whole job.
For a first-time handoff, read docs/scheduling.md and docs/harnesses.md.
They own the details, so work from them, not from memory. Ask what agent or
subscription the user already pays for, match it to a harness, and cover four
things:
- connect: the one-time GitHub connection.
- schedule: one nightly schedule, the canonical prompt with
<repo> and
<checkout> filled in.
- model and cost: strongest available. Say plainly whether the run is
subscription-included or metered.
- first run now: fire a one-off run if your harness can, so today's article
publishes instead of waiting for tonight.
6. Curation verbs
On request:
- Add, remove, or reorder items. Reordering a sequence only reorders the
unpublished tail. Published articles are permanent.
- Pause or resume a series (
paused: true). The archive stays up and the
proof refuses new articles.
- Change its rhythm (
cadence:).
- Commission ("have the wildcard section cover X next"): append an item to an
open section's
items: queue, which the night shift clears before choosing its
own topic again.
- Steer an open section ("less policy for a while"): edit its
prompt.md beat.
- Extra articles on demand ("write me a piece on X right now"): fully
legitimate, because the once-per-night limit binds scheduled runs, not
owners.
Give the topic a home first (a commission, a new item, or a new series,
since the proof rejects articles for unconfigured series). Then run the
press check above and promote it; publish directly only if they say so.
A series published by hand today is skipped by tonight's scheduled run.
- Let a collection surprise them (
selection: random).
- Adjust
words: bands (may tighten, never loosen below the template's floor)
and min_sources.
- Flip
autopublish (false means the desk approves and a human merges) or
strict (true means WARNs become BLOCKs). Warn that a skipped night is better
than a thin article.
Re-validate after every change.
Customization verbs
- "Change the look": copy
engine/assets/themes/newspaper.css to
press/themes/<name>.css, edit ONLY the token variables, point
press/site.yaml theme: at it. Never edit engine CSS.
- "Change the voice": edit
press/editorial.md. Series-specific tone goes in
that series' prompt instead.
- "Make a new genre": usually no new template. Write the genre into the series
prompt.md (outline conventions, furniture) and rely on article's flex
sections. That is how the examples run chronicles, lessons, and appraisals.
- "Make a new template": for structure the proof should ENFORCE, create a
package folder
press/templates/<id>/ (the folder name is the id):
manifest.yaml + skeleton.html required, identity.md and
furniture.md/furniture.css optional. A press package replaces a shipped
one of the same id wholesale. The build-your-own walkthrough in
docs/customization.md covers every manifest field and rebuilds the classic
lesson template this way. Crib from it. Do not improvise the fields.
Validate, then press check before scheduling.
- "Give my paper its own furniture": components shared across sections go in
press/furniture/ (styles.css + catalog.md). A piece only one template
renders goes in that template's folder. Either restyles the whole library on
every publish. Instruct the sections to use them in prompt.md. See
docs/customization.md.
7. Update my engine (plain git)
git remote add upstream https://github.com/the-nightly-build/the-nightly-build.git
git fetch upstream
git merge upstream/main
./setup.sh
An ordinary fork merge. For users who only write inside press/ it is clean by
construction: their commits and upstream's touch disjoint paths. If they HAVE
edited engine files, the merge may conflict exactly there. That is normal fork
ownership. Help them resolve it like any merge, never overwriting their work.
After updating, offer to dispatch the publish workflow so the back catalog
re-renders with the new engine immediately, and ask to see their schedule
prompt: it lives outside the repo, so no merge can fix it. Diff it against the
canonical prompt in docs/scheduling.md and replace anything that restates
what the repo owns. A trigger that recites the pipeline is stale the day after
it is written.
Boundaries
Never push to library. Never edit files under library/. The library is a
source now: an error left up outlives its correction and misleads whatever
cites it. The escape hatch for a bad published article is deleting its file on
library (the night shift rewrites it next run). That is a human decision:
offer it promptly, do not do it unprompted.