--- layer: to-be status: designed code: [hal] updated: 2026-08-23 decisions: [02-DECISIONS/0015-mesh-brokers-nodes-host-agents-think.md] --- # Work breakdown — the decomposition How [ADR 0015](../../02-DECISIONS/0015-mesh-brokers-nodes-host-agents-think.md) gets built, in what order, and where a human must look. Ordering is not preference. Each phase removes a constraint the next one needs gone. --- ## Rules of engagement These exist so the work can run largely unattended without accumulating the kind of damage this refactor is meant to remove. ### Autonomous by default An agent may, without asking: - read anything, measure anything, query any database read-only - create branches, write code and tests, open pull requests - run the test suite and typechecks - write and update `hq/` documents ### Always stop and ask - **destroying or overwriting data** — dropping a table, deleting a provision, rotating a live credential, removing a module from a node - **merging anything** — every merge is a human checkpoint, without exception - **a decision the ADRs do not already answer** — record the question in the relevant research effort rather than picking and moving on - **any change to `hq/00-META`** — it is stable by nature ### Definition of done for every task 1. tests written **and failing first**, then passing 2. typecheck clean in every package the change touches 3. the local mesh (Phase 0) comes up, and the behaviour is demonstrated in it 4. `hq/` updated if the task changed or answered anything documented 5. deployed, and **delivery verified on every node** — not "the pipeline was green" ### Non-negotiables carried from the current system - **Never edit mesh-managed files on disk.** Use the owning tool. - **Never write to production databases directly.** Migrations for schema, application code for data. - **Every schema change ships twice** — consolidated schema *and* an incremental migration. - **Expand, then contract.** Add the new shape, migrate, verify, and only then remove the old one — never in a single step. - **A green pipeline proves transport, not effect.** Verify the effect. --- ## Phase 0 — A mesh that runs locally *(prerequisite)* Nothing else starts until this exists. Every fault this refactor addresses was found in production because there was nowhere else to find it. | # | task | done when | |---|---|---| | 0.1 | Container image for a node runtime | a node process starts in a container and registers | | 0.2 | Compose topology: broker, registry DB, object store, *n* nodes | `up` yields a mesh that elects a provider node and settles | | 0.3 | Seed a minimal mesh: nodes, one module, one provision | a module deploys end-to-end with no external service | | 0.4 | Run the pipeline inside it | a push-equivalent produces a cascade and a deployed artifact | | 0.5 | Fixtures for the failure modes already known | credential rotation reaching a running session; a provider deploy rotating a shared credential; a migration that ships nothing — each reproducible on demand | **Checkpoint:** a human confirms the local mesh reproduces at least one bug from 2026-08-22 before any decomposition begins. --- ## Phase 1 — Make the model expressible The decomposition is impossible while a feature is a singleton per module. | # | task | done when | |---|---|---| | 1.1 | Decision record — named features, per-node opt-in (next free number) | accepted | | 1.2 | Manifest: declared `features:` with type + directory | a module declares two of one kind and both build | | 1.3 | Selection: `always` / flavor-selected / `optional` | a node installs a subset; artifacts stay flavor-blind | | 1.4 | `requires:` moves onto the feature | a schema feature's database is not provisioned where the feature is not installed | | 1.5 | Assignment carries the opted-in feature set | opting a node in requires no rebuild | **Checkpoint:** one existing module converted to declared features, deployed, verified — before any others follow. --- ## Phase 2 — Draw the boundary the domain already has Cheapest first, and each one proves the extraction pattern before the expensive ones. | # | task | extracted from | risk | |---|---|---|---| | 2.1 | `hal/knowledge` — one store, review workflow ported | hippocampus + noxflow `knowledge_*` | low — additive | | 2.2 | `hal/stream` — the record; notifications and messaging as views | axon, synapse, notifications, meetings, conversations | medium | | 2.3 | `hal/agents` — identity, licence, runs, memory, thoughts | noxflow agents, `hal/thoughts` | **high** — touches credentials | | 2.4 | `hal/work` — what remains of noxflow | noxflow tasks | medium | | 2.5 | `hal/ai` — provider integration, flavored | `hal/claude*` | medium | Each extraction is expand-then-contract: new context alongside, dual-write, verify, cut over, remove. **Never a move commit.** **Checkpoint:** after 2.1, a human confirms the extraction pattern before 2.2 begins. After 2.3, a human confirms credentials still reach every agent on every node. --- ## Phase 3 — Reclaim the kernel Only possible once domains have modules to own their code. | # | task | done when | |---|---|---| | 3.1 | Move work-domain code out of `hal/sdk` | `workflow-engine.ts`, `task-commands.ts` live in `hal/work` | | 3.2 | Move provider code out | `claude-credentials.ts` lives in `hal/ai` | | 3.3 | Move delivery code out | feature handlers, artifact manager, build executor live in `hal/delivery` | | 3.4 | Decide the residue | ADR: what `hal/sdk` keeps (open question 4) | **Measure:** `hal/sdk` line count, tracked per task. Today: **34,636** across **155** files. --- ## Phase 4 — Separate what the mesh runs from the mesh | # | task | done when | |---|---|---| | 4.1 | Decide the destination (open question 3) | ADR accepted | | 4.2 | Cross-repository dependency resolution proven | a catalogue module builds against a published `@hal/*` | | 4.3 | Move the 91 catalogue modules | this repository contains only mesh contexts | **Checkpoint:** move one application first and run it for a week before the rest follow. --- ## Sequencing constraints - **0 before everything.** Unverifiable refactors are how this list got long. - **1 before 2.** Extracting into contexts without per-node features recreates the module count inside the new names. - **2 before 3.** A domain can only own its shared code once the domain has a module. - **2.3 after 2.1 and 2.2.** Agents touch credentials; do it once the pattern is proven on cheaper contexts. - **4 last.** It is the only phase that is pure movement, so it is the only one safe to defer indefinitely. ## What "done" looks like Eight contexts. `hal/sdk` holding only what is genuinely cross-cutting. A mesh that stands up on a laptop. A module count that grows only when the domain does.