75 lines
2.4 KiB
Python
75 lines
2.4 KiB
Python
"""Detached software-only worker for one fixed STAIRCASE_SEARCH task."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from tools.rf001_http_control import PROTOCOL_VERSION, STAIRCASE_SEARCH_TASK, utc_now
|
|
from tools.rf001_rx_http_agent import run_staircase_search
|
|
|
|
|
|
def _atomic_write(path: Path, value: dict[str, object]) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
temporary = path.with_suffix(path.suffix + ".tmp")
|
|
temporary.write_text(
|
|
json.dumps(value, ensure_ascii=False, separators=(",", ":"), sort_keys=True)
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
os.replace(temporary, path)
|
|
|
|
|
|
def run_job(spec_path: Path, result_path: Path) -> dict[str, object]:
|
|
spec = json.loads(spec_path.read_text(encoding="utf-8-sig"))
|
|
if not isinstance(spec, dict):
|
|
raise ValueError("job spec must be a JSON object")
|
|
task = spec.get("task")
|
|
if not isinstance(task, dict) or task.get("kind") != STAIRCASE_SEARCH_TASK:
|
|
raise ValueError("job spec does not contain STAIRCASE_SEARCH")
|
|
started_at = utc_now()
|
|
task_result, errors = run_staircase_search(
|
|
Path(str(spec["work_root"])),
|
|
str(task["session_id"]),
|
|
str(task["expected_rx_sha256"]),
|
|
str(task["expected_reference_sha256"]),
|
|
progress_path=Path(str(spec["progress_path"])),
|
|
)
|
|
result = {
|
|
"protocol_version": PROTOCOL_VERSION,
|
|
"task_id": str(task["task_id"]),
|
|
"agent_id": str(spec["agent_id"]),
|
|
"status": "COMPLETE" if not errors else "FAILED",
|
|
"started_at": started_at,
|
|
"finished_at": utc_now(),
|
|
"result": task_result,
|
|
"errors": errors,
|
|
"rf_tx": 0,
|
|
}
|
|
_atomic_write(result_path, result)
|
|
return result
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--job-spec", required=True, type=Path)
|
|
parser.add_argument("--result", required=True, type=Path)
|
|
arguments = parser.parse_args()
|
|
result = run_job(arguments.job_spec, arguments.result)
|
|
print(f"TASK ID = {result['task_id']}")
|
|
print(f"TASK STATUS = {result['status']}")
|
|
print("HARDWARE ACCESSED = false")
|
|
print("RF TX = 0")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|