plans: correct extraction note — declined after reading both impls
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
Reading lib/mod (Prolog) and lib/acl (Datalog) side by side shows the convergence is in module names only. Federation: opposite trust models (SX registry + decision sharing vs in-engine Datalog trust facts + fact replication), zero shared code. Audit: only a ~5-fn core overlaps and it diverges (entry shapes, seq base 0 vs 1, op sets, mutation idiom) — not worth a shared module under two restricted envs. Outcome: keep them parallel; revisit only on a third same-model consumer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -238,28 +238,41 @@ lib/mod/fed.sx
|
||||
`mod/dedup-reports` collapses identical reports (reporter|subject|reason key,
|
||||
case-insensitive); `mod/distinct-reporters-of` counts unique reporters.
|
||||
|
||||
## Shared-plumbing extraction — post-merge integration note
|
||||
## Shared-plumbing extraction — evaluated post-merge, DECLINED
|
||||
|
||||
mod-sx (Prolog) and acl-sx (Datalog, `lib/acl/`, 120/120) independently converged
|
||||
on the same module shape: `schema / engine / audit / explain / federation / api`.
|
||||
That parallel is the signal both plans flagged. **Recommendation: do NOT extract
|
||||
from a loop branch — extract at the architecture-merge integration point, after
|
||||
both `lib/mod` and `lib/acl` have landed, refactoring both consumers in one change.**
|
||||
Both layers now live on architecture; the extraction was evaluated by reading
|
||||
both implementations side by side. **Finding: do not extract — the convergence is
|
||||
in module *names* only, not implementations.** The engines and decision models
|
||||
genuinely differ, so a shared module would be premature abstraction that ages
|
||||
badly. (This reverses the pre-read note that listed audit + fed trust/outbox as
|
||||
candidates; reading the code showed they don't actually share.)
|
||||
|
||||
- **Different engines.** acl = Datalog bottom-up (native derivation trees); mod =
|
||||
Prolog backtracking (proof via per-goal `pl-query-all`). The engine and most of
|
||||
`explain` are NOT shared — same intent, different mechanism. Don't try to unify them.
|
||||
- **Genuinely convergent shapes (the only real candidates):**
|
||||
- **Append-only audit log** — `{seq, payload, retrieve-by-id}`; both have it (~40
|
||||
lines). Lift to e.g. `lib/guest/audit-log.sx` parameterized by the entry payload.
|
||||
- **Federation trust/outbox** — advisory-unless-`(trust peer :scope)` + a send
|
||||
seam; both have it. Lift the trust registry + outbox; keep `:scope` a parameter
|
||||
(`:mod` vs `:acl`).
|
||||
- **Trivia not worth a module:** `join-with`, `any?`, `str-contains?`, `distinct`.
|
||||
- **Why not now:** the branches merge independently; lifting from one leaves the
|
||||
other's copy un-refactored → duplication, not sharing. Real extraction must touch
|
||||
both consumers atomically, which only the post-merge integrator can do. Designing
|
||||
the abstraction also needs both payload shapes in view (only mod's is visible here).
|
||||
- **Federation — zero shared code.** mod gates trust in SX (a `{:peer :scope}`
|
||||
registry + `grant`/`revoke`/`trusted?`) and shares *decisions* (outbox,
|
||||
advisory/applied logs, `receive-decision`). acl gates trust *inside Datalog*
|
||||
(`trust(Peer,L)` / `level_covers` facts + an engine rule re-checked per query)
|
||||
and shares *facts* (`fetch`/`collect`/`build-db`, `assert!`/`retract!`). acl has
|
||||
no trust registry, no `trusted?`, no outbox. Opposite architectures — the only
|
||||
common token is the word "trust."
|
||||
- **Audit — only a ~5-fn core overlaps, and it diverges.** Entry shapes differ
|
||||
entirely (mod `{:action :rule :proof :evidence :report-id :seq}` vs acl
|
||||
`{:allowed? :act :subj :res :seq}`); seq base differs (acl 0, mod 1, both
|
||||
test-visible); op sets barely intersect (mod: by-`report-id` + `latest`; acl:
|
||||
`tail`/`snapshot`/`restore`/`serialize`); even the list idiom differs (acl
|
||||
`append!`+copy vs mod pure `append`+`set!`). A shared module would also have to
|
||||
satisfy two different restricted eval envs (prolog- vs datalog-loaded). Cost
|
||||
(shared module + refactor both + rewrite acl's serialize/snapshot onto a foreign
|
||||
core + cross-env risk + coupling two independent loops) far exceeds the benefit
|
||||
(dedup ~5 trivial lines that don't even agree on seq-base or mutation idiom).
|
||||
- **Engines + `explain`** were never shareable: Datalog yields derivation trees
|
||||
natively; mod reconstructs proofs via per-goal `pl-query-all`.
|
||||
- **Trivia** (`join-with`, `any?`, `str-contains?`, `distinct`) is one-liners, not
|
||||
worth a module.
|
||||
|
||||
**Outcome:** keep mod (Prolog) and acl (Datalog) as parallel independent
|
||||
implementations. The parallel structure is correct for two different engines; the
|
||||
shared abstraction is not. Revisit only if a third rule-engine consumer appears
|
||||
with the *same* trust/audit model (rule of three), not before.
|
||||
|
||||
## Progress log
|
||||
|
||||
|
||||
Reference in New Issue
Block a user