VV

vouchington/vouchington-tooling

Developer tools
0 stars 품질 66 트렌드 20MIT

Public tooling extracted from the Vouchington product monorepo. Two npm packages, one CLI.

개요

Public tooling extracted from the Vouchington product monorepo. Two npm packages, one CLI. Both packages are published to npm. Releases go through the Release workflow (workflow_dispatch) using npm trusted publishing (OIDC). Do not publish from a laptop. The repository also publishes the public security-triage, vouchington-workflow, vouchington-testing, and vouchington-database agent plugins. security-triage has one repository-neutral security-finding skill. vouchington-workflow provides reusable implementation, commit, GitHub Actions, Dependabot, package-metadata, npm-publishing, static-analysis, planning, issue-management, blackboard journaling, retrospective and follow-up review, CI-log review, stacked-pull-request draining, and pull-request-description skills. All plugins use one canonical skills/ tree for every supported host; consumer repositories add their local mechanics and policy in repository-local instruction files or thin wrapper skills.

README

vouchington-tooling

Public tooling extracted from the Vouchington product monorepo. Two npm packages, one CLI.

Package What it is
vouchington-tooling Libraries plus the vouchington CLI
eslint-plugin-vouchington Non-generic Vouchington ESLint / Oxlint rules

Both packages are published to npm. Releases go through the Release workflow (workflow_dispatch) using npm trusted publishing (OIDC). Do not publish from a laptop.

Agent plugins

The repository also publishes the public security-triage, vouchington-workflow, vouchington-testing, and vouchington-database agent plugins. security-triage has one repository-neutral security-finding skill. vouchington-workflow provides reusable implementation, commit, GitHub Actions, Dependabot, package-metadata, npm-publishing, static-analysis, planning, issue-management, blackboard journaling, retrospective and follow-up review, CI-log review, stacked-pull-request draining, and pull-request-description skills. All plugins use one canonical skills/ tree for every supported host; consumer repositories add their local mechanics and policy in repository-local instruction files or thin wrapper skills. The portable issue workflow verifies live collaborator authority before creation, routes denied external work to a verified consumer tracker, uses existing labels without extra approval, and requires explicit approval before creating labels. Consumers still own repository defaults, taxonomy definitions, templates, and stricter policy.

Domain skill entrypoints read applicable AGENTS.md and a repository-local adapter when present. The default adapter is .agents/skills//SKILL.md; local instructions may name an alias, such as nextjs-vitest-test-authoring → web-vitest-test-authoring. A previously read adapter or canonical skill is not loaded again. This is agent guidance, not runtime concatenation or a new loader API; linked files and plugin installation alone do not prove an adapter was read. Workflow references load by phase. Plans are proportional and saved once outside Git, including in an existing issue or PR description; the skills do not require a separate Plan issue or template. The github-actions-authoring skill requires event-driven orchestration and prohibits remote-state polling in CI; it loads github-actions-checklist as a prerequisite. The checklist also defines the portable trigger, 30-minute timeout, runner, action-pinning, dependency-update testing, real required checks, domain-oriented test jobs, and branch-aware concurrency policies.

security-triage is intentionally repository-neutral: it analyzes findings and returns a versioned handoff, while each consuming repository owns issue taxonomy and issue creation.

vouchington-testing supplies shared test-authoring guidance plus Vitest, backend, Next.js, Playwright, Storybook, Swift, and .NET specializations. vouchington-database supplies PostgreSQL performance and UUIDv7 partitioning guidance. Consumer wrappers own runner configuration, fixtures, database policy, and commands.

These integrations are opt-in. Installing a package or cloning this repository does not enable an AI coding platform, transcript adapter, workflow, or CI provider. Select only the plugin directories, transcript formats, and provider-specific Actions adapters that your repository explicitly adopts; generic skills remain host-neutral and read the consuming repository’s local instructions.

