Name-preserving port of the 12 audit-missing lifecycle fns into src/go/operator-deep/gaps_lifecycle.go (family lane factory-heavy-ro-life): GetConversationWindow, TasksToDictList (list_tasks x2), RoutingProfilesPath, ConstructionStorePath, ConstructionNoteDoc, the _construction_activation glue (SplitScaffoldOverride/DeriveConstructionTarget/observation rows), InitConversationFiles+MigrateLegacyTasks, LoadOperatorState, SaveOperatorStateOrd (ordered Python json.dump byte-parity writer), ClearPendingApproval, TerminalizeExecutionFailure, EmitTaskOutcomePayload, EmitTaskFailedPayload. CLI dispatch via the 'lifecycle' subcommand. Truth: truth_lifecycle.json 37 rows frozen under scripts/olc_freeze_seams (pinned clock, deterministic uuid counter, fixed scratch, cone cores, event_bus recorder) — freeze_truth --verify byte-identical x3. Battery replays verbatim (ordered parse; save rows byte-compare). Live parity 35/35 (scripts/check_operator_lifecycle_parity.py) incl. env-unset derive branches. gofmt/vet/build/test green; Python 65x2 both pins. Dichotomy audit rune_operator 29/68 -> 42/68 (family complete; remaining fns are sibling lanes). Divergences documented in verification/olc-summary.md (segments-store evidence sort, migration msg-id placeholders, checkpoint-window input, classifier-as-input seams).
266 lines
11 KiB
Python
266 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""gen_operator_lifecycle_truth.py — shared-harness truth battery for the
|
|
rune_operator TASK-LIFECYCLE/STATE family gap closure (#2479, family lane
|
|
factory-heavy-ro-life).
|
|
|
|
Uses scripts/freeze_truth.py (the ONE truth law) + the
|
|
scripts/olc_freeze_seams rig (clock/ids/cores pinned, fixed-path scratch)
|
|
to freeze src/rune/rune_operator.py behavior for the Go port at
|
|
src/go/operator-deep (new family file gaps_lifecycle.go):
|
|
|
|
* get_conversation_window (module fn) / list_tasks (method + module fn)
|
|
* _routing_profiles_path / _construction_store / _construction_note
|
|
* _construction_activation (override regex, target derivation,
|
|
DISCUSSION meaning-gate observation, activation observation)
|
|
* _init_conversation_state (legacy operator.json migration report)
|
|
* _load (defaults / unknown-key filtering / corrupt-file degrade)
|
|
* _save (Python json.dump indent=2 file bytes)
|
|
* _clear_pending_approval (state triple-clear)
|
|
* _terminalize_execution_failure (task+canonical transition+envelope+emit)
|
|
* _emit_task_outcome / _emit_task_failed (journal payload contract)
|
|
|
|
The olc_* seams live in the rig (bound onto the oracle module); every
|
|
case drives the REAL oracle function on hermetic scratch state. The
|
|
clock is pinned process-wide (freeze_rigs pin_clock), uuid minting is a
|
|
deterministic per-call counter, and every emitted id/ts is therefore
|
|
byte-identical across processes. event_bus is swapped for an in-memory
|
|
recorder by the emit seams (journal transport = event_bus's own port
|
|
surface, src/go/event-bus).
|
|
|
|
Verify (byte-identical law):
|
|
PYTHONPATH=scripts/olc_freeze_seams:src python3 scripts/freeze_truth.py \
|
|
--verify src/go/operator-deep/truth_lifecycle.json \
|
|
--module rune.rune_operator
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parent.parent
|
|
|
|
FROZEN_NOW = "2026-10-14T22:40:00.123456+00:00"
|
|
|
|
_TASK_A = {
|
|
"task_id": "task_alpha",
|
|
"description": "fix the parser crash",
|
|
"status": "completed",
|
|
"assigned_model": "qwen3:14b",
|
|
"result": "replaced the regex and tests pass",
|
|
"created_at": "2026-10-14T19:00:00.000000+00:00",
|
|
"completed_at": "2026-10-14T19:05:00.000000+00:00",
|
|
"route": "LOCAL_FIX",
|
|
"route_instruction": "ROUTE LOCAL_FIX: do the edit.",
|
|
}
|
|
_TASK_B = {
|
|
"task_id": "task_beta",
|
|
"description": "research storage engines",
|
|
"status": "pending",
|
|
"assigned_model": None,
|
|
"result": None,
|
|
"created_at": "2026-10-14T19:10:00.000000+00:00",
|
|
"completed_at": None,
|
|
"route": "",
|
|
"route_instruction": "",
|
|
}
|
|
|
|
_STATE_RICH = {
|
|
"identity": "Rune",
|
|
"role": "Operator",
|
|
"current_task": "task_beta",
|
|
"active_model": "qwen3:14b",
|
|
"tasks": [_TASK_A, _TASK_B],
|
|
"pending_task_id": "task_beta",
|
|
"pending_request": {"name": "run_command", "args": ["make"]},
|
|
"pending_runtime_state": {"exposed_tools": ["read_file"]},
|
|
}
|
|
_STATE_DEFAULT = {
|
|
"identity": "Rune",
|
|
"role": "Operator",
|
|
"current_task": None,
|
|
"active_model": None,
|
|
"tasks": [],
|
|
"pending_task_id": None,
|
|
"pending_request": None,
|
|
"pending_runtime_state": None,
|
|
}
|
|
|
|
_MSGS = [
|
|
{"msg_id": "msg_1", "ts": "2026-10-14T19:00:01.000000+00:00",
|
|
"role": "user", "content": "first turn", "channel_id": "operator",
|
|
"task_id": "task_alpha", "token_estimate": 2},
|
|
{"msg_id": "msg_2", "ts": "2026-10-14T19:00:02.000000+00:00",
|
|
"role": "assistant", "content": "first reply", "channel_id": "operator",
|
|
"task_id": "task_alpha", "token_estimate": 2},
|
|
{"msg_id": "msg_3", "ts": "2026-10-14T19:00:03.000000+00:00",
|
|
"role": "user", "content": "second turn", "channel_id": "operator",
|
|
"task_id": "task_alpha", "token_estimate": 2},
|
|
{"msg_id": "msg_4", "ts": "2026-10-14T19:00:04.000000+00:00",
|
|
"role": "user", "content": "other channel", "channel_id": "voice",
|
|
"task_id": None, "token_estimate": 2},
|
|
]
|
|
|
|
_FIXTURE_FULL = """{
|
|
"identity": "Rune",
|
|
"role": "Operator",
|
|
"current_task": "task_alpha",
|
|
"active_model": "qwen3:14b",
|
|
"tasks": [
|
|
{
|
|
"task_id": "task_alpha",
|
|
"description": "fix the parser crash",
|
|
"status": "completed",
|
|
"assigned_model": "qwen3:14b",
|
|
"result": "replaced the regex and tests pass",
|
|
"created_at": "2026-10-14T19:00:00.000000+00:00",
|
|
"completed_at": "2026-10-14T19:05:00.000000+00:00",
|
|
"route": "LOCAL_FIX",
|
|
"route_instruction": "ROUTE LOCAL_FIX: do the edit."
|
|
},
|
|
{
|
|
"task_id": "task_beta",
|
|
"description": "research storage engines",
|
|
"status": "pending",
|
|
"assigned_model": null,
|
|
"result": null,
|
|
"created_at": "2026-10-14T19:10:00.000000+00:00",
|
|
"completed_at": null,
|
|
"route": "",
|
|
"route_instruction": ""
|
|
},
|
|
{
|
|
"task_id": "task_unknown_keys",
|
|
"description": "legacy row with extra keys",
|
|
"status": "running",
|
|
"future_field": "dropped by the dataclass-fields filter"
|
|
}
|
|
],
|
|
"pending_task_id": null,
|
|
"pending_request": null,
|
|
"pending_runtime_state": null
|
|
}
|
|
"""
|
|
_FIXTURE_EMPTY = "{}\n"
|
|
_FIXTURE_CORRUPT = "{not json at all"
|
|
|
|
_LONG_NOTE = "n" * 299 + "tail-overflow"
|
|
|
|
_VERIF_PASS = {"verification_id": "vr_task_alpha", "passed": True}
|
|
|
|
|
|
def main():
|
|
cases = [
|
|
# -- _routing_profiles_path (env branch; derive branch covered by
|
|
# the live parity sweep -- repo anchor is machine-specific).
|
|
# Seam str()s the PosixPath the oracle returns.
|
|
("olc_routing_profiles_path", (), {}),
|
|
# -- _construction_store (env branch, same law)
|
|
{"fn": "RuneOperator._construction_store",
|
|
"recv": {"cls": "RuneOperator"}, "args": [], "kwargs": {}},
|
|
# -- _clear_pending_approval: full triple-clear on a loaded state
|
|
{"fn": "RuneOperator._clear_pending_approval",
|
|
"recv": {"cls": "RuneOperator", "state": dict(_STATE_RICH)},
|
|
"args": [], "kwargs": {}},
|
|
# -- list_tasks (method): to_dict projection, None fields ride
|
|
{"fn": "RuneOperator.list_tasks",
|
|
"recv": {"cls": "RuneOperator", "state": dict(_STATE_RICH)},
|
|
"args": [], "kwargs": {}},
|
|
{"fn": "RuneOperator.list_tasks",
|
|
"recv": {"cls": "RuneOperator", "state": dict(_STATE_DEFAULT)},
|
|
"args": [], "kwargs": {}},
|
|
# -- list_tasks (module fn) via the _operator global
|
|
("olc_module_list_tasks", (dict(_STATE_RICH),), {}),
|
|
("olc_module_list_tasks", (dict(_STATE_DEFAULT),), {}),
|
|
# -- get_conversation_window (module fn): channel bucket, n clip,
|
|
# n<=0 -> empty, n beyond bucket
|
|
("olc_module_get_conversation_window", ([dict(m) for m in _MSGS],),
|
|
{"channel": "operator", "n": 2}),
|
|
("olc_module_get_conversation_window", ([dict(m) for m in _MSGS],),
|
|
{"channel": "operator", "n": 0}),
|
|
("olc_module_get_conversation_window", ([dict(m) for m in _MSGS],),
|
|
{"channel": "operator", "n": 8}),
|
|
("olc_module_get_conversation_window", ([dict(m) for m in _MSGS],),
|
|
{"channel": "voice", "n": 3}),
|
|
("olc_module_get_conversation_window", ([],),
|
|
{"channel": "operator", "n": 8}),
|
|
# -- _emit_task_outcome: completed+verification, failed bare,
|
|
# truncation [:200], route passthrough
|
|
("olc_emit_task_outcome", (dict(_TASK_A),),
|
|
{"channel": "operator", "verification": _VERIF_PASS, "route": "LOCAL_FIX"}),
|
|
("olc_emit_task_outcome", (dict(_TASK_A, status="failed", result="boom"),),
|
|
{"channel": ""}),
|
|
("olc_emit_task_outcome",
|
|
(dict(_TASK_A, description="d" * 250, result="r" * 250,
|
|
assigned_model=None),),
|
|
{"channel": "operator"}),
|
|
# -- _emit_task_failed: error truncation [:300], model None
|
|
("olc_emit_task_failed", (dict(_TASK_A, status="failed", result="e" * 350),),
|
|
{"channel": "operator"}),
|
|
("olc_emit_task_failed",
|
|
(dict(_TASK_B, status="failed", result="short failure", assigned_model=None),),
|
|
{"channel": ""}),
|
|
# -- _save: file bytes (Python json.dump indent=2 shape)
|
|
("olc_save", (dict(_STATE_RICH),), {}),
|
|
("olc_save", (dict(_STATE_DEFAULT),), {}),
|
|
# -- _load: full fixture / empty dict defaults / unknown-key
|
|
# filtering rides _FIXTURE_FULL / corrupt JSON degrades to the
|
|
# fresh default state (logged, not silent)
|
|
("olc_load", (_FIXTURE_FULL,), {}),
|
|
("olc_load", (_FIXTURE_EMPTY,), {}),
|
|
("olc_load", (_FIXTURE_CORRUPT,), {}),
|
|
# -- _init_conversation_state: no operator.json / two-task
|
|
# migration with current_task restore / idempotent rerun /
|
|
# unknown-status degrade (report None)
|
|
("olc_init_conv_state", (None,), {}),
|
|
("olc_init_conv_state", (_FIXTURE_FULL,), {}),
|
|
("olc_init_conv_state", (_FIXTURE_FULL,), {"rerun": True}),
|
|
("olc_init_conv_state",
|
|
('{"tasks": [{"task_id": "task_bad", "status": "weird"}]}',), {}),
|
|
# -- _construction_note: append + [:300] truncation
|
|
("olc_construction_note", ("activated LOCAL_CHANGE for the parser",), {}),
|
|
("olc_construction_note", (_LONG_NOTE,), {}),
|
|
# -- _construction_activation: override marker / DISCUSSION
|
|
# meaning-gate / rune target / standalone target / existing
|
|
# target / unknown target
|
|
("olc_construction_activation",
|
|
("/scaffold-mode LOCAL_CHANGE build the parser fix", "t_ovr"),
|
|
{"channel": "operator"}),
|
|
("olc_construction_activation",
|
|
("what do you think about the storage design?", "t_disc"),
|
|
{"channel": "operator"}),
|
|
("olc_construction_activation",
|
|
("fix the rune operator bug", "t_rune"),
|
|
{"channel": "operator"}),
|
|
("olc_construction_activation",
|
|
("build the standalone timer utility", "t_new"),
|
|
{"channel": "operator"}),
|
|
("olc_construction_activation",
|
|
("change the existing project config", "t_exist"),
|
|
{"channel": "operator"}),
|
|
("olc_construction_activation",
|
|
("do the thing", "t_unk"),
|
|
{"channel": "operator"}),
|
|
# -- _terminalize_execution_failure: defaults + explicit error +
|
|
# long result text
|
|
("olc_terminalize",
|
|
(dict(_TASK_B, status="running"), "outcome-ref-1", "research dispatch failed"),
|
|
{"channel": "operator", "model": "qwen3:14b", "error": None}),
|
|
("olc_terminalize",
|
|
(dict(_TASK_B, status="running"), "outcome-ref-2", "explode"),
|
|
{"channel": "", "model": "", "error": "ValueError: bad input"}),
|
|
("olc_terminalize",
|
|
(dict(_TASK_B, status="running"), "outcome-ref-3", "x" * 350),
|
|
{"channel": "operator", "model": "", "error": None}),
|
|
]
|
|
dest = REPO / "src/go/operator-deep/truth_lifecycle.json"
|
|
sys.path.insert(0, str(REPO / "scripts"))
|
|
sys.path.insert(0, str(REPO / "src"))
|
|
from freeze_truth import freeze, write
|
|
|
|
truth = freeze("rune.rune_operator", cases, oracle_module="rune.rune_operator")
|
|
write(truth, dest)
|
|
print(f"wrote {len(truth)} cases -> {dest}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|