mod: Phase 1 — report schema + policy engine on Prolog, 31/31
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m5s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m5s
Reports → Prolog facts (report/3, classification/2, report_count/2); ordered policy rules compile to policy_action/3 clauses, first match wins via pl-query-one. Decisions carry their proof (matching rule + conditions + evidence). Spam/abuse keyword classification, repeated-report escalation via Prolog join+arithmetic, no-rule→keep default. Registry api + conformance harness. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,7 @@ federation extension.
|
||||
|
||||
## Status (rolling)
|
||||
|
||||
`bash lib/mod/conformance.sh` → **0/0** (not yet started)
|
||||
`bash lib/mod/conformance.sh` → **31/31** (Phase 1 complete)
|
||||
|
||||
## Ground rules
|
||||
|
||||
@@ -66,17 +66,19 @@ lib/mod/fed.sx
|
||||
|
||||
## Phase 1 — Report representation + simple policy
|
||||
|
||||
- [ ] `lib/mod/schema.sx` — `report(id, by, about, reason)`, `evidence(id, kind, val)`,
|
||||
`policy-action(report, action)` predicates as Prolog facts/rules
|
||||
- [ ] `lib/mod/policy.sx` — rule declarations: `(defrule action :when conditions)`
|
||||
desugars to Prolog clause
|
||||
- [ ] `lib/mod/engine.sx` — `(decide report-id)` runs Prolog query, returns first
|
||||
matching action
|
||||
- [ ] `lib/mod/api.sx` — `(mod/report by about reason)`, `(mod/decide id)`
|
||||
- [ ] `lib/mod/tests/decide.sx` — 15+ cases: spam keyword → hide, repeated reports →
|
||||
escalate, no rule matches → keep
|
||||
- [ ] `lib/mod/scoreboard.{json,md}`
|
||||
- [ ] `lib/mod/conformance.sh`
|
||||
- [x] `lib/mod/schema.sx` — `report(id, by, about)`, `classification(id, kind)`,
|
||||
`report_count(subject, n)` Prolog facts; keyword classifier derives evidence
|
||||
- [x] `lib/mod/policy.sx` — `mod/mk-rule` + ordered `mod/default-rules`; conditions
|
||||
(`:classification`, `:count-at-least`) compile to Prolog goals; `policy_action/3`
|
||||
clauses, last clause `true` so every report yields at least `:keep`
|
||||
- [x] `lib/mod/engine.sx` — `(mod/decide-report r reports rules)` queries
|
||||
`policy_action(Id, Action, Rule)` with `pl-query-one` (clause order = precedence);
|
||||
returns a decision dict `{:action :rule :report-id :proof}` carrying the why
|
||||
- [x] `lib/mod/api.sx` — registry + `(mod/report by about reason)`, `(mod/decide id)`
|
||||
- [x] `lib/mod/tests/decide.sx` — 31 cases: spam/abuse keyword, repeated→escalate,
|
||||
no-rule→keep, precedence (spam beats repeated), proof shape, registry ids
|
||||
- [x] `lib/mod/scoreboard.{json,md}`
|
||||
- [x] `lib/mod/conformance.sh`
|
||||
|
||||
## Phase 2 — Evidence + audit trail
|
||||
|
||||
@@ -105,8 +107,24 @@ lib/mod/fed.sx
|
||||
|
||||
## Progress log
|
||||
|
||||
(loop fills this in)
|
||||
- **Phase 1 complete — 31/31.** Report schema, keyword classifier, policy DSL,
|
||||
engine, registry api, conformance harness. Decisions are proofs: each carries
|
||||
`:rule` (matching clause), `:proof {:rule :conditions :evidence :count}`.
|
||||
Precedence is Prolog clause order resolved by `pl-query-one`; a trailing
|
||||
`true`-bodied default rule makes "no rule matched" a real `:keep`, not a query
|
||||
failure. Evidence (spam/abuse classification) derived in SX and asserted as
|
||||
`classification/2` facts; repeated-report escalation uses a genuine Prolog
|
||||
join + arithmetic (`report(Id,_,S), report_count(S,N), N >= 3`).
|
||||
- **Gotcha (env):** loading the prolog libs strips `includes?` (and other
|
||||
high-level string prims) from the eval env — only the set the prolog
|
||||
tokenizer itself uses survives (`slice`, `len`, `nth`, `=`, `join`,
|
||||
`downcase`, `map`, `reduce`, `append!`). Implemented `mod/str-contains?` over
|
||||
`slice`/`len` rather than relying on `includes?`. Watch for this in later
|
||||
phases — stick to the blessed primitive set.
|
||||
- **Liftable (acl-sx watch):** `mod/join-with`, `mod/str-contains?`, `mod/any?`,
|
||||
and the rule→clause compilation shape are generic rule-engine plumbing. Do not
|
||||
extract to `lib/guest/` until both mod-sx and acl-sx are past Phase 2.
|
||||
|
||||
## Blockers
|
||||
|
||||
(loop fills this in)
|
||||
(none)
|
||||
|
||||
Reference in New Issue
Block a user