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:
@@ -128,6 +128,22 @@
|
||||
:id (host/blog-cid slug) ;; the object's content CID
|
||||
:object {:type "article" :slug slug
|
||||
:category (host/blog--post-category slug)}}))))
|
||||
;; P0.2: the publish WORKFLOW as an EXECUTE-FOLD composition (host/execute.sx) — the SYNCHRONOUS
|
||||
;; business flow. Validate, then BRANCH on category (newsletter → build a digest, urgent → notify
|
||||
;; now, else skip). Content flow (effect/alt), NOT dataflow — so it's the execute-fold, not artdag.
|
||||
;; Its required capabilities are {effect, branch} (host/flow--required-caps) → binds to the sync
|
||||
;; execute-fold runner (which advertises {effect, branch, each}). A `wait` node would add {suspend}
|
||||
;; and fail-fast against that runner (requiring the Erlang runner, RA). Runs against a ctx built
|
||||
;; from the activity's object.
|
||||
(define host/blog--publish-dag
|
||||
(quote (seq
|
||||
(effect validate (field "slug"))
|
||||
(alt (when (eq "category" "newsletter") (effect digest (field "slug")))
|
||||
(when (eq "category" "urgent") (effect notify (field "slug")))
|
||||
(else (effect skip))))))
|
||||
;; the ctx a publish activity presents to the publish-DAG (string keys — preds read ctx by key).
|
||||
(define host/blog--publish-ctx
|
||||
(fn (activity) (let ((o (get activity :object))) {"category" (get o :category) "slug" (get o :slug)})))
|
||||
|
||||
;; ── render ──────────────────────────────────────────────────────────
|
||||
;; A post's sx_content is SX element markup -> HTML via render-page (which supplies
|
||||
|
||||
Reference in New Issue
Block a user