repo-mailbox/docs/focus-filter-decision.md
Kjell Tore Guttormsen f9d2c927ab feat(board): give --plan a focus cutoff that reports what it held back
--focus "<prose>" narrows the day plan to repos whose STATE.md DECLARES a
matching topic marker. Measured on the real tree: 26 blocks to 6.

The filter alone was never the feature. --plan documents that it takes one
position (the order), hides nothing, and labels what it cannot rank rather
than dropping it, so a silent cutoff would break a property the format had
already written down. The same run prints the slugs the prose resolved to,
how many blocks it removed, the repos that MENTION a resolved slug with no
marker line - named, not counted - and how many STATE.md it searched. Each
surviving block carries the declaration it survived on.

Enumerated rather than counted because the decisive find behind this feature
was invisible to every string measurement until the held-back population was
listed. "nevner", never "dekker": this reports text found, and board.sh has
no grounds for a claim about relevance. The slug vocabulary comes from the
scanned STATE.md themselves, so the "no other file" invariant survives.

Emitted as key=value, not '#' comments: the consumer's parser runs in
paragraph mode and drops any block without tab=, so a comment would reach the
operator on the terminal path and vanish on the driver path - the one case
where the cutoff is applied unseen.

board-selftest 89 -> 113. The narrowing check is comparative, since every
presence-only assertion passes against a no-op filter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186vKCzuUEN5WcJB82kddzF
2026-08-02 19:58:25 +02:00

7.1 KiB

--focus: what was decided, and the one condition it rests on

Measured 2026-08-02 across 27 STATE.md in the operator's tree. Nothing here is built; board.sh is unchanged at v0.17.0. This file exists because the decision constrains a future feature, and the exchange that produced it lives in a private mailbox and a local-only STATE.md — neither of which is a durable record.

Repos other than morning-driver (the plan format's second declared consumer) are deliberately unnamed: this is a public mirror, and which repo carries which malformed marker line is that repo's business, not this one's. Every count below is reproducible by the party that owns the data.

The decision

A --focus "<free text>" argument may filter --plan down to the repos whose STATE.md declares a matching topic slug, on the condition that the same run also reports the repos it held back: those whose STATE.md mentions the resolved slug without a valid marker line. Without that report the feature is not built.

Why the report is a precondition, not an improvement

--plan already documents three properties about itself: it takes exactly one position (the order), it has no cutoff so it hides nothing, and repos with no board line are labelled rather than dropped — because a plan that omitted them silently would repeat the defect the plan exists to avoid.

--focus is a cutoff. Absent a line saying what fell outside it, the flag breaks a property the format has already written down. The report is what keeps the two compatible. command_missing= and today's MERK: N repo mangler board-linje are the same shape: they report, they select nothing, and the boundary at board.sh:45-51 is untouched by either.

What the report actually yields (measured)

Strict marker lines over 27 STATE.md yield 7 distinct topic slugs; the slug used as the worked example is declared by 6 repos. For the operator's real phrase the truth set is ~11 repos, so a strict-marker answer has ~55% recall and no way to say so. A predicate at that recall presenting itself as a finished day plan is not a partial answer — it is a wrong one.

"The matched token" has two readings, differing only in noise:

reading STATE.md mentioning of those, unmarked
the operator's bare word 16 10
the resolved slug 13 7

Both catch every known miss. The resolved slug is the chosen reading: same recall, half the noise, and the breadth of the report stops depending on the operator's choice of words.

The 7 unmarked mentions fall into three classes, all owned by the topic register (~/.claude/coord/register.md), none by this repo:

  1. Malformed marker — the declaration exists but the register's own grep loses it: a status token wrapped in bold, or a status token outside the register's closed set of seven.
  2. Participation without declaration — the repo owns the specification, or names the subject in prose, and never writes a marker line at all. One case is the repo that is the subject, which carries zero marker lines.
  3. Discussion — see the next section.

The most consequential single find was class 1: a repo that pins the library in its build file, one of the heaviest consumers in the tree, invisible to every measurement in the exchange until the held-back population was listed. That is the argument for the report, and it was found by enumerating, not by reasoning.

Two constraints on the wording

It says "mentions", never "covers". The population is self-modifying: this repo and morning-driver enter it only because they spent 2026-08-02 discussing the subject. Excluding both reproduces exactly the count morning-driver measured independently. A repo can enter the report by talking about a subject, so the line must state a fact about text found (N repo nevner <slug> uten markørlinje) and never a claim about relevance, which board.sh has no grounds for.

It states its own reach. board.sh reads STATE.md and no other file, and will not start reading others. One repo in the measured set has its strongest evidence in a README, which the scan never sees; it is caught only because a different line in its STATE.md happens to mention the slug. The report has searched 27 STATE.md, and must say that rather than imply it searched repos.

A third invariant is inherited, not new: the scan must never be built on an ignore-aware search tool. STATE.md is gitignored by policy in exactly the repos that have a public mirror, so such a tool loses precisely that class — it inverts its own purpose. board.sh is immune today because it reads each STATE.md by explicit path in a plain loop. Any topic reader must stay that way.

topics= is closed, not deferred

A topics= line per plan block was requested so a natural-language layer in morning-driver could upgrade its evidence from "prose hit" to "declared". That layer was withdrawn when selection moved here, so the field has no reader, and a reported field with no reader is noise in a format with two declared consumers.

The need it covered survives but relocates: a focused run must say why each surviving block survived. That is per-block evidence inside --focus, not a line in all 27 blocks on every day the operator has no focus.

Before any of this is built

No order from the operator exists. If one comes: a failing board-selftest.sh check first, the report in the same commit as the filter — never after it — and morning-driver notified before any field in the block format changes. --focus is the chosen spelling over --topic: "topic" names the vocabulary, which the register owns and this repo only reads; "focus" names the operator's day, which is what the argument carries.

What shipped

Built 2026-08-02, after the operator's order. The condition held: the filter and the report landed in one commit, and a failing board-selftest.sh check came first — the narrowing check is comparative (focused block count strictly below unfocused, and non-zero), because every presence-only assertion passes against a no-op filter, which is what the flag was while the unknown-argument fallback swallowed it.

Fields: fokus=, fokus_droppet=, fokus_utenfor=, fokus_rekkevidde= in the header, fokus_treff= per surviving block, and fokus_ikke_brukt= when the prose resolves to nothing. They are key=value and not # comments for a reason found by reading the consumer's parser rather than assuming it: it runs in paragraph mode and discards any block without a tab= line, so a comment — and equally a bare key=value in the header — never reaches its records. The disclosure is therefore emitted in both regions, and morning-driver was told the field names so their side can surface it. A cutoff whose disclosure is dropped by the consumer is applied unseen, which is the failure this whole condition exists to prevent.

Measured on the real tree the day it shipped: 26 blocks to 6 for the worked slug, 20 dropped, 3 repos mentioning it without a marker line. The doc's own earlier counts (13 mentioning / 7 unmarked) no longer reproduce — the population is rewritten every session, which is the argument for the report counting live and never carrying a baked-in number.