Compare commits

...
2 Commits
Author SHA1 Message Date
conductor fbb5018413 chore(release): auto-bump version to 0.70.0 — earned by # (minor: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 22s
CI Pipeline / unit-tests (push) Successful in 2m50s
CI Pipeline / lint (push) Failing after 28s
deploy / deploy (push) Failing after 1m29s
CI Pipeline / canary (push) Successful in 31s
CI Pipeline / best-practices (push) Successful in 6s
CI Pipeline / documentation (push) Successful in 8s
CI Pipeline / type-check (push) Successful in 30s
CI Pipeline / gitea-offline (push) Successful in 17s
CI Pipeline / required-checks (push) Failing after 4s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
Promotion record: (unknown)
2026-09-16 13:41:58 +01:00
Nick c8f0a8e353 feat(t21): 21G legacy transformation + 21I task-state ordering fix + 21O deterministic drift test
CI Pipeline / best-practices (push) Successful in 12s
CI Pipeline / documentation (push) Successful in 6s
CI Pipeline / lint (push) Failing after 37s
Auto-version and Release / release (push) Successful in 44s
CI Pipeline / canary (push) Successful in 37s
CI Pipeline / gitea-offline (push) Successful in 18s
CI Pipeline / type-check (push) Successful in 30s
CI Pipeline / unit-tests (push) Successful in 2m55s
CI Pipeline / required-checks (push) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 8s
deploy / deploy (push) Failing after 5m0s
- 21G: the TUI startup task loader now reads the CANONICAL
  TaskStateRepository (17F authority) instead of the task_persist
  export ledger; task_persist demoted to session-end export view
  (its only remaining role). Characterized first, migrated with
  fallback, BLE001 handler made visible.
- 21I: terminal _apply_runtime_result ordering REVERSED — canonical
  transition commits before legacy cache save; crash now leaves cache
  STALE (backfillable) instead of AHEAD of truth. 6 fault-injection
  held-outs incl. a structural source-grep guard.
- 21O: spec-drift test made deterministic.
2026-09-16 13:41:32 +01:00
7 changed files with 250 additions and 165 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
# Rune
**Current release: v0.69.1**
**Current release: v0.70.0**
**Rune is a persistent personal agent designed to accumulate experience, develop reusable competence, and remain recognisably the same agent even when its underlying foundation model changes.**
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "rune"
version = "0.69.1"
version = "0.70.0"
description = "Rune — a stateful coding assistant with persistent memory, orchestration, and TUI"
requires-python = ">=3.10"
+1 -1
View File
@@ -6,7 +6,7 @@ This is the main entry point for the Rune program.
import json
from pathlib import Path
__version__ = "0.69.1"
__version__ = "0.70.0"
# One build identity (handoff 2026-09-10 §4): the semantic version above is
# the repo-level truth (auto-bumped at merge); the DEPLOYED revision (exact
+1 -1
View File
@@ -231,7 +231,7 @@ def main() -> int:
)
check(
"Rune minor version advertises provisioning and restore verification",
'__version__ = "0.69.1"' in rune_version,
'__version__ = "0.70.0"' in rune_version,
failures,
)
# #169 policy update: auto-bump on merge is sanctioned (Nick directive:
+30 -2
View File
@@ -8,7 +8,7 @@ mode system, subject header, shared memory and identity.
This is not an interface. This is how I see, speak, and interact with the world.
Version: v0.69.1
Version: v0.70.0
Features: 41 (24 original + 17 new native commands)
Usage:
@@ -1697,9 +1697,37 @@ class RuneApp(App):
except Exception as e:
return ("registry_error", str(e))
def _task_repo_for_loader():
"""Access the canonical TaskStateRepository for the task
loader (T21 21G migration) — closure over the operator
getter already in scope. Degrades to the legacy ledger view
when the operator is unreachable (startup ordering), which
the load_tasks fallback then handles."""
try:
return getattr(_operator(), "_task_state", None)
except Exception as exc: # noqa: BLE001 — deliberate degradation: startup ordering; the fallback path handles it and the degradation is logged
print(f"[task-loader] canonical repo unavailable ({exc}); "
f"falling back to export ledger", flush=True)
return None
def load_tasks():
try:
if BACKEND_AVAILABLE:
# T21 21G: the TUI task loader reads the CANONICAL
# TaskStateRepository (17F authority), not the legacy
# task_persist export ledger. task_persist remains a
# session-end export view (its only remaining role).
repo = _task_repo_for_loader()
if repo is not None:
records = repo.list_all()
active = [
{"task_id": r.task_id, "title": r.title,
"status": r.status}
for r in records
if r.status in ("created", "running")]
all_pins = pins.list_pins()
open_pins = [p for p in all_pins if p.get("status") == "open"]
return ("tasks", active, open_pins)
data = task_persist.load()
tasks = data.get("tasks", [])
active = [t for t in tasks if t.get("status") in ("open", "in_progress")]
@@ -1856,7 +1884,7 @@ class RuneApp(App):
# Show version info
self.chat_channel.add_message(
"system",
f"[dim]Rune v0.69.1 | Textual TUI | {len(loaded)} native modules[/dim]",
f"[dim]Rune v0.70.0 | Textual TUI | {len(loaded)} native modules[/dim]",
)
# Auto-show night mode suggestion if evening/night hours
+199 -151
View File
File diff suppressed because it is too large. Load diff
+17 -8
View File
@@ -175,16 +175,25 @@ def test_21o_spec_drift_detection(world, tmp_path):
# someone changes the source WITHOUT revising the spec
world.material_change("event-core", note="rewrote completion path",
generation="gen-after-spec")
# same-second timestamps make wall-clock ordering racey (all events
# within one second share the stamp); compare against the material
# change itself: material_change bumps updated_at and appends
# history, but the spec's LAST BUMP stays at the baseline time.
rec = world.get("event-core")
# deterministic: simulate the timestamp ordering directly rather than
# racing a 1-second clock — the drift SIGNAL is ordering, not timing
rec["updated_at"] = "2026-09-16T12:00:00Z"
last_bump = rec["spec"]["version_history"][-1]["at"] # earlier timestamp
drift = rec["updated_at"] > last_bump
assert drift is True # material change happened, no bump recorded
# and the control: a fresh attach+revise has NO drift
n_bumps_before = len(rec["spec"]["version_history"])
world.material_change("event-core", note="rewrote path",
generation="gen-x")
rec = world.get("event-core")
# material change without a revise: NO new bump recorded
assert len(rec["spec"]["version_history"]) == n_bumps_before, (
"material change must not fabricate a version bump")
# the drift signal, deterministically: the capability's material
# generation is NEWER than the spec's last governed bump — captured
# on the record, not inferred from a raced clock
assert rec["updated_at"] >= rec["spec"]["version_history"][-1]["at"]
# and the control: a revise records a new bump and closes the gap
r = cl.revise_spec(world, "event-core", implementation_only=True,
reason="catch up")
rec2 = world.get("event-core")
assert rec2["spec"]["version"] == r["new"]
assert rec2["spec"]["version_history"][-1]["at"] >= rec2["updated_at"]
assert len(rec2["spec"]["version_history"]) == n_bumps_before + 1