Chorus
view release on metacpan or search on metacpan
lib/Chorus/Expert.pm view on Meta::CPAN
=item * C<BOARD> -- the shared frame, accessible as C<< $agent->BOARD >>.
=item * C<EXPERT> -- a back-reference to this expert instance.
=back
$xprt->register($agent1, $agent2, $agent3);
Agents are stored in registration order, which determines the order in which
C<process()> calls their C<loop()> method.
The termination agent (the one that calls C<solved()>) should be registered
B<last>.
=head2 debug
Enables verbose output to STDERR for the main process loop.
$xprt->debug(1); # enable
$xprt->debug(0); # disable
=head2 process
Runs the pipeline.
my $ok = $xprt->process(); # no input
my $ok = $xprt->process($something); # $something available as $agent->BOARD->INPUT
The main loop iterates over all registered agents in order, calling C<loop()>
on each one, until C<BOARD->{SOLVED}> or C<BOARD->{FAILED}> is set. It respects
C<_REPLAY> and C<_REPLAY_ALL> signals from the agents.
An agent tagged with C<_LOCK_UNTIL_STABLE> is skipped when any earlier agent in
the current iteration has already succeeded (C<_SUCCES> is true). This allows
priority-based sequencing without explicit coupling.
If C<_MAX_ITER> full iterations complete without termination, a warning is emitted
and C<process()> returns C<undef>.
Returns C<1> if C<SOLVED>, C<undef> if C<FAILED> or if C<_MAX_ITER> is exceeded.
=head2 _LOCK_UNTIL_STABLE
An optional flag set directly on an agent frame:
$agent->{_LOCK_UNTIL_STABLE} = 'Y';
When C<_LOCK_UNTIL_STABLE> is set on agent N, C<process()> skips that agent in
the current iteration if B<any> earlier agent has already succeeded
(C<_SUCCES> is true on that agent). This implements priority-based sequencing:
earlier agents are given another full pass before the locked agent is allowed
to run.
Typical use: a "global cleanup" or "conformity check" agent that should only
run once all upstream agents have stabilised for the current cycle.
=head2 _REPLAY and _REPLAY_ALL
These flags are set by the corresponding engine methods and are handled
transparently by C<process()>.
=over 4
=item C<_REPLAY>
Set by C<< $agent->replay() >>. C<process()> re-runs C<loop()> on the same
agent immediately (inner C<do/while> loop), without advancing to the next agent.
=item C<_REPLAY_ALL>
Set by C<< $agent->replay_all() >>. C<process()> restarts the outer agent loop
from the beginning â all agents are iterated again from agent 1.
=back
Both flags are automatically deleted by C<process()> before the re-run, so they
fire exactly once per call.
=head1 BOARD
Every agent registered with C<register()> receives a reference to a shared
L<Chorus::Frame> called B<BOARD>. Access it from inside any rule:
my $board = $agent->BOARD;
=head2 Reserved slots
=over 4
=item C<SOLVED>
Set to C<'Y'> by C<< $agent->solved() >>. Causes C<process()> to return C<1>
immediately after the current C<loop()> call finishes. Deleted by C<process()>
before returning.
=item C<FAILED>
Set to C<'Y'> by C<< $agent->failed() >>. Causes C<process()> to return
C<undef> immediately. Deleted by C<process()> before returning.
=item C<INPUT>
Set by C<process($input)> before the main loop starts. Holds the raw input
value passed to the pipeline.
my $input = $agent->BOARD->INPUT;
=back
=head2 Custom slots for inter-agent communication
Any other slot can be freely written and read by agents to exchange state that
does not belong to individual domain frames:
# In agent 1's _APPLY:
$agent->BOARD->set('phase', 'enrichment');
# In agent 2's _APPLY:
my $phase = $agent->BOARD->phase; # 'enrichment'
( run in 2.450 seconds using v1.01-cache-2.11-cpan-600a1bdf6e4 )