MB678 continues the progressive decomposition of Mediabot’s Partyline subsystem.
After separating the transport layer in MB678-I and the session/authentication layer in MB678-II, this round isolates the central Partyline dispatcher: the _handle_line method that decides where each incoming Partyline line must go.
The objective was deliberately narrow: move routing responsibility out of the large Mediabot::Partyline module without changing the protocol, command syntax, authentication flow, command implementations, or historical method surface.
MB678-III introduces:
Mediabot/Partyline/Dispatcher.pm
and moves exactly one method into it:
_handle_line
That method remains responsible for:
The command implementations themselves remain in:
Mediabot/Partyline.pm
This is intentional.
MB678-III creates the routing boundary first; command extraction is reserved for the next Partyline round.
The historical call surface is preserved by importing _handle_line back into Mediabot::Partyline, so existing callers and tests can continue to use:
$partyline->_handle_line(...)
without knowing that the implementation now lives in Mediabot::Partyline::Dispatcher.
Before MB678-III:
Mediabot/Partyline.pm : 5426 lines
After MB678-III:
Mediabot/Partyline.pm : 5046 lines
Mediabot/Partyline/Dispatcher.pm : 407 lines
Mediabot/Partyline/SessionAuth.pm : 676 lines
Mediabot/Partyline/Transport.pm : 1012 lines
The Partyline subsystem now has three explicit responsibility boundaries:
Partyline.pm
command implementations and remaining core Partyline behaviour
Partyline/Dispatcher.pm
line routing and command dispatch
Partyline/SessionAuth.pm
session lifecycle and authentication
Partyline/Transport.pm
TCP / DCC transport and low-level input handling
The dispatcher extraction removes roughly 380 lines of routing logic from the parent module while preserving the existing Partyline API.
A dedicated extraction contract was added:
t/cases/864_mb678_partyline_dispatcher_extraction.t
The focused dispatcher validation covered the new extraction contract together with existing transport, session/authentication, module-structure, export, and throttle contracts.
Result:
PASSED : 703/703
This included the important:
779_mb596_partyline_throttle_hardening.t
which exercises runtime behaviour around _handle_line, rather than only inspecting source structure.
Moving _handle_line exposed several historical tests that treated physical source location as part of the contract.
The runtime behaviour was correct, but those tests still searched only:
Mediabot/Partyline.pm
for routing code that now legitimately lives in:
Mediabot/Partyline/Dispatcher.pm
No production-code rollback was made.
Instead, the affected source contracts were updated to inspect the correct module set.
The first fast run reported three failures:
FAILED : 3/5640
They came from:
21_partyline_schedule_control.t
237_partyline_quota_cmd.t
The stale assumptions concerned:
.schedule routing;.ban dispatch block;.quota routing.Those tests now inspect Partyline.pm + Dispatcher.pm where appropriate.
Targeted result:
PASSED : 26/26
The first full run reported:
FAILED : 4/14552
The four failures were all source-location assumptions:
587_mb368_atomic_config_reload.t
780_mb597_precommit_hardening.t
836_mb654_achievement_identity_diagnostics.t
They covered:
.reloadconf routing;.achievementprofile dispatch;.achievementprofile argument forwarding.The tests were updated so their source contracts follow the new architecture:
Partyline.pm + Dispatcher.pm
or, for the flood/transport invariant:
Partyline.pm + Transport.pm + Dispatcher.pm
Targeted result:
PASSED : 101/101
These failures were architectural test debt, not runtime regressions.
The security audit remained completely green after the extraction.
Final result:
Verdict: GO — all 11 security invariants hold.
Among the preserved guarantees:
The Partyline authentication-throttling invariant remained intact despite _handle_line moving into its own module.
The development instance was restarted successfully:
mediabot@dev.service
Active: active (running)
The Partyline listener remained available on:
0.0.0.0:23456
A real TCP smoke test against the Partyline produced:
Mediabot Partyline
Please enter your nickname.
Enter your password.
with:
RC_SMOKE=0
This is an important runtime check for MB678-III.
The nickname line now passes through the extracted dispatcher, which correctly recognizes the session state and routes execution into the authentication flow.
No obvious runtime errors were found in the service journal.
After updating the stale source contracts:
PASSED : 5640/5640 (64s)
No fast-suite regression remained.
The final complete test suite passed:
PASSED : 14552/14552 (207s)
This validates the extraction across the complete Mediabot regression surface, including the full-only source and behaviour contracts.
Before this round, the Partyline transport and authentication layers had already been separated, but routing still lived inside the large parent module.
MB678-III establishes a clean dispatcher boundary.
That matters because Partyline now has a much clearer flow:
Transport
↓
Dispatcher
↓
Session/Auth or command implementation
The new structure makes it easier to reason about:
It also makes the next extraction safer.
The remaining large block in Partyline.pm is now predominantly command implementation code. That gives MB678-IV a much better starting point for extracting Partyline commands without mixing transport, authentication, and routing concerns into the same change.
Just as importantly, this round preserved compatibility.
No Partyline protocol change was introduced.
No command syntax changed.
No authentication behaviour changed.
No public Partyline method disappeared.
The architecture changed; the route did not.
Version : 3.4dev-20260820_162844
Commit : ff633dc
Branch : master
🧭 Give Partyline Dispatch Its Own Marauder's Map Without Changing the Route
Commit summary:
14 files changed
507 insertions
393 deletions
New files:
Mediabot/Partyline/Dispatcher.pm
t/cases/864_mb678_partyline_dispatcher_extraction.t
The commit was successfully pushed to GitHub.
🧭 The corridors have not changed, and every door still leads where it did before. Partyline simply has a Marauder’s Map now.
You must be logged in to reply.