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

@termwright/recognizers

v0.5.2

Published

Probe IR to semantic tree: the rules that turn observed facts into roles, names and states

Readme

@termwright/recognizers

The rules that turn observed facts into meaning.

A probe reports what a framework exposed — classes, coordinates, flags. This package decides what those facts are: a role, a name, a state. Keeping the two apart is what lets six frameworks disagree about what is knowable without that disagreement leaking into the semantic tree.

Everything here is a pure function over Probe IR, so the rules can be tested without a process, a framework or a socket, and the same rules apply to every framework instead of being reinvented once per adapter.

Install

npm install @termwright/recognizers

Depends on @termwright/protocol and nothing else.

Usage

import { recognize } from '@termwright/recognizers';

const snapshot = recognize(probeFrame, {
  sessionId,
  revision,
  columns: 80,
  rows: 24,
  framework: 'opentui',
  paintOrderKnown: true,
});

The rules

Role resolves in the normative order: an author annotation, then the framework's widget map, then generic. An annotation naming a role outside the closed set falls through to the map rather than becoming an invented role.

An unrecognised widget is never dropped. It becomes generic and keeps its frameworkType, bounds, text and children, so a test can still find it by what the framework called it.

Names come from content only for the roles that take them that waybutton, listitem, menuitem, tab, checkbox, radio, cell, row, heading, plus text for its own string. A container keeps an empty name unless annotated: naming it from its content is what makes getByRole('region', {name: 'Approve'}) match the dialog containing the button.

Physical facts stay the framework's. An author may name a thing; an author may not declare where it is on screen, whether it has focus, or whether it is visible. Provenance records this: one source per node in p, exceptions in px.

Deviations

OpenTUI's map is short on purpose. BoxRenderable, ScrollBoxRenderable, TabSelectRenderable and SliderRenderable resolve to generic. A tab strip is not a tab, and a role that reads right while matching the wrong node is worse than an honest generic — which, with frameworkType, is still findable.

An orphan is reparented, not dropped. If a node's parent did not survive the frame — a truncated walk, a removal mid-observation — the node attaches to the root. A dangling parentId is refused by snapshot validation outright, and losing the subtree would be the worse of the two failures.