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

vouchington-tooling

v0.44.0

Published

Vouchington CLI and extractable tooling libraries.

Readme

vouchington-tooling

Libraries and the vouchington CLI.

The workflow and compiler primitives provide consumer supplied GitHub Actions policy checks and compiler host freshness with bounded build settlement.

config-inventory collects environment, dynamic-configuration, and package-manager evidence using caller-owned file roles and policies.

finite-enum-ripple compares finite TypeScript declarations, route configuration, routed pages, and factory calls. Consumers supply every tracked-file role, declaration name, route label, factory pattern, and exception.

npm install vouchington-tooling
# optional, only if you import vouchington-tooling/sql-ast
npm install @libpg-query/parser
# optional, if you import vouchington-tooling/contract-schema, finite-enum-ripple,
# or post-publication-inventory
# (classic compiler API; typescript@7's package root is version-only)
npm install @typescript/typescript6
# optional, only if you use the Vitest reporter export
npm install vitest
# optional, only for vouchington-tooling/agent-blackboard and agent-blackboard CLI commands
npm install agent-blackboard@^0.6.0
# optional, only for `vouchington mcp` (zod is a peer of the SDK)
npm install @modelcontextprotocol/sdk zod

vouchington mcp serves the agent-blackboard journal tools to an agent over stdio, with Claude, Codex, and Cursor registration examples.

CLI

vouchington --help
vouchington runner-port-policy
vouchington runner-port-policy --file ./policy.json
vouchington runner-port-policy --reserved 2200
vouchington with-host-lock --name expensive-build --timeout-seconds 60 -- make build
vouchington gha-runtime-audit --pr-workflow CI --push-workflow '/^Main CI \\(.+\\)$/'
vouchington require-up-to-date --remote origin --branch main
vouchington gitleaks-directory-scan --config .gitleaks.toml
vouchington ast-grep-examples --rules ast-grep-tests --config sgconfig.yml
vouchington ast-grep-pack
vouchington gha-workspace-policy
vouchington gha-output name
vouchington gha-needs-results
vouchington download-with-diagnostics <url> <destination>
vouchington download-optional-run-artifacts --pattern 'coverage-*' --dir ./coverage-fallback
vouchington download-optional-run-artifacts --name coverage-tooling --name coverage-web --dir ./coverage-fallback
vouchington host-pressure-diagnostics
vouchington allocate-browser-safe-ports 2 --policy ./policy.json --forbidden-ports ./ports.json
vouchington diagnose-port-collision --ports "2200 2216"
vouchington prepare-trivy-db
vouchington gha-artifacts-cleanup run --run-id 123 --keep-pattern 'plan-*' --delete-pattern 'coverage-*'
vouchington http-origin --field cdn_origin https://images.example.com
vouchington vitest-blob-manifest <suite> [reports-directory]
vouchington vitest-report-attempt write <directory> <suite>
vouchington vitest-report-attempt read <root>
vouchington prepare-vitest-reports [primary-directory] [fallback-directory] [output-directory]
vouchington pnpm-install --runner-lifecycle persistent --install-scripts true
vouchington check-cache-size /tmp/cache 1048576 node-modules
vouchington make-shard-matrix 4
vouchington load-runner-env
vouchington clean-workspace
vouchington install-github-release --repo lycheeverse/lychee --version 0.24.2 --asset 'lychee-{platform}.tar.gz' --bin lychee
vouchington run-with-timeout 120 10 docker push example
vouchington lint-links --offline
vouchington materialize-pr-context
vouchington wait-for-apt-locks
vouchington retrospective-transcript --jsonl /path/to/transcript.jsonl
vouchington retrospective-facts --pr 49 --repo vouchington/vouchington-infra --raw
vouchington agent-blackboard probe
vouchington agent-blackboard journal append --session-id <uuid> --agent codex --version 1 --file note.md --repository owner/repo --mode autonomous --source-event-id event:1 --work-outcome in-progress --coverage-status partial --timestamp 2026-01-01T00:00:00.000Z
vouchington agent-blackboard journal entries --session-id <uuid>
vouchington agent-blackboard snapshot partition --snapshot <snapshot.jsonl> --checksum <sha256> --counts <counts.json>
vouchington agent-blackboard snapshot cleanup --snapshot <snapshot.jsonl> --partition-directory <partitions-dir> --receipt <receipt-json>
vouchington mcp
vouchington install-playwright-chromium-arm64
vouchington ghcr-package-retention example%2Fapi
vouchington harness-admission-lane 4
vouchington harness-assert-gates HARNESS_DISPATCH_ENABLED HARNESS_SHEPHERD_ENABLED
echo '[{"login":"octocat","type":"User"}]' | vouchington gha-collaborator-trust owner/repo --allow-bot github-actions[bot]
vouchington nuget-central-version trusted.props candidate.props metadata.json out.props
vouchington swift-semantic-equal BASE HEAD App.swift
vouchington post-review
vouchington stage-review-payload optional|required <source> <destination>

Running allocate-browser-safe-ports without an install

The allocator is a standalone Python script that needs only the Python 3 standard library: no Node, no pnpm install. Run it from the extracted published tarball:

npm pack vouchington-tooling@<version>   # or download the registry .tgz
mkdir extracted && tar -xzf vouchington-tooling-<version>.tgz -C extracted
python3 extracted/package/scripts/allocate-browser-safe-ports.py <count> [--policy ...] [--forbidden-ports ...]

pnpm dlx and npx resolve the package's whole dependency tree, which can fail under minimumReleaseAge (ERR_PNPM_NO_MATURE_MATCHING_VERSION) when a lockstep-published dependency straddles the cutoff. CI jobs without an install should fetch the tarball instead. Tests enforce that the script stays stdlib-only and reads only its two sibling JSON files.

