How to Do Literate Programming How to Write and Audit a Note How to Do Verified Promise Driven Development
BraindumpTable of Contents
- The rules this note works under
- The export is the primary artifact
- The reader’s flow is sacred
- When a block exists
- Where blocks sit
- Rewrite, don’t patch
- Notes linking here
- Permalink
Table of Contents
- The rules this note works under
- The export is the primary artifact
- The reader’s flow is sacred
- When a block exists
- Where blocks sit
- Rewrite, don’t patch
- Notes linking here
- Permalink
- what
- literate programming combines a programming language with a documentation language, the main idea being to treat a program as a piece of literature, addressed to human beings rather than to a computer1.
The rules this note works under
how to write and audit a note
- what
- a note is a self contained org-mode file digging into one subject — a question to answer, or a topic to explore.
- how
- the title summarizes that subject, and a heading states it in full when the title cannot.
- who
- the agent that writes is the writer, the agent that audits is the auditor, and the human is the user.
- rule
- the user talks informally, and the writer lands what they mean in the note’s own words and form.
values that an ia agent must respect
How one reads a note
- why
- a human reads a note top to bottom, following one thread.
- rule
- the note treats its subject and nothing else — no detour, no
meta-commentary, no secondary justification, no iteration, no mistake, whatever the
circumstances.
- why: a writer drifts by default, and no one cares that the writer worked badly on the way.
- rule
- fewer words is the default.
- check:
note_hedgeslists the hedges and emphasis markers lost between a passage and its rewrite.
- check:
- rule
- readability counts2.
- rule
- one word per meaning — a second name for the same thing reads as a second
thing.
- how: when the user gives a second word for something already named, the writer asks which of the two to keep, rather than adopting the new one.
- rule
- past 7 siblings or 50 lines of body before the first subheading, go deeper —
headings under a parent heading, bullets into sub-bullets.
- scope: where a heading has no subheading, the body runs to the end of its section.
- scope: source blocks, export blocks and their results do not count toward the 50.
- rule
- a note whose outline has grown too long to hold in the head carries a table
of contents.
- why: the whole structure is then visible at a glance and every heading is one click away.
- how: in org-mode, a
#+TOC: headlines Ndirective placed where the overview belongs, or#+OPTIONS: toc:tto let the exporter render one. - scope: a short note with two or three headings does without it.
Where each piece goes
- scope
- an argdown map takes a graph — an objection, a premise two conclusions share, reasons that hold only combined — since bullet nesting already covers a tree.
- rule
- nothing is stated twice — inside a note the duplicate is cut, across notes it
is refactored out and pointed at.
- why: simple is better than complex3.
- rule
- the writer asks the user what to do with a cut piece.
- rule
- the writer reads or links another note only if the user agrees.
- rule
- the note being written is the only one edited.
The form of a bullet
- rule
- the narrative of a note is structured — every body line is a bullet of the
form
- <intention word> :: <claim>.- why: the writer pads when writing free-form text, so a list of bullets carries more than a paragraph of useless writer words.
- why: the structure also makes a flaw easier to find, and that is worth the cost in readability.
- how: the « intention word » is the single word before
::, naming what the line does; any word may serve. - scope: tables and footnote definitions keep their own form.
- rule
- one meaning per bullet.
- rule
- a reason the user holds is a
why, and it needs no other backing. - rule
- a
whyis written by the user.- scope: the writer rewrites its wording, never its meaning.
- rule
- a
whythe user has not explicitly accepted is never written.- why: a writer that writes a
whyunasked invents the user’s reason rather than recording it. - why: the user is the one who checks, a justification being easiest to fake and the writer worst-positioned to catch its own.
- why: a writer that writes a
What a checker can decide
- rule
- only these flaws are mechanical — a body line that is not a bullet, a bullet
with no
::, an « intention word » that is more than one word, a line of 120 characters or more with links counted as they render, a link that does not resolve, a heading with more than 7 children or more than 50 lines of body, a footnote whose text sits in the line instead of at the foot.- scope: one word is a run with no whitespace in it —
au-delà,peut-être,tl;dr— so a mark inside a word is part of it.
- scope: one word is a run with no whitespace in it —
- rule
- the rest is not mechanisable, and a silent checker is not conformance.
- check
note_mechanicsreports those flaws for an open note, and a count for each « intention word » in use.
How the file is typeset
- rule
- the user sets
#+filetags,#+KONIX_ORG_PUBLISH_KINDand every:CUSTOM_ID:, and the writer neither adds nor edits one. - rule
- a file is opened with the
ensure_file_openMCP tool. - rule
- the text under a heading is indented two spaces, as in this note.
- rule
- every line stays under 120 characters, text wrapping to fit.
- how: a link counts only its visible part, the target being invisible in the rendered line.
- scope: a keyword line and a table row cannot be wrapped and are exempt.
- scope: a line babel wrote is not the writer’s line and is exempt too.
- rule
- French prose carries the espace insécable where French typography asks for
one.
- how:
note_insecablesinserts U+00A0 before : ; ? ! » and after «.
- how:
- rule
- the writer strips the insécables before editing a typeset note, and restores
them after.
- how:
note_strip_insecablesruns, then the whole edit pass, thennote_insecables.
- how:
The audit loop
- rule
- the auditor is a different party from the writer, and judges without ever
editing.
- why: you are the worst-positioned reader of your own work.
- how:
spawn_auditorbakes these rules in.
- rule
- each audit covers one fix — the whole patched passage against every rule,
not « does this fix it? ».
- why: a batch is read at one pace, and the fix that needed a fresh look goes by with the rest.
- rule
- each audit reports every objective flaw found, in one verdict.
- why: subjective battles never end.
- rule
- each audit runs on the model the work needs — not Opus for a straightforward command.
- rule
- the writer asks the user to confirm a new term before using it.
- why: writers coin very poor terms.
- rule
- when a fact changes, the writer asks rather than assumes.
- why: the user may change their mind.
- rule
- a contested flaw escalates to an adversarial debate.
how to do verified promise driven development
- what
- a promise is a claim about what the program does for whoever uses it.
- what
- a story is the sequence of whats somebody really performs.
- what
- a test is the file on disk that runs a story.
- how
- the code holds the promise, and the test measures that it still holds in time.
The promise and its measure
A test asserts a promise
- rule
- a story names the promises it asserts.
- why: everything else a test could check is a measure of a promise the program makes.
- rule: a story with no promise to name is deleted rather than filed.
- rule
- the promise is written down, and the test only measures it.
- why: a promise legible only as a test name is unreadable to the one it was made to.
- why: the writing states the promise, the test holds it to time.
- rule
- the promise and its test stand or fall together, in both directions.
- why: a promise held makes its test green, so a red names the promise that broke.
- why: the other direction must be proved — a green means the promise holds only if breaking the promise would redden the test.
The promise decides what is measured
- rule
- a test tries the inputs the promise covers, not every input the code accepts.
- why: an input the interface never presents measures a promise nobody made.
- rule
- the promise says when the work is done, never the coverage number.
A reasoning links the stories to the promise
- rule
- what links a promise and its stories is a reasoning, written beside the
promise — these stories passing entails this promise held.
- why: a red test then traces back to the promise that broke.
- why: if unwritten, the next reader guesses the link, and a gap looks like a choice.
Stories are what matter
- rule
- we tell the stories, never the feature.
- why: a use comes in whole stories — triaging a morning’s photos, running the cabinet frame, picking a few shots to send — and those stories are the promises the program makes.
- why: a test written per feature asserts a promise nobody holds, since nobody opens a program in order to exercise one feature.
- what
- when described in text, the desired behaviour is a what
- what
- when described in text, the chosen technical approach is a how
- rule
- stories describe whats in the order the person performs
them, carrying state from step to step.
- why: a chain of gestures on one open program is what using it looks like, and an isolated one-gesture run is a path no human takes.
- rule
- every story is one somebody really lives.
- how: the user tells the stories and the writer never invents one.
- how: the writer writes the what, the how and the tests, and assembles them into the stories it was told.
- why: there are very few of them, because a story is a whole real use rather than a feature.
- rule
- between them the stories reach every promise the program makes — that reach is
the semantic coverage.
- why: a promise no story reaches goes unmeasured.
- how: the writer finds the gap and must propose it; the user decides.
- how: a what that fits no story is that signal — either one is missing from the set, or nobody does that thing, and which it is is the user’s call.
- rule
- ground walked twice is cut.
- why: overlapping stories cost CPU, RAM, time and money
- how: the writer suggests the stretch to cut and the user cuts it.
- scope: stories overlap a little whatever happens, each one opening the program and loading the same first screen, and that much is irreducible.
- scope: the user may bend a story so that it stops short of showing the whole
thing, when the reasoning shows the trimmed part is measured elsewhere.
- why: what is protected is semantic coverage, not the walking of every path.
- rule: the reasoning linking promises to stories capture the cut and indicate how a set of stories is fulfilling a given promise
The surface and the data
The promise is made at the seam the user touches
- rule
- whoever uses the work decides where the seam is — the end user of an
application, the programmer calling a library.
- why: the promise is made at that interface; below it is the how.
- rule
- assertions probe the observable surface — visible text, public API,
exported artifact, ARIA role — not internals like private stores, test-only hooks
or implementation-selector classes.
- why: an internal is the how, no user should care about the fact that how works, but people care that the promise is fulfilled.
- example: in web dev, the suite reaches for
get_by_role,get_by_labelandget_by_placeholderrather than CSS selectors that encode the current DOM.
- rule
- the code carries nothing that exists solely for the test.
- why: an affordance that exists only so a test can reach something serves no one who uses the program.
- example: in web dev, a
data-testidor an attribute added for the suite — the final user never reads a test id. - how: when the program turns out hard to test at the seam the user touches, the
difficulty is real information, and the fix belongs in the design.
- why: usually the interface is just as unclear to the user.
A test seeds the world it reads
- rule
- the test world must be as close as possible to the real life
- why: the product ends being used in real life, promises tested in a different env but that don’t work in real life are worth nothing.
- rule
- when possible, the real world is duplicated for the test purpose
- example: if possible a pg_dump of the production database gives a good sandbox to check the promises.
- rule
- but a test creates the fixtures it depends on
- why: it helps reproducible result by contrast to using the real world.
- why: tests must assert there promises while not being disturbed by the changes of the real world
- rule
- the user decides the properties of the test world, not the writer
- why: the writer is tempted to create a dummy world that has nothing to do with real life to make tests pass
When it goes wrong
Test, don’t patch
- what
- a bug is a promise found broken.
- rule
- every fix starts from a red, added to an existing story or by writing a new story. Observed red, then made green by the smallest change that satisfies it.
A flake is a diagnosis, not a knob
- rule
- an intermittent red is measured before any limit is touched.
- why: widening a timeout is hiding the symptom, not fixing the problem
- why: the expected time usually sits far under the ceiling, so the failure is a transient — a CDN stall, a resource race — to remove (e.g. by a fixture) or isolate.
- rule
- a timeout is raised only when the measurement shows the expected time
nearing it.
- rule: the new number is justified in a comment.
- rule
- any limit change must be validated by the user
- rule
- flakiness that is not obvious to fix gets meaningful logging.
- why: it helps investigate the next time the flakiness occurs.
- rule
- moving on a flaky test is the choice of the user, never the one of the writer.
The cycle
- rule
- the cycle is the unit of change.
- why: each step exists because the previous one is provably insufficient.
- why: skipping a step leaves a gap the next regression will fall into.
- rule
- the baseline run covers THE WHOLE SUITE, not a subset.
- why: a subset baseline says nothing about pre-existing reds of the whole baseline.
- rule
- the baseline run is gated like any other action.
- rule
- a codebase that is red and not flaky has its tests fixed before the task at hand resumes, unless the user explicitly asks otherwise.
- rule
- a promise is measured by the suite the cycle runs, and by nothing else.
- why: a measure taken anywhere else is one no cycle can cite.
- rule
- the cycle is the succession of the following sub headings
1. focus on one promise at a time
- rule
- only one promise is fulfilled during a cycle
- why: focusing on several creates a mess hard to untangle
- rule
- the other known promises are still taken into account when writing one
- why: sometimes, we know that what we are doing is going to be put into question or factorized by a future promise
- why: there are several minimal ways to fulfil a promise, choosing the one of least future friction is preferable
2. Red proves the test
- rule
- every test must be observed RED for the good reason at least once
- rule
- a test that passes for the wrong reason is worse than one that fails for
the wrong reason.
- why: a wrong-failure test still points at a real fault to hunt; a wrong-pass test sits green and hides a gap the suite reports covered, and its green is indistinguishable from outside, so it survives every whole-suite run.
- rule
- the test is written first and observed red before any production code
changes.
- why: that failure is what establishes that the test measures the promise it names.
- rule
- the failure mode and message are part of the test’s value.
- rule
- provided a given code, a test either always fails or always succeeds always for the same reasons
- why: a flaky test cannot be trusted
- rule
- a test that was restructured rather than written is observed red again, by
breaking the promise it names.
- why: a restructuring starts and ends green, so the moment that would have shown the test still bites never arrives (see the wrong-pass rule above).
- why: the failure names which test catches the break, so one that has drifted to where an earlier test already covers it is visible as well.
- how: break one behaviour at a time, in the production code, and require the named test to be the one that fails; a break nothing catches is a test that claims a promise it does not read, and a break something else catches first is a promise measured elsewhere.
- rule
- a promise that cannot be broken from where the suite stands is recorded as
such, in writing, with the reason NEVER without the user gating the decision.
- why: otherwise it is indistinguishable from one nobody has got round to breaking, and the next reader spends the effort again.
- why: the reason is itself a finding — it usually names a boundary the suite cannot reach past, which is worth knowing before trusting what lies beyond it.
3. Minimum to green, then a test before the next line of code
- rule
- new behaviour appears under a failing test, and the next line of code waits
for the next test.
- why: code beyond what the failing test demands is untested by definition and therefore unwanted.
- why: the coupling keeps the suite a faithful description of the system, every branch tracing back to a test that was once red.
- scope: a refactor pass adds structure no single test motivates.
- rule: an anticipated edge case is written as the next failing test, not as a preemptive guard in the current change.
4. The whole suite measures the whole contract
- what
- the contract is every promise the program makes to whoever uses it.
- rule
- a change is verified only when the whole suite is green.
- why: the new test going green proves its own promise realised, and says nothing about which of the others the change broke.
- why: implicit dependencies between modules — shared state, cached values, ordering assumptions — surface only when every test runs.
- why: the test you left out is the one most likely to catch the regression you did not predict.
- why: a green-to-green refactor can still flip a subtle ordering, a fixture, or a shared helper.
- why: what each run guards against is unknown ahead of time, which is what makes it a regression rather than an anticipated case.
5. Refactor lives under green
- rule
- structural change runs under a green suite.
- rule
- behaviour is held fixed by the tests, and structure is the only thing
allowed to move.
- why: mixing behaviour change with structure change loses the bisect signal — a test going red mid-refactor no longer tells you whether it caught a regression or reacted to an in-progress edit.
- rule
- the tests are refactored with the same discipline.
- why: tests are code, and they drift.
- why: the refactor-tests step is the only place in the cycle where test debt can be paid without losing signal, the suite being green on both sides of the edit.
- why: a suite that takes too long stops being run.
- why: a suite full of duplicated assertions gives false confidence that semantic coverage is broader than it is.
The export is the primary artifact
- what
- a code block is the technical translation of a bullet’s claim.
- rule
- a code block sits a glance away from the bullet it translates.
- check
- remove all code blocks mentally, and the remaining text still forms
coherent and complete reasoning.
- why: this is part of what makes the note literate — code and reasoning interleaved, not inserted side by side.
- how: a gap means either a bullet is missing or an existing bullet was paraphrasing a block rather than advancing the reasoning, and the heading is rewritten accordingly.
- how: the auditor reads the narrative-only version and judges whether the
narrative fulfills the stated need.
- why: narrative coherence has no binary signal, so that reading catches what a passing suite cannot.
- rule
- a code block carries the
:exportsheader the reading needs.
When a code block appears in the export
- rule
- a code block appears in the export only when the narrative talks about it.
- why: re-showing a block the reader has already seen adds nothing, even when the next block depends on it.
- scope: repetition is justified when seeing the surrounding code genuinely helps the reading.
- how:
:nowebisyesorno-exportdepending on what makes the code readable.
The reader’s flow is sacred
- rule
- what breaks the flow — a technical derivation, a self-contained construction whose result the reasoning will consume — moves to its own heading or note, linked from the reasoning where its result is used.
- rule
- an ungrounded name breaks the flow wherever it appears — narrative, comments,
docstrings, function names, variable names, symbols, any identifier in any form.
- why: the reading flow does not care which fence a name sits behind.
- how: where a forward-reference to a code-level term — a field, a function, a
class — hides a readback, removing the term fixes both at once.
- why: the narrative was reaching for the implementation when it should have been naming the need.
- rule: a reference in the exported flow is grounded in the exported flow.
- why: content kept out of what the reader will read does not exist for that reader, so grounding that lives only there leaves the reference ungrounded forever.
- how: either the grounding moves into the export, or the reference leaves it.
- rule: vocabulary lives in the narrative — the states a field can take, the thresholds that govern behavior and the constants that pace the system are named there, not in a type comment listing valid values, a magic number setting a tempo, or a literal fixing a bound.
- rule
- the narrative carries the reasoning a picture cannot state — the motivation, the texture, the judgment.
- rule
- the narrative stops re-describing what a picture states better.
- why: a picture delivers in one glance what a bullet hands over clause by clause for the reader to reassemble.
- rule
- literate also means literary — the note is written to be read, not recited.
- why: a note that is technically clear but emotionally flat loses readers as surely as one that breaks flow with detours.
- rule
- exported content links only to exported content.
- why: a link from the export to what is not exported is a dead link.
- scope: content that is not exported links wherever it likes.
When a block exists
- rule
- a block exists only where the narrative has made it necessary.
- why: a block the narrative did not lead to means a piece of reasoning is missing.
- how: the why, the reason for the choice, stays in bullets, never in a code
comment.
- scope: what remains in code is at most a one-liner annotating the specifics of the line below.
- how: the what is translated into a test.
- how: the how is translated into code.
- rule: the narrative states the problem or need, never a readback of the code.
- rule: a what is never stated without its why.
- why: a narrative that paraphrases the block is duplication, not justification, and a note listing “this does X, that does Y” hands over facts no one asked for.
- how: the note moves in a single register — I need to meet this objective, so I will do this, and so I will do it this way — need, then intent, then technique.
- scope: where the gap between intent and form is wide enough that a short readback bridges it, the readback stands as a translation aside.
- scope: this binds the reading, not the source — tangle scaffolding lives
invisibly, usually under a
:noexport:heading or marked:exports none, and needs no motivating narrative because it is not read.
- rule
- the code is carved along its own joints, never along the narrative’s.
- how: noweb reassembles the pieces at tangle time, so the two structures owe each other nothing.
How a block is cut
- rule
- the reading flow is the only criterion for how the narrative and code are
sliced against each other.
- scope: one block per symbol, several symbols per block, several blocks per symbol are all legitimate.
- how: the slicing has failed when the reader pauses on a function and asks “wait, what is this for? I was reading about something abstract and I don’t see the connection.”
- how: boilerplate — every getter and setter of a Java bean, say — does not
get a bullet each.
- why: that would drown the reader in motivation no one needed.
- how: a block dropping several unrelated functions under a single vague
bullet calls either for more bullets or for splitting the block,
whichever restores the flow.
- why: it leaves the reader unmoored.
- rule
- a block is taken in at a glance — past 30 lines, it splits.
- why: past that the reader loses the thread between the bullet that motivated the block and the code that is supposed to translate it.
- how: the block splits along the seams the narrative already has, each responsibility that was introduced as a distinct idea becoming its own block with a bullet of motivation just before.
- how: a block that resists splitting means the narrative has collapsed several ideas into one, so the narrative is expanded first and the block splits naturally.
Translation asides
- rule
- where the intent is clear but its shape in code is surprising, a short
bullet acts as a translator’s note — “we want X, but in code this is written as
Y because Z”.
- scope: this explains the gap between intent and form, not what the code does.
- how: an aside is clearly identifiable as such, introduced by something like “In practice,” or “Under the hood,”.
- how: an aside that grows beyond its role, explaining more than the translation
gap, moves to its own note the narrative points at with a short link.
- why: it would otherwise break the reader’s flow.
- rule
- asides stay rare.
- why: too many of them pollute the note.
- rule
- needing an aside is read as a diagnostic before it is written.
- why: sometimes it reflects a genuine gap between what human language and code can express, which is what the aside is for.
- why: it can also reveal that the code is poorly organized, the surprising shape that needs a translator’s note simply being the wrong shape.
- how: where the shape is wrong the code is refactored rather than papered over with an aside.
Where blocks sit
- rule
- the stories come first, in a heading of their own.
- why: the reader meets what the program is for before meeting its parts, and a block that is only a limb of a story cannot be read until the story binding it has been.
- rule
- the test, the what, comes before the code, the how.
- why: that is how we talk to each other — the desired behavior first, then the technique used to achieve it.
- how: the narrative states what is needed and what we are going to do — “we need
the list to reject a duplicate,” “so we block creation” — and the block just
below is that need made visible, code that happens to be a test.
- why: the word test barely surfaces in the reading, and the reader meets a promised behavior and, right under it, the code that pins it down.
- how: a test standing apart, not flowing from an explicit assertion in the narrative, means a bullet is missing.
- scope: test-specific machinery — a tricky fixture, an unusual harness step — gets a bullet only when it is genuinely hard to follow, which is rare.
- rule
- a block is laid out against the narrative that promises it.
- rule: one bullet promises one what, and one test block checks it.
- why: a test block checking several whats under a single bullet breaks the narrative flow, and the reader cannot trace which bullet promised what the test is checking.
- rule: the bullet that promises a what is the one above the block that pins it.
- why: when a block is only a step — it cannot fail unless an earlier one fails with it — the promise it appears to pin is pinned upstream, so the narrative that named it here has sent the reader to the wrong bullet.
- rule: each what stays a visible block in the story heading that motivated it.
- how: the scattered blocks tangle into the test file.
- rule: one bullet promises one what, and one test block checks it.
Rewrite, don’t patch
- rule
- when something forces the note to change — a bug, an oversight, a change of
mind, a breaking change in an upstream library, a refactor that obsoletes an earlier
choice — the affected narrative is rewritten so it reads as if the issue never
existed.
- why: adding a test and an explanatory bullet describing the mitigation leaves a visible scar rather than restoring the narrative.
- how: the result is not a narrative that fixes something but one that was always correct, betraying no trace of the path that led to it.
- rule
- a scar is retrospective — a trace of a revision already applied, a debate
already settled.
- how: the distinguishing test is tense — a bullet describing a fix already made is a scar and is rewritten, one naming an open question the reader should know about is a caveat and is kept.
- scope: prospective language is not a scar — honest framing of a value still to validate empirically, of an explicit test plan, or of a guard-rail against a tempting wrong path.
- rule
- when reasoning leaves the code — a justification moved to the narrative, a
constraint absorbed into a cleaner design — the code that only carried it leaves
as well.
- how: an empty body, a one-armed conditional, a vestigial helper is each a fragment whose work now lives elsewhere.
- why: the artifact then reads as if neither narrative nor code remembered the revision.
Notes linking here
Permalink
-
Donald E. Knuth on Literate Programming (CSLI Lecture Notes no. 27, 1992), at https://www-cs-faculty.stanford.edu/~knuth/lp.html: “Literate programming is a methodology that combines a programming language with a documentation language, thereby making programs more robust, more portable, more easily maintained, and arguably more fun to write than programs that are written only in a high-level language. The main idea is to treat a program as a piece of literature, addressed to human beings rather than to a computer.”
↩︎ -
« Readability counts. » — PEP 20, The Zen of Python, Tim Peters. ↩︎
-
« Simple is better than complex. » — PEP 20, The Zen of Python, Tim Peters. ↩︎