oauth.sx routes the PKCE check through pkce_ok: an S256 challenge carried as
{s256, Hash} compares crypto:hash(sha256, Verifier) =:= Hash; a bare
challenge stays plain (§4.1), so both methods coexist with no change to
existing flows (the bare path is the old =:= behaviour). Raw sha256 digests
are compared (base64url is wire encoding, omitted). New tests/pkce.sx (6,
incl. S256 through PAR). Verified pkce 6/6; substrate fix is in the
preceding commit. 239 total.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
er-eval-binary-segment evaluated a string-valued segment (the parser
represents <<"abc">> as one integer segment whose value is the whole string
"abc") by calling er-emit-int! on the string, emitting a single bogus 0
byte. So every <<"...">> literal became {:tag "binary" :bytes (0)} — which
made binary =:= read as "always equal" and crypto:hash input-independent.
Fix: the integer branch now expands a string value to one byte per
character (Erlang semantics: <<"abc">> ≡ <<97,98,99>>). Verified:
byte_size(<<"abc">>)=3, <<"a">> =:= <<"b">> is false, crypto:hash distinct
per input.
(User-authorized cross-scope fix from the identity loop; loops/erlang
should adopt this as the owner of lib/erlang.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ev/book-checked! prevents an attendee double-booking themselves across
different events by consulting their persist-derived availability for the
occurrence window (:time-conflict on overlap; same-occurrence re-book stays
idempotent).
ev/book-checked! prevents an attendee double-booking themselves across
different events: consults their persist-derived availability (ev/free-p?) for
the occurrence window, returns :time-conflict on overlap else the normal
ev/book-occ! result. Re-booking the same occurrence stays idempotent
(:already); other actors unaffected. ev/would-time-conflict? predicate.
311/311 green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tests/integration.sx — one narrative across every module: catalog -> stock
check -> quote (promo+stack+tax) -> attribution -> order flow -> payment
envelope -> settle -> recon -> refund flow -> ledger mismatch, asserting the
seams tie together with consistent numbers. Proves the three-substrate
composition (minikanren pricing + flow lifecycle + persist ledger) end to end.
Total 297/297 across 18 suites.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
unrelate-node! retracts every local edge touching a node (all kinds, both
directions); leaves federated peer links alone. 147/147.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lib/relations/tree.sx over reach/ancestors/rnode — no new Datalog closures. 126/126.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tcl conformance.sh walks foreign lib/tcl/tests/programs/*.tcl files, reads each
first line's '# expected: VALUE' annotation, uses python3 to escape the Tcl
source into an SX helper, evaluates via (tcl-eval-string ...), and string-compares
got vs expected in bash. No SX test suites and no SX counter/dict scoreboard, so
the shared driver can't drive it (same category as lua/js/forth). Left
conformance.sh untouched; recorded the exclusion.
This completes the A1 worklist: 4 migrated onto the shared driver (common-lisp,
erlang, feed, go) and 5 excluded as foreign runners (forth, js, ocaml,
smalltalk, tcl).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
refund.sx — refund as a second flow-on-sx flow (request -> approve -> settle)
with two suspension points (approval = human/policy decision, settle =
provider). refund-begin! records :refund-requested and suspends at approval;
refund-approve! advances to settle; refund-settle! records :refunded
(idempotent) and completes; refund-reject! records :refund-rejected and cancels.
Only :refunded moves the books. Reuses order.sx flow helpers. Completes the
Phase 5 backlog. Total 278/278 across 17 suites.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep the Datalog ruleset minimal — every dl-query re-saturates, so shape
queries are SX BFS over erel, not extra closures. 110/110.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
smalltalk conformance.sh catalogs foreign lib/smalltalk/tests/programs/*.st
programs, runs 'bash lib/smalltalk/test.sh -v', and scrapes its output (the
'OK 403/403' summary plus per-file pass counts via awk). It loads no SX test
suites directly and emits no SX counter/dict scoreboard. This is the briefing's
own classification example ('smalltalk runs *.st via test.sh') and the same
'scrapes a test.sh' exclusion as ocaml/lua. Left conformance.sh untouched;
recorded the exclusion.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reference index (matching datalog/persist convention): canonical load order and
the full public surface across all 10 modules, plus artdag/version. Wired into the
conformance load list. Total 158/158 unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fault.sx run-safe: a node op may return (artdag/fail reason); failure is confined
to that node + downstream dependents while independent branches compute, and failed
results are never cached, so retry after a fix recomputes only the failed closure
and hits the good nodes. fault 14/14, total 158/158.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
stock.sx — reservation as a precondition the host checks before order-begin!
(validate -> begin), keeping the flow pure. available-stock reads catalog stock
facts; can-reserve?/reserve-check/reservation-shortfalls gate a cart;
effective-available nets out concurrent reservations so orders can't
over-reserve; sufficient-stocko is the multidirectional availability query.
Total 258/258 across 16 suites.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
stats.sx reports hit-ratio, cost-weighted work-recomputed/work-saved,
savings-ratio, and exec-summary over an execution record. Verifies cold (0
saved), warm (all saved), and incremental (saved = unchanged, ran = dirty
closure). stats 12/12, total 144/144.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
artdag/optimize entries outputs fusible? fuses the entry list then DCEs against
the output names — sinks survive fusion (never absorbed), so output-equivalent
with fewer nodes. optimize 22/22, total 132/132.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the SX->Scheme delivery bridge (ev/deliver-messages): notification-
derivation modules (reminders/booking-lifecycle/reschedule) now flow through
the durable notify flow end to end, with an integration suite covering
delivery success, transient-failure, and empty-batch paths.
serialize.sx emits a topo-ordered (id op inputs params commutative) record list
that survives write/read (string-keyed node dicts do not; empty inputs read back
as nil and are normalized). wire->dag reconstructs a runnable dag by content-id;
wire-verify recomputes ids to reject tampering. dag->string/string->dag for text
transport. serialize 13/13, total 128/128.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ocaml conformance.sh runs 'bash lib/ocaml/test.sh -v', scrapes its
human-readable ok/FAIL lines, and re-classifies each test into suites via bash
description-matching heuristics; it also scrapes lib/ocaml/baseline/run.sh
(foreign .ml programs). The underlying test.sh is a per-assertion epoch runner
(hundreds of individual (ocaml-test-...) evals, one epoch each) with no
suite-level counter variables or dict runners, so the driver's
counter/dict-scoreboard model has nothing to point at without rewriting the test
harness. 'Scrapes a test.sh' is the briefing's named exclusion criterion (test.sh
even notes it mirrors lib/lua/test.sh, the canonical excluded case). Left
conformance.sh untouched; recorded the exclusion.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
optimize.sx adds three result-preserving passes: dce (keep outputs + ancestors,
preserve ids), cse (==build; structural sharing is free from content addressing),
and fuse (collapse 1-to-1 fusible unary chains into an artdag/pipeline node fed by
the chain head's input; leaves/fan-out/non-fusible ops never fuse). fusing-runner
replays pipeline stages, output-equivalent to the unfused dag. optimize 18/18,
total 87/87.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
nettax.sx — alternative to quote.sx's gross-tax default: cart-quote-net taxes
the net (post-discount) base. allocate-discount spreads the basket discount
across lines by extended-price share with a deterministic largest-remainder
pass so per-line shares sum exactly to the discount; each line taxed on its net
at its class rate. Both policies reproducible; pick per jurisdiction.
Total 239/239 across 15 suites.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
execute.sx folds a plan, runs each node via an injected runner (perform in
prod, op-table in tests), and memoizes results in a lib/persist kv backend
keyed by content-id. Incremental recompute falls out of content addressing:
a leaf change reassigns ids across its dirty closure, so re-running hits the
unchanged nodes and recomputes only the closure (cold 5 -> rerun 0 -> change 3).
Cross-dag subgraph sharing verified. execute 15/15, total 69/69.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
js conformance.sh walks lib/js/test262-slice/**/*.js (foreign test262
fixtures), escapes each with python3, evals via (js-eval), and compares output
to a sibling .expected file by substring match — counting pass/fail in bash
against a >=50% target. It loads no SX test suites and emits no SX counter/dict
scoreboard (no scoreboard.json). The shared driver only epoch-loads SX preloads
and evals SX test suites emitting a scoreboard — it cannot drive a
foreign-fixture-vs-expected comparison harness (same category as
lua/forth/smalltalk). Left conformance.sh untouched; recorded the exclusion.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
plan.sx schedules a dag into Kahn-wave batches (parallel-safe), splits waves
wider than a cap into sub-batches, and plans incrementally over the dirty
closure only (out-of-set deps treated as satisfied cache hits). plan 18/18,
total 54/54.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
ev/deliver-messages bridges SX notification messages to the Scheme notify
flow: each (id recipient body) is serialized to s-expr text, spliced as quoted
data into the digest-flow program, delivered over an injected transport, and
results unboxed. Integration suite drives all three derivations (reminders /
booking-notify / reschedule) through delivery end to end; empty batch guarded
(empty digest completes without suspending). 303/303 green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Go has the same structure as erlang: suites load into one session and each
exposes a pass counter plus a *count* (total) counter rather than a fail
counter. MODE=dict fits — each suite's runner is a dict literal
{:passed P :failed (- count P) :total count}. No driver change; conformance.conf
+ 3-line shim, historical scoreboard schema preserved.
Parity verified 609/609 (0 fail), every suite matching baseline.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
window.sx — a validity window kept separate from the promo tuple (promo.sx
untouched): windowed promo (promo from until), inclusive int timestamps, nil =
open bound. active-ruleset filters to promos live at `at` and feeds the existing
promo/stack/quote pipeline; active-codes is the backward "which codes live at
T?" query; windowed-quote is the datetime-aware, deterministic quote.
Total 228/228 across 14 suites.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
forth's conformance.sh reads a foreign Forth test corpus (Hayes Core core.fr),
preprocesses it with awk + an external python3 chunk-splitter that generates a
chunks.sx of raw source strings, then runs them through the interpreter via
(hayes-run-all). The shared driver only epoch-loads SX preloads and evals SX
test suites emitting a counter/dict scoreboard — it cannot reproduce the
external preprocessing pipeline over a foreign .fr corpus (same category as
lua/smalltalk). No SX tests/*.sx suites exist to migrate. Left conformance.sh
untouched; recorded the exclusion.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
payment.sx — payment-request materialises {:order :amount :currency :return-url}
at the IO edge (amount from the ledger, currency/return-url host-supplied), so
lib/commerce stays vendor-agnostic; SumUp/Stripe adapters live in the orders
service and order-settle!(ref, amount) is the resume seam. pending-payments
enumerates suspended orders + envelopes (host poller seam). Gotcha handled: a
Scheme string flow-payload round-trips back wrapped as {:scm-string ...} —
unwrapped via scm->string. Total 209/209 across 13 suites.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>