Commit graph

2,845 commits

Author SHA1 Message Date
Meta Vens
c8563e533f Single-file judge: the removals need not travel as checks (a removal has no upsert); pin the flatten and retype refusal texts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:39:26 +01:00
Meta Vens
2239fb9b5f Contract and CHANGELOG: a one-batch retype is an eviction then an add, a rebase follows the plain-write rule, the protected per-key judge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:29:21 +01:00
Meta Vens
1ff5ae79dc Validate: the key-home check needs no eviction exception (an evicted key's home is already in the batch's homes)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:26:50 +01:00
Meta Vens
edad333a4d RetypeEvictionTests: RbY lists RbX's real schema id; the refused-flush test refuses k1 under the lock
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:20:52 +01:00
Meta Vens
60474bd2b3 Single-file CommitBatch: a deleted key the batch also upserts reaches the judge as its removal half
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:19:56 +01:00
Meta Vens
ad51e45183 RetypeEvictionTests: pin the retype as an eviction, the variant and global retypes, the removal bookkeeping and the rebase rule
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:19:07 +01:00
Meta Vens
e19d98d0b8 A one-batch retype is the held record's eviction then the add, on every write path; the stores judge through one protected per-key judge
Delete StagedOperation.Replaces and Admit's replaced set. CultCacheBatch records the keys Remove named; Land evicts the held record at each (or checks the key when held by no one) and the add lands after it, so watchers, the globals copy, the variant guard, the key-home check, Claim, the store judges and the change journal see what they see when the two are staged apart. A Flatten after a Remove in the batch is refused as a flatten of a non-variant.

