Harden RF handoff and stream OTA decode

This commit is contained in:
LittleSam129
2026-09-22 17:43:58 +03:00
parent 168e03d9e7
commit a94f2db4ee
17 changed files with 1548 additions and 497 deletions

View File

@@ -37,9 +37,13 @@ from tools.tx_handoff_channel import ( # noqa: E402
CHANNEL_COMPLETE_OBSERVED,
CHANNEL_READY_OBSERVED,
RX_READY_OBSERVED,
TX_AUTHORIZATION_CREATED,
TX_ACK_SCHEMA_VERSION,
TX_AUTHORIZED,
TX_COMPLETE,
TX_STARTED,
GitAcknowledgementChannel,
TxHandoffAcknowledgement,
load_acknowledgement,
)
@@ -445,12 +449,12 @@ def acknowledgement_for_result(
elif status == "RED_APPROVAL_BLOCKED":
acknowledgement_state = RX_READY_OBSERVED
elif status == "TX_AUTHORIZATION_PREPARED":
acknowledgement_state = TX_AUTHORIZATION_CREATED
acknowledgement_state = TX_AUTHORIZED
rf_tx_authorized = True
if acknowledgement_state is None:
return None
return TxHandoffAcknowledgement(
schema_version=1,
schema_version=TX_ACK_SCHEMA_VERSION,
task_id=result.task_id,
state=acknowledgement_state,
source_rx_commit=result_head,
@@ -461,6 +465,7 @@ def acknowledgement_for_result(
rf_tx_authorized=rf_tx_authorized,
rf_tx_started=False,
rf_tx=0,
tx_task_id=(EXPECTED_TX_TASK_ID if rf_tx_authorized else None),
)
@@ -536,6 +541,42 @@ def process_history_cycle(
def run_watcher(arguments: argparse.Namespace) -> int:
state_path = arguments.state_file.resolve()
if arguments.publish_tx_event is not None:
if arguments.dry_run:
raise ValueError("--publish-tx-event cannot be combined with --dry-run")
repository = arguments.repository.resolve()
event = load_acknowledgement(arguments.publish_tx_event.resolve())
if event.state not in {TX_STARTED, TX_COMPLETE}:
raise ValueError("published execution event has the wrong state")
branch = _git_output(repository, ["branch", "--show-current"])
if branch != arguments.source_branch:
raise ValueError("TX event publisher is on the wrong source branch")
if _git_output(repository, ["status", "--porcelain", "--untracked-files=no"]):
raise ValueError("tracked worktree must be clean before TX event publication")
_git_output(
repository,
["fetch", "--quiet", arguments.remote, arguments.source_branch],
)
head = _git_output(repository, ["rev-parse", "HEAD"])
remote_head = _git_output(
repository,
["rev-parse", f"{arguments.remote}/{arguments.source_branch}"],
)
if head != remote_head:
raise ValueError("current HEAD disagrees with remote source branch")
if event.source_head != head:
raise ValueError("TX event SOURCE_HEAD disagrees with current HEAD")
publisher = GitAcknowledgementChannel(
repository,
remote=arguments.remote,
branch=arguments.acknowledgement_branch,
)
outcome = publisher.publish_execution_event(event)
print(f"TX EVENT PUBLISH = {outcome.status}")
print(f"TX EVENT STATE = {event.state}")
print(f"TX EVENT HEAD = {outcome.commit}")
print(f"TX EVENT REMOTE HEAD = {outcome.remote_head}")
return 0
if arguments.request_stop:
stopped = request_stop(state_path, arguments.stop_timeout)
print("TX WATCHER STOPPED" if stopped else "TX WATCHER STOP TIMEOUT")
@@ -664,6 +705,7 @@ def build_parser() -> argparse.ArgumentParser:
parser.add_argument("--once", action="store_true")
parser.add_argument("--dry-run", action="store_true")
parser.add_argument("--result-file", type=Path)
parser.add_argument("--publish-tx-event", type=Path)
parser.add_argument("--approval", choices=("authorize", "deny"))
parser.add_argument("--request-stop", action="store_true")
parser.add_argument("--stop-timeout", type=float, default=15.0)