This repository adopts Agent Blackboard for durable agent-session notes. The vouchington-workflow journaling skills call the tools of the vouchington mcp server, which vouchington-machines registers once per machine as vouchington-tooling in each harness, not per repository; it also disables the upstream agent-blackboard plugin machine-wide (decision vouchington#1019). This repository carries no MCP, Claude settings, or Codex config for it. Credential-management commands remain CLI-only. MCP is the supported path. When it is unavailable, the journaling skill has agents tell the human how to restore it; its CLI fallback is a last resort and requires both a journal entry and a human-facing notice.

Install (opt-in)

Codex:

codex plugin marketplace add vouchington/vouchington-tooling --ref main
codex plugin add security-triage@vouchington
codex plugin add vouchington-workflow@vouchington
codex plugin add vouchington-testing@vouchington
codex plugin add vouchington-database@vouchington

Claude:

claude plugin marketplace add vouchington/vouchington-tooling --sparse .claude-plugin plugins
claude plugin install security-triage@vouchington
claude plugin install vouchington-workflow@vouchington
claude plugin install vouchington-testing@vouchington
claude plugin install vouchington-database@vouchington

Grok:

grok plugin install vouchington/vouchington-tooling#plugins/security-triage
grok plugin install vouchington/vouchington-tooling#plugins/vouchington-workflow
grok plugin install vouchington/vouchington-tooling#plugins/vouchington-testing
grok plugin install vouchington/vouchington-tooling#plugins/vouchington-database

Other Claude-compatible clients that support the same direct-install syntax can select either plugin directory.

Cursor loads local Agent Plugins. Clone the source once and link its plugin directory into Cursor’s local plugin root, then restart Cursor or reload the window:

mkdir -p ~/.cursor/plugins/sources ~/.cursor/plugins/local
git clone --depth 1 https://github.com/vouchington/vouchington-tooling.git \
  ~/.cursor/plugins/sources/vouchington-tooling
ln -s ~/.cursor/plugins/sources/vouchington-tooling/plugins/vouchington-workflow \
  ~/.cursor/plugins/local/vouchington-workflow
ln -s ~/.cursor/plugins/sources/vouchington-tooling/plugins/security-triage \
  ~/.cursor/plugins/local/security-triage
ln -s ~/.cursor/plugins/sources/vouchington-tooling/plugins/vouchington-testing \
  ~/.cursor/plugins/local/vouchington-testing
ln -s ~/.cursor/plugins/sources/vouchington-tooling/plugins/vouchington-database \
  ~/.cursor/plugins/local/vouchington-database

The clone and symlink commands intentionally fail if either target already exists, preventing an update from overwriting or nesting an existing local plugin.

Centralized Cursor marketplace publication is not part of this repository change.

GitHub Actions

Pin composite actions by commit SHA and keep a trailing # vX.Y.Z comment. Git tags are vouchington-tooling/vX.Y.Z (slash-separated) so Dependabot can parse them. Hyphenated vouchington-tooling-vX.Y.Z tags from before v0.6.2 are historical. The Backfill slash release tags workflow aliases those hyphen tags onto the same commits without creating GitHub Releases or publishing to npm.

Pin the public Dependabot automerge action by commit SHA.

- uses: vouchington/vouchington-tooling/.github/actions/dependabot-automerge@ # vX.Y.Z
  with:
    automerge_token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }}
    # Optional: JSON rules that require manual merge for an ecosystem/directory.
    manual_update_rules: '[{"packageEcosystem":"nuget","directory":"/native"}]'

dependabot-automerge fetches trusted Dependabot metadata with the workflow token, only enables auto-merge for patch updates at any version and minor updates with a stable target on major 1 or later, and rechecks the live bot-owned same-repository branch before using the dedicated token to enable eligible auto-merge or disable stale auto-merge. Enable auto-merge once per PR on opened, reopened, and ready_for_review. Do not re-run enablement on synchronize. Keep edited so a base-branch retarget can disable stale auto-merge. Already-armed PRs are a no-op. Unsigned or otherwise unverified HEAD (mixed repair commits) is a successful human-merge no-op and does not fail the job. The automerge_token must be a dedicated token because a GITHUB_TOKEN merge does not trigger downstream workflows. It must be stored specifically as a repository Dependabot secret, or as an organization Dependabot secret selected for every consumer repository—not only as an Actions secret—and needs Contents and Pull requests read/write permission. Mutation failures intentionally fail the job so a broken or underprivileged token cannot look like successful automation. Both manual-rule fields must exactly match dependabot/fetch-metadata; ecosystems are lowercase and directories include the leading slash. Use the action only from a trusted pull_request_target workflow that checks out the exact base SHA with credentials disabled; never check out or execute pull-request code.

