tmu da5ab79f9b ♻️ Replace verify skill with an npm verify script
A skill duplicated AGENTS.md policy and only worked in Agent-Skills harnesses.
A bare top-level script is the repo-native affordance: every harness (and CI,
and a human) reads package.json#scripts as the source of truth. Add
`npm run verify` = `npm run check` + `test:unit` (tsc runs once, since check
already type-checks) as the one-shot whole-project correctness gate.

Delete .agents/skills/verify/SKILL.md. Document verify in README (Development +
a Tooling-decisions bullet + bare-command note in the prefix list), CONTRIBUTING
(feedback-tier table, "Before pushing", the bare-command paragraph, a "why these
splits" bullet), and AGENTS.md (test = fast iterating gate, verify = definition
of done; skill pointer removed).
2026-09-05 21:46:59 +02:00
2026-02-02 13:38:42 +01:00
2025-04-29 13:43:07 +02:00
2026-09-04 23:53:26 +02:00

tiny-pattern-ts

Pattern matching for TypeScript/ESM environments (F#-style, not regex).

Development

  • Build: npm run build
  • Test: npm run test, npm run test:ci
  • Watch: npm run watch (re-runs tests on file save; the earliest feedback tier)
  • Checks: npm run check, npm run fix
  • Verify (definition of done): npm run verify — npm run check + the unit suite in one shot; the whole-project correctness gate (excludes advisory maintain)
  • Maintenance (advisory): npm run maintain — knip + check-outdated; run on a maintenance / update-deps branch, not part of the feature loop
  • Individual fixes: npm run fix:oxfmt, npm run fix:oxlint

Tooling

  • TypeScript 7 — type checker and build (tsc).
  • node --test + --experimental-strip-types — test runner (Node 22.6+, flag dropped on Node 24).
  • c8 — code coverage for test:ci.
  • oxlint — Rust-based linter. Type-aware rules are enabled via options.typeAware: true in .oxlintrc.json (powered by oxlint-tsgolint).
  • oxlint-tsgolint — type-aware linting via typescript-go (declarative via .oxlintrc.json, no CLI flag). Catches unsafe type assertions, unnecessary type parameters, and other type-system issues that regular oxlint can't see. Source-level oxlint-disable directives are used to silence known false positives (e.g., expectTypeOf() in test files).
  • oxfmt — Rust-based formatter (Prettier-compatible). Formats JS/TS, JSON/JSONC, YAML, Markdown, MDX, and more; built-in package.json key sorting replaces sort-package-json.
  • cspell — spell checking.
  • knip — finds unused dependencies, exports, and files. Scoped via --include dependencies,exports,files to skip the noisy types category (which produces false positives for libraries whose exported types are part of the public API).
  • publint — validates package.json for ESM publishing correctness. Runs on publish only (in CI), not as part of npm run check.
  • @arethetypeswrong/cli (attw) — validates .d.ts declarations against multiple module-resolution scenarios. Runs on publish only with --profile esm-only (the package is intentionally ESM-only).
  • lefthook — git pre-commit hooks.

Tooling decisions

The choice and configuration of each tool above is the result of deliberate trade-offs, not defaults. The non-obvious ones:

  • tsconfig.json extends @tsconfig/strictest + @tsconfig/node26; tsconfig.build.json extends it to add the emit-only options (declaration, sourceMap, outDir, target: es2024, rewriteRelativeImportExtensions: true) and to exclude test files. This separation lets the editor and CI type-check from one config while the build emits from the other.
  • Source imports use .ts extensions so node --strip-types resolves them at test time. rewriteRelativeImportExtensions: true in tsconfig.build.json rewrites them to .js in the emitted dist/* output, so consumers see conventional ESM imports.
  • Type-aware oxlint is enabled declaratively via options.typeAware: true in .oxlintrc.json (powered by oxlint-tsgolint). The script commands stay clean — no CLI flag — and type-aware mode is a property of the config, not the invocation.
  • Source-level oxlint-disable directives are used for known type-aware false positives (see src/pattern.ts, src/match.ts, src/index.test.ts). The disable lives next to the code it silences, not in .oxlintrc.json, so the trade-off is visible to anyone reading the source.
  • knip --include dependencies,exports,files intentionally omits the types category, which produces systematic false positives for libraries whose exported types are part of the public API. The targeted scope keeps the signal high without config-file boilerplate.
  • attw --profile esm-only is semantically correct: this package is intentionally ESM-only (no CommonJS shim), so CJS resolution scenarios are out of scope by design, not a bug.
  • The publish: prefix has no local aggregator. publint and attw validate the publishable artifact (dist/), not the source, and require a fresh build. They run only in the CI publish job immediately before npm publish — there is intentionally no npm run publish.
  • check:tsc runs first in the npm run check chain so a type error short-circuits the rest (faster feedback than letting oxlint/oxfmt run and then failing on tsc at the end).
  • verify is the one-shot definition of done. npm run verify composes npm run check with the unit suite (test:unit) into a single whole-project correctness gate, so a human or an agent reaches for one command instead of re-deriving the sequence. It deliberately uses test:unit (not test) because check already runs check:tsc — so tsc runs exactly once. It excludes maintain (advisory) by design. CI is not switched to it: the build job runs check + test:ci to also collect coverage.
  • The check: / maintain: split is correctness gates vs. advisory scans. npm run check is the fast, offline, whole-project correctness ladder (tsc → oxlint → oxfmt → cspell) and can run anywhere, including the agent loop. knip (~4s, whole project) and check-outdated (~6.5s, queries the npm registry) are advisory, not correctness — a stale dependency or an unused export must not fail a feature PR — so they moved to npm run maintain, kept out of pre-commit, and run in CI as a non-blocking job (see .github/workflows/ci.yml). Note check-outdated exits non-zero whenever any dep is outdated, which is exactly why it must not gate merges.
  • The pre-commit hook sets the LEFTHOOK_FILES env var to the staged-files list, and the affected scripts use ${LEFTHOOK_FILES:-<default>} to default to the whole project when invoked manually. This keeps package.json#scripts as the single source of truth for the underlying commands — lefthook.yml only describes what to run on which files.
  • tslib and type-fest are deliberately not used. tslib is a runtime helper for old ES3/ES5 targets (the project targets ES2024); type-fest was never imported. knip caught both.

Requirements

  • Node.js >= 26 (engines field; pinned via .node-version).

VSCode integration

  • Recommended extensions: see .vscode/extensions.json (oxc, cspell).
  • TypeScript 7 is used via the typescriptteam.native-preview extension.
  • oxc extension provides oxlint squiggles and oxfmt format-on-save.

Workflows

  • Version updates via npm version.
  • Publishing via GitHub Actions on tagged commits (see .github/workflows/ci.yml); the publish job runs publish:publint and publish:attw before npm publish.

Script prefix convention

Script names follow a prefix convention that signals when they run:

  • check:* — read-only verification. Aggregated by npm run check. Used in pre-commit hooks and CI's build job.
  • fix:* — mutating counterpart of check:*. Aggregated by npm run fix. Use after npm run check to auto-resolve issues.
  • test:* — test scripts. npm run test runs the full suite; test:unit / test:ci are scope-specific variants.
  • maintain:* — advisory repo-maintenance scans (dead code, dependency freshness). Aggregated by npm run maintain. Whole-project and/or network-bound, so not correctness gates: run on a maintenance branch, and in CI as a non-blocking job that reports without failing.
  • publish:* — runs only at publish time, in the CI publish job (immediately before npm publish). There is no local npm run publish script — publishing is CI-only by policy.

Bare, prefix-free top-level commands are the entry points: build, clean, check, fix, test, watch, maintain, and verify. verify (check + test:unit) is the one-shot "whole-project correctness" gate; maintain is the advisory counterpart that never gates a merge.

Contributing

For maintainer and contributor docs — the script prefix convention, the feedback-tier system, the rules the tools don't enforce, and the publishing workflow — see CONTRIBUTING.md. AI coding agents: your entry point is AGENTS.md, which points back to CONTRIBUTING.md.

  • Commit signing (GPG).
  • Set up commit message template: npm run use:git-commit-message.
  • See commit-message-template.
  • Type-only tests use expect-type's expectTypeOf(...) inside node --test cases.
S
Description
No description provided
Readme MIT
1.5 MiB
0 Stars 1 Watchers 0 Forks
0.9.0
Latest
2026-09-29 23:57:54 +02:00
Languages
TypeScript 88.4%
Shell 9.9%
Dockerfile 1.7%