artdag: Phase 2 Analyze on Datalog + 16 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s

analyze.sx projects DAG edges to (edge in out) facts and runs recursive
reachable rules for deps-of/dependents-of/reachable-from/ancestors-of, plus
dirty-closure (dirty(Y):-edge(X,Y),dirty(X)) for incremental recompute. Keystone:
changing a mid node dirties only it + downstream. analyze 16/16, total 36/36.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 11:53:29 +00:00
parent e4a8dff9ba
commit b9afe671ae
6 changed files with 239 additions and 9 deletions

View File

@@ -30,7 +30,7 @@ edges.
## Status (rolling)
`bash lib/artdag/conformance.sh`**20/20** (1 suite: dag)
`bash lib/artdag/conformance.sh`**36/36** (2 suites: dag, analyze)
## Ground rules
@@ -88,11 +88,11 @@ lib/artdag/optimize.sx lib/artdag/federation.sx
## Phase 2 — Analyze (Datalog)
- [ ] `lib/artdag/analyze.sx` — project edges to Datalog; `deps-of`, `dependents-of`,
- [x] `lib/artdag/analyze.sx` — project edges to Datalog; `deps-of`, `dependents-of`,
transitive `reachable` (the recursive-reachability shape)
- [ ] **dirty propagation:** given a set of changed nodes, compute the transitive
- [x] **dirty propagation:** given a set of changed nodes, compute the transitive
set of dependents that must recompute (`dirty-closure`)
- [ ] `lib/artdag/tests/analyze.sx` — deep chains, diamonds, dirty closure
- [x] `lib/artdag/tests/analyze.sx` — deep chains, diamonds, dirty closure
correctness, unaffected nodes stay clean
## Phase 3 — Plan
@@ -136,6 +136,17 @@ lib/artdag/optimize.sx lib/artdag/federation.sx
## Progress log
- **Phase 2 — Analyze on Datalog** (analyze suite 16/16, total 36/36).
`lib/artdag/analyze.sx`: `artdag/edge-facts` projects each `(input-id, node-id)`
pair to an `(edge ...)` fact; `artdag/analyze` builds a `dl-program-data` db with
recursive `reachable(X,Y) :- edge(X,Y); edge(X,Y),reachable(Y,Z)` (the acl/relations
reachability shape). Query helpers `deps-of`/`dependents-of` (direct),
`reachable-from` (transitive downstream), `ancestors-of` (transitive upstream), all
returning sorted id lists. `dirty-closure` builds a db with `dirty(Y) :- edge(X,Y),
dirty(X)` seeded by changed-node facts and returns the transitive forward closure —
keystone test confirms changing a mid node dirties only it + downstream, leaving
siblings/upstream clean. Content-ids work as opaque Datalog string constants.
- **Phase 1 — DAG model + content addressing** (dag suite 20/20). `lib/artdag/dag.sx`:
node `{:op :inputs :params :commutative}`; `artdag/content-id` = `"node:"` + a
deterministic canonical serialization of `(op, inputs, params)` with dict keys