Live crash-recovery (not fixtures — the REAL serve process): 300-step irreversible task over /v1, SIGSTOP-frozen journal observed, SIGKILL, restart on same home: epoch 2, task resumed, drained live, every irreversible effect exactly once across both generations; a kill inside one effect fails closed as ambiguous. Real defect found + fixed: K9's recovery epoch derived from checkpoint-only truth — crash leaves no checkpoint, every crash-restart reported epoch 1; now generation = max(checkpoint, journal) + 1 (journal-truth counting, crash-proof). Plan document store: durable plans under <home>/plans, atomic tmp+fsync+rename, append-only revisions, traversal-proof IDs; serve surface /v1/plans create/list/fetch/revisions; restart byte-identical recall. Red-first; race-clean. Main-session verify: green own runs.
142 lines
5.8 KiB
Python
142 lines
5.8 KiB
Python
"""Admission dispatch for wave K25 (continuous-depth, spec 1.1 depth +
|
|
4.2 groundwork).
|
|
|
|
classify + activate + admit (the headless scaffolding entry law,
|
|
scripts/admit_wave_k9_continuous_runtime.py pattern, research-gated per
|
|
scripts/admit_wave_research_gate.py): the K9 continuous runtime gains its
|
|
auto-recovery depth — crash → restart → resume with in-flight task
|
|
continuation proven on the REAL runtime (the actual `rune run` serve
|
|
process: SIGKILL mid-task, restart, resumption without duplicate
|
|
irreversible effects, live) — plus the task-4.2 Plan-loop groundwork: the
|
|
durable plan document store (home/plans, atomic writes, append-only
|
|
revisions) wired to the serve surface (/v1/plans), user-dispatch approved.
|
|
"""
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
|
|
|
|
from rune import construction_activation as cact # noqa: E402
|
|
from rune import construction_admission as cadm # noqa: E402
|
|
from rune import construction_mode as cmode # noqa: E402
|
|
from rune import scaffold as sc # noqa: E402
|
|
|
|
ROOT = os.path.join(os.path.dirname(__file__), "..")
|
|
SLUG = "wave-K25-continuous-depth"
|
|
|
|
OBJECTIVE = (
|
|
"build the K9 continuous runtime's auto-recovery depth (rune-runtime "
|
|
"spec task 1.1) and the task-4.2 Plan groundwork: (a) a frozen LIVE "
|
|
"crash-replay test that starts the real rune run serve process, "
|
|
"submits a multi-step irreversible task over the live /v1 surface, "
|
|
"SIGKILLs the process mid-task, restarts it against the same "
|
|
"continuity store, and proves the in-flight task resumes with every "
|
|
"irreversible effect executed exactly once (no duplicates across "
|
|
"generations) and the gap status explicit; (b) the plan document "
|
|
"store (durable, atomic temp+fsync+rename, append-only revisions) "
|
|
"wired to the serve surface as /v1/plans create/fetch/revise, "
|
|
"proven by a frozen round-trip test (write, restart the runtime, "
|
|
"recall byte-identical) plus serve-surface conformance; red-first"
|
|
)
|
|
AFFECTED = [
|
|
"src/go/rune-entry/internal/entry/runtime_serve.go",
|
|
"src/go/rune-entry/internal/entry/plan_store.go",
|
|
"src/go/rune-entry/internal/entry/plan_store_test.go",
|
|
"src/go/rune-entry/internal/entry/runtime_live_test.go",
|
|
"scripts/admit_wave_k25_continuous_depth.py",
|
|
]
|
|
|
|
|
|
def run_gate() -> str:
|
|
"""The admission-time gate: BEFORE mint (the research-first law).
|
|
Returns the marker line; raises SystemExit(1) on REFUSED."""
|
|
cmd = [sys.executable, "scripts/check_research_gate.py", "admit",
|
|
"--slug", SLUG, "--objective", OBJECTIVE]
|
|
r = subprocess.run(cmd, cwd=ROOT, capture_output=True, text=True)
|
|
print(r.stdout, end="")
|
|
if r.stderr:
|
|
print(r.stderr, end="", file=sys.stderr)
|
|
if r.returncode != 0:
|
|
print("research gate REFUSED — contract not minted")
|
|
raise SystemExit(1)
|
|
markers = [line for line in r.stdout.splitlines()
|
|
if line.startswith(("exempt:research-gate:",
|
|
"research-gate:ALLOW"))]
|
|
if not markers:
|
|
print("research gate allowed but printed no marker — refusing to "
|
|
"mint without a recordable chain marker")
|
|
raise SystemExit(1)
|
|
return markers[0]
|
|
|
|
|
|
def main() -> int:
|
|
marker = run_gate()
|
|
|
|
store = os.path.join(ROOT, "store", "scaffold")
|
|
scaffold = sc.Scaffold(store, "rune")
|
|
|
|
md = cmode.classify_mode(
|
|
OBJECTIVE,
|
|
target_project="rune",
|
|
project_exists=True,
|
|
affected_surface=AFFECTED,
|
|
)
|
|
print("classified mode:", md.mode)
|
|
|
|
need = {
|
|
"need_id": "need-wave-K25-continuous-depth",
|
|
"objective": OBJECTIVE,
|
|
"origin": "worker",
|
|
"project": "rune",
|
|
"task_ref": SLUG,
|
|
"affected_surface": AFFECTED,
|
|
"evidence_refs": [
|
|
marker,
|
|
"docs/openspec/changes/add-native-rune-tui/specs/rune-runtime/spec.md",
|
|
"docs/openspec/changes/add-native-rune-tui/tasks.md",
|
|
"src/go/rune-entry/internal/entry/runtime.go",
|
|
"src/go/rune-entry/internal/entry/runtime_serve.go",
|
|
],
|
|
}
|
|
act = cact.activate(md, need=need, scaffold=scaffold,
|
|
builder=SLUG)
|
|
print("activated:", act.get("activated"), act.get("mode"))
|
|
|
|
env = cadm.admit(
|
|
act,
|
|
objective=OBJECTIVE,
|
|
builder=SLUG,
|
|
affected_surface=AFFECTED,
|
|
evidence_refs=need["evidence_refs"],
|
|
origin="worker",
|
|
task_ref=SLUG,
|
|
expected_new_entities=[
|
|
"src/go/rune-entry/internal/entry/plan_store.go",
|
|
"src/go/rune-entry/internal/entry/plan_store_test.go",
|
|
"src/go/rune-entry/internal/entry/runtime_live_test.go",
|
|
],
|
|
expected_runtime_effects=[
|
|
"the real rune run serve process survives SIGKILL mid-task and the restart resumes the in-flight task",
|
|
"irreversible effects execute exactly once across generations (no duplicate dispatch)",
|
|
"crash recovery reports explicit gap status on the live serve surface",
|
|
"plan documents are durable under home/plans with atomic writes and append-only revisions",
|
|
"the /v1/plans serve surface creates, fetches, and revises plan documents",
|
|
],
|
|
verification_obligations=[
|
|
"go test ./internal/entry/ -run 'TestLiveCrashReplay|TestPlanStore' green (red-first: both RED before implementation)",
|
|
"go test ./internal/entry/ full package green (no regressions)",
|
|
],
|
|
approval_ref="user:wave-K25-continuous-depth dispatch",
|
|
contract_id="ADMIT-wave-K25-continuous-depth",
|
|
project_store=store,
|
|
project_id="rune",
|
|
)
|
|
print(json.dumps(env, indent=2, default=str)[:2400])
|
|
return 0 if env.get("success") else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|