SSyncropel Docs

Trust

Evidence-based reputation computed from outcomes reviewed by independent evaluators — domain-scoped, statistically honest, and decaying over time. Not a policy, not a vote, not an opinion.

Overview

Syncropel computes trust from what actually happened. An actor completes work. An independent evaluator reviews it. The verdict creates a data point. Thousands of data points produce a score that tracks the actor's empirical success rate in that domain. That's trust.

The contrast is deliberate. Trust is not a policy ("Alice is approved for prod") because policies stay fixed while reality changes. Trust is not a vote ("the team voted Alice in") because votes don't compound. Trust is not an opinion because opinions are cheap. Trust is the statistical lower bound on a success rate, maintained by continuous evidence, with an honest answer when evidence is thin.

This is the substrate that lets the system automate more work over time. As trust in an actor on a domain accumulates, their work becomes cheaper to dispatch, more of it can be pre-approved via routing rules, and proven patterns can be replayed without re-computation. Nothing moves faster than the evidence allows.

Three dimensions

Trust is a three-valued function:

trust(actor, domain, judged_by)
  • actor — the DID of the participant whose work we're scoring.
  • domain — the category of work: code, ops, data, research, shell, api, spec, agent, meta, browser, workflow. Domains are declared by whoever emits the verdict; the system doesn't enforce a fixed list.
  • judged_by — the DID of the evaluator who produced the verdict. This matters because two evaluators can legitimately disagree, and the system preserves both perspectives instead of averaging them into noise.

So a single actor can have many trust entries:

trust(did:sync:agent:dev, code, did:sync:user:alice)      = 0.82  ← 47 reviews
trust(did:sync:agent:dev, code, did:sync:agent:director)      = 0.76  ← 31 reviews
trust(did:sync:agent:dev, ops,  did:sync:user:alice)      = 0.05  ← 2 reviews
trust(did:sync:agent:director, research, did:sync:user:alice) = 0.64

The agent is strongly trusted in code by two independent evaluators; weakly trusted in ops because only two reviews exist; and its review trust is tracked separately from its execution trust.

In most deployments, the judged_by dimension is mostly-invisible — you typically care about "how good is this actor in this domain?" and let the fold aggregate across evaluators. But the dimension is there when you need it. Routing rules can ask for trust scored by a specific reviewer; audit can ask "what did this reviewer approve?" without double-counting.

The evaluation gate

Trust is produced at exactly one place: the evaluation gate. The flow:

  1. An actor claims work is complete — spl task done or equivalent. This emits a KNOW with body.topic: "task_done_claim". This does not produce trust.
  2. An evaluator reviews the outcome. In Syncropel's dogfood, that's spl task approve or spl task reject, which emits a KNOW with body.verdict: "accept" (or "reject") and body.judged_by: <completer_did>. This produces one trust observation.
  3. The trust fold (on TICK loop) ingests the verdict and updates (actor, domain, judged_by) evidence.
  4. The next query of trust(actor, domain) returns the updated Wilson score.

The approve/reject records are the observations. Nothing else generates trust evidence. Self-reported success, heuristic judgments, fold-derived "this looks like it worked" — none of these contribute. The rule is: no verdict record, no trust delta.

Independence is structural, not advisory

