- pl-eval-arith: add floor, ceiling, truncate, round, sqrt, sign, pow, integer,
float, float_integer_part, float_fractional_part, **, ^ operators
- pl-collect-vars: helper that extracts unbound variables from a term (left-to-right,
deduplicated by var id)
- term_variables/2: dispatches via pl-collect-vars, unifies second arg with var list
- pl-predsort-insert!: inserts one element into a sorted list using a 3-arg comparator
predicate; deduplicates elements where comparator returns '='
- pl-predsort-build!: builds sorted list via fold over pl-predsort-insert!
- predsort/3: full ISO predsort — sorts and deduplicates a list using a caller-supplied
predicate
- lib/prolog/tests/advanced.sx: 21 tests (12 arith, 5 term_variables, 4 predsort)
- conformance.sh: add advanced suite
- scoreboard: 517/517 (was 496/496)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two new builtins to lib/prolog/runtime.sx:
- sub_atom/5: non-deterministic substring enumeration. Iterates all
(start, length) pairs over the atom string, tries to unify Before,
Length, After, SubAtom for each candidate. Uses CPS loop helpers
pl-substring, pl-sub-atom-try-one!, pl-sub-atom-loop!. Fixed trail
undo semantics: only undo on backtrack (k returns false), not on success.
- aggregate_all/3: collects all solutions via pl-collect-solutions then
reduces. Templates: count, bag(T), sum(E), max(E), min(E), set(T).
max/min fail on empty; count/bag/sum/set always succeed.
New test suite lib/prolog/tests/string_agg.sx: 25 tests, all passing.
Total conformance: 496/496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- parser.sx: add (":-" 1200 "xfx") to pl-op-table so (head :- body) parses
inside paren expressions (parens reset prec to 1200, allowing xfx match)
- parser.sx: extend pl-token-op to accept "op" token type, not just "atom",
since the tokenizer emits :- as {:type "op" :value ":-"}
- tests/assert_rules.sx: 15 new tests covering assertz/asserta with rule
terms, conjunction in rule body, recursive rules, and ordering
- conformance.sh: wire in assert_rules suite
- 456 → 471 tests, all passing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds 6 new built-in predicates to the Prolog runtime and 24 tests covering
term<->atom conversion (bidirectional), output capture, format directives (~w/~a/~d/~n/~~).
456/456 tests passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds 5 new built-in predicates to the Prolog runtime with 15 tests.
390 → 405 tests across 20 suites (all passing).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds pl-apply-goal helper for safe call/N goal construction (atom or compound),
five solver helpers (pl-solve-forall!, pl-solve-maplist2!, pl-solve-maplist3!,
pl-solve-include!, pl-solve-exclude!), five cond clauses in pl-solve!, and a
new test suite (15/15 passing). Total conformance: 390/390.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previous version ran all 7 claude sessions in the main working tree on
branch 'architecture'. That would race on git operations and cross-
contaminate commits between languages even though their file scopes
don't overlap. Now each session runs in /root/rose-ash-loops/<lang> on
branch loops/<lang>, created from the current architecture HEAD.
sx-loops-down.sh gains --clean to remove the worktrees; loops/<lang>
branches stay unless explicitly deleted.
Also: second Enter keystroke after the /loop command, since Claude's
input box sometimes interprets the first newline as a soft break.
sx-loops-up.sh spawns a tmux session 'sx-loops' with 7 windows (lua,
prolog, forth, erlang, haskell, js, hs). Each window runs 'claude'
and then /loop against its briefing at plans/agent-briefings/<x>-loop.md.
Optional arg is the interval (e.g. 15m); omit for model-self-paced.
Each loop does ONE iteration per fire: pick the first unchecked [ ] item,
implement, test, commit, tick, log — then stop. Commits push to
origin/loops/<lang> (safe; not main).
sx-loops-down.sh sends /exit to each window and kills the session.
Attach with: tmux a -t sx-loops
- scripts/loop-guard.sh — atomic claim with 30-min staleness overtake,
appends NDJSON event to .loop-logs/<lang>.ndjson. Exit 0 = go ahead,
exit 1 = another run is live, skip.
- scripts/loop-release.sh — clear lock, log release with exit status.
Intended for 7 per-language /schedule routines firing every 15 minutes.
Lock detects overlap so tight cadences are safe; stale lock (>30 min)
overtaken automatically if an agent dies mid-run.
sx-tree MCP file ops broken this session (Yojson Type_error "Expected
string, got null" on every file-based call — sx_read_subtree,
sx_find_all, sx_replace_by_pattern, sx_summarise, sx_pretty_print, even
sx_load_check on existing files works but summarise fails). Can't edit
integration.sx to add before:init/after:init dispatch. Additionally 4
of the 6 tests fundamentally require stricter parser error-rejection
(add - to currently parses to (set! nil ...); on click blargh end
accepts blargh as symbol expression) — out of single-cluster budget.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>