Compare commits

..
16 Commits
Author SHA1 Message Date
conductor 5b2712f5e6 chore(release): auto-bump version to 0.68.0 — earned by # (minor: converged release (push-to-master bump))
Promotion record: (unknown)
2026-09-16 04:53:32 +01:00
Nick 124b77e95b feat(t21): wait-guard regression protection + MiMo controller hook (21B)
- 21B-1: Rune sleep audit — no UNJUSTIFIED_SLEEP in active paths;
  auto_bump_pr.py polling classified legacy (21G candidate). T20's
  sleeps were MODEL-GENERATED Bash (controller-level defect).
- 21B-2/3: controller is a compiled binary (not source-patchable) —
  guard implemented at the extension surface: ~/.mimocode/hooks/
  event-wait-guard.ts via @mimo-ai/plugin tool.execute.before.
  LIVE_PROVEN_THIS_SESSION: v1 hot-reloaded and intercepted a tool
  call mid-session (no restart). v1 false-positive (heredoc
  documentation containing the pattern) found live and fixed: v2
  requires sleep+poll pairing across adjacent segments with heredoc
  bodies stripped.
- 21B-4: wait_guard.py — Python mirror of the classification logic in
  the Rune suite (survives model changes/compaction); 8 held-outs
  reproducing the exact T20 patterns (540/300/600 sleeps + status
  probes blocked; heredoc docs, bare sleep, short backoff, segment
  isolation permitted).
2026-09-16 04:52:23 +01:00
conductor 1b7995e093 chore(release): auto-bump version to 0.67.1 — earned by # (patch: converged release (push-to-master bump))
Promotion record: (unknown)
2026-09-16 04:03:24 +01:00
Nick fcd835883e chore(store): T20 evidence 2026-09-16 04:02:53 +01:00
Nick 37ce68eff8 fix(tui): /testing used Path without import (F821) — raw-ruff gate caught it, lint ratchet scope gap noted (T20 follow-through) 2026-09-16 04:02:53 +01:00
conductor 2fa0a5f144 chore(release): auto-bump version to 0.67.0 — earned by # (minor: converged release (push-to-master bump))
Promotion record: (unknown)
2026-09-16 03:43:31 +01:00
Nick c3ef29c59d feat(retrofit): semantic release 0.67.0 — governed minor release of the Rune-wide retrofit (T20)
T20 is a feature-level tranche: Rune structural taxonomy (15 domains,
107+ entities), capability/behaviour ledgers, /testing backlog, Spine
modernization, rune graph projection, semantic release policy — new
subsystem functionality and materially expanded system behaviour.
Classified MINOR per docs/RELEASE_POLICY.md. First release computed by
the FIXED semver_bump (synthesized-title kind carried through).
2026-09-16 03:43:06 +01:00
conductor f079aa2cc9 chore(release): auto-bump version to 0.66.84 — earned by # (patch: converged release (push-to-master bump))
Promotion record: (unknown)
2026-09-16 03:33:28 +01:00
Nick c03c953a45 fix(release): semver_bump honors synthesized convergence title kind (T20 20B REAL DEFECT)
The push-convergence path synthesizes PR titles as '<kind>: converged
release' where kind comes from version_convergence.highest_warranted_bump
(minor|patch). semver_bump then re-derived the kind from the TITLE TEXT
and 'minor:' matched nothing → patch. Every feature tranche downgraded:
T18/T19/T20 feat ranges bumped 0.66.77-83 instead of 0.67.0. Fixed:
MINOR_PREFIX_RE carries the convergence decision through. Held-out
proves minor-title→0.67.0 and patch-title→0.67.1 (no accidental
re-minor). This is the 0.66.x problem the mandate named, root-caused.
2026-09-16 03:32:53 +01:00
conductor 90ae1c2612 chore(release): auto-bump version to 0.66.83 — earned by # (minor: converged release (push-to-master bump))
Promotion record: (unknown)
2026-09-16 03:16:08 +01:00
Nick cb1b8303fe feat(retrofit): 20U/20W evidence + 20B policy record (T20 final tranche work)
- 20U: V1 requirement classification (NEAR_V1_ACCEPTANCE_READY with
  exact missing proof classes).
- 20W: 12-case retrofit adversarial matrix (unknown ownership,
  ghost relationships, duplicate authority, dynamic consumers,
  spine↔scaffold reconciliation, file moves, stale ledgers, packet
  scoping, read-only projection, hidden-consumer retirement blocks,
  canonical task-state wins, env-skew visibility, bounded packets).
  Matrix found REAL spine↔model drift (4 missing domains — fixed in
  the model).
- 20B: semantic release policy doc + held-outs (patch→.81,
  minor→.67.0, no accidental re-minor). T20 classified MINOR.

Suite 2019 green.
2026-09-16 03:14:53 +01:00
conductor 3c54782634 chore(release): auto-bump version to 0.66.82 — earned by # (minor: converged release (push-to-master bump))
Promotion record: (unknown)
2026-09-16 03:02:15 +01:00
Nick 478ce45755 feat(retrofit): T20 0.67.0 MINOR release record (semantic policy) 2026-09-16 03:02:04 +01:00
Nick a96ed90b90 feat(retrofit): rune taxonomy + 20Q honesty fixes + 20W matrix + coverage (T20 20D-20W)
- 20D/E: rune taxonomy from import-graph reality (15 domains, 107+
  entities, 171+ edges); honest coverage (37% file — NOT complete).
- 20F: 4 representative capability ledgers (699-866 bytes) + risk_notes
  field added from the 20Q cold-benchmark finding (write-ordering
  failure window now recorded where fresh models re-read it).
- 20G: 10-behaviour Rune inventory (8 AUTO_VERIFIED from live evidence,
  1 manual pending, 1 hardening item; ZERO USER_CONFIRMED manufactured).
- 20I: Spine↔Rune-model boundary (Spine=module facts; rune model=
  domains/capabilities/behaviours; 8 subsystems linked by name map).
- 20J: rune graph projection (107 nodes/171 edges, JSON/DOT/Mermaid).
- 20K: honest coverage by category (file 37%, structural 36%,
  dependency 92%, state 3 explicit, behaviour 10, validation 8+1).
- 20L: 5 legacy candidates classified (bounded/migration/keep/retire).
- 20Q: HONEST comparison — cold agents found MORE breadth (9 vs 2
  influencers) and a REAL ledger gap; recorded without inflation.
- 20R: REAL quicksand proof on Rune entities (reopen + preserve).
- 20W: 12 held-outs; matrix found REAL spine↔model drift (4 domains
  missing — fixed in the model, not the test).
- 20T: 37 stale build worktrees removed (verified clean); no open
  contracts; programmes durable.
2026-09-16 03:01:42 +01:00
conductor 713f85a0e3 chore(release): auto-bump version to 0.66.81 — earned by # (minor: converged release (push-to-master bump))
Promotion record: (unknown)
2026-09-16 02:41:18 +01:00
Nick 504935828b feat(retrofit): rune structural model + ledgers + backlog + Spine links (T20 20C-20R)
- 20B: semantic release policy (docs/RELEASE_POLICY.md) + held-outs
  (patch→0.66.81, minor→0.67.0, no accidental re-minor).
- 20C: QUALIFIED retrofit Build Basis (stable-ID contract, dynamic-
  uncertainty taxonomy, strangler-fig, two-tier coverage, LSP combine).
- 20D/E: rune taxonomy from import-graph reality (9 domains, 11
  subsystems, 107 entities/171 edges, honest 37% file coverage —
  NOT claimed complete).
- 20F: 4 representative capability ledgers (699-866 bytes each).
- 20G: 10-behaviour Rune inventory (8 AUTO_VERIFIED from live
  evidence, 1 manual pending, 1 hardening item; ZERO USER_CONFIRMED
  manufactured).
- 20I: Spine↔Rune-model authority boundary defined (Spine=module
  facts; Rune model=domains/capabilities/behaviours; shared kind:name
  discipline; 8 spine subsystems linked to rune domains).
- 20J: rune graph projection (JSON/DOT/Mermaid, 107 nodes/171 edges).
- 20K: honest coverage metrics by category (file 37%, structural 36%,
  dependency 92%, state 3 explicit, behaviour 10, validation 8+1).
- 20L: 5 legacy candidates classified (build_mode=BOUNDED_ADAPTER,
  task_persist=MIGRATION, canaries=KEEP, complexity_scorer=RETIREMENT,
  message_queue=MIGRATION).
- 20R: REAL quicksand proof — construction_mode change reopened
  VAL-RUNE-001 (history preserved); voice_synthesis change left
  VAL-RUNE-004 untouched.
- 20P: lock-parity proven (0 diff); residual rule recorded; VAL-010.

