fix(issue-6): fail-closed registry timeout and TUI turn handshake
- Introduce finalize_unfinished in multi-agent-mux-delegate-job for fail-closed atomic transitions - Enforce CAS dispatch_token and attempt_id pinning across engine, CLI, and lifecycle scripts - Integrate Herdr wait_for_agent_idle turn handshake to prevent prompt loss and race conditions - Resolve bash 3.2 set -u empty array expansion compatibility in lib.sh - Preserve Issue #5 R2 contract in CAS transition engine (engine.py, publish_event.py, service.py) - Add comprehensive regression suites (test_issue6_fail_closed.py, test_issue6_turn_handshake.py) - Bump lockstep framework and skills to v4.4.1 across lib.sh, eager.py, VERSIONS.md, 8 SKILL.md - Synchronize documentation (IMPROVEMENTS.md, MESSAGING.md, state-transitions.md, task.md, phase5-e2e.md) - Unanimous PASS achieved across 4 reviewer team leaders (Claude, Codex, OpenCode, Grok) Closes #6
This commit is contained in:
1 parent
7b761be7b8
commit
ec61511699
51 files changed
+3477
-293
No files matched your search
@@ -59,10 +59,14 @@ class WaitOutcome(object):
|
||||
|
||||
|
||||
def build_argv(target: str, until: Sequence[str] = DEFAULT_UNTIL,
|
||||
timeout_ms: Optional[int] = None) -> list:
|
||||
timeout_ms: Optional[int] = None,
|
||||
session: Optional[str] = None) -> list:
|
||||
if not target:
|
||||
raise ValueError("wait target is required")
|
||||
argv = ["herdr", "agent", "wait", target]
|
||||
if session and session != "default":
|
||||
argv = ["herdr", "--session", session, "agent", "wait", target]
|
||||
else:
|
||||
argv = ["herdr", "agent", "wait", target]
|
||||
for state in until:
|
||||
if state not in VALID_STATES:
|
||||
raise ValueError("unsupported --until state: {!r}".format(state))
|
||||
@@ -83,9 +87,10 @@ def _parse(stream: str) -> Optional[Dict[str, Any]]:
|
||||
|
||||
|
||||
def wait_once(target: str, until: Sequence[str] = DEFAULT_UNTIL,
|
||||
timeout_ms: Optional[int] = None, run=subprocess.run) -> WaitOutcome:
|
||||
timeout_ms: Optional[int] = None, session: Optional[str] = None,
|
||||
run=subprocess.run) -> WaitOutcome:
|
||||
"""One barrier call. `run` is injectable so tests never touch a real herdr."""
|
||||
argv = build_argv(target, until, timeout_ms)
|
||||
argv = build_argv(target, until, timeout_ms, session=session)
|
||||
try:
|
||||
proc = run(argv, capture_output=True, text=True)
|
||||
except Exception as exc:
|
||||
@@ -164,3 +169,42 @@ class ReconnectBackoff(object):
|
||||
return [self.record_failure() for _ in range(n)]
|
||||
finally:
|
||||
self.current, self.consecutive_failures, self.cached_snapshot = saved
|
||||
|
||||
|
||||
def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
parser = argparse.ArgumentParser(description="watcher CLI for herdr agent wait")
|
||||
sub = parser.add_subparsers(dest="command", required=True)
|
||||
p_wait = sub.add_parser("wait", help="wait for agent state")
|
||||
p_wait.add_argument("target", help="target agent name")
|
||||
p_wait.add_argument("--session", default=None, help="herdr session name")
|
||||
p_wait.add_argument("--until", action="append", default=[], help="until state(s)")
|
||||
p_wait.add_argument("--timeout-ms", type=int, default=None, help="timeout in ms")
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
session = args.session or os.environ.get("HERDR_SESSION_NAME") or None
|
||||
until = args.until or DEFAULT_UNTIL
|
||||
outcome = wait_once(args.target, until=until, timeout_ms=args.timeout_ms, session=session)
|
||||
agent_st = None
|
||||
if outcome.agent:
|
||||
agent_st = outcome.agent.get("agent_status")
|
||||
print(json.dumps({
|
||||
"kind": outcome.kind,
|
||||
"agent_status": agent_st,
|
||||
"error_code": outcome.error_code,
|
||||
}))
|
||||
rc_map = {
|
||||
MATCHED: 0,
|
||||
TIMEOUT: 2,
|
||||
AGENT_NOT_FOUND: 3,
|
||||
TRANSPORT_ERROR: 4,
|
||||
}
|
||||
return rc_map.get(outcome.kind, 4)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user