feat(kernel-utils): add described*() combinators for guard+schema authoring#958
Open
grypez wants to merge 4 commits into
Open
feat(kernel-utils): add described*() combinators for guard+schema authoring#958grypez wants to merge 4 commits into
grypez wants to merge 4 commits into
Conversation
4 tasks
Contributor
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
d7220eb to
b8ac175
Compare
…horing
Add a `./described` export whose combinators author an `@endo/patterns`
interface guard and a matching `MethodSchema` from a single source. The
combinator namespace is exported as `S` (mirroring `@endo/patterns`'s `M`):
each leaf (`S.string`/`number`/`boolean`/`arrayOf`/`record`/`object`/`nothing`)
yields a `{ pattern, schema }` pair; `S.arg` names a positional parameter; and
`S.method` / `S.interface` assemble them into a `{ guard, schema }` / `{
interfaceGuard, schemas }` ready to splat into `makeDiscoverableExo`.
Because the enforced pattern and the descriptive schema are projected from the
same authored leaves, their conformance is a construction invariant rather than
an after-the-fact check. Method guards use `M.callWhen(...).returns(...)` (exo
methods are invoked across an eventual-send boundary) and the interface guard
sets `defaultGuards: 'passable'` so the injected `__getDescription__` is allowed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
b8ac175 to
6bc1fee
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6bc1fee. Configure here.
…ir guards
Resolve two review findings on the described() combinators:
- S.object is documented as a closed/shaped object but M.splitRecord defaults
its rest pattern to M.any(), so neither the pattern nor the schema rejected
extra keys. Close both: pass an empty-record rest pattern and emit
additionalProperties: false (which routes jsonSchemaToStruct through its
strict branch).
- S.method emits optional trailing args via M.callWhen(...).optional(...), but
MethodSchema could not express optionality, so methodArgsToStruct and
method-schema-convert treated every arg as required. Add an optional
`required` field to MethodSchema (mirroring object JsonSchema's `required`),
populate it from S.method, honor it in methodArgsToStruct via a `{ required }`
option, and map it to ValueSpec.optional in method-schema-convert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The converter now emits optional parameters from `MethodSchema.required`; record that consumer-observable change under the unreleased section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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
Adds a
./describedexport whose combinators author an@endo/patternsinterface guard and a matching
MethodSchemafrom a single source, so adiscoverable exo's enforced shape and its
__getDescription__hint cannotdrift.
The combinator namespace is exported as
S(mirroring@endo/patterns'sMand
@endo/eventual-send'sE).Dwas avoided because it reads as liveslots'D()device operator to readers familiar with that codebase.Sis the singleauthoring surface — there are no bare combinator function exports:
S.string/S.number/S.boolean/S.arrayOf/S.record/S.object/S.nothingeach yield a{ pattern, schema }pair.S.argnames a positional parameter.S.methodandS.interfaceassemble them into{ guard, schema }/{ interfaceGuard, schemas }, ready to splat intomakeDiscoverableExo.Because the enforced pattern and the descriptive schema are projected from the
same authored leaves, their conformance is a construction invariant. Method
guards use
M.callWhen(...).returns(...)(exo methods are invoked across aneventual-send boundary) and the interface guard sets
defaultGuards: 'passable'so the
__getDescription__method injected bymakeDiscoverableExois allowed.Optional arguments must be trailing (enforced by
S.method).Before this PR
After this PR
Test plan
yarn workspace @metamask/kernel-utils test:dev:quiet(304 pass, incl. 13 newdescribedtests)yarn workspace @metamask/kernel-utils buildyarn workspace @metamask/kernel-utils lintNote
Low Risk
Additive API and schema metadata; behavior change is limited to optional-arg validation/conversion where
requiredis set.Overview
Adds
@metamask/kernel-utils./described(and rootS) so discoverable exos can author@endo/patternsguards andMethodSchemafrom one definition, avoiding drift between membrane enforcement and__getDescription__.Sexposes leaves (string,number,boolean,arrayOf,record,object,nothing),S.arg,S.method(asyncM.callWhen, trailing optional args), andS.interface(defaultGuards: 'passable'for injected description).MethodSchemagains optionalrequired;methodArgsToStructhonors it for Superstruct validation.service-discovery-typesmethodSchemaToMethodSpecnow marks parameters not inrequiredasoptional.Reviewed by Cursor Bugbot for commit af20bba. Bugbot is set up for automated code reviews on this repo. Configure here.