Calls propose, verdicts dispose
Source:
harness/docs/decisions/calls-propose-verdicts-dispose.md
Status: current
Calls propose, verdicts dispose
Section titled “Calls propose, verdicts dispose”Decision
Section titled “Decision”Every input is processed map-then-reduce. Mappers (programs) are pure:
(event, fold-views, KV-snapshot) → proposals. Introducing a mapper is SAFE.
Reducers consolidate: each takes (original, accumulated) and may override the
previous reducer’s output. Introducing a reducer is a DANGEROUS operation requiring
audit. The first reduce layer is hardcoded host law — shape-consolidation only (e.g.
array→string) — and always runs first; plugin reducers run after it, so the LAST
reducer has final say. Safety rests on the audit gate, not on host-final-say. Audit is
a dedicated hook lane: audit hooks are themselves mappers, producing go / no-go /
Question (“here are my concerns, confirm”). The default audit reducer is hardcoded:
any no-go → no-go; else concerns exist → surface for a human approved write (../runtime/approval.md); else auto-approve.
Reducer chain order is C3 linearization over plugin dependency declarations (plugins may
depend on plugins), ties broken by programId. Supporting laws: post-chain shape
validation (schema-invalid reducer output is treated as a timeout — skip, keep prior
accumulated); drops/skips/timeouts are observable on the dispose series / host notices,
not via a global session event monoid.
Work authority and chrome derive from PEW + SessionRoot folds, not from replaying a session event monoid. The map/reduce propose → audit → dispose law is the program path only.
Rationale
Section titled “Rationale”Mapper-safety / reducer-danger is asymmetric because mappers can’t decide — they only propose, so a buggy or malicious mapper produces a bad proposal that still has to survive the reduce chain. A reducer holds override authority; a bad reducer can silently invert an upstream verdict, which is exactly the class of bug the audit lane exists to catch. Putting host shape-consolidation first keeps “last reducer wins” meaningful for plugin authors while guaranteeing the accumulated value is always well-shaped before any plugin reducer sees it. C3 linearization (rather than registration order or priority numbers) is the same dependency-respecting order already used for capability-symbol composition elsewhere, so authors learn one ordering rule. Treating a schema-invalid reducer output as a timeout, not a crash, means a malformed reducer degrades to “was skipped” instead of corrupting the accumulated verdict.