Commit Graph
160 Commits
Author SHA1 Message Date
dev-agent e6aaa4783d Merge pull request 'Add a bring-up script and a transcript dump; let nisse-dev install on its own VM (M0.2)' (#86) from bringup-script into main
CI / checks (push) Successful in 1m28s
2026-10-01 16:18:15 +00:00
dongarandClaude Opus 5.5 a18321b4b0 Add a bring-up script and a transcript dump; let nisse-dev install on its own VM (M0.2)
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m16s
Development Plan M0.2.

- scripts/bringup.sh: start [REF] sets the previous run aside under
  /root/nisse-e2e/runs/, exports the ref under test and starts the agent
  as the transient systemd unit nisse-bringup, so it outlives the shell
  that started it; stop (SIGTERM, clean shutdown), status, logs, and
  collect (the journal log and a readable transcript).
- nisse_dev.dump (python -m nisse_dev.dump STATE_DB [--full]): a readable
  dump of a state store's state, pending intents and canonical log. Opens
  the store read-only, so it is safe against a live agent.
- The agent runs as root on this development VM, as it will on its own
  VM. Architecture D3/D6/D7 corrected to match the operator's intent:
  installing packages and toolchains on its own VM is class 2, recorded
  so the environment can be rebuilt (it was class 3 with provisioning an
  open question); egress names OS package mirrors. The plan's M0.2, M4.1,
  M4.2 and bring-up guards follow.

Acceptance: a smoke run started, answered status in the test room,
stopped cleanly, and collect produced the log and transcript.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-10-01 16:16:32 +00:00
dongar 678466c176 Merge pull request 'Retire the old build spec, and point every reference at the architecture (M0.1)' (#85) from retire-old-spec into main
CI / checks (push) Successful in 1m15s
Reviewed-on: dongar/nisse#85
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-10-01 00:52:53 +00:00
dongarandClaude Opus 5.5 1ad0b2147d Retire the old build spec, and point every reference at the architecture (M0.1)
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m22s
Development Plan M0.1. Every section reference in code, tests, specs/,
the example config, the tuning guide, and the CLAUDE.md and README files
now cites docs/Architecture.md (P, L, D, O, X, Q) instead of the old
spec's A-H, and docs/Architecture-Build-Spec.md is deleted (git keeps
it). The plan's old-to-new table goes with it.

Mostly mechanical, with a per-site choice where one old section split:
A4 became L2 where it meant stop/abandon/the loop and L3 where it meant
approvals; A10 became L6 in the context-budget code and L7 elsewhere; B2
became D4 for outbound Gitea and publishing and D5 for review intake;
'A3 step N' became the matching step of L8's boot sequence. Comments
describing behaviour the architecture drops (planning always escalating,
thresholds tuned at an old build step) now describe the current code and
point at the Development Plan.

docs/Architecture.md gains one line the rewrite missed: intake outages
delay but never fail work (old B2), now in L5, where the poller and
Matrix code cite it.

Comments and docs only; no behaviour change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-10-01 00:17:48 +00:00
dongar 890708594b Merge pull request 'Propose the Development Plan' (#84) from development-plan into main
CI / checks (push) Successful in 1m14s
Reviewed-on: dongar/nisse#84
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-30 21:07:39 +00:00
dongarandClaude Opus 5.5 ae6513fd26 Development Plan: say which open issues are superseded, and which stay open
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m15s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-30 21:06:13 +00:00
dongarandClaude Opus 5.5 f53b2777bc Propose the Development Plan, and mark the architecture agreed
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m22s
docs/Development-Plan.md: where the code stands against each section of
docs/Architecture.md, the environment today, how we work (plan-first per
milestone, tests, the Quint model, a bring-up run on this box ending
each phase), and seven phases of milestones from housekeeping to
nisse-ops, each marked pre-approved or needs discussion. Every open
issue is mapped to a milestone or marked superseded; an old-to-new
section table serves the reference update in M0.1.

docs/Architecture.md: status now agreed; D7 regains the browser tool
for the internal test network, left out of the rewrite by mistake.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-30 19:47:19 +00:00
dongar 73a035dfcc Merge pull request 'Draft: rewrite the architecture (docs/Architecture.md)' (#83) from architecture-rewrite into main
CI / checks (push) Successful in 1m14s
Reviewed-on: dongar/nisse#83
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-30 19:40:21 +00:00
dongarandClaude Opus 5.5 a18294fa0c Draft: rewrite the architecture as docs/Architecture.md
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m18s
A full rewrite of the architecture, following the outline agreed with the
operator: a threat model of mistakes, injection and crashes rather than a
malicious model; actions classed by their effects; hard walls, a
deterministic fast path and an action classifier; a conversational loop
driven by a local model with frontier helpers; approvals as scoped
permissions with pre-approved milestones and a trust dial; context and
memory, including agent memory; documents as nisse-dev's workflow.

Added beside docs/Architecture-Build-Spec.md, which stays until this is
agreed; the Development Plan and reference updates come after. New
section letters (P, L, D, O, X, Q) avoid clashing with the old A-H
references in the code meanwhile.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-30 15:50:24 +00:00
dongar d302d337d6 Merge pull request 'Redeliver an interrupted review comment, and close the issue on completion' (#76) from redeliver-review-and-close-issue into main
CI / checks (push) Successful in 1m25s
Reviewed-on: dongar/nisse#76
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 20:37:04 +00:00
dongarandClaude Opus 5.5 848bd9f122 Redeliver an interrupted review comment, and close the issue on completion
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m16s
Fixes counterexamples 6 and 7 from specs/orchestrator.qnt, the last two.

6. A crash while the executor answered a review comment lost it: its
   cursor is saved before the work (at most once), and a restart in
   PR_OPEN resumed quietly. Now pr.reviewing marks the comment until
   the executor returns (every way it returns, but not a crash), and
   boot resumes the watch just before it, with a notice. The mark stays
   until it is answered, so a second crash cannot lose it either.
7. 'project complete' left the plan issue open. It now closes it with a
   note, after IDLE is saved, as abandon does (shared helper).

The model marks and redelivers, and closes the issue; scenarios 6 and 7
now expect their properties to hold. A mutant without redelivery fails
scenario 6. All eight properties held together over 300,000 traces.
No xfail reproductions remain.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 20:30:14 +00:00
dongar 83a4bd72b5 Merge pull request 'Adopt an already-published PR instead of publishing again' (#75) from adopt-published-pr into main
CI / checks (push) Successful in 1m15s
Reviewed-on: dongar/nisse#75
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 20:14:47 +00:00
dongarandClaude Opus 5.5 8bd1ac0fa2 Adopt an already-published PR instead of publishing again
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m12s
Fixes counterexample 5 from specs/orchestrator.qnt. A crash after the
PR was opened but before PR_OPEN was recorded left the agent in
EXECUTING; the restart question's 'continue' and 'start' then published
again, Gitea refused a second PR, and there was no way back to PR_OPEN.
On the live run the executor model happened to notice the existing
work; recovery must not depend on that.

- Boot (A3 step 4): in EXECUTING, if Gitea shows the milestone's PR
  open, adopt it, watch it from the start, and resume in PR_OPEN with a
  notice. Gitea unreachable or the PR closed: the restart question, as
  before.
- MilestonePublisher.publish is idempotent: after pushing, an open PR
  for the branch is adopted (and so updated) rather than a second one
  opened. This also covers a PR opened whose response was lost.
- The model adopts too, gains the lost-response outcome, and now counts
  PRs opened per milestone (one_pr_per_milestone was a flag the fixed
  model could never set). A mutant without adoption fails the new
  scenario; the properties held over 200,000 traces each.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 19:58:19 +00:00
dongar 6fdec6922b Merge pull request 'Bind approvals and feedback to the revision they were about' (#74) from bind-approvals-to-revisions into main
CI / checks (push) Successful in 1m21s
Reviewed-on: dongar/nisse#74
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 19:45:07 +00:00
dongarandClaude Opus 5.5 97863c1939 Bind approvals and feedback to the revision they were about
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m16s
Fixes counterexamples 1-4 from specs/orchestrator.qnt: a repeated
'approve', 'approve rev-1' meant for the architecture, approving on both
channels, and 'approve' plus an afterthought all landed on the next
plan, one the operator had not seen.

- Revisions are numbered across the work item (A4 already required
  monotonic tags; the code numbered per gate), so rev-N names one plan.
- Each reply is stamped on arrival with the revision that was up: in
  Matrix the one whose approval request had been sent (a plain value
  the transport thread reads, restored on boot), in Gitea the latest
  plan comment older than the reply (board.posts).
- Gate.evaluate applies a reply that names no revision only if its stamp
  is the current revision. Otherwise an approval is not applied and
  feedback rejects nothing (it is still in the transcript), and the
  agent says which revision is up. 'approve rev-N' binds by its number.
- Spec A4 states both rules. The model applies them; scenarios 1-4 now
  expect the properties to hold, and both held over 200,000 random
  traces and Apalache's exhaustive check to depth 8.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 19:13:20 +00:00
dongar 6c83839f4d Merge pull request 'Model the orchestrator in Quint, and reproduce its counterexamples' (#73) from quint-orchestrator-spec into main
CI / checks (push) Successful in 1m22s
Reviewed-on: dongar/nisse#73
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 18:56:29 +00:00
dongarandClaude Opus 5.5 9f38e7a467 Ignore Apalache's output directory
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m18s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 18:52:06 +00:00
dongarandClaude Opus 5.5 d79e399933 Model the orchestrator in Quint, and reproduce its counterexamples
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m14s
specs/orchestrator.qnt models control.py: states, gate, pending
questions, comment cursors, publish intents and the worker queue, with
operator messages, Gitea comments, work outcomes (exceptions included)
and a crash at any point interleaving freely. Eight properties.

Seven counterexamples, each written out as a trace in
specs/orchestrator_scenarios.qnt and reproduced against the real code in
nisse-dev/tests/test_quint_counterexamples.py (xfail, strict, until
fixed):

1-4 an approval or feedback lands on a plan the operator had not seen:
    a double 'approve', 'approve rev-1' meant for the architecture,
    approving on both channels, and 'approve' plus an afterthought;
5   a crash after the PR opens but before PR_OPEN publishes again and
    cannot get back to PR_OPEN;
6   a crash while answering a review comment loses it silently;
7   'project complete' leaves the plan issue open.

no_stranding, await_input_has_a_question and execution_needs_approval
held over 200,000 random traces of 40 steps, and under Apalache's
exhaustive check to depth 8, which does find counterexample 1 at that
depth. No behaviour changes here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 18:51:59 +00:00
dongar 26dabc3d54 Merge pull request 'Match approvals and commands regardless of case and trailing punctuation' (#72) from case-insensitive-commands into main
CI / checks (push) Successful in 2m11s
Reviewed-on: dongar/nisse#72
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 18:00:27 +00:00
dongarandClaude Opus 5.5 6afd0cc914 Match approvals and commands regardless of case and trailing punctuation
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m15s
A phone keyboard's "Approve" did not match the approval pattern, so it
counted as rejection feedback and threw the plan away; "Stop" did not
reach the cancel flag; other capitalised commands got a hint instead of
acting.

gates.command_form() is how a message reads as a command: case,
surrounding whitespace, inner runs of whitespace and a trailing '.' or
'!' do not matter. The approval gate and every command match in the
orchestrator (stop, status, abandon, use, start milestone, next
milestone, project complete, the restart choices) use it. Only matching
changes: the project name in 'use <name>' keeps its case, and feedback
and answers are recorded and passed on as written. A stale revision is
still refused, and approval still needs the whole message to be the
command.

Closes #64.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 17:57:34 +00:00
dongar b893fba342 Merge pull request 'Add the abandon command' (#71) from abandon-command into main
CI / checks (push) Successful in 1m15s
Reviewed-on: dongar/nisse#71
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 17:52:30 +00:00
dongarandClaude Opus 5.5 d68e3b3a83 Add the abandon command
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m18s
A4 already names abandon as one of the ways out of a halt (continue,
re-plan, or abandon) and 0.2 closes a work item as completed or
abandoned, but no command did it: from a gate or a question the only way
to drop a task was to edit the state database.

- 'abandon' ends the task from any waiting state and returns to IDLE.
  The move is made durable first; then the plan issue and any open
  milestone PR are closed with a note (branches kept), and any
  unresolved intent is aborted so boot reconciliation does not gate on
  work dropped on purpose. A Gitea failure is reported, not fatal.
- Like 'status' it is a command in every state, never read as an answer
  or feedback. While work runs, 'stop' comes first, as before.
- The restart / stranded question and the PR_OPEN hints mention it.
- Spec: B1 gains the abandon edge and B2 the command.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 17:43:43 +00:00
dongar 4e8ebea26a Merge pull request 'Keep Gitea threads watched across restarts and interruptions' (#68) from pr-open-handling into main
CI / checks (push) Successful in 1m20s
Reviewed-on: dongar/nisse#68
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 17:37:25 +00:00
dongarandClaude Opus 5.5 3b6aae92c5 Keep Gitea threads watched across restarts and interruptions
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m20s
- Record a comment cursor per thread (board.last_comment, the field that
  already existed unused; pr.last_comment), advanced durably when a
  comment is taken up. CommentPoller.resume_after() skips comments at or
  below it, so re-attaching needs no request and cannot replay.
- Boot re-attaches the plan watch at an open gate and the review watch in
  PR_OPEN from their cursors, catching up on comments posted while the
  agent was down (#59). Data saved without a cursor skips what is there,
  so an old approval cannot approve the current revision.
- A restart in PR_OPEN resumes with a notice instead of the restart
  question (#58). A stored restart question for PR_OPEN returns to it on
  either reply instead of re-planning the milestone.
- A stopped or failed review response gets its own pending kind; the
  reply returns to PR_OPEN and resumes the watch from the cursor, so
  comments that arrived meanwhile are delivered. It used to return to
  milestone sign-off, where starting the milestone would open a second PR.
- Comments ignored because of the state leave the cursor alone, so they
  are delivered once the agent is back where they apply.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 17:33:41 +00:00
dongar ab932f2ef4 Merge pull request 'Don't assert the exact word in the LiteLLM smoke test' (#67) from smoke-test-no-exact-word into main
CI / checks (push) Successful in 1m17s
Reviewed-on: dongar/nisse#67
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 17:24:43 +00:00
dongarandClaude Opus 5.5 1ab5d86a88 Don't assert the exact word in the LiteLLM smoke test
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m24s
The test checks that a request reaches the executor model through
LiteLLM and text comes back. It also asserted the model obeyed "Reply
with exactly one word: pong", which Haiku once answered with "ping" and
failed CI on #66. Assert non-empty text instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 17:22:24 +00:00
dongar 40b59e77bf Merge pull request 'Never leave the agent stranded in a working state' (#66) from no-stranded-states into main
CI / checks (push) Successful in 1m16s
Reviewed-on: dongar/nisse#66
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 17:21:42 +00:00
dongarandClaude Opus 5.5 b077906631 Let the live milestone test expect a waiting state after execution
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m19s
It drove the orchestrator until EXECUTING and accepted EXECUTING as the
end state, which with no publisher configured was the stranding this
branch removes: the milestone now finishes in PR_OPEN. Return once
'start milestone 1' is sent, since the milestone runs inside it, and
expect PR_OPEN or AWAIT_INPUT.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 17:17:19 +00:00
dongarandClaude Opus 5.5 92e5452161 Never leave the agent stranded in a working state
CI / checks (push) Skipped
CI / checks (pull_request) Failing after 1m20s
The first live run found four dead ends one at a time: states where no
operator message could move the agent. Most had one shape: work ended,
by an exception or by a path that never transitioned, and left the agent
in PLANNING_* or EXECUTING, where every message is answered "busy".
The worker only prints an exception, so that would keep happening.

- Every job the orchestrator runs for an operator message or a Gitea
  comment now goes through _settled(). If the job leaves a working state
  behind, whatever the reason, the agent moves to AWAIT_INPUT with the
  continue / re-plan choice a restart offers, and says why. An exception
  in a waiting state is reported and the state kept, since its commands
  still lead on.
- A sign-off state whose gate record is missing asks to plan again
  instead of crashing on every reply.
- The stub configurations (no executor, no publisher) complete the
  milestone and wait in PR_OPEN instead of resting in EXECUTING.

test_no_stranding.py drives a whole two-milestone project with a fault
injected at each planner, executor and publisher call, and asserts after
every message that the agent is not in a working state and that the
project still reaches 'project complete'.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 16:39:20 +00:00
dongar 1ccea20a10 Merge pull request 'Publish work the executor committed itself, and gate when there is none' (#63) from publish-executor-commits into main
CI / checks (push) Successful in 1m13s
Reviewed-on: dongar/nisse#63
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 16:23:19 +00:00
dongarandClaude Opus 5.5 f97e459bc7 Publish work the executor committed itself, and gate when there is none
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m15s
On the first live run the executor committed its milestone itself, as
its plan asked. The publisher only published a commit it made, found a
clean tree, reported "no changes to publish", and left the agent in
EXECUTING, where every message is answered "busy".

- publish(): with nothing left to commit, publish anyway when the branch
  has commits origin/<base> lacks; report no changes only when it has
  none.
- push_followup(): same for review fixes, comparing HEAD with what the
  remote branch holds (ls-remote; pushes go by URL, so there is no
  tracking ref).
- Nothing to publish now gates to AWAIT_INPUT, and the reply returns to
  the still-approved milestone plan.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-09-29 16:17:41 +00:00
dev-agent 8283e9eb1c Merge pull request 'Handle leading mentions in Matrix messages' (#60) from matrix-mentions into main
CI / checks (push) Successful in 1m18s
2026-09-29 16:01:08 +00:00
dongarandClaude Opus 5.5 b0c5f48be4 Handle leading mentions in Matrix messages
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m24s
Clients put the addressee's name in front of a message that mentions
it ("Nisse Dev Testing: re-plan"), and the transport passed that text
on whole, so no command matched: the live run's re-plan was asked again,
and an addressed 'approve' would have counted as rejection feedback.

- A leading mention of the agent (an HTML pill, its user ID, or its
  display name followed by ':') is removed before commands are matched.
  The display name is learnt from the agent's own member event.
- A message whose leading mention is someone else is skipped: in a
  shared room it is addressed to another agent or person.
- Only the start counts; a mention later in the text is left alone.
- The transcript records the message as sent (InboundMessage.original).

The sender is unaffected: it still comes from the event's homeserver-set
sender field, never from the text.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 15:59:27 +00:00
dongar 9620404a2a Merge pull request 'Keep a pending question across restarts, and make the restart question answerable' (#57) from fix-await-input-restart into main
CI / checks (push) Successful in 1m20s
Reviewed-on: dongar/nisse#57
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 15:54:01 +00:00
dongarandClaude Opus 5.5 e5450e3e77 Keep a pending question across restarts, and make the restart question answerable
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m18s
A restart in AWAIT_INPUT replaced the saved pending item with a generic
"continue or re-plan?" whose answer nothing handled: the reply cleared
it and left the agent in AWAIT_INPUT with nothing to resume, where 'use'
was refused too. The first live run hit this after a planning failure
and could not be moved by any message.

- Waiting on the operator is a committed state (A3 step 8): on boot, ask
  the saved question again instead of replacing it. _await_input keeps
  the prompt with the pending item for this.
- The restart question (A3 step 7) records the state it interrupted, and
  'continue' / 're-plan' now do what they offer: re-run the interrupted
  planning turn, or return an interrupted milestone to its approved plan.
  Any other reply asks again rather than being swallowed.
- With nothing pending, 'use <project>' starts over, as the reply
  already advised.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 15:03:37 +00:00
dongar e5ed32bc2b Merge pull request 'Use qwen3.8-27b as the example executor' (#56) from executor-qwen3.8-27b into main
CI / checks (push) Successful in 1m18s
Reviewed-on: dongar/nisse#56
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-29 14:20:25 +00:00
dongarandClaude Opus 5.5 fe73112aa2 Use qwen3.8-27b as the example executor
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m22s
It led the executor benchmark (PR #55): 37/40 over eight tasks and 17/20
on the harder four, ahead of claude-haiku-4-5's 15/20. local-fast, the
previous example, scored 0/8 on the harder four. Model selection is on
the dev executor alone for now; the shared-host question (spec Part H)
stays open.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 14:18:50 +00:00
dongar dfa08d4900 Merge pull request 'Benchmark the finalists on all eight tasks, and archive older results' (#55) from bench-results-harder-tasks into main
CI / checks (push) Successful in 1m17s
Reviewed-on: dongar/nisse#55
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-28 12:41:48 +00:00
dongarandClaude Opus 5.5 4b6c48cc96 Benchmark the finalists on all eight tasks, and archive older results
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m12s
Five runs per task at 320 W with max_turns 40, after the fixes in
#50-#52, for qwen3.8-27b, qwen3.6-35b-a3b, gemma-4-26b-a4b,
devstral-small-2-24b and mimo-v2.6-9b; the harder four also for
claude-haiku-4-5 as the ceiling, and two calibration runs each for
local-fast as the floor. Runs failed by the proxy's rate limiter were
set aside, not stored.

Earlier results move to bench/results/archive/, which the report does
not read: they were made at other power caps, at max_turns 24, or on
the RTX 4070, and are kept as the record.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 03:14:40 +00:00
dongar a891932739 Merge pull request 'Spec: prefer one local model for all roles; record host sharing, park vision' (#54) from spec-shared-inference-host into main
CI / checks (push) Successful in 1m16s
Reviewed-on: dongar/nisse#54
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-28 01:47:08 +00:00
dongarandClaude Opus 5.5 2ab86bf0da Spec: OpenSCAD work needs vision, in nisse-dev or its own agent
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m18s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 01:32:20 +00:00
dongarandClaude Opus 5.5 75d96b4197 Spec: restore the blank line before the section rule
CI / checks (push) Skipped
CI / checks (pull_request) Failing after 1m14s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 01:30:36 +00:00
dongarandClaude Opus 5.5 9239a56bd1 Spec: park vision as a need of future agents, not current ones
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m20s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 01:30:18 +00:00
dongarandClaude Opus 5.5 50a2a75342 Spec: prefer one local model; add vision as an open decision
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m19s
The host-sharing item now records the operator's preference: one local
model for every local role, with agents tagging in and out of the host
as the fallback if no single model fits. A new item records vision as a
requirement (OpenSCAD renders, later video files) and what the text-only
agent needs before any vision work.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 01:29:29 +00:00
dongarandClaude Opus 5.5 e5c18b3bf4 Spec: record sharing the local inference host as an open decision
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m15s
nisse-dev and nisse-ops both send local roles to the one 24GB host,
where llama-swap keeps one model resident. Different models per agent
would reload weights on every switch. Per-key rate limits don't help.
Lists the options, simplest first, to decide after the executor
benchmark and the ops evaluation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 01:25:38 +00:00
dev-agent 8467b8747f Merge pull request 'Add four harder benchmark tasks' (#53) from harder-bench-tasks into main
CI / checks (push) Successful in 1m17s
2026-09-28 00:31:17 +00:00
dongarandClaude Opus 5.5 277bff6fcd trace-bug: say how much precision the rates need
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m14s
Calibration showed Haiku fixing the right constant but keeping only four
decimal places, which passes the visible test and still loses the JPY
rate's precision. An explicit plan should say so.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 22:43:39 +00:00
dongarandClaude Opus 5.5 25fd57351d Add four harder benchmark tasks
All seven newer local models passed the original four tasks 20 of 20,
so the benchmark no longer told them apart. The new tasks keep plans
explicit, as the planner is told to write them, and make the work
itself harder:

- trace-bug: a wrong multi-currency total whose cause is a shared
  rate helper; discounts and tax go through it too, so a fix at the
  call site fails the check.
- refactor-rename: rename load_config across a ten-module package,
  leaving load_config_defaults and reload_config alone.
- spec-parser: implement parse_duration from an eight-rule SPEC.md
  given three examples, and write tests for every rule.
- long-milestone: eight dependent steps adding due dates to a task
  tracker, from the model through storage versions to the CLI.

Self-tests prove that a call-site fix, a blind text replace and a
partial rename all fail their checks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 22:43:39 +00:00
dongar f2c48d8b16 Merge pull request 'Keep runs with different tuning apart in the report, and raise max_turns to 40' (#52) from report-keeps-tuning-apart into main
CI / checks (push) Successful in 1m13s
Reviewed-on: dongar/nisse#52
Reviewed-by: Don Garrett <dgarrett@acm.org>
2026-09-27 22:43:26 +00:00
dongarandClaude Opus 5.5 f881a18ca4 Keep runs with different tuning apart in the report, and raise max_turns to 40
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m11s
The report grouped runs by model, serving note and task version, so
runs made at different tuning were silently averaged together. Tuning
is now part of the key, and a tuning column shows how a row's settings
differ from today's defaults; it appears only when some row needs it.

tuning.executor.max_turns goes from 24 to 40. On the harder benchmark
tasks Haiku, the calibration ceiling, hit 24 on both refactor-rename
runs and both long-milestone runs, one of which had finished the work.
The cap guards against a model trying forever; it isn't a budget.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 22:25:14 +00:00