What isn't the dev agent's moves to nisse-core, unchanged in behaviour, with its tests: canonical, render, render_anthropic, llm, catalog, probe, context, views, state, reconcile, worker, cancel, dump, transport, matrix, execution, testing, vault, memory, oplog, envfile and gitea (whole). - nisse_core.state.StateStore holds the tables every agent has; an agent's subclass adds its tables (version, migrations), roles and views. nisse_dev.state.StateStore adds the build VM blocks (v5). - views.project takes what each role is shown, rather than a fixed table. - Vault takes the agent's name (agent=), for provenance. - A test that nisse_core never imports an agent. - The loop, config, git, delegation, expert, tools and evals stay in nisse-dev until nisse-ops has a loop to share. Docs: the Development Plan marks M7.1 done and notes that Phase 6 waits on the agent host and Terraform; Architecture Part L names the package. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5Utyfzw7gF7UhjRDEtjTk
62 lines
2.3 KiB
Python
62 lines
2.3 KiB
Python
"""nisse-dev's state store: the shared one, with its own roles, views and
|
|
build VM blocks (D3)."""
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from nisse_core.canonical import ToolCall
|
|
from nisse_core.state import StateStore as CoreStore
|
|
from nisse_dev.state import StateStore
|
|
|
|
|
|
@pytest.fixture
|
|
def db(tmp_path: Path) -> Path:
|
|
return tmp_path / "state.db"
|
|
|
|
|
|
def test_a_vm_block_persists_across_reopen(db: Path) -> None:
|
|
with StateStore(db) as store:
|
|
store.block_vm("root@vm1", cause="broken", reason="pip crashes", work_item="x")
|
|
store.block_vm("root@vm1", cause="broken", reason="later", work_item="y")
|
|
with StateStore(db) as store:
|
|
[block] = store.vm_blocks().values()
|
|
assert (block.host, block.reason, block.work_item) == (
|
|
"root@vm1",
|
|
"pip crashes", # the first block is kept
|
|
"x",
|
|
)
|
|
assert store.unblock_vm("root@vm1", cause="test") == block
|
|
assert store.unblock_vm("root@vm1", cause="test") is None
|
|
assert store.vm_blocks() == {}
|
|
|
|
|
|
def test_a_version_4_store_gains_vm_blocks(db: Path) -> None:
|
|
with StateStore(db, schema_version=4) as store:
|
|
store._conn.execute("DROP TABLE vm_blocks") # as a real version 4 store
|
|
with StateStore(db) as store:
|
|
assert store.schema_version == 5
|
|
store.block_vm("root@vm1", cause="broken", reason="r", work_item=None)
|
|
assert list(store.vm_blocks()) == ["root@vm1"]
|
|
|
|
|
|
def test_the_dev_roles_are_the_dev_stores_own(db: Path) -> None:
|
|
with StateStore(db) as store:
|
|
store.transcript("x", "toolchain")
|
|
assert store.oplog.agent == "nisse-dev"
|
|
core = CoreStore(db.with_name("core.db"))
|
|
with core, pytest.raises(ValueError, match="unknown actor"):
|
|
core.transcript("x", "toolchain")
|
|
|
|
|
|
def test_each_role_is_shown_the_others_as_the_dev_store_says(db: Path) -> None:
|
|
with StateStore(db) as store:
|
|
for actor in ("driver", "toolchain"):
|
|
store.transcript("x", actor).append(
|
|
ToolCall(call_id=actor, tool="read_file", arguments={"path": "a"})
|
|
)
|
|
[seen] = store.transcript("x", "memory").view() # the driver's, told
|
|
assert seen.actor == "driver" and "read_file(a)" in seen.event.text
|
|
[own] = store.transcript("x", "driver").view() # not the toolchain's
|
|
assert own.event.call_id == "driver"
|