- GO CORE TURN ENGINE (src/go/rune-core): per-channel single-flight, channel-keyed context, K25 tail+snapshot store (D40 seam), live Ollama with the thinking split, PTY parity proven with Python stopped + the owner's 27B live with thinking surfaced - FULL-WIDTH SHARED BOX (D36): spans both panes, focus-signage placeholder, drafts survive focus round-trips, PTY-proven 110+140 - MODEL SPLIT (D37): pane-aware /model, per-pane record fields, status line; letter-stealing round 2 fixed (j/k type) - APPROVAL CARD (T5): gold y/n through /v1/approvals/resolve, stale revalidation, chained asks, PTY-proven both legs - PROVIDERS P1: 18 providers both languages, three-artifact drift gate, provider step in first-run (real names, no 'local' hardcode) - SCROLLBACK: /history depth persisted, ctrl+up/down + pgup/pgdn, dim ↑N indicator, deeper-page fetch, PTY-proven on real history - RETIREMENT rows 4+10 advanced: tool-executor dispatch wired (49/49+48/48), Go mode-gate door built, work-manager CLI parity
142 lines
5.5 KiB
Python
142 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
|
"""gen_mode_matrix.py — ONE mode matrix, three doors (wave-tools-live T1;
|
|
local-tool-runtime joined 2026-10-19, retirement campaign tools row).
|
|
|
|
The frozen CHAT/TASK/PLAN matrix lives ONCE in
|
|
schemas/mode/v1/mode_matrix.json. The Go authorities (toolexec mode
|
|
enforcement + local-tool-runtime dispatch gate) each embed a copy
|
|
because go:embed cannot reach above their module; this script generates
|
|
those copies BYTE-IDENTICALLY and ``--check`` makes drift structurally
|
|
impossible (the boundary-codegen single-source law, mirrored):
|
|
|
|
- a hand-edited embedded copy trips --check RED (byte-diff vs regen),
|
|
- a canonical change without regeneration trips --check RED,
|
|
- a structurally invalid matrix (modes/classes/executor-tool names)
|
|
refuses to generate at all.
|
|
|
|
Python reads the canonical artifact directly (rune.mode_gate) — no
|
|
generation for the Python side.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
CANONICAL = ROOT / "schemas" / "mode" / "v1" / "mode_matrix.json"
|
|
EMBEDDED = [
|
|
ROOT / "src" / "go" / "tool-executor" / "internal" / "toolexec" / "mode_matrix.json",
|
|
ROOT / "src" / "go" / "local-tool-runtime" / "mode_matrix.json",
|
|
]
|
|
|
|
HARD_MODES = {"CHAT", "TASK", "PLAN"}
|
|
GO_CLASS_VOCABULARY = {
|
|
"read", "research.queue", "research.run", "plan.draft", "plan.revise",
|
|
"viability.check", "task.create", "task.start", "build", "edit", "shell",
|
|
}
|
|
|
|
|
|
def _validate(data: dict) -> list[str]:
|
|
errors: list[str] = []
|
|
if data.get("schema_version") != 1:
|
|
errors.append("schema_version must be 1")
|
|
modes = data.get("modes")
|
|
classes = data.get("tool_classes")
|
|
if not isinstance(modes, dict) or set(modes) != HARD_MODES:
|
|
errors.append(f"modes must be exactly {sorted(HARD_MODES)}")
|
|
return errors
|
|
if not isinstance(classes, dict) or set(classes) != GO_CLASS_VOCABULARY:
|
|
errors.append("tool_classes must be exactly the frozen Go vocabulary "
|
|
f"{sorted(GO_CLASS_VOCABULARY)}")
|
|
return errors
|
|
for mode, spec in modes.items():
|
|
if not isinstance(spec, dict):
|
|
errors.append(f"mode {mode} must be an object")
|
|
continue
|
|
for field in ("model", "context", "rules"):
|
|
if not isinstance(spec.get(field), str) or not spec.get(field):
|
|
errors.append(f"mode {mode} must hard-set {field}")
|
|
named = spec.get("classes")
|
|
if not isinstance(named, list) or not named:
|
|
errors.append(f"mode {mode} names no classes")
|
|
continue
|
|
for name in named:
|
|
if name not in classes:
|
|
errors.append(f"mode {mode} names unknown class {name!r}")
|
|
# Executor-tool names must exist in the Python registry the chat door
|
|
# dispatches to (two languages, one vocabulary half).
|
|
sys.path.insert(0, str(ROOT / "src"))
|
|
try:
|
|
from rune.tool_executor import TOOLS # noqa: E402
|
|
|
|
registry = {tool["name"] for tool in TOOLS}
|
|
except Exception as exc: # pragma: no cover - registry drift is a gate failure
|
|
errors.append(f"tool_executor registry unreadable: {exc}")
|
|
return errors
|
|
for class_name, spec in classes.items():
|
|
if not isinstance(spec, dict):
|
|
errors.append(f"class {class_name} must be an object")
|
|
continue
|
|
tools = spec.get("executor_tools")
|
|
if not isinstance(tools, list):
|
|
errors.append(f"class {class_name} executor_tools must be a list")
|
|
continue
|
|
for name in tools:
|
|
if name not in registry:
|
|
errors.append(f"class {class_name} maps unknown executor tool {name!r}")
|
|
status = spec.get("status", "")
|
|
if status == "not_implemented" and tools:
|
|
errors.append(f"class {class_name} is not_implemented but maps executor tools")
|
|
return errors
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--check", action="store_true",
|
|
help="verify the embedded copy is byte-identical; exit 1 on drift")
|
|
args = parser.parse_args()
|
|
|
|
try:
|
|
raw = CANONICAL.read_bytes()
|
|
data = json.loads(raw)
|
|
except (OSError, ValueError) as exc:
|
|
print(f"mode matrix canonical artifact unreadable: {exc}", file=sys.stderr)
|
|
return 1
|
|
errors = _validate(data)
|
|
if errors:
|
|
for error in errors:
|
|
print("mode matrix INVALID:", error, file=sys.stderr)
|
|
return 1
|
|
|
|
if args.check:
|
|
failed = False
|
|
for embedded in EMBEDDED:
|
|
try:
|
|
current = embedded.read_bytes()
|
|
except OSError:
|
|
print(f"CHECK FAILED: embedded copy missing ({embedded}) — run scripts/gen_mode_matrix.py",
|
|
file=sys.stderr)
|
|
failed = True
|
|
continue
|
|
if current != raw:
|
|
print(f"CHECK FAILED: embedded copy drifted from the canonical artifact ({embedded}) — "
|
|
"run scripts/gen_mode_matrix.py", file=sys.stderr)
|
|
failed = True
|
|
if failed:
|
|
return 1
|
|
print("mode matrix: embedded copies byte-identical to canonical")
|
|
return 0
|
|
|
|
for embedded in EMBEDDED:
|
|
embedded.parent.mkdir(parents=True, exist_ok=True)
|
|
embedded.write_bytes(raw)
|
|
print(f"mode matrix: embedded copy written ({len(raw)} bytes) -> {embedded}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|