Merge loops/artdag into architecture: job-as-post-object projection

lib/artdag/post.sx (job<->feed post object, post-id = content-id, self-verifying wire,
post-run for peers) per the host loop's 'jobs as posts' direction. Additive. artdag 225/225.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 18:38:52 +00:00
6 changed files with 228 additions and 11 deletions

View File

@@ -31,19 +31,19 @@ edges.
## Status (rolling)
`bash lib/artdag/conformance.sh`**213/213** (12 suites: dag, analyze, plan, execute, optimize, fed, cost, serialize, stats, fault, maude-optimize, schedule)
`bash lib/artdag/conformance.sh`**225/225** (13 suites: dag, analyze, plan, execute, optimize, fed, cost, serialize, stats, fault, post, maude-optimize, schedule)
Base roadmap (Phases 16) COMPLETE + Phase 7 (maude rule-based optimization) COMPLETE
(only optional miniKanren scheduling remains). Now hardening only.
## Integration / merge status (2026-06-28)
**MERGED to architecture (Phase 7) at `b0d845bb`** — local `architecture` now carries
`lib/maude` + artdag Phase 7, conformance green there (198/198 at merge time). The merge
was clean/additive; `architecture` itself was NOT pushed (pushing it triggers a large dev
reload — a deliberate separate call). **NOTE: re-merge needed**`loops/artdag` has since
added `lib/artdag/schedule.sx` (miniKanren CLP(FD) scheduler, 213/213), not yet on
architecture.
**MERGED to architecture, fully up to date.** Phase 7 merged at `b0d845bb`; the miniKanren
CLP(FD) scheduler re-merged at `fdd0c8f7` (architecture HEAD). Local `architecture` now
carries `lib/maude` + the complete artdag engine, conformance green there (213/213). Both
merges were clean/additive (only artdag-scoped files). `architecture` itself was NOT pushed
to origin — pushing it triggers a large dev reload, a deliberate separate call left to a
maintainer.
(Historical, for the Phase 7 merge above:) `origin/architecture`'s `lib/artdag/`
is stale — it predates the maude-bridge, so it is missing ALL of Phase 7
@@ -104,6 +104,28 @@ lib/artdag/optimize.sx lib/artdag/federation.sx
CSE (free from content-addressing) result import/export + provenance/trust
```
## Forward direction — artdag jobs as a feed "post" (per the host loop)
artdag jobs will become a **type of post**: a job rides as the `:object` of a feed
activity (`{:actor :verb :object :at :tags}`, `:verb` "post"), served through the host
loop's `GET/POST /feed`. The engine already has the primitives; the wrapping lives on the
**host/feed** side, NOT in `lib/artdag`:
- **content-id = the post/object id** (stable structural digest = natural AP object id).
- **wire format = the post payload** — `dag->wire`/`dag->string` are self-describing +
content-addressed and survive `write-to-string`/`read`; `wire-verify` re-checks ids on
receipt (self-verifying embeddable object).
- **federation already mirrors the feed** — `fed-export`/`fed-import` are trust-gated with
provenance; a re-posted job dedupes/cache-hits by global content-id.
Boundary: host loop owns the activity wrapping (actor/verb/at/tags); `lib/artdag` owns the
job⇄object projection. **BUILT — `lib/artdag/post.sx`** (post suite 12/12): a post object is
`{:type "artdag/job" :id <output content-id> :wire <dag->wire>}``job->post-object`,
`post-object->job`, `post-object-verify` (wire ids intact + the post id is produced by the
job; rejects tampered params and bogus ids), `job->post-string`/`post-string->object` for the
feed/SXTP body, and `post-run` (a peer decodes → runs → result at the post id, content-address
cache-hitting what it already has). The host loop drops the object into a feed activity's
`:object`; post-id = content-id = the AP object id.
## Phase 1 — DAG model + content addressing
- [x] `lib/artdag/dag.sx` — node `{:op :inputs :params}`; structural content-id =
@@ -219,6 +241,19 @@ be an op token.
## Progress log
- **2026-06-28 Forward — job as a feed post object** (post suite 12/12, total 225/225).
`lib/artdag/post.sx`: the artdag-side projection for "a job is a type of post" (per the
host loop). `job->post-object dag output-name``{:type "artdag/job" :id <content-id of
output> :wire <dag->wire>}` — the post/object id IS the output node's content-id (= the
natural AP object id), the body is serialize.sx's self-describing wire. `post-object-verify`
binds the claimed id to the payload (every record's id recomputes + the post id is present
among them) — rejects a param tampered under a stale id and a bogus post id.
`job->post-string`/`post-string->object` carry it in a feed activity / SXTP body;
`post-object->job` decodes; `post-run post runner cache` lets a peer decode → run → read the
result at the post id (content-addressed, so a warm peer cache-hits what it already holds).
The activity wrapper (actor/verb/at/tags) stays on the host/feed side — this is only
job⇄object. Reuses serialize.sx + execute.sx; no new substrate.
- **2026-06-28 Phase 3/7 — miniKanren CLP(FD) scheduler** (schedule suite 15/15, total
213/213). `lib/artdag/schedule.sx` on `lib/minikanren` (read-only substrate): each node
gets a slot var in `[1..max-slots]`, every edge `(input->node)` imposes `fd-lt