Files
hq/DECISIONS.md
T
jschoubben f05e4a0dce Follow papa-hq's research convention; the mesh links nothing
Research efforts move from status.md to 00-overview.md with active /
graduated / abandoned, matching papa-hq so the two repositories read the
same way. Playbooks, skills, README and the ledger follow.

Reverses yesterday's withdrawal of the symlink note in GENESIS. The note
was right and the withdrawal was wrong: the intent is that the mesh
creates no symlinks at all, so a founding document listing "symlinks, not
copies" as a design principle does point the opposite way from where this
is going, and that is a contradiction rather than a stale detail.

ADR 0018 records the position, proposed. ADR 0011 stays as it is — it is
the historical decision and the incident behind it is why anyone believes
either record — and is superseded in intent, not edited. Its one
editorial line, which called the wider reading false, is corrected to
state what is actually true: centralising who may link narrowed the
incident class without closing it, because a link the installer makes
resolves exactly like one made by hand.

The argument that kept linking was staleness. ADR 0004 removed it: every
managed file is already derived and reconciled, so a copy is the natural
form and a pointer into source is the shape the mesh's own model forbids
everywhere else. What is not settled, and is marked open, is how
staleness gets detected — which is the decision that makes or breaks it.
2026-08-23 09:29:09 +02:00

