1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// Copyright 2024-2026 Reflective Labs
// SPDX-License-Identifier: MIT
//! The Suggestor trait — the contract all suggestor implementations satisfy.
//!
//! # Why this shape?
//!
//! Suggestors in Converge are not actors, not services, not workflow steps.
//! They are pure functions over context: given the current state of shared
//! context, a suggestor decides whether to act (`accepts`) and what to
//! contribute (`execute`).
//!
//! This design makes suggestors:
//! - **Deterministic**: same context → same decision.
//! - **Composable**: suggestors don't know about each other, only about context.
//! - **Testable**: mock the context, assert the effect.
//!
//! # Critical rules
//!
//! - `accepts()` must be **pure** — no side effects, no I/O, no mutations.
//! - `execute()` is **read-only** — it reads context and returns an effect.
//! - Suggestors **never call other suggestors** — all communication via shared context.
//! - **Idempotency is context-based** — check for existing contributions in
//! context, not internal state. Internal `has_run` flags violate the
//! "context is the only shared state" axiom.
use crate;
use crateAgentEffect;
/// The core suggestor contract.
///
/// Every suggestor in the Converge ecosystem implements this trait — whether
/// it wraps an LLM, a policy engine, an optimizer, or a simple rule.
///
/// The engine calls `accepts()` to determine eligibility, then `execute()`
/// to collect effects. Effects are merged by the engine in deterministic
/// order (sorted by suggestor name).
///
/// # Thread Safety
///
/// Suggestors must be `Send + Sync` because the engine executes eligible
/// suggestors in parallel (via Rayon). Suggestor state, if any, must be
/// internally synchronized.