Uh oh!
There was an error while loading. Please reload this page.
feat(kernel-agents): author built-in capabilities as pattern-guarded exos - #959
Merged
Merged
Conversation
4 tasks
Contributor
Coverage Report
File Coverage
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grypezforce-pushed
the
feat/described-exo-combinators
branch
from
June 17, 2026 16:04
707aa13 to
d7220ebComparegrypezforce-pushed
the
feat/capabilities-as-discoverable-exos
branch
from
June 17, 2026 16:04
fc7d58e to
9e110e2Comparegrypezforce-pushed
the
feat/described-exo-combinators
branch
from
June 17, 2026 16:41
d7220eb to
b8ac175Comparegrypezforce-pushed
the
feat/capabilities-as-discoverable-exos
branch
2 times, most recently
from
June 18, 2026 15:37
6c6abee to
620c437Comparegrypezforce-pushed
the
feat/described-exo-combinators
branch
from
June 18, 2026 15:50
b8ac175 to
6bc1feeComparegrypezforce-pushed
the
feat/capabilities-as-discoverable-exos
branch
from
June 18, 2026 15:56
620c437 to
1812ca4Compare…exos
Rewrite the `math`, `end`, and `examples` capabilities as discoverable exos
built with the `described*()` combinators, so each capability's argument shape
is enforced by the exo's interface guard at invocation rather than only
advertised in the prompt. A mistyped argument now fails with a guard rejection
at the membrane instead of surfacing deep inside the capability.
Each module derives its `{ func, schema }` capability specs via a new
synchronous `makeInternalCapabilities` constructor, which builds the
pattern-guarded exo and projects a capability record from the just-authored
schemas — without round-tripping through `GET_DESCRIPTION`. The exo is kept
private as the in-realm enforcement membrane; internal capabilities are guarded
closures, not passable exos (to cross a boundary, publish an exo and `discover`
it). All existing consumers (example transcripts, e2e tests, the REPL
evaluator, prepare-attempt) keep the same spec shape and `makeEnd` stays
synchronous. `end`'s closed-over result object is intentionally left un-hardened
so the exo method can mutate it.
`makeInternalCapabilities` asserts at construction that the implementation and
schema method sets match exactly, so an authoring typo (an implementation
without a matching schema, which the guard's `defaultGuards: 'passable'` would
otherwise accept as an unreachable passable method) fails loudly instead of
surfacing as a capability that silently resolves to `undefined`. A colocated
`discover.test.ts` covers the positional-arg mapping, guard rejection at the
membrane, and this construction-time check.
`getMoonPhase` loses its (already unsupported, `@ts-expect-error`'d) `enum`
return hint; `end`'s off-spec per-argument `required` flags are gone, with
`final` required and `attachments` optional expressed by the guard.
Install the endoify mock as a package-wide vitest setup so capability modules,
which now build exos at import, have a `harden` global before they load.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>grypezforce-pushed
the
feat/capabilities-as-discoverable-exos
branch
from
June 23, 2026 18:01
1812ca4 to
06d6853Comparegrypez
marked this pull request as ready for review
June 23, 2026 18:45
Uh oh!
There was an error while loading. Please reload this page.
3 tasks
SherfeyInv pushed a commit
to SherfeyInv/ocap-kernel
that referenced
this pull request
Jul 29, 2026
…g enforcer (MetaMask#960) ## Explanation The base PRs ([MetaMask#958](MetaMask#958), [MetaMask#959](MetaMask#959)) made every built-in capability a pattern-guarded discoverable exo. Now that the exo's interface guard already enforces each capability's argument shape, this PR retires the parallel membraneless authoring and validation paths so the guard is the single argument enforcer: - Removes the `capability()` authoring helper and the internal `validateCapabilityArgs` validator (and its now-dead module). The chat strategy no longer re-validates arguments before invoking — it relies on the guard rejection it catches and reports as an `Error calling …` tool message. That catch is hardened to handle a non-`Error` rejection, so an invalid-argument tool call surfaces as a tool error instead of crashing the task (covered by a new regression test). - Collapses the redundant `CapabilitySchema` type into kernel-utils' `MethodSchema` (a capability's `schema` is exactly the `MethodSchema` its exo describes), removing the parallel type and its `ExtractRecordKeys` helper. - Adds a `test/make-method-capability.ts` helper that builds a guarded, discovered single-method capability from an `S.method`, and migrates the chat and JSON evaluator tests (and the capability test, repurposed to cover the surviving `extract*` helpers) onto it. - Drops the now-unused `@metamask/superstruct` dependency. ### Breaking changes - The `capability()` authoring helper is no longer exported from `@ocap/kernel-agents/capabilities/capability`. Author capabilities as pattern-guarded discoverable exos (via the `described*()` combinators in `@metamask/kernel-utils`) and convert them with `discover`. (`validateCapabilityArgs` was internal and never exported.) ## Test plan - [x] \`yarn workspace @ocap/kernel-agents test:dev:quiet\` (56 pass), incl. a chat-strategy regression test that an invalid-argument tool call comes back as an \`Error calling …\` tool message instead of crashing the task - [x] \`yarn workspace @ocap/kernel-agents-repl test:dev:quiet\` (178 pass) - [x] \`build\` + \`lint\` for both packages; changelog validates <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Breaking public API (`capability()` removal) affects downstream authors, but runtime behavior stays aligned with prior exo-backed builtins; main risk is consumers still using the old helper or assuming pre-invoke Superstruct errors. > > **Overview** > **Breaking:** Removes the exported `capability()` helper and the internal Superstruct-based `validateCapabilityArgs` path. Capabilities are expected to be authored as pattern-guarded discoverable exos (`described*()` + `discover` / `makeInternalCapabilities`); `CapabilitySpec.schema` is now kernel-utils `MethodSchema` instead of a parallel `CapabilitySchema` type. > > Invocation errors from the exo interface guard are normalized in `capabilitiesFrom` to `Error calling <name>(<params>): …` so chat and other callers can surface actionable tool messages without a second validation layer. The chat agent parses tool JSON locally when needed, invokes capabilities directly, and pushes guard/implementation failures as tool errors (including a regression test for bad args) instead of crashing the loop. > > Tests migrate to `test/make-method-capability.ts`; `@metamask/superstruct` is dropped from dependencies. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6dc44a8. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- 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 freeto 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
Rewrites the
math,end, andexamplescapabilities as discoverable exosbuilt with the
described*()combinators (added in #958, now onmain), soeach capability's argument shape is enforced by the exo's interface guard at
invocation rather than only advertised in the prompt. A mistyped argument now
fails with a guard rejection at the membrane instead of surfacing deep inside
the capability.
Each module derives its
{ func, schema }capability specs via a newsynchronous
makeInternalCapabilitiesconstructor, which builds thepattern-guarded exo (kept private as the in-realm enforcement membrane) and
projects a capability record from the just-authored schemas — without
round-tripping through
GET_DESCRIPTION. All existing consumers (exampletranscripts, the REPL evaluator,
prepare-attempt) keep the same spec shape andmakeEndstays synchronous.end's closed-over result object is intentionallyleft un-hardened so the exo method can mutate it.
makeInternalCapabilitiesasserts at construction that the implementation andschema method sets match exactly. A missing implementation already throws inside
makeDiscoverableExo, but an extra implementation absent from the schema wouldotherwise be silently accepted by the guard's
defaultGuards: 'passable'andnever be reachable as a capability — so an authoring typo (e.g.
serchvssearch) now fails loudly at construction instead of surfacing as a capabilitythat resolves to
undefined. A colocateddiscover.test.tscovers thepositional-arg mapping, guard rejection at the membrane, and this construction
check.
Installs the endoify mock as a package-wide vitest setup, since capability
modules now build exos at import and need a
hardenglobal before they load.Notable behavior changes
getMoonPhaseloses its (already unsupported,@ts-expect-error'd)enumreturn hint.end's off-spec per-argumentrequiredflags are gone;finalis required andattachmentsoptional, expressed by the guard.Test plan
yarn workspace @ocap/kernel-agents test(58 pass) andtest:dev:quietyarn workspace @ocap/kernel-agents-repl test(178 pass)build+lintfor both packages; changelog validateskernel-test-localagent e2e: see Agent-layer e2e tests should run inside a hardened kernel and assert via logs (not import agents into vitest under mock-endoify) #961 (out of scope here)Note
Medium Risk
Touches core agent capability invocation and changes runtime validation behavior (guard rejections vs deep errors), though external capability shapes and
makeEndsync API stay the same.Overview
Built-in
math,end, andexamplescapabilities are no longer hand-authored withcapability(); they are built via newmakeInternalCapabilities, which wraps implementations in a private pattern-guarded discoverable exo and projects the same{ func, schema }shape agents already use. Invalid or missing arguments are rejected at the exo interface guard before implementation code runs.discoveris refactored to sharecapabilitiesFromwith the local path so remote and in-realm invocation both map named-arg objects to positional exo calls the same way.makeInternalCapabilitiesalso fails at construction if schema and implementation method names do not match exactly.Tests cover mapping, membrane rejection, and the construction check; package vitest loads the endoify mock globally because capability modules build exos at import.
getMoonPhaseno longer advertises an unsupportedenumreturn hint;endoptional/required args are expressed only via the guard schema.Reviewed by Cursor Bugbot for commit 06d6853. Bugbot is set up for automated code reviews on this repo. Configure here.