feat(kernel-agents): author built-in capabilities as pattern-guarded exos#959
Open
grypez wants to merge 1 commit into
Open
feat(kernel-agents): author built-in capabilities as pattern-guarded exos#959grypez wants to merge 1 commit into
grypez wants to merge 1 commit into
Conversation
4 tasks
Contributor
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
707aa13 to
d7220eb
Compare
fc7d58e to
9e110e2
Compare
d7220eb to
b8ac175
Compare
6c6abee to
620c437
Compare
b8ac175 to
6bc1fee
Compare
620c437 to
1812ca4
Compare
…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>
1812ca4 to
06d6853
Compare
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
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.Follow-ups (out of scope here)
S.interface's return type to its method-name keys (DescribedInterface<Method>) so an implementation/schema name mismatch is caught at compile time, not just by the runtime construction check above. Purely a type change; toucheskernel-utils/described.ts.enumsupport to the capability schema sogetMoonPhasecan advertise its allowed return values.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.