Repository navigation
[REFACTOR] the advertised surface is the implemented surface - #1
Merged
Merged
Conversation
This was referenced Sep 25, 2026
Merged
`AIToolStateTransfer` was designed, tested and documented, and orrery never called it: `ToolCapability.stateTransfer` has zero call sites in orrery's Sources, while `initialize` advertised `tool/copyLoginState` and `tool/copyNonLoginSettings` to every plugin author who asked. A capability is a promise that the host calls it. Advertising one nothing redeems means someone implements those two methods, ships them, and is never invoked. So the method set now contains only what orrery projects today: `tool/describe`, `tool/listIdentities`, `tool/showIdentity`. The protocol version does not move — a host that never called these cannot notice, and a plugin that implemented them was already talking to nobody. The README was wrong in both directions, which is the more useful half of this. It documented `tool/accountInfo` and `tool/credentialCopy`, neither of which ever existed under those names, and drew `accountInfo` as a member of `AITool` — where identity has never lived, precisely so that a tool which cannot answer can be seen not to conform. Meanwhile `AIToolIdentityReporting` and `LoginIdentity`, the two types actually in the surface, appeared in no diagram at all. Both diagrams now name what the code names. `Reads degrade, writes abort` keeps its section and loses its example. The rule decides the shape of the first write that gets added, so deleting it would throw away the reasoning; illustrating it with a method that does not exist is the thing being removed. It now says plainly that every method in the surface is a read. A test pins the advertised set whole rather than by presence. The old one asserted `tool/describe` was there, which no addition could ever fail. Verified by adding a method and watching it fail, then removing it again.
The exactness test added here uses an identity-only fixture, so it cannot see the account methods at all — a seventh could be added and nothing would fail. This pins the set an account-owning tool advertises. Verified it discriminates: adding a capability fails it immediately. A test that cannot fail is decoration, and this one exists precisely so that adding a method means updating a test, which is where documenting it gets remembered.
gradyzhuo
force-pushed
the
refactor/surface-matches-implemented
branch
from
September 29, 2026 07:29
8bc402a to
eeea146
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.
The method set now contains only what orrery actually projects:
tool/describe,tool/listIdentities,tool/showIdentity.Why
AIToolStateTransferwas designed, tested and documented — and orrery never called it.ToolCapability.stateTransferhas zero call sites in orrery'sSources, whileinitializeadvertisedtool/copyLoginStateandtool/copyNonLoginSettingsto every plugin author who asked what they could implement.A capability is a promise that the host calls it. Advertising one that nothing redeems means someone implements those two methods, ships them, and is never invoked.
The protocol version does not move. A host that never called these cannot notice, and a plugin that implemented them was already talking to nobody.
This is not "orrery does not need state transfer." orrery copies login state on every account setup —
ToolSetupRunnercallsToolFlow.copyLoginState/copyNonLoginSettings, with real implementations inClaudeFlow,CodexFlowandGeminiFlow. That feature exists and works; it is simply not projected onto the plugin boundary. The method set is the projection of what orrery routes through a plugin, and state transfer is not routed that way yet. When it is, the method comes back — with a call site.The README was wrong in both directions
This is the more useful half of the change.
tool/accountInfoandtool/credentialCopy— neither ever existed under those names.accountInfoas a member ofAITool, where identity has never lived. That separation is deliberate: a tool that cannot answer must be visibly non-conforming rather than silently returning nothing.AIToolIdentityReportingandLoginIdentity— the two types actually in the surface — appeared in no diagram at all.Both diagrams now name what the code names.
Reads degrade, writes abortkeeps its section and loses its example. The rule decides the shape of the first write that gets added, so deleting it would throw away the reasoning; illustrating it with a method that does not exist is the thing being removed. It now states plainly that every method in the surface today is a read.Drift protection
The old capabilities test asserted
tool/describewas present, which no addition could ever fail. A new test pins the advertised set whole:Verified by temporarily adding a method and watching it fail, then removing it — a test that cannot fail is decoration.
Verification
74 tests pass. Net −409 lines.
Downstream
orrery pins
exact: "0.0.1-dev.9", which still has the protocol, so nothing breaks until the pin moves. Once this lands and a0.0.1-dev.10tag exists, orrery's own dead plumbing comes out in a separate PR:RemoteAITool.stateTransfer, itsinitializecapability check, andToolCapability.stateTransfer. That must land after orrery 3.5.5, which is mid-release and pins dev.9.🤖 Generated with Claude Code