Allow progressive insight, and apply two to the bus record
A record can assert a fact that goes stale while the decision it supports stays right. Superseding for that buries a sound record under a second one and makes every reader work out which is live. So a correction of fact is now made in place, marked and dated, with the old wording quoted — bounded by three conditions and checked by records.py, which fires on an unmarked, undated or back-dated note. Judgements still supersede. Applied to 0115: no conformance suite exists to recapture, and the full genesis bed cannot run until the links exist. Designs 25 and 28 follow.
This commit is contained in:
@@ -284,6 +284,59 @@ def check_numbering(failures, records):
|
||||
)
|
||||
|
||||
|
||||
def check_progressive_insights(failures, records):
|
||||
"""A correction made inside a record is marked and dated, or it is a silent rewrite.
|
||||
|
||||
A record may be corrected in place when a *fact* in it went stale and the decision still
|
||||
stands (`02-DECISIONS/README.md`, "Progressive insight"). The whole safety of that allowance
|
||||
is that the correction is legible in the record rather than only in a diff nobody reads, so
|
||||
the form is what is checked here: every mention of an insight is the marker, the marker
|
||||
carries an ISO date, and that date is not earlier than the decision's own — an insight
|
||||
predating the decision it corrects is a copied marker, not a correction.
|
||||
|
||||
What this cannot check is an edit made with no marker at all. Nothing mechanical can; that
|
||||
one is the reviewer's, reading the diff. The check keeps the *marked* path honest so that an
|
||||
unmarked change stands out as the anomaly it is.
|
||||
"""
|
||||
phrase = re.compile(r"progressive insight", re.I)
|
||||
marker = re.compile(r"\*\*Progressive insights?\s*[\u2014\u2013-]\s*(\d{4}-\d{2}-\d{2})\.?\*\*")
|
||||
loose = re.compile(r"\*\*[^*]*[Pp]rogressive insights?[^*]*\*\*")
|
||||
iso = re.compile(r"^\d{4}-\d{2}-\d{2}$")
|
||||
|
||||
for number, record in sorted(records.items()):
|
||||
text = record["text"]
|
||||
if not phrase.search(text):
|
||||
continue
|
||||
decided = str(record["front"].get("date", ""))
|
||||
good = [(m.start(), m.end(), m.group(1)) for m in marker.finditer(text)]
|
||||
|
||||
for m in loose.finditer(text):
|
||||
if any(s <= m.start() and m.end() <= e for s, e, _ in good):
|
||||
continue
|
||||
failures.add("insights", rel(record["path"]),
|
||||
"a progressive insight is not in the dated marked form "
|
||||
"'**Progressive insight \u2014 YYYY-MM-DD.**': %s" % m.group(0))
|
||||
|
||||
for _, _, stamp in good:
|
||||
if decided and iso.match(decided) and stamp < decided:
|
||||
failures.add("insights", rel(record["path"]),
|
||||
"a progressive insight dated %s predates the decision (%s)"
|
||||
% (stamp, decided))
|
||||
|
||||
covered = [(s, e) for s, e, _ in good]
|
||||
for m in phrase.finditer(text):
|
||||
if any(s <= m.start() and m.end() <= e for s, e in covered):
|
||||
continue
|
||||
line = text.rfind("\n", 0, m.start()) + 1
|
||||
if text[line:m.start()].lstrip().startswith("#"):
|
||||
continue
|
||||
if loose.search(text, line, text.find("\n", m.end()) + 1 or len(text)):
|
||||
continue
|
||||
failures.add("insights", rel(record["path"]),
|
||||
"'progressive insight' appears unmarked; a correction is marked and "
|
||||
"dated, or it is a silent rewrite")
|
||||
|
||||
|
||||
def check_status_against_code(failures):
|
||||
"""A design document naming specific code may not still call itself `designed`.
|
||||
|
||||
@@ -325,6 +378,7 @@ def main():
|
||||
check_numbering(failures, records)
|
||||
check_topics(failures, records)
|
||||
check_status_against_code(failures)
|
||||
check_progressive_insights(failures, records)
|
||||
print(f"records: {len(records)} decision records checked")
|
||||
return failures.report()
|
||||
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
A design changes only through a decision.
|
||||
|
||||
1. Write the decision record. If it reverses an earlier one, the earlier record's `status:`
|
||||
becomes `superseded-by: 02-DECISIONS/NNNN-....md` — **its text is never edited**.
|
||||
becomes `superseded-by: 02-DECISIONS/NNNN-....md` — **its reasoning is never rewritten**. If the
|
||||
earlier record is sound and only a *fact* in it went stale, that is a **progressive insight**,
|
||||
corrected in place and marked in the record rather than superseded
|
||||
([`02-DECISIONS/README.md`](../../02-DECISIONS/README.md)).
|
||||
2. Edit the to-be design document and set `updated:` to today.
|
||||
3. If the amendment came from an issue, set that issue's `amended-design:` to the document
|
||||
path.
|
||||
@@ -54,4 +57,5 @@ Implementation state is a third axis, independent of both design and decision.
|
||||
|
||||
- Do not move a to-be document into `00-as-is/`. Write the as-is document; both stand.
|
||||
- Do not edit an as-is document to describe an intention. That is what the to-be layer is for.
|
||||
- Do not change a decision record's meaning. Supersede it.
|
||||
- Do not change a decision record's meaning. Supersede it. Correcting a fact it got wrong, while
|
||||
the decision stands, is a progressive insight — marked and dated in the record, never silent.
|
||||
|
||||
@@ -61,8 +61,9 @@ may not disagree about* still describes the bus being replaced.
|
||||
waits for the one after it. The cutover remains a single rollout** — dividing the build does not
|
||||
divide the bus.
|
||||
|
||||
**Step 1 — genesis raises the broker.** The `nats` module and a mesh raised on it from nothing.
|
||||
This is built and proven even though the mesh it is for will never travel this path, because
|
||||
**Step 1 — genesis raises the broker.** The `nats` module, and genesis placing it in the
|
||||
foundation. This is built and proven even though the mesh it is for will never travel this path,
|
||||
because
|
||||
genesis is where the foundation is *defined*: the only place the mesh comes from nothing, and the
|
||||
definition every other path is measured against. A genesis path that exists only on paper is one
|
||||
nobody discovers is wrong until there is a second mesh.
|
||||
@@ -78,8 +79,9 @@ renamed by every change the seat exists to survive.
|
||||
protocol, an SDK is an implementation of it in one language and nothing more, the protocol is split
|
||||
per capability, and conformance is executable fixtures per capability rather than prose. What
|
||||
changes is what the specification specifies. Design 19's wire section is rewritten from exchanges
|
||||
and queues to subjects and streams; the fixtures are recaptured on NATS; every SDK claims the
|
||||
capabilities it passes, and a language may arrive with connection and events alone.
|
||||
and queues to subjects and streams; the conformance suite is built — first against the bus the
|
||||
mesh has, then restated on NATS; every SDK claims the capabilities it passes, and a language may
|
||||
arrive with connection and events alone.
|
||||
|
||||
**The SDK gains no conveniences in the process.** [ADR 0039](0039-what-the-sdk-holds-and-refuses.md)
|
||||
refuses frequent-and-cascading code in the shared library, and ADR 0074 restates it — an SDK is
|
||||
@@ -119,17 +121,48 @@ is still on AMQP throughout. The bus moves on one day, at the end, once.
|
||||
## How it is checked
|
||||
|
||||
- **Per step, a bed, and the bed named in design 25 §10 against the step it belongs to.** Step 1:
|
||||
a mesh raised on NATS from genesis. Step 2: the broker adopted into a mesh already running, and
|
||||
a second holder of `mesh-broker` refused at resolution. Step 3: the conformance suite passing per
|
||||
capability, on NATS, for every SDK that claims it — and a module built before the binding serving
|
||||
its tools unchanged. Step 4: each converted flow proved against the behaviour it replaced. Step 5:
|
||||
the cutover bed, then the rollout with every node reporting.
|
||||
a mesh raised from nothing has the server standing, its streams asserted and every account
|
||||
composed from the manifests — no mesh traffic on it yet. Step 2: the broker adopted into a mesh
|
||||
already running, a second holder of `mesh-broker` refused at resolution, and nothing routed to it.
|
||||
Step 3: the conformance suite passing per capability, on NATS, for every implementation that
|
||||
claims it — and a module built before the binding serving its tools unchanged. Step 4: each
|
||||
converted flow proved against the behaviour it replaced, **and the full genesis bed** — a mesh
|
||||
enrolling, holding a push, and rolling out an upgrade on NATS. Step 5: the cutover bed, then the
|
||||
rollout with every node reporting.
|
||||
- **Step 3 is not done when the code runs.** It is done when the fixtures match byte for byte
|
||||
across implementations, which is ADR 0074's own test and the only one that catches two SDKs
|
||||
quietly ignoring each other.
|
||||
- **A step that cannot name what its bed proves is not a step**, and is divided further before it
|
||||
is started.
|
||||
|
||||
## Progressive insights
|
||||
|
||||
Corrections of fact made in this record after it was accepted, under the rule in
|
||||
[`README.md`](README.md). The decision — five steps, each proved, one rollout — is untouched by
|
||||
both; each corrects something this record asserted about the *state of the code*, which nobody had
|
||||
measured when it was written.
|
||||
|
||||
> **Progressive insight — 2026-09-26.** *There is no conformance suite to recapture.* This record
|
||||
> said step 3's "fixtures are recaptured on NATS", and design 19's wire was described as specified
|
||||
> and conformed. Measuring the four repositories found no conformance fixtures in any of them:
|
||||
> [design 22](../03-DESIGN/01-to-be/22-the-work-ahead.md)'s Phase 1.2, which would have built the
|
||||
> suite, is still open. Step 3 therefore **builds** it, and builds it first against the bus the
|
||||
> mesh has — a suite born on the new bus certifies whatever the new bus happens to do. The step's
|
||||
> place in the order, and ADR 0074's model it implements, are unchanged.
|
||||
|
||||
> **Progressive insight — 2026-09-26.** *The full genesis bed belongs to step 4, not step 1.* This
|
||||
> record attributed "a mesh raised on NATS from genesis" to step 1, and described that step as "the
|
||||
> `nats` module and a mesh raised on it from nothing". A bed that enrols a node, holds a push and
|
||||
> rolls out an upgrade needs the controller and the host to speak NATS — which is step 3's
|
||||
> implementations and step 4's flows. A step whose proof cannot run is exactly the failure this
|
||||
> record was written to prevent, so step 1 now ends at the server standing from genesis, correctly
|
||||
> configured and carrying nothing, and the full bed is named under step 4. The five steps, their
|
||||
> names, their order and the single rollout are unchanged; only where two beds run has moved.
|
||||
>
|
||||
> Recorded here rather than superseded because the decision this record makes — that the work is
|
||||
> divided and each division is proved — is what *produced* the correction: the dependency was
|
||||
> invisible while the build was one item.
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0106](0106-the-bus-is-nats.md) — the decision this divides.
|
||||
|
||||
+39
-2
@@ -8,8 +8,45 @@ the decision is recorded here, and only then is the design written. Following th
|
||||
numbers walks the process in the order it happens.
|
||||
|
||||
One file per decision, numbered, never deleted. A superseded record has its `status:` changed
|
||||
and gains a pointer to what replaced it — **its text is never edited**. The reasoning that was
|
||||
rejected is the expensive half to rediscover.
|
||||
and gains a pointer to what replaced it — **its reasoning is never rewritten**. The reasoning that
|
||||
was rejected is the expensive half to rediscover.
|
||||
|
||||
## Progressive insight
|
||||
|
||||
A record is a decision, not a snapshot of everything that was true the day it was written, and
|
||||
those two fail differently. **A fact a record asserted can turn out to be wrong while the decision
|
||||
it supports stays right** — a count taken before anyone measured, a file named that does not
|
||||
exist, a proof attributed to a step that cannot run it. Superseding a record for that buries a
|
||||
correct decision under a second one, and teaches every reader to first work out which of two
|
||||
records is live. Done a few times, the reading order stops being one.
|
||||
|
||||
So: **a correction of fact that leaves the decision standing is made in the record, in place,
|
||||
marked and dated.**
|
||||
|
||||
> **Progressive insight — YYYY-MM-DD.** What was found, what the record said before, and what it
|
||||
> says instead.
|
||||
|
||||
Three conditions, all of which hold:
|
||||
|
||||
- **It corrects a fact, not a judgement.** That a suite does not exist is a fact. That building it
|
||||
is the wrong order is a judgement, and judgements supersede.
|
||||
- **It adds; it never quietly replaces.** Where body text changes, the note says what stood there
|
||||
before, so a reader who followed a citation to the old wording can find out what happened to it.
|
||||
A correction nobody can see is indistinguishable from a record that was always right, which is
|
||||
the failure the immutability rule exists to prevent.
|
||||
- **The decision, the options weighed and the consequences stand untouched.** If the correction
|
||||
changes what was decided, which alternatives were rejected, or a consequence another record
|
||||
relies on, it is not an insight — write the superseding record.
|
||||
|
||||
**What still supersedes**, without exception: reversing a decision, changing its scope, rejecting
|
||||
an option it accepted, or making a consequence false that a later record cites. The test is not
|
||||
how large the edit looks in a diff; it is whether a reader who acted on the old text would now be
|
||||
wrong about *what was decided* rather than about *a detail the decision did not rest on*.
|
||||
|
||||
**How this is checked.** `00-META/checks/records.py` requires every insight to be marked in the
|
||||
form above and dated no earlier than the record's own `date:` — an unmarked edit is a rule
|
||||
violation the reviewer looks for in the diff, and a marked one is legible in the record itself.
|
||||
The git history is the backstop, not the record of intent; the note is the record of intent.
|
||||
|
||||
The records run in the order the decisions were taken, oldest first.
|
||||
|
||||
|
||||
@@ -316,26 +316,20 @@ including the two places their dependencies put a bed later than the step that n
|
||||
real if the proofs divide with it. A step that cannot name what its bed proves is not a step, and is
|
||||
divided further before it is started.
|
||||
|
||||
**Step 1 — the genesis bed**, a mesh raised on NATS from nothing:
|
||||
- a node enrols over TLS with a claimed token, and the enrolment user cannot read a declaration;
|
||||
- a push composes; the store is stopped; the push is held (nak with delay), the store returns, the
|
||||
push applies, nothing was lost or duplicated;
|
||||
- a node that was away gets exactly the newest declaration, and a replayed older one is refused
|
||||
by sequence;
|
||||
- an upgrade rolls out to two nodes;
|
||||
- a module's tool is invoked from another node and from a person's client, each with an account
|
||||
that can invoke it, and refused from one that cannot;
|
||||
- a module's account cannot publish outside its `emits` nor subscribe outside its `consumes` —
|
||||
refused by the server;
|
||||
- a module acks a delivery from its own durable consumer, and is refused acking another module's;
|
||||
- a user subscribes another module's or person's inbox prefix and is refused by the server, not
|
||||
by the client's own good behaviour;
|
||||
- an event whose consumer keeps failing dead-letters after `max-deliver`;
|
||||
- an enrolment request held by a `nak`-with-delay cycle still reaches the enrolling node's inbox
|
||||
once the controller answers — proving the reply travels in the payload and not the transport
|
||||
field a consumer's ack has already claimed;
|
||||
- the `nats` container is not recreated when only its composed configuration file changes, and
|
||||
a change to that file is live (a new user can connect, a revoked one cannot) within one
|
||||
**Step 1 — the genesis-broker bed**, a mesh raised from nothing, the server standing on it. The
|
||||
mesh does not yet *live* on this bus — nothing speaks it until step 3's implementations exist — so
|
||||
what this bed proves is the server, its configuration and the permissions, each of which the server
|
||||
itself enforces and a plain client can therefore check:
|
||||
- the four streams exist, asserted idempotently on a second start, with the retention of §3;
|
||||
- every account and permission in the composed file is derived from the manifests' `emits` and
|
||||
`consumes` and nothing else, with each user's own ack subject and its own inbox prefix;
|
||||
- a user cannot publish outside its `emits` nor subscribe outside its `consumes` — refused by the
|
||||
server, not by convention;
|
||||
- a user cannot ack another user's delivery, and cannot subscribe another's inbox prefix — refused
|
||||
by the server, not by the client's own good behaviour;
|
||||
- the monitoring port is refused from anything but the private network;
|
||||
- the `nats` container is not recreated when only its composed configuration file changes, and a
|
||||
change to that file is live (a new user can connect, a revoked one cannot) within one
|
||||
watcher-poll interval, without a restart.
|
||||
|
||||
**Step 2 — the adoption bed**, a mesh already running that has never had this server:
|
||||
@@ -358,14 +352,24 @@ divided further before it is started.
|
||||
- the shared library gained nothing but the binding: its surface is the protocol and the
|
||||
primitives, and a helper that arrived with the transport is a review failure, not a detail.
|
||||
|
||||
**Step 4 — each converted flow against the behaviour it replaced:**
|
||||
**Step 4 — the mesh living on it.** The implementations exist from step 3, so this is where a mesh
|
||||
can first be raised on NATS and run:
|
||||
- a node enrols over TLS with a claimed token, and the enrolment user cannot read a declaration;
|
||||
- a push composes; the store is stopped; the push is held (nak with delay), the store returns, the
|
||||
push applies, nothing was lost or duplicated;
|
||||
- a node that was away gets exactly the newest declaration, and a replayed older one is refused
|
||||
by sequence;
|
||||
- an upgrade rolls out to two nodes;
|
||||
- an enrolment request held by a `nak`-with-delay cycle still reaches the enrolling node's inbox
|
||||
once the controller answers — proving the reply travels in the payload and not the transport
|
||||
field a consumer's ack has already claimed;
|
||||
- an event whose consumer keeps failing dead-letters after `max-deliver`;
|
||||
- a module's tool is invoked from another node and from a person's client, each with an account
|
||||
that can invoke it, and refused from one that cannot;
|
||||
- a build source's change reaches the builder over the bus, and the build that follows is the one
|
||||
the change asked for;
|
||||
- an installation completes over the bus, with the same outcome the path it replaces produced;
|
||||
- a module's reports arrive, and a node that was unreachable catches up rather than losing them;
|
||||
- nothing of research 017's observation work is present — no heartbeat semantics, no condition
|
||||
store — because that design is not written yet and a flow built ahead of it would have to be
|
||||
rebuilt.
|
||||
- a node that was unreachable catches up on its reports rather than losing them.
|
||||
|
||||
**Step 5 — the cutover bed:** a mesh on AMQP with a predecessor stand-in on the compatibility
|
||||
broker moves its bus in one rollout; every node reports on NATS afterwards; the stand-in's client
|
||||
|
||||
@@ -65,12 +65,12 @@ mirror rather than share (the host imports nothing, by
|
||||
host's link, and the runtime's client. And a search for conformance fixtures finds none anywhere in
|
||||
the four repositories: design 22's Phase 1.2 — the suite — has not been built.
|
||||
|
||||
> **A correction to ADR 0115, found in the measuring.** That record says step 3's fixtures are
|
||||
> *recaptured* on NATS. There is nothing to recapture: the suite does not exist. Step 3 **builds**
|
||||
> it, and its first job is to pin the wire the mesh has before changing it, because a suite written
|
||||
> only against the new bus certifies whatever the new bus happens to do. The record's decision is
|
||||
> unaffected; the word was wrong, and is corrected here rather than edited there
|
||||
> ([`02-DECISIONS/README.md`](../../02-DECISIONS/README.md): a record's meaning is never edited).
|
||||
> **This corrected the record.** ADR 0115 said step 3's fixtures were *recaptured* on NATS. There
|
||||
> is nothing to recapture, so step 3 **builds** the suite, and its first job is to pin the wire the
|
||||
> mesh has before changing it — a suite written only against the new bus certifies whatever the new
|
||||
> bus happens to do. A fact went stale while the decision stood, which is a **progressive insight**
|
||||
> ([`02-DECISIONS/README.md`](../../02-DECISIONS/README.md)): it is marked and dated in ADR 0115
|
||||
> itself rather than left to be discovered here.
|
||||
|
||||
## The order the work actually allows
|
||||
|
||||
@@ -91,12 +91,12 @@ otherwise would put two beds where they cannot run.** Three edges decide it:
|
||||
So step 1's bed proves *the server, from genesis, configured* — not a mesh living on it. The full
|
||||
genesis bed is step 4's, where it can first run.
|
||||
|
||||
> **This differs from ADR 0115's check list, deliberately.** That record attributes "a mesh raised
|
||||
> on NATS from genesis" to step 1. Measuring the dependency showed that bed cannot run until the
|
||||
> links exist, and a step whose proof cannot run is the exact failure the record was written to
|
||||
> prevent. The five steps, their names and the single rollout are unchanged; only where two beds
|
||||
> run has moved. If that reads as a change of meaning rather than a correction of fact, the fix is
|
||||
> a superseding record, not an edit.
|
||||
> **This corrected the record too.** ADR 0115 first attributed "a mesh raised on NATS from genesis"
|
||||
> to step 1. That bed cannot run until the links exist, and a step whose proof cannot run is the
|
||||
> exact failure the record was written to prevent — so step 1 now ends at the server standing,
|
||||
> correctly configured and carrying nothing, and the full bed is named under step 4. The five
|
||||
> steps, their names, their order and the single rollout are unchanged; only where two beds run has
|
||||
> moved. Marked and dated in ADR 0115 as a progressive insight, with what the record said before.
|
||||
|
||||
```
|
||||
step 1 module, genesis places it ──┐
|
||||
@@ -132,10 +132,15 @@ paper is wrong until there is a second mesh to find out.
|
||||
- [ ] 1.6 the genesis-broker bed
|
||||
|
||||
**Done when.** A mesh raised from nothing has the server standing with the streams asserted and
|
||||
every account and permission composed from the manifests; the monitoring port is refused from
|
||||
anything but the private network; a change to the composed file is live within one watcher interval
|
||||
without a restart, and the container is not recreated by it. No mesh traffic is on it yet — that is
|
||||
step 4's bed, not this one's.
|
||||
every account and permission composed from the manifests; a user cannot publish outside its
|
||||
`emits`, subscribe outside its `consumes`, ack another user's delivery or subscribe another's inbox
|
||||
prefix; the monitoring port is refused from anything but the private network; a change to the
|
||||
composed file is live within one watcher interval without a restart, and the container is not
|
||||
recreated by it.
|
||||
|
||||
**The permission checks belong here rather than later** because the server enforces them itself — a
|
||||
plain client proves them, no link required — and they are the whole of what ADR 0043 asks for. No
|
||||
mesh traffic is on the bus yet; that is step 4's bed, not this one's.
|
||||
|
||||
## Step 2 — adoption puts it in the seat
|
||||
|
||||
@@ -191,14 +196,14 @@ module.
|
||||
**Why here.** The links exist from step 3, so the flows that are not on the bus at all can move onto
|
||||
it, and the beds that need a mesh living on NATS can finally run.
|
||||
|
||||
- [ ] 4.1 **the full genesis bed** — a mesh raised on NATS from nothing: a node enrols over TLS with
|
||||
a claimed token and the enrolment user cannot read a declaration; a push is held while the
|
||||
store restarts and applies after, nothing lost or duplicated; a node that was away gets
|
||||
exactly the newest declaration and refuses a replayed older one by sequence; an upgrade rolls
|
||||
out to two nodes; an event dead-letters after `max-deliver`; a module cannot publish outside
|
||||
its `emits`, ack another module's delivery, or subscribe another's inbox prefix; and an
|
||||
enrolment held by a `nak`-with-delay cycle still reaches the enrolling node, proving the reply
|
||||
travels in the payload and not the transport field the consumer's ack has claimed
|
||||
- [ ] 4.1 **the full genesis bed** — a mesh raised on NATS from nothing and living on it: a node
|
||||
enrols over TLS with a claimed token and the enrolment user cannot read a declaration; a push
|
||||
is held while the store restarts and applies after, nothing lost or duplicated; a node that
|
||||
was away gets exactly the newest declaration and refuses a replayed older one by sequence; an
|
||||
upgrade rolls out to two nodes; an event dead-letters after `max-deliver`; and an enrolment
|
||||
held by a `nak`-with-delay cycle still reaches the enrolling node, proving the reply travels
|
||||
in the payload and not the transport field the consumer's ack has claimed. The server-enforced
|
||||
permissions were proved at step 1 and are not re-proved here
|
||||
- [ ] 4.2 a build source's change reaches the builder over the bus, and the build that follows is
|
||||
the one the change asked for
|
||||
- [ ] 4.3 an installation completes over the bus, with the same outcome as the path it replaces
|
||||
|
||||
@@ -52,8 +52,12 @@ vocabulary — *controller* (not "control plane"), *foundation* (not "substrate"
|
||||
docs (`layer`, `status`, `code`, `updated`), issue reports (`status`, `located-in`,
|
||||
`fixed-by`, `amended-design`) and decision records (`status`, `date`, `deciders`).
|
||||
Never create a central status file; cross-cutting views are generated from frontmatter.
|
||||
- **`02-DECISIONS/` records are immutable.** Supersede with a new record; never edit meaning. Fixing a
|
||||
broken link or path is allowed.
|
||||
- **`02-DECISIONS/` records hold their meaning.** Supersede with a new record rather than rewriting
|
||||
what was decided, the options weighed, or a consequence another record relies on. Fixing a broken
|
||||
link or path is allowed, and so is a **progressive insight** — a correction of *fact* that leaves
|
||||
the decision standing, made in place, marked and dated in the record's own words
|
||||
([`02-DECISIONS/README.md`](02-DECISIONS/README.md)). A fact going stale is not the decision going
|
||||
wrong, and superseding a sound record for one buries it.
|
||||
- **Design docs are prose and diagrams only** — no code. A manifest field may be named; a
|
||||
manifest may not be pasted.
|
||||
- **Two layers, never mixed.** [`03-DESIGN/00-as-is/`](03-DESIGN/00-as-is/) describes the mesh
|
||||
|
||||
Reference in New Issue
Block a user