Judge relevance against a purpose, not against a unit
Route one talk to three readers under one budget, and see a unit judged not relevant still travel with the unit that depends on it.
“Important to whom?” is the question the chapter is built around, and its answer is that importance is not a property of a unit. It is a relation among a unit, a declared purpose and a context. The same sentence can be decisive for one reader, irrelevant to another, and travel with a third because something else depends on it.
Run it
git clone https://github.com/ernanhughes/project-language.git
cd project-language
git checkout 329660f679a5a87831f91fe1430c20ac9360dda8
npm ci
npm run example:talkThe same program as Chapter 14. No host, no interface and no model are involved, and the relevance judgements are written by hand.
Expected outcome
One talk, three readers, one budget. Iris is asking about safety under unbounded delay, and the qualification that governs the result is shown to her while the headline benchmark is not:
...
iris-safety-unbounded: "Determine whether this protocol remains safe when network delays become unbounded."
withheld u-intro not_relevant introduction
withheld u-history not_relevant an anecdote about the name
SHOWN u-scope decisive states the condition the safety result depends on, and unbounded delay violates it
SHOWN u-sync-sense relevant the sense of partial synchrony the result is stated in
SHOWN u-quorum low a definition the safety argument uses
withheld u-round not_relevant mechanism detail, not part of the safety argument as she is reading it
SHOWN u-proof relevant the safety argument itself
withheld u-benchmark low judged low (the headline, but it concerns speed, not safety under unbounded delay) but not selected: budget: unit exceeds remaining budgetTom wants the history and the speed. The qualification is not relevant to that — and it still travels, because the result it limits depends on it:
...
tom-history: "Write the history of consensus protocols for a literature review, starting with how fast this one is."
withheld u-intro not_relevant introduction
SHOWN u-history relevant where the protocol's name came from belongs in a history
ATTACHED u-scope not_relevant not relevant to this purpose, but u-benchmark depends on it, so it travels with itAnd the run states the rule in one line:
...
Tom wants only the speed. The qualification about bounded delay is not relevant to that, and it still travels with the result it limits.A judgement belongs to one purpose
A judgement is not a property of the unit. It is bound to one purpose, needs a reason, cites the units it is about, and a model’s judgement is a proposal until a person accepts it.
export interface Judgement {
unit_id: string;
purpose_id: string;
verdict: Verdict;
/** In the person's terms. Must be non-empty and must say what the unit does for or against the purpose. */
reason: string;
/** Units the reason rests on. At least the unit itself. */
cites: string[];
by: "person" | "domain_rule" | "model";
/** A model's judgement counts only once a person has accepted it. */
accepted_by?: "person";
}The rules are enforced, not described:
export function validateJudgement(j: Judgement, purpose: Purpose, units: readonly Unit[]): JudgementProblem[] {
const out: JudgementProblem[] = [];
const ids = new Set(units.map(u => u.id));
if (!ids.has(j.unit_id)) out.push({ code: "UNKNOWN_UNIT", detail: j.unit_id });
if (j.purpose_id !== purpose.id) out.push({ code: "WRONG_PURPOSE", detail: `judged for "${j.purpose_id}", used under "${purpose.id}"; a judgement is not reusable across purposes` });
if (!(VERDICTS as readonly string[]).includes(j.verdict)) out.push({ code: "BAD_VERDICT", detail: String(j.verdict) });
if (!j.reason.trim()) out.push({ code: "NO_REASON", detail: "a relevance judgement without a reason is a number nobody can argue with" });
if (!j.cites.includes(j.unit_id) || j.cites.some(c => !ids.has(c))) out.push({ code: "BAD_CITATION", detail: "the reason must cite the unit it is about, and only units that exist" });
if (j.by === "model" && j.accepted_by !== "person") out.push({ code: "MODEL_JUDGEMENT_NOT_ACCEPTED", detail: "a model's judgement is a proposal until a person accepts it" });
return out;
}And the attachment rule — a unit judged not relevant still travels when a shown unit depends on it — is one branch of the planner:
if (chosen.has(u.id)) {
if (verdict === "not_relevant" || verdict === "unjudged") {
const by = units.filter(x => chosen.has(x.id) && x.dependsOn.includes(u.id)).map(x => x.id);
return { unit_id: u.id, disposition: "attached", verdict, reason: `not relevant to this purpose, but ${by.join(", ")} depend${by.length === 1 ? "s" : ""} on it, so it travels with ${by.length === 1 ? "it" : "them"}`, reopenable: false };
}
return { unit_id: u.id, disposition: "shown", verdict, reason: j!.reason, reopenable: false };
}Mechanism and limitations
Documented: the five rules this module enforces — one purpose per judgement,
a stated reason, a proposal until accepted, a declared purpose never replaced
by an inferred one, and the attachment rule — are listed at the top of
core/radar/src/attention/relevance.ts.
Observed: the run above. The same unit was decisive for Iris, low for
Tom, and not relevant but attached for Mina, each with a reason. Everything
not shown was withheld with a reason, and a unit excluded by the budget was
withheld as judged low … but not selected: budget: unit exceeds remaining budget rather than silently dropped.
Not shown. The judgements are written by hand; nothing here decides whether a unit is relevant, and nothing extracts concepts. The verdict ordering is a declared number handed to the compiler, not a computed score, and it is not shown to the person. Whether readers would choose these boundaries, find the records usable, or read less as a result is untested.
Understand this example
Copy this prompt into your AI tool. No code runs here.
Apply this example
Copy this prompt into your AI tool. No code runs here.