diff --git a/.claude/skills/hal-amend-design/SKILL.md b/.claude/skills/hal-amend-design/SKILL.md index 847807e..baad1d9 100644 --- a/.claude/skills/hal-amend-design/SKILL.md +++ b/.claude/skills/hal-amend-design/SKILL.md @@ -1,6 +1,6 @@ --- name: hal-amend-design -description: Use when a hal-hq design document must change, or when an as-is document is found to be wrong about what the mesh actually does. Triggers on "the design changed", "that's not how it works any more", "update the as-is", "this shipped differently". +description: Use when an HQ design document must change, or when an as-is document is found to be wrong about what the mesh actually does. Triggers on "the design changed", "that's not how it works any more", "update the as-is", "this shipped differently". --- # hal-amend-design diff --git a/.claude/skills/hal-diagnose/SKILL.md b/.claude/skills/hal-diagnose/SKILL.md index e7aa44c..ab48aa0 100644 --- a/.claude/skills/hal-diagnose/SKILL.md +++ b/.claude/skills/hal-diagnose/SKILL.md @@ -1,6 +1,6 @@ --- name: hal-diagnose -description: Use when investigating an open hal-hq issue — finding which component owns a symptom, and why. Triggers on "diagnose issue N", "where does this live", "who owns this bug", "why does this happen". +description: Use when investigating an open HQ issue — finding which component owns a symptom, and why. Triggers on "diagnose issue N", "where does this live", "who owns this bug", "why does this happen". --- # hal-diagnose diff --git a/.claude/skills/hal-graduate/SKILL.md b/.claude/skills/hal-graduate/SKILL.md index 1d38d93..051bc64 100644 --- a/.claude/skills/hal-graduate/SKILL.md +++ b/.claude/skills/hal-graduate/SKILL.md @@ -1,6 +1,6 @@ --- name: hal-graduate -description: Use when a hal-hq research effort concludes and becomes design, or when a design must change. Triggers on "graduate this research", "this is decided", "write the ADR", "close the effort", "the design changed". +description: Use when a research effort in HQ concludes and becomes design, or when a design must change. Triggers on "graduate this research", "this is decided", "write the ADR", "close the effort", "the design changed". --- # hal-graduate diff --git a/.claude/skills/hal-handoff/SKILL.md b/.claude/skills/hal-handoff/SKILL.md index 6f31b1a..9bbfa94 100644 --- a/.claude/skills/hal-handoff/SKILL.md +++ b/.claude/skills/hal-handoff/SKILL.md @@ -1,6 +1,6 @@ --- name: hal-handoff -description: Use when a hal-hq design is settled and implementation is about to start in a code repository. Triggers on "start building this", "hand this off", "ready to implement", "who owns this now". +description: Use when an HQ design is settled and implementation is about to start in a code repository. Triggers on "start building this", "hand this off", "ready to implement", "who owns this now". --- # hal-handoff @@ -20,7 +20,7 @@ Hands a settled design to a code repository. **Authoritative playbook:** `03-DESIGN/00-as-is/` before it is changed. Building against an undocumented as-is is how shipped behaviour gets lost. 4. **Flip the status** to `in-progress`, `updated:` today. -5. Build in the code repository. hal-hq never carries implementation. +5. Build in the code repository. HQ never carries implementation. 6. On completion, run `hal-graduate`'s "when something ships" section. ## Non-negotiable diff --git a/.claude/skills/hal-new-research/SKILL.md b/.claude/skills/hal-new-research/SKILL.md index 66081c6..59eed23 100644 --- a/.claude/skills/hal-new-research/SKILL.md +++ b/.claude/skills/hal-new-research/SKILL.md @@ -1,6 +1,6 @@ --- name: hal-new-research -description: Use when starting a new research effort in hal-hq — an idea, technology or approach worth investigating before it is committed to design. Triggers on "research X", "investigate X", "spike X", "should we use X", "is X worth doing". +description: Use when starting a new research effort in HQ — an idea, technology or approach worth investigating before it is committed to design. Triggers on "research X", "investigate X", "spike X", "should we use X", "is X worth doing". --- # hal-new-research diff --git a/.claude/skills/hal-status/SKILL.md b/.claude/skills/hal-status/SKILL.md index 0b1a131..c80b7bd 100644 --- a/.claude/skills/hal-status/SKILL.md +++ b/.claude/skills/hal-status/SKILL.md @@ -1,12 +1,12 @@ --- name: hal-status -description: Use when you need a cross-cutting view of where hal-hq stands — research state, design implementation state, open issues, or the decision-record index. Triggers on "what's the status", "show the ADR index", "where do things stand", "what's in progress", "what's open". +description: Use when you need a cross-cutting view of where HQ stands — research state, design implementation state, open issues, or the decision-record index. Triggers on "what's the status", "show the ADR index", "where do things stand", "what's in progress", "what's open". --- # hal-status Generates a cross-cutting view **from frontmatter**. This is a read-and-render skill, not a -workflow — hal-hq has **no central status file by design** (decision 35). Every view is +workflow — HQ has **no central status file by design** (decision 35). Every view is generated on demand and never written back to disk. ## What to read diff --git a/.claude/skills/hal-sync-constitution/SKILL.md b/.claude/skills/hal-sync-constitution/SKILL.md index 41f07b6..2e32521 100644 --- a/.claude/skills/hal-sync-constitution/SKILL.md +++ b/.claude/skills/hal-sync-constitution/SKILL.md @@ -1,6 +1,6 @@ --- name: hal-sync-constitution -description: Use after changing a rule in hal-hq's 00-META/how-we-build.md, to publish the derived constitution page the mesh injects into design sessions. Triggers on "sync the constitution", "publish the rules", "I changed how-we-build", "update the governed page". +description: Use after changing a rule in HQ's 00-META/how-we-build.md, to publish the derived constitution page the mesh injects into design sessions. Triggers on "sync the constitution", "publish the rules", "I changed how-we-build", "update the governed page". --- # hal-sync-constitution diff --git a/00-META/process/00-overview.md b/00-META/process/00-overview.md index 788c89d..478f178 100644 --- a/00-META/process/00-overview.md +++ b/00-META/process/00-overview.md @@ -1,6 +1,6 @@ # Process — overview -How work moves through hal-hq, and who may do what. Every other document in this folder is a +How work moves through 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. @@ -8,7 +8,7 @@ playbooks; agents must not act outside them. | Audience | Contract | |---|---| -| **Engineers** | Read and write everything. hal-hq is the single source of truth for mission, research, design, decisions and issue diagnosis. | +| **Engineers** | Read and write everything. 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. | diff --git a/00-META/process/04-build-handoff.md b/00-META/process/04-build-handoff.md index 5c3b84f..4c26baf 100644 --- a/00-META/process/04-build-handoff.md +++ b/00-META/process/04-build-handoff.md @@ -16,7 +16,7 @@ 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 +5. **Build in the code repository.** 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). diff --git a/00-META/repos.md b/00-META/repos.md index c221e87..08a7b41 100644 --- a/00-META/repos.md +++ b/00-META/repos.md @@ -3,7 +3,7 @@ status: canonical updated: 2026-08-23 --- -# The HAL repositories +# The Novox 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 @@ -15,7 +15,7 @@ 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. | +| `hq` | This repository, under the company organisation — mission, research, design, decisions, issue diagnosis. Company-scoped ([ADR 0028](../02-DECISIONS/0028-hq-is-company-scoped.md)); the mesh is its first product. 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 diff --git a/01-RESEARCH/006-mesh-from-scratch/code-skeleton.md b/01-RESEARCH/006-mesh-from-scratch/code-skeleton.md index 977c6e9..fad0bb5 100644 --- a/01-RESEARCH/006-mesh-from-scratch/code-skeleton.md +++ b/01-RESEARCH/006-mesh-from-scratch/code-skeleton.md @@ -31,7 +31,7 @@ Run the test. *Can the control plane exist without a relational store?* No. **Po tier 1.** It lives once: ``` -hal-substrate/store/postgres/ +mesh-substrate/store/postgres/ ``` There is no second copy in the catalogue, because the thing that differs between the mesh's own @@ -40,7 +40,7 @@ database and a project's database is **not the module**. It is how that instance | | The mesh's own instance | A project's database | |---|---|---| | Brought up by | the host, from the pinned bundle, with no control plane present | the ordinary delivery and provisioning path | -| Declared in | `hal-substrate/bundle.yml` | the consuming module's `requires:` | +| Declared in | `mesh-substrate/bundle.yml` | the consuming module's `requires:` | | Exists because | the control plane cannot start without it | something asked for it | Same module, two roles. **Tier is a property of the module** — what must exist before what — and @@ -66,7 +66,7 @@ feels. ## Becoming self-hosting — the forge and the registries Self-improvement means the mesh hosts the things it improves itself with: a forge, an image -registry, a package registry. The obvious worry is that these duplicate — a `hal-mesh-gitea` +registry, a package registry. The obvious worry is that these duplicate — a `mesh-gitea` for the mesh and a `gitea` for everyone else. **They do not, and the reason is worth stating carefully, because it is the same reason the bootstrap keeps failing today.** @@ -203,7 +203,7 @@ parts is not a module. Worked through for the substrate's relational store: ``` -hal-substrate/store/postgres/ +mesh-substrate/store/postgres/ module.yml provides: database · profiles: [managed] parts/ service/ the container, its volume, its network exposure @@ -215,7 +215,7 @@ hal-substrate/store/postgres/ ## The tree, at file level ``` -hal-host/ TIER 0 +mesh-host/ TIER 0 cmd/host/ internal/ apply/ reconcile declared state @@ -230,14 +230,14 @@ hal-host/ TIER 0 profile/ managed · user · edge substrate.lock pinned tier-1 descriptor -hal-substrate/ TIER 1 +mesh-substrate/ TIER 1 bundle.yml the pinned set, by digest store/postgres/ bus// objects// images// -hal-mesh/ TIER 2 +mesh-control/ TIER 2 record/ the event log contexts integrate through inventory/ nodes · modules · assignments · versions config/ settings · secrets · derivation @@ -250,13 +250,13 @@ hal-mesh/ TIER 2 knowledge/ memory · documents · retrieval api/ the one interface surfaces speak to -hal-surfaces/ TIER 3 +mesh-surfaces/ TIER 3 tools/ web/ cli/ -hal-catalog/ TIER 4 +mesh-catalog/ TIER 4 // layout as above -hal-lab/ hal-sdk/ hal-hq/ +mesh-lab/ mesh-sdk/ mesh-hq/ ``` ## What this does not settle diff --git a/01-RESEARCH/006-mesh-from-scratch/skeleton.md b/01-RESEARCH/006-mesh-from-scratch/skeleton.md index d8e4bff..3cb355d 100644 --- a/01-RESEARCH/006-mesh-from-scratch/skeleton.md +++ b/01-RESEARCH/006-mesh-from-scratch/skeleton.md @@ -20,8 +20,8 @@ bare machine │ one command lands ONE binary. Nothing else exists. TIER 0 host │ │ it reads a pinned file it already carries and raises a - │ database, a bus, an object store, a registry, an - │ identity provider — locally, alone. TIER 1 substrate + │ database, a bus, an object store and an image + │ registry — locally, alone. TIER 1 substrate │ │ on those, the mesh's brain starts: which nodes exist, │ what runs where, what is reachable. TIER 2 control plane @@ -46,7 +46,7 @@ A tier is not a repository and not a bounded context. Those are different cuts: ## The tree ``` -hal-host/ TIER 0 — the only thing ever installed by hand +mesh-host/ TIER 0 — the only thing ever installed by hand apply/ reconcile declared state on this machine inventory/ what this node is, has, and is capable of link/ the single outbound connection to the control plane @@ -54,15 +54,14 @@ hal-host/ TIER 0 — the only thing ever installed by hand profile/ capability detection: managed · user · edge substrate.lock pinned tier-1 descriptor, appliable with no mesh present -hal-substrate/ TIER 1 — declarations only, no logic of its own +mesh-substrate/ TIER 1 — declarations only, no logic of its own store/ relational state bus/ commands and events objects/ blobs and build artifacts images/ container images - identity/ the identity provider bundle.yml the pinned set tier 0 can raise alone -hal-mesh/ TIER 2 — the control plane +mesh-control/ TIER 2 — the control plane record/ the event log every context integrates through inventory/ nodes · modules · assignments · versions config/ settings · secrets · derivation onto nodes @@ -75,17 +74,17 @@ hal-mesh/ TIER 2 — the control plane knowledge/ memory · documents · retrieval api/ the one interface every surface speaks to -hal-surfaces/ TIER 3 — thin; no logic lives here +mesh-surfaces/ TIER 3 — thin; no logic lives here tools/ the agent-facing tool surface web/ the operator-facing interface cli/ the shell-facing interface -hal-catalog/ TIER 4 — what the mesh hosts +mesh-catalog/ TIER 4 — what the mesh hosts / grouped per ADR 0017, list per research 005 -hal-lab/ the whole mesh, disposable, on one machine -hal-sdk/ contracts shared across tiers — types, not behaviour -hal-hq/ this repository +mesh-lab/ the whole mesh, disposable, on one machine +mesh-sdk/ contracts shared across tiers — types, not behaviour +mesh-hq/ this repository ``` ## The dependency rule @@ -101,15 +100,15 @@ rule enforced by intention is the same as no tier rule — that is ## Move 1 — the substrate is applied, not delivered -**The problem.** The mesh needs a database, a bus, an object store, a registry and an identity -provider. Today those are modules, and modules are installed by the delivery pipeline, which +**The problem.** The mesh needs a database, a bus, an object store and an image registry. +Today those are modules, and modules are installed by the delivery pipeline, which needs the database and the bus. The first node is therefore raised by a special script that exists only because of the circularity, and every later change to the substrate has to pretend the circularity is not there. **The move.** The host can apply a declaration without anyone telling it to. The substrate is a **pinned bundle** the host carries: a fixed, versioned, self-contained descriptor of the -five services and nothing else. Raising a first node is `host apply substrate.lock` — not a +four services and nothing else. Raising a first node is `host apply substrate.lock` — not a special path, just the ordinary one with no control plane on the other end. The circularity disappears rather than being worked around: **the substrate is applied by tier @@ -217,9 +216,10 @@ confusing. Tiers 0–3 are the mesh. Tier 4 is everything it carries, and the boundary is stated by requirement rather than by taste: **a module is part of the mesh if removing it stops the mesh -managing nodes.** A media server does not. An identity provider does — which is why identity -sits in the substrate and not the catalogue, despite being, in every other respect, an -application like any other. +managing nodes.** A media server does not. A relational store does — which is why it sits in the +substrate and not the catalogue, despite being, in every other respect, an application like any +other. An identity provider, notably, does **not**: the control plane authenticates its own +callers, so identity is a hosted service like the media server. That test also settles the IT-company goal without a special category. Development, design and deployment tooling are **workloads** — tier 4, hosted, provisioned, delivered like anything @@ -261,7 +261,7 @@ being the one thing nobody exercises until it breaks. ## A naming near-miss, recorded -The tier-0 binary was first called `hal-agent`, because "node agent" is the reflex everywhere +The tier-0 binary was first called `mesh-agent`, because "node agent" is the reflex everywhere else in the industry. That is wrong here, and wrong in the specific way [`how-we-build.md`](../../00-META/how-we-build.md) §4 exists to catch: **Agent** is a first-class concept in this mesh — a participant, some of whom are human, holding identity and @@ -273,8 +273,8 @@ pointing at infrastructure. [ADR 0015](../../02-DECISIONS/0015-mesh-brokers-nodes-host-agents-think.md) supplies the fix in its own title — *the mesh brokers capabilities; nodes host; agents think.* Three verbs, three -components: the control plane **brokers** (`hal-mesh`), the tier-0 binary **hosts** -(`hal-host`), the participant **thinks** (`agents`, untouched). +components: the control plane **brokers** (`mesh-control`), the tier-0 binary **hosts** +(`mesh-host`), the participant **thinks** (`agents`, untouched). -`hal-node` was the alternative and was rejected: *Node* is the aggregate in the inventory — the +`mesh-node` was the alternative and was rejected: *Node* is the aggregate in the inventory — the record of a machine — while the binary is what runs on it and does the hosting. diff --git a/01-RESEARCH/009-migration/00-overview.md b/01-RESEARCH/009-migration/00-overview.md new file mode 100644 index 0000000..f72efb4 --- /dev/null +++ b/01-RESEARCH/009-migration/00-overview.md @@ -0,0 +1,92 @@ +--- +status: active +initiated: 2026-08-23 +touches: + - 01-RESEARCH/006-mesh-from-scratch/code-skeleton.md + - 03-DESIGN/01-to-be/01-end-to-end-testing.md + - 02-DECISIONS/0016-a-lab-node-is-a-virtual-machine.md + - 03-DESIGN/00-as-is/00-overview.md +became: [] +--- + +# 009 — Getting from the mesh that exists to the mesh that is designed + +## What is being investigated + +How a running mesh becomes the one in +[research 006](../006-mesh-from-scratch/code-skeleton.md), without losing what it currently +carries. + +The proposed shape: **build tiers 0, 1 and 2, then replace the current setup in one move.** + +## Why big-bang is the right instinct here + +Recorded because incremental is the reflex answer and it is wrong in this case. + +- **The two models are structurally incompatible.** The tier rule, the host absorbing what are + now modules, the artifact/part split, provisioning generalised to the control plane's own + requirements — none of these can half-apply. Running both models at once means the old one's + assumptions keep constraining the new one, which is how a migration becomes permanent. +- **Nothing external depends on it.** No users outside the operator, no service level to hold. +- **The lab exists precisely for this** ([ADR 0016](../../02-DECISIONS/0016-a-lab-node-is-a-virtual-machine.md)). + A big-bang that has been rehearsed end to end, repeatedly, on identical machines is not the + same risk as one performed for the first time on the real mesh. +- **Incremental would carry the rot forward.** The as-is layer documents silent failure paths, + a dead test harness and unenforced rules. A gradual migration preserves them by definition. + +## The distinction that lowers the risk + +**Replace the control plane; do not move the workloads.** + +The things that would hurt to lose — mail, media, source, databases, their data directories — +are not the mesh. They are what the mesh manages. They sit in container volumes on nodes, and +they do not need to move for the control plane above them to be replaced. + +So the big-bang is: the old control plane stops managing these nodes, and the new one starts — +with the workload data untouched, in place, and re-declared rather than migrated. + +That reframing turns "replace the mesh" into "replace the part with no persistent state of its +own", which is a materially smaller act than it first sounds. + +## The tension this exposes + +Taking over already-running workloads is **adoption**, and adoption was ruled out of scope — +recorded as a legacy path in +[`03-DESIGN/01-to-be/01-end-to-end-testing.md`](../../03-DESIGN/01-to-be/01-end-to-end-testing.md). +The migration appears to need exactly the capability the design declared it would not have. + +The way out, to be tested: the new mesh does not adopt anything. It **declares** the workloads +from scratch and points them at data directories that already exist. Nothing inspects a running +machine to learn what is there; the declarations are written from the as-is layer, which is what +that layer is for. Data survives because it was never touched, not because it was adopted. + +If that holds, adoption stays out of scope and the migration is ordinary declaration. If it does +not, adoption needs a one-time, explicitly unsupported tool, and that should be a decision rather +than a discovery. + +## Sequencing + +| Phase | What | Done when | +|---|---|---| +| A | Build tier 0. The host's interface first — it carries the skeleton's biggest unproven claim. | A bare machine becomes a managed node with no mesh present. | +| B | Build tier 1 and 2. | The lab raises a full mesh from nothing, repeatedly, from pinned external artifacts. | +| C | Enough of tier 3 to operate it. | The mesh can be driven without direct database access. | +| D | Declare the existing workloads against the new model. | The lab runs them, with copies of real data shapes. | +| E | **Rehearse the cutover in the lab** against a mesh built to resemble the real one. | Repeatable, and repeatably reversible. | +| F | Cut over. | The real nodes are managed by the new control plane. | +| G | Reach self-hosting — re-bind delivery from external providers to the mesh's own forge and registries. | The mesh builds and deploys itself. | + +Phase G is deliberately last. Per research 006, self-hosting is a state the mesh **reaches**; +attempting the cutover and the self-hosting transition in the same move recreates exactly the +circularity the skeleton removes — and would mean a failed cutover could take away the means to +fix it. + +## The questions + +| Question | Why it matters | +|---|---| +| What state must **survive** the cutover, versus be re-created? | Workload data must. Provisioned credentials could be re-issued. The mesh's own inventory could be re-declared. Each answer changes the risk. | +| What is the **way back**? | A cutover with no rollback is not a plan. If workload data is untouched, reverting may be as small as re-pointing the old control plane at it — to be verified, not assumed. | +| How is the cutover **rehearsed** against something resembling the real mesh, without copying the real mesh into a repository? | The lab must be able to model the real topology's shape without carrying its identity. | +| Does anything have to keep running **during** the cutover? | Mail and source are the obvious candidates. If yes, "big-bang" is really "big-bang with exceptions", and the exceptions should be named now. | +| Is the forge inside or outside the cutover? | If the mesh's own forge goes down with the old control plane, the means of deploying a fix goes with it. This is the self-hosting circularity appearing as a migration risk. | diff --git a/02-DECISIONS/0027-the-product-is-novox-mesh.md b/02-DECISIONS/0027-the-product-is-novox-mesh.md new file mode 100644 index 0000000..192b7a3 --- /dev/null +++ b/02-DECISIONS/0027-the-product-is-novox-mesh.md @@ -0,0 +1,112 @@ +--- +status: accepted +date: 2026-08-23 +deciders: jochen +reconstructed: false +--- + +# 27. The product is Novox Mesh; Nox is an identity, not a second system + +## Context + +The name `HAL` was never chosen. This began as a dotfiles repository, the first commits in +February 2026 adopt dotfiles and per-node overrides, and the name arrived with the code — as +recorded in +[`03-DESIGN/00-as-is/10-module-catalogue.md`](../03-DESIGN/00-as-is/10-module-catalogue.md), +most of the current shape is inherited from that origin rather than designed for a mesh. The +name is part of the inheritance. + +Three things make it worth changing rather than living with. + +**It is borrowed, and borrowed badly.** HAL is the canonical *untrustworthy* machine +intelligence. For infrastructure whose entire proposition is that it manages your machines, +heals itself, and is trusted with credentials, that is an unhelpful flag to fly, and it is not +a name anyone owns. + +**There is a name available that is owned.** The company is Novox. A product of Novox should +carry that lineage rather than a film reference. + +**A platform and a persona are different things, and one name was doing both.** `HAL` named the +mesh *and*, implicitly, the thing an operator talks to. Those are separate concerns — the +platform is what runs; the persona is who answers. + +## Considered options + +1. **Keep `HAL`.** Rejected. Every reason to keep it is sunk cost, and the sunk cost is at its + smallest today. +2. **Rename everything to a single new name covering platform and persona.** Rejected: it + repeats the conflation that made `HAL` ambiguous. +3. **Separate the two: a product name and an identity.** Chosen. + +## Decision + +**The product is `Novox Mesh`**, shortened to `mesh` in internal use — repository names, the +module namespace, environment variables, paths. + +**`Nox` is an identity of Novox**, and specifically an **agent identity within the mesh's own +model** — a named participant, exactly as +[ADR 0012](0012-agents-are-persistent-employees.md) defines one. Not a separate product, not a +separate runtime, not a privileged path. + +**Nox is the agent of the mesh, not of a node.** This is the part that carries weight: + +- **Every node keeps its own identity.** That already exists and stays — a node is a named + participant with its own character, and addressing one directly remains possible and normal. +- **Nox is scoped to the whole mesh.** It is what the mesh is called when the mesh itself + speaks, rather than one machine within it. +- **Nox addresses node identities.** Asking Nox for something that lives on one node is Nox + talking to that node, not a human choosing a machine. +- **A human mostly talks to Nox.** It is the front door. + +That last point makes Nox the concrete form of the vision in +[`00-META/mission.md`](../00-META/mission.md): *an agent states an intent and the mesh carries +it out — no console to open, no runbook to follow, no remembering which node holds which +thing.* Nox is who that intent is stated to. The mission described the behaviour; this names +the thing that has it. + +Nox holds no private channel. Whatever it can do, it does through the same surfaces every other +agent uses — which is not a naming detail: a persona with its own path would be the one part of +the mesh with no human checkpoint, and the skeleton already rules that out. + +`HAL` is retired. + +**Timing is the substance of this decision, not an aside.** The skeleton in +[research 006](../01-RESEARCH/006-mesh-from-scratch/code-skeleton.md) is not built. Renaming +before it exists costs a search and replace across research documents. Renaming after costs the +same class of migration as everything else this repository is trying to avoid, and would +therefore not happen. + +## Consequences + +- **The as-is layer keeps `HAL`.** It describes what runs, and what runs is called HAL. The + to-be layer uses `mesh`. The rename is part of the migration, and the two-layer split + ([ADR 0020](0020-design-is-written-in-two-layers.md)) is what makes holding both names + coherent rather than confusing. +- **Records 0001–0026 keep `HAL`.** They are immutable and they say what was decided when it + was decided. No record is edited for a name. +- Tier 2 cannot be `mesh-mesh`. The control plane is **`mesh-control`**; `mesh-broker` was + rejected because the substrate already contains a message broker. +- The namespace, environment variable prefix, service names and on-disk paths all change. In + the existing system that is a migration and is not attempted here. +- **`mesh` is a generic word**, and it already means something specific in infrastructure — a + service mesh is a different thing. Recorded as a known trade rather than an oversight: the + full name `Novox Mesh` is distinctive, and the short form is internal. +- The persona has a name before it has behaviour. That is the right order — it is an identity in + a system that already has a model of identities, so it needs no new machinery to exist. +- **Except in one respect, and it is a real gap.** + [ADR 0012](0012-agents-are-persistent-employees.md) binds every agent to a home node, one to + one, with a workspace on that machine. A mesh-scoped agent has no home node by definition, so + the model does not currently have a shape for Nox. Extending it — an agent whose scope is the + mesh rather than a machine — is a decision of its own and is not taken here. +- Two levels of identity now exist where there was one: the node, and the mesh. The distinction + has to stay visible in every surface, or "ask Nox" and "ask a node" collapse into each other + and it stops being clear who is answering. + +## References + +- [ADR 0012](0012-agents-are-persistent-employees.md) — what an identity is in this system, and + why `Nox` needs no separate mechanism. +- [ADR 0020](0020-design-is-written-in-two-layers.md) — why the as-is and to-be layers can + legitimately use different names for the same system. +- The dotfiles origin, and the naming inheritance it explains: + [`03-DESIGN/00-as-is/10-module-catalogue.md`](../03-DESIGN/00-as-is/10-module-catalogue.md). diff --git a/02-DECISIONS/0028-hq-is-company-scoped.md b/02-DECISIONS/0028-hq-is-company-scoped.md new file mode 100644 index 0000000..d4aef7d --- /dev/null +++ b/02-DECISIONS/0028-hq-is-company-scoped.md @@ -0,0 +1,89 @@ +--- +status: accepted +date: 2026-08-23 +deciders: jochen +reconstructed: false +--- + +# 28. HQ is company-scoped; the mesh is its first product + +## Context + +This repository was `hal-hq` — one product's headquarters, named for the product. Then the +product was renamed ([ADR 0027](0027-the-product-is-novox-mesh.md)), which forced the question +of what the repository is actually the headquarters *of*. + +Two facts settled it, and both were checked rather than assumed. + +**Novox already delivers other things.** The company's forge organisation holds live projects +beside the mesh, and they are registered as build sources — meaning the mesh already builds and +deploys them. They are not hypothetical future products; they exist and ship today. + +**They are tenants, not peers.** They run *on* the mesh. Every one of them is developed, +delivered and hosted by it. So the mesh is not one product among several — it is the ground the +others stand on. + +That distinction decides the scope. If the mesh were a product beside others, a per-product HQ +would be right. Because it is the substrate the company operates on, a decision about the mesh +is a decision about how the company works. + +## Considered options + +1. **`mesh-hq` — one HQ per product.** The safe choice, and the reversible one: a second + product creates its own HQ and shared practice graduates upward later. Rejected, knowingly, + because it models the mesh as a peer of things that are actually its tenants. +2. **A company HQ *and* a product HQ, from the start.** Rejected as ceremony — two repositories + for one operator, and the constitution's own YAGNI rule says not to. +3. **One company-scoped HQ, `novox/hq`, with the mesh as its first product.** Chosen. + +## Decision + +The repository is **`novox/hq`** — Novox's headquarters, not the mesh's. + +It holds the reasoning behind what Novox builds. Today almost all of that is the mesh, because +the mesh is what Novox is building. That is a fact about the present, not a definition of the +repository. + +**The scope of each document is fixed now, so the eventual split is mechanical rather than +archaeological:** + +| Scope | Documents | Moves if products separate? | +|---|---|---| +| **Company** | [`how-we-build.md`](../00-META/how-we-build.md), [`process/`](../00-META/process/), [`repos.md`](../00-META/repos.md), this record and [0019](0019-hq-is-its-own-repository.md)–[0027](0027-the-product-is-novox-mesh.md) | No — they stay at the top | +| **Product (mesh)** | [`mission.md`](../00-META/mission.md), [`context.md`](../00-META/context.md), [`effect.md`](../00-META/effect.md), `01-RESEARCH`, `03-DESIGN`, `04-ISSUES`, records 0001–0018 | Yes — into a product section | + +The folders are **not** restructured now. One product's content under a company name is +correct while there is one product's worth of it, and nesting before there is anything to nest +is the ceremony option 2 was rejected for. + +## Consequences + +- Engineering practice has a home that does not belong to the mesh. `how-we-build.md` — never + write to production directly, migrations for schema changes, runtime evidence for behavioural + criteria — is true of any Novox project, and its being in a mesh repository was always a + slight mislabelling. +- The constitution derived from it ([ADR 0025](0025-hq-is-the-source-of-the-constitution.md)) + can legitimately govern work outside the mesh. Under a product HQ it could not have, without + either duplicating or reaching across repositories. +- **The bet is not entirely forward-looking, and that is worth being honest about.** Novox + already has work that is *not* a mesh tenant — client engagements and at least one product + that is developed outside it. So the company genuinely has a scope wider than the mesh + **today**, which strengthens the case for a company HQ and simultaneously means the split in + the table above is closer than "some day". The table is not a precaution; it is a plan whose + trigger already half-exists. +- What has *not* happened yet is any of that work needing the constitution. That is the actual + trigger ([ADR 0025](0025-hq-is-the-source-of-the-constitution.md)): the moment something + outside the mesh must be governed by the same rules, product-level content moves down a level + and this repository becomes what its name already claims. +- A new repository was created rather than the old one transferred — the forge predates the + transfer API. `jschoubben/hq` is left in place untouched; it is not the source of truth and + nothing points at it. +- The mesh's own documents now live one conceptual level below the repository they are in. A + reader arriving at `01-RESEARCH` should understand it as the mesh's research, not Novox's. + Nothing in the folder names says so, and that is the cost of not restructuring. + +## References + +- [ADR 0027](0027-the-product-is-novox-mesh.md) — the product name that forced the question. +- [ADR 0019](0019-hq-is-its-own-repository.md) — why HQ is a repository at all. Unchanged; only + its scope moves. diff --git a/04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md b/04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md index 3725926..214127c 100644 --- a/04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md +++ b/04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md @@ -1,7 +1,7 @@ --- status: open opened: 2026-08-23 -located-in: [hal, hal-hq] +located-in: [hal, hq] fixed-by: amended-design: --- diff --git a/AGENTS.md b/AGENTS.md index a4ab546..4f49f5c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -# Agent instructions — hal-hq +# Agent instructions — Novox HQ This repository is the source of truth for the HAL mesh's mission, research, design and decisions. Implementation lives in the code repositories (see