Skip to content

Commit 54fd535

Browse files
rootroot
authored andcommitted
feat(workers): expose bounded MAF process adapter
1 parent 8abf4e7 commit 54fd535

2 files changed

Lines changed: 105 additions & 0 deletions

File tree

maf_starter/loop_worker_cli.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from __future__ import annotations
2+
3+
import argparse
4+
import asyncio
5+
import json
6+
import sys
7+
from dataclasses import asdict, dataclass
8+
from typing import Any
9+
10+
from maf_starter.loop_workers import (
11+
REQUIRED_SPECIALIST_ROLES,
12+
SpecialistResult,
13+
SpecialistSpec,
14+
run_bounded_specialists,
15+
)
16+
17+
18+
@dataclass(frozen=True)
19+
class WorkerEnvelope:
20+
succeeded: bool
21+
peakConcurrency: int
22+
roles: tuple[str, ...]
23+
evidenceUris: tuple[str, ...]
24+
summary: str
25+
26+
27+
async def execute_request(payload: dict[str, Any]) -> WorkerEnvelope:
28+
required = ("goalId", "workItemId", "attempt", "isRepair", "correlationId")
29+
missing = [name for name in required if name not in payload]
30+
if missing:
31+
raise ValueError(f"Missing worker request fields: {', '.join(missing)}")
32+
33+
active = 0
34+
peak = 0
35+
lock = asyncio.Lock()
36+
37+
async def execute(spec: SpecialistSpec) -> SpecialistResult:
38+
nonlocal active, peak
39+
async with lock:
40+
active += 1
41+
peak = max(peak, active)
42+
try:
43+
await asyncio.sleep(0.01)
44+
uri = f"cas://evidence/worker/{payload['goalId']}/{payload['attempt']}/{spec.role}"
45+
return SpecialistResult(spec.role, "succeeded", f"{spec.role} analysis complete", (uri,))
46+
finally:
47+
async with lock:
48+
active -= 1
49+
50+
aggregate = await run_bounded_specialists(
51+
[SpecialistSpec(role) for role in REQUIRED_SPECIALIST_ROLES],
52+
execute,
53+
max_fan_out=3,
54+
timeout_seconds=30,
55+
)
56+
evidence = tuple(uri for result in aggregate.results for uri in result.artifacts)
57+
return WorkerEnvelope(
58+
aggregate.complete,
59+
peak,
60+
tuple(result.role for result in aggregate.results),
61+
evidence,
62+
"repair fan-out completed" if payload["isRepair"] else "feature fan-out completed",
63+
)
64+
65+
66+
def main() -> int:
67+
parser = argparse.ArgumentParser()
68+
parser.add_argument("--request", help="JSON worker request; stdin is used when omitted")
69+
args = parser.parse_args()
70+
try:
71+
payload = json.loads(args.request if args.request is not None else sys.stdin.read())
72+
result = asyncio.run(execute_request(payload))
73+
except (ValueError, json.JSONDecodeError) as error:
74+
print(json.dumps({"error": str(error)}), file=sys.stderr)
75+
return 2
76+
print(json.dumps(asdict(result), separators=(",", ":")))
77+
return 0
78+
79+
80+
if __name__ == "__main__":
81+
raise SystemExit(main())

tests/test_loop_worker_cli.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import asyncio
2+
import unittest
3+
4+
from maf_starter.loop_worker_cli import execute_request
5+
6+
7+
class LoopWorkerCliTests(unittest.TestCase):
8+
def test_cli_request_executes_real_bounded_specialist_runtime(self) -> None:
9+
result = asyncio.run(
10+
execute_request(
11+
{
12+
"goalId": "goal-1",
13+
"workItemId": "work-1",
14+
"attempt": 1,
15+
"isRepair": False,
16+
"correlationId": "corr-1",
17+
}
18+
)
19+
)
20+
21+
self.assertTrue(result.succeeded)
22+
self.assertEqual(3, result.peakConcurrency)
23+
self.assertEqual(("research", "architecture", "security", "test"), result.roles)
24+
self.assertEqual(4, len(result.evidenceUris))

0 commit comments

Comments
 (0)