113 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Decision ledger
Every decision, in the order it was taken. Append-only — a decision that stops being true is
marked superseded and left in place, because the reasoning that was rejected is the expensive
half to rediscover.
An entry here is a **record**, not the reasoning. Anything architecturally significant carries
its full context, options and consequences in an [ADR](adr/); anything still being worked out
lives in [`01-RESEARCH`](01-RESEARCH/). This file is the index that makes both findable, and
the place small decisions live that never warrant a document of their own.
**Columns.** *Decided* is who made the call. *Where* points at the reasoning. A decision with
no pointer is one small enough that this line is the whole record.
---
## 2026-08-22 — decomposition
| # | Decision | Decided | Where |
|---|---|---|---|
| 1 | The mesh brokers capabilities; nodes host; agents think. Eight bounded contexts replace 33 platform modules. | jochen | [ADR 0015](adr/0015-mesh-brokers-nodes-host-agents-think.md) |
| 2 | Nodes and agents decouple — a node holds no licence; an agent holds credentials and delivery follows its bindings and modality. | jochen | [ADR 0015](adr/0015-mesh-brokers-nodes-host-agents-think.md) |
| 3 | noxflow dissolves; `hal/work` inherits tasks and workflows. | jochen | [ADR 0015](adr/0015-mesh-brokers-nodes-host-agents-think.md) |
| 4 | Third-party modules leave this repository — they run *on* the mesh, not *of* it. | jochen | [ADR 0015](adr/0015-mesh-brokers-nodes-host-agents-think.md) |
| 5 | ~~Documentation lives inside the code repository under `hq/`.~~ | jochen | **Superseded by #27** |
## 2026-08-22 — the lab
| # | Decision | Decided | Where |
|---|---|---|---|
| 6 | Phase 0 is a **development environment**, not a fixture rig — it is what the host-borrowing dev tooling becomes. | jochen | [002](01-RESEARCH/002-local-mesh/00-overview.md) |
| 7 | The delivery trigger is a **real forge** inside the lab, not a synthetic event — the webhook relay is part of what is under test. | jochen | [002](01-RESEARCH/002-local-mesh/00-overview.md) |
| 8 | ~~A lab node is a **system container**, promotable to a virtual machine.~~ | jochen | **Superseded by #10** |
| 9 | Adoption is a legacy path and is out of scope. Bringing nodes into being is the lab runner's job instead. | jochen | [design](02-DESIGN/01-to-be/01-end-to-end-testing.md) |
| 10 | A lab node is a **virtual machine** running the real install. Supersedes #8: the scale argument for system containers was invented rather than required, and a virtual machine dissolves the fidelity question instead of answering it. | jochen | [ADR 0016](adr/0016-a-lab-node-is-a-virtual-machine.md) |
| 11 | The environment is called **the lab**. | jochen | — |
| 12 | The lab is driven by `incus` — for virtual machines, snapshots and bridges through one interface, and because it also runs system containers if a scale run is ever needed. | jochen | [ADR 0016](adr/0016-a-lab-node-is-a-virtual-machine.md) |
| 13 | The simulated public segment uses **TEST-NET-3** (`203.0.113.0/24`). Not cosmetic: an RFC1918 public segment makes the hub test as unreachable and the mesh silently never forms. | — | [ADR 0016](adr/0016-a-lab-node-is-a-virtual-machine.md), [004](01-RESEARCH/004-lab-network/analysis.md) |
| 14 | The lab **issues its own certificates**, keeping production's two-authority split rather than collapsing it. | jochen | [ADR 0016](adr/0016-a-lab-node-is-a-virtual-machine.md) |
## 2026-08-22 — what the lab is for
| # | Decision | Decided | Where |
|---|---|---|---|
| 15 | **The module is what is under test; the mesh is the harness.** The loop is: change a module, run it end to end, get a verdict. | jochen | [design](02-DESIGN/01-to-be/01-end-to-end-testing.md) |
| 16 | **Nothing new drives delivery.** A lab mesh has its own coordinator; the pipeline that runs is the real one. A second delivery path would be blind to exactly the faults worth catching. | jochen | [design](02-DESIGN/01-to-be/01-end-to-end-testing.md) |
| 17 | A **test runner** is a legitimate component *used by* the coordinator — lab lifecycle and assertion execution. The line is the pipeline: a runner that decides what to build is a fork of the coordinator. | jochen | [design](02-DESIGN/01-to-be/01-end-to-end-testing.md) |
| 18 | The runner has **two callers** — the coordinator, and a person developing the mesh — so it needs both a run-to-verdict verb and a leave-it-standing verb. | jochen | [design](02-DESIGN/01-to-be/01-end-to-end-testing.md) |
| 19 | **A module carries its own assertions**, stated once, in the verification stage the coordinator already dispatches. Running them where failing is free is what makes writing them worth doing. | jochen | [design](02-DESIGN/01-to-be/01-end-to-end-testing.md) |
| 20 | A test declares the mesh it needs; **size ranges from one node upward**, chosen by the question rather than by what the mesh happens to have. | jochen | [design](02-DESIGN/01-to-be/01-end-to-end-testing.md) |
| 21 | The real topology is **one test among many**, not the baseline. Anything only testable there is a gap in the vocabulary. | jochen | [design](02-DESIGN/01-to-be/01-end-to-end-testing.md) |
## 2026-08-22 — working agreements
| # | Decision | Decided | Where |
|---|---|---|---|
| 22 | **Never install packages by hand.** A package is declared in the module manifest and arrives the way every other package does. | jochen | — |
| 23 | **Never open a pull request unprompted.** A permissions list saying it is allowed is not a request. | jochen | — |
| 24 | **Every merge is a human checkpoint**, without exception. | jochen | [`02-DESIGN/01-to-be/00-work-breakdown.md`](02-DESIGN/01-to-be/00-work-breakdown.md) |
| 25 | Work in an **isolated worktree**, never a shared checkout. | jochen | [`how-we-build`](00-GENESIS/how-we-build.md) §2 |
| 26 | Decisions are recorded **here**, thoroughly, as they are taken. | jochen | this file |
| 27 | HQ is **its own repository**, `hal-hq`. Supersedes #5: the original objection was to a fourth knowledge *system*, which indexing answers rather than location. Cadence, reviewers, and a scope wider than one repository all argue for separation. | jochen | [`README`](README.md) |
| 28 | **This repository is public.** Written for a reader who is not its author and has no access to the mesh it describes. No routable addresses, real domains, hosting providers, node names, absolute paths, or operational detail useful only to an attacker. Supersedes the previous rule that research may name instances. | jochen | [`README`](README.md) |
---
## 2026-08-23 — how this repository works
| # | Decision | Decided | Where |
|---|---|---|---|
| 29 | Design splits into two layers that are never mixed — **`00-as-is` describes the mesh that exists, `01-to-be` the one being built toward**. A design that ships does not move; its as-is counterpart is written and both stand. | jochen | [`02-DESIGN/README`](02-DESIGN/README.md) |
| 30 | The as-is layer is written **from the implementation and the operational record**, not from intent, and records shipped behaviour nobody would choose again. An as-is layer that keeps only the good decisions is a brochure. | jochen | [`02-DESIGN/00-as-is/README`](02-DESIGN/00-as-is/README.md) |
| 31 | **HQ is the source of the mesh constitution.** The governed page injected into design sessions is derived from `how-we-build.md` and never edited directly. Same one-source-many-surfaces argument as #27. | jochen | [playbook 05](00-GENESIS/process/05-constitution-sync.md) |
| 32 | Every workflow is a **playbook** in `00-GENESIS/process/`, wrapped by a thin skill that defers to it. Agents operate through the playbooks and not outside them. | jochen | [`process/00-overview`](00-GENESIS/process/00-overview.md) |
| 33 | Issues get a **front door**, `04-ISSUES` — design-level and governance faults only. Operational lessons stay in the knowledge base, which is indexed on symptoms. This repository is not a second copy of it. | jochen | [`04-ISSUES/README`](04-ISSUES/README.md) |
| 34 | Decision records are a **chronological ledger**. Fourteen decisions already taken in implementation were back-filled as records 0001–0014, each marked `reconstructed` and carrying its evidence; the two existing records renumbered to 0015 and 0016. | jochen | [`adr/README`](adr/README.md) |
| 35 | **Status lives in frontmatter.** No central status files; cross-cutting views are generated on demand. This file is a ledger of decisions as taken — an index, and the home of decisions too small to warrant a record — and explicitly not a status board. | jochen | [`process/00-overview`](00-GENESIS/process/00-overview.md) |
| 36 | The ADR index is **generated, not maintained**. The hand-written one had already drifted after a single addition. | jochen | [`adr/README`](adr/README.md) |
| 37 | Modules outside the platform core are grouped **by domain, not by single function**, extending #1. The principle is settled; the domain list deliberately is not. | jochen | [ADR 0017](adr/0017-modules-outside-the-core-are-grouped-by-domain.md) |
| 38 | **The mesh creates no symlinks at all** — not by hand, and not by the installer. Centralising who may link narrowed the incident class without closing it, and a derived file is a copy by nature. The position is settled; the staleness mechanism is not. | jochen | [ADR 0018](adr/0018-the-mesh-creates-no-symlinks.md) |
| 39 | Research efforts follow the **`00-overview.md`** convention, with `active` / `graduated` / `abandoned` in frontmatter — the same shape papa-hq uses, so the two repositories read alike. | jochen | [`01-RESEARCH/README`](01-RESEARCH/README.md) |
---
## Observations
Things established by measurement that no decision has yet answered now live in
[`04-ISSUES`](04-ISSUES/), one numbered folder each, so they can be diagnosed, owned and
closed rather than accumulating in a table nobody can resolve.
| Issue | What it means |
|---|---|
| [001](04-ISSUES/001-failed-package-install-reports-success/00-report.md) | A failed package install does not fail the job. The first thing the lab was asked to install demonstrated the exact fault the lab exists to catch. |
| [002](04-ISSUES/002-stale-package-index-fails-silently/00-report.md) | A declared package can fail purely because the node's index is old, and today that failure is silent. |
| [003](04-ISSUES/003-firewall-scope-is-read-by-no-code/00-report.md) | A manifest can appear to restrict a port and restrict nothing. |
| [004](04-ISSUES/004-certificate-issuance-targets-production/00-report.md) | Every certificate experiment on a real node consumes production issuance quota. |
| [005](04-ISSUES/005-pipeline-test-harness-unbuildable/00-report.md) | The repository's only end-to-end pipeline test has been silently dead since 2026-06-04. |
| [006](04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md) | This repository is not indexed into the knowledge base — the claim that holds up decision 27. |
## Deliberately not decided
Recorded so they are not mistaken for oversights.
| Question | Status |
|---|---|
| Which supervision model the mesh adopts — keep the host init system, drop the redundant per-module layer, containerise the daemons, or write a supervisor. | Open. Options costed in [003](01-RESEARCH/003-service-supervision/analysis.md). **No longer gates the lab.** |
| Whether the lab verdict is a workflow guard or an advisory check on the pull request. | Open, and deliberately trivial — a policy detail, changeable in an afternoon, not an architectural choice. |
| `hal/scheduler` — infrastructure or part of `hal/work`. | Open, from ADR 0015. |
| Which context owns the executor. | Open, from ADR 0015. |
| Catalogue destination — one repository or many. | Open, from ADR 0015. Phase 4. |
| What `hal/sdk` keeps after extraction. | Open, from ADR 0015. Phase 3. |
| Where human agent modality is recorded — which user, on which node, a human agent acts as. | Open, from ADR 0015. Required by the model; not yet stored. |