Full walk draft→approved→building→verifying→closed in one process (builder factory-heavy-te-life); observed_evidence carries the battery/ parity/build gates; divergences documented per the oracle-stays-contract law.
139 lines
6.1 KiB
Python
139 lines
6.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Close the #2479 tool_executor lifecycle-family gap contract (GO port).
|
|
Full lifecycle walk in ONE process (shared-store clobber law). Builder:
|
|
factory-heavy-te-life. Carries the pushed parity SHA ca90bd99.
|
|
|
|
Usage: close_contract_tool_executor_lifecycle.py [contract_id]
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
os.environ.setdefault(
|
|
"CS_RUST_LIB",
|
|
"/mnt/workdrive/rune/src/rust/capability_scoring/target/release/libcapability_scoring.so",
|
|
)
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
|
|
from rune.construction_interface import ConstructionInterface
|
|
|
|
PARITY_SHA = "ca90bd99"
|
|
EVIDENCE = f"parity {PARITY_SHA}"
|
|
|
|
NEED = (
|
|
"tool_executor lifecycle-family dichotomy gap-close (GO): "
|
|
"name-preserving port of the six audit-missing functions "
|
|
"(_execute_tool_now, serialize_prepared_tool, "
|
|
"deserialize_prepared_tool, execute_tool with the prepare_tool "
|
|
"kernel body, confirm_write, _find_capability) into "
|
|
"src/go/tool-executor/gaps_lifecycle.go (20-arm dispatch with the "
|
|
"Unknown-tool refusal and str(e)-law TypeError envelopes — no type "
|
|
"prefix inside handler 'Read failed:' arms, present-but-null vs "
|
|
"absent args.get distinction, integral-float JSON ints vs fractional "
|
|
"slice-indices crashes; asdict-shape 9-field SerializePreparedTool "
|
|
"with nil optionals; DeserializePreparedTool exact validation ladder "
|
|
"with the six oracle error messages; PrepareTool with read-only "
|
|
"passthrough, preview verdicts, operation+path digest binding, "
|
|
"now-pinning; ConfirmWrite via ApplyContent; FindCapability over an "
|
|
"injectable broker seam with pyRepr quoting and ordered-args "
|
|
"rendering), frozen-truth battery truth_lifecycle.json (52 rows via "
|
|
"scripts/gen_tool_executor_lifecycle_truth.py against the LIVE "
|
|
"oracle, hermetic {{TMP}}/{{WROOT}}/{{HOME}}/{{TOKEN}}/{{DIGEST}} "
|
|
"placeholders, byte-identical regeneration verified twice) embedded "
|
|
"in truth_lifecycle_test.go TestLifecycleTruth 52/52 + divergence "
|
|
"sentinels; live parity scripts/check_tool_executor_lifecycle_parity."
|
|
"py 49/49 (per-side isolated fixture roots so neither side inherits "
|
|
"the other's side effects); gofmt/vet/go build/go test -count=1 "
|
|
"clean; Python suite green both pins (no loader seam — vacuous pin, "
|
|
"tiered_executor precedent). Repairs en route: write-denial message "
|
|
"carries Python str(list) bytes (pyListRepr, paths.go); ReadFile "
|
|
"numbers with the RAW offset (offset=0 renders '0: line 1' — the "
|
|
"old clamp rewrote footer/numbering, fileops.go). Sibling-gap arms "
|
|
"(edit_file, glob_files, repo_map, run_command, read_persona, "
|
|
"query_memory, check_growth, diagnose_behavior) pinned as notPorted "
|
|
"sentinels — documented divergences that flip when their family "
|
|
"lanes land (verification/te-life-summary.md). Audit fn-level "
|
|
"33/47 → 39/47 (83%, FULL threshold). Delivered on gitea/master: "
|
|
"feat " + PARITY_SHA + "."
|
|
)
|
|
|
|
iface = ConstructionInterface(builder="factory-heavy-te-life")
|
|
|
|
if len(sys.argv) > 1:
|
|
cid = sys.argv[1]
|
|
print("resuming contract:", cid)
|
|
else:
|
|
r = iface.submit_need(NEED, origin="builder")
|
|
print("submit_need:", json.dumps(r)[:300])
|
|
if not r.get("success"):
|
|
print("NEED FAILED — aborting")
|
|
sys.exit(1)
|
|
cid = r["ids"]["contract_id"]
|
|
print("contract_id:", cid)
|
|
|
|
|
|
def phase_of(cid):
|
|
doc = iface.scaffold.load()
|
|
e = iface.scaffold.contract(doc, cid)
|
|
return e.get("phase") if e else "MISSING"
|
|
|
|
|
|
phase = phase_of(cid)
|
|
print("current phase:", phase)
|
|
for want in ("approved", "building", "verifying"):
|
|
if phase == want:
|
|
break
|
|
t = iface.transition(cid, want, evidence_ref=EVIDENCE)
|
|
ok = t.get("success")
|
|
print(f"transition->{want}:", "ok" if ok else json.dumps(t)[:300])
|
|
if not ok:
|
|
sys.exit(1)
|
|
phase = want
|
|
|
|
c = iface.close(
|
|
cid,
|
|
observed_evidence=[{
|
|
"kind": "port_evidence",
|
|
"detail": "tool_executor lifecycle-family completion — parity "
|
|
f"{PARITY_SHA} feat(tool-executor): lifecycle family "
|
|
"gap-close; pushed gitea/master. Go port at "
|
|
"src/go/tool-executor/gaps_lifecycle.go closes the six "
|
|
"audit gaps name-preserving (ExecuteToolNow 20-arm "
|
|
"dispatch + crash envelopes, SerializePreparedTool, "
|
|
"DeserializePreparedTool validation ladder, ExecuteTool/"
|
|
"PrepareTool approval previews with digest binding, "
|
|
"ConfirmWrite, FindCapability broker seam). Freeze: "
|
|
"scripts/gen_tool_executor_lifecycle_truth.py — 52-row "
|
|
"truth regenerates byte-identical (verified twice); "
|
|
"battery TestLifecycleTruth 52/52; live parity "
|
|
"scripts/check_tool_executor_lifecycle_parity.py 49/49; "
|
|
"gofmt/vet/go build clean; Python both pins 122 passed "
|
|
"(CS_RUST_LIB law honored; memory_store _py_norm_key "
|
|
"RecursionError pre-exists in HEAD, verified "
|
|
"independently). Audit 33/47 → 39/47 (83% FULL "
|
|
"threshold). Divergences documented in "
|
|
"verification/te-life-summary.md: sibling-gap notPorted "
|
|
"arms, bool-offset footer rendering, non-string "
|
|
"optional fields, unreachable constructor-TypeError "
|
|
"branch, {{DIGEST}} structural invariant, grep_files "
|
|
"hit formatting (pre-existing _search_files-shaped "
|
|
"kernel).",
|
|
}],
|
|
scope_files=[
|
|
"src/go/tool-executor/gaps_lifecycle.go",
|
|
"src/go/tool-executor/truth_lifecycle.json",
|
|
"src/go/tool-executor/truth_lifecycle_test.go",
|
|
"src/go/tool-executor/paths.go",
|
|
"src/go/tool-executor/fileops.go",
|
|
"scripts/gen_tool_executor_lifecycle_truth.py",
|
|
"scripts/check_tool_executor_lifecycle_parity.py",
|
|
"verification/te-life-summary.md",
|
|
],
|
|
)
|
|
print("close:", json.dumps(c)[:400])
|
|
if not c.get("success"):
|
|
sys.exit(1)
|
|
print("CLOSED", cid)
|