Commit graph CultLib/tests
Author SHA1 Message Date
Libby
52dd5e8acb docs: docs/start onboarding page with tested CultCache first calls in C# and TypeScript
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest one-command multiplayer onboarding (pull_request) Has been cancelled
CultMesh portability and performance / windows-latest one-command multiplayer onboarding (pull_request) Has been cancelled
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Has been cancelled
CultMesh portability and performance / windows-latest reactive semantics and leases (pull_request) Has been cancelled
CultNet cross-runtime interop / C# / TypeScript / Rust / Python / Kotlin (pull_request) Has been cancelled
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Has been cancelled
A language x package matrix (each cell a tested snippet or "not yet"), a C# first-call test and a TypeScript first-call test that the docs link, and a pointer from the top of README.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-04 16:11:05 +00:00
Meta Vens
64b86e0a27 write-ownership-cs: a write owns a record by the written type; one-batch retype is eviction then add (squash of hands/variants-write-ownership a4eae905..8c7252ea)
A write owns the record at its key when the written type declares the
record's schema id, or reads an older undeclared id of its own schema name
whole (ruling own-entry-reads-whole); every other registered type's record
is refused, in every cache, with or without a backing store
(cache-refuses-retype).

Removing a record and adding one of another type in a single batch is
staged as the held record's eviction then the add, so validators, Claim,
the store judges and the change journal see what they see staged apart
(one-batch-retype-is-eviction-then-add); Watch<old> gets Removed and
Watch<new> Added. A one-batch retype across home stores is refused by the
batch-spans rule and must be staged apart. A variant rebase changes type
exactly where a plain write may (variant-rebase-follows-plain-write).
Store kinds outside the library get one protected per-key judge
(store-kind-per-key-judge), exercised by tests/GameCult.Caching.OutsideStoreTests.