The action never submits or requires an approval review. Branch-protection required checks remain the merge gate; consumers should not add a separate workflow that auto-approves Dependabot PRs.

Required-result gate

Pin ci-required-result-gate by its full 40-character commit SHA to give a required fan-in job a strict, compact dependency-result contract. The action accepts only a non-empty JSON object whose entries contain exactly a result of success or skipped; failures, cancellations, missing result fields, and malformed input fail the gate. It is dependency-free and resolves its checked-in shell script from GITHUB_ACTION_PATH, so it does not require checkout or Node dependencies.

- uses: vouchington/vouchington-tooling/.github/actions/ci-required-result-gate@ # vX.Y.Z
  with:
    results: >-
      {"tests":{"result":"${{ needs.tests.result }}"},"lint":{"result":"${{ needs.lint.result }}"}}

Keep the full commit SHA authoritative. The trailing comment must be this package’s release version (# vX.Y.Z for tag vouchington-tooling/vX.Y.Z) so Dependabot can compare it. An action-local # v1.0.0 looks newer than 0.y.z package tags, so Dependabot never proposes a bump. Build the compact object explicitly from each dependency’s result instead of passing toJSON(needs), which may contain unsupported fields or exceed process environment limits. The caller owns key-set completeness: keep a repository test that compares the explicit keys with the fan-in job’s declared needs. A second hand-built expected-key input would duplicate the same contract and could drift independently.

Use mode: build only when preserving an existing build-gate name or message contract; it applies the same success/skipped acceptance rule.

CLI

vouchington --help
vouchington --version
vouchington runner-port-policy
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 ast-grep-pack
vouchington gha-output name
vouchington gha-needs-results
vouchington download-with-diagnostics  
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-*'
vouchington http-origin --field cdn_origin https://images.example.com
vouchington vitest-blob-manifest  [reports-directory]
vouchington vitest-report-attempt write  
vouchington vitest-report-attempt read 
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 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
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  

pnpm-install runs the pnpm on PATH and never reads the consumer’s packageManager field, so consumers need no pnpm pin. It works with pnpm 11 and 12. The metadata fingerprint includes pnpm --version and every workspace manifest, so changing either triggers one reconciling install.

For persistent pnpm-install, v5 metadata tracks structural inputs separately from the --install-scripts policy and records scriptsEnabledInstallVerified only after pnpm reports a parseable empty pendingBuilds ledger. A v4, malformed, or missing stamp on a populated tree, a matching stamp with pending or unreadable build state, and an unverified scripts-enabled tree all use two script-free forced reconciliation passes. If a scripts-enabled install or reconciliation leaves a parseable nonempty ledger, it completes pnpm’s own generic pnpm rebuild --pending --recursive finalization. Before that rebuild, it safely deduplicates identical pending IDs. After rebuilding, it removes only residual IDs proven absent from pnpm’s current workspace and installed virtual-store lockfiles, without dropping live dependencies or workspace importers. Removed stale IDs are reported. This covers pnpm 11.13.1’s duplicate-importer and stale-package ledger behavior, then rechecks native and workspace-link health and requires an empty ledger. Unreadable or unresolved ledger state fails without refreshing the stamp for scripts-enabled runs. Scripts-disabled installs can finish with unreadable state, but write an unverified stamp so the next scripts-enabled invocation reconciles. They retain verification only when the matching prior stamp was verified and pnpm still reports an empty ledger. 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 two script-free reconciliation passes plus generic pending finalization. Native and workspace-link health are verified after the two script-free passes and any generic pending rebuild, before its metadata stamp is refreshed. ignoredBuilds remains consumer policy, but disqualifies isolated native repair. 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 flags (mutually exclusive with --pattern), lists the run’s artifacts once, and extracts every requested name that is present into /. 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= exit=, exits non-zero (a downloader exit of 3 is reported as 1 so it cannot be mistaken for absence), and writes no availability output.

Machine-wide agent settings now belong to vouchington-machines. Use its configure-agents.sh and diagnose-agents.sh; see the migration note.

Packages

vouchington-tooling

Subpath imports keep consumers off modules they do not need. Heavy parsers are optional:

import { isRunnerReservedPort, runnerPortPolicy } from 'vouchington-tooling/runner-port-policy'
import { initSqlAst, extractCreateTableMetadata } from 'vouchington-tooling/sql-ast'
import { splitSqlStatements } from 'vouchington-tooling/sql-scanner'
import { auditCiJobRuntime } from 'vouchington-tooling/gha-runtime-audit'
import { 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 { 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 { decide } from 'vouchington-tooling/transient-retry'
import { parseCsvRows } from 'vouchington-tooling/csv'
import { readResponseBody } from 'vouchington-tooling/http-body'
import { parseReviewPayload } from 'vouchington-tooling/gha-review-payload'
import { runPostReview } from 'vouchington-tooling/gha-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 { 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 { isSwiftCodeOffset } from 'vouchington-tooling/swift-source-offset'
import { validateResolvedPinDelta } from 'vouchington-tooling/swift-resolved-pin-delta'
import { runRetrospectiveTranscript } from 'vouchington-tooling/retrospective-transcript'
import { buildSessionFrictionReport, recordFriction } from 'vouchington-tooling/session-friction'
import { createPullRequest, processDiffCommand, runGh, runGit } from 'vouchington-tooling/gh-cli'

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.

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,
})

sql-ast requires the optional dependency @libpg-query/parser. sql-scanner does not. dockerfile-parse uses dockerfile-ast.

session-friction remains dormant until a caller explicitly supplies a session id, absolute log directory, hook observation, and journal loader. Host payload parsing, hook installation, session discovery, and journal transport stay with the consuming repository. Capture stores at most 500 events per session, counts rejected captures in a bounded atomic sidecar, 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. Log reads are capped at 2 MB, journal Markdown at 10,000 bytes per entry, and newly created evidence directories and files are owner-only. Recording and report construction synchronously access the evidence log and may wait up to one second for a contended per-session file lock before failing explicitly. Evidence-directory validation requires POSIX ownership and mode checks (Linux and macOS), so session-friction throws on Windows. Command-prefix normalization attempts limited redaction of obvious credential patterns but is not a secret scrubber; callers must not include credentials in captured commands.

composeRetrospective (vouchington-tooling/agent-blackboard) can also assess ## CI Failures and ## Sandbox & Permission Audit from journal entries alone with journal: {journalLoader}, which needs no friction directory or log and reports frictionStatus: 'journal-only'. It is an alternative to the friction input, and the two are mutually exclusive.

Security-sensitive helpers are provider-neutral and fail closed on malformed artifacts, payloads, response bodies, and pagination links. Product policy, credentials, and network transport remain in the consuming repository.

eslint-plugin-vouchington

House-style rules shared across Vouchington repositories. Rule routing:

  1. Generic (any TypeScript/JavaScript repo) → eslint-plugin-no-mistakes
  2. Vouchington convention with no product nouns → this plugin
  3. Single-repo product coupling → stays in the product monorepo

The plugin currently ships postgres-cursor-call-contract, banned-member-read, and factory-owner-location. Callers pass module specifiers, members, factories, and owner files; product paths stay in the consuming repository.

Development

Requires Node 24+ and pnpm 12. The repository does not pin pnpm: no manifest declares packageManager, and local work uses whichever pnpm 12 is installed. CI asks pnpm/action-setup for latest-12 after actions/setup-node, so it runs the newest pnpm 12 release that is at least one day old. New 12.x releases reach CI without a PR; moving to pnpm 13 needs one. pnpm-setup-policy.test.mts enforces that shape.

pnpm install
pnpm run lint
pnpm run typecheck
pnpm run build
pnpm test

pnpm run lint includes the jscpd clone-size gate and the scc complexity ceiling. Both match the Vouchington product repository: any clone of 200 lines or more fails at 85% similarity, and scc 3.7.0 fails a counted file whose complexity is over 50.

Run the local CLI after a build:

node packages/vouchington-tooling/dist/cli/index.mjs --help

Validated journal and retrospective feedback uses the existing agent-blackboard subpath. Explicit interactive mode persists sanitized pending records in a bounded outbox; autonomous mode requires fresh online admission and acknowledged terminal readback. Work outcome, evidence coverage, and delivery remain separate. See the feedback contract for current APIs, privacy bounds, stable event replay, and the breaking journal writer adoption.

View this README on GitHub

추천 도구

다른 키워드를 입력하거나 필터를 제거해 보세요.

설치

npx skillfish add vouchington/vouchington-tooling