Reorder the plan for a minimal live loop, checked by an end-to-end test
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m46s

The priority is the smallest new loop running live, so M1.4 and M1.5 move
after M2.1. Each milestone is now checked by an automated end-to-end test
(new M1.6) against real resources, not a manual live run; manual runs are
for the new loop's first runs and phase ends.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
This commit is contained in:
dongarandClaude Opus 5.5 committed 2026-10-02 22:51:26 +00:00
1 parent 92e67b8bd9
commit 577a08bf95
1 file changed
+41 -26
+41 -26
View File
@@ -6,9 +6,10 @@
architecture says *what and why*; this document says *how and when*, and is revised architecture says *what and why*; this document says *how and when*, and is revised
as work lands. as work lands.
**The priority is live testing.** Work is ordered so the agent runs live against **The priority is a minimal new loop, running live.** Work is ordered to reach the
real resources as early and as often as possible, and what each run finds steers smallest end-to-end version of the conversational loop (M2.1) as soon as
what comes next. possible; everything not needed for it waits. Each milestone is checked by an
automated end-to-end test against real resources, not by hand.
--- ---
@@ -66,9 +67,11 @@ Only `nisse-dev` has real code; `nisse-core` and `nisse-ops` are placeholders.
`CLAUDE.md`. A milestone marked **needs discussion** starts with a design `CLAUDE.md`. A milestone marked **needs discussion** starts with a design
discussion first. discussion first.
- **Every change comes with tests,** through `scripts/check.sh`. - **Every change comes with tests,** through `scripts/check.sh`.
- **A live run follows each milestone that changes behaviour,** not just each phase: - **The end-to-end test follows each milestone** (M1.6): the real agent, real models,
a short bring-up run of what the milestone added. Findings are filed as issues and the Gitea sandbox and a real build host, driven by a scripted operator. It runs
either fixed before moving on or deliberately deferred. after each milestone, not on every push, since it spends model tokens. Manual
live runs are for the new loop's first runs and phase ends. Findings are filed as
issues and either fixed before moving on or deliberately deferred.
- **The Quint models move with the loop:** `orchestrator.qnt` while `control.py` - **The Quint models move with the loop:** `orchestrator.qnt` while `control.py`
runs, `loop.qnt` for the new loop, whose properties become tests as each piece runs, `loop.qnt` for the new loop, whose properties become tests as each piece
lands (Phase 2). lands (Phase 2).
@@ -86,11 +89,11 @@ Only `nisse-dev` has real code; `nisse-core` and `nisse-ops` are placeholders.
**M0.1 Retire the old spec.** **Done.** **M0.2 A bring-up script.** **Done.** **M0.1 Retire the old spec.** **Done.** **M0.2 A bring-up script.** **Done.**
### Phase 1 — Execution over SSH, and the agent in a container ### Phase 1 — Execution over SSH, and an end-to-end test
**M1.1 Work items in the state store.** **Done.** **M1.1 Work items in the state store.** **Done.**
**M1.2 Transcript views.** **Done.** (#78 closes when a live run confirms it.) **M1.2 Transcript views.** **Done.** (#78 confirmed live, and closed.)
**M1.3 Execution over SSH.** *Pre-approved.* **Done** (#93). **M1.3 Execution over SSH.** *Pre-approved.* **Done** (#93).
- `execute(host, command, *, secrets, stdin)` as the only way to run anything; file - `execute(host, command, *, secrets, stdin)` as the only way to run anything; file
@@ -106,26 +109,25 @@ Only `nisse-dev` has real code; `nisse-core` and `nisse-ops` are placeholders.
a branch named after the task; **publishing only the work (#80)**, brought a branch named after the task; **publishing only the work (#80)**, brought
forward from M2.1; credentials kept out of every repr. forward from M2.1; credentials kept out of every repr.
**M1.4 Projects** (D8). *Pre-approved.* **M1.6 The end-to-end test.** *Pre-approved.*
- The project entry in configuration: repository, default branch, build VM, label - Automates bring-up run 3: the assembled agent, real models, the Gitea sandbox and
defaults, secrets by name with their visibility, egress additions. a real build host, with a scripted operator that answers whatever the agent asks.
- Acceptance: the bring-up configuration is one project entry; a second project - Asserts what was checked by hand: a PR on the sandbox containing only the work,
needs only a second entry. pushed with the push credential; no credential in the clone; the planner's next
turn citing the facts rather than the executor's turns.
- Runs against the current loop now, and against the new loop from M2.1.
**M1.5 The agent as a container image.** *Pre-approved.* **Phase 1 acceptance:** the end-to-end test passes against the current loop.
- A Dockerfile for `nisse-dev`, stateless with a volume for state; a Gitea Actions
workflow that builds it and pushes to Gitea's registry on each release tag (X4).
- `bringup.sh` runs the image instead of a venv.
- Acceptance: a tagged release produces an image; a live run from the image.
**Phase 1 acceptance:** a live run, from the image, of a milestone and a review **Moved after M2.1:** M1.4 (projects) and M1.5 (the container image). Neither is
comment on the build VM. needed for a minimal loop running live; both are done before the switch-over
(M2.8), when several projects and deployment start to matter.
### Phase 2 — The new loop, as a thin slice first ### Phase 2 — The new loop, as a thin slice first
Built alongside `control.py`, reusing the state store, log, views, publisher, Built alongside `control.py`, reusing the state store, log, views, publisher,
pollers and recovery. The first milestone is the smallest end-to-end path; each pollers and recovery. The first milestone is the smallest end-to-end path; each
later one widens it and is followed by a live run. later one widens it and extends the end-to-end test (M1.6) to cover it.
**M2.1 The slice.** *Needs discussion* (the loop's shape in code). **M2.1 The slice.** *Needs discussion* (the loop's shape in code).
- An issue assigned to `dev-agent` → a work item (D1); a restatement in the item's - An issue assigned to `dev-agent` → a work item (D1); a restatement in the item's
@@ -137,23 +139,24 @@ later one widens it and is followed by a live run.
(#69, #70); the review-fix check after merge. (Publishing only the work, #80, (#69, #70); the review-fix check after merge. (Publishing only the work, #80,
landed early in M1.3.) landed early in M1.3.)
- `loop.qnt`'s properties for these paths become tests. - `loop.qnt`'s properties for these paths become tests.
- Acceptance: a live run of that path, plus a crash mid-publish. - Acceptance: the end-to-end test runs that path on the new loop, plus a crash
mid-publish; then a first manual live run.
**M2.2 The queue.** *Pre-approved.* Several items: states, park-and-switch with **M2.2 The queue.** *Pre-approved.* Several items: states, park-and-switch with
branches pushed, next-item order, blocked items from Gitea dependencies, a closed branches pushed, next-item order, blocked items from Gitea dependencies, a closed
PR handled (L1, D4). Live run with two issues and a dependency. PR handled (L1, D4). End-to-end: two issues and a dependency.
**M2.3 Threads and labels.** *Pre-approved.* Routing by thread, ambiguous commands **M2.3 Threads and labels.** *Pre-approved.* Routing by thread, ambiguous commands
asked about (L5); `bug` grace periods, `discuss`, `design`; questions and asked about (L5); `bug` grace periods, `discuss`, `design`; questions and
plain-language go-aheads (D1). Live run. plain-language go-aheads (D1). End-to-end: a bug and a feature, labelled and not.
**M2.4 Multi-milestone work and documents.** *Pre-approved.* Build plans in the **M2.4 Multi-milestone work and documents.** *Pre-approved.* Build plans in the
repository, `ARCHITECTURE.md` kept current, waiting for merges between milestones repository, `ARCHITECTURE.md` kept current, waiting for merges between milestones
(D2, D4). Live run of a two-milestone feature. (D2, D4). End-to-end: a two-milestone feature.
**M2.5 Conversations and new projects.** *Needs discussion.* Work started in **M2.5 Conversations and new projects.** *Needs discussion.* Work started in
conversation, record issues carrying their item's ID, the new-project flow and its conversation, record issues carrying their item's ID, the new-project flow and its
project entry (D1, D8, #29). Live run of a small new project. project entry (D1, D8, #29). End-to-end: a small new project.
**M2.6 Roles and capability profiles.** *Pre-approved.* `driver`, `helper`, **M2.6 Roles and capability profiles.** *Pre-approved.* `driver`, `helper`,
`expert`, `classifier` (L9); escalation triggers; delegation and `ask_expert` on the `expert`, `classifier` (L9); escalation triggers; delegation and `ask_expert` on the
@@ -162,6 +165,18 @@ new loop.
**M2.7 Conversation.** *Pre-approved.* Explanations, progress in prose, asking **M2.7 Conversation.** *Pre-approved.* Explanations, progress in prose, asking
mid-work (L5, #42, #77). mid-work (L5, #42, #77).
**M1.4 Projects** (D8). *Pre-approved.*
- The project entry in configuration: repository, default branch, build VM, label
defaults, secrets by name with their visibility, egress additions.
- Acceptance: the bring-up configuration is one project entry; a second project
needs only a second entry.
**M1.5 The agent as a container image.** *Pre-approved.*
- A Dockerfile for `nisse-dev`, stateless with a volume for state; a Gitea Actions
workflow that builds it and pushes to Gitea's registry on each release tag (X4).
- `bringup.sh` runs the image instead of a venv.
- Acceptance: a tagged release produces an image; the end-to-end test runs from it.
**M2.8 Switch over.** *Pre-approved, after acceptance.* `nisse-dev` runs the new **M2.8 Switch over.** *Pre-approved, after acceptance.* `nisse-dev` runs the new
loop; `control.py`, its tests and `orchestrator.qnt` are removed. loop; `control.py`, its tests and `orchestrator.qnt` are removed.