Rebuilds, frees the port (stale servers from earlier sessions squat on
it), and restarts detached on 0.0.0.0:8787; the .lan/ store and its log
are long-lived and gitignored.
The amalgamation and the bindings now ship with sx itself
(sx library/vendors/sqlite/ — bindings + c/ amalgamation); every
import flips from ../src/db/sqlite.sx to vendors/sqlite/sqlite.sx,
resolved through the compiler's stdlib search paths. vendor/ and
src/db/ leave this repo entirely. make test 22/22 — the object cache
keys on content, not path, so the relocated source still hits the
existing cache entries.
src/db/sqlite.sx declares the vendored amalgamation as a named
'#import c' unit (pinned defines + -O2 + #source); every #foreign
binding resolves against it with UNPREFIXED sqlite3_* names. sx
compiles the unit through its content-addressed object cache — once
per checkout — links the objects into 'sx build' binaries, and loads
them as a priority symbol target under 'sx run', so the OS libsqlite3
can never shadow the vendored copy (the version pin in sqlite_smoke
proves it).
Retired: the Makefile vendor targets (cc -> .a + jit/.dylib), the
GENERATED dist_sqlite3_* rename.h (the JIT no longer resolves
program-owned symbols through the process images, so the rename's
reason is gone), and the -L plumbing in make build + tests/run.sh.
make test 22/22; otool -L build/dist carries no libsqlite3.
src/db/sqlite.sx grows from the P5.1 subset (~19 fns) to the complete
practical surface (~100): open_v2 + flags, extended errcodes +
error_offset, txn_state/autocommit, changes64/total_changes64, limits,
the full bind/column families (double/blob/zeroblob), parameter and
column introspection (built with SQLITE_ENABLE_COLUMN_METADATA),
table_column_metadata, statement introspection (sql/expanded_sql/
readonly/busy/isexplain/status), incremental blob I/O (SqliteBlob),
online backup (SqliteBackup + sqlite_backup_run), serialize/
deserialize, and library utilities (complete, strglob/strlike/stricmp,
randomness, memory, compileoptions). One variant per duplicate family
(modern/64-bit preferred; bind_text/blob keep the 32-bit length forms
that skip text64's encoding arg). Not bound, by design: callback-taking
APIs (hooks/UDFs/collations need C->sx callbacks), sqlite3_value_*
(UDF-coupled), varargs config, UTF-16, and subsystems this build omits
— the boundary list lives in the module header and vendor README.
rename.h is now GENERATED by make into build/vendor/ from the bindings'
#foreign names — src/db/sqlite.sx is the single source of truth and the
rename list cannot drift (checked-in vendor/sqlite/rename.h removed).
make test 21/21 (new: sqlite_api.sx — 15 cases over every wrapper
family, including a blob round trip with interior NULs, UNIQUE
constraint extended errcodes, txn_state through BEGIN IMMEDIATE,
backup db->db, and a serialize->deserialize round trip).
KNOWN sx BOUNDARY (filed as a followup): 'if !e' on an error binding
evaluates true even when the error is set — negated error logic in
tests routes through plain bools.
Subplan 02 Slice 2 foundation. vendor/sqlite/ holds the amalgamation
(provenance + upgrade notes in its README); make build compiles it into
build/vendor/libsqlite3.a (statically linked into dist via -L) and
build/vendor/jit/libsqlite3.dylib (dlopen'd by sx run via tests/run.sh's
-L flag) — separate directories because the macOS linker prefers a dylib
over an archive in one search dir.
The sx JIT resolves #foreign symbols via dlsym(RTLD_DEFAULT), where the
already-loaded OS libsqlite3 wins by load order — so the vendored build
renames its API to dist_sqlite3_* (vendor/sqlite/rename.h, -include'd),
making resolution unambiguous in both modes: those symbols exist only in
the vendored products.
src/db/sqlite.sx binds the renamed surface behind Sqlite/SqliteStmt
(open/exec/prepare/bind/step/column/finalize, errmsg, last_insert_rowid,
changes, libversion); opaque handles cross the FFI as usize, strings
read from sqlite are copied before its buffers die.
make test 20/20 (new: sqlite_smoke.sx — pins the loaded version to the
vendored 3.53.2, round trip, reopen persistence, BEGIN/ROLLBACK, errmsg;
also verified as an AOT binary with no libsqlite3 in otool -L).
Real local publish success pipeline replacing the ci-publish stub: validate manifest,
find/create app + draft release, per-artifact content-address store (P2.2) + common
validation (P3.3) with optional manifest-declared size/sha256 (PO ruling), publish via
the repo integrity transaction with channel promotion + audit events (P2.3), persist
db.json (P2.3), emit stable JSON (release id, artifact ids, sha256, file:// URLs) with
--json purity. make publish-example target + tests/publish_happy.sx (fail-before/pass-after).
Salvaged from a worker that completed the work (make test 10/10) but hit the 50-min wall
before committing; manager-verified at ground truth (make test green, make publish-example
exit 0, stored object re-hashes to its key via shasum, db.json records release/2 artifacts/
channel/4 audit events).
The sx 0100 fix (cli.parse / json.parse name collision) is merged on sx
master, so `dist.sx` — co-importing std.cli (via dist) and std.json (via
json_out) — now lowers and builds. Finish the step:
- dist.sx: fix two real frontend errors the old IR-lowering crash had
masked — `main` returns `!` (noreturn exit tails), and the post-parse
dispatch is guarded by `if !perr` so the failable `p` is used only with
its error proven absent. Drop the stale BLOCKED narration.
- Makefile: `make build` now also compiles src/dist.sx -> build/dist;
`make test` depends on `build` so the acceptance test finds the binary.
- tests/cli_dispatch.sx: drives the BUILT build/dist via process.run and
asserts the std.cli exit-code + --json purity contract: no-args and
unknown-command -> human text on stderr + EX_USAGE (64); `ci publish
--json` -> stdout is a single valid JSON object (std.json.parse, no
trailing junk) with the human ack on stderr; `--help` lists ci/release.
Handlers stay honest stubs (real ci publish is P3.4). Gate green:
make build (build/dist), make test (7/7).
Stand up the foundation every later step depends on:
- Source layout: src/, src/infra/, tests/, examples/ (.gitkeep markers).
- Makefile: `build` compiles the smoke program via $SX, `test` runs the
runner over tests/**/*.sx, `publish-example` placeholder (real in P3.4).
Compiler located via `SX ?= /Users/agra/projects/sx/zig-out/bin/sx`.
- tests/run.sh: POSIX-sh runner; discovers tests/**/*.sx, runs each via
`$SX run`, prints ok/FAIL, exits 0 only when all pass (errors on zero
tests so the gate is never silently empty).
- tests/smoke.sx: passing smoke test importing modules/std.sx — proves
toolchain wiring end-to-end (std resolves via the binary's own location).
- .gitignore: ignore build/ artifacts.