SPEC v0.3: orchestrator resolutions of the plans' open points

Records D-004 and D-015 to D-025: shells and ownership, server seams
(router middleware, rate_limit layer, tasks::start, AuditWriter and PushQueue
traits, next_occurrence_date in kvitt-domain, M3 owns recurring generation,
M4 lands after M3), OpenAPI parsed-value equality, feature convention and
strings, empty fake scenario and resolveRange exception, shared ledger rows and
editor fields in :core:design, no bundled font, pruning at 04:00, development
infrastructure as M2c-dev built it, M2c-pi allowances, release keystore,
production import procedure. Plans and prompts close their open points;
HANDOFF rewritten to the real state; CLAUDE.md: implementation agents never
edit SPEC.md or docs/decisions.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-17 21:23:38 +02:00
parent c885aba313
commit 76ee957f41
45 changed files with 501 additions and 342 deletions
+3 -3
View File
@@ -9,7 +9,7 @@ Operating guide for AI agents and humans working on **Kvitt**. This is the only
## SOURCE OF TRUTH
* **`SPEC.md` wins.** If a plan, this file or existing code disagrees with the spec, the spec is right.
* A revised decision updates the spec **in the same change**, with an entry in `docs/decisions.md` (numbered D-001…; never deleted, revised in place with a pointer).
* A revised decision updates the spec **in the same landing**, with an entry in `docs/decisions.md` (numbered D-001…; never deleted, revised in place with a pointer). Only a docs agent edits `SPEC.md` and `docs/decisions.md` (see Numbering).
* Each `PLAN-*.md` lists the spec sections to read first. Read them before writing anything.
* Never encode a threshold, limit or rule that is not in the spec. Ask, or leave a `TODO(spec)`; a wrong number is worse than a missing one.
* One handoff: `docs/HANDOFF.md`, rewritten in place. One decisions log. One working-rules file (this one). Delete superseded copies the same day; never keep two sources of truth.
@@ -44,7 +44,7 @@ The owner talks to one **orchestrator** session. The orchestrator plans, briefs,
* **Briefs are the whole context an agent has.** A brief states: the goal, what to read first (file paths), what is already established, the exact numbers it may use (next free decision, spec version, schema), the setup steps, the gate, what to report. If the orchestrator cannot write a clear brief, it does not understand the task yet.
* **Agents' reports are not shown to the owner.** The orchestrator extracts the decision: one line per finding, fixed or not, and relays every owner step in chat.
* **Subagents are Opus.** Haiku or Sonnet only for a read-only scan the owner explicitly asks for that way.
* **Numbering** (decisions, spec versions, schema versions, contract requests) is handed out by the orchestrator in the brief. Two parallel agents get disjoint ranges; the second to land renumbers to be contiguous on rebase.
* **Numbering** (decisions, spec versions, schema versions, contract requests) is handed out by the orchestrator in the brief. Two parallel agents get disjoint ranges; the second to land renumbers to be contiguous on rebase. **Implementation agents never edit `SPEC.md` or `docs/decisions.md`:** they put proposed decision entries and spec text, numbered from their range, in their report, and the orchestrator has them recorded by a docs agent, landed together with the implementation.
* **Parallel agents** each have their own worktree, build through `tools/gradle-serial.sh` (one Gradle build at a time on this machine), and take turns on the phone: **one agent on the phone at a time**, named in the brief.
---
@@ -106,7 +106,7 @@ python3 tools/dependency-report/latest.py # version drift of android/gradle/li
* **Version drift:** run the dependency report at the start of every plan. A library more than one stable minor behind gets a line in the plan's report; a toolchain component more than one line behind triggers an upgrade plan first.
* **Screenshots.** Goldens are committed; `check` fails when a render differs. Re-record only for an intended change and **open every changed PNG** before committing. Code that compiles is not evidence of a good screen.
* **Every schema change gets a migration and a migration test** (sqlx migration on the server, Room migration on the phone). User data stored in the database is not derived data and must survive every migration.
* **Contracts are versioned.** A change to any contract file (`contracts/openapi.yaml`, the SQLite schema, the sync protocol, the Room entities, `contracts/test-vectors/*.json`, the push payload) requires a spec version bump and a `docs/decisions.md` entry in the same change. Number both from the brief.
* **Contracts are versioned.** A change to any contract file (`contracts/openapi.yaml`, the SQLite schema, the sync protocol, the Room entities, `contracts/test-vectors/*.json`, the push payload) requires a spec version bump and a `docs/decisions.md` entry, landed together with it: the implementation agent proposes both in its report (numbered from the brief) and a docs agent records them (Numbering). Representational edits to `contracts/openapi.yaml` (key order, `$ref` naming, description wording) need neither (SPEC §14.8).
* **Cargo builds** are not serialised by `gradle-serial.sh`; run at most one `cargo build`/`cargo test` per worktree at a time and never build Docker images for the Pi while a Gradle build runs.
---