omp packages

@mcsherrylabs/pi-evolver0.9.1

Pi agent extension: chain-generic tools over an Evolver node — read the chain, sign a transfer, administer what you own, write to a channel, submit a signed transaction. Wraps @mcsherrylabs/evolver-client; implements no wire format of its own.

GitLab CI/CD Published 10 days ago Apache-2.0 ~2.1K downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

@mcsherrylabs/pi-evolver

A Pi agent extension: chain-generic tools over an Evolver node. Read the chain, sign a transfer, administer what you own, write to a channel, submit a signed transaction.

It wraps @mcsherrylabs/evolver-client and implements no wire format or signing encoding of its own. It knows about no particular channel, ledger or service — a tool that names a channel belongs in that channel's own repository.

Specs: 161-pi-evolver-tools, 162-agent-write-coverage, 164-sign-channel-write.

Running the checks

Every check runs with one command (Constitution Quality Gate 10), from this directory:

Command What it pins
npm test everything below, after building the client. ⚠️ Held to it by check:packaging, which asserts that the check:* scripts, the test chain and this table name the same set — check:signing was declared, documented here as wired, and in no gate for eight days
npm run check:identity-keys Direct principal key lookup, absence and failed reads
npm run check:config the precedence rule — a project file may override the chain url and nothing else
npm run check:result the failure taxonomy — a transport error is never a refusal, fined is never committed
npm run check:principal a name that exists as the OTHER kind is wrong_kind, never absent — and a 404 group is null, not an empty one
npm run check:decode every transaction body decodes, through a reader written from the WIRE FORMAT rather than from the encoder it checks
npm run check:admin every signing verb signs and submits nothing, records what it composed, and refuses what the chain would only refuse by FINING
npm run check:amount amounts are strings out and bigint in, and the string is validated
npm run check:boundary scan coverage is a round window, never a row count
npm run check:signing signing does not submit
npm run check:bearer no tool takes or returns the signed transaction — submit and inspect work by id, and the artefact never reaches the transcript in any encoding
npm run check:heights the three heights a node reports mean three different things, and the read never collapses them
npm run check:coverage every tool the extension registers is exercised by a check, so a new verb cannot arrive untested
npm run check:surface no tool names a channel; a signing tool takes named typed fields only — and the ONE verb exempt from that is exempt by name and must refuse every core ledger id
npm run check:channelterms a channel's owners are OBJECTS and the SDK's type says so — scraped from the node's own JSON builder, elements AND container, with a scrape-broke control
npm run check:coreledger the core-ledger set is the one the node declares, scraped from its own source, with a scrape-broke control
npm run check:channelwrite a channel write refuses a malformed body, an oversized one and an unstated toll ceiling — and costs the same whatever its length
npm run check:ownership every signing verb is classified as ownership-changing or explicitly neutral; the node's identity is never guessed
npm run check:packaging the package declares an entry point that resolves
npm run check:registration loading the extension registers every tool
npm run check:signed-request evolver_signed_request against a REAL local relying party: a proof it verifies; a NO or no human signs and sends nothing; no placeholder chooses the destination; redirects are not followed; the prompt shows what is sent

⚠️ These now run in CI. ci/npm-test.sh is the last step of the test job and the root npm test includes this package, so a red pipeline is this package's problem. (That is a change from what this file said while issue #77 was open; a stale "CI does not run this" is how a gate stops being read.)

⚠️ npm test builds @mcsherrylabs/evolver-client first on purpose. The checks import it by package name, which resolves to its built output — without the build they would pass against stale bytes.

⚠️ The ownership report is a tripwire, not decoration

evolver_status reports what the configured identity owns. It should say none.

⚠️ AND THE AGENT CAN NOW END THAT ITSELF. Before 162 the only way this identity came to administer anything was somebody else adding it to a group. It can now create groups, admit members and hand groups over — so "owns nothing" stops being true by the agent's own action, and the no-confirmation decision that rests on it (161 FR-012a) has to be re-made rather than re-weighed when it does.

Nothing enforces that. Ownership is reported, never a precondition for signing: the chain is the authority — a non-owner's membership change is FINED and a transfer spends only the sender's balance — and a gate here would add nothing while coupling every signature to a paged walk of every channel owner on the chain. The status tool is the tripwire, and a human reading it is what notices. It is re-asked after any submission that can change the answer, so it will not keep reporting a state the agent has already left.

