host P0.2: publish-DAG + execute-fold runner + capability check (hypothesis confirmed)
The hypothesis test. FINDING: a synchronous business flow expresses NATURALLY as an EXECUTE-FOLD
composition (host/execute.sx: seq/effect/alt — the category branch IS 'alt'), NOT an artdag
DATAFLOW DAG (which has no control flow). So 'business logic = art-dag' holds at the ABSTRACTION
(both content-addressed op-DAGs) and is REFINED at the vocabulary: the synchronous control-flow
runner is the execute-fold (caps {effect,branch,each}); artdag is the dataflow sibling. Two
instances of one thing, run very differently — exactly the framing.
lib/host/flows.sx: capability typing (host/flow--node-cap/required-caps derive a DAG's capability
set from its node vocabulary; effect→effect, alt→branch, each→each, wait→suspend), the execute-fold
seam runner (advertises {effect,branch,each}), and host/flow--bind (required ⊆ advertised → derive
the runner, else fail-fast). host/blog--publish-dag (the publish workflow) + publish-ctx.
Verified: publish-DAG required-caps = {effect,branch} → binds to the sync runner; runs →
newsletter→[validate,digest] / urgent→[validate,notify] / other→[validate,skip]; a node →
{suspend} → binds FAIL-FAST against the exec-runner (would need the Erlang runner, RA). Runner is
DERIVED, not chosen. flows 7/7, blog 203/203, full host conformance 591/591.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -126,15 +126,20 @@ fed-sx yet — those are adapter phases (RA/TA). Every piece swaps later; the DA
|
||||
|
||||
- [x] **P0.1 — publish-activity contract (SX side).** host/blog--publish-activity + post-category.
|
||||
blog 200/200. NOTE: emits the next/-Erlang shape today; P0.4 reconciles to the canonical seam shape.
|
||||
- [ ] **P0.2 — the publish-DAG + op-table runner + the CAPABILITY check.** Author the publish
|
||||
workflow as an SX artdag DAG (validate → publish → notify/digest) whose nodes need only
|
||||
`{effect, branch}`, + the op-table runner (advertises `{effect, branch, each}`). ACCEPTANCE
|
||||
(the hypothesis test): (a) the workflow expresses NATURALLY as a DAG — if it's forced, that's the
|
||||
signal the node vocabulary / representation needs rethinking BEFORE RA/TA; (b) artdag/analyze
|
||||
computes the DAG's required-capability set = `{effect, branch}`; (c) the binder confirms required
|
||||
⊆ op-table caps → runs; (d) run it → the expected effect-as-data. Then flip one node to `wait`
|
||||
and confirm the bind FAILS FAST against the op-table runner (would require the Erlang runner, RA)
|
||||
— proving durability is derived, not chosen.
|
||||
- [x] **P0.2 — the publish-DAG + execute-fold runner + the CAPABILITY check. DONE 2026-07-02.**
|
||||
**HYPOTHESIS-TEST FINDING:** the synchronous business flow expresses NATURALLY as an EXECUTE-FOLD
|
||||
composition (host/execute.sx: seq/effect/alt — the branch on category IS `alt`, exactly what it's
|
||||
for), NOT an artdag DAG — artdag is pure DATAFLOW with no control flow. So "business logic = art-
|
||||
dag" is confirmed at the ABSTRACTION (both content-addressed op-DAGs) and REFINED at the vocabulary:
|
||||
the SYNCHRONOUS control-flow runner is the execute-fold (caps {effect,branch,each}); artdag is the
|
||||
DATAFLOW sibling (a different runner). Two instances of one thing, run very differently — as
|
||||
predicted. Built: lib/host/flows.sx (host/flow--{node-cap, required-caps, subset?, exec-runner,
|
||||
bind}); host/blog--publish-dag + publish-ctx. Verified: publish-DAG required-caps derived =
|
||||
{effect,branch} → binds to exec-runner; runs → newsletter→[validate,digest]/urgent→[validate,
|
||||
notify]/other→[validate,skip]; a `wait` node → required {suspend} → binds FAIL-FAST against the
|
||||
exec-runner (would need Erlang, RA). flows 7/7, blog 203/203, conformance 591/591.
|
||||
IMPLICATION for RA/TA: the Erlang runner isn't a "different flow language" — it's the SAME op-DAG
|
||||
with +{suspend} nodes; RA is the runner that advertises suspend + wraps flow_dispatch.
|
||||
- [ ] **P0.3 — wire the seam on the live host.** A local-SX trigger registry (on-publish →
|
||||
publish-DAG), an in-process transport (a KV-backed log), the host as effect driver. In edit-submit
|
||||
detect the draft→published TRANSITION (prev≠published & new=published — fire-once), build the
|
||||
@@ -185,6 +190,12 @@ covers everything until a DAG's cost/latency/placement forces the substrate.
|
||||
activities), so business logic can change state, which federates, which triggers more flows.
|
||||
|
||||
## Progress log (newest first)
|
||||
- 2026-07-02 — P0.2 DONE + the hypothesis CONFIRMED (and refined). The synchronous publish workflow
|
||||
is NATURAL as an execute-fold composition (seq/effect/alt), NOT artdag dataflow (no branch there).
|
||||
So business-logic = art-dag holds at the abstraction (content-addressed op-DAG) but the SYNCHRONOUS
|
||||
runner is the execute-fold, artdag the dataflow sibling — two instances, run differently, exactly
|
||||
the framing. lib/host/flows.sx (capability layer + exec-runner + bind) + host/blog--publish-dag.
|
||||
Runner DERIVED via required-caps ⊆ advertised; wait→fail-fast. flows 7/7, blog 203/203, 591/591.
|
||||
- 2026-07-02 — folded in CAPABILITY-TYPED nodes / CAPABILITY-ADVERTISING runners. A node declares
|
||||
`:needs` (wait→suspend, fan-out→parallel, heavy→offload); a runner advertises `:capabilities`
|
||||
(op-table {effect,branch,each}; Erlang +suspend; celery-sx +parallel,retry,offload); artdag/analyze
|
||||
|
||||
Reference in New Issue
Block a user