npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agent-plexus/conformance

v0.2.1

Published

Conformance suites for agent-plexus ports and host hooks: prove an adapter behaves

Readme

@agent-plexus/conformance

Conformance suites for the agent-plexus ports and host hooks: one suite per port that proves an adapter behaves as its port page says.

npm install --save-dev @agent-plexus/conformance @agent-plexus/core
import assert from 'node:assert/strict';
import { test } from 'node:test';
import { checkAdapter } from '@agent-plexus/conformance';
import { adapter } from '../src/index.ts';

test('adapter passes conformance', async () => {
  const report = await checkAdapter(adapter, { options: { greeting: 'Hi' }, fixtures: { inputs: ['hello'] } });
  assert.deepEqual(report.failures, []);
});

checkAdapter(descriptor, { options, fixtures, ctx }) checks the descriptor (D1, D2), creates the adapter with options the way assemble does (D3: options schema and limits) and runs the suite of what it fills; it closes the instance. conformance(fills, instance, fixtures) runs one suite on an instance. The suites never throw: a report lists failures, skipped (checks that need a fixture or an operation the adapter does not have), warnings (notes that fail no rule, such as a deprecated ext key) and the rules evaluated.

Every failure starts with the id of the rule it breaks. A known gap of an adapter is marked in its test, without weakening the rest:

test('passes ExecutionPort conformance', async (t) => {
  const report = await checkAdapter(adapter, { options });
  assert.deepEqual(failuresExcept(report, 'E14'), []);
  await t.test('E14: close settles the pending waits', { todo: 'close leaves pending waits' }, () => {
    assert.deepEqual(failuresOf(report, 'E14'), []);
  });
});

Suites

