Skip to content
Back to Ideas 4 min read

One Command, Three Policies, Zero Duplication

One Command, Three Policies, Zero Duplication

Encoding the release, part 5 of 8.

We built the release in three separately shippable stages, in story order: ekohacks release preflight (the checklist as a command), ekohacks release cut (branch, bump, PR, CI, merge) and ekohacks release ship (Release, gate, publish, registry). Each stage worked alone, was tested alone, and was useful alone before the next one existed.

Then the final story composed them: ekohacks release 0.4.1, one command from a clean main and a written changelog entry to a verified version on npm. The story's one architectural sentence carried all the constraint: no stage's logic is duplicated — the command composes the three tested policies.

The composition layer turned out to be barely forty lines, and that is its whole virtue. It runs preflight and narrates the report; it hands the report to cut — which already knew how to refuse a red preflight, so the chain does not re-implement that judgement; it hands off to ship. The only decision that genuinely lives in the chain is the --yes policy from part 4: which pauses may answer themselves, and which one — the gate — never does. Composition is where cross-cutting policy belongs, and nowhere else.

The output was designed as carefully as the behaviour. The command narrates one line per step, in the past tense, so the terminal scrollback reads as the release's story:

  ok changelog entry
  ok version is new
  ok on main
  ok in sync with origin
  ok clean working tree
  ok lockfile registry
  ok package smoke
  branched release/v0.4.1
  bumped to 0.4.1
  committed chore: release 0.4.1
  pushed
  opened pr #198
  merged pr #198
  release v0.4.1 cut
  gate approved for run #16
  publish run green
  registry serves ekolite@0.4.1

That scrollback is the release record — what happened, in order, ending with the registry's confirmation. And because the record matters, it is pinned: the chain's happy-path test asserts the entire narration as one array, every line, in order. Change a word and the specification fails.

The stages did not disappear into the chain; they are still commands, and that is deliberate. The stories chose clean, named stops over resume logic — when a run stops part-way, the command tells you where and a human finishes by hand, using the standalone stages as the recovery vocabulary: finish the merge, then run ship alone. We believed that trade was right when we made it. Part 7 is the afternoon reality tested the belief, hard, from both directions.

Next: The First Real Run Said No.

More from Ideas

·8 min read

Inversion of Control Doesn't Need a DI Container

We started designing a dependency scanner, and its needs led us to Inversion of Control. It turned out we were already doing it, without a DI container.

A
Anastasios Orfanidis
·7 min read

Unknown Is an Answer

A stub that holds no documents could not say whether a change still matched a query. Letting it answer unknown named a case the real database has too.

·7 min read

The Inbox That Delivers Nowhere

Signing in by emailed code puts a mailbox on the critical path. How we use Mailpit on Studomia, how our tests read the code, and what one question taught us.