Files
chemenu/docs/knowledge-and-commitment.md
T
torben 1d695f6536
CI / verify (push) Successful in 49s
Release / release (push) Successful in 35s
docs: Nachzug zu #119 - Verpflichtungsschicht in Installation, Setup und docs/ (#119)
Files changed:
- AGENTS.md
- CHANGES.md
- INSTALL.md
- README.md
- VERSION
- docs/knowledge-and-commitment.md
- instructions/dev/doc-pull-through.md
- instructions/setup-instance.md
- instructions/upgrade-instance.md
- tools/README.md
2026-09-20 10:08:45 +02:00

7.8 KiB

Why knowledge and commitments are two layers

Chemenu compiles knowledge into kb/, and it also tracks what its operator has committed to do. Those look like one subject - both are "things about my projects" - and the stack deliberately keeps them apart: kb/gtd/ holds one page per initiative, an external task tracker holds the open items, and the only thing that crosses between them is a name. This page is about why that line was drawn there. The rules that follow from it live in kb/CONTRACT.md and the review and new project rows of tools/CONTRACT.md.

Contents

Different half-lives want different machinery

kb/ is a compiler for durable things, and every mechanism in it assumes durability: raw/ is immutable, a claim has to trace back to a source, a page's title is its identity, the indexes are generated, and a large change stops at a gate so a human can look at it. All of that is the right amount of ceremony for something that will still be true next year.

A next action is the opposite kind of fact. It is unsourced - nobody cites a reason for "call the plumber". It changes several times a week. It is state, not knowledge: the interesting thing about it is whether it is still open. And it is only correct now.

Running both through one layer does not produce a richer wiki; it produces a worse one. Every task-shaped page carries provenance: general because there is no source to bind it to, which drains that field of meaning for the pages where it matters. kb/log.md fills with "task checked off" entries until the audit trail of what the wiki learned is unreadable. Lint findings about orphans and stale claims start firing on pages that are supposed to be short-lived. And a weekly pass over the task list trips the Mass-Update Gate every single time, which is how a gate stops being read and starts being cleared reflexively.

The GTD method this borrows from draws the same line for its own reasons: of its horizons, kb/ covers the two slowest - project support material and reference - and nothing faster.

Pattern 4: separate ownership, no synchronization

Four arrangements were on the table, and three of them fail in ways worth naming.

One layer is the case above. Export - the wiki writes a task list the tracker imports - means a checkbox ticked in the tracker is a tick in a view, while the truth sits in a file the operator was not editing; the two disagree immediately and silently. Bidirectional sync works, at the cost of an id mapping to maintain, a conflict-resolution rule to design, and a deletion semantics to decide - all of it machinery whose only job is to repair a split nobody needed.

What is left is separate ownership with no sync at all: the tracker owns the tasks, kb/ owns the project memory, and the single point of contact is the project's name. Nothing is mirrored, so nothing can drift out of mirror.

The join happens at read time, and stores nothing

Because there is no shared state, the connection between the two sides has to be made when somebody actually asks - which is what wikitool review does: it reads both sides, matches them on the case-normalized project name, prints what it found, and saves nothing. Not a cache, not a mapping file, not even a reports/ artifact.

That is the same posture search takes, and for the same reason: anything it wrote down would be a third copy of a state the two sides already hold, stale the moment either side moved, and the first thing to distrust in a report. A read-time join can be wrong about the present, but it cannot be wrong about the past, because it does not remember one.

One name, carrying the duties of an identifier

Reducing the coupling to a name is cheap, and it is not free. A name that joins two systems is an identifier, whether or not anything enforces it, so the design had to pick up an identifier's obligations explicitly: uniqueness is checked before a project is created rather than discovered later; a rename is a deliberate, infrequent operation that touches both sides in one pass; and nothing tries to re-match automatically behind the operator's back.

The last one is what makes the review's both-directional report matter. A tracker project with no page and a page with no tracker project are reported separately, as two findings. They are usually the two halves of one rename - and reporting them separately is exactly what turns a silent decoupling into a visible event, at the cost of the review occasionally saying the same thing twice.

Status has exactly one home

The sharpest consequence of the split is a rule that feels like a restriction: a kb/ page never summarizes its own task list. No "3 open items", no "next: call the supplier".

Two places claiming to know the current status is the failure mode the whole arrangement exists to avoid, and a summary is a copy with a slower clock. The page says what an initiative is - its goal, its participants, its durable state, why it is worth doing. The tracker says what is open right now. Anyone wanting the second reads the tracker, or runs the review.

This pays for itself somewhere unexpected: with the page carrying no task state, an agent has no reason to read the task list at all outside the weekly review. That is what keeps the command surface as small as it is - one read command and one creation command - rather than growing a full CRUD tree over somebody's todo list.

A finished initiative is a state, not a location

Archiving moves nothing. A completed initiative's page stays where it is and changes its state: value, because the moment an initiative finishes is the moment its page is most valuable - what was decided, what it cost, who was involved - and filing it away is how that gets lost.

The state field carries the distinction the review actually needs, which is not "open vs. done" but "does silence here mean something is wrong". An initiative that is deliberately paused looks identical, from the outside, to one that quietly stalled; only the operator knows which. Without a value for "paused on purpose", the review reports the same untouched initiatives every week, and a report that is mostly noise stops being read by the third week - which would cost more than the findings are worth.

Which tracker is a decision the stack does not make

The tracker is reached through a provider layer, and no instruction anywhere names which one it is. An instruction that said "open Super Productivity" would bake one instance's tool choice into the shared stack, and the next instance - a different context, a different employer, a different set of constraints - would have to edit prose to change a setting.

So the provider lives in configuration (.wikitool-tasks.json), the adapters live behind one protocol, and a capability the provider lacks surfaces as an ordinary tool error rather than as a paragraph of instruction explaining what this particular tracker cannot do. A provider that cannot create a project, for instance, stops and asks the operator to do it - the same posture the gates take, and for the same reason: better a visible stop than an invented workaround.