For persistent pnpm-install, v5 metadata tracks structural inputs separately from the --install-scripts policy. A warm scripts-enabled tree can therefore toggle true → false → true without forced reconciliation; a tree first installed with scripts disabled uses two script-suppressed verification installs followed by pnpm rebuild --pending --recursive. Before rebuilding, duplicate pending IDs are collapsed. After rebuilding, IDs proven absent from the current workspace and installed virtual-store lockfiles are reported and removed; live dependency and workspace-importer IDs are retained. Any residual ID after the generic rebuild remains a reported hard failure. An isolated native-binary mismatch uses one strict forced install only when structural provenance matches, workspace links are valid, and pnpm records empty ignoredBuilds and pendingBuilds ledgers; otherwise it retains the two script-free reconciliation passes. Native and workspace-link health are verified before its metadata stamp is refreshed. The command emits a structured non-secret provenance diagnostic identifying changed structural categories, the last script policy, script capability, and native-binary health.

download-optional-run-artifacts uses the current Actions run and host. Pattern mode discovers non-expired artifacts across the run, keeps the first result for each name (matching gh run download), and extracts each selected name into its own directory. Ordinary absence is reported as availability=unavailable. Artifact listing retries up to three times with bounded backoff; exhausted transport errors, invalid names, and cancellation remain hard failures.

Name mode takes one or more --name <artifact> flags (mutually exclusive with --pattern), lists the run's artifacts once, and extracts every requested name that is present into <dir>/<name>. Names are matched literally, in request order, with repeats downloaded once; empty names, ., .., and names containing /, \, or a line break are rejected before anything is listed. Requested names absent from the run are expected (callers pass a superset such as retry-attempt variants) and are skipped with a single bounded ::notice:: (the absent count, the first three names, then and N more) and never one line per name. availability=available means at least one requested artifact was downloaded; availability=unavailable (exit 0) means none was present. A present artifact whose download fails is a hard failure: the helper stops at the first one, prints download failed artifact=<name> exit=<n>, exits non-zero (a downloader exit of 3 is reported as 1 so it cannot be mistaken for absence), and writes no availability output.

require-up-to-date fetches the requested remote branch and fails unless its fetched tip is an ancestor of HEAD. fresh-base refreshes <remote>/<branch> (default origin/main, 8 s fetch timeout, --skip-fetch to compare the cached ref) and prints a JSON report classifying the worktree as up-to-date, ahead, behind, diverged, dirty (matches the base but has uncommitted changes), fetch-failed (a failed refresh outranks every other status), or unknown. It prints nothing outside a Git repository. Unlike require-up-to-date it never fails on staleness; callers decide what to do with the status. gitleaks-directory-scan builds and scans isolated staged-index and current nonignored-working-tree mirrors with an explicit config; --directory selects the repository root. ast-grep-examples runs native ast-grep test, then validates each scoped rule's files: and ignores: examples with project languageGlobs replay from its root --config. The shipped pack maps **/*.ts, **/*.mts, **/*.cts, and **/*.tsx to Tsx so one rule covers script and JSX surfaces. Consumers must use the same languageGlobs and language: Tsx; do not add -tsx companion YAML. Angle-bracket type assertions (<T>value) are not valid TSX. compareAstGrepCompanions compares recursive <name>.yml/.yaml and <name>-tsx companion rules across every YAML field, returns stable JSON-pointer differences, and rejects unsafe or ambiguous rule paths. The supplied rule path and every ancestor must be physical directories; YAML aliases and non-JSON tagged values are rejected before comparison. Callers own any explicit normalization for language-specific differences. ast-grep-pack prints JSON { rules, config } for the shipped unconditional rule pack. Point a consumer sgconfig.yml ruleDirs at rules and keep product-specific YAML locally. gha-workspace-policy checks tracked workflow and composite-action files in the current repository; pass --root, --workflow-directory, or --action-directory for consumer-owned layouts.

retrospective-transcript discovers Codex and Claude transcripts by default. It also reads a Claude-compatible transcript when CURSOR_SESSION_ID is set, and Grok's updates.jsonl session layout when GROK_SESSION_ID is set. Use --grok-sessions-dir to point discovery at a nondefault Grok session root. Without --session-id, it reads those session identities from the host environment.

retrospective-facts keeps local Git evidence separate from GitHub PR data. Commits ahead of origin/main is populated only from a local ancestry range; GitHub responses instead populate PR commits. API-derived file and directory counts are labelled GitHub API. When a named local branch is absent, the command refreshes origin/<branch> before using it and refuses a stale remote ref when that refresh fails. For an explicit --repo, it performs no local Git checks: Merged to main is yes only when GitHub reports a merged PR whose baseRefName is main; a merged PR into another base is reported as not merged to main, and a missing base is unavailable.

Agent Blackboard support is optional: only the agent-blackboard subpath and its CLI commands need agent-blackboard@^0.6.0. Snapshot cleanup accepts only package-generated temporary paths. appendJournal and the journal CLI now require explicit mode, stable source-event identity, work outcome, feedback coverage, and exact repositories. This is a breaking pre-1.0 API change; adopt the shared contract before upgrading consumers. appendJournal reads a bounded UTF-8 note and delegates to writeFeedback, returning delivered or pending state rather than a success-shaped message. The CLI accepts one or more --repository owner/name flags; it records the entry's exact repositories and updates the session's cumulative repository list before appending. Programmatic callers launched from a different workspace directory pass their own module URL as dependencies: { resolveFrom: import.meta.url }; the CLI defaults to the current package context. It captures a target under a private tombstone, validates partition names, permissions, JSONL, ordering, terminal manifests, and the identity-bound cleanup receipt before deleting files, and restores the original path on a validation failure. Once deletion begins, it retains a private tombstone plus signed resume metadata instead; retry cleanup with the original partition-directory path and the same receipt until it completes. The partition command returns that receipt; directory cleanup requires it. The receipt is authenticated with an owner-only per-user HMAC key stored under a dedicated 0700 directory in the system temporary directory. This small host-local state is the trust boundary: a copied or caller-created receipt cannot authorize cleanup without that key.

Host-lock environment:

| Variable | Default | Meaning | | --------------------------------------- | --------------------- | ------------------------------------------- | | HOST_LOCK_ROOT | /tmp/host-lock-$UID | Absolute lock directory root | | HOST_LOCK_LEASE_SECONDS | 60 | Reclaim ceiling for a held lock | | HOST_LOCK_PROCESS_GROUP_DRAIN_SECONDS | 30 | Time to wait for the command process group | | HOST_LOCK_ACTIVE | unset | Set while a lock is held; nested locks fail |

Sourceable Bash libraries

scripts/worktree/git-worktrees.sh is included in the published package. Source it to parse git worktree list --porcelain with git_worktree_* helpers. Its git_worktree_canonical_path_hash <path> helper resolves the physical path and prints a stable d plus the first 12 lowercase hexadecimal characters of its SHA-256 digest.

Library

import {
  isRunnerReservedPort,
  listenOnRunnerUnreservedEphemeralPort,
  runnerPortPolicy,
} from 'vouchington-tooling/runner-port-policy'
import { initSqlAst, extractCreateTableMetadata } from 'vouchington-tooling/sql-ast'
import { splitSqlStatements, stripSqlComments } from 'vouchington-tooling/sql-scanner'
import { auditCiJobRuntime } from 'vouchington-tooling/gha-runtime-audit'
import {
  inspectHarnessEnvironment,
  selectHarnessSession,
} from 'vouchington-tooling/agent-harness-identity'
import {
  readVitestReportAttempts,
  writeVitestBlobManifest,
} from 'vouchington-tooling/vitest-blob-manifest'
import { prepareVitestReports } from 'vouchington-tooling/vitest-reports'
import { runInstallLifecycle, validateReleaseAgePolicy } from 'vouchington-tooling/pnpm-install'
import {
  buildSharedContext,
  installFakeGit,
  runNamedChecks,
} from 'vouchington-tooling/shared-context'
import { createSourceModuleGraph } from 'vouchington-tooling/source-module-graph'
import {
  decodeSelectedFiles,
  writeSelectedFilesOutput,
} from 'vouchington-tooling/gha-selected-files'
import { createArtifactClassifier, runCleanup } from 'vouchington-tooling/gha-artifacts-cleanup'
import { validateOptionalHttpOrigin } from 'vouchington-tooling/http-origin'
import { boundPendingLine, splitCompleteLines } from 'vouchington-tooling/process-line-buffer'
import {
  isProcessGroupAlive,
  runBrowserSession,
  waitForProcessGroupExit,
} from 'vouchington-tooling/browser-session-runner'
import {
  generateSchemaSnapshot,
  renderSchemaMarkdown,
} from 'vouchington-tooling/pg-schema-snapshot'
import { buildOpenApiDocument, writeOpenApi } from 'vouchington-tooling/openapi-document'
import {
  extractResponseContracts,
  validateResponseContract,
} from 'vouchington-tooling/contract-schema'
import {
  buildFixtureSchemaLock,
  validateFixtureContracts,
  writeGeneratedFiles,
} from 'vouchington-tooling/api-fixtures'
import { decide, deriveRetryAttempt } from 'vouchington-tooling/transient-retry'
import { parseCsvRows, streamCsvRows } from 'vouchington-tooling/csv'
import {
  extractLooseMarkdownTableRows,
  extractMarkdownTables,
  markdownSectionBetweenHeadings,
  parseGfmMarkdown,
  parseMarkdownTables,
} from 'vouchington-tooling/markdown'
import { readResponseBody } from 'vouchington-tooling/http-body'
import { runAstGrepRule } from 'vouchington-tooling/ast-grep-rule'
import { parseReviewPayload, remapReviewComments } from 'vouchington-tooling/gha-review-payload'
import { postReviewWithTokenFromEnv, runPostReview } from 'vouchington-tooling/gha-post-review'
import { postClaudeReviewFromEnv } from 'vouchington-tooling/gha-claude-post-review'
import { nextPageUrlFromLinkHeader } from 'vouchington-tooling/http-link-pagination'
import {
  cmdUpload,
  discoverDownloadControl,
  mintPrefixUploadControl,
} from 'vouchington-tooling/coverage-transport'
import { pruneDeployedRuntimeDeps } from 'vouchington-tooling/pnpm-deploy'
import { parseDockerfileRuntimeImages } from 'vouchington-tooling/dockerfile-parse'
import { checkSccComplexity } from 'vouchington-tooling/scc-complexity'
import { runCiLocal } from 'vouchington-tooling/ci-local'
import { rateLimitDelay } from 'vouchington-tooling/gha-rate-limit'
import { parseCheckpoint } from 'vouchington-tooling/gha-pr-checkpoint'
import { checkWorkspaceGatesPolicy } from 'vouchington-tooling/workspace-gates'
import {
  collectPnpmLicenseReport,
  evaluatePnpmLicenseReport,
} from 'vouchington-tooling/dependency-license-policy'
import { checkGhaWorkspacePolicy } from 'vouchington-tooling/gha-workspace-policy'
import { requireUpToDate } from 'vouchington-tooling/require-up-to-date'
import { checkFreshBase, classifyFreshBase } from 'vouchington-tooling/fresh-base'
import { runGitleaksDirectoryScan } from 'vouchington-tooling/gitleaks-directory-scan'
import { runAstGrepExamples } from 'vouchington-tooling/ast-grep-examples'
import { astGrepPackPaths } from 'vouchington-tooling/ast-grep-pack'
import { validateNugetUpdate } from 'vouchington-tooling/nuget-central-version'
import { normalizeSwiftSource } from 'vouchington-tooling/swift-semantic-equal'
import { parseUniqueSwiftBinaryTargetChecksum } from 'vouchington-tooling/swift-source-offset'
import { validateResolvedPinDelta } from 'vouchington-tooling/swift-resolved-pin-delta'
import {
  createForkLeakDetector,
  createVitestWorkerExitDiagnosticsReporter,
  formatDiagnosticReportSummaries,
  readDiagnosticReportSummaries,
  registerForkExitSentinel,
} from 'vouchington-tooling/vitest-diagnostics'
import { runRetrospectiveTranscript } from 'vouchington-tooling/retrospective-transcript'
import { appendJournal, probeBlackboard } from 'vouchington-tooling/agent-blackboard'
import { buildSessionFrictionReport, recordFriction } from 'vouchington-tooling/session-friction'
import { GITHUB_BODY_MAX_CHARACTERS, validateGitHubBodyLength } from 'vouchington-tooling'
import { createPullRequest, processDiffCommand, runGh, runGit } from 'vouchington-tooling/gh-cli'
import {
  shellScriptViolations,
  workflowYamlViolations,
} from 'vouchington-tooling/gh-api-shell-quoting'