| Fills | Suite | Fixtures | |---|---|---| | ExecutionPort | checkExecution | reopen (durable), secondInstance, exclusive, lease, alive | | TopologyPort | checkTopology | kinds (default: the adapter's kinds) | | MemberPort | checkMember | inputs, wait, reply, slow, checkpoint, promptMs, ctx | | RegistryPort | checkRegistry | ids, filters; the members come from ctx.members (default SAMPLE_ENTRIES) | | AgentRouterPort | checkRouter | cases ({ input, candidates?, expect? }) | | AttributionPort | checkAttribution | cases ({ input, expect }): the adapter's rules table | | Host | checkHost | member, denied, caller, other, othersMayResume, audience, block, score |

A topology runs on fake members through fakeScope, a RunScope that records every call and route, and queues calls beyond maxParallel as the core does. It is exported for an adapter's own tests.

Rules

| Id | Rule | |---|---| | D1 | The descriptor passes the core's checkDescriptor and has an options schema | | D2 | Every top-level limit (options.<name>) is described by the options schema | | D3 | The adapter is created from options, validated as a system config would validate them | | E1 | A step runs once and replays: in the same execution, after a new begin, after a restart (reopen) | | E2 | Step results are JSON clones; undefined replays as undefined; a value JSON cannot hold rejects and stores nothing | | E3 | A fn that throws stores nothing and the step rejects; a later call runs fn again | | E4 | Concurrent calls of one step share one run of fn | | E5 | The core's key formats (call:root.steps[1]:0#1, <key>:task, <key>:reply:<n>, run:*) and run ids of 128 characters | | E6 | fn may call recall and remember on its run without a deadlock; a key kept as null recalls null | | E7 | A signal before its wait is returned, also past the deadline; a later signal releases every pending wait; a deadline gives undefined; an invalid untilAt rejects | | E8 | First signal wins: a second one is false before and after the wait; of two concurrent ones exactly one is true, also across instances; an unknown run rejects | | E9 | put returns a new key per text; read returns it, also after the run ended; an unknown key is undefined | | E10 | remember keeps a clone, a later one replaces it, recall returns a clone; runs are isolated; values survive begin and a restart; a value JSON cannot hold or an empty key rejects | | E11 | begin resumes a run that ended, whatever its status, and resets nothing | | E12 | An exclusive adapter rejects a second holder with RUN_BUSY until end, release or close; a hold expires; the old holder's writes are then refused | | E13 | An adapter that can reject with RUN_BUSY implements release, which keeps the run as it was | | E14 | A pending wait does not keep the process alive; close settles pending waits | | T1 | kinds is a non-empty list of known kinds; bind rejects another kind, naming it and its path | | T2 | Members only through scope.call, routers only through scope.route, both with a node path | | T3 | Node paths follow the documented forms, differ between call sites, are the same on every run | | T4 | Branches that finish in another order give the same result and the same calls | | T5 | A waiting result passes through every supported kind with its wait unchanged | | T6 | route: the chosen member with the decision, failed decisions, fallback, nobody; handoff: optional routing, ends on nobody, fails on failed | | T7 | loop, handoff and graph stay within their bounds and stop with code limit | | T8 | Concurrent calls pass shares that sum to at most 1; join: "first" aborts and abandons the other branches | | T9 | Every result is valid; input: "original" gives a node the system's input | | M1 | describe returns a valid entry, with trust booleans, the same each time | | M2 | invoke returns a known status, a text output, a reason with a code unless completed, namespaced ext (the protocol keys plexus.delegate and plexus.handoff allowed; the bare delegate and handoff of 0.1.0 are warnings) | | M3 | An aborted signal ends the call promptly, stopped with code aborted, before or during the call | | M4 | The call's credential never appears in a result or an entry | | M5 | A checkpointed taskRef is a non-empty string of at most 1024 characters; a member that checkpoints has resume | | M6 | A waiting result has code needs_input or needs_auth and a handle; resume answers it | | M7 | cancel settles once its signal fired | | M8 | usage and costUsd are non-negative | | M9 | The descriptor declares capabilities, and they match the instance | | M10 | A result's reason.layer, when set, is member: a member's own layer name goes in reason.memberLayer | | R1 | list returns valid entries, ids not repeated | | R2 | get returns the entry list returns; an unknown id is undefined | | R3 | Filters (skills, tags, attrs) behave as the spec says and are not changed | | R4 | Every entry carries trust with booleans | | R5 | ext keys are namespaced | | A1 | A decision is an object naming a candidate or none | | A2 | ranked lists only candidates, once each, with finite scores | | A3 | route does not change the question (frozen) | | A4 | route never reads the caller's credential | | A5 | reason is a string; no candidates means no member; the cases table holds | | At1 | An empty record of a completed run gives no attribution | | At2 | An attribution has a valid layer, a confidence in [0, 1], evidence strings, by, and names hops of the record | | At3 | Abandoned hops are skipped | | At4 | needs_input, needs_auth and aborted give no attribution | | At5 | Stored texts and detail never reach an attribution | | At6 | Only reason.code drives: detail and by change nothing | | At7 | A source that fails is ignored | | At8 | The adapter's cases table holds | | H1 | name is set and tier is prototype or production | | H2 | allow answers allow, deny or ask for invoke questions | | H3 | Only the owner resumes a run (same id, kind and delegates), unless the host says otherwise (othersMayResume) | | H4 | A token is never the caller's own credential | | H5 | check answers allow, block or redact with text; the block fixture is blocked | | H6 | Telemetry never throws; span returns what fn returns and rejects with its error | | H7 | Scores are in [0, 1] | | H8 | state keeps and returns clones; a deleted key reads as undefined | | H9 | An approved answer does not turn a deny into an allow | | S1 | In a system: a run that waits, then a resume that answers it (on a system assembled again when durable) | | S2 | In a system: a parallel run on a budget completes within it (skipped only when the topology adapter does not run parallel) | | S3 | In a system: a run's record can be attributed |

System level

checkSystem(descriptor, { adapters, options, durable }) assembles the adapter under test with the reference adapters given in adapters (a topology, an execution and an attribution, unless it fills one of them) and fake members, then runs S1-S3. A MemberPort adapter runs as a member of that system.

How to write an adapter: CONTRIBUTING.md, starting from examples/adapter-template.

Requires Node >= 22.18. License: MIT.