Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ The test that an edit actually *reduced* redundancy rather than moving it: **net

Minimization holds only if each fact lives in exactly one place. The recurring violation is **nicknaming — a second name for one concept** — which duplicates work at the meaning layer and, since we generate from concepts, duplicates it again in everything derived. A fork always gets consolidated later, so it is a correctness concern, not a style one. Until it is enforceable this is diligence: faithfully model the accepted universal frameworks (classical logic, set theory, algebra), and in `extdeps/` the real upstream spec — cite the source, keep its real names, declare its version, model what the API actually returns.

Single authority applies to meaning, not only to code symbols. Nicknaming gives one meaning two names; its dual, a **meaning fork**, gives one name two materially different meanings. Product names, service names, tier names, status names, and terms in every layer are semantic carriers: within one naming surface and one declared effective version or epoch, holding the name constant may not silently change the obligations, quality floor, refusal behavior, billing consequence, or remedy — while the same spelling in explicitly distinct scopes, or across a declared version transition, is legitimate reuse. A materially different contract needs a materially different name.

Two corollaries. The import graph's only structural law is **acyclicity**: the `std`/`extdeps`/`compiler`/`workflow` folders are browsing conventions, not a direction rule. And a fact's home is its *layer*, not its file — paths are discriminators, not gospel.

The load-bearing consequence is that **interface, realization and policy are three facts, not one row.** For a dependency: the *interface shape* is what `extdeps/` owns; the *transport* (shell, REST, SDK) is a §2 Realization handler bound to that shape, one of N, never a fact about the dependency; and *business policy* — which base ref, which flag, an idempotency protocol the dependency does not provide — is a workflow fact, and modeling it in extdeps is a layer inversion. The tells are mechanical: policy has leaked when an argv carries a literal it should receive as a parameter; transport has fused when one operation is forked once per transport instead of one shape with N bound handlers. Its direction is always the same: **the dispatch that selects a realization is itself realization**, so it sits peripheral, never in the interface.
Expand Down Expand Up @@ -108,6 +110,8 @@ Four meta-obligations make the ladder operational:
3. **No silent regression.** A change may lower a rung only by declaring previous rung, temporary rung, reason, bounded population, and restoration trigger. A compatibility exemption is not bootstrap glue; it is a visible safety regression with a finite runway. **The trigger must name the CAPABILITY, not an artifact that would contribute to one** — a declared drop is retired by its trigger and by nothing else, so a trigger naming less than the capability it restores will be satisfied while the capability stays dead. Where a trigger names an artifact, the row must state what that artifact must be SUFFICIENT FOR. The review tell is a grain mismatch between the loss sentence and the trigger sentence: a plural loss with a singular trigger, a corpus loss with a per-module trigger, a route loss with a single-call trigger.
4. **Dissolution on climb — production handling only, never the evidence.** A climb deletes the redundant lower-rung *production* machinery it obsoletes, but the class's discriminating RED and positive control **remain enrolled** as the executing evidence that the higher rung stays real. An expecting-red probe that greens when its wall lands flips to a permanent regression control; it does not retire.

At a service boundary, rung honesty has a commercial consequence: a dimension may remain opaque only above a falsifiable quality floor with a named consequence. A claim that can change billing, trigger a remedy, or require refusal is a contract; without such a consequence it is marketing and establishes no rung. Delivery below the floor must refuse or discharge the remedy; a materially different delivery may be admitted only as its own named and priced product — a different contract subject, not a declared drop of the premium one; and a temporary loss of the ability to verify or enforce a floor is a §4b(3) declared drop on that same subject, which may force the commercial path to refuse and never authorizes silent below-floor delivery. Deviation is allowed; silence is refused.

Every newly discovered error class — incident, review finding, runtime exception, falsifier divergence — files or updates one row: invalid state, harm, distinguishing facts, rung found at, ceiling with reason, next trigger. Declared drops are rostered in full — previous rung, temporary rung, reason, population, restoration trigger — in [docs/design-ledgers.md](docs/design-ledgers.md), authority `gunbc.rung_drop`. A drop is retired BY ITS TRIGGER AND BY NOTHING ELSE, so the trigger is the whole check. The ones standing today:

- **CI required-run composition** — declared 2026-08-15
Expand Down Expand Up @@ -144,6 +148,8 @@ The same demand for an independent referent governs a test's oracle. **A merge-b

A third named trap, the subtlest because it wears this section's own name: **the absorbing fallback — degradation is disguised fail-open.** When a mechanism cannot compute its precise answer, the tempting arm substitutes the *superset*: can't compute the affected set → rerun everything; cache key uncertain → scan all keys. Nothing is missed, so the arm gets labeled fail-closed — but it is **⊤-as-answer conflated with ⊤-as-ignorance**, and it fails open twice. On safety: absorption destroys the only signal that the precise mechanism has a deficit, so the deficit never ranks for fixing and the anemia compounds. On cost: the fallback is denominated in the *corpus*, not the *change*, so it grows until the budget breaks instead of the build. The confidence threshold that selects such an arm is a smuggled heuristic, so its existence *locates* the anemic modeling it papers over. **The rule, and the review tell: a failure arm must refuse, never widen** — every degradation a typed, located, countable diagnostic. Two neighbors are not this pattern: a structural over-approximation computed *as* the answer, and a deliberate interim fallback that is loud, budget-bounded, and lands with its dissolution trigger.

When §2's deferred cost is moved from the actor that accepted or caused it onto another principal, it becomes **externalization**. A risk intermediary or cost-causing actor fails open across an accountability boundary when it quietly re-exports an accepted risk or leaves a caused cost unpriced while preserving the apparent name, price, or contract — onto customers, employees, sellers, liquidation buyers, neighbors, or future maintainers. There are only two honest arms: absorb the risk and reserve for it, or expose the transfer as a separately named and priced contract; a materially degraded service is therefore its own product. Keeping the old name, price, or contract while another principal bears the changed burden is **externalized degradation**.

A corollary on the refusal itself: **no escape hatches** — a toggle whose only effect is "proceed as if the refusal had not fired" re-opens the arm §5 just closed. The operative discipline is the **factory model**, a merge requirement rather than a preference: a deficit stops the line; the stopped line is analyzed before it restarts; the only sanctioned second mode is a stopped-line audit that replays the run to ledger every deficit for that analysis — it reports, it does not green. **Review bar:** a diff that lands a non-fail-closed failure arm — a silent widen, a fabricated default, an uncounted degradation, an escape hatch — is a **hard reject**, regardless of what else it delivers. The reviewer's three questions: does the line stop? is the stop typed and located? does analysis precede restart?

The same arm exists at authoring time: **the workaround — an absorbing fallback executed by the author.** When the obstacle is the substrate itself — a parse error you do not understand, a check that will not green — the tempting move is to route around it: a different spelling, a dodged codepath, a "for now". The concealment is identical, except the concealed deficit is usually in the *language layer*, precisely what §6 says to root-cause first. So: **noticing you are implementing a workaround IS the line-stop signal.** Back up, reassess, root-cause it or flag for help.
Expand Down Expand Up @@ -194,6 +200,8 @@ One row per class, each carrying its recognition rule and its receipts, in [docs
- `diagnostic_name_mechanism_silent`
- `identity_absent_graph_traversal`
- `surface_shorthand_preempts_resolved_identity`
- `meaning_fork`
- `externalized_degradation`

## Building & checks

Expand Down
Loading
Loading