processDiffCommand runs a caller-supplied git diff or gh pr diff executable and argv without a shell, emitting complete unified-diff file blocks without accumulating the whole patch. It keeps at most one file block (which can itself be large), preserves preambles and line content, and drains a bounded stderr tail for typed command failures. Blocks are provisional until the returned promise resolves: callers must discard accumulated results if the command later exits nonzero or is signaled.

let changedFileCount = 0
await processDiffCommand({ executable: 'git', args: ['diff', 'origin/main...HEAD'] }, async () => {
  changedFileCount += 1
})
// Use changedFileCount only after processDiffCommand resolves.

vouchington-tooling/gh-cli also parses pull request body references. parseClosingIssueReferences finds GitHub closing keywords (close/closes/closed, fix/fixes/fixed, resolve/resolves/resolved) followed by #N, owner/repo#N or an issue URL, deduplicated by key (#N or lowercased owner/repo#N, see formatReferenceKey). parseNonClosingRefs collects Ref, Refs and Part of keys from text the caller has already scoped, such as a "Related issues" section.

vouchington-tooling/pull-request-diff counts added and deleted lines in unified-diff text (countDiffLineChanges, excluding +++/--- headers) and compares them with caller-supplied LargeDiffThresholds through exceedsLargeDiffThreshold. DEFAULT_LARGE_DIFF_THRESHOLDS (5,000 added, 20,000 deleted) is only an example default.

import {
  countDiffLineChanges,
  exceedsLargeDiffThreshold,
} from 'vouchington-tooling/pull-request-diff'

exceedsLargeDiffThreshold(countDiffLineChanges(diffText), {
  addedLines: 5000,
  deletedLines: 20_000,
})

This breaking minor removes getDiffAgainstBase; migrate callers to processDiffCommand and pass the command they need to run.

checkSccComplexity keeps its single repository-wide scan when scopes is omitted. Consumers that need separately ratcheted areas may provide named scopes with positional includePaths; SCC runs once per scope and reports the scope in each diagnostic. Parse a consumer-owned JSON baseline with parseSccComplexityBaseline and pass it as baseline. Baselines are versioned, record the maximum permitted complexity for each { scope, file }, suppress only values at or below that ceiling, and reject malformed, duplicate, untracked, stale, or out-of-scope entries.

shellScriptViolations/workflowYamlViolations flag a gh api call whose argument carries an unquoted ? or &: an unquoted & silently backgrounds the command and truncates the query (the call still exits 0), and an unquoted ? fails loudly under zsh glob-nomatch but passes through unexpanded under bash. workflowYamlViolations decodes quoted and folded YAML run: scalars before scanning, so a hazard hidden by YAML's own quote-stripping is still caught; it throws on a run: value that is a YAML alias or a multiline PLAIN scalar, shapes it cannot yet scan safely. Both functions scan already-in-scope source text — deciding which files count as a shell script or a workflow/action YAML file is left to the caller.

validateGitHubBodyLength measures an issue or pull-request body against GitHub's 65,536 Unicode code-point limit without altering it. Its result includes the UTF-8 byte count for diagnostics; that byte count is not a validation limit.

vouchington-tooling/markdown parses GFM into standard mdast/unist nodes, provides pre-order walking and typed searches, normalizes node text, and extracts positioned tables or heading-bounded source sections. parseMarkdownTables preserves its compact { cells, line }[][] compatibility shape, including short table delimiters. extractLooseMarkdownTableRows is intentionally literal recovery for malformed pipe rows; callers supply table positions to exclude and retain ownership of their policy interpretation.

parseMarkdownSections returns visible root H2 sections, their exact original content, startOffset/endOffset source ranges, heading line, and hasVisibleContent. Heading text is normalized by collapsing whitespace and removing Markdown formatting/comments and collapsed text; matching remains case-sensitive. Source offsets are JavaScript string offsets, so source.slice(startOffset, endOffset) preserves Unicode and CRLF exactly. Sections end at the next visible root H2 or EOF; fenced examples, quoted headings, and headings inside <details> do not create boundaries.

import { parseMarkdownSections, validateMarkdownSections } from 'vouchington-tooling/markdown'

const document = parseMarkdownSections(body)
const diagnostics = validateMarkdownSections(document, {
  requiredHeadings: ['Summary', 'Impact'],
})
const relatedIssues = document.sections.find((section) => section.heading === 'Related issues')

The caller owns required headings. Validation returns diagnostics with code, message, and optional heading/line, for missing-heading, duplicate-heading, empty-section, or malformed-details. Nonempty visible paragraphs, lists, and populated table bodies satisfy the content check; comments, fenced/indented code, images, disclosure labels, and collapsed-only content do not. The parser tracks balanced nested details/summary tags in GFM HTML nodes, accepting optional summaries and quoted attributes; it is not a general HTML validator or sanitizer. It never rewrites the input or infers semantic relevance, cost, schema conformance, or failure causes. The existing markdownSectionBetweenHeadings API retains its original boundary behavior.

hasUncheckedMarkdownTask reports parsed unchecked GFM task items, ignoring code and non-task text. markdownLiteralSpans returns source-backed { kind, position, value } facts for fenced or indented code, inline code, and raw HTML. markdownHtmlFacts distinguishes inline HTML from block HTML and labels CommonMark block types 1–7; markdownHtmlBlocks selects block types 1, 6, and 7, retaining the parser's source bounds, including type 1 blocks through their matching closer or end of input. Positions use 1-indexed line/column coordinates and JavaScript string offsets, including CRLF and Unicode source text. These APIs return facts rather than mdast nodes so callers can apply their own content policy without binding it to parser internals.

