Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions specs/port/trios/crates/trios-bridge/src/agents.t27
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Agent registry — tracks connected agents and their status.
// Port of gHashTag/trios:crates/trios-bridge/src/agents.rs
// (at 8b229e9e9489ee, 116 lines) — Roadmap Stage 6, goal #4548, target
// t27c gen-rust.
//
// The original is a thread-safe agent map: new builds the empty
// registry; register inserts an agent keyed by its id with the Idle
// status, no task, the connected-at stamp and the last heartbeat —
// the capabilities ride along unused (the comment names future
// routing); update_status rewrites BOTH the status and the task and
// refreshes the heartbeat, but ONLY for a registered agent; unregister
// removes the key; list answers every entry's info; agent_ids answers
// the keys alone (for broadcast); and is_registered answers the
// membership gate.
//
// The RwLock, the HashMap and the clock are the callers' plumbing;
// the decisions — the empty start, the Idle+no-task+stamped insert,
// the both-fields update gated on membership, the heartbeat refresh on
// every update, the remove, the info-vs-ids answer pair, and the
// membership gate — are ported here as pure functions over a
// presence-flag registry view and tested, including the original's
// own register/list, update_status and unregister tests (issue #6078,
// "Port the decision, not the plumbing").

module port::trios_bridge_agents;

// ---------------------------------------------------------------------------
// Original lines 23-27: `new` — the registry starts EMPTY.
// ---------------------------------------------------------------------------

pub fn AgentRegistry_new() -> usize {
return 0;
}

// ---------------------------------------------------------------------------
// Original lines 30-44: `register` — the insert shape: the agent keyed by
// its id, the Idle status, no task, the connected-at stamp and the last
// heartbeat set to the same now; the capabilities ride along unused.
// ---------------------------------------------------------------------------

pub fn register_initial_status() -> str {
return "idle";
}

pub fn register_initial_task_present() -> bool {
return false;
}

pub fn register_stamps_heartbeat() -> bool {
return true;
}

pub fn register_capabilities_used() -> bool {
return false;
}

pub fn AgentRegistry_register(agent_registered_count: usize) -> usize {
return agent_registered_count + 1;
}

// ---------------------------------------------------------------------------
// Original lines 47-54: `update_status` — BOTH the status and the task
// rewrite, the heartbeat refreshes, and ONLY a registered agent answers;
// an unknown id changes nothing.
// ---------------------------------------------------------------------------

pub fn AgentRegistry_update_status(agent_registered: bool) -> bool {
return agent_registered;
}

pub fn update_rewrites_both_fields() -> bool {
return true;
}

pub fn update_refreshes_heartbeat() -> bool {
return true;
}

// ---------------------------------------------------------------------------
// Original lines 57-59: `unregister` — the remove by key.
// ---------------------------------------------------------------------------

pub fn AgentRegistry_unregister(agent_registered_count: usize) -> usize {
if (agent_registered_count > 0) {
return agent_registered_count - 1;
}
return 0;
}

// ---------------------------------------------------------------------------
// Original lines 62-69: `list` — every entry's INFO; original lines
// 72-74: `agent_ids` — the keys ALONE, for broadcast.
// ---------------------------------------------------------------------------

pub fn AgentRegistry_list(registered_count: usize) -> usize {
return registered_count;
}

pub fn AgentRegistry_agent_ids(registered_count: usize) -> usize {
return registered_count;
}

// ---------------------------------------------------------------------------
// Original lines 77-79: `is_registered` — the membership gate.
// ---------------------------------------------------------------------------

pub fn AgentRegistry_is_registered(agent_registered: bool) -> bool {
return agent_registered;
}

// ---------------------------------------------------------------------------
// Tests: every decision above asserted against values read from the
// original's own tests (lines 86-115).
// ---------------------------------------------------------------------------

test new_starts_empty {
assert(AgentRegistry_new() == 0);
}

test register_shape_and_count {
assert(register_initial_status() == "idle");
assert(!register_initial_task_present());
assert(register_stamps_heartbeat());
assert(!register_capabilities_used());
assert(AgentRegistry_register(0) == 1);
assert(AgentRegistry_register(1) == 2);
}

test update_gated_on_membership {
assert(AgentRegistry_update_status(true));
assert(!AgentRegistry_update_status(false));
assert(update_rewrites_both_fields());
assert(update_refreshes_heartbeat());
}

test unregister_removes {
assert(AgentRegistry_unregister(1) == 0);
assert(AgentRegistry_unregister(0) == 0);
}

test list_and_ids_answer_the_registered {
assert(AgentRegistry_list(2) == 2);
assert(AgentRegistry_list(0) == 0);
assert(AgentRegistry_agent_ids(2) == 2);
assert(AgentRegistry_agent_ids(0) == 0);
}

test membership_gate {
assert(AgentRegistry_is_registered(true));
assert(!AgentRegistry_is_registered(false));
}

test original_flow_register_update_unregister {
// The original's own flow: two registers list 2; the busy update
// rewrites status and task for a registered agent; the unregister
// empties the list.
assert(AgentRegistry_register(AgentRegistry_register(0)) == 2);
assert(AgentRegistry_list(2) == 2);
assert(AgentRegistry_update_status(true));
assert(AgentRegistry_list(AgentRegistry_unregister(1)) == 0);
}
Loading