Skip to content

Slice 010: core domain and persistence - #17

Merged
HackTuah merged 11 commits into
mainfrom
slice/010-core-domain-persistence
Sep 20, 2026
Merged

HackTuah merged 11 commits into
mainfrom
slice/010-core-domain-persistence

Conversation

@HackTuah

Copy link
Copy Markdown
Member

Slice 010 at G3. PROOF.md carries the evidence per criterion; NOTES.md carries the G1 plan, every line's record and three deviations. The postgres job on this pull request is AC1's and AC2's Postgres half on the closing tree. Merge-commit method, then tag slice/010 on main.

ROADMAP row 010 to in_progress (plan_check rule 11 on a slice branch).
NOTES.md carries the twelve-line G1 plan with the test or command each line
names, the empty manual queue, and two deviations stated before any code:
postgrex optional rather than default, and an in-tree UUIDv7 generator
rather than a new dependency. plan_check: PASS.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
Red demonstrated on the exact defect PR #7 fixed, planted in the working
tree and reverted; green on the clean tree; both outputs in NOTES.md. The
population derives from git ls-files over .github; a missing YAML parser is
a FAIL, never a skip. G1 line 1.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…ts repo slot

The adapter is chosen at compile time from TRINITY_DB (sqlite by default,
postgres for the CI matrix), stated in config because use Ecto.Repo takes
it as a literal. On SQLite the pool holds one connection in every
environment and each pragma is named rather than inherited. Trinity.Repo.Receipts
is declared, unstarted, for slice 024's own file. A test reads the pragmas
back from a live connection; busy_timeout cannot be read through the pragma
because exqlite installs its own busy handler, and the test says so with
the driver's reason. 79 tests pass; compile with warnings-as-errors and
credo --strict clean. G1 line 2.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
… job with a Postgres service

TRINITY_DB=postgres selects the adapter at compile time (config/config.exs
from line 2); config/test.exs takes DATABASE_URL under it; postgrex is an
optional dependency so the desktop build carries no Postgres driver. A
second job in gate.yml, named postgres so the required check keeps its
context name, runs a postgres:17 service, asserts the compiled adapter is
Ecto.Adapters.Postgres, then mix ecto.reset and the suite with :sqlite
tagged tests excluded by tag. The version rows split: postgrex (in
mix.lock) and pgvector (not yet a dependency). G1 line 3; the job's first
green run on this branch is AC1's Postgres half.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…tory by pid and mode

Trinity.DataDir.Lock takes <data_dir>/LOCK with an exclusive create,
records OS pid, mode, a per-boot token and the time, and is a supervised
child placed before the Repo so a refused boot has opened no database
file. A second acquire is refused naming the live holder's pid and mode; a
file from a dead pid is taken over on Linux through /proc and treated as
held elsewhere; a malformed file is never taken over. Ten tests, including
the boot half against the running application and the child's position
before the Repo. NOTES.md also records line 3's CI evidence: the postgres
job on run 35509095238 dropped and created the database and ran the suite
with the :sqlite tag excluded, 72 passed. G1 line 4.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…do --strict was red on nesting depth

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…n's data-dir call

mix compile --warnings-as-errors --force was red: forbidden reference to
Trinity.Paths from lib/trinity/application.ex:74, which the previous
commit's grep swallowed. Exported with the reason in lib/trinity.ex; the
compile exits 0 and the suite passes.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
… seq, the stress test

Trinity.UUID is an Ecto.Type minting RFC 9562 v7 ids with a monotonic
rand_a, so rows sort by creation without a second column and both adapters
keep their storage rule. Three migrations: personas, sessions, messages
with the unique index on (session_id, seq). Trinity.Sessions is the only
public surface over the tables; Store and the schemas stay inside a
sub-boundary that Trinity exports, so TrinityWeb reaches the context and
nothing else, proven by a compile that fails on a planted Store call and
passes on the lawful one. append_message/2 assigns seq inside one
transaction, locking the session row FOR UPDATE on a Postgres build (the
lock is compiled in or out from the adapter, because the type checker
refuses a runtime branch on a constant). Unknown roles, blank content and
a missing session are refused by name. history/2 orders by seq with limit
and offset. Factories are three plain functions.

Stress: 20 writers, 200 appends each, 5 sessions, gapless, integrity ok,
in the sandbox and again outside it on the dev database through
scripts/stress_010.exs: 4000 appends in 1.2 to 1.3 s, about 3,000 per
second, -wal at 4,152,992 bytes (1,014 pages, at the 1,000-page
autocheckpoint). 105 tests pass; compile with warnings-as-errors, credo,
plan_check and the name check are clean. G1 lines 5 to 9.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…reasons, the boundary probe compiles forced

coverage.tsv gains 010 at 44.88% (up from 30.37%); trinity.coverage OK.
sobelow flagged four File calls in Trinity.DataDir.Lock as low-confidence
traversal; every path is composed from the application's own data
directory and a constant name, and each fingerprint carries that reason
in .sobelow-skips.reasons. The boundary compile test now forces every
compile: mix decides by mtime at one-second resolution, and the gate
caught both a lawful half compiled against a stale violation and a red
half that never compiled the violation. Four consecutive runs pass; the
full gate exits 0. G1 line 11.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
PROOF.md carries every criterion's evidence: the gate at exit 0, 105
tests, coverage 44.88% (up from 30.37%), ecto.reset on SQLite here and on
Postgres in CI, the stress run inside the sandbox and again outside it
with the real WAL size, the boundary refusal text, the data-dir lock's
refusal text. ROADMAP row 010 reads done; docs/05 names the id minter.
The three deviations are stated in NOTES.md and repeated in PROOF.md.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
Signed-off-by: Ayla Croft <aylacroft@proton.me>
@HackTuah
HackTuah merged commit 4349b8f into main Sep 20, 2026
4 checks passed
@HackTuah
HackTuah deleted the slice/010-core-domain-persistence branch September 20, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant