feat(kernel-utils): narrow default-guarded exos - #1054
Draft
ci-belphegor wants to merge 1 commit into
Draft
Conversation
A base built with makeDefaultExo carries defaultGuards: 'passable' and an empty methodGuards map, so there is no per-method guard to conjoin onto. Since 'passable' admits any passable arguments, the delta's patterns can be the whole guard: the result admits no more calls than the base did, and a delta of length 0 synthesizes M.callWhen().rest(M.any()).returns(M.any()), which admits exactly what the base admits. That makes narrow usable against the exos this repo actually builds. The base names no methods, so a delta naming one it does not implement is indistinguishable from one it does and can no longer be refused while narrowing. Calling it rejects with 'target has no method', which is what a caller holding no such authority must see. The error for a base that names its methods is unchanged, as is the one for raw defaults. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ci-belphegor
force-pushed
the
grypez/narrowing-8-default-guarded
branch
from
September 11, 2026 11:42
2d4b340 to
d2c3fc8
Compare
ci-belphegor
added this pull request to stack #1060
September 11, 2026 11:44
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
Most exos in this repo are built with
makeDefaultExo, which producesM.interface(name, {}, { defaultGuards: 'passable' })— an emptymethodGuardsmap, so there is no per-method guard to conjoin a delta onto. Without this PR,narrowcannot narrow almost any existing exo: 79 non-test files usemakeDefaultExoagainst 9 with explicit method guards.defaultGuards: 'passable'means every method admits any passable arguments, so for a method absent frommethodGuardsa delta of length n synthesizes:Sound on the same grounds as the general case: the synthesized guard admits no more calls than the base's own, and the method still forwards unaltered.
This replaces only the
defaultGuards: 'passable'arm of the error PR 5 left as a seam. Unmarks one ratchet case.Notes for reviewers
defaultGuards: 'raw'keeps throwing, deliberately. Raw guards pass arguments unmarshalled, which is not "admits any passable argument," so the soundness argument does not transfer. Theit.eachcase that previously covered the'passable'error now covers'raw', so the surviving arm keeps its coverage rather than quietly becoming untested.A length-0 delta is a proven no-op, not an approximation: the test pins the whole shape — zero required positions, zero optionals, and a rest guard admitting
'anything'and42. So it is ⊆ with equality, which is the claim the design needs.The cost, documented at the synthesis site. Such a base names no methods, so a delta naming one the base does not implement is indistinguishable from one it does, and no error can be raised at narrowing time. A misspelled method therefore mints a forwarder for a method that does not exist — which rejects at call time with
target has no method "..."rather than silently returningundefined. That is why PR 6 refused an optional call in the forwarding path.Probing past the case's own assertion shows the synthesized guard genuinely enforces, including
..rejection through the rest position:rejected:… ...rest: [0]: ".." - Must fail negated pattern: "..". AmakeDefaultExobase with no guards of its own ends up as tightly scoped as an explicitly-guarded one.Stack
PR 8 of 12. Base: #1053.