import {
  hasUncheckedMarkdownTask,
  markdownHtmlBlocks,
  markdownLiteralSpans,
} from 'vouchington-tooling/markdown'

const hasOpenTask = hasUncheckedMarkdownTask(body)
const literalSpans = markdownLiteralSpans(body)
const blockHtml = markdownHtmlBlocks(body)

markdownHtmlBlocks reports CommonMark types 1, 6, and 7; inline tags do not appear in that result. Use markdownHtmlFacts when inline/block classification and other CommonMark HTML block types are also needed.

Machine-wide agent configuration now belongs to vouchington-machines. Use its configure-agents.sh and diagnose-agents.sh; project hooks and MCP configuration remain in their checkouts.

agent-harness-identity inspects the four harness environment signals without choosing a winner. Callers supply their own precedence to selectHarnessSession, keeping product-specific identity policy out of this package.

checkWorkspaceGatesPolicy rejects tracked test assertions that hard-code the exact version of a dependency declared by a non-fixture package manifest. Assert dependency membership or placement, or derive a configuration or documentation package spec from that manifest instead.

dependency-license-policy keeps legal policy in the consumer. collectPnpmLicenseReport returns a promise. It creates an isolated, script-free temporary workspace, expands pnpm's supported architectures to every os, cpu, and libc selector represented in the lockfile, drops every engines constraint from the audit copy of the lockfile, and validates the JSON report. Dropping engines keeps pnpm fetch from skipping optional packages that exclude the running Node.js; pnpm 12's fetch ignores force, so their licenses would otherwise report as Unknown. Packages are fetched into a private store inside that temporary workspace. Each audit has its own store, and workspace cleanup removes every downloaded package when the audit succeeds or fails, without changing the developer's pnpm store. The exported options no longer accept a storeDir override because caller-owned paths cannot be safely removed; callers that provide a custom prepareWorkspace own the returned workspace and its nested store lifecycle. Pass explicit denied SPDX IDs and prefixes, exact aliases, and justified allowlist scopes to evaluatePnpmLicenseReport. Unknown, malformed, and custom SPDX references fail closed. Allowlist scopes are either intentionally global or an exact package-name set; the library returns structured violations and does not format CI-provider diagnostics. When present, the repository .npmrc is copied into the owner-private temporary workspace so pnpm can authenticate to the same registries. The workspace and its package store are removed when the audit finishes, when the process receives SIGINT, SIGTERM, or SIGHUP, and on the next audit if the previous process died first, including SIGKILL. Each workspace records its owner's PID so a later audit can delete directories whose owner is gone.

session-friction is an opt-in capture and reporting library. Callers supply the session id, absolute log directory, host-independent observation, and journal loader; it does not inspect host environment variables, install hooks, or connect to a journal service by itself. Invoking recordFriction touches the session log even when no event is classified, preserving the difference between an observed clean session and missing evidence. Report markdown keeps backend diagnostics separate from its paste-safe output. Capture stores at most 500 events per session and counts rejected captures in a fixed-size atomic sidecar under the same session lock for either the event or byte limit, with visible truncated/droppedCount metadata. Saturated capture reads only the bounded counter; reports also preserve historical overflow markers. Interrupted or inconsistent counter updates make coverage unavailable. Malformed records also make the scan partial. It truncates event detail to 1,000 characters, and consumes up to 500 entries from the journal loader when building a report, stopping earlier when its aggregate 1 MB inspected-byte budget is reached. Bounded journal scans that stop before exhaustion are reported as incomplete rather than clean. Report liveness inherits the caller-supplied journal loader, which must bound its own I/O and yields. Log reads are capped at 2 MB, journal Markdown at 10,000 bytes per entry, and rendered audit fields are kept whole: composition loads the journal and friction log once, redacts each field from its raw text before Markdown escaping (a caller-supplied redactor runs first, then the built-in one), then renders the CI and sandbox sections, measures the real envelope against its 12,000-byte markdown and 16,384-byte envelope limits, and shrinks them in a few bounded attempts. A block shrinks Root diagnostic first and Evidence last, cutting only at token boundaries (never inside a URL or SHA) with a trailing …; groups that still cannot fit are omitted and counted in an explicit conforming group that points at the journal. The final attempt keeps only that omission note (about 300 bytes), so an input within roughly 300 bytes of the limit can still fail to compose. A caller-supplied budgets cap limits rendered groups only; the omission note is exempt from it. Permission requests record requested outcomes; explicit result observations may record approved or denied outcomes. A decision and simultaneous tool failure are both retained and counted in the report. Escalation detail without a decision remains unknown. Localhost connection refusal is an ambiguous failure and does not establish a sandbox cause. The supplied log directory must be dedicated to session-friction; existing directories must already be owner-only, while newly created directories and log files are enforced as owner-only when recording. Reads use a fixed bounded buffer that can detect growth one byte beyond the documented 2 MB cap. Ownership checks require POSIX effective-user IDs (Linux and macOS); session-friction throws on Windows and other platforms where those IDs are unavailable. Root-owned system symlink ancestors are supported for paths such as macOS /var; callers must not allow the directory chain to be mutated while it is being validated. Command-prefix normalization recognizes simple shell segments with single or double quotes; it does not evaluate substitutions or implement a full shell grammar. Normalization attempts limited redaction of obvious credential patterns but is not a secret scrubber; callers must ensure credentials are never included in captured commands. Failure classification inspects at most 100,000 structured-stderr characters, split evenly between the beginning and end when input exceeds that bound. Cooperating log readers and writers are serialized, including the initial clean-session touch. Recording and report log reads are synchronous: on contention they block the caller's event loop for up to one second before failing explicitly. Avoid these APIs on hot request paths.

