diff --git a/packages/cultmesh-ts/README.md b/packages/cultmesh-ts/README.md index ea67efe3..5a4e73b7 100644 --- a/packages/cultmesh-ts/README.md +++ b/packages/cultmesh-ts/README.md @@ -108,6 +108,20 @@ reactive.update(draft => { }); ``` +`node.get`, `node.getRequired` and the value `node.put` resolves to return the +object the node's cache holds, not a copy: two reads of one record return the +same object. That object belongs to the cache and must not be mutated. Mutating +it changes what later reads see without writing anything to the store. To +change a document, build a new value (or use a writer) and put it: + +```ts +const held = station.getRequired(stationStockDocument, "station:starbridge:stock"); +await station.put(stationStockDocument, "station:starbridge:stock", { + ...held, + availableMissiles: held.availableMissiles - 4, +}); +``` + State pointers are the same kind of managed surface for UI and tools. They can advertise source documents, inherit a Verse route when bound, and resolve through that Verse without caller-side context plumbing: diff --git a/packages/cultmesh-ts/test/cultmesh.test.ts b/packages/cultmesh-ts/test/cultmesh.test.ts index c513503d..99e44a31 100644 --- a/packages/cultmesh-ts/test/cultmesh.test.ts +++ b/packages/cultmesh-ts/test/cultmesh.test.ts @@ -3074,6 +3074,24 @@ test("CultMesh TS reads remote RUDP snapshots through document handles", async ( } }); +// What ships (F8): a node's reads and puts return the object its cache holds, not a copy, and the README says that object +// belongs to the cache. The caller's own value is never the one held. +test("CultMesh TS node reads and puts return the cache's own object", async () => { + const node = await CultMesh.startNode( + join(await mkdtemp(join(tmpdir(), "cultmesh-ts-held-object-")), "node.ccmp"), + { documents: [noteDocument] }, + ); + const written = { noteId: "note:held", body: "held" }; + const put = await node.put(noteDocument, "note:held", written); + assert.notEqual(put, written); + assert.deepEqual(put, written); + assert.equal(node.get(noteDocument, "note:held"), put); + assert.equal(node.getRequired(noteDocument, "note:held"), put); + assert.equal(node.get(noteDocument, "note:held"), node.get(noteDocument, "note:held")); + written.body = "changed by the caller"; + assert.equal(node.getRequired(noteDocument, "note:held").body, "held"); +}); + test("CultMesh TS syncs remote RUDP snapshots into a local node", async () => { const connectionId = 0x1020304a; const source = await CultMesh.startNode(