Suite 2002 green; ratchets PASS.
2026-09-16 02:40:53 +01:00
27 changed files with 7822 additions and 167 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
# Rune
**Current release: v0.66.80**
**Current release: v0.68.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.**
+2 -1
View File
@@ -1,7 +1,7 @@
{
"_comment": "GENERATED by rune.spine \u2014 compatibility view for legacy umbrella consumers. DO NOT EDIT: structural truth lives in store/spine/current.json; edits here are flagged by spine drift.",
"_generated_by_spine": true,
"generated_at": "2026-09-16T00:01:04Z",
"generated_at": "2026-09-16T03:45:21Z",
"umbrellas": {
"capability": {
"description": "Tool selection and execution authority",
@@ -255,6 +255,7 @@
"testing_mode",
"toolchain",
"tui_backlog",
"wait_guard",
"witness"
],
"depends_on": [
+53
View File
@@ -0,0 +1,53 @@
# Rune Semantic Release Policy (T20 §20B)
Pre-1.0 convention. Scaffolding "V1" does NOT mean Rune 1.0.
## Bump kinds
**PATCH** (0.66.80 → 0.66.81):
- bug fix, correction, implementation/internal maintenance
- no meaningful new user/system capability
**MINOR** (0.66.80 → 0.67.0):
- meaningful new Rune capability
- new subsystem functionality
- materially expanded system behaviour
- significant new supported workflow
**MAJOR**: reserved for Rune 1.0+ compatibility/public-contract semantics.
## How the machinery expresses this (no manual version edits)
The existing machinery already maps commit shape → bump kind:
- `semver_bump.next_version` (PR titles): feat→minor, else patch
- `version_convergence.highest_warranted_bump` (push ranges):
feat/breaking→minor, fix/perf→patch, else None
**Tranche-level rule (20B)**: a feature tranche lands its feature
commits (`feat(...)`), and the convergence machinery bumps MINOR at
the tranche's release boundary. Patch-only follow-ups (fix/perf)
warrant only PATCH — the machinery cannot accidentally re-minor
because `highest_warranted_bump` takes the max over the *post-
boundary* range, and a fix-only range yields "patch".
## Why T20 → 0.67.0
T20 is a feature-level tranche (Rune-wide retrofit: structural
taxonomy, capability/behaviour ledgers, rune graph, /testing backlog,
Spine modernization, semantic release). The release is classified
MINOR under this policy, earned through the governed convergence
machinery — never a manual version edit.
## T20 0.67.0 release record
T20 classified MINOR under this policy: Rune-wide retrofit (structural
taxonomy, capability/behaviour ledgers, rune graph, /testing backlog,
Spine modernization, semantic release) = new subsystem functionality +
materially expanded system behaviour. Earned through the governed
convergence machinery (feat-bearing range → minor), never a manual edit.
## Root cause record (T20, 2026-09-16)
semver_bump re-derived the bump kind from the SYNTHESIZED title text —
"minor: converged release" matched nothing → patch. Feature tranches
T18/T19/T20 downgraded to 0.66.77-83. Fixed: MINOR_PREFIX_RE carries the
convergence kind through; first push after the fix with a feat-bearing
range lands 0.67.0 through the normal machinery.
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "rune"
version = "0.66.80"
version = "0.68.0"
description = "Rune — a stateful coding assistant with persistent memory, orchestration, and TUI"
requires-python = ">=3.10"
+9
View File
@@ -18,6 +18,13 @@ from __future__ import annotations
import re
import sys
# T20 §20B: push-convergence synthesizes PR titles as "<kind>: converged
# release (push-to-master bump)" where kind comes from
# version_convergence.highest_warranted_bump. The title text must carry
# that decision — "minor:" was re-classified as patch here, downgrading
# every feature tranche (observed: feat ranges bumped 0.66.77-83 not 0.67.0).
MINOR_PREFIX_RE = re.compile(r"^\s*minor\b", re.IGNORECASE)
BREAKING_RE = re.compile(r"^\s*\w+(\([^)]*\))?!:")
FEAT_RE = re.compile(r"^\s*feat(\([^)]*\))?")
@@ -25,6 +32,8 @@ FEAT_RE = re.compile(r"^\s*feat(\([^)]*\))?")
def next_version(version: str, title: str) -> str:
if BREAKING_RE.match(title) or "BREAKING CHANGE" in title:
kind = "major"
elif MINOR_PREFIX_RE.match(title):
kind = "minor" # synthesized convergence title carries the kind
elif FEAT_RE.match(title):
kind = "minor"
else:
+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.66.80"
__version__ = "0.68.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.66.80"' in rune_version,
'__version__ = "0.68.0"' in rune_version,
failures,
)
# #169 policy update: auto-bump on merge is sanctioned (Nick directive:
+5 -4
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.66.80
Version: v0.68.0
Features: 41 (24 original + 17 new native commands)
Usage:
@@ -1856,7 +1856,7 @@ class RuneApp(App):
# Show version info
self.chat_channel.add_message(
"system",
f"[dim]Rune v0.66.80 | Textual TUI | {len(loaded)} native modules[/dim]",
f"[dim]Rune v0.68.0 | Textual TUI | {len(loaded)} native modules[/dim]",
)
# Auto-show night mode suggestion if evening/night hours
@@ -3117,6 +3117,7 @@ class RuneApp(App):
/testing → aggregate across registered projects
/testing <project> → one project's outstanding items."""
try:
from pathlib import Path as _Path
from rune import testing_mode as tm
from rune.behaviour_ledger import BehaviourLedger
from rune.project_registry import ProjectRegistry
@@ -3131,7 +3132,7 @@ class RuneApp(App):
f"{arg.strip()!r}[/yellow]")
return
loc = entry["scaffold_location"]
if not (Path(loc) / "behaviour_ledger.json").is_file():
if not (_Path(loc) / "behaviour_ledger.json").is_file():
ch.add_message("system",
f"[yellow]{arg.strip()} has no behaviour ledger "
f"yet[/yellow]")
@@ -3142,7 +3143,7 @@ class RuneApp(App):
f"[bold]{arg.strip()}: {len(items)} outstanding "
f"validation(s)[/bold]")
else:
rows = tm.aggregate(registry, Path("store/scaffold"))
rows = tm.aggregate(registry, _Path("store/scaffold"))
ch.add_message("system", "[bold]Testing aggregate "
"(registered scaffolded projects)[/bold]")
for r in rows:
+73
View File
@@ -0,0 +1,73 @@
"""wait_guard.py — T21 §21B: the sleep→poll regression detector.
Mirror of the MiMo Code controller guard (~/.mimocode/hooks/
event-wait-guard.ts) in Python, so the CLASSIFICATION LOGIC is
regression-tested in the Rune suite (rule 21B-4: the fix must survive
model changes, compaction, provider swaps).
Detection: a command SEGMENT (split on ; | newline && ||) that combines
a long sleep (>= 30s) with a status query of CI/deploy/release state.
Heredoc bodies are stripped first (v2 precision fix — documentation
about the pattern must not trip the guard).
Classification vocabulary (21B-1):
USER_REQUESTED_DELAY bare sleep, user's explicit choice
RATE_LIMIT_BACKOFF short bounded backoff (<30s)
RETRY_BACKOFF bounded retry loop inside a script
WATCHDOG deadline-based failure detection
EVENT_FALLBACK_WITH_REASON declared no-event-source fallback
SCHEDULED_TIMER cron/scheduled work
UNJUSTIFIED_SLEEP DEFECT: sleep+poll with an event source available
"""
from __future__ import annotations
import re
LONG_SLEEP_RE = re.compile(r"\bsleep\s+(\d{2,4})\b")
STATUS_POLL_RE = re.compile(
"|".join(
(
r"actions/runs",
r"commits/.*/status",
r"required.checks",
r"deploy_qualify",
r"releases/tags",
r"readlink.*rune-code/current",
)
),
re.IGNORECASE,
)
THRESHOLD_SECS = 30
def classify_wait(command: str) -> dict:
"""Classify one shell command's wait behaviour. Returns
{"classification": ..., "evidence": ...}. UNJUSTIFIED_SLEEP is a
defect: the controller guard rejects it and redirects to the
canonical event primitive."""
stripped = re.sub(
r"<<-?\s*['\"]?(\w+)['\"]?\n[\s\S]*?\n\1", " [heredoc] ", command
)
segments = [s.strip() for s in
re.split(r"[;|\n]|&&|\|\|", stripped) if s.strip()]
for i, segment in enumerate(segments):
m = LONG_SLEEP_RE.search(segment)
if not m:
continue
secs = int(m.group(1))
if secs < THRESHOLD_SECS:
continue
# the regression pattern is sleep THEN check: the status poll may
# be in the same segment or the immediately following ones (the
# "sleep; curl status" / "sleep && fetch && readlink" shapes)
lookahead = " ".join(segments[i:i + 3])
if STATUS_POLL_RE.search(lookahead):
return {
"classification": "UNJUSTIFIED_SLEEP",
"evidence": f"sleep {secs}s then status poll: "
f"{' / '.join(segments[i:i + 2])[:140]}",
"redirect": "scripts/ci_event_wait.py --sha <sha>",
}
if re.match(r"^\s*sleep\s+\d+\s*$", stripped.strip()):
return {"classification": "USER_REQUESTED_DELAY", "evidence": stripped.strip()}
return {"classification": "NO_WAIT", "evidence": ""}
+99
View File
@@ -0,0 +1,99 @@
{
"alternatives_considered": [],
"created_at": "2026-09-16T01:24:46Z",
"deeper": {
"findings": [],
"refs": [],
"used": false
},
"depth": {
"decided_at": "2026-09-16T01:24:46Z",
"depth": "FULL",
"mode": "",
"route": "RESEARCHED_CHANGE",
"why": "route RESEARCHED_CHANGE default"
},
"dispositions": [
{
"disposition": "ADOPT",
"item": "kind:name stable IDs with path-as-attribute + alias records on move",
"ref": "backstage.io",
"why": "Backstage entity-ref discipline; Kythe VName declines cross-version stability (we promise it); uid-style instability rejected"
},
{
"disposition": "ADOPT",
"item": "dynamic-uncertainty edges (static vs dynamic vs exotic taxonomy)",
"ref": "dependency-cruiser",
"why": "dependency-cruiser taxonomy validates our explicit dynamic edges; import-linter uncovered=unknown framing"
},
{
"disposition": "ADOPT",
"item": "strangler-fig: model per subsystem alongside legacy; bounded adapters as transitional architecture",
"ref": "martinfowler.com",
"why": "incremental retrofit without big-bang"
},
{
"disposition": "ADOPT",
"item": "two-tier coverage: manifest coverage vs relationship coverage; fail CI on empty-scope contracts",
"ref": "archunit.org",
"why": "ArchUnit failOnEmptyShould prevents vacuous passes; file-in-manifest \u2260 ownership-known"
},
{
"disposition": "COMBINE",
"item": "LSP call hierarchy for symbol precision where static",
"ref": "lsp spec",
"why": "with import-graph evidence; dynamic dispatch stays runtime-verified"
},
{
"disposition": "ADAPT",
"item": "characterization tests before contract enforcement on legacy adapters",
"ref": "feathers",
"why": "Feathers legacy pattern; one characterization test per adapter"
},
{
"disposition": "INNOVATE",
"item": "per-edge trust weights from predicted-vs-observed history",
"ref": "t19 basis",
"why": "impact_deltas.jsonl compounds into precision; no mainstream tool logs per-edge prediction accuracy"
}
],
"implications": {
"architecture": [],
"migration": [],
"structural": [],
"verification": []
},
"inward": {
"findings": [],
"refs": []
},
"issue_ref": "research/t20-retrofit",
"kind": "build_basis",
"outward": {
"findings": [],
"prior_art_questions_answered": [
"what already exists addressing this intent",
"what open-source systems/products/workflows attempt it",
"what architectural patterns already work",
"what standards/conventions exist",
"what can be directly ADOPTED",
"what can be ADAPTED",
"what can be COMBINED",
"what should be REJECTED",
"where is genuine INNOVATION required"
],
"refs": [
"https://kythe.io/docs/schema/",
"https://github.com/sourcegraph/scip/blob/main/scip.proto",
"https://backstage.io/docs/features/software-catalog/descriptor-format",
"https://import-linter.readthedocs.io/en/stable/",
"https://github.com/sverweij/dependency-cruiser/blob/main/doc/rules-reference.md",
"https://martinfowler.com/bliki/StranglerFigApplication.html",
"https://www.archunit.org/userguide/html/000_Index.html"
]
},
"question": "How to retrofit Rune's ~160 modules into a structural model incrementally, without big-bang rewrite or excessive granularity?",
"risks": [],
"schema_version": 1,
"uncertainty": []
}
@@ -0,0 +1,35 @@
# 20I — Spine modernization decision (2026-09-16)
## What Spine stores today
- 150 module entities (flat, all with source identities), 8 subsystems,
1 deployment_surface. NO domains, NO components-as-structural-units,
NO interfaces, NO test_suites, NO state stores, NO environments.
- Strengths: module-level structural facts (imports, tests, maturity
ladder), umbrella ingest, impact_frontier, byte-deterministic snapshots.
## Rune model (store/rune_model) today
- 55 entities: domains (9), subsystems (11), components (31), 1 interface,
2 test_suites. Construction-governance oriented.
## Authority boundary (rule E — defined, not duplicated)
| Data | Canonical home | Consumers |
|---|---|---|
| Module-level facts (imports, maturity, canary wiring) | **Spine** | umbrella gates, Henxels, structural health |
| Domain/subsystem/component nesting + purpose | **Rune model** | construction, impact, /testing narrowing |
| Capability ledgers | **Rune model** (capability_ledger.json) | surgical packets |
| Behaviour specs + validation state | **Rune model** (behaviour_ledger.json) | /testing, invalidation |
| Cross-store ID discipline | **shared** (kind:name) | both |
## Modernization performed (bounded, rule I)
1. Spine projectors now READ the Rune model for domain membership
(no copy): spine's subsystem entities gain an `ext.rune_domain`
pointer where the Rune model nests them — LINKED, not copied.
2. Drift rule: if a Spine module's source disappears while the Rune
model still claims it (or vice versa), detect_structural_drift flags
MATERIAL — neither store silently contradicts the other.
## What was NOT done
- No Spine schema migration (domains not forced into Spine).
- No bulk copy of Rune-model entities into Spine.
- No graph_projection authority claims (projection stays read-only).
+55
View File
@@ -0,0 +1,55 @@
[
{
"candidate": "component:build_mode_adapter",
"purpose": "worktree/ledger bounded adapter",
"callers": [
"rune_tui (gated)",
"tests"
],
"dynamic_risk": "low (no reflection entry)",
"replacement": "component:scaffold + workspace lifecycle",
"classification": "BOUNDED_ADAPTER"
},
{
"candidate": "component:task_persist",
"purpose": "persisted.json export ledger (T17: demoted)",
"callers": [
"auto_context",
"CLI only"
],
"dynamic_risk": "low",
"replacement": "TaskStateRepository (canonical)",
"classification": "MIGRATION_CANDIDATE"
},
{
"candidate": "canary_native + canary_full_system",
"purpose": "layered overlap, acceptable per 17I",
"callers": [
"CI",
"spine registry"
],
"dynamic_risk": "none",
"replacement": "keep layered",
"classification": "KEEP"
},
{
"candidate": "component:complexity_scorer",
"purpose": "complexity hint (prints, never gates)",
"callers": [
"rune_tui:2105"
],
"dynamic_risk": "none",
"replacement": "adaptive_router (authoritative)",
"classification": "RETIREMENT_CANDIDATE"
},
{
"candidate": "message_queue.detect_task_addition",
"purpose": "chat\u2192task queue with regex confidence",
"callers": [
"rune_tui:2070"
],
"dynamic_risk": "none",
"replacement": "construction_intent (semantic)",
"classification": "MIGRATION_CANDIDATE"
}
]
+29
View File
@@ -0,0 +1,29 @@
# 20P — CI/type-check determinism investigation (2026-09-16)
## Finding
With the lock at parity (propcache 0.5.4/yarl 1.25.1 pinned everywhere),
runner-user and nick-user pyright on the SAME venv give IDENTICAL
results (121 errors, 442 warnings, 211 files). The T14H-class skew is
NOT user-environment — it is LOCK-CONTENT skew: when requirements-ci.txt
pins drift between local and CI (propcache churned twice mid-T19/T20),
the two environments resolve different package versions.
## Root cause
`uv pip compile` regenerates against the live index; any upstream
release between a local compile and a CI run shifts resolution.
requirements-ci.txt pins the RESULT, but the baseline was being
re-baselined against whichever environment ran last.
## Fix applied
- Lock re-pinned to current (0.5.4/1.25.1) — verified parity (0 diff lines
between fresh compile and committed lock at python-version 3.11).
- Baseline set against CI's fresh-resolution arithmetic (454) — matches
the environment the gate actually runs in.
- RULE recorded: when the lock changes, re-baseline against a venv built
from the NEW lock, never against the old venv.
## Honest residual
Local pre-flight cannot perfectly predict CI when upstream releases land
between push and CI run. The structural fix (fully hermetic lockfile
with hashes) is a bounded item for the retrofit tranche, recorded as
behaviour VAL-RUNE-010.
+63
View File
@@ -0,0 +1,63 @@
# 20Q — surgical-context benchmarks across Rune domains (2026-09-16)
## Task 1: provider decision ownership (inference-providers domain)
- COLD (fresh explore agent): running in parallel — results appended below.
- SCAFFOLD-GUIDED: 1 context_packet call (0 file reads), answered from
capability ledger + structural edges: owner=rune_operator,
influences=adaptive_router+construction_mode, consumers=rune_tui.
Context: ~700-byte ledger entry + structural closure. No repo scan.
## Task 2: task-state canonical authority (state-resilience domain)
- SCAFFOLD-GUIDED: 0 file reads — ledger state_touched field answers
directly: "TaskStateRepository (canonical), operator.json (legacy
cache)". Invariant recorded: "route decided before execution".
## Honest assessment
The cold agents' parallel results will show whether raw discovery cost
differs. What the scaffold demonstrably provides regardless of speed:
- authority answers carry the VALIDATION state (VAL-* links),
- obligations (what to retest) come free with the answer,
- the answer is stable across sessions (no re-derivation each time).
## Structural facts
- Rune model: 107 entities, 94 relationships, 37% file coverage
(50/136 — honest: NOT "fully mapped"), 3 state stores, 9 domains.
- Capability ledgers: 4 representative (699-866 bytes each — compact).
- Behaviour ledger: 10 specs (8 AUTO_VERIFIED, 1 manual pending,
1 hardening item), 0 USER_CONFIRMED (none manufactured).
## Cold results (parallel fresh agents, received)
### Task 1: provider decision ownership
- COLD: **16 tool calls, 10 files opened** — rune_operator.py:1015-1066
(tier loop = final decider), model_routing rank() advisory,
work_manager route_batch, model_connect, tiered_executor, TUI
override, subsystem_health fallback — 9+ influencing modules mapped.
- SCAFFOLD-GUIDED: 1 packet call, 0 file reads. Answer: owner +
adaptive_router/construction_mode as dependencies, rune_tui consumer.
- **Assessment: cold found MORE breadth (9 influencers vs 2 deps) —
the model's dependency edges were COARSER than cold analysis.**
Honest: for "list every influencer" questions, cold grep+sweep wins.
The scaffold's edge set under-models advisory-only influencers
(rank() is advisory — not a depends_on edge by our vocabulary).
### Task 2: task-state canonical authority
- COLD: **11 tool calls, 2 files** — found canonical repo + caches +
RISK: ~10 non-canonical writers mutate RuneTask.status THEN mirror
via transition(); crash between = legacy ahead of truth;
_task_counters falls back to cache on empty repo.
- SCAFFOLD-GUIDED: 0 file reads — ledger answered canonical-vs-cache
directly but did NOT surface the write-ordering crash-window risk.
- **Assessment: cold found a REAL defect-shaped risk the ledger
lacked.** The ledger's invariants covered ownership, not failure
ordering. This is a genuine ledger-content gap, recorded.
## Verdict (honest, per mandate)
- Speed: scaffold-guided is faster on narrow authority questions
(1 vs 11-16 calls) but this repo is well-organized; on breadth
questions cold sweeps still win.
- The scaffold's structural edges are COARSER than code reality —
impact closure over-approximates narrowly (misses advisory-only
influencers) and ledgers lack failure-ordering detail.
- Improvement recorded: capability ledgers should carry a
"risk_notes" field for write-ordering/failure-window facts.
+43
View File
@@ -0,0 +1,43 @@
# 20U — V1 requirement classification after retrofit (2026-09-16)
| Requirement | Status | Evidence |
|---|---|---|
| construction kernel | LIVE_PROVEN | T14-T19 production cycles; 19A fail-closed |
| contextual intent | TEST_PROVEN + LIVE (17R, 19R) | 22+6 held-outs; two live conversational proofs |
| Research Core integration | TEST_PROVEN | build_basis qualified ×2 real bases; depth-from-route |
| structural Scaffold | TEST_PROVEN + LIVE (18O, 19R) | self-scaffold consistency-enforced; 107-entity Rune model |
| bounded scope/impact | TEST_PROVEN | closures + previews + deltas |
| new-build mode | TEST_PROVEN | classify + bootstrap; 17Q-1/14 |
| retrofit mode | LIVE_PROVEN | T20: 107 entities via surgical workflow |
| future-upgrade mode | LIVE_PROVEN | 18P 11-step scaffold-driven upgrade |
| Capability Ledgers | TEST_PROVEN + LIVE | 19R packet bound 1 file; risk_notes added from benchmark |
| Project Registry | TEST_PROVEN | boundaries proven |
| Behaviour Validation Ledger | TEST_PROVEN | generation history; selective invalidation; no manufactured USER_CONFIRMED |
| quicksand protection | TEST_PROVEN + LIVE (20R) | real-entity invalidation + preservation |
| /testing | TEST_PROVEN + LIVE (19R) | backend + command; dynamic queue |
| Observation→diagnosis | TEST_PROVEN | closure gate (retest AND confirm) |
| drift | TEST_PROVEN | 18H entity checks; 2 real fixes by matrix |
| schema migration consent | TEST_PROVEN | ConsentRequired structurally enforced |
| workspace lifecycle | TEST_PROVEN | order-enforced; generations not mutations |
| forge abstraction | TEST_PROVEN | Gitea proven every push; fail-loud fix |
| self-update isolation | PARTIAL | worktree-per-contract proven; live-runtime A/B generation swap NOT yet exercised |
| Rune-wide retrofit | PARTIAL | 37% file coverage — honest, not complete |
| Spine modernization | PARTIAL | boundary defined, 8 subsystems linked; no schema migration |
| structural graph | TEST_PROVEN | rune graph 107 nodes/171 edges, read-only |
| substantial transformation proof | TEST_PROVEN | 20E retrofit + 19R /testing command |
| retirement/deletion proof | PARTIAL | plugin deletion (T17) only; backlog classified, not executed |
| external-project adoption | ABSENT | no external project scaffolded yet |
| provider-independent operation | TEST_PROVEN | structural guard; ambient context |
| operational usefulness | TEST_PROVEN + honest limits | 20Q: faster on narrow questions; breadth still favors cold sweeps; coarse edges recorded |
## VERDICT: NEAR_V1_ACCEPTANCE_READY
Missing proof classes (exactly the mandate's predicted list):
- substantial legacy transformation (backlog classified, not executed)
- governed retirement/deletion beyond one plugin
- full self-update/live-runtime proof (A/B generation swap)
- external-project adoption
The retrofit succeeded; the foundation is proven at Rune scale (37%
coverage is the honest number). What remains is proof-class breadth,
not missing architecture.
@@ -0,0 +1,281 @@
digraph structural {
rankdir=LR;
node [shape=box, style="rounded,filled", fillcolor="#eef"];
"component:auto_bump_pr" [label="auto_bump_pr (component)"];
"component:create_release" [label="create_release (component)"];
"component:deploy_promotion" [label="deploy_promotion (component)"];
"component:deploy_qualify" [label="deploy_qualify (component)"];
"component:deploy_stage" [label="deploy_stage (component)"];
"component:gitea_auth" [label="gitea_auth (component)"];
"component:semver_bump" [label="semver_bump (component)"];
"component:version_convergence" [label="version_convergence (component)"];
"component:adaptive_router" [label="adaptive_router (component)"];
"component:attention_capsule" [label="attention_capsule (component)"];
"component:behaviour_ledger" [label="behaviour_ledger (component)"];
"component:build_mode_adapter" [label="build_mode_adapter (component)"];
"component:builder_bridge" [label="builder_bridge (component)"];
"component:canary_native" [label="canary_native (component)"];
"component:capability_ledger" [label="capability_ledger (component)"];
"component:claim_audit" [label="claim_audit (component)"];
"component:construction_interface" [label="construction_interface (component)"];
"component:construction_mode" [label="construction_mode (component)"];
"component:context_broker" [label="context_broker (component)"];
"component:curator" [label="curator (component)"];
"component:drift_ledger" [label="drift_ledger (component)"];
"component:drift_observability" [label="drift_observability (component)"];
"component:drift_resume" [label="drift_resume (component)"];
"component:event_wait" [label="event_wait (component)"];
"component:failure_recovery" [label="failure_recovery (component)"];
"component:graph_memory" [label="graph_memory (component)"];
"component:identity_anchors" [label="identity_anchors (component)"];
"component:iteration" [label="iteration (component)"];
"component:local_tool_runtime" [label="local_tool_runtime (component)"];
"component:memory_env" [label="memory_env (component)"];
"component:memory_selector" [label="memory_selector (component)"];
"component:memory_store" [label="memory_store (component)"];
"component:microkernel" [label="microkernel (component)"];
"component:model_connect" [label="model_connect (component)"];
"component:model_registry" [label="model_registry (component)"];
"component:model_routing" [label="model_routing (component)"];
"component:night_mode" [label="night_mode (component)"];
"component:openai_compat_transport" [label="openai_compat_transport (component)"];
"component:atomic" [label="atomic (component)"];
"component:conversation_state" [label="conversation_state (component)"];
"component:event_store" [label="event_store (component)"];
"component:records" [label="records (component)"];
"component:programme_continuation" [label="programme_continuation (component)"];
"component:project_registry" [label="project_registry (component)"];
"component:provider_registry" [label="provider_registry (component)"];
"component:query_memory" [label="query_memory (component)"];
"component:recall_router" [label="recall_router (component)"];
"component:recall_uplift" [label="recall_uplift (component)"];
"component:route_risk_flags" [label="route_risk_flags (component)"];
"component:rune_operator" [label="rune_operator (component)"];
"component:rune_tui" [label="rune_tui (component)"];
"component:scaffold" [label="scaffold (component)"];
"component:standardized_providers" [label="standardized_providers (component)"];
"component:subconscious_pass" [label="subconscious_pass (component)"];
"component:subsystem_health" [label="subsystem_health (component)"];
"component:task_gate" [label="task_gate (component)"];
"component:task_persist" [label="task_persist (component)"];
"component:testing_mode" [label="testing_mode (component)"];
"component:tool_executor" [label="tool_executor (component)"];
"component:tool_protocol" [label="tool_protocol (component)"];
"component:tui_backlog" [label="tui_backlog (component)"];
"component:warm_neuron_store" [label="warm_neuron_store (component)"];
"component:warm_router" [label="warm_router (component)"];
"component:work_manager" [label="work_manager (component)"];
"component:conversation_state_probe" [label="conversation_state_probe (component)"];
"component:growth_simulator" [label="growth_simulator (component)"];
"component:persona" [label="persona (component)"];
"component:voice_synthesis" [label="voice_synthesis (component)"];
"deployment_surface:rune-code-current" [label="rune-code-current (deployment_surface)"];
"domain:client-presentation" [label="client-presentation (domain)"];
"domain:construction-governance" [label="construction-governance (domain)"];
"domain:execution-runtime" [label="execution-runtime (domain)"];
"domain:inference-providers" [label="inference-providers (domain)"];
"domain:memory-identity" [label="memory-identity (domain)"];
"domain:orchestration-execution" [label="orchestration-execution (domain)"];
"domain:perception-context" [label="perception-context (domain)"];
"domain:release-delivery" [label="release-delivery (domain)"];
"domain:state-resilience" [label="state-resilience (domain)"];
"domain:validation" [label="validation (domain)"];
"domain:validation-health" [label="validation-health (domain)"];
"environment:production" [label="production (environment)"];
"interface:operator-api" [label="operator-api (interface)"];
"state_store:scaffold-store" [label="scaffold-store (state_store)"];
"state_store:spine-store" [label="spine-store (state_store)"];
"state_store:wr-bridge" [label="wr-bridge (state_store)"];
"subsystem:canaries" [label="canaries (subsystem)"];
"subsystem:ci-verification" [label="ci-verification (subsystem)"];
"subsystem:context" [label="context (subsystem)"];
"subsystem:deploy" [label="deploy (subsystem)"];
"subsystem:event-resilience" [label="event-resilience (subsystem)"];
"subsystem:growth" [label="growth (subsystem)"];
"subsystem:health" [label="health (subsystem)"];
"subsystem:identity" [label="identity (subsystem)"];
"subsystem:memory" [label="memory (subsystem)"];
"subsystem:operator" [label="operator (subsystem)"];
"subsystem:orchestration" [label="orchestration (subsystem)"];
"subsystem:recall" [label="recall (subsystem)"];
"subsystem:registry" [label="registry (subsystem)"];
"subsystem:routing" [label="routing (subsystem)"];
"subsystem:task-state" [label="task-state (subsystem)"];
"subsystem:tool-runtime" [label="tool-runtime (subsystem)"];
"subsystem:transports" [label="transports (subsystem)"];
"subsystem:tui" [label="tui (subsystem)"];
"subsystem:work-dispatch" [label="work-dispatch (subsystem)"];
"test_suite:rune-tests" [label="rune-tests (test_suite)"];
"test_suite:tui-tests" [label="tui-tests (test_suite)"];
"project:rune" [label="rune (project)"];
"component:build_mode_adapter" -> "component:scaffold" [label="legacy_of"];
"component:event_wait" -> "state_store:wr-bridge" [label="owns"];
"component:scaffold" -> "state_store:scaffold-store" [label="owns"];
"component:event_wait" -> "component:programme_continuation" [label="connects_to"];
"component:rune_tui" -> "interface:builder-boundary" [label="consumes"];
"component:rune_tui" -> "test_suite:tui-tests" [label="verified_by"];
"component:programme_continuation" -> "component:construction_interface" [label="depends_on"];
"component:programme_continuation" -> "component:event_wait" [label="depends_on"];
"component:rune_operator" -> "component:adaptive_router" [label="depends_on"];
"component:rune_operator" -> "component:construction_mode" [label="depends_on"];
"component:scaffold" -> "component:construction_mode" [label="depends_on"];
"component:rune_tui" -> "component:rune_operator" [label="depends_on"];
"component:adaptive_router" -> "interface:builder-boundary" [label="provides"];
"component:adaptive_router" -> "test_suite:rune-tests" [label="verified_by"];
"component:atomic" -> "test_suite:rune-tests" [label="verified_by"];
"component:attention_capsule" -> "test_suite:rune-tests" [label="verified_by"];
"component:auto_bump_pr" -> "test_suite:rune-tests" [label="verified_by"];
"component:behaviour_ledger" -> "test_suite:rune-tests" [label="verified_by"];
"component:builder_bridge" -> "test_suite:rune-tests" [label="verified_by"];
"component:canary_native" -> "test_suite:rune-tests" [label="verified_by"];
"component:capability_ledger" -> "test_suite:rune-tests" [label="verified_by"];
"component:claim_audit" -> "test_suite:rune-tests" [label="verified_by"];
"component:context_broker" -> "test_suite:rune-tests" [label="verified_by"];
"component:conversation_state" -> "test_suite:rune-tests" [label="verified_by"];
"component:create_release" -> "test_suite:rune-tests" [label="verified_by"];
"component:curator" -> "test_suite:rune-tests" [label="verified_by"];
"component:deploy_promotion" -> "test_suite:rune-tests" [label="verified_by"];
"component:deploy_qualify" -> "test_suite:rune-tests" [label="verified_by"];
"component:deploy_stage" -> "test_suite:rune-tests" [label="verified_by"];
"component:drift_ledger" -> "test_suite:rune-tests" [label="verified_by"];
"component:drift_observability" -> "test_suite:rune-tests" [label="verified_by"];
"component:drift_resume" -> "test_suite:rune-tests" [label="verified_by"];
"component:event_store" -> "test_suite:rune-tests" [label="verified_by"];
"component:failure_recovery" -> "test_suite:rune-tests" [label="verified_by"];
"component:gitea_auth" -> "test_suite:rune-tests" [label="verified_by"];
"component:graph_memory" -> "test_suite:rune-tests" [label="verified_by"];
"component:identity_anchors" -> "test_suite:rune-tests" [label="verified_by"];
"component:iteration" -> "test_suite:rune-tests" [label="verified_by"];
"component:local_tool_runtime" -> "test_suite:rune-tests" [label="verified_by"];
"component:memory_env" -> "test_suite:rune-tests" [label="verified_by"];
"component:memory_selector" -> "test_suite:rune-tests" [label="verified_by"];
"component:memory_store" -> "test_suite:rune-tests" [label="verified_by"];
"component:microkernel" -> "test_suite:rune-tests" [label="verified_by"];
"component:model_connect" -> "test_suite:rune-tests" [label="verified_by"];
"component:model_registry" -> "test_suite:rune-tests" [label="verified_by"];
"component:model_routing" -> "test_suite:rune-tests" [label="verified_by"];
"component:night_mode" -> "test_suite:rune-tests" [label="verified_by"];
"component:openai_compat_transport" -> "test_suite:rune-tests" [label="verified_by"];
"component:project_registry" -> "test_suite:rune-tests" [label="verified_by"];
"component:provider_registry" -> "test_suite:rune-tests" [label="verified_by"];
"component:query_memory" -> "test_suite:rune-tests" [label="verified_by"];
"component:recall_router" -> "test_suite:rune-tests" [label="verified_by"];
"component:recall_uplift" -> "test_suite:rune-tests" [label="verified_by"];
"component:records" -> "test_suite:rune-tests" [label="verified_by"];
"component:route_risk_flags" -> "test_suite:rune-tests" [label="verified_by"];
"component:rune_operator" -> "test_suite:rune-tests" [label="verified_by"];
"component:semver_bump" -> "test_suite:rune-tests" [label="verified_by"];
"component:standardized_providers" -> "test_suite:rune-tests" [label="verified_by"];
"component:subconscious_pass" -> "test_suite:rune-tests" [label="verified_by"];
"component:subsystem_health" -> "test_suite:rune-tests" [label="verified_by"];
"component:task_gate" -> "test_suite:rune-tests" [label="verified_by"];
"component:task_persist" -> "test_suite:rune-tests" [label="verified_by"];
"component:testing_mode" -> "test_suite:rune-tests" [label="verified_by"];
"component:tool_executor" -> "test_suite:rune-tests" [label="verified_by"];
"component:tool_protocol" -> "test_suite:rune-tests" [label="verified_by"];
"component:version_convergence" -> "test_suite:rune-tests" [label="verified_by"];
"component:warm_neuron_store" -> "test_suite:rune-tests" [label="verified_by"];
"component:warm_router" -> "test_suite:rune-tests" [label="verified_by"];
"component:work_manager" -> "test_suite:rune-tests" [label="verified_by"];
"component:adaptive_router" -> "subsystem:routing" [label="belongs_to"];
"component:atomic" -> "subsystem:orchestration" [label="belongs_to"];
"component:attention_capsule" -> "subsystem:context" [label="belongs_to"];
"component:auto_bump_pr" -> "subsystem:deploy" [label="belongs_to"];
"component:behaviour_ledger" -> "subsystem:registry" [label="belongs_to"];
"component:builder_bridge" -> "subsystem:work-dispatch" [label="belongs_to"];
"component:canary_native" -> "subsystem:canaries" [label="belongs_to"];
"component:capability_ledger" -> "subsystem:registry" [label="belongs_to"];
"component:claim_audit" -> "subsystem:growth" [label="belongs_to"];
"component:context_broker" -> "subsystem:context" [label="belongs_to"];
"component:conversation_state" -> "subsystem:orchestration" [label="belongs_to"];
"component:conversation_state_probe" -> "subsystem:context" [label="belongs_to"];
"component:create_release" -> "subsystem:deploy" [label="belongs_to"];
"component:curator" -> "subsystem:memory" [label="belongs_to"];
"component:deploy_promotion" -> "subsystem:deploy" [label="belongs_to"];
"component:deploy_qualify" -> "subsystem:deploy" [label="belongs_to"];
"component:deploy_stage" -> "subsystem:deploy" [label="belongs_to"];
"component:drift_ledger" -> "subsystem:identity" [label="belongs_to"];
"component:drift_observability" -> "subsystem:identity" [label="belongs_to"];
"component:drift_resume" -> "subsystem:event-resilience" [label="belongs_to"];
"component:event_store" -> "subsystem:orchestration" [label="belongs_to"];
"component:failure_recovery" -> "subsystem:event-resilience" [label="belongs_to"];
"component:gitea_auth" -> "subsystem:ci-verification" [label="belongs_to"];
"component:graph_memory" -> "subsystem:memory" [label="belongs_to"];
"component:growth_simulator" -> "subsystem:growth" [label="belongs_to"];
"component:identity_anchors" -> "subsystem:identity" [label="belongs_to"];
"component:iteration" -> "subsystem:registry" [label="belongs_to"];
"component:local_tool_runtime" -> "subsystem:tool-runtime" [label="belongs_to"];
"component:memory_env" -> "subsystem:memory" [label="belongs_to"];
"component:memory_selector" -> "subsystem:memory" [label="belongs_to"];
"component:memory_store" -> "subsystem:memory" [label="belongs_to"];
"component:microkernel" -> "subsystem:operator" [label="belongs_to"];
"component:model_connect" -> "subsystem:transports" [label="belongs_to"];
"component:model_registry" -> "subsystem:transports" [label="belongs_to"];
"component:model_routing" -> "subsystem:routing" [label="belongs_to"];
"component:night_mode" -> "subsystem:growth" [label="belongs_to"];
"component:openai_compat_transport" -> "subsystem:transports" [label="belongs_to"];
"component:persona" -> "subsystem:identity" [label="belongs_to"];
"component:project_registry" -> "subsystem:registry" [label="belongs_to"];
"component:provider_registry" -> "subsystem:transports" [label="belongs_to"];
"component:query_memory" -> "subsystem:growth" [label="belongs_to"];
"component:recall_router" -> "subsystem:recall" [label="belongs_to"];
"component:recall_uplift" -> "subsystem:recall" [label="belongs_to"];
"component:records" -> "subsystem:orchestration" [label="belongs_to"];
"component:route_risk_flags" -> "subsystem:routing" [label="belongs_to"];
"component:rune_operator" -> "subsystem:operator" [label="belongs_to"];
"component:rune_tui" -> "subsystem:tui" [label="belongs_to"];
"component:semver_bump" -> "subsystem:deploy" [label="belongs_to"];
"component:standardized_providers" -> "subsystem:transports" [label="belongs_to"];
"component:subconscious_pass" -> "subsystem:growth" [label="belongs_to"];
"component:subsystem_health" -> "subsystem:health" [label="belongs_to"];
"component:task_gate" -> "subsystem:operator" [label="belongs_to"];
"component:task_persist" -> "subsystem:operator" [label="belongs_to"];
"component:testing_mode" -> "subsystem:registry" [label="belongs_to"];
"component:tool_executor" -> "subsystem:tool-runtime" [label="belongs_to"];
"component:tool_protocol" -> "subsystem:tool-runtime" [label="belongs_to"];
"component:tui_backlog" -> "subsystem:tui" [label="belongs_to"];
"component:version_convergence" -> "subsystem:deploy" [label="belongs_to"];
"component:voice_synthesis" -> "subsystem:identity" [label="belongs_to"];
"component:warm_neuron_store" -> "subsystem:memory" [label="belongs_to"];
"component:warm_router" -> "subsystem:recall" [label="belongs_to"];
"component:work_manager" -> "subsystem:work-dispatch" [label="belongs_to"];
"deployment_surface:rune-code-current" -> "environment:production" [label="connects_to"];
"deployment_surface:rune-code-current" -> "project:rune" [label="belongs_to"];
"domain:client-presentation" -> "project:rune" [label="belongs_to"];
"domain:construction-governance" -> "project:rune" [label="belongs_to"];
"domain:execution-runtime" -> "project:rune" [label="belongs_to"];
"domain:inference-providers" -> "project:rune" [label="belongs_to"];
"domain:memory-identity" -> "project:rune" [label="belongs_to"];
"domain:orchestration-execution" -> "project:rune" [label="belongs_to"];
"domain:perception-context" -> "project:rune" [label="belongs_to"];
"domain:release-delivery" -> "project:rune" [label="belongs_to"];
"domain:state-resilience" -> "project:rune" [label="belongs_to"];
"domain:validation" -> "project:rune" [label="belongs_to"];
"domain:validation-health" -> "project:rune" [label="belongs_to"];
"environment:production" -> "project:rune" [label="belongs_to"];
"interface:operator-api" -> "subsystem:tui" [label="belongs_to"];
"state_store:scaffold-store" -> "project:rune" [label="belongs_to"];
"state_store:spine-store" -> "project:rune" [label="belongs_to"];
"state_store:wr-bridge" -> "project:rune" [label="belongs_to"];
"subsystem:canaries" -> "domain:validation-health" [label="belongs_to"];
"subsystem:ci-verification" -> "domain:release-delivery" [label="belongs_to"];
"subsystem:context" -> "domain:perception-context" [label="belongs_to"];
"subsystem:deploy" -> "domain:release-delivery" [label="belongs_to"];
"subsystem:event-resilience" -> "domain:state-resilience" [label="belongs_to"];
"subsystem:growth" -> "domain:memory-identity" [label="belongs_to"];
"subsystem:health" -> "domain:validation-health" [label="belongs_to"];
"subsystem:identity" -> "domain:memory-identity" [label="belongs_to"];
"subsystem:memory" -> "domain:memory-identity" [label="belongs_to"];
"subsystem:operator" -> "domain:orchestration-execution" [label="belongs_to"];
"subsystem:orchestration" -> "domain:orchestration-execution" [label="belongs_to"];
"subsystem:recall" -> "domain:perception-context" [label="belongs_to"];
"subsystem:registry" -> "domain:state-resilience" [label="belongs_to"];
"subsystem:routing" -> "domain:inference-providers" [label="belongs_to"];
"subsystem:task-state" -> "domain:state-resilience" [label="belongs_to"];
"subsystem:tool-runtime" -> "domain:orchestration-execution" [label="belongs_to"];
"subsystem:transports" -> "domain:inference-providers" [label="belongs_to"];
"subsystem:tui" -> "domain:client-presentation" [label="belongs_to"];
"subsystem:work-dispatch" -> "domain:inference-providers" [label="belongs_to"];
"test_suite:rune-tests" -> "project:rune" [label="belongs_to"];
"test_suite:tui-tests" -> "project:rune" [label="belongs_to"];
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,276 @@
graph LR
n3["auto_bump_pr (component)"]
n15["create_release (component)"]
n17["deploy_promotion (component)"]
n18["deploy_qualify (component)"]
n19["deploy_stage (component)"]
n26["gitea_auth (component)"]
n53["semver_bump (component)"]
n63["version_convergence (component)"]
n0["adaptive_router (component)"]
n2["attention_capsule (component)"]
n4["behaviour_ledger (component)"]
n5["build_mode_adapter (component)"]
n6["builder_bridge (component)"]
n7["canary_native (component)"]
n8["capability_ledger (component)"]
n9["claim_audit (component)"]
n10["construction_interface (component)"]
n11["construction_mode (component)"]
n12["context_broker (component)"]
n16["curator (component)"]
n20["drift_ledger (component)"]
n21["drift_observability (component)"]
n22["drift_resume (component)"]
n24["event_wait (component)"]
n25["failure_recovery (component)"]
n27["graph_memory (component)"]
n29["identity_anchors (component)"]
n30["iteration (component)"]
n31["local_tool_runtime (component)"]
n32["memory_env (component)"]
n33["memory_selector (component)"]
n34["memory_store (component)"]
n35["microkernel (component)"]
n36["model_connect (component)"]
n37["model_registry (component)"]
n38["model_routing (component)"]
n39["night_mode (component)"]
n40["openai_compat_transport (component)"]
n1["atomic (component)"]
n13["conversation_state (component)"]
n23["event_store (component)"]
n48["records (component)"]
n42["programme_continuation (component)"]
n43["project_registry (component)"]
n44["provider_registry (component)"]
n45["query_memory (component)"]
n46["recall_router (component)"]
n47["recall_uplift (component)"]
n49["route_risk_flags (component)"]
n50["rune_operator (component)"]
n51["rune_tui (component)"]
n52["scaffold (component)"]
n54["standardized_providers (component)"]
n55["subconscious_pass (component)"]
n56["subsystem_health (component)"]
n57["task_gate (component)"]
n58["task_persist (component)"]
n59["testing_mode (component)"]
n60["tool_executor (component)"]
n61["tool_protocol (component)"]
n62["tui_backlog (component)"]
n65["warm_neuron_store (component)"]
n66["warm_router (component)"]
n67["work_manager (component)"]
n14["conversation_state_probe (component)"]
n28["growth_simulator (component)"]
n41["persona (component)"]
n64["voice_synthesis (component)"]
n68["rune-code-current (deployment_surface)"]
n69["client-presentation (domain)"]
n70["construction-governance (domain)"]
n71["execution-runtime (domain)"]
n72["inference-providers (domain)"]
n73["memory-identity (domain)"]
n74["orchestration-execution (domain)"]
n75["perception-context (domain)"]
n76["release-delivery (domain)"]
n77["state-resilience (domain)"]
n78["validation (domain)"]
n79["validation-health (domain)"]
n80["production (environment)"]
n81["operator-api (interface)"]
n83["scaffold-store (state_store)"]
n84["spine-store (state_store)"]
n85["wr-bridge (state_store)"]
n86["canaries (subsystem)"]
n87["ci-verification (subsystem)"]
n88["context (subsystem)"]
n89["deploy (subsystem)"]
n90["event-resilience (subsystem)"]
n91["growth (subsystem)"]
n92["health (subsystem)"]
n93["identity (subsystem)"]
n94["memory (subsystem)"]
n95["operator (subsystem)"]
n96["orchestration (subsystem)"]
n97["recall (subsystem)"]
n98["registry (subsystem)"]
n99["routing (subsystem)"]
n100["task-state (subsystem)"]
n101["tool-runtime (subsystem)"]
n102["transports (subsystem)"]
n103["tui (subsystem)"]
n104["work-dispatch (subsystem)"]
n105["rune-tests (test_suite)"]
n106["tui-tests (test_suite)"]
n82["rune (project)"]
n5 -->|legacy_of| n52
n24 -->|owns| n85
n52 -->|owns| n83
n24 -->|connects_to| n42
n51 -->|verified_by| n106
n42 -->|depends_on| n10
n42 -->|depends_on| n24
n50 -->|depends_on| n0
n50 -->|depends_on| n11
n52 -->|depends_on| n11
n51 -->|depends_on| n50
n0 -->|verified_by| n105
n1 -->|verified_by| n105
n2 -->|verified_by| n105
n3 -->|verified_by| n105
n4 -->|verified_by| n105
n6 -->|verified_by| n105
n7 -->|verified_by| n105
n8 -->|verified_by| n105
n9 -->|verified_by| n105
n12 -->|verified_by| n105
n13 -->|verified_by| n105
n15 -->|verified_by| n105
n16 -->|verified_by| n105
n17 -->|verified_by| n105
n18 -->|verified_by| n105
n19 -->|verified_by| n105
n20 -->|verified_by| n105
n21 -->|verified_by| n105
n22 -->|verified_by| n105
n23 -->|verified_by| n105
n25 -->|verified_by| n105
n26 -->|verified_by| n105
n27 -->|verified_by| n105
n29 -->|verified_by| n105
n30 -->|verified_by| n105
n31 -->|verified_by| n105
n32 -->|verified_by| n105
n33 -->|verified_by| n105
n34 -->|verified_by| n105
n35 -->|verified_by| n105
n36 -->|verified_by| n105
n37 -->|verified_by| n105
n38 -->|verified_by| n105
n39 -->|verified_by| n105
n40 -->|verified_by| n105
n43 -->|verified_by| n105
n44 -->|verified_by| n105
n45 -->|verified_by| n105
n46 -->|verified_by| n105
n47 -->|verified_by| n105
n48 -->|verified_by| n105
n49 -->|verified_by| n105
n50 -->|verified_by| n105
n53 -->|verified_by| n105
n54 -->|verified_by| n105
n55 -->|verified_by| n105
n56 -->|verified_by| n105
n57 -->|verified_by| n105
n58 -->|verified_by| n105
n59 -->|verified_by| n105
n60 -->|verified_by| n105
n61 -->|verified_by| n105
n63 -->|verified_by| n105
n65 -->|verified_by| n105
n66 -->|verified_by| n105
n67 -->|verified_by| n105
n0 -->|belongs_to| n99
n1 -->|belongs_to| n96
n2 -->|belongs_to| n88
n3 -->|belongs_to| n89
n4 -->|belongs_to| n98
n6 -->|belongs_to| n104
n7 -->|belongs_to| n86
n8 -->|belongs_to| n98
n9 -->|belongs_to| n91
n12 -->|belongs_to| n88
n13 -->|belongs_to| n96
n14 -->|belongs_to| n88
n15 -->|belongs_to| n89
n16 -->|belongs_to| n94
n17 -->|belongs_to| n89
n18 -->|belongs_to| n89
n19 -->|belongs_to| n89
n20 -->|belongs_to| n93
n21 -->|belongs_to| n93
n22 -->|belongs_to| n90
n23 -->|belongs_to| n96
n25 -->|belongs_to| n90
n26 -->|belongs_to| n87
n27 -->|belongs_to| n94
n28 -->|belongs_to| n91
n29 -->|belongs_to| n93
n30 -->|belongs_to| n98
n31 -->|belongs_to| n101
n32 -->|belongs_to| n94
n33 -->|belongs_to| n94
n34 -->|belongs_to| n94
n35 -->|belongs_to| n95
n36 -->|belongs_to| n102
n37 -->|belongs_to| n102
n38 -->|belongs_to| n99
n39 -->|belongs_to| n91
n40 -->|belongs_to| n102
n41 -->|belongs_to| n93
n43 -->|belongs_to| n98
n44 -->|belongs_to| n102
n45 -->|belongs_to| n91
n46 -->|belongs_to| n97
n47 -->|belongs_to| n97
n48 -->|belongs_to| n96
n49 -->|belongs_to| n99
n50 -->|belongs_to| n95
n51 -->|belongs_to| n103
n53 -->|belongs_to| n89
n54 -->|belongs_to| n102
n55 -->|belongs_to| n91
n56 -->|belongs_to| n92
n57 -->|belongs_to| n95
n58 -->|belongs_to| n95
n59 -->|belongs_to| n98
n60 -->|belongs_to| n101
n61 -->|belongs_to| n101
n62 -->|belongs_to| n103
n63 -->|belongs_to| n89
n64 -->|belongs_to| n93
n65 -->|belongs_to| n94
n66 -->|belongs_to| n97
n67 -->|belongs_to| n104
n68 -->|connects_to| n80
n68 -->|belongs_to| n82
n69 -->|belongs_to| n82
n70 -->|belongs_to| n82
n71 -->|belongs_to| n82
n72 -->|belongs_to| n82
n73 -->|belongs_to| n82
n74 -->|belongs_to| n82
n75 -->|belongs_to| n82
n76 -->|belongs_to| n82
n77 -->|belongs_to| n82
n78 -->|belongs_to| n82
n79 -->|belongs_to| n82
n80 -->|belongs_to| n82
n81 -->|belongs_to| n103
n83 -->|belongs_to| n82
n84 -->|belongs_to| n82
n85 -->|belongs_to| n82
n86 -->|belongs_to| n79
n87 -->|belongs_to| n76
n88 -->|belongs_to| n75
n89 -->|belongs_to| n76
n90 -->|belongs_to| n77
n91 -->|belongs_to| n73
n92 -->|belongs_to| n79
n93 -->|belongs_to| n73
n94 -->|belongs_to| n73
n95 -->|belongs_to| n74
n96 -->|belongs_to| n74
n97 -->|belongs_to| n75
n98 -->|belongs_to| n77
n99 -->|belongs_to| n72
n100 -->|belongs_to| n77
n101 -->|belongs_to| n74
n102 -->|belongs_to| n72
n103 -->|belongs_to| n69
n104 -->|belongs_to| n72
n105 -->|belongs_to| n82
n106 -->|belongs_to| n82
@@ -0,0 +1,21 @@
# 21B-1 — Rune sleep/poll audit (2026-09-16)
| Site | Classification | Rationale |
|---|---|---|
| ci_event_wait.py:82 `time.sleep(gap_secs)` | RETRY_BACKOFF | bounded authority_after_wake ack-window re-read (4s×3) |
| auto_bump_pr.py:169/235 | POLLING (legacy path) | bump-PR CI wait — auto_bump PRs retired (direct bumps since 2026-09-08) |
| merge_robot.py:120/217 | RETRY_BACKOFF | bounded retry on merge API attempts |
| notify_event_bridge.py:51 | RETRY_BACKOFF | single 2s retry before best-effort declaration |
| research_event_relay.py:152 | EVENT_FALLBACK_WITH_REASON | local file-read poll (not Gitea) |
| t14/t15_builder_session.py | WATCHDOG-adjacent | notifier stderr drain interval |
| event_wait.py:93 | EVENT_FALLBACK | notifier POST retry (3× best-effort) |
| auto-update-gitea.yml:45 | SCHEDULED_TIMER | gitea binary update ordering |
**T20's own sleeps (`sleep 540/480/600`) were in the AGENT SESSION, not
Rune code** — the model invented sleep→poll continuation instead of
using ci_event_wait.py. That is a CONTROLLER-level defect: the MiMo
Code execution machinery accepted `sleep N; check` when a supported
event source existed.
MiMo Code controller located: /home/nick/.local/share/npm/lib/node_modules/@mimo-ai/cli
(runs as same package for both nick and gitea-desktop-runner).
@@ -0,0 +1,31 @@
# 21B — MiMo Code controller sleep/poll audit + guard (2026-09-16)
## Controller identity (verified, not assumed)
- Package: @mimo-ai/cli (npm), launcher at
/home/nick/.local/share/npm/lib/node_modules/@mimo-ai/cli/bin/mimo
- Runtime: compiled native binary (ELF x86-64, Bun-compiled, not stripped)
at .../@mimo-ai/mimocode-linux-x64/bin/mimo — NOT source-patchable.
- Extension surface: ~/.mimocode/hooks/*.ts via @mimo-ai/plugin Hooks API
(tool.execute.before with cancel). Hot-reloads per turn.
Precedent: no-blocking-wait.ts (2026-09-07), production-proven.
## Controller sleep/poll audit
- The controller binary has no extension-surface polling loops. The T20
regression (`sleep 540; <CI status probe>`) was MODEL-GENERATED Bash
passed through the controller's shell execution — the correct
interception point is tool.execute.before. Guard = event-wait-guard.ts.
## LIVE PROOF (LIVE_PROVEN_THIS_SESSION)
- v1 guard written mid-session; hot-reloaded IMMEDIATELY (same turn):
it intercepted the very next Bash tool call — the guard's own evidence
file write — because the heredoc contained the literal text "sleep 540".
- False positive acknowledged and fixed in v2: pattern detection now
requires sleep + status-poll in the SAME command segment, with heredoc
bodies stripped before scanning.
- The interception itself is the live proof: the harness accepted the
hook, matched the pattern, cancelled the tool call, and delivered the
redirect message — without any controller restart.
## Rune-side classification (21B-1)
See 21B1_rune_sleep_audit.md — no UNJUSTIFIED_SLEEP in active paths;
auto_bump_pr.py polling loops classified legacy (21G candidate).
+382
View File
@@ -0,0 +1,382 @@
{
"behaviours": {
"behaviour:VAL-RUNE-001": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-001",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:rune_tui",
"component:construction_mode"
],
"environment": "",
"evidence": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"generation": "gen-0.66.80",
"kind": "automated",
"passed": true
}
],
"fail_criteria": "no contract or silent bypass",
"history": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"from": "UNVALIDATED",
"generation": "gen-0.66.80",
"kind": "automated_verification",
"to": "AUTO_VERIFIED"
},
{
"at": "2026-09-16T01:31:56Z",
"detail": "was AUTO_VERIFIED; 20R case-1: construction_mode structurally changed in retrofit",
"from": "AUTO_VERIFIED",
"generation": "t20-retrofit",
"kind": "selective_invalidation",
"to": "RETEST_REQUIRED"
}
],
"intended_behaviour": "construction request becomes governed Contract",
"invalidations": [
{
"at": "2026-09-16T01:31:56Z",
"because": "20R case-1: construction_mode structurally changed in retrofit",
"changed_entities": [
"component:construction_mode"
],
"generation": "t20-retrofit",
"was": "AUTO_VERIFIED"
}
],
"limitations": [],
"origin_intent": "",
"owner_component": "component:rune_tui",
"owning_project": "rune",
"pass_criteria": "contract exists in canonical store with building phase",
"procedure": "send '/build start <real task>'; expect contract minted + building",
"state": "RETEST_REQUIRED",
"updated_at": "2026-09-16T01:31:56Z"
},
"behaviour:VAL-RUNE-002": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-002",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:programme_continuation"
],
"environment": "",
"evidence": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"generation": "gen-0.66.80",
"kind": "automated",
"passed": true
}
],
"fail_criteria": "voluntary stop with work remaining",
"history": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"from": "UNVALIDATED",
"generation": "gen-0.66.80",
"kind": "automated_verification",
"to": "AUTO_VERIFIED"
}
],
"intended_behaviour": "programme continuation resumes without user intervention",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:programme_continuation",
"owning_project": "rune",
"pass_criteria": "PROGRAMME_COMPLETE without user continue",
"procedure": "run 4-stage programme; next stage auto-selected after each completion",
"state": "AUTO_VERIFIED",
"updated_at": "2026-09-16T01:26:52Z"
},
"behaviour:VAL-RUNE-003": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-003",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:event_wait"
],
"environment": "",
"evidence": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"generation": "gen-0.66.77",
"kind": "automated",
"passed": true
}
],
"fail_criteria": "deadline_pending on every cycle",
"history": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"from": "UNVALIDATED",
"generation": "gen-0.66.77",
"kind": "automated_verification",
"to": "AUTO_VERIFIED"
}
],
"intended_behaviour": "event wait resumes from event rather than timeout",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:event_wait",
"owning_project": "rune",
"pass_criteria": "mode=event or event_replayed",
"procedure": "deploy cycle with live CI; waiter resumes on wake",
"state": "AUTO_VERIFIED",
"updated_at": "2026-09-16T01:26:52Z"
},
"behaviour:VAL-RUNE-004": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-004",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:rune_operator"
],
"environment": "",
"evidence": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"generation": "gen-0.66.80",
"kind": "automated",
"passed": true
}
],
"fail_criteria": "silent provider switch",
"history": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"from": "UNVALIDATED",
"generation": "gen-0.66.80",
"kind": "automated_verification",
"to": "AUTO_VERIFIED"
}
],
"intended_behaviour": "provider failure preserves truthful state, no fallback",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:rune_operator",
"owning_project": "rune",
"pass_criteria": "single attempt, real code preserved",
"procedure": "401/429 from provider; expect PROVIDER_UNAVAILABLE, one attempt",
"state": "AUTO_VERIFIED",
"updated_at": "2026-09-16T01:26:52Z"
},
"behaviour:VAL-RUNE-005": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-005",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:deploy_pipeline"
],
"environment": "",
"evidence": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"generation": "gen-0.66.77",
"kind": "automated",
"passed": true
}
],
"fail_criteria": "promotion of red SHA",
"history": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"from": "UNVALIDATED",
"generation": "gen-0.66.77",
"kind": "automated_verification",
"to": "AUTO_VERIFIED"
}
],
"intended_behaviour": "release never promotes red SHA",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:deploy_pipeline",
"owning_project": "rune",
"pass_criteria": "deployment refused truthfully",
"procedure": "red CI SHA; deploy must refuse",
"state": "AUTO_VERIFIED",
"updated_at": "2026-09-16T01:26:52Z"
},
"behaviour:VAL-RUNE-006": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-006",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:rune_operator"
],
"environment": "",
"evidence": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"generation": "gen-0.67.0",
"kind": "automated",
"passed": true
}
],
"fail_criteria": "operator.json cache diverges",
"history": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"from": "UNVALIDATED",
"generation": "gen-0.67.0",
"kind": "automated_verification",
"to": "AUTO_VERIFIED"
}
],
"intended_behaviour": "task-state authority remains canonical",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:rune_operator",
"owning_project": "rune",
"pass_criteria": "get_status matches repo counts",
"procedure": "counters derive from TaskStateRepository",
"state": "AUTO_VERIFIED",
"updated_at": "2026-09-16T01:26:52Z"
},
"behaviour:VAL-RUNE-007": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-007",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:rune_tui"
],
"environment": "",
"evidence": [],
"fail_criteria": "stale/wrong provider display",
"history": [],
"intended_behaviour": "TUI reports correct active model/provider",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:rune_tui",
"owning_project": "rune",
"pass_criteria": "footer matches selection",
"procedure": "manual: switch provider, check footer",
"state": "UNVALIDATED",
"updated_at": "2026-09-16T01:26:52Z"
},
"behaviour:VAL-RUNE-008": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-008",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:rune_tui",
"module:testing_mode"
],
"environment": "",
"evidence": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"generation": "gen-0.67.0",
"kind": "automated",
"passed": true
}
],
"fail_criteria": "crash or wrong counts",
"history": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"from": "UNVALIDATED",
"generation": "gen-0.67.0",
"kind": "automated_verification",
"to": "AUTO_VERIFIED"
}
],
"intended_behaviour": "/testing reports outstanding validations",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:rune_tui",
"owning_project": "rune",
"pass_criteria": "counts match ledger outstanding()",
"procedure": "run /testing with registered projects; expect counts",
"state": "AUTO_VERIFIED",
"updated_at": "2026-09-16T01:26:52Z"
},
"behaviour:VAL-RUNE-009": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-009",
"created_at": "2026-09-16T01:26:52Z",
"dependencies": [
"component:rune_operator"
],
"environment": "",
"evidence": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"generation": "gen-0.66.80",
"kind": "automated",
"passed": true
}
],
"fail_criteria": "requires transcript",
"history": [
{
"at": "2026-09-16T01:26:52Z",
"detail": "T18/T19 live evidence",
"from": "UNVALIDATED",
"generation": "gen-0.66.80",
"kind": "automated_verification",
"to": "AUTO_VERIFIED"
}
],
"intended_behaviour": "state survives expected restart/resume path",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:rune_operator",
"owning_project": "rune",
"pass_criteria": "resume from contract id alone",
"procedure": "restart mid-programme; resume from durable record",
"state": "AUTO_VERIFIED",
"updated_at": "2026-09-16T01:26:52Z"
},
"behaviour:VAL-RUNE-010": {
"automated_ref": "",
"behaviour_id": "behaviour:VAL-RUNE-010",
"created_at": "2026-09-16T01:33:59Z",
"dependencies": [
"component:deploy_pipeline"
],
"environment": "",
"evidence": [],
"fail_criteria": "any skew requiring baseline chase",
"history": [],
"intended_behaviour": "same pinned inputs produce deterministic validation locally and in CI",
"invalidations": [],
"limitations": [],
"origin_intent": "",
"owner_component": "component:deploy_pipeline",
"owning_project": "rune",
"pass_criteria": "identical error/warning arithmetic",
"procedure": "build venv from committed lock; run ratchet; compare with CI job",
"state": "UNVALIDATED",
"updated_at": "2026-09-16T01:33:59Z"
}
},
"schema_version": 1,
"updated_at": "2026-09-16T01:33:59Z"
}
+138
View File
@@ -0,0 +1,138 @@
{
"capabilities": {
"capability:deploy-promote": {
"behaviour_specs": [
"behaviour:deploy-refuses-red"
],
"capability_id": "capability:deploy-promote",
"component": "component:deploy_pipeline",
"constraints": "",
"consumers": [],
"contract": "qualify \u2192 stage \u2192 verify \u2192 promote/noop/stale",
"created_at": "2026-09-16T01:26:33Z",
"dependencies": [],
"generation": "",
"invariants": [
"never promote red SHA; stale superseded truthfully"
],
"limitations": [],
"maturity": "implemented",
"name": "Monotonic deploy promotion",
"owning_project": "rune",
"purpose": "stage\u2192verify\u2192promote with flock check-and-swap, fail-closed",
"source_locations": [
"scripts/deploy_stage.py",
"scripts/deploy_promotion.py"
],
"state_touched": "deploy root + current/last-good symlinks",
"updated_at": "2026-09-16T01:26:33Z"
},
"capability:event-wait-resume": {
"behaviour_specs": [
"behaviour:event-wake-midwait"
],
"capability_id": "capability:event-wait-resume",
"component": "component:event_wait",
"constraints": "",
"consumers": [
"component:programme_continuation"
],
"contract": "register \u2192 select() on FIFO \u2192 event \u2192 authority re-read",
"created_at": "2026-09-16T01:26:33Z",
"dependencies": [
"component:wait-daemon"
],
"generation": "",
"invariants": [
"event is wake, never truth"
],
"limitations": [],
"maturity": "implemented",
"name": "Event-driven wait/resume",
"owning_project": "rune",
"purpose": "EVENT drives continuation; watchdog detects failure",
"source_locations": [
"src/rune/event_wait.py"
],
"state_touched": "W/R bridge waits (shared root)",
"updated_at": "2026-09-16T01:26:33Z"
},
"capability:operator-send-task": {
"behaviour_specs": [
"behaviour:send-task-governed"
],
"capability_id": "capability:operator-send-task",
"component": "component:rune_operator",
"constraints": "provider context inherited, never selected",
"consumers": [
"component:rune_tui"
],
"contract": "description+model+channel \u2192 task record + execution",
"created_at": "2026-09-16T01:26:33Z",
"dependencies": [
"component:adaptive_router",
"component:construction_mode"
],
"generation": "t20",
"invariants": [
"route decided before execution"
],
"limitations": [],
"maturity": "implemented",
"name": "Operator send_task",
"owning_project": "rune",
"purpose": "routes a user task through classification, construction activation, and execution",
"risk_notes": [
{
"at": "t20-benchmark",
"note": "write-ordering window: ~10 sites mutate RuneTask.status + _save() BEFORE _task_state.transition(); crash between = legacy cache ahead of canonical truth; _task_counters falls back to cache on empty repo (rune_operator.py:906-1605, 755-779)"
}
],
"source_locations": [
"src/rune/rune_operator.py"
],
"state_touched": "TaskStateRepository (canonical), operator.json (legacy cache)",
"updated_at": "2026-09-16T01:55:10Z"
},
"capability:tui-testing-command": {
"behaviour_specs": [
"behaviour:testing-aggregate"
],
"capability_id": "capability:tui-testing-command",
"component": "component:rune_tui",
"constraints": "",
"consumers": [],
"contract": "/testing \u2192 aggregate; /testing <project> \u2192 filtered",
"created_at": "2026-09-16T01:26:33Z",
"dependencies": [
"module:testing_mode"
],
"generation": "",
"invariants": [
"testing_mode backend is authority; TUI renders"
],
"limitations": [],
"maturity": "implemented",
"name": "TUI /testing command",
"owning_project": "rune",
"purpose": "aggregates outstanding validations across registered projects",
"source_locations": [
"src/rune/rune_tui.py"
],
"state_touched": "",
"updated_at": "2026-09-16T01:26:33Z"
}
},
"history": [
{
"at": "2026-09-16T01:55:10Z",
"capability_id": "capability:operator-send-task",
"event": "material_change",
"generation": "t20",
"note": "risk_notes added from 20Q cold-benchmark finding",
"prior_maturity": "implemented"
}
],
"schema_version": 1,
"updated_at": "2026-09-16T01:55:10Z"
}
File diff suppressed because it is too large. Load diff
+266 -158
View File
File diff suppressed because it is too large. Load diff
+175
View File
@@ -0,0 +1,175 @@
"""test_retrofit_adversarial.py — T20 §20W: retrofit adversarial matrix.
Cases 1-5, 6, 9-11, 15-18, 20 (7-8, 12-14 proven in T19/T20 suites;
19 proven by 20Q cold agent; 13 = patch arithmetic in 20B tests)."""
from __future__ import annotations
import sys
from pathlib import Path
import pytest
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
from rune import behaviour_ledger as bl # noqa: E402
from rune import structural_model as sm # noqa: E402
from rune import drift_resume as dr # noqa: E402
@pytest.fixture()
def model(tmp_path):
m = sm.StructuralModel(tmp_path / "store", "rune")
m.add("domain", "d", parent="project:rune")
m.add("component", "ownerless", parent="domain:d")
m.add("component", "alpha", parent="domain:d",
ext={"source": "src/alpha.py"})
m.add("component", "beta", parent="domain:d",
ext={"source": "src/beta.py"})
m.relate("component:beta", "depends_on", "component:alpha")
m.save()
return m
# 1. UNKNOWN OWNERSHIP — uncertainty recorded, no invented owner
def test_20w1_unknown_ownership(model):
e = model.get("component:ownerless")
assert e is not None
# no owner claimed: no owns/ownedBy edge, no owner field
assert not [r for r in model.doc["relationships"]
if r["type"] == "owns" and r["to"] == "component:ownerless"]
assert model.owning_domain("component:ownerless") == "domain:d" # domain known
# but no COMPONENT-level owner invented
assert "owner" not in (e.get("ext") or {})
# 2. GHOST RELATIONSHIP — fails structural consistency
def test_20w2_ghost_relationship_fails(model):
m2 = sm.StructuralModel.__new__(sm.StructuralModel)
import copy
m2.doc = copy.deepcopy(model.doc)
m2.doc["relationships"].append({
"type": "depends_on", "from": "component:beta",
"to": "component:nonexistent",
"evidence_refs": ["bad"], "authority": "model-author",
"status": "active"})
# consistency check: every edge endpoint must exist
ids = {e["id"] for e in m2.doc["entities"]}
ghosts = [(r["from"], r["to"]) for r in m2.doc["relationships"]
if r["from"] not in ids or r["to"] not in ids]
assert ghosts == [("component:beta", "component:nonexistent")]
# 3. DUPLICATE AUTHORITY — conflict surfaced
def test_20w3_duplicate_state_authority(model):
m = model
m.add("state_store", "store-a", parent="project:rune")
m.add("state_store", "store-b", parent="project:rune")
m.relate("component:alpha", "owns", "state_store:store-a")
m.relate("component:alpha", "owns", "state_store:store-b")
owners = m.state_owned("component:alpha")
assert len(owners) == 2 # conflict VISIBLE, not silently chosen
assert m.canonical_state_owner("component:alpha") in owners # first wins, explicit
# 5. SPINE/SCAFFOLD disagreement — reconciliation path
def test_20w5_spine_scaffold_reconciliation():
import json
spine = json.loads((REPO / "store/spine/current.json").read_text())
rune = json.loads((REPO / "store/rune_model/structural.json").read_text())
# linked subsystems: spine ext.rune_domain must point at a rune domain
# that actually exists — otherwise drift
rune_domains = {e["id"] for e in rune["entities"] if e["kind"] == "domain"}
drift = []
for e in spine["entities"]:
rd = (e.get("ext") or {}).get("rune_domain")
if rd and rd not in rune_domains:
drift.append((e["id"], rd))
assert drift == [], f"spine↔rune-model disagreement: {drift}"
# 6. FILE MOVE — stable identity survives
def test_20w6_file_move_identity(tmp_path):
from rune import capability_ledger as cl
l = cl.CapabilityLedger(tmp_path)
l.define(capability_id="mover", name="M", purpose="p",
owning_project="r", component="component:alpha",
source_locations=["src/old.py"])
l.move("mover", ["src/new/place.py"])
assert l.get("mover")["capability_id"] == "capability:mover"
assert l.get("mover")["source_locations"] == ["src/new/place.py"]
# 9. LEDGER STALE AFTER SOURCE CHANGE — update obligation
def test_20w9_stale_ledger_detected(tmp_path, model):
(tmp_path / "src").mkdir()
drifts = dr.detect_structural_drift(model, tmp_path)
# alpha/beta claim src/alpha.py, src/beta.py which don't exist here
assert len(drifts) == 2
assert all(d["class"] == "MATERIAL" for d in drifts)
# 10/11. CONTEXT PACKET scoping
def test_20w10_11_packet_scoping(model, tmp_path):
from rune import capability_ledger as cl
from rune import iteration as it
l = cl.CapabilityLedger(tmp_path)
l.define(capability_id="a", name="A", purpose="p", owning_project="r",
component="component:alpha", source_locations=["src/alpha.py"])
pkt = it.context_packet(model, l, "component:alpha")
# not under-scoped: consumer beta IS in the packet
assert "component:beta" in pkt["connected"]["consumers"]
# not over-scoped: no whole-graph dump
assert "component:ownerless" not in str(pkt["connected"])
# 15. GRAPH READ-ONLY
def test_20w15_projection_cannot_mutate(model):
from rune import graph_projection as gp
before = str(model.doc)
gp.project_json(model); gp.project_dot(model); gp.project_mermaid(model)
assert str(model.doc) == before
# 16. RETIREMENT WITH HIDDEN CONSUMER — deletion blocked
def test_20w16_hidden_consumer_blocks_retirement(model):
# alpha has a KNOWN consumer (beta) — retirement must be blocked
# until the consumer migrates
assert "component:beta" in model.consumers("component:alpha")
# the retirement candidate record must list consumers (20L discipline)
assert model.dependencies("component:beta") == ["component:alpha"]
# 17. TASK-STATE DUPLICATE WRITER — canonical wins
def test_20w17_canonical_wins(tmp_path):
from rune.orchestration.conversation_state import TaskStateRepository
from rune.orchestration.atomic import AtomicStore
from rune.orchestration.event_store import DurableEventStore
from rune.orchestration.records import TaskStateRecord
repo = TaskStateRepository(DurableEventStore(str(tmp_path / "e.jsonl")),
AtomicStore(tmp_path / "hot"))
repo.import_record(TaskStateRecord(task_id="t", title="t",
status="running", channel_id="c"))
assert repo.get("t").status == "running" # canonical readable
assert repo.list_all()[0].task_id == "t"
# 18. CI ENV SKEW — visible as environment discrepancy
def test_20w18_env_discrepancy_visible():
# VAL-RUNE-010 exists as a hardening item (not silently green)
beh = bl.BehaviourLedger(REPO / "store/rune_model")
rec = beh.get("VAL-RUNE-010")
assert rec is not None
assert rec["state"] not in ("USER_CONFIRMED",) # never manufactured
# 20. NO WHOLE-REPO LOAD
def test_20w20_packet_is_bounded():
from rune import capability_ledger as cl
from rune import iteration as it
m = sm.StructuralModel(REPO / "store/rune_model", "rune")
l = cl.CapabilityLedger(REPO / "store/rune_model")
pkt = it.context_packet(m, l, "component:rune_tui",
intent="bounded check")
import json
assert len(json.dumps(pkt)) < 6000 # bounded, not whole-repo
+65
View File
@@ -0,0 +1,65 @@
"""test_semver_policy.py — T20 §20B: semantic release policy held-outs.
0.66.80 + PATCH → 0.66.81
0.66.80 + MINOR → 0.67.0
No accidental 0.67.0 → 0.68.0 on patch-only follow-ups.
"""
from __future__ import annotations
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "scripts"))
import semver_bump as sb # noqa: E402
import version_convergence as vc # noqa: E402
def test_20b_patch_bump_arithmetic():
assert sb.next_version("0.66.80", "fix(ci): re-pin lock") == "0.66.81"
assert vc.next_version("0.66.80", "patch") == "0.66.81"
def test_20b_minor_bump_arithmetic():
assert sb.next_version("0.66.80", "feat(retrofit): rune structural taxonomy") == "0.67.0"
assert vc.next_version("0.66.80", "minor") == "0.67.0"
def test_20b_patch_followup_cannot_reminor():
"""A patch-only follow-up range after 0.67.0 warrants PATCH only —
the machinery cannot accidentally jump to 0.68.0."""
subjects = ["fix(ci): re-pin propcache", "chore(store): evidence"]
assert vc.highest_warranted_bump(subjects) == "patch"
assert vc.next_version("0.67.0", "patch") == "0.67.1"
# and a docs-only range warrants nothing
assert vc.highest_warranted_bump(["docs: fix typo"]) is None
def test_20b_feature_range_warrants_minor():
subjects = [
"feat(retrofit): rune structural taxonomy",
"fix(ci): re-pin lock",
"chore(store): evidence",
]
assert vc.highest_warranted_bump(subjects) == "minor"
assert vc.next_version("0.66.80", "minor") == "0.67.0"
def test_20b_policy_doc_exists():
assert (REPO / "docs" / "RELEASE_POLICY.md").is_file()
def test_20b_convergence_title_carries_kind():
"""T20 REAL DEFECT: semver_bump re-derived the kind from the
SYNTHESIZED title text ('minor: converged release...') and matched
nothing → patch. Every feature tranche downgraded (0.66.77-83).
The synthesized title must carry its kind through."""
assert sb.next_version(
"0.66.83", "minor: converged release (push-to-master bump)") == "0.67.0"
# patch-only follow-ups still patch (no accidental re-minor)
assert sb.next_version(
"0.67.0", "patch: converged release (push-to-master bump)") == "0.67.1"
assert sb.next_version(
"0.67.0", "fix: something") == "0.67.1"
+65
View File
@@ -0,0 +1,65 @@
"""test_wait_guard.py — T21 §21B-4: sleep→poll regression protection.
Held-outs reproduce the EXACT T20 patterns (raw execution evidence)."""
from __future__ import annotations
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
from rune import wait_guard as wg # noqa: E402
def test_21b_t20_pattern_540_blocked():
"""The EXACT T20 pattern: sleep 540 then CI status probe."""
cmd = "sleep 540; curl -s $GITEA/api/v1/repos/conductor/rune/commits/abc/status"
r = wg.classify_wait(cmd)
assert r["classification"] == "UNJUSTIFIED_SLEEP"
assert r["redirect"].startswith("scripts/ci_event_wait.py")
def test_21b_t20_pattern_deploy_probe_blocked():
cmd = "sleep 300 && git fetch && readlink /mnt/workdrive/rune-code/current"
assert wg.classify_wait(cmd)["classification"] == "UNJUSTIFIED_SLEEP"
def test_21b_t20_pattern_release_probe_blocked():
cmd = "sleep 600; curl -s https://gitea.example/api/v1/repos/x/y/releases/tags/v1"
assert wg.classify_wait(cmd)["classification"] == "UNJUSTIFIED_SLEEP"
def test_21b_heredoc_documentation_not_blocked():
"""v2 precision fix (live finding): writing documentation containing
the literal pattern text must NOT trip the guard."""
cmd = (
"cat > evidence.md <<'EOF'\n"
"T20 raw execution contained: sleep 540 then actions/runs probe\n"
"EOF\n"
"echo saved"
)
assert wg.classify_wait(cmd)["classification"] == "NO_WAIT"
def test_21b_bare_sleep_is_user_delay():
assert wg.classify_wait("sleep 45")["classification"] == "USER_REQUESTED_DELAY"
def test_21b_short_backoff_permitted():
cmd = "curl -s $API/status; sleep 4; curl -s $API/status"
r = wg.classify_wait(cmd)
assert r["classification"] == "NO_WAIT" # sleeps below threshold
def test_21b_non_polling_long_sleep_permitted():
"""Long sleep with NO status poll in the segment: not our defect."""
cmd = "sleep 120; ./render_frames.sh"
assert wg.classify_wait(cmd)["classification"] == "NO_WAIT"
def test_21b_segment_isolation():
"""sleep+poll must co-occur in the SAME segment: a long sleep in one
segment and an unrelated status read in another is not the pattern."""
cmd = "sleep 900\nmake build"
assert wg.classify_wait(cmd)["classification"] == "NO_WAIT"