On this page

Chapter 2 of 7. Prerequisite: Chapter 1. You have a devlog that records real work in a parseable format, and you have seen what happens without one. This chapter builds the layer on top: the thresholds and the four-outcome rubric that decide which entries become article candidates and which stay worklog.

Chapter 1 named the failure mode: ideas accumulate, articles do not. The pattern is common enough that developer communities document it in the first person. One Indie Hackers post, titled "After 8 months of drafts, I completed my first blog post", puts a number on it: "During these 8 months, I have accumulated a handful of partial drafts and 30 or so ideas for posts." Thirty ideas, one post, eight months. The bottleneck was never material. It was the absence of a decision procedure for which idea to work next.

A devlog makes the problem sharper, not easier. After three months of honest entries you hold hundreds of dated, tagged records of real work. Any ten of them could seed an article. Density without a rubric produces the same paralysis as the ideas list, at larger scale. Triage is the decision procedure, and on this site it runs as a system rather than a mood.

A devlog triage system: which ideas are publishable

Triage is step 0 of the six-step editorial gate this course documents (triage, propose, clarify, draft, edit, ship). It was not in the original design. The gate started at propose and grew a step 0 in front of it, because skipping straight to a thesis produced a specific failure the skill docs name directly: articles whose source cannot back the thesis. The prose reads fine. The evidence under it is thin. Triage exists to ask "does the devlog have enough source?" before anyone drafts a sentence.

The system splits the work between machine and human on one principle: the machine surfaces candidates, the human decides. Every morning a digest job scans each registered repo's devlog through the editorial index, applies three mechanical thresholds, and posts each surviving candidate to a chat surface as one message with four inline buttons. A tap records the decision in a database row with the candidate, the action, and an idempotency key so a double-tap cannot record twice. No candidate advances without a recorded decision.

That is the whole system: a parseable log, three thresholds, four outcomes, an audit trail. The rest of this chapter takes each part in order.

The entry format is the triage substrate

Triage can only be mechanical if the log is. Every entry follows one parse format:

## YYYY-MM-DD — type(scope): subject [tag] [tag]
One dense paragraph. What happened, what broke, what was decided, with numbers.

The log is append-only and newest-first. History is never edited; a correction is a new entry citing the old one. The markdown file stays authoritative, and every database built on it is a rebuildable cache. Each of those caches is a single local SQLite file, which is a stance as much as an implementation detail: SQLite's own docs argue that "an SQLite database file with a defined schema often makes an excellent application file format", and a disposable, regenerable editorial index is that argument applied to workflow state.

Tags carry the entire relatedness model. The index draws explicit links only: no embeddings, no fuzzy matching, no model guessing that two entries feel similar. The design doc states the rule as an instruction: if you want two entries to relate, add a shared tag. The consequence for triage is structural. A candidate is not an entry. A candidate is a tag cluster, a group of entries sharing a tag, and the quality of your clustering is exactly the quality of your tagging discipline.

Which means a vague entry is not a small sin. Compare:

## 2026-06-02 — chore: misc fixes
Fixed some stuff, cleaned up the pipeline a bit. More tomorrow.
## 2026-06-02 — fix(scheduler): past-due rows older than 48h now expire [pipeline] [sla]
Sweep woke at 09:07 and found a 09:00 row with no policy to apply. Added a
grace ladder: under 5 min silent, to 6 h fire soft, to 48 h fire with a nudge,
beyond that mark expired with a reason. Nothing vanishes silently.

The first entry is invisible to triage. No tags, so it joins no cluster; no specifics, so even a human reading the digest sample learns nothing. The second entry is a future article paragraph wearing a date stamp. Write the second kind and triage gets cheap. Write the first kind and no rubric can save you.

Three thresholds surface candidates

The digest job applies three numbers to every tag cluster in every registered repo:

Density: at least 5 uncited entries in the cluster. Uncited is the load-bearing word. When an article ships (step 5 of the gate), the entries it drew on are recorded in a citation graph. Those entries stop counting toward future candidates. The citation graph is the feedback loop that stops triage from surfacing the same well twice: a topic you have already mined must accumulate five new entries before it reappears.

