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

@am_shork/attest

v1.6.0

Published

TDD-native spec framework: tests are the source of truth for verification, ID-bound requirements the source of truth for intent.

Readme

A TDD-native spec framework. Tests are the source of truth for verification; ID-bound requirements are the source of truth for intent. Attest binds the two by a stable ID and continuously detects drift.

  • Coverage — does every requirement have ≥1 scenario? (statically, or from the run)
  • Result — is every test green? (from the test runner)
  • Drift — do intent and assertions still agree? (static + runtime cross-check)

The killer move against drift: values a requirement promises (timeouts, limits, budgets) live once in its params, and tests read them from there — so a number is physically impossible to drift between the spec and the assertion. Values that merely tune behaviour stay ordinary constants; nothing is owed to anyone when a tuning knob changes. A param may be any JSON value, so a composite constant — a vendor blacklist, a kind -> payload table — gets the same single source as a lone number, which is where drift is worst.

Why this shape, when an agent is writing the code

Everything above holds whoever the author is. Three of the properties change character when the author is not a person, and they are the reason the framework is shaped this way rather than as a linter:

  • Intent outlives the context window. A requirement is a file with a stable id, not a paragraph in a conversation. A summarised or truncated context cannot drop it, and the next session reads the same one — so "what did we agree this should do" is answered by the tree rather than by recall.
  • "Done" is not the author's to declare. attest archive is the definition of done, and green tests do not clear it. Every scenario of a requirement the change adds must have been observed failing at least once — recorded in a file the gate trusts and cannot regenerate from a green tree. An assertion that never discriminated is the cheapest way to finish a task, and it is the one thing this gate exists to refuse.
  • Every diagnostic is a next action. Issues carry a stable code, a link to the section explaining that code, and a file and line wherever the finding has a location — on stdout and in --json alike. Consumers branch on code, never on wording, so a report is something to act on rather than something to interpret, and rewording a message breaks nobody's CI.

None of that asks you to hand the work over. It is the same gate whether a person or an agent is on the other side of it, which is the point: the evidence a reviewer reads does not depend on who wrote the code. Working with an agent is the setup, and it is one command.

Prerequisites

  • Node ≥ 20.19
  • pnpm, plus vitest ≥ 4 and vite ≥ 8 (peer dependencies)

The peer range is exactly the one CI runs, which is the point of it. Older majors are not merely untested: verify relies on a startVitest signature that Vitest narrowed by 4, and ATX-36 — reading a registry opens no listening socket — is asserted against the Vite that is installed, so on any other major it is a claim rather than a measurement. If you are on Vitest 2 or 3, stay on 0.3.x.

