mod: Ext 8 — quorum over distinct reporters (anti-brigade), 232/232
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 55s

(:reporters-at-least N) compiles to setof(Br, report(_, Br, Sr), Bsr),
length(Bsr, Nr), Nr >= N — counts distinct reporters, not raw reports.
mod/decide-quorum asserts every report's report/3 fact (base engine scopes to the
decided report) so Prolog can aggregate reporters. One user filing 3 reports stays
:keep under quorum while the count rule escalates. Own suite. +9 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-06 18:45:28 +00:00
parent 50eb7079e5
commit 062a76e64f
7 changed files with 200 additions and 12 deletions

View File

@@ -16,7 +16,7 @@ federation extension.
## Status (rolling)
`bash lib/mod/conformance.sh`**223/223** (roadmap + 7 extensions complete)
`bash lib/mod/conformance.sh`**232/232** (roadmap + 8 extensions complete)
## Ground rules
@@ -147,6 +147,14 @@ lib/mod/fed.sx
derivation goal-by-goal with `[proved]`/`[unproved]` marks and unification
bindings. E.g. `Report rc: escalate (rule: repeated-escalate)` … `[proved]
report(rc, B, S), report_count(S, N), N >= 3 {B=ann, N=3, S=dave}`.
- [x] **Ext 8 — quorum over distinct reporters** (`lib/mod/quorum.sx`, +9). Anti-
brigade: `(:reporters-at-least N)` compiles to `setof(Br, report(_, Br, Sr), Bsr),
length(Bsr, Nr), Nr >= N` — distinct reporters, not raw report count.
`mod/decide-quorum` asserts every report's `report/3` fact (the base engine only
asserts the decided one) so Prolog can aggregate reporters. Verified one user
filing 3 reports stays `:keep` under quorum while the count rule would escalate.
(Substrate note: `^` existential doesn't parse; `setof(B, p(_, B, S), …)` with `_`
yields the distinct set in a single solution here.)
- [x] **Ext 7 — repeat-offender escalation** (`lib/mod/offenders.sx`, +19). The
audit log as evidence: `mod/subject-sanctions` counts prior hide/remove/ban
decisions about a subject; `mod/decide-escalating id k` decides normally then
@@ -172,6 +180,13 @@ lib/mod/fed.sx
## Progress log
- **Ext 8 — quorum over distinct reporters, 232/232** (+9). Distinct-reporter
consensus via Prolog `setof`/`length`, requiring a second engine variant that
asserts all reports (the base engine deliberately scopes facts to the decided
report). Demonstrates the substrate handles set-aggregation, and that the
brigade case (one actor, many reports) is defeated by counting reporters not
reports. `^` existential doesn't parse here — `setof(B, p(_,B,S), …)` with `_`
gives the distinct set in one solution.
- **Ext 7 — repeat-offender escalation, 223/223** (+19). Decisions can now depend
on history: the append-only audit log is read back as evidence, and a subject
with k prior sanctions has its next sanction upgraded to `:ban`. Closes the loop