Commit Graph
6 Commits
Author SHA1 Message Date
dongarandClaude Opus 5.5 6ae2375194 M2.8: switch over to the new loop
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 2m16s
CI / e2e (pull_request) Successful in 10m51s
nisse-dev now runs only the conversational loop. The gated state machine
it was built alongside is gone:

- Removed control.py, planner.py, executor.py, approvals.py, gates.py
  (command_form moves to loop/reader.py), publish.py and poller.py, the
  old assembly in agent.py (its shared helpers move to loop/build.py),
  the store's state-machine view (get_state, transition), their tests,
  the old end-to-end and live planning/milestone/gate tests, and
  specs/orchestrator.qnt with its scenarios.
- Roles are driver, helper, expert and classifier; driver is required.
  loop:, roles.planner, roles.executor and tuning.executor are refused
  with what to use instead; tuning.driver takes the turn cap and failure
  limit.
- The benchmark and the capability matrix measure the driver: the
  loop's own system prompt and tools, the task's plan as the agreed
  restatement. Task plans end with finish_milestone, so earlier runs
  show as (old); stored runs' executor tuning reads as the driver's.
- A delegation on the loop records what its helper's alias resolved to
  (L9), as the old path's did.
- The dump shows a work item's revision and what it waits for.
- Behaviour the old tests covered and the loop shares stays covered:
  driver runs that fail on a model call, stop mid-turn, reset the
  failure count; go-aheads ignoring case and punctuation; a request too
  big to fit is never sent; the assembly tests, now on build_loop_agent.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-10-08 03:12:58 +00:00
dongarandClaude Opus 5.5 83804fe02a Put work items in the state store, and bind the log to them (M1.1)
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m14s
Development Plan M1.1, as discussed.

- Schema v4: a work_items table (id, scope, title, status, outcome,
  position, data) and an agent row whose active_item points at one
  (NULL: idle). Canonical events and intents carry their work item, and
  events their actor. Older stores are refused with a clear message:
  there was no production data, so no migration (the mechanism stays).
- The log is reached through a Transcript bound to one work item and
  one actor: store.transcript(item, actor) reads only that item and
  writes with both. The planner, executor, delegation and expert desk
  get one per call from the orchestrator instead of holding the store,
  so a component can neither read another task's events (the planner
  read every earlier task's, #78) nor write without attribution.
  store.all_events() is kept for readers that span items (evaluation
  capture, dumps). Intents are begun through the transcript or with
  work_item=, so each belongs to its item.
- The orchestrator opens a work item on 'use', closes it with its
  outcome (completed or abandoned), and carries what the operator said
  while idle into the new item as copies with their origin, so a task
  sent before 'use' is still planned from (D1). control.py keeps its
  state machine through get_state()/transition(), now over the active
  work item, until M2.6 retires it.
- nisse_dev.dump shows work items and each event's item and actor.

Tests: test_work_items.py (scoping, attribution, intent ownership,
restart, outcomes, carried messages, a second task never seeing the
first); the suites updated for the per-call transcript.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-10-01 23:20:29 +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
dongarandClaude Fable 5 ac81dd6234 Add canonical event log and renderer skeleton (A10)
CI / checks (push) Successful in 9s
CI / checks (pull_request) Successful in 8s
Build-order step 4, sequenced before the LLM client (step 3) because
the client interface consumes the canonical log.

- canonical.py: typed events for the full A10 table (user_message
  through compaction); canonical tool-call IDs minted locally,
  provider IDs never a join key; strict payload validation on load
- StateStore: canonical_events table via schema v2 — the first real
  migration, exercised in a test against a hand-built v1 database —
  with append_event/read_events on the same fsync-per-commit path
- render.py: request bodies rendered from the log at call time;
  first adapter targets the OpenAI-compatible shape of LiteLLM's
  normalized route; compaction events replace their id range at
  render time while staying in the durable log
- Crash integration test now also verifies transcript appends
  survive process death

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 19:51:58 +00:00
dongarandClaude Fable 5 18d4fcd701 Implement A9 state-change logging in the state store
CI / checks (push) Successful in 9s
CI / checks (pull_request) Successful in 8s
Retrofit for the conventions merged in #4 (issue #3):

- OpLog: JSON-lines emitter with the fixed envelope (ts, agent,
  event, task_id, cause); task_id set by the orchestrator at
  unit-of-work start
- StateStore owns emission: transition, intent begin/commit/abort,
  and schema migrations each emit their event right after the
  durable write commits; callers pass the cause
- reconcile_on_boot emits boot.reconcile with action and verdicts,
  and resolves intents with reconciliation-verdict causes
- Failed resolutions emit nothing (a line exists iff the write
  committed)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 21:13:36 +00:00
dongarandClaude Fable 5 4319882f35 Add durable state store and boot-time reconciliation (A2/A3)
CI / checks (push) Successful in 8s
CI / checks (pull_request) Successful in 7s
Build-order step 1: the critical path everything else sits on.

- StateStore: SQLite in WAL mode with synchronous=FULL, so every
  state transition and intent-log write is committed and fsynced
  before returning; a power cut cannot tear state
- Durable intent log: begin_intent records a unit of work before it
  starts; commit/abort resolve it; pending intents survive restart
- schema_version stamped from the first commit, with a sequential
  migration hook; a newer state file than the code supports is
  refused rather than misread
- reconcile_on_boot (A3 first cut): pending intents are checked
  against external truth by registered reconcilers (observable
  checks, never model self-assessment); verified effects are
  committed, verified no-ops aborted, anything unverifiable gates
  to AWAIT_INPUT — never blind-resume
- Lives in nisse_dev per spec 0.1: the library is extracted after
  the dev agent works, not designed up front
- Integration test kills a subprocess mid-work with os._exit and
  verifies state integrity and intent visibility on reopen

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 18:59:15 +00:00