Skip to content

642 Storage SL5b allholonNodes fix - #657

Open
nphias wants to merge 3 commits into
mainfrom
642-storage-sl5b
Open

642 Storage SL5b allholonNodes fix#657
nphias wants to merge 3 commits into
mainfrom
642-storage-sl5b

Conversation

@nphias

@nphias nphias commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Whole-space discovery becomes ordinary graph traversal. Publishing a lineage writes
Holon ─OwnedBy→ HolonSpace and its HolonSpace ─Owns→ Holon inverse; get_all_holons_internal
reads that Owns collection instead of the AllHolonNodes path index. This is the
coordinator-owned replacement #631 §3 and §9 named as SL5b's precondition.

GetAllHolons, the legacy dance, the wire binding, and the TS SDK keep their contracts.

One semantic change: the LocalHolonSpace anchor is no longer in GetAllHolons results — it is
not a member of its own Owns collection (#642 §1, §9), so every DB count drops by one. Callers
that want the anchor use TransactionContext::get_space_holon().

AllHolonNodes is still written and all of its tests still pass. Nothing reads it, which makes this
a reversible checkpoint rather than a cutover.

Changes

commit_functions.rs — new persist_space_membership, called from commit_holon's ForCreate
arm immediately after persist_holon returns. It writes the OwnedBy and Owns SmartLinks
directly through the existing persist_smartlink, in the node pass.

Membership is deliberately not staged for the relationship pass. See the first note below — this
is the load-bearing decision in the PR.

staged.rsrelationship_collections_for_commit excludes OwnedBy from every scope. Storage
authors membership; the coordinator never replays it. A staged OwnedBy can still arrive (cloning a
saved holon carries its persisted membership into the staged map) and is dropped rather than
re-anchored to the clone or to a new version.

guest_holon_service.rsget_all_holons_internal resolves the space and delegates to the
existing fetch_related_holons_internal with Owns; no new traversal code. delete_holon_internal
gains retract_space_membership, deleting the Owns link on the space and the OwnedBy link on the
holon before the node delete. create_local_space_holon gains a comment recording that its staging
bypass is now load-bearing.

Reading through fetch_related_holons_internal is a small win: the old code built its collection
with add_references and no keys, whereas the Owns link's canonical key is the owned holon's
key — so the collection is now keyed from tag bytes with no hydration, which is what every
get_by_key consumer behind this call already wanted.

Contract docsholon_service_api.rs, holon_dance_adapter.rs, get_all_holons_dance.rs,
transaction_command.rs, transaction_wire.rs, map-sdk/.../transaction.ts, and
schema-src/commands/schema.tdl (with the generated JSON regenerated — a one-line diff). All said
"all persisted holons".

Fixturescount_saved() drops the + 1 for the anchor, carrying eight fixtures at once;
load_holons_internal_fixture's five hardcoded MapInteger(1) baselines become MapInteger(0);
ENSURE_DB_EMPTY and the inline "+1 for the space holon" comments corrected. New
partial_commit_membership_fixture — see Testing.

Notable decisions

  • Membership is authored in the node pass, beside persist_holon. This is where the design
    landed after two earlier attempts, and the reason matters. Membership is what whole-space
    discovery reads, so a holon that publishes without it is persisted and permanently invisible —
    something AllHolonNodes could not produce, because it indexed inside PublishRoot.

    Staging the edge for the relationship pass reintroduces exactly that split. The relationship pass
    is skipped outright whenever any staged holon fails to publish, so a commit of two holons where
    one is rejected leaves the other published and unowned, with nothing to repair it later. Ordering
    OwnedBy first within the pass — which an earlier revision of this PR did — narrows the window
    but does not close it. Writing membership beside the node write restores the coupling
    unconditionally.

  • The coordinator never replays membership. Since storage authors it, replaying a staged copy
    can only do harm: a version-producing commit replays the full scope against the new version's
    id, which would make the space own the lineage root and every version after it separately (Storage SL5b — Replace AllHolonNodes with HolonSpace ownership #642
    §8 rejects re-anchoring per version). Excluding OwnedBy from every scope is one filter and
    covers the version case, the clone case, and any future path that stages it.

-resolve_inverse_relationship_name never sees OwnedBy, so the descriptor
short-circuit added for it is gone and the descriptor system is back to having no exceptions.

  • Deletion retracts membership both ways. delete_holon_node deletes only the path link and the
    entry; SmartLinks survive it, which would leave deleted holons discoverable (Storage SL5b — Replace AllHolonNodes with HolonSpace ownership #642 §9). The
    retraction lives in delete_holon_internal, not the persistence layer, which is deliberately
    descriptor-unaware.

  • A latent harness bug surfaced. FixtureHolons::counts() charged a deleted holon saved -= 1
    in addition to its head no longer counting as Saved. The old anchor allowance cancelled it
    exactly, which is why it went unnoticed and why delete_holon_fixture's post-delete assertion was
    commented out with a TODO. Deleted now contributes nothing and that assertion is enabled — it is
    how the retraction above is tested.

  • The saved-content comparator ignores OwnedBy. assert_saved_content_eq refused to compare an
    undescribed actual holon carrying any relationship content, and every saved holon now carries
    membership. Infrastructure-supplied edges never appear in fixture snapshots — the same reasoning
    that already tolerates commit-materialized inverse SmartLinks there.

  • all_holon_nodes.rs and its mod.rs wiring; index_under_all_holon_nodes and its PublishRoot
    call; ALL_HOLON_NODES_PATH; LinkTypes::AllHolonNodes and its four dispatch arms; both validators,
    the AllHolonNodesDelete rejection, and their re-exports; the all_holon_nodes_delete_for_test
    probe and the RootIndexLinkType::AllHolonNodes variant; both coordinator-surface.toml
    [[export]] blocks; and the AllHolonNodes tests and table legs. mock_conductor.rs's liveness
    probe calls the get_all_holon_nodes extern purely as a callability check and needs repointing.

  • validate_root_index_create and the shared rejection variants stay — LocalHolonSpace still uses
    them (Storage SL5 — Retire Obsolete Persistence Indexes #631 §9). Removing the enum variant renumbers LocalHolonSpace 1→0 and SmartLink 2→1 and so
    changes the DNA hash: the same accepted consequence as SL5a, inert by construction since the enum is
    the single source of truth for both the write and the read of every link.

Testing

The write and retract paths are both directly exercised, which matters because discovery now
depends entirely on them:

  • Create. Every ensure_database_count step pins membership exactly, now that the anchor
    allowance is gone: pre-commit steps assert the anchor is excluded, post-commit steps assert new and
    cloned lineages appear, and stage_new_version_fixture asserts a version adds no member.
  • Partial commit. partial_commit_membership_fixture (new) stages two holons, one carrying more
    properties than PVL permits, so its PublishRoot is rejected and the commit reports Incomplete
    before the relationship pass runs. It then asserts the other holon is still an owned member. This
    is the case the earlier staged-membership design got wrong; the fixture was confirmed to fail
    against that design and pass against this one.
  • Delete. delete_holon_fixture's post-delete count assertion, re-enabled here, asserts the
    deleted holon is gone from GetAllHolons — the retraction's only test, and the reason the harness
    counting bug above had to be fixed.

Not measured: the Owns fan-in cost. Every inverse Owns link is based on the space holon, and
put_smartlink scans all live links on the base for conflict detection — so a 191-holon core-schema
load is ~O(n²) tag decodes against one base. Numbers on this branch: dance_tests 144.9s,
holon_storage_tests 68.8s, pvl_validation_tests 47.9s, smartlink_tests 19.1s. A before/after
comparison still needs a baseline run on the parent commit. This is the open SL3 candidate-scan cost,
now on a hot path; conflict-detection semantics were deliberately left alone.

Environment note. The three workspaces share one target/; running cargo outside
nix develop mixes rustc versions and the next nix-side build fails with E0514 plus misleading
cannot find type X errors in untouched files. Also, npm run sweet:test skips the WASM rebuild and
the audit.

Scope

Unchanged: QueryExpression, QueryDance, query planning (#642 §5); any new public whole-space
query API; key or type indexes; the core-schema JSON inputs beyond one regenerated command
description; persistence_layer::smartlink and the Tag v1 codec; LocalHolonSpace bootstrap
behavior; exact-version reads and Storage SL2 record behavior.

OwnedBy and Owns still set neither IsDefinitional nor AllowsDuplicates in the TDL. Nothing
reads them — storage authors membership directly and the coordinator never resolves it through
descriptor policy — so it is not blocking, but it is a trap for anyone who later routes ownership
through that policy.

Still open, unaffected: the put_smartlink candidate-scan cost (SL3), now more load-bearing than
before, and the reference-layer/storage disagreement over what "the same link" means (SL4).

@nphias nphias linked an issue Aug 23, 2026 that may be closed by this pull request
11 tasks
@nphias nphias changed the title allholonNodes fix 642 Storage SL5b allholonNodes fix Aug 24, 2026
@nphias
nphias marked this pull request as ready for review August 24, 2026 15:17
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.

Storage SL5b — Replace AllHolonNodes with HolonSpace ownership

1 participant