Recency: the cluster's latest entry is at most 90 days old. Older clusters are not deleted, they just stop being candidates. A devlog entry describes state at a point in time; code moves, and an article drafted from a stale cluster asserts things the repo no longer does. Ninety days is the widest window this site trusts itself to fact-check from memory.

Cap: the top 10 candidates per digest, with 3 recent entry subjects sampled for each. The cap is an attention budget. A digest with forty candidates gets skimmed; a digest with ten gets decided. The three sampled subjects exist so the human decision (next section) can be made from the message itself, without opening the repo.

The job is fail-open per repo (one repo's parse error never blocks another's digest) and idempotent per day (re-running it does not re-post).

Four outcomes: upgrade, leave, skip, defer

Every candidate gets exactly one of four decisions. Each maps to an explicit state in the editorial index, so the system always knows why a topic is not in play.

OutcomeMeaningResulting state
upgradeEnough source, right time. Proceed to thesis proposal.proposed
leaveAn existing article already covers this, and that coverage is intentional.left
skipSource too thin to back a thesis. Back-fill the devlog or pick another topic.skipped
deferGood candidate, wrong time. Stores an explicit resurface date.deferred

The distinctions earn their keep at the margins. Leave and skip both mean "no article now" for opposite reasons: leave is a completeness judgment (the topic is done), skip is an evidence judgment (the topic is underfed). Conflate them and six months later you cannot tell whether a silent topic was finished or starved. Skip also carries a prescription: the fix for a skipped topic is more devlog entries, not more drafting effort.

Every decision leaves a durable row, but the two entry points record different things. A digest tap writes one row carrying the candidate, the action, and, for a deferral, the resurface date. Four buttons cannot capture prose, so the tap path trades the written reason for speed. Reasons live on the other path: the CLI triage command writes an append-only audit row with the command, the candidate, and a free-text reason, and the design note on that audit table is blunt: without it, decisions evaporate at session close. Triage decisions are exactly the kind of judgment that feels memorable in the moment and is unrecoverable a month later. "Why is there no article about the scheduler rewrite?" has an answer in the audit trail, or it has no answer at all. When a call is marginal, make it on the CLI path and spend the ten seconds on the reason.

The rubric, applied to one candidate

The thresholds got the candidate into the digest. The human decision runs on the samples. Here is the pass this site makes on each candidate, in order:

  1. Read the three sampled subjects, ignore the entry count

    The count got the candidate here; it has no further vote. Read the sampled subjects as evidence. Do they describe decisions and failures, or do they describe activity? "Fixed some stuff" clusters pass counts and back nothing.

  2. Say the claim out loud

    Complete the sentence "this article argues that…" from the samples alone. If nothing thesis-shaped emerges, the cluster is a chronicle, not an argument. Skip it and let the devlog keep feeding it.

  3. Check the shipped corpus

    The index mirrors published-article tags precisely so triage can see prior coverage. If an existing article covers the topic and still holds, the decision is leave. If the new entries improve on, divert from, or regress against what shipped, that difference is the article, and the decision is upgrade.

  4. Check what the window contains

    Scan the cluster's date range for the incident arc: a failure, a diagnosis, a fix, a number. Clusters with an arc draft themselves. Clusters that are five flavours of routine maintenance pass every threshold and produce the dullest possible article.

  5. Record the outcome

    One tap, one row: the action lands, a deferral with its resurface date. When you triage from the CLI instead, record the reason too. It costs ten seconds now and is the only durable record of your editorial judgment later.

Threshold numbers are proxies, and three shipped articles proved it

Everything above leans on numeric checks, so this chapter has to be honest about what a numeric check is. It is a proxy for a rule, and a proxy can be satisfied while the rule is violated. This site learned that in production, one day after automating this exact triage flow.