CacheBackingStore gains one protected RefuseUndeclaredOnDisk overload taking the catalog, the held record, the written entry and the removed keys; both shipped stores call it. The old overload and Undeclared stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:19:06 +01:00
Meta Vens
6f1930b354 ElementIdTests: pin the StoredPublishedBy guard through a push that relabels a loaded record in place
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 05:31:46 +01:00
Meta Vens
009de19879 WriteOwnershipTests: a removal is spent by the flush that judged it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 05:29:31 +01:00
Meta Vens
20be80cc23 Restore the codec-less variant test's cache; the one-batch retype test keeps the replacement through a later add of the batch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 05:16:32 +01:00
Meta Vens
3e283c81d4 Keep the StoredPublishedBy staleness guard and pin it: a record minting relabels in place is owned by a newer version that reads its current publisher whole
The probe (a throw where a loaded record is relabelled in place) tripped 32 existing tests, so
the guard is reachable, not dead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 05:14:10 +01:00
Meta Vens
36873e696e VariantTests: the store-less rebase test builds its cache with the codec
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 05:12:19 +01:00
Meta Vens
abf4f0387a WriteOwnershipTests, ForeignRecordTests, VariantTests: pin the one-batch retype, the store-less refusal, the late declarer's removal and the rebase refusal
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 05:11:09 +01:00
Meta Vens
e163e6b006 Retype in one batch or staged apart, and a store-less cache refuses it too
A removal followed by an add at the same key is a retype (variants:ruling:cache-refuses-retype):
the batch's staged add records that it replaces, the key is judged as the removal it names, and
the record lands. The store carries the same fact for removals the cache staged apart (Remove then
UpsertAsync), so the flush no longer reads the add as an upsert over the record it removed and
discards it. A cache with no backing store judges the upsert against the record it holds. The
variant plan's rebase-type check is deleted: write ownership refuses that retype first. The
StoredPublishedBy staleness guard is deleted (a loaded record is never relabelled in place).
Protected RefuseUndeclaredOnDisk doc states the per-key rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 05:11:09 +01:00
Meta Vens
cf9f8dc0e1 WriteOwnershipTests: a batch removal of a staged key is judged as a removal
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 04:31:46 +01:00
Meta Vens
d1032b1617 WriteOwnershipTests: judge a stale two-key batch per key; the unattached store cannot carry upserts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 02:45:17 +01:00
Meta Vens
0b147ea519 ForeignRecordTests, VariantTests: retype a key by removal and add, and a late type writes its own record
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 02:43:27 +01:00
Meta Vens
244ad2280e WriteOwnershipTests, WrittenOwnsTests: pin the per-key write predicate in both arms and both store kinds
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 02:36:17 +01:00
Meta Vens
340c9507e4 Write ownership by the written type: one per-key predicate, the registry leaves upserts
An upsert may replace the record at its key only when the type it writes there owns the record
(CultDocumentRegistry.WrittenOwns): the entry declares the stored id, or reads the stored entry whole
under its own schema name. Cache and cacheless writers, single-file and directory stores ask the same
per-key judge (CacheBackingStore.UndeclaredAt); a cache no longer replaces another registered type's
record. Registry.Owns is the removal/check rule only. Deleted: CatalogEntryLookup's registry half,
CultDocumentRegistry.Lookup, Owns<T>'s mayClaim, the per-batch union and the per-id memo.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 02:36:17 +01:00
Meta Vens
a4eae90561 Unity CHANGELOG: remote writes to a CultNetDatabaseServer need a granting authority
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 02:07:59 +01:00
Meta Vens
a924512e01 Garden path: remote writes need a granting authority (cut remote-write-authority)
Merges hands/garden-path-remote-write-authority (51ca81a1..1e73e206).
cultmesh-garden-path:cut_report:cut-remote-write-authority.h1/h2; Soul s1 and s2 hold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 02:07:44 +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
cf1e4f7a9d CultNetDatabaseServer: delete the ApplyPutAsync/ApplyDeleteAsync pass-throughs
A second public door named like the peer path with no caller besides the
handlers. Hosts keep CultNetDatabase.ApplyPutAsync/ApplyDeleteAsync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:44:09 +01:00
Meta Vens
4b3bb26e76 Garden path map: stage 1 rulings fill the model page; GP1 and F13-F17 for the remote write door
Every fork the model page waited on is ruled, so its cells now carry the
rulings. GP1 confirms at runtime that the database server applies a put
from a peer that carries no identity. F13-F17 record what the remote
write authority cut stands on: peers have no identity, refusal codes are
a coordinated cross-runtime enum, forwarding re-sends as a new client,
the door has no consumer outside CultLib, and the Rust document server
has the same gap. The cut sequence splits authority collapse into its
remaining lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:36:36 +01:00
Meta Vens
51ca81a1d4 AOT cut 1: consumers with the MessagePack generator on can declare CultRecordRef<T> members and keys
Merges hands/cultlib-aot-record-ref (b7a68884..3d4efc89).
cultlib-gaps:cut_report:cut-aot-record-ref-generator.h1, Soul verdict s1 holds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:19:05 +01:00
Meta Vens
16d68660de Write-ownership map: body facts across runtimes, authority table, cut sequence
Probed at b7a68884: only the C# cache arm retypes a key (cache {A,B}
replaces B's record with A); cacheless writes already refuse. TS, Rust
and Python key records by (type, key), so two types coexist at one key
and no leaf has a retype path; leaf parity needs key identity first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:08:03 +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
b7a68884c6 Land C2a: CultCache document variants, element ids and write ownership (3.0.0 Unreleased)
Merges hands/variants-c2a at 7605bd17. Verified at 463714c4 (code tree
identical): every C#, TS, Rust and Python suite green on Yggdrasil and the
old-reader refusal gate refusing in all four runtimes
(variants:cut_report:cut-land-c2a-main.h1, Soul variants:verdict:cut-land-c2a-main.s1).
No tag: tags, Unity plugin rebuild and the declared-range gate are the 3.0.0 release cut.
Non-building branch commits exist; bisect with --first-parent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:56:22 +01:00
Meta Vens
7605bd1777 C2a land map: steps 3 and 4 closed, step 5 held by Soul
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:56:04 +01:00
Meta Vens
463714c48f Land map: step 6 records the land is --no-ff and why; steps 1, 2 and 5 marked closed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:43:09 +01:00
Meta Vens
3157d4b325 Merge origin/main into hands/variants-c2a (docs and research only) 2026-10-27 23:42:49 +01:00
Meta Vens
7a7b76efdd Research: prior art for structural versus name-inclusive schema ids (serves variants store-identity question)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 18:34:41 +01:00
Meta Vens
723b799668 Caching docs: state exactly what a cacheless write owns and refuses
The CHANGELOG bullet, the persistence-contract paragraph and the registry param docs of WriteRecord and WriteDocument now list the two ways a record is owned and every refusal the code makes, including a stored entry that lists another registered type's id ahead of the written one's and a call that writes no entry. The registry-less Shared read is described as it is today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 18:24:16 +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
a731eaf3dc Research: prior art for a process-global default registry deciding write ownership (serves variants❓registryless-write-reads-shared)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 18:12:25 +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
be12d75a01 Map: claimant-one-owner r2 body facts (one description of the written type decides ownership)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:15: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