Skip to content

feat(kernel-utils): join - #1053

Draft
ci-belphegor wants to merge 1 commit into
grypez/narrowing-6-narrowfrom
grypez/narrowing-7-join
Draft

feat(kernel-utils): join#1053
ci-belphegor wants to merge 1 commit into
grypez/narrowing-6-narrowfrom
grypez/narrowing-7-join

Conversation

@ci-belphegor

Copy link
Copy Markdown

Explanation

join({ name, refs }) returns a narrowing of its operands' common base admitting exactly what any of them admits. Variadic; the result's method set is the union of the operands', and where two operands name the same method each argument position is disjoined.

Every ref must carry a provenance record naming the same base — a ref the library did not mint throws. That is what makes the operation sound: each operand's guard is AND(guard(base), X) by construction, so OR-ing the deltas stays ⊆ the base with no pattern subtyping needed.

The unnarrowed base is a legal operand and absorbs, contributing { method: [] } for every method in its guard. Absorption therefore falls out of the algebra rather than needing a branch.

Unmarks one ratchet case.

Notes for reviewers

The missing-method versus hole rule is one rule, not two, because two read as an inconsistency: a join is a union of authority, so a method absent from an operand contributes the empty set (and survives at the other operand's delta), while a hole contributes everything (and leaves that position unconstrained). A position past the end of a delta is a hole.

disjoinDeltas sits directly below conjoinDeltas so the asymmetry is visible: the OR dual takes the union of keys, whereas conjoinDeltas takes its keys from one side, because narrowing must not restore authority an intermediate narrowing dropped.

One deviation from the design doc, documented in the JSDoc rather than left to be discovered. The doc says the unnarrowed base "is a legal operand and absorbs." It absorbs only in company: the common base is discovered from a minted ref's record, and an unminted ref is recognizable as that base only by identity against it. So a call whose refs are all unminted throws — refs: [] and the degenerate refs: [base] included. Refusing beats trusting an unminted ref to be a base it cannot confirm; supporting the degenerate case would need a guard fetch for a call that means "copy the base."

Probing all four directions rather than just the case's own assertion: ok:read:srv/logs/y, ok:read:srv/data/x, and rejections for ["etc","passwd"] and ["srv","logs","..","etc"] against Must match one of [splitArray([srv,data],…), splitArray([srv,logs],…)].

Stack

PR 7 of 12. Base: #1052.

Return a narrowing of the refs' common base admitting whatever any of them
admits: the method set is the union of the operands', and where two name
the same method each argument position is disjoined.

disjoinDeltas sits beside conjoinDeltas as its dual, and the asymmetry is
the whole missing-method rule. A join is a union of authority, so its keys
are the union of both sides: a method absent from an operand contributes
the empty set and survives at the other operand's delta, while a hole
contributes everything and leaves that position unconstrained. Narrowing
is the opposite, which is why conjoinDeltas takes its keys from one side.

The base is a legal operand and absorbs, so the lattice has a representable
top and a fold needs no special case. It is recognizable only by identity
against a minted ref's record, so a call whose refs are all unminted throws
rather than trusting one of them. The result records the same base and the
disjoined delta, so a join can be narrowed or joined again.

narrow and join now share the minting step, since join needs the same
derive-forward-record sequence against a guard it already holds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ci-belphegor
ci-belphegor force-pushed the grypez/narrowing-7-join branch from 203b1df to 16c884f Compare September 11, 2026 11:42
@ci-belphegor
ci-belphegor added this pull request to stack #1060 September 11, 2026 11:44
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