The evaluator must be a different DID than the executor. If Alice approves her own work, the record is accepted into the log (the kernel doesn't reject it), but the trust fold structurally discards self-verdicts. No trust is earned from self-approval.

This has teeth in day-to-day use: the dev agent that closes a task cannot approve its own work. Its evidence is its claim of completion; the evidence that produces trust comes from the director agent or the human reviewing the PR.

For agent-to-agent review (did:sync:agent:dev reviewed by did:sync:agent:director), independence holds trivially — two different DIDs, two separate trust chains. The evaluator's trust itself accumulates independently, which is why trust(did:sync:agent:director, review) is a legitimate score you can query.

The Wilson lower bound

The raw success rate (successes / total) is the wrong aggregator. With 1 success out of 1 observation, 1.0 looks perfect but carries almost no information. With 100 out of 100, 1.0 looks identical but is far more reliable.

Syncropel uses the Wilson score lower bound at 95% confidence. This gives a statistically honest answer that rises with evidence:

Success / TotalWilson LB (95%)What it means
1 / 10.05Almost no evidence; score stays near zero.
5 / 50.57Promising; worth routing simple work to.
10 / 100.72Strong; routing rules can pre-approve.
50 / 500.93Crystallization territory.
10 / 120.57Same ceiling as 5/5, accounting for the 2 failures.
45 / 500.79High but not perfect — occasional misses weigh down the lower bound.

The lower bound under-counts on purpose. You cannot bootstrap high trust from a handful of lucky approvals; you have to keep producing.

The dial and the cost curve

Trust feeds the dial — a continuous value in [0, 1] that maps into four zones:

ZoneDial rangeWhat it meansTypical cost
REPLAY0.00 – 0.33A proven pattern is replaying.Near zero.
ADAPT0.33 – 0.50Known pattern, minor adaptation.Low.
EXPLORE0.50 – 0.67Moderate novelty, iterative approach.Moderate.
CREATE0.67 – 1.00Genuinely novel; full reasoning required.Higher.

The dial is derived from trust and pattern match strength — a well-trusted actor doing novel work still lands in EXPLORE/CREATE, and an untrusted actor touching a well-matched pattern lands in REPLAY. Trust shifts where on the curve a task sits; pattern match determines which curve.

Over time, a domain dominated by a high-trust actor and a well-matched pattern shifts most of the distribution into REPLAY. That's the economic payoff — not cheaper LLM calls, but fewer LLM calls, because replay doesn't call the model at all.

Decay

Evidence gets stale. The default decay half-life is 90 days: an approval from three months ago counts as 0.5 of an approval from today; one from six months ago counts as 0.25. The Wilson computation runs over the decayed counts, so the score drifts downward as evidence ages unless refreshed.

This is what keeps the model honest. An actor who was great a year ago but hasn't worked recently returns to a neutral score, and any renewed work has to re-prove itself. Teams that rotate responsibilities, agents whose substrate has changed, domains whose requirements have drifted — all of them get rescored continuously without needing a manual reset.

Decay is a fold-time operation, not an ingest-time one. Nothing happens to the underlying records as they age; only the computed score reflects decay. You can query "what was the trust score on 2025-11-01?" by running the fold with a reference date.

What's enforced today vs the spec

Current implementation covers the core trust loop end-to-end: verdict records produce evidence, Wilson LB computes scores, self-verdicts are discarded, decay runs on schedule, scores are exposed via spl trust and the trust() CEL function in all 7 CEL contexts.

Two pieces are partially implemented and tracked as follow-ups:

  • CUSUM drift detection is in the algebra crate (see syncropel-trust/src/cusum.rs) but the alert surface isn't wired to push notifications yet. The counters are observable at GET /v1/governance/cusum-alerts.
  • Crystallization of patterns from trusted actors works — a pattern from an actor with trust ≥ 0.90 and 100+ observations crystallizes per the C1-C4 criteria — but the REPLAY path doesn't yet fully bypass the LLM for crystallized patterns in all 7 decision points; it short-circuits in routing but not yet in AITL.

Both are bounded gaps. The trust layer is statistically honest and domain-scoped today; the full payoff (automatic replay everywhere) lands as the remaining consumers are wired.

When trust won't help you

Worth flagging up front — trust is not a universal solvent.

Cold start. A brand-new actor has zero observations and therefore zero trust. The first few dispatches are expensive because nothing has crystallized and nothing routes via trust. This is unavoidable and intentional — artificially bootstrapping trust defeats the purpose.

Domain mismatch. An actor with high trust in code has none in ops. Routing an ops task to them produces a low-evidence verdict that doesn't leverage their code trust. Either tag the domain correctly or accept the lower confidence.

Rare-event tasks. If a task type happens once per year, you won't accumulate observations fast enough to build trust. These are legitimately EXPLORE/CREATE; the model is telling the truth when it stays expensive.

Evaluator disagreement. If two evaluators give consistently opposite verdicts on the same actor's work, the aggregated trust score is misleading. Look at trust(actor, domain, judged_by) separately per evaluator before making routing decisions.

What's next

On this page