The artifact, review-payload, HTTP body, and pagination APIs validate untrusted inputs at their boundaries. Neutral review posting lives in gha-post-review and requires a caller-supplied GitHub token. Claude App OIDC is an explicitly selected gha-claude-post-review adapter; the legacy token-source router remains deprecated for one release line.

vitest-diagnostics reads Node diagnostic report JSON from a caller-selected directory. It sorts filenames, tolerates partial files, returns only a bounded field allowlist, and never emits raw native frame symbols. Both structured reads and text rendering have hard report-count limits.

Fork diagnostics use a caller-selected recordDirectory in both the worker setup file and the main-process reporter. Call registerForkExitSentinel({ recordDirectory }) once per fork, then update setCurrentForkExitModule and setCurrentForkExitProject around tests. Construct createVitestWorkerExitDiagnosticsReporter({ recordDirectory }) in the Vitest reporter list before workers start. The reporter clears stale records at construction, preserves them across watch reruns, and prints an attribution summary only for abnormal worker exits. The worker writes a synchronous stderr line and one JSONL file per PID; a start record without an exit record identifies a fork killed before its handler could run. createForkLeakDetector accepts tracked resource names and warmup, threshold, and sustained-growth settings; the caller supplies each checkpoint's resource counts. Use a caller-owned run directory: the reporter clears only regular numeric PID .jsonl files there at construction and leaves the directory and other files alone. Application metrics and CI artifact handling stay with the caller.

browser-session-runner supervises caller-created browser-test processes. Callers supply command construction, line classification, retry/outcome policy, and budgets; the library owns process-group termination, output line buffering, shared deadlines, progress watchdogs, diagnostics, and parent signals. The returned process must identify a dedicated process group, such as a child spawned with detached: true; its processGroupId is signalled without assuming the child PID is a group ID. Stall exits use the caller's classifyExit policy, while parent signals and shared-deadline expiration are terminal. Output is decoded independently per stream; unfinished lines are classified at close and diagnosticTailBytes retains a UTF-8-safe tail no larger than its byte budget. The runner uses monotonic elapsed time, rejects timer budgets above Node's maximum delay, and waits for the dedicated process group to exit after the direct child closes so descendants cannot overlap a retry. isProcessGroupAlive and waitForProcessGroupExit are also available when callers need the same process-group probe and bounded-drain semantics outside a browser session.

Generated arbiter input

The pg-schema-snapshot export also provides projectGeneratedArbiterInput(conflict) for PostgresSqlConflict facts from [email protected] or newer. It projects normalized key and partial-predicate column identities, ordered assignment columns, direct non-EXCLUDED references, and assignment indirection. Named constraints and unresolved expression keys have undefined keyColumns; missing or incomplete expression coverage sets complete to false. Callers must reject incomplete projections and retain their own snapshot-dependent replay verdict. The adapter loads no optional parser peer at runtime and implements no replay-safety policy. Its public GeneratedArbiterConflict contract is structural, so importing snapshot declarations does not require the optional peer either.

Contract schema type queries

getExportedTypeFacts and getCallRowTypeFacts use an existing TypeScript Program from the contract-schema subpath. Every request must also pass typescript, the same TypeScript compiler API instance that created that Program. The source-file recognition check is a compatibility guard, and callers remain responsible for pairing the same compiler instance; the query uses the supplied API for compiler operations. Pass the exact SourceFile.fileName, an exported name or exact call expression text, and only the property names and exported comparison types the consumer needs. Facts include the displayed type, whether it is any, requested property displays, and requested assignability booleans. defaultTypeParameterIndex selects an exported generic default; direct defaults and direct references to preceding defaults are supported. Dependent composite defaults and uninstantiated generic type declarations used as assignability targets fail with an instruction to export and select a named instantiated type. Generic function values remain valid compiler-backed comparison targets. Default lookup uses an outer class, interface, or type-alias parameter list when present; otherwise it uses the first checker-visible call or construct signature, never a hidden implementation or a later overload. rowSource: 'typeArgument' selects a call's explicit type argument, while rowSource: 'awaitedRows' selects Awaited<ReturnType>.rows[number]. Call results are source ordered and include one-based line and column. An absent call returns an empty array so the consumer can enforce its own cardinality; a selected call missing its requested row type fails with a descriptive error. The package does not choose source files, expected properties, or contract policy.

Workflow skills outside plugins

The package ships a flat union of canonical workflow, testing, and database skills at skills/<skill>/SKILL.md. This stable installed path supports agents that do not load Claude or Codex plugins. The package build materializes plugin source trees without hand-copying skill content and writes sorted schema-v1 provenance to skills/manifest.json. Each manifest entry may declare its ordered prerequisites; ordinary Markdown links remain cross-references and never cause additional skills to be linked. Prerequisites ensure installation closure; they do not require eagerly reading every installed skill. Follow the invoked skill's conditional instructions for the current task.

Canonical entrypoints direct agents to applicable local instructions and adapters before using portable policy. Local AGENTS.md may name an adapter alias; an already-read canonical skill or adapter is not loaded again. linkSkill still links files only: it does not load instructions, resolve local aliases, or execute a workflow. Validate observed agent loading separately from installation and packaged-resource checks.

Use readSkillManifest(skillsRoot) to discover installed skills or linkSkill({ name, sourceRoot, targetRoot }) to link one into an explicit consumer directory. The CLI equivalent is vouchington link-skill <name> --source-root <skills-dir> --target-root <dir>. When sourceRoot contains manifest.json, linking validates the packaged inventory and recursively links declared prerequisites. Without a manifest, it links the conventional <sourceRoot>/<name>/SKILL.md repository-local skill. It rejects missing or unsafe sources, paths outside either root, and existing non-matching destinations. targetRoot must already exist as a physical directory path: symlinked target roots or ancestors are rejected.

Validated feedback and delivery

