71. A feature exists only when its delivery is computed and every dimension passes
Context
ADR 23
made a product feature an object of the layer and every fact a surface says about it a
derivation — except one. Whether the feature is there was never derived. A feature file
declares status: stable, the site renders it, and nothing distinguishes a feature that is
merged, published, tested and linked from one that is merged on a branch nobody deployed.
The words used for that difference drift the way prose drifts. "Done" meant merged to one
worker, green on CI to another, visible on the site to a third. ADR 41
refused the same collapse for claims: a test file that exists and a test that ran are not
one state. The product had no equivalent, and the obvious one — a delivered: true or a
tested: true beside the feature — is a hand-written assertion that nothing produced and
nothing invalidates.
Decision
A feature exists only when every one of six dimensions passes, and each dimension is a verdict computed on every read:
EXISTS = ON_MASTER ∧ DEPLOYED ∧ PUBLICLY_VERIFIED ∧ REQUIRED_TESTS_CURRENT ∧ TEST_EVIDENCE_PUBLISHED ∧ UI_LINKED
- A verdict has three values, and unknown is never pass.
pass,failandunknown, each with the sentence that decided it and a remediation. A site that could not be reached is not deployed; a clone without the trunk is not on master. A conjunction over nothing measured is not a vacuous yes. - Delivery and development are different types.
DeliveryStateisdeliveredornot_delivered { stage, blocking }; the stage —not_implemented,implemented_on_branch,on_master,tested,deployed— exists only inside the second variant. A stage cannot be read as delivery because it cannot be put where delivery goes. The stage is a ladder: a rung is reached only when every rung below it passes. - Nothing is stored. No feature file, no ledger line and no generated artifact carries a verdict. The schema of a feature is unchanged.
ON_MASTERis read from git. The paths that implement a feature are derived from what its file already names: the source file of each capability module (the registry'ssource_path),lib/<command>.shof each shell command (the filebin/majordomussources to dispatch it), and theimplementationof each claim. The latest commit touching them atHEADmust be an ancestor oforigin/<trunk>, or the paths must be identical on both — a squash merge carries the content without the commit. A change only on the current branch isimplemented_on_branch.DEPLOYEDis an ancestry check against the public identity. The site serves the documentdeploy.identityof.ai/repo/ci/pages.yamlnames; the commit in it must contain the feature's trunk revision. The identity is fetched once per report, because containment is not the questionscripts/pages verifyanswers — it answers equality.PUBLICLY_VERIFIEDreusesscripts/pages, and does not re-derive it. Deployed, a clean identity (dirty: false),scripts/pages verify --timeout 0confirming the site from outside, andscripts/pages builtreading GitHub's own build of the published branch. Their exit codes are the vocabulary: 0 pass, 10 fail, 12 unknown.- The network is injectable.
MAJORDOMUS_DELIVERY_SITE_URLreplaces the site's address; afile://directory with an identity document is a site both this module andscripts/pages verifyread through the samecurl, so the behavioural cases never reach the network. - Two capabilities, one declaration.
delivery.report(every feature, ordered by id) anddelivery.feature(one), projected to the command line (delivery report,delivery show), HTTP, OpenAPI and MCP. Both are reads; both are waived from the benchmark as an external dependency and not cached.
Phase 1
This record lands the model and the three dimensions that need no recorded evidence.
REQUIRED_TESTS_CURRENT, TEST_EVIDENCE_PUBLISHED and UI_LINKED are computed as
unknown with the reason evidence model lands with PR #577. They are dimensions of the
type now so that phase 2 fills them instead of widening it — and so that, until it does, no
feature can be reported as existing. EXISTS is false for every feature on the day this
lands, and that is the true answer.
The public site does not show delivery yet. PUBLIC_FEATURE_FIELDS in src/product.rs is
the allow-list of what a public page may carry; the site's status slice is a later change
that adds to it deliberately.
Consequences
- "Is it done?" has one answer with a derivation behind it:
majordomus delivery show <id>. - A merged feature the site has not caught up with reads
on_masterwithdeployed: failand the served commit named — the silent lag thatscripts/pages builtwas written for becomes visible per feature. - The report reaches the network and GitHub. On a machine without either the publication
dimensions are
unknown, which is correct and slower to read than a cached answer would be; a cache here would answer about a publication that may have moved. - The path derivation is shallow, as ADR 41's is: a change to a helper no module, command or
claim names does not move a feature's revision. A feature that names nothing implementable
fails
on_masterwith the remediation to name it.
Alternatives rejected
status: deliveredortested: truein the feature file. The defect in one field: a person's assertion that nothing produced and nothing can invalidate.- A boolean
existsbeside a stage. It permitsexists: truewithstage: on_branch. Two variants of one type make that combination unrepresentable. - Deciding
DEPLOYEDwithscripts/pages verify --commit <revision>. It asks whether the site serves exactly that commit, so a feature merged before the last publication would read as not deployed. Containment is the question, and the one read it needs is the identity. - Treating an unreachable site as the last known state. It is the collapse of unknown into pass that this record exists to refuse.