The numbering is the flow: decisions are 02, design is 03
papa-hq reads 01 research -> 03 decision -> 02 design. The order is a scar, not a choice: 02-DESIGN existed from its initial commit, and when adr/ was finally promoted on 2026-07-13 it took the next free number rather than its place in the sequence. By then design was too settled to renumber. hal-hq was three commits old, so it is not. adr/ becomes 02-DECISIONS and 02-DESIGN becomes 03-DESIGN, and following the folder numbers now walks the process in the order it happens: research produces a decision, the decision authorises a design. 00-GENESIS becomes 00-META, matching papa's rename from the same restructure. Every path reference rewritten across documents, frontmatter, playbooks and skills. All links resolve; all 58 frontmatter blocks parse and their path fields still point at files that exist.
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
# 00-META
|
||||
|
||||
The **northern star**. What HAL is, the environment it runs in, and what changes when it
|
||||
works. Every research effort and design decision is checked against this folder.
|
||||
|
||||
| File / folder | Purpose |
|
||||
|------|---------|
|
||||
| [`mission.md`](mission.md) | Vision, mission, and the values that decide arguments |
|
||||
| [`context.md`](context.md) | The environment — conditions, not aspirations |
|
||||
| [`effect.md`](effect.md) | What is different when the work is done |
|
||||
| [`how-we-build.md`](how-we-build.md) | The rules that hold across the mesh, each one earned. **The source of the mesh constitution** — the governed page the mesh injects into design sessions is derived from it. |
|
||||
| [`repos.md`](repos.md) | Where implementation lives, and what each repository owns |
|
||||
| [`process/`](process/) | The playbooks — how work moves through this repository, for engineers and agents alike |
|
||||
|
||||
## Rules
|
||||
|
||||
- Markdown only.
|
||||
- **Stable by nature.** Changes here reflect a genuine shift in intent, not iteration. The one
|
||||
exception is `how-we-build.md`, which changes whenever a rule is earned — and only through
|
||||
its amendment process.
|
||||
- Research and design must be traceable back to what is written here.
|
||||
- **Instance-agnostic.** These documents describe the mesh as a concept. No machine names, no
|
||||
counts, no topology.
|
||||
|
||||
## On the architecture overview in the code repository
|
||||
|
||||
The code repository carries an architecture overview predating this folder. It is a useful
|
||||
description of *how* the mesh works, and its content now lives — anonymised and checked against
|
||||
the implementation — in [`03-DESIGN/00-as-is/`](../03-DESIGN/00-as-is/). GENESIS answers *why*;
|
||||
that document answered *how*, which is the design layer's job.
|
||||
|
||||
It had also drifted from the implementation in ways worth recording, since both were found by
|
||||
comparing it against the code rather than by anyone noticing:
|
||||
|
||||
- It described the pipeline as having a separate builder process and a build stage that
|
||||
packages. Neither was true after 2026-08-04; the documents stayed stale until 2026-08-06
|
||||
([ADR 0014](../02-DECISIONS/0014-build-publish-and-deploy-are-three-silos.md)).
|
||||
- It listed the mesh as spanning a fixed number of named machines, which is exactly the
|
||||
content this repository cannot carry.
|
||||
|
||||
It also lists **"symlinks, not copies" as a key design principle**, and that is a genuine
|
||||
contradiction rather than a stale detail. The mesh's stated intent is that it creates no
|
||||
symlinks at all — the rule is not merely "only the installer may link", and a founding document
|
||||
elevating linking to a principle points the opposite way from where this is going.
|
||||
|
||||
What exists today is that the installer owns and reconciles every link
|
||||
([ADR 0011](../02-DECISIONS/0011-the-installer-owns-linking.md)) — an as-is fact, recorded in
|
||||
[`03-DESIGN/00-as-is/05-runtime-and-installation.md`](../03-DESIGN/00-as-is/05-runtime-and-installation.md).
|
||||
Centralising who may link narrowed the incident class; it did not close it. The intent is to
|
||||
remove the mechanism, recorded as [ADR 0018](../02-DECISIONS/0018-the-mesh-creates-no-symlinks.md).
|
||||
|
||||
A founding document contradicting the direction of travel is precisely the failure this folder
|
||||
exists to prevent.
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
status: canonical
|
||||
updated: 2026-08-22
|
||||
---
|
||||
|
||||
# Engineering Context
|
||||
|
||||
The conditions the mesh is built for. Properties, not an inventory — no node here is
|
||||
named, and nothing should be designed around a particular one existing.
|
||||
|
||||
## Mandatory
|
||||
|
||||
- **Nodes are heterogeneous.** Desktops, laptops and servers, with different hardware,
|
||||
different operating systems and wildly different uptime. A design that assumes uniform
|
||||
nodes does not survive contact.
|
||||
- **Some nodes are mobile and frequently absent.** They sleep, change networks and lose
|
||||
addressability. A node being unreachable is ordinary operation, never an incident.
|
||||
- **At least one node must be stably addressable.** Central components — transport,
|
||||
registry, artifact storage — can only live where they can always be reached. That is a
|
||||
property some node must have, not an identity a particular node holds.
|
||||
- **Human agents are few — often one — and usually asleep.** There is no team, no rota, no
|
||||
second reviewer. Anything requiring a human to notice it will be noticed late.
|
||||
- **Nodes are personal.** A human agent works on the same node the mesh runs on. The mesh
|
||||
is a guest there and must not make a node worse to use.
|
||||
|
||||
## Default
|
||||
|
||||
- **Self-hosted throughout.** Transport, state, artifacts and memory run on nodes the mesh
|
||||
owns, not a managed service.
|
||||
- **A hosted model provider** supplies the thinking for non-human agents, drawn from a
|
||||
shared pool of subscriptions — which is why budget pacing is a first-class concern.
|
||||
- **Long-lived user services** rather than an orchestrator. No cluster scheduler, no cloud
|
||||
control plane.
|
||||
|
||||
Defaults, not mandates. A second model provider is anticipated by design; nothing in the
|
||||
domain may assume one vendor's credential lifecycle.
|
||||
|
||||
## Deviations
|
||||
|
||||
- **No enterprise identity.** No directory, no SSO. Identity is mesh-internal.
|
||||
- **Public exposure is minimal.** Only nodes that must terminate public traffic do so.
|
||||
- **Agents share a pool of provider subscriptions** rather than holding billing
|
||||
relationships of their own. A consequence of personal-scale infrastructure, and the
|
||||
reason spend must be paced rather than merely billed.
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
status: canonical
|
||||
updated: 2026-08-22
|
||||
---
|
||||
|
||||
# Effect
|
||||
|
||||
Imagine the mesh works as intended. What is different?
|
||||
|
||||
## You ask, and it happens
|
||||
|
||||
An agent says what it wants — from a terminal, a phone, a message — and the mesh takes it
|
||||
from there. It works out which nodes are involved, does the work, and returns a
|
||||
result. Nobody opens a console, recalls which node holds what, or follows a runbook
|
||||
written months ago.
|
||||
|
||||
The interface is intent. The mesh handles the rest.
|
||||
|
||||
## The nodes look after themselves
|
||||
|
||||
Updates land, services recover, disks are kept clear, certificates renew, and the mesh
|
||||
notices when something is wrong before you do. Maintenance stops being a thing you
|
||||
schedule and becomes a thing that has already happened.
|
||||
|
||||
When something genuinely needs a decision, you are asked — with the context, not a log
|
||||
line.
|
||||
|
||||
## Work continues while nobody is watching
|
||||
|
||||
Agents keep working overnight and across the week. What they did is legible afterwards
|
||||
because it is all in one record: what was asked, what was decided, what changed. The
|
||||
overnight work can be trusted, which is what makes it worth doing at all.
|
||||
|
||||
## The mesh remembers
|
||||
|
||||
Nothing has to be explained twice. What was learned — how a thing works, why a decision
|
||||
went the way it did, what broke last time — is available to whoever needs it next,
|
||||
whether that is an agent working at 4am or a human agent six months later.
|
||||
|
||||
## A human agent's environment is part of it
|
||||
|
||||
The node a human agent sits at is not outside the mesh looking in. The desktop, the
|
||||
notifications, the shell are how that agent acts — maintained by the mesh, exactly as a
|
||||
spawned session is for an agent that is not human.
|
||||
|
||||
## The difference for a human agent
|
||||
|
||||
Less time spent operating the mesh. More time spent deciding what it should do.
|
||||
@@ -0,0 +1,186 @@
|
||||
---
|
||||
status: canonical
|
||||
updated: 2026-08-23
|
||||
derives: knowledge-base constitution page
|
||||
decisions:
|
||||
- 02-DECISIONS/0009-the-mesh-is-governed-by-a-constitution.md
|
||||
---
|
||||
|
||||
# How we build
|
||||
|
||||
The rules that hold across the mesh. Short, and each one earned.
|
||||
|
||||
**This document is the source of the mesh constitution.** The governed page the mesh injects
|
||||
into design sessions is *derived* from it, section for section, and carries the rules without
|
||||
the reasoning. Never edit that page directly — an edit there survives until the next sync and
|
||||
then vanishes, taking its reasoning with it. The sync is playbook
|
||||
[`process/05-constitution-sync.md`](process/05-constitution-sync.md), and it is how the claim
|
||||
"HQ is the source" is checked.
|
||||
|
||||
Section numbers are stable. The orchestrator and the review fragments cite them.
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
These are the principles and guardrails every piece of work in the mesh is checked against —
|
||||
design sessions, analysis gates, reviews, and agents acting on their own. A rule stated here is
|
||||
non-negotiable unless amended per §6.
|
||||
|
||||
They exist because each was violated first. Where a rule reads as arbitrary, that is a sign the
|
||||
incident behind it is not written down, and the fix is to write it down, not to relax the rule.
|
||||
|
||||
---
|
||||
|
||||
## 2. Non-negotiables
|
||||
|
||||
| Rule | What it means |
|
||||
|---|---|
|
||||
| **Never write to a production database directly** | No insert, update, delete or schema statement executed against production by hand. Schema changes go through numbered migrations; data changes go through application code or the module's own capabilities. Raw statements skip every side effect the proper path has — events, audit, cache invalidation, fan-out. |
|
||||
| **Every schema change is a migration** | Numbered, in the module's own language, compiled with it. Both a baseline for a fresh installation *and* an incremental migration for installations that already exist. If code references a column, the migration creating it must exist. [ADR 0006](../02-DECISIONS/0006-schema-changes-are-numbered-migrations.md) |
|
||||
| **Never bypass the pipeline** | No manual database edit, no manual restart as a workaround. Fix the cause and deploy. A workaround that works is a workaround that is never removed, and the next person cannot tell the node from its declaration. |
|
||||
| **Never create a symlink** | A hand-made link caused production data loss through container volume resolution, and the judgement needed to make a safe exception is exactly the judgement unavailable at the moment it matters. Today the installer owns and reconciles the links the mesh still uses [ADR 0011](../02-DECISIONS/0011-the-installer-owns-linking.md); the intent is that the mesh creates none at all [ADR 0018](../02-DECISIONS/0018-the-mesh-creates-no-symlinks.md). Neither reading permits you to make one. |
|
||||
| **Never push directly to the main branch** | Branch, push, review, merge. Every merge is a human checkpoint, without exception. |
|
||||
| **One change per pull request, and never merge your own** | Unrelated improvements bundled together cannot be reviewed or reverted separately. Self-merging removes the checkpoint that is the entire point. |
|
||||
| **Never open a pull request unprompted** | A permissions list saying it is allowed is not a request. |
|
||||
| **A failed step fails the job** | A sequence that continues past a failure does the next thing in the wrong place. Gate each step on the last. [ADR 0008](../02-DECISIONS/0008-a-failed-step-fails-the-job.md), and §5. |
|
||||
|
||||
### A failed step must stop the steps after it — how it was earned
|
||||
|
||||
A worktree creation failed because the branch name collided with an existing namespace. The
|
||||
change into that worktree failed too. The copy, the staging and the commit that followed all
|
||||
ran in the shared checkout and committed to a local main. The error was printed and scrolled
|
||||
past.
|
||||
|
||||
This is the same shape as the faults the mesh's whole refactor exists to remove: a step
|
||||
reported failure, nothing stopped, and the damage happened somewhere nobody was looking.
|
||||
|
||||
---
|
||||
|
||||
## 3. Module and infrastructure rules
|
||||
|
||||
### Manifests
|
||||
|
||||
- **Never bump a version by hand.** The builder owns versioning. A version change in a diff is
|
||||
a defect; revert it.
|
||||
- **Features are detected, not declared.** The installer discovers what a module carries from
|
||||
what its directory contains. A declared list and the directory it describes drift, and the
|
||||
directory is the one that is true.
|
||||
- **Every runtime variable is declared.** A variable the module reads and the manifest does not
|
||||
declare is invisible to the mesh: it will not be generated, injected, or audited.
|
||||
- **Provisioned credentials arrive through declared requirements**, never hardcoded in code,
|
||||
compose files or scripts. [ADR 0005](../02-DECISIONS/0005-capabilities-are-provisioned-on-declaration.md)
|
||||
|
||||
### Placement
|
||||
|
||||
- **Core modules belong to the monorepo** — the runtime, delivery, provisioning, configuration,
|
||||
knowledge, and the shared infrastructure the mesh provisions against.
|
||||
- **Every standalone application gets its own repository**, with a manifest at its root,
|
||||
registered as a build source. Creating an application directory in the monorepo is a
|
||||
convention violation and reviewers reject it.
|
||||
[ADR 0010](../02-DECISIONS/0010-applications-live-in-their-own-repository.md)
|
||||
|
||||
### Migrations
|
||||
|
||||
- Numbered, idempotent, and safe to re-run. Guard every statement.
|
||||
- The initial migration is **frozen** once it has run anywhere. Change is a new number.
|
||||
- Numbers are unique. A duplicate prefix is a defect, not a style question.
|
||||
|
||||
### Managed files
|
||||
|
||||
**A file edited on a node is a bug with a delay on it.** Everything under the mesh's managed
|
||||
surface is regenerated from the mesh database; a local edit survives one synchronisation and is
|
||||
then silently overwritten, bringing back whatever it fixed. Use the mesh operation that owns
|
||||
the value. If unsure whether a file is managed, ask the tooling — the answer is not visible
|
||||
from the file. [ADR 0004](../02-DECISIONS/0004-managed-files-are-generated-never-edited.md)
|
||||
|
||||
---
|
||||
|
||||
## 4. Naming and boundaries
|
||||
|
||||
### Name a context after its aggregate, not after a metaphor
|
||||
|
||||
A context named `agents` owns **Agent**. A *brain* — memory, thoughts, cognition — is something
|
||||
an agent **has**: a concept inside the aggregate, not a module.
|
||||
|
||||
The cost of getting this wrong is visible today. An anatomy name points at the node runtime, so
|
||||
the most evocative word in the system names infrastructure; another describes itself as "mesh
|
||||
messaging" in its manifest while the anatomy documentation calls it the interactive runtime —
|
||||
and it runs on no node at all.
|
||||
|
||||
Anatomy makes attractive names and poor boundaries. Name the thing the domain calls it.
|
||||
|
||||
### Group by domain, not by single function
|
||||
|
||||
A module is a purpose, not a piece of software. Four modules that together constitute "how a
|
||||
node is reachable" and cannot be assigned, versioned or replaced as one thing are four
|
||||
accidents, not four boundaries.
|
||||
[ADR 0017](../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md)
|
||||
|
||||
### Contexts integrate through the record, never through a shared schema
|
||||
|
||||
Publish to the stream; do not join across a boundary. Today several domains share one
|
||||
forty-five-table schema, which is why work belonging to one context keeps having to be
|
||||
implemented in another.
|
||||
|
||||
---
|
||||
|
||||
## 5. Evidence and verification
|
||||
|
||||
### Ubiquitous language is checked, not assumed
|
||||
|
||||
**If a document states a rule about the mesh, it says how the rule is verified.** This
|
||||
repository has a documented requirement that every capability-exposing module declare the core
|
||||
runtime as a dependency. Zero modules do.
|
||||
|
||||
An unenforced rule is indistinguishable from a wrong one, and costs more, because people
|
||||
believe it.
|
||||
|
||||
### Behavioural criteria require runtime evidence
|
||||
|
||||
A criterion of the form *"the script runs"*, *"the endpoint answers"*, or *"the migration
|
||||
applied"* is satisfied only when the change has actually been exercised: a real run, a real
|
||||
request, a pipeline log, a live query showing the expected result.
|
||||
|
||||
**Marking a runtime criterion verified from a diff is itself a violation.** A reviewer who
|
||||
finds one names the evidence required and returns the work.
|
||||
|
||||
The reason is the mesh's most consistent failure shape: a green result proves transport, not
|
||||
effect. Absence reads as success unless something looked.
|
||||
|
||||
### Search the record before forming a hypothesis
|
||||
|
||||
The first action on any error message, failing service or unexpected behaviour is to search the
|
||||
operational memory for the literal error text — before a hypothesis, not after one fails. The
|
||||
knowledge base is indexed on symptoms.
|
||||
|
||||
This fires hardest on *familiar* ground, where a confident trail feels like progress. Two
|
||||
entries were each rediscovered from scratch over several hours in a single session because the
|
||||
search was skipped. Both were already written down.
|
||||
|
||||
---
|
||||
|
||||
## 6. Amendment
|
||||
|
||||
This document is governed. It does not change by commit message or unilateral decision.
|
||||
|
||||
1. **Propose** — a change stating what rule is changing, why the current wording is
|
||||
inadequate, and what reviewed it.
|
||||
2. **Review** — sign-off by reviewers who are not the proposer.
|
||||
3. **Record** — the change is a decision and gets a record in [`02-DECISIONS/`](../02-DECISIONS/), because a
|
||||
rule the mesh enforces is architecturally significant.
|
||||
4. **Sync** — playbook [`process/05-constitution-sync.md`](process/05-constitution-sync.md)
|
||||
publishes the derived page. An unsynced rule is a rule the mesh does not enforce, whatever
|
||||
this document says.
|
||||
|
||||
No drive-by edits. Every change traces to a recorded decision.
|
||||
|
||||
---
|
||||
|
||||
## 7. Overrides
|
||||
|
||||
A team or product may define additional constraints that **narrow or tighten** these rules.
|
||||
They may never relax them.
|
||||
|
||||
An override says which rule it tightens, or which gap it fills, and follows the same amendment
|
||||
process. Absence of an override means these rules apply unmodified.
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
status: canonical
|
||||
updated: 2026-08-22
|
||||
---
|
||||
|
||||
# Mission
|
||||
|
||||
## Vision
|
||||
|
||||
**A mesh that controls itself.**
|
||||
|
||||
An agent states an intent — in words, from wherever they already are — and the mesh
|
||||
carries it out. It takes the request in, works out what it means, does the work across
|
||||
whichever nodes it needs, and returns a result. No console to open, no runbook to follow,
|
||||
no remembering which node holds which thing.
|
||||
|
||||
Not automation, which does what it was told to do in advance. Self-control: the mesh
|
||||
holds the context, decides how, and acts.
|
||||
|
||||
## Mission
|
||||
|
||||
Build the layer that turns a set of nodes into one self-controlling mesh.
|
||||
|
||||
- **Intake, process, deliver.** A request arrives, is understood, becomes work, and
|
||||
returns an answer. That loop is the product; everything else exists to make it possible.
|
||||
- **Agents inhabit the mesh.** They are not scripts that run and exit. They hold identity,
|
||||
memory and skills, run on whichever node has room, and act continuously.
|
||||
- **The mesh brokers everything the work needs.** Storage, credentials, compute,
|
||||
knowledge, delivery — requested by capability, resolved by the mesh, never by the
|
||||
requester knowing where things are.
|
||||
|
||||
## Agents, some of whom are human
|
||||
|
||||
There is one kind of participant: the **agent**. Some agents are human and some are not,
|
||||
and the mesh does not treat that as a category difference. Both hold identity, both hold
|
||||
credentials, both act, remember and coordinate. What differs is **modality** — how an
|
||||
agent acts:
|
||||
|
||||
- a non-human agent acts through a spawned session and the record
|
||||
- a human agent acts through a shell, a desktop, a message from a phone
|
||||
|
||||
That is why a desktop environment is as much a core concern as a knowledge store. One is
|
||||
how some agents remember; the other is how some agents act. Neither is a courtesy
|
||||
extended to a user outside the system.
|
||||
|
||||
### What belongs in the mesh's own domain
|
||||
|
||||
A **core** module supports an agent's *participation* — acting, remembering,
|
||||
coordinating, or interfacing with the mesh.
|
||||
|
||||
A media server supports a human, but not their participation. It is therefore not a core
|
||||
module. It is still a perfectly valid HAL module — the
|
||||
mesh installs it, provisions for it, brokers its capabilities and ships it through the
|
||||
same pipeline. Entirely legitimate as a module, and no part of the mesh's own domain.
|
||||
|
||||
The distinction is **core module** versus **module the mesh runs**, not module versus
|
||||
not-a-module. Both use the same manifest, the same pipeline, the same provisioning —
|
||||
which is exactly what makes the mesh's own components no more privileged than anything
|
||||
else it carries.
|
||||
|
||||
## Core values
|
||||
|
||||
- **Evidence over assertion.** A claim that cannot be checked will quietly stop being
|
||||
true. Say what was measured.
|
||||
- **Failure must be loud.** The expensive faults are always the silent ones — work that
|
||||
reported success and did nothing. Prefer failing to lying.
|
||||
- **The mesh owns the truth.** State lives in the mesh and is derived onto nodes. A file
|
||||
edited on a node is a bug with a delay on it.
|
||||
- **Sovereignty.** The mesh runs on nodes it owns. External dependencies are
|
||||
deliberate and few.
|
||||
- **Dogfood everything.** The mesh's own components ship through the same machinery as
|
||||
anything else it runs. If they need an exception, the machinery is not finished.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Process — overview
|
||||
|
||||
How work moves through hal-hq, and who may do what. Every other document in this folder is a
|
||||
playbook: trigger, who runs it, steps, outputs. Engineers and agents follow the same
|
||||
playbooks; agents must not act outside them.
|
||||
|
||||
## The audiences
|
||||
|
||||
| Audience | Contract |
|
||||
|---|---|
|
||||
| **Engineers** | Read and write everything. hal-hq is the single source of truth for mission, research, design, decisions and issue diagnosis. |
|
||||
| **Agents** | The same rights as engineers, exercised through these playbooks. |
|
||||
| **Anyone else** | This repository is public and written for them, but it is not a support channel. Nothing here identifies the mesh it describes. |
|
||||
|
||||
## The knowledge flow
|
||||
|
||||
```
|
||||
idea ──► 01-RESEARCH ──► decision (02-DECISIONS/) ──► 03-DESIGN/01-to-be ──► built (code repo)
|
||||
│ │ │
|
||||
│ │ └─► 03-DESIGN/00-as-is once shipped
|
||||
│ └────► abandoned (recorded, kept)
|
||||
└─(small/obvious, decision recorded in DECISIONS.md)────► 03-DESIGN directly
|
||||
|
||||
symptom ──► 04-ISSUES ──► diagnosis ──► code-repo fix and/or design amendment
|
||||
|
||||
how-we-build.md ──► constitution sync ──► knowledge base ──► injected into design meetings
|
||||
```
|
||||
|
||||
## The two design layers
|
||||
|
||||
`03-DESIGN` holds two layers that are never mixed:
|
||||
|
||||
| Layer | What it is | Changes when |
|
||||
|---|---|---|
|
||||
| `00-as-is/` | The mesh that exists today. Describes shipped behaviour, including behaviour nobody would choose again. | Something ships, or an as-is claim is found to be wrong. |
|
||||
| `01-to-be/` | The mesh being built toward. Every statement traceable to a record in `02-DECISIONS/`. | A decision is taken or amended. |
|
||||
|
||||
A to-be document that ships does not move. Its as-is counterpart is written or updated, the
|
||||
to-be document's frontmatter goes to `implemented`, and both stand — one describing what runs,
|
||||
the other recording what was intended. Deleting the intention loses the reasoning, which is
|
||||
the expensive half.
|
||||
|
||||
## The playbooks
|
||||
|
||||
| # | Playbook | Trigger |
|
||||
|---|---|---|
|
||||
| [01](01-research.md) | Research | An idea worth investigating before committing to design |
|
||||
| [02](02-graduation.md) | Graduation & design change | Research concludes, or a design must change |
|
||||
| [03](03-issues.md) | Issues | Something is wrong — often with the owner unknown |
|
||||
| [04](04-build-handoff.md) | Build handoff | A design is ready to be built |
|
||||
| [05](05-constitution-sync.md) | Constitution sync | `how-we-build.md` changed a rule the mesh enforces |
|
||||
|
||||
## Status lives in frontmatter
|
||||
|
||||
Research overviews, design docs, issue reports and decision records each carry their status as
|
||||
YAML frontmatter (schemas in the section READMEs and playbooks). There are **no central status
|
||||
files**. `DECISIONS.md` is a ledger of decisions as they were taken — an index and a home for
|
||||
decisions too small to warrant a record — and is explicitly *not* a status board. Cross-cutting
|
||||
views are generated on demand by the `hal-status` skill and never written to disk.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Playbook 01 — Research
|
||||
|
||||
**Trigger.** An idea, technology or approach worth investigating before it is committed to
|
||||
design. Also: an as-is document that raises a question nobody can answer.
|
||||
|
||||
**Who runs it.** Anyone.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Take the next free number: highest `01-RESEARCH/NNN-*` plus one, zero-padded to three
|
||||
digits. Never skip or reuse a number.
|
||||
2. Create `01-RESEARCH/NNN-descriptive-name/` and a `00-overview.md` in it carrying:
|
||||
|
||||
```yaml
|
||||
---
|
||||
status: active
|
||||
initiated: YYYY-MM-DD
|
||||
touches: [] # areas, subsystems or as-is design docs the effort bears on
|
||||
---
|
||||
```
|
||||
|
||||
Then a short prose summary: **what** is being investigated, **why**, and **what it
|
||||
touches**.
|
||||
3. Do the research in further documents in the same folder — notes, option analyses, evidence,
|
||||
draft designs. Anything goes. Keep the summary in `00-overview.md` current as the effort changes
|
||||
shape.
|
||||
|
||||
## What makes research worth reading
|
||||
|
||||
State evidence, not assertion. *"Zero of 124 modules declare `brain` as a dependency"*
|
||||
outranks *"the dependency rule is not followed"*. An effort that measured nothing has not
|
||||
finished.
|
||||
|
||||
Research describes real observations but never identifies the mesh it observed. The shape of a
|
||||
finding survives anonymisation intact — *a node publicly named but behind a household NAT*
|
||||
carries the whole lesson without naming anything.
|
||||
|
||||
## Do not
|
||||
|
||||
- Do not put status in prose. It lives in `00-overview.md`'s frontmatter, and the prose must not restate it.
|
||||
- Do not set `became:` while the effort is open — playbook 02 sets it at closure.
|
||||
- Do not write into `03-DESIGN` from an open effort.
|
||||
|
||||
## Closing
|
||||
|
||||
An effort never just stops. It closes through playbook [02](02-graduation.md) as `graduated`
|
||||
or `abandoned`, always with `became:` pointing at what it turned into. Nothing is deleted —
|
||||
what was rejected, and why, is the more expensive half to rediscover.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Playbook 02 — Graduation and design change
|
||||
|
||||
**Trigger.** A research effort concludes, or an existing design must change.
|
||||
|
||||
**Who runs it.** Anyone, with the decision recorded before the design moves.
|
||||
|
||||
## Graduating research
|
||||
|
||||
1. **Check it against GENESIS.** An effort graduates only if its conclusion is traceable to
|
||||
[`mission.md`](../mission.md), [`context.md`](../context.md) and
|
||||
[`effect.md`](../effect.md). If it conflicts, either the effort is wrong or GENESIS is —
|
||||
say which, in writing, before proceeding.
|
||||
2. **Record the decision.** Write a record in [`02-DECISIONS/`](../../02-DECISIONS/) taking the next free
|
||||
number. Format and rules are in [`02-DECISIONS/README.md`](../../02-DECISIONS/README.md). State evidence,
|
||||
not assertion, and record the options that were rejected — that is the half worth keeping.
|
||||
3. **Write the design.** Create the document under `03-DESIGN/01-to-be/` with frontmatter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
layer: to-be
|
||||
status: designed
|
||||
code: [] # owning code repo(s); set at build handoff, empty before
|
||||
updated: YYYY-MM-DD
|
||||
decisions: [02-DECISIONS/NNNN-....md]
|
||||
---
|
||||
```
|
||||
|
||||
4. **Close the effort.** Set the effort's `00-overview.md` frontmatter to `status: graduated` and
|
||||
`became:` pointing at the design document and the decision record.
|
||||
5. **Add a ledger line.** Append the decision to [`DECISIONS.md`](../../DECISIONS.md) under
|
||||
today's heading, pointing at the record.
|
||||
|
||||
## Amending an existing design
|
||||
|
||||
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**.
|
||||
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.
|
||||
4. Add the ledger line.
|
||||
|
||||
## When something ships
|
||||
|
||||
Implementation state is a third axis, independent of both design and decision.
|
||||
|
||||
1. Write or update the matching document under `03-DESIGN/00-as-is/` so it describes what now
|
||||
runs — including anything that shipped differently from the intent. A design that shipped
|
||||
bent is an as-is fact, not a design amendment.
|
||||
2. Set the to-be document's `status: implemented` and its `code:` to the owning repositories
|
||||
from [`repos.md`](../repos.md).
|
||||
3. `status: implemented` must be defensible from the owning repository's main branch, not from
|
||||
intent. If it cannot be checked, it is `in-progress`.
|
||||
|
||||
## Do not
|
||||
|
||||
- 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.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Playbook 03 — Issues
|
||||
|
||||
**Trigger.** Something is wrong at the level of the mesh's design or governance — a rule that
|
||||
turns out to be unenforced, a stated behaviour that does not happen, a silent failure the
|
||||
design permits.
|
||||
|
||||
**Who runs it.** Anyone may open an issue. No localisation is required to report one.
|
||||
|
||||
## What belongs here, and what does not
|
||||
|
||||
| Belongs in `04-ISSUES` | Belongs in the knowledge base |
|
||||
|---|---|
|
||||
| The design permits a failure to be silent | How to fix one occurrence of it |
|
||||
| A documented rule is enforced by nothing | A command that works around it |
|
||||
| A stated invariant is false in practice | A node-specific quirk |
|
||||
| The owning component is unknown and finding it needs the whole mesh in view | Symptom → fix, once the answer is known |
|
||||
|
||||
The knowledge base already holds the operational record and is indexed on symptoms. This
|
||||
folder is not a second copy of it. An issue here is a question HQ must **answer**, not an
|
||||
incident someone must **clear**.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Take the next free number. Create `04-ISSUES/NNN-short-name/00-report.md`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
status: open
|
||||
opened: YYYY-MM-DD
|
||||
located-in: [] # owning repo(s)/module(s), filled by diagnosis
|
||||
fixed-by: # PR or commit reference, filled at resolution
|
||||
amended-design: # design doc path, when the root cause was a design gap
|
||||
---
|
||||
```
|
||||
|
||||
Then the symptom **as observed**, in plain terms, with the evidence that it happened.
|
||||
2. Investigate in `01-diagnosis.md` in the same folder — the trail, dated, including what was
|
||||
ruled out. Move `status:` to `diagnosing`, then `located` once the owner is known.
|
||||
3. Resolve. Set `status: resolved`, fill `fixed-by:`, and if the root cause was a design gap,
|
||||
run playbook [02](02-graduation.md) and fill `amended-design:`.
|
||||
|
||||
## Rules
|
||||
|
||||
- Closed issues are never deleted — they are the mesh's symptom-to-component memory.
|
||||
- An issue whose answer is a general lesson should also be written to the knowledge base, so
|
||||
the next person searching a symptom finds it. Both, not either.
|
||||
- `status: wontfix` is legitimate and requires a sentence saying why.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Playbook 04 — Build handoff
|
||||
|
||||
**Trigger.** A to-be design is settled and work is about to start in a code repository.
|
||||
|
||||
**Who runs it.** Whoever starts the build.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Confirm the design is settled.** Its frontmatter reads `status: designed`, and every
|
||||
claim in it traces to a record in [`02-DECISIONS/`](../../02-DECISIONS/). An open question in the text is a
|
||||
reason to run playbook [01](01-research.md), not to start building around it.
|
||||
2. **Name the owner.** Set `code:` in the design's frontmatter to the repositories from
|
||||
[`repos.md`](../repos.md). If the repository does not exist yet, add it to `repos.md` in
|
||||
the same change.
|
||||
3. **Check the as-is.** Read the matching `03-DESIGN/00-as-is/` document. What is being
|
||||
replaced is stated there; if it is not, write it before changing it. Building against an
|
||||
undocumented as-is is how a shipped behaviour gets lost.
|
||||
4. **Flip the status.** `status: in-progress`, `updated:` today.
|
||||
5. **Build in the code repository.** hal-hq is not a code repository and never carries
|
||||
implementation.
|
||||
6. **On completion**, run the "when something ships" section of playbook
|
||||
[02](02-graduation.md).
|
||||
|
||||
## Rules
|
||||
|
||||
- Every merge is a human checkpoint, without exception.
|
||||
- Never open a pull request unprompted. A permissions list saying it is allowed is not a
|
||||
request.
|
||||
- Work in an isolated worktree, never a shared checkout. A failed `cd` in a shared checkout
|
||||
commits to the wrong branch, and the error scrolls past.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Playbook 05 — Constitution sync
|
||||
|
||||
**Trigger.** [`how-we-build.md`](../how-we-build.md) changed a rule that the mesh enforces at
|
||||
runtime.
|
||||
|
||||
**Who runs it.** Whoever made the change.
|
||||
|
||||
## Why this playbook exists
|
||||
|
||||
The mesh injects a constitution into every eligible design meeting; agents check their output
|
||||
against it and a constitution-check phase can block a meeting. That text is **derived**.
|
||||
`how-we-build.md` is the source.
|
||||
|
||||
Two texts stating the same rules will drift, and the enforced copy winning by default means
|
||||
the reasoned copy quietly stops being true. This playbook is the mechanism that stops that —
|
||||
and, per the repository's own rule, it is how the rule "HQ is the source" is checked.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Edit [`how-we-build.md`](../how-we-build.md). Each rule keeps the reasoning that earned it;
|
||||
the derived page carries the rule alone.
|
||||
2. Record the change as a decision — a rule the mesh enforces is architecturally significant.
|
||||
Playbook [02](02-graduation.md).
|
||||
3. Publish the derived page to the knowledge base under the constitution slug, replacing its
|
||||
body. Keep the section numbering stable: the meeting orchestrator and the review fragments
|
||||
cite sections by number.
|
||||
4. Verify the derived page reads back with the change present. A publish that reported success
|
||||
and did nothing is exactly the failure class this repository exists to name.
|
||||
5. Note the sync in the ledger line for the decision.
|
||||
|
||||
## Rules
|
||||
|
||||
- **Never edit the derived page directly.** An edit there survives until the next sync and
|
||||
then vanishes, taking its reasoning with it.
|
||||
- The derived page may only be **tightened** by per-team override pages, never relaxed.
|
||||
- If the sync cannot be performed, say so in the ledger line. An unsynced rule is a rule the
|
||||
mesh does not enforce, whatever `how-we-build.md` says.
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
status: canonical
|
||||
updated: 2026-08-23
|
||||
---
|
||||
|
||||
# The HAL repositories
|
||||
|
||||
The map of where implementation lives. Humans use it for orientation; agents use it for issue
|
||||
triage (playbook [`process/03-issues.md`](process/03-issues.md)). The `code:` frontmatter
|
||||
field in design documents points at entries here.
|
||||
|
||||
Repository *names* are recorded; hosts, URLs and owners are not — this repository is public,
|
||||
and a forge address is an operational detail (see [`README`](../README.md)).
|
||||
|
||||
| Repository | Owns |
|
||||
|---|---|
|
||||
| `hal` | The monorepo — the node runtime, the module catalogue, the delivery machinery, and the bootstrap scripts. Every core module lives here. |
|
||||
| `hal-hq` | This repository — mission, research, design, decisions, issue diagnosis. The source of truth for *why*. Carries no implementation. |
|
||||
| *(one per application)* | Every standalone application, site or side-project gets its own repository, with `module.yml` at the root. Registered with the mesh as a build source; built and deployed by the same pipeline as anything in the monorepo. |
|
||||
|
||||
## What lives where inside the monorepo
|
||||
|
||||
Named by role, because the layout is itself part of the as-is design — see
|
||||
[`03-DESIGN/00-as-is/`](../03-DESIGN/00-as-is/).
|
||||
|
||||
| Area | Holds |
|
||||
|---|---|
|
||||
| Module catalogue | One directory per module, each with a manifest. Core modules sit under the mesh's own namespace; everything else at the top level. |
|
||||
| Node runtime | The daemon and interactive runtime that every node runs. |
|
||||
| Bootstrap scripts | First-node initialisation, joining an existing mesh, and node rescue. |
|
||||
| Shared library | The SDK every module builds against. |
|
||||
| Pipeline test harness | End-to-end coverage of the delivery pipeline. Currently unbuildable — see [`04-ISSUES/005`](../04-ISSUES/005-pipeline-test-harness-unbuildable/00-report.md). |
|
||||
|
||||
## Why applications do not live in the monorepo
|
||||
|
||||
A standalone application in the monorepo is a convention violation, and reviewers reject it.
|
||||
The reasoning is recorded in [`02-DECISIONS/0010`](../02-DECISIONS/0010-applications-live-in-their-own-repository.md):
|
||||
the mesh installs, provisions for, and ships an application through exactly the same machinery
|
||||
whether or not its source sits beside the mesh's own — so co-location buys nothing and costs
|
||||
the monorepo's review cadence.
|
||||
|
||||
## There is no npm workspace
|
||||
|
||||
Each module is a standalone package that consumes its dependencies from the private registry,
|
||||
not from a sibling directory. The workspace was removed after it caused build-versus-development
|
||||
divergence — a workspace member importing another resolved to local unbuilt source in the
|
||||
pipeline and to a published version in development. Recorded in
|
||||
[`02-DECISIONS/0007`](../02-DECISIONS/0007-no-npm-workspace.md).
|
||||
|
||||
Consequence, and it is a real one: a cross-package change is two steps — publish, then consume
|
||||
— and a repository-wide `npm install` does not exist.
|
||||
Reference in New Issue
Block a user