The TypeScript compiler is a bundled dependency, not a peer — Attest reads your registries and specs through the compiler API, and typescript@7 no longer exposes one (its AST moved behind typescript/unstable/*). So the supported range is ^5.5.0 || ^6.0.0, both ends run in CI, and your own compiler is not involved: on a project already using TypeScript 5 or 6 the two resolve to one copy, and on TypeScript 7 you will simply have a second one that only Attest uses. Your project's TypeScript version is yours to choose either way.

Getting started

Install (the framework plus its vitest + vite peers):

pnpm add -D @am_shork/attest vitest vite

1. Declare a requirement (requirements/auth.reqs.ts) — import the intent API from the vitest-free /define subpath so registry loading never touches the runtime. A registry is a literal: every value is written where you can read it, because the commands below read it without executing it (why).

import { defineRequirements } from '@am_shork/attest/define';

export default defineRequirements({
  'AUTH-3': {
    statement:
      'The system SHALL expire a session after {idleTimeoutMin} minutes of inactivity.',
    rationale: 'Security: limit the exposure window of an unattended session.',
    params: { idleTimeoutMin: 30 }, // the single source for this number
  },
});

2. Attest it with scenarios (session.spec.ts):

import { expect } from 'vitest';
import { requirement, scenario } from '@am_shork/attest';
import reqs from './requirements/auth.reqs.js';
import { createSession, advance, touch, isValid } from './session.js';

requirement('AUTH-3', () => {
  scenario('idle timeout invalidates the session', () => {
    const t = reqs['AUTH-3'].params.idleTimeoutMin; // single source, typed `30` — no cast
    const s = createSession();
    advance(s, t + 1, 'minutes');
    expect(isValid(s, t)).toBe(false);
  });

  scenario('activity resets the idle timer', () => {
    const t = reqs['AUTH-3'].params.idleTimeoutMin;
    const s = createSession();
    advance(s, t - 1, 'minutes');
    touch(s);
    advance(s, t - 1, 'minutes');
    expect(isValid(s, t)).toBe(true);
  });
});

Both files above are quoted from fixtures/consumer/, which the packaging test installs from a real tarball and runs — a test asserts the quotes are byte-equal to the files, so a sample the engine would now reject cannot survive here.

3. Run the engine:

attest check    # static: orphan tests, uncovered requirements, unbound params
                # (reads your registry; runs none of your code)
attest verify   # run tests + coverage + drift, graded report
                # (runs only the spec files that declare a requirement())
attest cover    # which requirements lack a scenario
attest render   # the requirements as Markdown, for people who don't read TS
attest archive <change>   # gate a proposed change: green + covered + no drift
attest status <change>    # per added id: scenario written? seen red? (part of that
                          # gate, without running anything — never a verdict)

Every command takes the project root as an optional last argument, and --json for exactly one machine-readable document on stdout. Flags, per-command behaviour and the JSON shape are in the CLI reference.

Reading a param is necessary and not sufficient — an assertion that recomputes its expectation from the same param the code just read has no independent term, and a scenario that loops over a list param covers exactly that list. Both have a known shape and a known repair, and both are in Judging your own intent layer, along with the decision table — the shape a composite param is best at.

Working with an agent

The engine above is only half the framework. The other half is the workflow — agree on intent, write the delta, drive the scenarios red, then implement to green — and it is written for an agent to follow:

attest init                    # .claude/skills/attest/SKILL.md
attest init --target cursor    # .cursor/rules/attest.mdc
attest init --target copilot   # .github/instructions/attest.instructions.md
attest init --target agents    # .agents/skills/attest/SKILL.md — Codex, Gemini CLI, …

"Every scenario has been seen to fail" is enforced rather than advised: archive records how each of a change's scenarios ended in every run it observes, into changes/<name>/first-run.json, and blocks with never-red on any requirement the delta adds whose scenarios were never seen to fail. Commit first-run.json with the change — it is the evidence, and CI has to reach the same verdict as you do.

It does not require you to write the test first. A recorded failure is permanent and a recorded pass is not, so a failure observed after the implementation exists satisfies the gate exactly like one observed before it: if you wrote the intent, the scenario and the code together, remove the implementation, run archive, and put it back. What is enforced is that the assertion can fail — not the order you worked in.

Before any of that, in Claude Code, there is a plugin. This repository is its own plugin marketplace, and what it hosts is a setup helper — not a second copy of the workflow:

/plugin marketplace add https://gitlab.com/Pseudorca/attest.git
/plugin install attest-setup@attest

It knows what Attest is, what to install, and to run attest init — and then it says so and stops. The workflow is deliberately not shipped as a plugin. A plugin installs per-user, so a teammate who does not have it would see nothing and no file in the repository would record which workflow was followed. The document init writes is committed to your project, which is the whole point of writing it there.

An agent loads the document on its own — its description is already in the agent's context, or its path matches what you have open — so nothing has to be found or pasted. See attest init for the targets and what init deliberately does not write.

When something goes wrong

Every diagnostic carries a code, and every code has a section in Troubleshooting — which the diagnostic itself links to:

ERROR   registry-not-static (requirements/upload.reqs.ts:5)
    Value is not a literal.
    → https://gitlab.com/Pseudorca/attest/-/blob/v1.6.0/docs/en/troubleshooting.md#registry-not-static

The anchor is the code, so the link cannot point somewhere the section isn't. In --json the same link is on each issue as docsUrl.

Documentation

| Document | English | 中文 | |---|---|---| | CLI reference — every command, flag and JSON field | en | 中文 | | Troubleshooting — one section per issue code | en | 中文 | | Design — the authoritative design of the framework | en | 中文 | | Judging your own intent layer — what no gate checks, and a method for it | en | 中文 | | Feedback template — report how adoption actually went | en | 中文 |

The change workflow is not here: it is what attest init writes into your project, as a skill, a rule or an instructions file, depending on which agent reads it.

Development

pnpm install
pnpm build       # tsc -> dist/
pnpm test        # vitest run (the framework's own unit tests)
pnpm typecheck
pnpm lint

Dogfooding

Attest describes its own behaviour under self/ and verifies itself:

pnpm verify:self   # attest verify self  -> all green

Packaging test

pnpm test:consumer packs a real tarball, npm installs it into a throwaway project outside the repo, and drives the installed CLI against fixtures/consumer/. It is the only test that exercises the published surface — the files allowlist, the exports map, the bin launcher, peer resolution from a foreign node_modules — so it is what catches "green in-repo, broken once installed" bugs. It needs network and is excluded from pnpm test; it runs in CI and as prepublishOnly.

Feedback

Adoption reports drive the roadmap. After using Attest on a real project, fill in the feedback template (linked above) and open it as an issue — it is also the Usage feedback issue template. It covers greenfield and mid-project adoption alike, and ends with a prompt to run inside the adopting repo that fills most of the report automatically and probes for problems you haven't hit yet. The highest-value part is false negatives: drift the engine should have caught and didn't.

Acknowledgments

Attest's architecture — the four-stage truth engine (AST parse → graded validation → diff-first delta apply → archive gate) and its diff-first change model — is adapted from OpenSpec (MIT), swapping two parts: parsing moves to the TypeScript Compiler API, and verify becomes running the tests. The design is re-implemented from scratch; no OpenSpec source code is included.

License

MIT