On 2026-06-11 the auto-pipeline went live end to end: digest, chat triage, thesis picker, LLM drafter, a deterministic style scrubber, a review email, automated publish. Within 24 hours, three articles that had cleared every automated check were caught by eye on the live site. The pacing was off. The style guide caps em-dash density at 3 per 1,000 words, measured across the whole article. The scrubber checked the budget per paragraph instead, flagging only when a single paragraph held 3 or more. A dozen paragraphs carrying 2 each never trips the paragraph flag and lands the article far over the article-scope budget. All three shipped with clean sidecar reports and zero flags. None were within budget. The gate had implemented a proxy for the rule at a different granularity. The drafting model reaches for em-dashes constantly, so it satisfied the proxy while violating the rule on every single article, systematically rather than by chance. The fix (B-014, PR #202) rewrote the check to article scope, matching the style guide's actual number instead of approximating it.

The incident is a style story, but its lesson lands squarely on triage, because the triage thresholds have identical shape. Five uncited entries is a proxy for "enough source to back a thesis". A cluster of five one-line entries passes the count and backs nothing. Ninety days is a proxy for "still true", and a repo that pivoted last week can invalidate a fresh cluster overnight. The system's answer is the division of labour this chapter keeps repeating: numbers surface candidates, a human reading the actual samples decides. The digest ships those three subjects per candidate precisely so the human check runs on evidence, not on the count that opened the door.

Voice enforcement after the fix became its own discipline, deterministic counters plus a human cadence read, and it is big enough to be its own course. The companion AI prose voice course covers it end to end; the pre-publish style audit chapter documents this same incident from the gate's side, including why the count must be article-scope and why a model can never be the thing that counts.

What upgrade hands forward

An upgraded candidate does not go to a drafter. It goes to step 1, propose, where the topic becomes 2 or 3 competing thesis variants, three sentences each, and never more than 3, on the recorded grounds that a fourth variant produces decision fatigue rather than deliberation. The human picks or redirects before any prose exists. That gate, its states, and the automation that runs it while keeping a human veto in the loop are the next chapter.

Triage is the cheapest step in the whole pipeline and the one that pays for the rest. A wrong triage decision costs a tap. A missing triage step costs a finished, fluent, well-formatted article that its own source cannot support, discovered at edit time or, worse, after publish. Spend the tap.

// EXERCISE

Build a triage rubric over your real notes

Turn your own worklog into triage candidates. Bring your notes into the parseable entry format with tags, cluster them by shared tag, then pick your own three thresholds: a density floor, a recency window and a per-digest cap, tuned to your entry cadence. Run the rubric over the clusters by hand and record a four-outcome decision with a reason for every surfaced candidate.

Expected behaviour
  • At least ten of your real entries follow the dated type(scope) format and carry at least one tag each
  • Clusters are formed by shared tag only, with no similarity guessing, and you can list each cluster's entries
  • Your three threshold numbers are written down next to a sentence justifying each against your own cadence
  • Every surfaced candidate has exactly one recorded outcome from upgrade, leave, skip or defer, with a reason
  • Each defer stores an explicit resurface date rather than a feeling

PROVE IT Pick your strongest cluster and complete the sentence: this article argues that. If a thesis-shaped claim emerges from the sampled subjects alone, mark the candidate upgrade; if nothing emerges, mark it skip and name which entries the devlog still needs.

// CHECKPOINT — TRIAGE
multiple choice · auto-checked

The density threshold counts uncited entries only. What does the uncited qualifier prevent?

exact answer · auto-checked

What is the recency threshold, in days, beyond which a cluster stops being a candidate?

open · self-checked

Leave and skip both mean no article now. Explain the difference, and what goes wrong if you conflate them.

Show answer

Leave is a completeness judgment: an existing article already covers the topic and that coverage is intentional. Skip is an evidence judgment: the source is too thin to back a thesis, and its prescription is more devlog entries rather than more drafting effort. Conflate them and six months later you cannot tell whether a silent topic was finished or starved.

↺ re-read: “Four outcomes: upgrade, leave, skip, defer

Lived experience

Sources

  • SQLite As An Application File Format
    SQLite Consortium (sqlite.org)
    The application-file-format argument quoted where the chapter explains why every index built on the devlog is a rebuildable single-file SQLite cache
    sqlite.org
Back to guide overview