From 4ae0b9411d09a3f9db6857e46f360313613a7c09 Mon Sep 17 00:00:00 2001 From: Vernon Stinebaker Date: Mon, 28 Sep 2026 22:10:19 +0800 Subject: [PATCH 1/2] docs: add AGENTS.md engineering protocol and CONTRIBUTING.md Consolidates the working conventions from recent orchestration work (A2A worker URL base convention, strict template rendering, FSM trigger naming, stored-workflow persistence) and the contribution flow with CI expectations. Module map remains in CLAUDE.md. --- AGENTS.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 15 +++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 AGENTS.md create mode 100644 CONTRIBUTING.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..30c812e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,59 @@ +# AGENTS.md — NullBoiler Engineering Protocol + +Default working protocol for coding agents in this repository. Scope: entire repository. +The module map and tech stack live in [CLAUDE.md](CLAUDE.md) and are kept authoritative there. + +## 1) Project Snapshot + +NullBoiler is the orchestration engine of the null stack: it decides what runs, +when, and on which worker. Zig 0.16.0, vendored SQLite (WAL), HTTP/1.1 JSON REST, +worker dispatch over webhook / api_chat / openai_chat / a2a (+ MQTT, Redis Streams). + +Division of labor (do not blur these boundaries): + +- `nulltickets` = durable task state (source of truth) +- `nullboiler` = orchestration policy (this repo) +- `nullclaw` (or compatible workers) = execution +- `nullwatch` = traces, evals, run intelligence +- `nullhub` = install, config, UI + +## 2) Architecture Facts (why this protocol exists) + +These are hard-won constraints — code changes must respect them: + +- The engine rebuilds the run graph from the **stored** `workflow_json`. Anything + strategy expansion derives (e.g. `depends_on` from `applyChain`) must be + persisted, not just used transiently (#36). +- A2A dispatch appends `/a2a` to the configured worker URL: worker URLs are + **base** URLs. `message/send` (A2A v0.3.0) is the wire format with `kind` + discriminators and required `messageId` (#42, #48, #53). +- Prompt templates render **strictly**: unresolved references fail the node + visibly. Never add silent-empty fallbacks (#40). +- `on_success.transition_to` / `on_failure.transition_to` are applied as the + pipeline FSM **trigger** name — the trigger must exist on the task's stage (#53). +- `/tracker/*` endpoints serve a published snapshot; never serve state under the + tick mutex (#41, #50). +- Known gaps — do not build on them: synchronous worker dispatch has no timeout + (#43); no-worker dead-ends wait silently without fail-fast (#44); MQTT and + Redis dispatch are stubs (#32). + +## 3) Engineering Principles + +- KISS / YAGNI / DRY (rule of three), fail fast with explicit errors. +- Determinism: tests must not depend on network, wall-clock ordering, or system state. +- Every code change ships with tests. `zig build test --summary all` must show + 0 failures and 0 leaks. Regression tests cite the issue they guard. +- Never weaken auth paths (worker tokens, API auth) or silently swallow dispatch + errors — unnamed failures are orchestrator bugs in themselves (#53). + +## 4) Validation + +```bash +zig build test --summary all # required before every commit +zig fmt --check src/ # required before every commit +zig build # dev build +``` + +## 5) Contribution flow + +See [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5c4007f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing to NullBoiler + +1. **Read [AGENTS.md](AGENTS.md)** first — it defines the engineering protocol, + architecture facts, and conventions for this repository. +2. One concern per PR. No drive-by refactors. +3. Before every commit: + - `zig build test --summary all` — 0 failures, 0 leaks + - `zig fmt --check src/` +4. Every PR runs the 4-target CI matrix (linux-x86_64, linux-aarch64, + macos-aarch64, windows-x86_64). Keep it green. +5. Bug fixes must include a regression test that reproduces the original + failure and cites the issue number. +6. API surface changes must update the OpenAPI export and the docs in + `docs/` (including `docs/multi-bot-integration.md` for worker protocol + changes). From 18c7814e4cc1eb048f0338d3f05553194d3b83a5 Mon Sep 17 00:00:00 2001 From: Vernon Stinebaker Date: Sun, 4 Oct 2026 00:23:30 +0800 Subject: [PATCH 2/2] docs(agents): mark on_failure.transition_to as intended contract, list in known gaps (DonPrus review) --- AGENTS.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 30c812e..4bab60d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,13 +29,16 @@ These are hard-won constraints — code changes must respect them: discriminators and required `messageId` (#42, #48, #53). - Prompt templates render **strictly**: unresolved references fail the node visibly. Never add silent-empty fallbacks (#40). -- `on_success.transition_to` / `on_failure.transition_to` are applied as the - pipeline FSM **trigger** name — the trigger must exist on the task's stage (#53). +- `on_success.transition_to` is applied as the pipeline FSM **trigger** name — + the trigger must exist on the task's stage (#53). The same naming is the + **intended contract** for `on_failure.transition_to`, which is parsed but not + yet applied (#52). - `/tracker/*` endpoints serve a published snapshot; never serve state under the tick mutex (#41, #50). - Known gaps — do not build on them: synchronous worker dispatch has no timeout (#43); no-worker dead-ends wait silently without fail-fast (#44); MQTT and - Redis dispatch are stubs (#32). + Redis dispatch are stubs (#32); `on_failure.transition_to` is parsed but never + read — `driveFailed` goes straight to `failRun` (#52, closed without merge). ## 3) Engineering Principles