Import createFeedbackEnvelope, validateFeedbackEnvelope, writeFeedback, verifyFreshFeedback, composeRetrospective, feedbackOutboxStatus, and flushFeedbackOutbox from the existing vouchington-tooling/agent-blackboard subpath. Consumers must run Node 24 or newer and install agent-blackboard@^0.6.0 explicitly alongside vouchington-tooling; the provider is not installed by this package. Missing provider installation returns client-unavailable; missing or invalid connection configuration returns configuration-invalid, separately from transport outages and authentication rejection. The upstream agent-blackboard client still owns the service protocol; this integration adds no provider schema or service. Supply consumer module context through dependencies.resolveFrom or inject the client loader at the transport boundary.

The version-one envelope retains canonical markdown and storage type: journal | retrospective. It requires exact canonical repositories, stable URL-safe sourceEventId, ISO timestamp, explicit workOutcome, and feedbackCoverage with status, sources, and dropped count. Optional category is context only. Retrospectives retain valid date and integer/string issue/PR references. Markdown is capped at 12 KB and the envelope at 16 KB. Known credentials are redacted; authors remain responsible for minimizing summaries and excluding raw logs, transcripts, environment dumps, and undisclosed secrets. A bound violation fails visibly without clipping findings.

writeFeedback({identity, envelope, mode, ...}) accepts an exact caller-owned session identity and never manufactures native agent identities. Interactive mode requires an absolute outbox directory. Ancestor ownership and permissions are not checked; existing directory and record modes are accepted. New directories and files default to 0700 and 0600. The outbox itself must be a real directory, and records must be regular files. The writer persists before transport with atomic rename, file/directory fsync, and a stable record path. The outbox holds at most 128 records and 2 MB. Saturation, corruption, or persistence failure blocks capture and preserves unsent records. Delivered records are removed only after matching readback. Pending state includes count and a safe diagnostic; interactive CLI exit zero means durable retention, and callers must inspect the printed status to know whether delivery was acknowledged. Autonomous errors and unpersisted writes fail nonzero. Identity, content, and archived-session conflicts fail in either mode while preserving the unsent record; they are not reported as transient pending delivery. Replay retains permanently conflicted records and continues to deliver unrelated pending records; transient failures stop that replay. Verified delivery retains its receipt when local cleanup fails, returning cleanupDiagnostic with value "outbox-cleanup-failed". A retained or crash-reappearing record is safe to replay: an event is identified by session, sourceEventId, and content, and a duplicate that differs only in timestamp is the same event, so it reports the stored record's timestamp and receipt and the retained duplicate is removed. Use vouchington agent-blackboard journal flush --outbox-directory PATH to replay unchanged pending records after connectivity returns.

Autonomous mode prohibits the filesystem outbox. verifyFreshFeedback requires a fresh source-event write plus readback of its own append receipt and rejects visible duplicate source records. This is fresh online reporting evidence, not a distributed execution lease: eventually consistent provider reads cannot establish source uniqueness. Trusted controllers supply a unique new authorization-probe source ID, preserve their authoritative run/session lineage, and atomically claim and revalidate the attempt before execution. Terminal writes keep work outcome separate from coverage and returned delivery state. The delivered result includes a verified receipt with session ID, source-event ID and creation time. Controllers require this online result together with atomically established attempt ownership before execution.

Delivery is at least once. Replays pre-read matching source identity/content, accept equivalent persistent duplicates, and reject conflicting reuse. Equality ignores object property order while preserving array order. Each online operation has a 20-second deadline (timeoutMs can shorten it); readback scans at most 10,000 records or 2 MB. The SDK does not expose cancellation for in-flight requests, so a timed-out write can commit later. That never grants admission or a delivery receipt; replay the identical envelope and source ID to verify its actual persistence.

composeRetrospective invokes the existing fact/transcript collectors with raw output disabled and generates required sections and markers. Tool and architectural assessments preserve observation, evidence, disposition and tracking reference. None-observed and unassessed states need a scoped reason. Complete coverage is rejected when required sources are unavailable or capture is partial. Typed collector reports expose availability independently of rendered text. Composition rejects aggregate dropped counts below observed friction drops and retains larger caller aggregates without double counting. Generated frontmatter carries validated work_outcome and feedback_coverage for consumers to preserve or reject conflicting explicit overrides; trusted mode stays external. Human top-five summaries do not authorize dropping additional durable findings.

The ## CI Failures and ## Sandbox & Permission Audit sections come from one optional audit source; the two inputs are mutually exclusive and supplying both throws before any collector runs. friction: {directory, journalLoader, ...} keeps reading the session-friction log together with the journal and is unchanged. journal: {journalLoader} needs no friction directory or log: both sections are assessed from the session's journal entries alone, and the report carries coverage.frictionStatus: 'journal-only' (in place of empty or events) so the text states that no log was observed. feedbackCoverage.status: 'complete' accepts either source. It is rejected when neither is supplied (the error names the missing source), and a journal-only audit does not count as assessed when the loader reports not-found (there is no log to establish that the session was observed), throws, or is truncated by the scan bounds.

await composeRetrospective({ ...input, journal: { journalLoader } })

journalLoader is the session-friction JournalLoader; JournalLoader, JournalLoadResult, JournalEntry, and JournalAuditOptions are exported as types from vouchington-tooling/agent-blackboard. The ## CI Failures block grammar and its three status lines (failures observed, none observed, unavailable (<reason>)) are the same for both sources. Journal-only sandbox and permission entries are journal Markdown entries that hold exactly one block, escaped and length-bounded like CI failures, and other entries are ignored:

- `sandbox-escalation` — git push — network write blocked
  - Outcome: requested | approved | denied | unknown
  - Evidence: permission prompt shown
  - Disposition: reran with approval
- `sandbox-failure` — node test — EPERM writing outside the worktree
  - Evidence: stderr showed EPERM
  - Disposition: moved output under TMPDIR

ambiguous-failure takes the same shape as sandbox-failure. The section reports Status: none observed or Status: events observed, each followed by (journal entries only; no friction log observed); a truncated scan reports unavailable (journal scan incomplete) with the entries read so far.

Basic Auth exemption facts

