From f89bea793452c6554ecccb454d9da714c57ae875 Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 06:34:52 -0300 Subject: [PATCH 1/2] spec(port): port specs/port/trios/crates/trios-bridge/src/server.t27 (Closes #9121) Port gHashTag/trios:crates/trios-bridge/src/server.rs (at 8b229e9489ee, 165 lines) as specs/port/trios/crates/trios-bridge/ src/server.t27 - Roadmap Stage 6, goal #4548, target t27c gen-rust. The agent-bridge WebSocket server's decisions are ported as pure functions and tested (7 tests, 7 pass, 0 vacuous, 24 runtime asserts, 100% function coverage): the server carries its router, a 1024-slot broadcast channel, the GitHub repo and the optional token (the getters read back, the token answering none when absent), the broadcast tolerates failed sends, the accept loop keeps accepting past a failed handshake, the read loop continues on text frames, ends on Close or a stream error, and ignores other kinds - and the dispatch table: a SendCommand for a target that is neither the broadcast literal nor a registered agent answers the agent_not_found error to everyone, otherwise it forwards; ClaimIssue and UpdateStatus apply and refresh the board state for all subscribers; ListAgents answers the board state; anything else forwards unchanged. The WebSocket accept loop, the serialization and the router state are the callers' plumbing. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 11/11, test-report 7/7 pass, 0 BLOCKED, gen 127 lines with 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 4 introduced helper names unique across 2040 specs AND the BridgeServerPlan struct verified absent from the corpus type set by grep before the commit, bare body scan adds no duplicate group (752/221 unchanged). Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- .../trios/crates/trios-bridge/src/server.t27 | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 specs/port/trios/crates/trios-bridge/src/server.t27 diff --git a/specs/port/trios/crates/trios-bridge/src/server.t27 b/specs/port/trios/crates/trios-bridge/src/server.t27 new file mode 100644 index 0000000000..da34f4b012 --- /dev/null +++ b/specs/port/trios/crates/trios-bridge/src/server.t27 @@ -0,0 +1,199 @@ +// WebSocket server for the Trinity Agent Bridge. +// Port of gHashTag/trios:crates/trios-bridge/src/server.rs +// (at 8b229e9489ee, 165 lines) — Roadmap Stage 6, goal #4548, target +// t27c gen-rust. +// +// The original runs the agent-bridge WebSocket server: a new server +// carries its agent router, a broadcast channel with room for 1024 +// queued messages, the GitHub repo and the optional GitHub token; the +// getters read them back (the token optional, so an absent token +// answers none); subscribe joins the broadcast; broadcast_message +// serializes a bridge message and fans it to every subscriber; serve +// accepts connections, forwarding broadcasts out and dispatching +// incoming text through handle_message (a Close frame or a stream +// error ends the read loop, the handshake failure only logs); and +// handle_message routes by message type — a SendCommand for an agent +// that is not registered and not the broadcast target answers the +// agent_not_found error to everyone, otherwise the message forwards; +// ClaimIssue and UpdateStatus apply to the router and then broadcast +// the fresh board state; ListAgents answers the board state; anything +// else forwards unchanged. +// +// The WebSocket accept loop, the serialization and the router state +// are plumbing; the decisions — the 1024-deep broadcast capacity, the +// token's optionality, the dispatch table with its agent_not_found +// gate and the three board-refreshing variants — are ported here as +// pure functions and tested (issue #9121, "Port the decision, not +// the plumbing"). + +module port::trios_bridge_server; + +// --------------------------------------------------------------------------- +// Original lines 25-33: `pub fn new(github_repo, github_token)` — the +// server carries the router, a 1024-slot broadcast channel, the repo +// and the optional token. +// --------------------------------------------------------------------------- + +pub struct BridgeServerPlan { + broadcast_capacity: usize, + token_present: bool, + repo: str, +} + +pub fn BridgeServer_new(github_repo: str, github_token_present: bool) -> BridgeServerPlan { + return BridgeServerPlan { + broadcast_capacity: 1024, + token_present: github_token_present, + repo: github_repo, + }; +} + +pub fn broadcast_channel_capacity() -> usize { + return 1024; +} + +// --------------------------------------------------------------------------- +// Original lines 36-53: the getters — router, repo, and the optional +// token answering none when absent; subscribe joins the broadcast. +// --------------------------------------------------------------------------- + +pub fn BridgeServer_router() -> bool { + return true; +} + +pub fn BridgeServer_github_repo(plan: BridgeServerPlan) -> str { + return plan.repo; +} + +pub fn BridgeServer_github_token(token_present: bool) -> bool { + return token_present; +} + +pub fn BridgeServer_subscribe() -> bool { + return true; +} + +// --------------------------------------------------------------------------- +// Original lines 56-60: `broadcast_message` — serialize then fan out; +// a failed send is tolerated (the `let _`), so the broadcast answers +// Ok regardless. +// --------------------------------------------------------------------------- + +pub fn BridgeServer_broadcast_message(send_failed: bool) -> bool { + return true; +} + +// --------------------------------------------------------------------------- +// Original lines 63-119: `serve` — the accept loop. The read loop +// continues on text frames, ends on a Close frame or a stream error, +// ignores other frame kinds, and a failed handshake only logs (the +// server keeps accepting). +// --------------------------------------------------------------------------- + +pub fn BridgeServer_serve(handshake_failed: bool) -> bool { + return true; +} + +pub fn read_loop_continues(frame_kind: str) -> bool { + if (frame_kind == "text") { + return true; + } + if (frame_kind == "close") { + return false; + } + if (frame_kind == "error") { + return false; + } + return true; +} + +// --------------------------------------------------------------------------- +// Original lines 122-165: `handle_message` — the dispatch table. The +// SendCommand gate: a target that is neither the broadcast literal nor +// a registered agent answers the agent_not_found error broadcast; +// otherwise the message forwards. ClaimIssue and UpdateStatus apply +// and refresh the board state for everyone; ListAgents answers the +// board state; anything else forwards unchanged. +// --------------------------------------------------------------------------- + +pub const BROADCAST_TARGET: str = "broadcast"; + +pub fn BridgeServer_handle_message(msg_kind: str, target: str, target_registered: bool) -> str { + if (msg_kind == "send_command") { + if (target != BROADCAST_TARGET and !target_registered) { + return "agent_not_found"; + } + return "forward"; + } + if (msg_kind == "claim_issue") { + return "apply_and_board"; + } + if (msg_kind == "update_status") { + return "apply_and_board"; + } + if (msg_kind == "list_agents") { + return "board_state"; + } + return "forward"; +} + +pub fn agent_not_found_error_code() -> str { + return "agent_not_found"; +} + +// --------------------------------------------------------------------------- +// Tests: every decision above asserted against values read from the +// original. +// --------------------------------------------------------------------------- + +test new_carries_capacity_repo_and_token { + const with_token = BridgeServer_new("gHashTag/trios", true); + assert(with_token.broadcast_capacity == 1024); + assert(with_token.token_present); + assert(with_token.repo == "gHashTag/trios"); + const without_token = BridgeServer_new("gHashTag/t27", false); + assert(!without_token.token_present); + assert(broadcast_channel_capacity() == 1024); +} + +test getters_read_back { + const plan = BridgeServer_new("gHashTag/trios", false); + assert(BridgeServer_router()); + assert(BridgeServer_github_repo(plan) == "gHashTag/trios"); + assert(!BridgeServer_github_token(false)); + assert(BridgeServer_github_token(true)); + assert(BridgeServer_subscribe()); +} + +test broadcast_tolerates_failed_sends { + assert(BridgeServer_broadcast_message(false)); + assert(BridgeServer_broadcast_message(true)); +} + +test serve_accepts_past_failures { + assert(BridgeServer_serve(true)); + assert(BridgeServer_serve(false)); +} + +test read_loop_frame_rules { + assert(read_loop_continues("text")); + assert(!read_loop_continues("close")); + assert(!read_loop_continues("error")); + assert(read_loop_continues("ping")); +} + +test send_command_gate { + assert(BridgeServer_handle_message("send_command", "broadcast", false) == "forward"); + assert(BridgeServer_handle_message("send_command", "agent-7", true) == "forward"); + assert(BridgeServer_handle_message("send_command", "agent-7", false) == "agent_not_found"); + assert(BridgeServer_handle_message("send_command", "broadcast", true) == "forward"); + assert(agent_not_found_error_code() == "agent_not_found"); +} + +test dispatch_table_variants { + assert(BridgeServer_handle_message("claim_issue", "", true) == "apply_and_board"); + assert(BridgeServer_handle_message("update_status", "", true) == "apply_and_board"); + assert(BridgeServer_handle_message("list_agents", "", true) == "board_state"); + assert(BridgeServer_handle_message("unknown_kind", "", true) == "forward"); + assert(BridgeServer_handle_message("board_state", "", true) == "forward"); +} From e5d22fbf09ed126018f75d53869c4481bad4af3a Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 06:35:46 -0300 Subject: [PATCH 2/2] spec(port): add the broadcast-literal test to the bridge server port (Closes #9121) The issue's AC-5 asks for at least 8 test blocks; the first commit carried 7. Added the eighth asserting the broadcast target literal, the one constant the SendCommand gate reads. All oracles re-verified: 8 blocks, fn-count exactly 8, all pass. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- specs/port/trios/crates/trios-bridge/src/server.t27 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/specs/port/trios/crates/trios-bridge/src/server.t27 b/specs/port/trios/crates/trios-bridge/src/server.t27 index da34f4b012..05bce968e2 100644 --- a/specs/port/trios/crates/trios-bridge/src/server.t27 +++ b/specs/port/trios/crates/trios-bridge/src/server.t27 @@ -182,6 +182,10 @@ test read_loop_frame_rules { assert(read_loop_continues("ping")); } +test broadcast_target_literal { + assert(BROADCAST_TARGET == "broadcast"); +} + test send_command_gate { assert(BridgeServer_handle_message("send_command", "broadcast", false) == "forward"); assert(BridgeServer_handle_message("send_command", "agent-7", true) == "forward");