Files
rune/tests/test_native_activation.py
Nick 0a436b2f97 feat(scaffolding): §15J/§15K — Scaffolding IS the native construction default
15J (native route through the REAL send_task path — TUI input →
RuneOperator.send_task → construction hook → classifier → activation →
durable state):
- 6 held-outs (tests/test_native_default.py): PROJECT_BUILD without any
  command; EXISTING attaches Rune authority; LOCAL_CHANGE light; NOT_
  CONSTRUCTION touches nothing; UNKNOWN probes without invention; manual
  override (/scaffold-mode <MODE>) through the SAME classify_mode with
  user provenance
- classifier: explicit FILE mentions ('the README', 'scheduler.js') now
  bind scoped targets — deterministic lexical evidence + the ONE surface
  authority (classify_surface), lazily imported (cycle-safe)

15K (bypass prevention):
- /build start hardened: classifies through the canonical machinery
  BEFORE BuildManager mints any state; NOT_CONSTRUCTION refused;Build-
  Manager remains execution vehicle, no longer a construction authority
- inventory: BuildManager provably creates NO canonical scaffolds

Process repairs caught during the stage (15X evidence):
- os.chdir pollution from a test leaked cwd into later tests (bare
  os.chdir → monkeypatch.chdir)
- construction-hook tests were making REAL model calls (42s, provider
  quota burned, starved stage-telemetry's model call → GATE_FAILED):
  send_task's _execute_on_model now stubbed in hook tests — suite 144s
  → 54s and deterministic
- S110 noqa for the deliberate classifier degrade; new modules mapped
  into config/umbrellas.json (perception: event_wait, stage_guards)
- suite: 1835 passed, 0 failed
2026-09-15 03:06:55 +01:00

110 lines
4.8 KiB
Python

"""12D tests: Rune-native activation through send_task."""
import json
import os
import sys
from unittest.mock import patch
import pytest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts"))
from rune import construction_mode as cm # noqa: E402
@pytest.fixture
def native_operator(tmp_path, monkeypatch):
"""A RuneOperator whose construction store points at a tmp scaffold via
the documented env override; send_task's downstream model call is
stubbed so the test exercises only the construction hook."""
store = tmp_path / ".rune" / "scaffold"
monkeypatch.setenv("RUNE_CONSTRUCTION_STORE", str(store))
# §15X: hook tests exercise the construction hook, not the provider —
# stub the downstream model execution (send_task otherwise makes REAL
# model calls, burning quota and coupling unit tests to provider health)
from rune.tool_protocol import OperatorResponse
monkeypatch.setattr(
"rune.rune_operator.RuneOperator._execute_on_model",
lambda self, *a, **k: OperatorResponse(success=True,
user_text="stubbed"))
from rune import scaffold as sc
sc.Scaffold(store, "rune").init(purpose="rune native test")
import rune.rune_operator as ro
op = ro.RuneOperator()
return op, store
class TestRuneNativeActivation:
def test_project_build_via_send_task(self, native_operator):
"""12D.A: normal input → PROJECT_BUILD → durable scaffold."""
op, store = native_operator
result = op.send_task(
"Build me a new standalone practice scheduler")
assert result is not None # task path completed normally
doc = json.loads((store / "current.json").read_text())
activated = [o for o in doc.get("observations", [])
if o.get("kind") == "construction_activated"]
assert activated, "no construction_activated observation"
modes = {o["mode"] for o in activated}
assert "PROJECT_BUILD" in modes or any(
o["mode"] == "PROJECT_BUILD" for o in activated)
class TestRuneNativeMatrix:
"""§12D full matrix through the REAL send_task backend path."""
def _last_activated(self, store):
doc = json.loads((store / "current.json").read_text())
return [o for o in doc.get("observations", [])
if o.get("kind") == "construction_activated"]
def test_existing_project_change(self, native_operator):
op, store = native_operator
op.send_task("Add CSV export to the existing Rune project")
activated = self._last_activated(store)
assert activated and activated[-1]["mode"] == "EXISTING_PROJECT_CHANGE"
def test_local_change(self, native_operator):
op, store = native_operator
op.send_task("Fix this typo in the existing module")
activated = self._last_activated(store)
assert activated and activated[-1]["mode"] == "LOCAL_CHANGE"
def test_non_construction_no_activation(self, native_operator):
op, store = native_operator
before = len(self._last_activated(store))
op.send_task("Make me a list of chord substitutions")
activated = self._last_activated(store)
new = [o for o in activated if o["activated"]]
assert all(o["mode"] == "NOT_CONSTRUCTION" or not o["activated"]
for o in activated[before:] or activated)
def test_unknown_probes_not_activation(self, native_operator):
op, store = native_operator
op.send_task("Build something that helps with this")
activated = self._last_activated(store)
last = activated[-1]
assert last["mode"] == "UNKNOWN"
assert last["activated"] is False
def test_fresh_process_resume(self, tmp_path, native_operator):
"""§17: after PROJECT_BUILD activation, a fresh process recovers
the bootstrap from the durable scaffold alone."""
op, store = native_operator
op.send_task("Build me a new standalone practice scheduler")
# fresh: find the bootstrapped project scaffold (slug derived from
# the objective — locate it, don't hardcode)
projects = store / "projects"
candidates = sorted(projects.glob("*/current.json")) \
if projects.exists() else []
assert candidates, "no project scaffold bootstrapped"
from rune import scaffold as sc, structural_store as ss
pdoc = sc.Scaffold(candidates[0].parent,
candidates[0].parent.name).load()
projects_found = [e for e in pdoc["entities"]
if e["kind"] == "project"]
assert projects_found
p = projects_found[0]
assert p["ext"]["bootstrap"] == "initialized"
assert p["ext"]["repository"] == "undecided"