vouchington-tooling/basic-auth-doc-sync extracts literal exemption collections from TypeScript and route rows from Markdown. Callers configure declaration names and runbook headings, then compare the returned data using their own route policy. See the API contract.

TypeScript source graph

vouchington-tooling/source-module-graph exports createSourceModuleGraph. It accepts the modules report from released no-mistakes analyzeTypeScriptModules({ root, files }), plus the caller's root, ordered source extensions, aliases, and file inventory. It resolves local imports and reexport owners without reading or parsing source again. runtimeImports(file) uses binding references rather than declaration presence, and reachableFrom(entrypoints, { runtimeOnly: true }) follows used runtime imports, reexports, and literal dynamic/require loads. Missing or incomplete facts for a reached file throw; external specifiers resolve to null. The default file inventory limit is 10,000 files and can be reduced with maxFiles.

Retrospective distill classifier

vouchington-tooling/retrospective-distill exports classifySession(session, entries, cutoffs), which assigns a session one of retrospective, entry-type-unresolved, checkpoint-only, journal-only, zero-entry-child, or zero-entry-root and decides distillation eligibility against caller-supplied retroCutoff and sessionCutoff timestamps. It deduplicates replayed source events, quarantines unknown entry types, invalid feedback envelopes, and conflicting source events, and never marks an entry-type-unresolved session eligible. readPartitionRecords(path) reads a local agent-blackboard partition JSONL file; parseDistillClassifyArgs and runDistillClassify wrap both behind <partition.jsonl> --retro-cutoff <iso> --session-cutoff <iso> and print one tab-separated line per session. The code is the source of truth for the taxonomy; the retrospective-distill skill is its human-facing description.

Static schema-allowlist pairs

extractStaticStringPairs(source) from pg-schema-snapshot collects the first two string literals of every array expression in ESTree field traversal order, including arrays with extra elements. Conditional alternatives precede consequents, preserving the existing parser walker. It preserves duplicates and decoded string values. It does not evaluate imports, exported constants, spreads, or templates, and malformed source throws. Schema-allowlist consumers retain their own file selection, key filtering, deduplication, snapshot comparison, and diagnostics. Parsing is source-only and does not build a TypeScript compiler program or execute the source.

SQL view declarations

vouchington-tooling/sql-ast exports extractViewDeclarations(sql) and the ManagedViewDeclaration type. Await initSqlAst() before calling the extractor. It returns the qualified, PostgreSQL-quoted names and kinds of top-level CREATE VIEW and CREATE MATERIALIZED VIEW declarations. It ignores comments, string literals, and other SQL statements. Keywords that cannot be bare relation names remain quoted. Blank or unparseable SQL returns an empty array; parser initialization and unexpected errors propagate. Consumers own view teardown and lifecycle decisions.

SQL index shapes

vouchington-tooling/sql-ast exports asynchronous extractIndexShapes(sql). Await its result; it lazily loads the optional no-mistakes peer and requires version 0.81.0 or newer when called with nonblank SQL. Other SQL exports do not require this peer. It does not need initSqlAst(). It returns { idxname, table, shapeKey } for each named top-level CREATE INDEX. Consumers can group identical keys to detect collisions. Keys use upstream structural identity, including effective sort/null ordering, quoted relation identity, expressions, predicates, operator classes, and INCLUDE columns. Key serialization is opaque and must not be persisted across versions. Any parse diagnostic rejects the whole input. Anonymous indexes and indexes inside DO blocks are omitted. Consumer call sites must change from synchronous calls to await when adopting this release.

Publication writer inventory facts

vouchington-tooling/post-publication-inventory exports analyzePostPublicationWriterSource(source, fileName, options). It returns five booleans for an approved capture-helper call, a capture opt-out, writes through a configured entity table, generated relation writes, and eligibility-table writes. Consumers supply every module, symbol, property, receiver, and table name through PostPublicationWriterSourceOptions and retain their inventory schema, tracked files, exceptions, and diagnostics.

This preserves source-inventory heuristics, rather than proving runtime execution or SQL safety. Capture imports/calls are name-based and order-independent; relation-variable appends are order-sensitive. DML recognition examines literal/template text. Static table matching lowercases the extracted name; dynamic literal table matching preserves case. Malformed TypeScript uses the compiler's recovery tree. An argument-free append returns no relation fact. Pass TypeScript source (.ts or .mts); the parser uses TypeScript mode even if the file name ends in .tsx. Template expressions join their static fragments for DML matching, while DML prefixes for generated-table facts come from templates rather than ordinary quoted strings. Dynamic eligibility-table matching expects an unquoted literal immediately after the DML prefix and does not recognize DELETE FROM ONLY.

Publication reader source facts

The same subpath exports sourceImportsAndComposesAny, sourceImportsAndUsesBoundaryAny, and sourceFiltersWithPublicBoundary. Each accepts source text, selected imported symbols, and ReaderSourceAnalysisOptions. Configure allowed modules per imported symbol, SQL tag and executor imports through the existing ReaderSqlTemplateOptions, the ignored-call identifier, and the candidate ID property. Missing import configuration admits no module.

These functions preserve the existing lexical source heuristics: named import aliases, local builder bindings, reassignment rejection, append/push consumption, returned boundary results, and collection filtering with the selected ID set. They do not prove runtime execution, general call graphs, or type identity. Malformed source throws through the ESTree parser. Inventory selection, classifications, exceptions, and diagnostics remain consumer policy.

composesPublicEligibilityView(source, options) checks live SQL fragments with ReaderPublicViewOptions: SQL extraction settings, source and eligibility relation names, and their ID columns. Await initSqlAst() from vouchington-tooling/sql-ast before calling it. The existing parser is reused; no separate SQL facts or parser dependency is introduced.

The check preserves the existing nested SELECT/CTE, equality, inner-join, and correlated EXISTS heuristics. It rejects weakened OR/NOT/boolean/CASE predicates and non-filtering left joins. Every recognized live source reader must be protected. Unparseable SQL fragments are skipped; malformed source returns false. These are bounded syntactic heuristics, not a general SQL safety proof.