This package spends without asking for confirmation, and that decision is sound because the consequence of a mistake — or of an instruction injected through chain content the agent reads — is bounded by this identity's own balance. That bound holds only while the identity owns nothing.

"Owns nothing" is a state a stranger can end. A group owner may add any identity to their group without that identity's consent or knowledge, and membership of a group that owns a channel confers administration of it — changing its toll, its write policy, its availability policy, or releasing it. The likeliest route is not an attack but a favour: adding the agent to the group is the only way to let it write to that group's channel.

So if owns ever reports anything but none, the premise behind spending-without-confirmation has expired and that decision has to be made again rather than weighed again. Signing refuses outright if ownership cannot be determined at all — an authority question with no answer is not a yes.

Signing in to an off-chain service: evolver_signed_request

The transaction verbs sign for the chain; this one proves who we are to anything that verifies evolver 157 login proofs. The model fetches a challenge itself and passes it with the service's audience and the request to send, marking where the answer goes in the body or a header with {answer} or {answer.<field>}, so any request shape works. The SDK's signedRequest shows the human that request as it will be sent, escaped, with the host repeated last and warnings for plain http or an audience that does not name the host. The choice defaults to No. Only on yes does it sign, with target.signer, send the request itself (following no redirects), and return the response.

⚠️ The tool sends because a returned answer could be relayed. Anyone holding a 157 answer can redeem it at its audience, so a tool that handed one to the model would let text the model read route a genuine-looking login to whoever asked for it. The answer leaves the process only inside the one request the human approved, to the origin they saw. So nothing rendered comes back: the answer may not be placed in the URL (URLs are echoed in errors, Location and logs), a failure after signing reports the template and a fixed error class, and the signature is scrubbed from any Location or response body that echoes it.

⚠️ What is accepted, and recorded (openstar/evolver-meerkat#1):

  • The response goes to the model, and for a login it may be a session credential. A service that mints a token on sign-in hands it back, and the model then holds it. The prompt says so. A service that re-proves every call returns nothing redeemable.
  • The audience is the model's to choose, and it decides where a proof is valid. It is bound to the destination only by the human reading the prompt and a label-aligned audience/host warning. Binding audience to origin in configuration would close relay whatever the human does; it is the follow-up.
  • Plain http is warned, not refused, because the first relying party is served over http. An on-path party can read the answer and use it first.
  • It signs AND sends, against 161 FR-006 ("signing must not submit"). Returning the answer instead is the relay. check:surface 5c records the exemption by name.
  • The body is not signed, which is why the prompt shows it in full.

⚠️ In RPC mode the RPC client is the human. pi reports a UI there, and every yes/no is answered by whatever drives the RPC connection, which may be a program. Driving an agent over RPC makes that program responsible for every approval.

Configuration

.pi/agent/evolver.json in a project, or ~/.pi/agent/evolver.json globally.

⚠️ A project-level file may override the chain URL and nothing else. The identity, the key and how the endpoint is trusted come from the home-level file or the environment only — otherwise a repository you open could name a different signing key, and the only gate is a prompt about trusting a project.

What this package will not do

  • Name a channel, ledger or service in any tool.
  • Claim an identity. It is given one.
  • Accept a transaction body, ledger, kind or sender in a signing tool — a signing tool composes what it signs from named fields and pins the ledger itself. ⚠️ With exactly one exception, granted by name and paid for: evolver_sign_channel_write takes both, because a channel write HAS no named fields — the body IS the payload and the ledger IS the channel. What it buys the exemption with is a refusal: it will not sign for any ledger the node would INTERPRET (the six core ledgers and the whole reserved ce.evolver. namespace), because writing "opaque bytes" to the identity ledger is signing whatever that ledger'''s handler reads — a transfer, or a key registration.

Identity key lookup requires evolver-node v0.24.1 or later. The SDK getIdentityKeys(name) and pi evolver_keys read one principal directly; an absent principal is distinct from an empty key set, an unsupported route, or a failed read. Chain-wide explorer scans are no longer used for this lookup.