Short answer: an admin writes what they want to read, in their own words; the desk turns it into ticked sub-fields and a few custom searches; the admin confirms; from the next morning the brew reads only that. One scope, shared by every admin. Clear it and Ink reads the whole world again.
Every brew keeps the whole harvest of its morning as pegs-all.json: about 2,400 stories a day, from Wikipedia's Current events, 37 Google News country editions, six topic feeds in five editions, 59 outlet feeds, and 189 free Google News searches (172 sub-field rows + 17 kinds of event). Ten days of pools were read for this page: six on the box (09-09 → 09-13, 09-20) and four on localhost.
The taxonomy a story is born with. One tree and three flat axes:
The checklist's eight「World › Africa / Latin America / …」rows are regions dressed as sub-fields; the scope treats them as regions and never as a topic, so the topical list is 164. The free-text tags an editor writes on a commissioned piece (["buffett", "succession"]) are a different thing — subject words for the repeat check, not a taxonomy.
| Fact | Measured | What it forced |
|---|---|---|
| half the pool carries no sub-field | 47% — every story that came from an edition, an outlet feed or a topic feed has a beat only, and an edition's beat is「World」by default | a filter on today's tags would see half the pool, and the personas write mostly from the other half: 63% of the 182 pieces commissioned on the box came from a peg with no sub-field |
| the sub-field counts are a quota | every checklist search returns 8 lines, so all 172 rows sit at 7–8 a day; only history (26) and obituaries (12) differ, because Wikipedia feeds them too | a distribution read off the raw tags is flat by construction — the pool has to be tagged before it can be read |
| Pass | How | Cost | Recovered (7 days, 16,704 stories) |
|---|---|---|---|
| ① the harvest's own tags | a story a checklist search found carries that row's sub-field from birth; the fold merges it onto the same story seen in a feed | free | 51% |
| ② keyword rules | each checklist row is a query a OR b OR c; split on OR, match every phrase as a whole word against title + snippet; a hit gives beat and sub-field at once | free | 13% |
| ③ one Flash pass | the rest, 40 headlines a call, the closed list in the system prompt; one sub-field and one region each, thinking off, JSON mode | $0.25 for the seven days · ~3.5¢ a morning | 36% |
| still empty | 1% | ||
Region: 43% from the harvest (a named place in the title, an edition's country, a regional checklist row), 32% from the Flash pass, 25% genuinely placeless — science, tech and life pieces mostly name no country.
The raw tags said World 29%: edition inflation. Tagged, World is 22%.
With the untagged half tagged, the range runs from 6 to 76 a day. A sub-field near 8/day is one only the checklist search reaches (90–100% of its stories came from that search); one well above it is what the world's editions and feeds push on their own.
| The world pushes these | /day | from the search | The search-only tail (~8/day, 90–100% from the search) |
|---|---|---|---|
| crime and trials | 76 | 9% | sleep · sex · grief · disability · faith and meaning · poetry · language · art crime · architecture · esports · quantum · drugs and addiction · private equity · shipping and logistics · philanthropy · winter sports · women's sport · cycling · the diaspora · Chinese sport |
| elections | 65 | 11% | |
| diplomacy and summits | 57 | 13% | |
| public health | 56 | 13% | |
| war and ceasefires | 42 | 18% | |
| celebrity · military and defence · disasters | 38 | 20% | |
| history · medicine · courts and rulings | 32–37 | 22–71% | |
| football (world) · pop music · cricket · schools · film | 25–29 | 26–31% |
Per beat, the heads: World → crime, elections, diplomacy · Science → public health, medicine, astronomy · Culture → celebrity, history, pop music · Markets → airlines, commodities, economics research · Tech → AI models, AI in use, gadgets · Sports → world football, cricket, American football · Life → schools, housing, travel · China → policy, trade, Taiwan. Beat × region: World is spread across every region (Middle East 65/day, Western Europe 56, Southeast Asia 47); every other beat is North America plus placeless.
The owner's own example: start-ups, tech, science, Bay Area real estate, Shanghai real estate, super-luxury real estate worldwide.
| Wanted | On the tree | Expected pool |
|---|---|---|
| start-ups | Markets › startups (+ IPOs and deals, private equity) | ~30/day |
| tech | the whole Tech & AI beat, 16 sub-fields | ~200/day |
| science | the whole Science beat, 20 sub-fields | ~310/day |
| Bay Area real estate | no fit — property × North America is a continent | — |
| Shanghai real estate | no fit — property × China is a country | — |
| super-luxury real estate, worldwide | no fit — property has no price tier; luxury and retail is shops | — |
The taxonomy's finest grain is a sub-field × a region, and a region is a continent. Cities and price tiers are below it. But a sub-field is nothing more than a name and a Google News query, and the search layer runs every row every day for free — so the scope can add rows:
A custom row behaves exactly like the built-in 164: the harvest searches it (a zh row in the Chinese edition as well), the fold tags stories with it, the Flash tagger sees it in the closed list so feed and edition stories can land in it too, and it is ticked. Each brings in roughly 8 to 20 stories a day, mostly from the search itself.
| Piece | Where | What |
|---|---|---|
| the store | settings.ink_scope | {text, subs: ["Beat › sub"…], custom: [{beat, sub, query, lang}], regions, updated, by} — empty or missing = no scope |
| the routes | run_room.py · /api/admin/ink/scope (GET · POST) · /scope/draft | under /api/admin/, so the central gate makes them admin-only; the console's /api/admin/ink carries the scope read-only |
| the draft + the tagger | ink_brew.py · scope() · clean_scope() · scope_draft() · tag_batch() | the eighteenth task leaf, app.ink_scope, on the Flash seat; a card on Models & APIs under Research |
| the harvest | ink_harvest.py · taxonomy() · scope_subs() · in_scope() · keyword_rules() · tag_pool() | model-free: the brew hands in the Flash call; without one the pass stops after the keyword rules. harvest(…, scope, tagger); the checklist rows carry a language |
| the page | room-ui.html · #inkScope · openScope | in DRAWERS, the back gesture, the wide-mode list; the ⊕ menu's first item on the Ink tab for admins; the reader's ⋯ after Feedback… |
| the console | Ink tab › The scope | read-only: what is set, by whom, when — it is set from the app |
pegs-all.json is the full, now fully tagged, pool. Widening the scope tomorrow costs nothing today; the tags are the record.pegs-all.json · pegs.json · coverage.json); /api/admin/ink/harvests + /harvest/{date}.The owner:「our harvest should be different. It's no longer pull all the sources and sort out what I need. It should be proactive search on my interested topic. Don't translate my text into tags from the existing database; do fuzzy and semantic search using my text on the web for news.」
As built (v1103). The page: your brief · Read it back (one Flash call: the readback line, the themes in your words, the number of searches) · Confirm / Clear · the harvest rows. The store: ink_scope = {text, summary, themes, queries:[{q, lang, theme}], updated, by}. The morning: ink_brew.stage_pegs → reading_scope() → ink_harvest.harvest_brief: every query searched (Google News RSS, 20 lines each, the Chinese edition for a zh query) → fold → judge_pool (the Flash seat reads every story against the brief: in · theme · closeness 0–3 · beat, 40 a call) → the stories in, ranked by (1 + closeness) × attention with the usual discounts → ~160 to the meeting; yesterday's pegs with closeness ≥ 2 → up to 10 follow-up queries (followup_queries). The harvest page shows ● ●● ●●● per story. The pick list, the tag recovery and the custom rows of v1101 are gone from the code; §2–3 stay as the study they were.
| The dry run, 09-21, the owner's brief | |
|---|---|
| queries drafted (6 themes: start-ups · tech · science · Bay Area · Shanghai · super-luxury; 12 in Chinese) | 45 |
| lines → stories after the fold | 772 → 641 |
| in scope after the read (●●● 110 · ●● 291 · ● 30) · out | 431 · 210 |
| by theme: tech 137 · start-ups 109 · science 62 · super-luxury 53 · Bay Area 38 · Shanghai 32 | |
| to the meeting · very close | 160 · 104 |
| time · cost (18 Flash calls) | 15 s · $0.016 |
The owner, reading the parsed searches:「biotech is not mentioned under tech. How can we solve this?」— and then:「I'm no expert in news. I just like the search to be reasonably well covered, not skewed towards a subset of the news space. I want the user to get what he wants with best effort.」
A finite list of phrases can never cover a broad theme; that was the tags' problem too. So Parse now decides, per theme, broad or narrow:
| What it is | What the morning does | On the Scope page | |
|---|---|---|---|
| broad | a whole section of the news — tech, science, health, sports, business, politics, world, culture, markets, environment, real estate, education, law and crime, China, lifestyle | reads the section WHOLE: every outlet feed it has, its Google News topic feed in two editions, its standing checklist searches — exhaustive by construction; the relevance read still decides what is close. 2–4 queries for the editor's particular angle, if the brief names one | 「tech · the whole technology section · 8 feeds · 17 standing searches」 |
| narrow | a place, a price tier, a company, a niche | enumerated: 10–15 searches covering the theme's sub-topics, players, places and phrasings | the searches, compact |
The sections map (lib/ink/harvest.json › sections, 15 sections, 92 feeds of which 33 new, 173 standing searches) is a second key over the same sources, by ordinary section names. It does not replace the eight beats: those stay the writing side's labels (hard news, the art director's accents). The eight were a lopsided map for reading — World and Markets were catch-alls, Health was split between Science and Life, Environment and Real estate had no home — so reading broad themes is keyed to sections instead. New feeds: Politico, The Hill, Guardian politics/law/environment/health/education/property, STAT, Medical Xpress, WHO, KFF, Nature, Science, Carbon Brief, Inside Climate News, Mongabay, The Real Deal, Realtor.com, Mansion Global, Inside Higher Ed, Chalkbeat, Times Higher Education, Caixin, China Daily, Courthouse News, ABA Journal, NYT style/travel/politics. A feed that fails is logged and skipped.
| The dry run, 09-21, the owner's brief, with sections | |
|---|---|
| Parse: tech → the technology section, science → the science section; start-ups, Bay Area, Shanghai, super-luxury enumerated at 15 searches each | 68 searches + 2 sections |
| lines: 68 searches 1,116 · technology whole 351 (26/26 sources) · science whole 368 (26/27) | 1,835 |
| stories after the fold · in scope after the read (●●● 220 · ●● 553 · ● 57) | 1,210 · 830 |
| by theme: tech 295 · science 185 · start-ups 155 · super-luxury 90 · Shanghai 65 · Bay Area 40 | |
| to the meeting · time · cost (32 Flash calls) | 160 · 33 s · $0.03 |
| Seen | Cause | Fix |
|---|---|---|
| the Shanghai theme was thirty developer sales-office notices from one portal, rated ●●● by the read | a listing is squarely「Shanghai real estate」to a reader that was not told ads are not news | ad-like lines are dropped before the fold (售楼处 · 官方专线 · 24小时响应 · sponsored · press release …, logged: 74 of 1,912) and the read is told a listing, a promotion or a press release is 0 however close its subject |
| after that, the Shanghai theme had twelve stories in scope and none at the meeting | three doors in a row: the tail seats handed each theme ONE story and stopped; the language limit (12 non-English) was the wide harvest's rule; and the brew's section-page guard counted a Chinese headline as one「word」and refused all twelve | the tail cycles the themes until its seats are used; under a brief a third of the seats may be non-English; the guard counts CJK characters as words |
| 「实得率超216%!杨浦滨江「外滩元境二期」推约110-174㎡风貌洋房」reached the meeting at ●●● — a soft ad: a launch report about one named development | it looks like news; the read's ad rule named listings and hotlines, not advertorial | two signals before the fold — a bracketed project name AND a sales term (实得率 · 推约 · 户型 · 均价 · 认筹 · 加推 · ㎡ …) — so a market report quoting prices survives; and the read is told the soft ad's tells: one named development quoting its own sales terms with no market fact and no event is 0, and a portal or self-media account is news only with a market fact from a source other than the seller |
| a theme's LPR / PBOC rate stories rated ●● for Shanghai real estate | the read is lenient on adjacency | left as is: rates move property; the meeting can still pass them over |
| Date | What |
|---|---|
| 2026-09-22 | v1106 (owner): the harvest page opens with a count strip — one tile a theme (in scope · seats), the Stats page's tiles; a tap filters the list to the theme. The soft-ad rule (§8). The owner's questions answered on the page: the coral tile = read at the meeting, grey = in the pool only, the ring = front; ●●● squarely · ●● within · ● loosely · out; attention = outlets + countries + 2×front pages + Wikipedia, no model. |
| 2026-09-21 | v1105 (owner:「reasonably well covered, not skewed」): §8 — the sections map, broad themes read whole, narrow themes enumerated; dry run 1,210 stories → 830 in → 160, 33 s, 3¢. |
| 2026-09-21 | v1104 (owner): the Ink ⋯ holds TWO commands, each its own page — Scope… (the brief · Parse · the readback line · every search, compact by theme, Chinese ones muted · Confirm / Clear; no status block) and Harvests… (the mornings as drawer rows, a row opens the day). The owner's question「what does 51 searches a morning mean」→ the number of queries the brief was parsed into, each run against Google News every morning, 4–8 per theme. |
| 2026-09-20 · night | v1103: the brief-driven search harvest BUILT (§7) — the page is the brief + the readback; under a scope the wide harvest does not run. Dry run on the owner's brief: 45 searches → 641 stories → 431 in → 160 to the meeting, 15 s, 1.6¢. v1102: the Ink tab's corner is the ⋯ (one command, admin only); the harvest rows + the harvest page. The pick list rejected by the owner. |
| 2026-09-20 | the ten pools read; the recovery run over 16,704 stories ($0.25); the distribution above. Built the same night: the store, the routes, the draft, the tagger, the harvest under a scope, the Scope page, the console line, the eighteenth leaf. Owed: the owner sets the first scope on the box tonight; the 09-21 03:00 brew is the first scoped morning — read its log line「scope: N of M stories in scope」and the by-sub counts in coverage.json. |