Spec variants:cut_spec:cut-write-ownership-cs.r1; reports h1-h5;
Soul s5 clears the merge (verdict variants:verdict:cut-write-ownership-cs.s5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 08:22:20 +01:00
Meta Vens
1e73e20645 RemoteWriteAuthorityTests: pin the refusal on the wire, the aliased delete's canonical ask and the null decision
A real LiteNetLib pair on ephemeral loopback ports carries the handlers' answers to a client that decodes them with the
production schema decoder; no fixed port and no global frame provider. The delete under a schema alias and a null
decision are pinned where each is decided.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 01:43:18 +01:00
Meta Vens
49594e4901 RemoteWriteAuthorityTests: pin that the refusal is built and sent, and a reasonless refusal's text
Mutation triage: removing the refusal exception's constructor body survived
because the handler threw on the uninitialized peer either way; the helper now
requires the failure to come from the peer's send, not from building the message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 01:10:03 +01:00
Meta Vens
85dbd47dcc RemoteWriteAuthorityTests: subscribe through R3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:48:53 +01:00
Meta Vens
5a80f2adca cultnet.error.v0: add code write_not_authorized across C#, both schema copies and Rust
Captured-bytes case in cultnet-rs error_message.rs, asserted byte-for-byte by
the C# schema contract test; the cultnet-distributed-database contract and the
Networking README state the remote write authority invariant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:47:24 +01:00
Meta Vens
b4f494b7a0 CultNetDatabaseServer: a peer's put or delete commits only when its write authority grants it
CultNetDatabaseServerOptions.RemoteWriteAuthority is asked once per received
write, after the schema resolves and before the shard does; none configured
refuses every remote write; an authority that throws refuses and is logged.
A refusal applies, publishes, logs and forwards nothing. The host's own
CultNetDatabase.ApplyPutAsync/ApplyDeleteAsync ask no remote authority.
Existing server tests whose subject is not the grant pass a test-local
granting authority.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:47:24 +01:00
Meta Vens
3d4efc893a GeneratorConsumer: skip every ref-keyed dictionary serialization under NativeAOT
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:03:21 +01:00
Meta Vens
e3fe3a32f6 GeneratorConsumer: upsert through UpsertAsync
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:01:41 +01:00
Meta Vens
5c55f9cb15 Assume CultRecordRef<T> formattable for MessagePack's source generator consumers
The package ships MessagePackAssumedFormattable(typeof(CultRecordRef<>)) as an
MSBuild AssemblyAttribute in buildTransitive, so generated resolvers defer the
ref to CultDocumentResolver. Geometry imports the targets and drops its three
per-member [MessagePackFormatter] workarounds. GeneratorConsumer is the
generator-on twin of ConsumerBuild.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:59:13 +01:00
Meta Vens
f80634df97 Caching tests: an unattached store's Delete then PushAll writes no entry and so owns no stored record
A cacheless call that writes nothing declares nothing and no written entry can claim the record, so the removal is refused and the file left as it was. Red under the Any-to-All mutant of the declared predicate in OwnsOnDisk, which owns every id when no entry is written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 18:24:16 +01:00
Meta Vens
648045a201 Tests: a lookup over several written entries shadows by the entry that has the id
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:48:44 +01:00
Meta Vens
928a5ff2ca Tests: the shape probe passes the registry's compatible ids so the lent entry would own it
The lent-shape test omitted the old id from the passed entry, so the base code refused it for the id and not for the shape. It now lists them, making the registry's wider entry the only thing that could own the record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:26:17 +01:00
Meta Vens
959f7e4965 Caching: a cacheless write's written entries are the only description of their schema ids
CatalogEntryLookup now takes the lent registry and answers from the written entries plus the registry's other types (descriptors whose schema id no written entry has). The registry Owns overload, the subset predicate and OwnsOnDisk's lent branch are deleted; the passed entry alone describes the written type, so a lent registry only adds claimants and can only refuse more.

Not yet built or run (verified by the job that follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:19:34 +01:00
Meta Vens
fc74cf6f41 Tests: C# refusal lines carry their source and the gate counts them distinct
The console logger repeated each line, so a raw count was 28 for 14 refusals. Names now prints the source (committed or live) and the gate counts distinct 'OLD-READER <runtime> refused <label>' lines.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:35:23 +01:00
Meta Vens
44faddbc3f Tests: count the C# refusal lines in the TRX, where each test's output appears once
The console logger repeats every test's output in its summary, so the log held 28 lines for 14 refusals.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:33:23 +01:00
Meta Vens
0b4606cbd4 Tests: every old-reader gate stage counts the refusal lines its probes printed
A case that returned or passed early is Passed but prints no 'OLD-READER <runtime> refused' line. Each stage now requires the pinned number of those lines (14 C#, 3 Rust, 4 Python, 3 TypeScript) and fails '<stage>-refused-count' otherwise.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:31:33 +01:00
Meta Vens
ce46a40153 Tests: rename the seeding loop variable that shadowed the record (414cf6e1 does not build the Caching tests)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:22:18 +01:00
Meta Vens
414cf6e1ee Tests: rename a lambda parameter that shadowed the record (f744817a does not build the Caching tests)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:19:57 +01:00
Meta Vens
f744817a15 Caching: a lent registry never widens what the passed entry declares; docs state every refusal
The cacheless written test now holds on the entry passed: the claimant's compatible ids must all be listed by the written entry of its id.
CHANGELOG and WriteRecord's registry doc describe the refusal through another registered type's listed id, the condition on own drift, and the Shared caveat. Not yet built or tested here.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:18:30 +01:00
Meta Vens
848fbcd4c5 Gate: a skipped or expected-failure Python case is not a passed one
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:13:48 +01:00
Meta Vens
c8d02949e0 Gate: fix the Python failure-count awk (unescaped paren)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:07:57 +01:00
Meta Vens
e82bf9a3c0 Gate: a failing Python probe is not a passed case
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:07:52 +01:00
Meta Vens
86bd050149 Gate: count passed cases, fail on any not-Passed result, pin the 1.0.60 writer vector by hash
C# stages count TRX results with outcome Passed per class and fail '<stage>-notpassed' on any other
outcome (an [Ignore]d case is NotExecuted); Python also fails on skipped=, expected failures= and
unexpected successes=. Every stage prints its passed count. The committed 1.0.60 writer vector is
compared to a recorded sha256 (the 1.0.60 writer stamps wall-clock times, so no writer stage can
reproduce its bytes).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 09:02:18 +01:00
Meta Vens
01a750afb2 Tests: a cacheless write never takes a record a same-named version of its schema claims
Kills the written-by-name mutant (the claimant condition compared schema names instead of ids).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 08:37:10 +01:00
Meta Vens
cad173ef11 Tests: AnUnpublishedIdIsOwnedByNoOne passes the claimant condition (d3a4d0a3 does not build the Caching tests)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 08:22:27 +01:00
Meta Vens
d3a4d0a3bc Caching: a cacheless write owns a record only through a claimant it writes
Owns takes a condition on the claimant's answer (mayClaim): the cache arm accepts any
claimant, the cacheless arm only one of the entries the call writes. Another registered
type's record, under its current id or an old one it lists, is refused as at 0e57bf11.
Tests pin P1a/P1e/P1f shapes, the writer's own drift under a larger registry, and that a
second same-name type in the lent registry only refuses. CHANGELOG entry for the cacheless
claimant; stale comments on the store's owns predicate and WriteDocument's registry doc fixed.

Builds not yet run when committed; verified on Yggdrasil before push.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 08:19:21 +01:00
Meta Vens
50a4d73f29 Tests: a gate stage that prints no REFLIST-SUMMARY line fails by name instead of aborting
summary_of ended in a grep that exits 1 on no match; under set -e that killed the script before it named the failed stage. With the
head ref-list test red (owns-declares-only) the gate exited 1 naming nothing; it now names head-ref-list and summary-diff.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 08:11:08 +01:00
Meta Vens
dcae9aa763 Tests: the 2.0.1 reader stage pins ten OldReaderGateProbe cases, not twelve
The five TestCaseSource tests each run over two sources (committed, live): ten cases, plus the one OldReaderRefListProbe case. The
first run of the count check reported 10 and 1.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 08:03:17 +01:00
Meta Vens
703786f40d Tests: close the 2.0.1 ref-list probe's method (it did not compile at the previous commit)
OldReaderRefListProbe.cs is staged into the 2.0.1 tree by old-reader-refusal.sh and is not part of this tree's build; its method
lacked a closing brace at fd9bbaf4, which the gate's 2.0.1-reader stage reported.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 08:01:15 +01:00
Meta Vens
f41dc3d63b Tests: every gate stage asserts how many cases it ran
old-reader-refusal.sh pins the expected case count of each stage as a constant (C# stages from the TRX the run writes, by class; Rust,
Python and TypeScript from their own output) and fails naming '<stage>-count' on any other number, so a probe renamed out of its filter
or a skipped leaf test no longer passes with nothing run.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 07:59:19 +01:00
Meta Vens
7c7bafe30e Tests: regenerate the C2a gate vectors with the fixed clock
Only StoredAt moves (Soul s1 vec2.log); the writer is deterministic (two runs, identical trees). The directory page is renamed by its new
content hash. A README says how they are made and compared.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 07:59:07 +01:00
Meta Vens
fd9bbaf4a4 Tests: the ref-list gate compares schema ids after one write at both trees; the C2a writer takes a fixed clock
The 1.0.60 ref-list summary is taken after attach, an upsert of alpha, beta and the list reversed, and a flush, at 2.0.1 and at
head, and names records by schema id (the restamp-on-write ruling makes them equal). C2aGateWriter stamps every record with one
instant and compares the committed vectors byte for byte, the directory store as relative path and bytes with lock files left out.
The committed vectors are regenerated in the next commit, so TheCommittedVectorsAreWhatC2aWrites is red at this commit; it builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 07:57:29 +01:00
Meta Vens
338035eacb Tests: a record under an id its entry only lists is published by that entry
Kills the Stryker survivor FirstOrDefault to First in PublishedBy.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 07:46:17 +01:00
Meta Vens
b23ed3f1d6 Tests: a registry-less record write takes its one entry as claimant
Kills the two survivors of the claimant lookup over written entries (Named inverted, Owner dropped).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 07:25:50 +01:00
Meta Vens
6fb0e22c41 Tests: pin the unpublished-id rule at Owns (a store file cannot hold such a record)
ReadStore refuses a record whose schema the catalog does not publish, so the
file-level scenario the spec named cannot be built; the rule is pinned where it is decided.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 07:17:04 +01:00
Meta Vens
bf29ddb33d Caching: one claimant precedence; a cacheless writer picks the claimant its registry picks
CultDocumentRegistry.Claimant is now the only precedence that decides which entry
reads a persisted catalog entry, static over a lookup (a registry's indexes, or the
entries a registry-less cacheless write writes). ClaimantEntry is deleted. A cacheless
WriteDocument or WriteRecord lent a registry is never more permissive than a cache
registering the same types; an unpublished id is carried, not owned, through Owns' catch.
Fixes the four Low findings of variants:verdict:cut-restamp-on-write.s2.
Not yet verified on Yggdrasil when committed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 07:13:21 +01:00
Meta Vens
10d012186a Test: owned drift variants run on the single-file store with a codec
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 06:15:10 +01:00
Meta Vens
2137b10efb One ownership rule for cache and cacheless writers; pin owned drift variants and the cross-schema guard
Owns is now a static rule over (declared, claimantOf): a registry supplies both from its indexes, a cacheless writer supplies its one entry, so
the hand-written cacheless lambda is deleted and a renamed entry listing the writer's id is owned by both. The schema-name check is the
claimant selection and is pinned. Variant read-whole flag pinned for rewrite, flatten and remove.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 06:14:11 +01:00
Meta Vens
e6ffe28043 Test: a lossy drift record is refused before the store's lock is asked
Kills the staging-flag hand mutant that the apply half's refusal hid.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 05:43:02 +01:00
Meta Vens
f87d12b9ae Cut the dead StoredSchemaReadWhole defaults and Wrote sets; test the refusal text, the cacheless declaration and the unnameable claimant
Stryker found the true default and the two Wrote sets equivalent: a constructed or written record is stored under its type's declared id, so the flag is never asked. Not run at this commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 05:34:43 +01:00
Meta Vens
a768b821fc Tests: three gates are reached by a stale guess followed by a settled cache, ordered with the store's hooks
The spec's account (guess null, then a successful attach) takes two gates, not three: the guess gate is taken only for a non-null guess.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 03:54:12 +01:00
Meta Vens
2181a7461f Tests: the racing cache holds its records in a routed store
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 03:51:01 +01:00
Meta Vens
5d66bb0ad4 Tests: fill the racing cache through AddAsync
Does not build-verify at the previous commit (Upsert is not on CultCache).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 03:49:58 +01:00
Meta Vens
bcefcf9382 Tests: declared-lossy id constant; successful-churn gate test races an attach with a long pre-publish check
Not run at this commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 03:49:16 +01:00
Meta Vens
da951adce0 Tests: fixtures that were read-only because their type read the record whole now lose a slot; restamp tests fixed
The ForeignRecordTests read-only fixtures (another runtime's deck, the moving deck) had the same shape as the deck, which the
type now reads whole and owns; each gets a slot the deck lacks, so it is read only by dropping it. RestampOnWriteTests and the
successful-churn gate test are corrected from the first run. Not run at this commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 03:46:27 +01:00
Meta Vens
5036244778 Tighten the gate-bound tests: two gates under failing churn, exactly one when detached or settled, three reached under successful churn
Not built or run at this commit: verified on Yggdrasil at the cut's head.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 03:39:02 +01:00
Meta Vens
0fbc12275a Restamp on write: one ownership rule, Owns, under which a type that reads a stored record whole may write it
CultDocumentRegistry.Owns replaces Declares as the one answer to whether a writer may write, relabel or remove a record under a
schema id: the id is declared, or the type that reads it reads it whole (equal content hash, or compatible shapes with no persisted
slot ignored). Staging asks the declared half or CultStoredDocument.StoredSchemaReadWhole; the apply halves (single file,
directory, cacheless CultMesh) ask Owns over the durable catalog, once per distinct id. A record read only by dropping slots
stays read-only until its id is declared compatible.

Not built or run at this commit: verified on Yggdrasil at the cut's head.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 03:39:02 +01:00
Meta Vens
193cf1c39e Store gate: Cache owns the attach window; pin the three-gate bound; fix the unseen-cache wording
A cacheless write that re-enters its own store's hold now consults Cache first, so a journal's WriteDocument or WriteRecord gets the same refusal during an attach as after it (the attached text); the re-entry text no longer names an attach's pull. InStoreHold takes the store instead of its gate.
CacheBackingStore.GateTakes (internal, thread-static) counts the gates Gate takes; OneStoreCallTakesAtMostThreeGatesUnderFailingAttachChurn asserts at most three per call under failing-attach churn, which pins the stale-guess loop (M4b).
The contract and AddBackingStore say what holds: other threads may guess the tentative cache, but none runs a body against it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 22:35:58 +01:00
Meta Vens
74021e2326 Caching tests: after the refused journal call the attached store still pulls
The folded-in writedoc case used to assert the refusal left the attach's registry in place and a later PullAll succeeded; the per-entry-point test now asserts that for every entry point.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 22:08:06 +01:00