{"_id":"@codegeneai/quality","_rev":"4-538b8eae542d9fdc56d1385b06f1c550","name":"@codegeneai/quality","dist-tags":{"latest":"2.2.3"},"versions":{"2.2.0":{"name":"@codegeneai/quality","version":"2.2.0","keywords":["quality","lint","biome","monorepo","ci","pipeline","adapters","hooks","bun","cli"],"license":"MIT","_id":"@codegeneai/quality@2.2.0","maintainers":[{"name":"rszemplinski","email":"rszemplinski22@gmail.com"}],"homepage":"https://github.com/CodeGeneAI/quality#readme","bugs":{"url":"https://github.com/CodeGeneAI/quality/issues"},"bin":{"quality":"src/bin.ts"},"dist":{"shasum":"7d88ef54cadf7767e7e6ac805acdb3b21fe48119","tarball":"https://registry.npmjs.org/@codegeneai/quality/-/quality-2.2.0.tgz","fileCount":85,"integrity":"sha512-KDSfOCGc8vgC1nYvkQz8KwF0ukKmktYt0HXN8F9w5/R9XfOG/N2EC2zsxyoLnTuu97GZfZPf8vtq8G+VVbW0hA==","signatures":[{"sig":"MEYCIQDe9wuMNBxa1yg48v0RW9fPev0zj3HPeL/yyyLiPrds9gIhALdNOi2c+gTogaAVNdl0YftvbrWPBM2a8UGHuGwssYrV","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":558150},"type":"module","engines":{"bun":">=1.3.0"},"exports":{".":"./src/index.ts","./cli":"./src/cli/index.ts","./schemas/quality.schema.json":"./schemas/quality.schema.json","./schemas/qualityrc.schema.json":"./schemas/qualityrc.schema.json"},"gitHead":"d06090490a75718bec6b6cc9220373f6e510df3e","scripts":{"lint":"biome check --write --diagnostic-level=error","clean":"rm -rf dist build lib out coverage .nyc_output .turbo .vite .cache node_modules tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo tmp temp","start":"bun src/bin.ts","test:unit":"files=$(find . -type f \\( -name '*.unit.spec.ts' -o -name '*.unit.spec.tsx' -o -name '*.unit.test.ts' -o -name '*.unit.test.tsx' \\)); if [ -n \"$files\" ]; then bun test $files; else echo 'No unit tests found'; fi","typecheck":"bun x tsgo --noEmit","prepublishOnly":"bun run typecheck && bun run test:unit"},"_npmUser":{"name":"rszemplinski","email":"rszemplinski22@gmail.com"},"repository":{"url":"git+https://github.com/CodeGeneAI/quality.git","type":"git"},"_npmVersion":"10.9.2","description":"Declarative quality pipeline (lint, format, hooks) with composable stage adapters for monorepo workflows","directories":{},"sideEffects":false,"_nodeVersion":"22.17.1","dependencies":{"zod":"4.4.3","kleur":"4.1.5","clipanion":"4.0.0-rc.4","micromatch":"4.0.8","typescript":"6.0.3","jsonc-parser":"3.3.1","diff-match-patch":"1.0.5"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"packageManager":"bun@1.3.14","devDependencies":{"ajv":"8.20.0","@types/bun":"1.3.14","@biomejs/biome":"2.4.15","@types/micromatch":"4.0.10","@types/diff-match-patch":"1.0.36","@typescript/native-preview":"7.0.0-dev.20260510.1"},"_npmOperationalInternal":{"tmp":"tmp/quality_2.2.0_1778892460606_0.25627055524452746","host":"s3://npm-registry-packages-npm-production"}},"2.2.1":{"name":"@codegeneai/quality","version":"2.2.1","keywords":["quality","lint","biome","monorepo","ci","pipeline","adapters","hooks","bun","cli"],"license":"MIT","_id":"@codegeneai/quality@2.2.1","maintainers":[{"name":"rszemplinski","email":"rszemplinski22@gmail.com"}],"homepage":"https://github.com/CodeGeneAI/quality#readme","bugs":{"url":"https://github.com/CodeGeneAI/quality/issues"},"bin":{"quality":"src/bin.ts"},"dist":{"shasum":"10adcf5cab96a08d79aed2533ea8be03ec885374","tarball":"https://registry.npmjs.org/@codegeneai/quality/-/quality-2.2.1.tgz","fileCount":85,"integrity":"sha512-GiROOhBdQ1ukIWm/xLVK/SATS0KU4o/vS60Fh7+fNBKz6uWBGeS2nQ8fQN9pcVue8JSf8daIO4g9nQ3ZLVqrew==","signatures":[{"sig":"MEYCIQCStxB3eaVp7Taj52ct4RmfTRtxf7ydmHrZyIxO+3Lr5wIhAIqPZW2QqfhqQ8FPg/MxOZMEtWu5hhjDmAzCWmGcxezb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@codegeneai%2fquality@2.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":560779},"type":"module","engines":{"bun":">=1.3.0"},"exports":{".":"./src/index.ts","./cli":"./src/cli/index.ts","./schemas/quality.schema.json":"./schemas/quality.schema.json","./schemas/qualityrc.schema.json":"./schemas/qualityrc.schema.json"},"gitHead":"c0226e26cc095cf79e632fcb2b5b399aac1ad8e3","scripts":{"lint":"biome check --write --diagnostic-level=error","clean":"rm -rf dist build lib out coverage .nyc_output .turbo .vite .cache node_modules tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo tmp temp","start":"bun src/bin.ts","test:unit":"files=$(find . -type f \\( -name '*.unit.spec.ts' -o -name '*.unit.spec.tsx' -o -name '*.unit.test.ts' -o -name '*.unit.test.tsx' \\)); if [ -n \"$files\" ]; then bun test $files; else echo 'No unit tests found'; fi","typecheck":"bun x tsgo --noEmit","prepublishOnly":"bun run typecheck && bun run test:unit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f429c082-867c-4324-9feb-c01f024643b9"}},"repository":{"url":"git+https://github.com/CodeGeneAI/quality.git","type":"git"},"_npmVersion":"11.12.1","description":"Declarative quality pipeline (lint, format, hooks) with composable stage adapters for monorepo workflows","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"zod":"4.4.3","kleur":"4.1.5","clipanion":"4.0.0-rc.4","micromatch":"4.0.8","typescript":"6.0.3","jsonc-parser":"3.3.1","diff-match-patch":"1.0.5"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"packageManager":"bun@1.3.14","devDependencies":{"ajv":"8.20.0","@types/bun":"1.3.14","@biomejs/biome":"2.4.15","@types/micromatch":"4.0.10","@types/diff-match-patch":"1.0.36","@typescript/native-preview":"7.0.0-dev.20260510.1"},"_npmOperationalInternal":{"tmp":"tmp/quality_2.2.1_1778897167704_0.174408134955367","host":"s3://npm-registry-packages-npm-production"}},"2.2.2":{"name":"@codegeneai/quality","version":"2.2.2","keywords":["quality","lint","biome","monorepo","ci","pipeline","adapters","hooks","bun","cli"],"license":"MIT","_id":"@codegeneai/quality@2.2.2","maintainers":[{"name":"rszemplinski","email":"rszemplinski22@gmail.com"}],"homepage":"https://github.com/CodeGeneAI/quality#readme","bugs":{"url":"https://github.com/CodeGeneAI/quality/issues"},"bin":{"quality":"src/bin.ts"},"dist":{"shasum":"a82cf972ad67aa756b403ae21ed06bd1b4efd1b7","tarball":"https://registry.npmjs.org/@codegeneai/quality/-/quality-2.2.2.tgz","fileCount":85,"integrity":"sha512-Xq1wQOKQwEc2AO2+8Xv5v4BZOutSJYheBcYlv+Hy7OZaTm4QAsdIc68L+bQ/91bWuy75uCUmB740dqQ6F56JfA==","signatures":[{"sig":"MEQCIGm2d3Bfmi4YJhdtZ6uWu7suA34Bpm4FT4QXk6yxrUS/AiB4AH6e4BEcuyrem0T/jvqhn+Vl+kcPVtESQaNUQ4mTBA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@codegeneai%2fquality@2.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":560839},"type":"module","engines":{"bun":">=1.3.0"},"exports":{".":"./src/index.ts","./cli":"./src/cli/index.ts","./schemas/quality.schema.json":"./schemas/quality.schema.json","./schemas/qualityrc.schema.json":"./schemas/qualityrc.schema.json"},"gitHead":"02ba01c3073dda30c1e2f37a7a30ae18a4f91eb0","scripts":{"lint":"biome check --write --diagnostic-level=error","clean":"rm -rf dist build lib out coverage .nyc_output .turbo .vite .cache node_modules tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo tmp temp","start":"bun src/bin.ts","test:unit":"files=$(find . -type f \\( -name '*.unit.spec.ts' -o -name '*.unit.spec.tsx' -o -name '*.unit.test.ts' -o -name '*.unit.test.tsx' \\)); if [ -n \"$files\" ]; then bun test $files; else echo 'No unit tests found'; fi","typecheck":"bun x tsgo --noEmit","prepublishOnly":"bun run typecheck && bun run test:unit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f429c082-867c-4324-9feb-c01f024643b9"}},"repository":{"url":"git+https://github.com/CodeGeneAI/quality.git","type":"git"},"_npmVersion":"11.12.1","description":"Declarative quality pipeline (lint, format, hooks) with composable stage adapters for monorepo workflows","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"zod":"4.4.3","kleur":"4.1.5","clipanion":"4.0.0-rc.4","micromatch":"4.0.8","typescript":"6.0.3","jsonc-parser":"3.3.1","diff-match-patch":"1.0.5","@types/micromatch":"4.0.10","@types/diff-match-patch":"1.0.36"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"packageManager":"bun@1.3.14","devDependencies":{"ajv":"8.20.0","@types/bun":"1.3.14","@biomejs/biome":"2.4.15","@typescript/native-preview":"7.0.0-dev.20260510.1"},"_npmOperationalInternal":{"tmp":"tmp/quality_2.2.2_1778897737033_0.015566013194250994","host":"s3://npm-registry-packages-npm-production"}},"2.2.3":{"name":"@codegeneai/quality","version":"2.2.3","type":"module","license":"MIT","description":"Declarative quality pipeline (lint, format, hooks) with composable stage adapters for monorepo workflows","keywords":["quality","lint","biome","monorepo","ci","pipeline","adapters","hooks","bun","cli"],"homepage":"https://github.com/CodeGeneAI/quality#readme","bugs":{"url":"https://github.com/CodeGeneAI/quality/issues"},"repository":{"type":"git","url":"git+https://github.com/CodeGeneAI/quality.git"},"packageManager":"bun@1.3.14","sideEffects":false,"bin":{"quality":"src/bin.ts"},"exports":{".":"./src/index.ts","./cli":"./src/cli/index.ts","./schemas/qualityrc.schema.json":"./schemas/qualityrc.schema.json","./schemas/quality.schema.json":"./schemas/quality.schema.json"},"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"engines":{"bun":">=1.3.0"},"scripts":{"start":"bun src/bin.ts","lint":"biome check --write --diagnostic-level=error","typecheck":"bun x tsgo --noEmit","test:unit":"files=$(find . -type f \\( -name '*.unit.spec.ts' -o -name '*.unit.spec.tsx' -o -name '*.unit.test.ts' -o -name '*.unit.test.tsx' \\)); if [ -n \"$files\" ]; then bun test $files; else echo 'No unit tests found'; fi","prepublishOnly":"bun run typecheck && bun run test:unit","clean":"rm -rf dist build lib out coverage .nyc_output .turbo .vite .cache node_modules tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo tmp temp"},"dependencies":{"@types/diff-match-patch":"1.0.36","@types/micromatch":"4.0.10","clipanion":"4.0.0-rc.4","diff-match-patch":"1.0.5","jsonc-parser":"3.3.1","kleur":"4.1.5","micromatch":"4.0.8","typescript":"6.0.3","zod":"4.4.3"},"devDependencies":{"@biomejs/biome":"2.4.15","@types/bun":"1.3.14","@typescript/native-preview":"7.0.0-dev.20260510.1","ajv":"8.20.0"},"gitHead":"dca504af25806e4b99d5a067682b3b307ec07030","_id":"@codegeneai/quality@2.2.3","_nodeVersion":"24.16.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-g7Hk2+Cgk7px3ZzbO/iRw19ZoLevsgB8g7NvXE3KKzjuGBPGcEoVB6YSX3k15sZ/O0n86jppaRu/DjSVl1Ls4g==","shasum":"925312503500003146a52e7ef73d61a57921bede","tarball":"https://registry.npmjs.org/@codegeneai/quality/-/quality-2.2.3.tgz","fileCount":85,"unpackedSize":567673,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@codegeneai%2fquality@2.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDZ8eQO84UPuD25uPsdAoJM/spcblwvT0V6nZ9yqdH3VgIhALYX7joP1lJ7l79IE4CrHZA5SIz2H2DzCN4yRe85sAhF"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f429c082-867c-4324-9feb-c01f024643b9"}},"directories":{},"maintainers":[{"name":"rszemplinski","email":"rszemplinski22@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/quality_2.2.3_1781210514018_0.6314536141635205"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-16T00:47:40.503Z","modified":"2026-06-11T20:41:54.466Z","2.2.0":"2026-05-16T00:47:40.853Z","2.2.1":"2026-05-16T02:06:07.846Z","2.2.2":"2026-05-16T02:15:37.226Z","2.2.3":"2026-06-11T20:41:54.156Z"},"bugs":{"url":"https://github.com/CodeGeneAI/quality/issues"},"license":"MIT","homepage":"https://github.com/CodeGeneAI/quality#readme","keywords":["quality","lint","biome","monorepo","ci","pipeline","adapters","hooks","bun","cli"],"repository":{"type":"git","url":"git+https://github.com/CodeGeneAI/quality.git"},"description":"Declarative quality pipeline (lint, format, hooks) with composable stage adapters for monorepo workflows","maintainers":[{"name":"rszemplinski","email":"rszemplinski22@gmail.com"}],"readme":"# @codegeneai/quality\n\n> Declarative, schema-driven quality pipeline (lint, format, test orchestration) for monorepos and single packages — built on Bun, written in TypeScript.\n\n[![npm version](https://img.shields.io/npm/v/@codegeneai/quality.svg)](https://www.npmjs.com/package/@codegeneai/quality)\n[![npm downloads](https://img.shields.io/npm/dm/@codegeneai/quality.svg)](https://www.npmjs.com/package/@codegeneai/quality)\n[![CI](https://github.com/CodeGeneAI/quality/actions/workflows/ci.yml/badge.svg)](https://github.com/CodeGeneAI/quality/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Bun](https://img.shields.io/badge/runtime-Bun-fbf0df)](https://bun.sh)\n\n```bash\nbun add -D @codegeneai/quality\nbun x quality init\nbun x quality check\n```\n\nThat's it — `quality init` drops a starter `.qualityrc.jsonc` in your repo, and `quality check` runs the pipeline.\n\n<details>\n<summary><strong>Table of contents</strong></summary>\n\n- [Why this exists](#why-this-exists)\n- [Core concepts](#core-concepts)\n- [Getting started](#getting-started)\n- [Shards and profiles](#shards-and-profiles)\n- [Configuration reference](#configuration-reference)\n  - [Files and shards](#files-and-shards)\n  - [Auto-fix defaults](#auto-fix-defaults)\n  - [CLI reference (quality)](#cli-reference-quality)\n  - [Global ignore](#global-ignore)\n  - [Built-in adapters](#built-in-adapters)\n  - [package-catalog](#package-catalog)\n  - [Husky hooks (recommended)](#husky-hooks-recommended)\n  - [Stage specs](#stage-specs)\n  - [Groups & parallel execution](#groups--parallel-execution)\n  - [Command adapter options](#command-adapter-options)\n  - [Extending adapters](#extending-adapters)\n  - [Schema & validation](#schema--validation)\n- [CLI reference](#cli-reference)\n- [Nested configs](#nested-configs)\n- [Development](#development)\n- [Contributing](#contributing)\n- [License](#license)\n\n</details>\n\n## Why this exists\n\nMost repos end up gluing together `husky`, `lint-staged`, `biome` (or `eslint` + `prettier`), and a stack of bespoke shell scripts to enforce quality before commits and in CI. `@codegeneai/quality` collapses that pile into a single declarative config file: pipelines, profiles (`local`, `pre-commit`, `pre-push`, `ci`), stage adapters, hooks, and reporters all live in `.qualityrc.jsonc`. You compose checks without writing TypeScript, share configuration across monorepo packages via nested configs, and run the same pipeline locally and in CI.\n\nIt pairs especially well with Bun and Biome but does not require either at the stage level — any check that can be expressed as a command or implemented as a stage adapter fits.\n\n## Core concepts\n\n- **Stage adapters** – Modules that implement a single responsibility (import hygiene, filenames, structure, bun-native, command, etc.). Adapters expose metadata (label, description, supported modes) and an execution hook.\n- **Presets** – Named option bundles defined per adapter under `stages.<adapter>.presets`. Presets can extend other presets (single or multiple inheritance) and configure defaults such as groups, modes, hooks, and adapter options.\n- **Profiles** – Named pipelines that order stages, set reporters, and attach hooks. Profiles can extend one another, allowing \"local\" and \"ci\" variants with small diffs.\n- **Groups** – Stages can join a group to opt into parallel execution, fail-fast semantics, or shared metadata.\n- **Hooks & reporters** – Declarative shell commands that run on start/success/failure, and reporters (summary/json/junit/verbose) that consume pipeline results.\n- **Schema-first** – A bundled JSON Schema models the entire configuration surface so editors and CI can validate configs.\n\n## Getting started\n\n1. Install: `bun add -D @codegeneai/quality`.\n2. After installing, run `bun x quality init` in your repo to generate a starter `.qualityrc.jsonc` (the stack demonstrates presets, command stages, and grouped adapters).\n3. Reference the schema inside `.qualityrc` files to enable editor IntelliSense:\n\n```jsonc\n{\n  \"$schema\": \"./node_modules/@codegeneai/quality/schemas/qualityrc.schema.json\",\n  \"stages\": {\n    \"command\": {\n      \"presets\": {\n        \"docs:check\": {\n          \"continueOnError\": true,\n          \"options\": {\n            \"abortPipelineOnFailure\": false,\n            \"commands\": [\"bun run docs:lint\"]\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n> Editors that support `npm:` schema references (or your monorepo tooling) can also use `\"$schema\": \"npm:@codegeneai/quality/schemas/qualityrc.schema.json\"`. The relative `./node_modules/...` path above works everywhere.\n\nProfiles can live entirely in shard files (e.g., `.qualityrc.local.jsonc`, `.qualityrc.pre-push.jsonc`). If the base config omits profiles, the loader discovers shards automatically and defaults to `local` (or a `--profile` override / the first shard found).\n\nCreate additional `.qualityrc` files inside packages to extend/override stages for that subtree. The loader walks upward from the file(s) being linted, merging presets, profiles, hooks, and adapter registrations.\n\n## Shards and profiles\n\n- Base config: `.qualityrc.jsonc` (or `.json`).\n- Profile shards: `.qualityrc.<profile>.jsonc|json` are loaded automatically and merged on top of the base. By default shards live beside the base config; set `\"shardDir\": \"relative/path\"` in the base config to load shards from another directory.\n- Example shards: `.qualityrc.local-fast.jsonc`, `.qualityrc.pre-commit.jsonc`, `.qualityrc.pre-push.jsonc`, `.qualityrc.ci.jsonc`.\n\n## Configuration reference\n\n### Files and shards\n\n- Base config: `.qualityrc.jsonc` (or `.json`). JSON/JSONC only.\n- Profile shards: `.qualityrc.<profile>.jsonc|json` loaded automatically and merged on top of the base. Default location is the same directory as the base; set `\"shardDir\": \"relative/path\"` in the base config to load shards from a custom folder.\n- Example shards: `.qualityrc.local-fast.jsonc`, `.qualityrc.pre-commit.jsonc`, `.qualityrc.pre-push.jsonc`, `.qualityrc.ci.jsonc`.\n\n### Auto-fix defaults\n\n- Each profile accepts `autoFix: true` to run fixable stages before verification without passing `--auto-fix`.\n- Developers can disable the default on a given invocation with `--no-auto-fix`.\n- Use the `-a` alias to keep hooks and scripts short while enabling auto-fix explicitly.\n- Example profile configuration and usage:\n\n```jsonc\n{\n  \"profiles\": {\n    \"local\": {\n      \"pipeline\": [\n        { \"id\": \"lint:imports\", \"type\": \"imports\" },\n        { \"id\": \"lint:structure\", \"type\": \"structure\" }\n      ],\n      \"autoFix\": true // Enable auto-fix by default\n    }\n  }\n}\n```\n\n```bash\nquality check  # Auto-fix enabled (profile default)\nquality check --no-auto-fix  # Override to disable auto-fix\nquality check -a  # Explicitly enable auto-fix regardless of profile default\n```\n\n### CLI reference (quality)\n\n- `quality check [-a|--auto-fix] [--no-auto-fix] [--profile <name>] [--files <glob>] [--stage <id>] [--reporter <name>] [--json <path>] [--shard-dir <dir>]`\n- `quality run --stage <id> [--mode check|fix|report] [--shard-dir <dir>]`\n- `quality list [--adapters] [--shard-dir <dir>]`\n- `quality init`\n- `quality validate-config [--stage <id>] [--shard-dir <dir>]` (prints resolved profile/stage as JSON)\n- `quality config validate [--shard-dir <dir>]` (validates all profiles/shards)\n- `quality config print [--compact] [--shard-dir <dir>]` (prints merged config; pretty-prints by default, use `--compact` for single-line JSON)\n- `quality telemetry analyze [--file <path>] [--profile <name>] [--context <substring>] [--success-only] [--json]`\n\n**Resolution order:** CLI flag (`--auto-fix` or `--no-auto-fix`) → profile `autoFix` → `false` (default).\n\n### Global ignore\n\n- Set `ignore` at the root of `.qualityrc` to provide glob patterns that should\n  be skipped by every stage. These patterns augment the built-in defaults\n  (`node_modules`, `.git`, caches, etc.) and flow through adapter internals, so a\n  single entry such as `\"scripts/helpers/**\"` keeps helper directories out of linting,\n  hooks, and stage-specific globbing.\n\n### Built-in adapters\n\n- imports — strip file extensions per allowlist.\n- bun-native — guard `node:` imports.\n- filenames — enforce test/fixture naming.\n- structure — require presence/absence of files; supports `requireWithContent` (autofix create/overwrite) e.g., `CLAUDE.md` with `@./AGENTS.md`.\n- unit-adjacency — ensure unit tests (e.g., `*.unit.spec.ts`) sit next to the subject file. Subject-less tests are allowed only under `src/__tests__/` (configurable) and only if that folder contains unit tests only; `requireSubject` and directory options are configurable.\n- command — run arbitrary commands.\n- package-scripts — enforce required scripts in `package.json` files.\n- package-catalog — enforce dependency versions use `catalog:<name>` (or `workspace:`) with optional fix-mode rewrite using the root catalogs map.\n- barrel-exports — enforce barrel-file conventions.\n- biome-config — validate Biome configuration consistency.\n- biome-ignore — keep Biome ignore lists in sync.\n- changeset-guard — guard changeset usage on configured branches.\n- dockerfile-required — require Dockerfiles in selected packages.\n- dotenv-plaintext — flag plaintext secrets in `.env` files.\n- dotenv-secrets — validate dotenvx-encrypted secret files.\n\nAdapters that support partial file input honour `--files` and profile-level\n`filesMode` selections. In pre-commit profiles, `biome-ignore`,\n`dotenv-plaintext`, and `dotenv-secrets` inspect only matching staged files and\nskip quickly when unrelated files are staged, while workspace/CI profiles still\nperform their configured full scans.\n\n### package-catalog\n\nEnsures dependency versions in targeted `package.json` files use shared catalogs (a Bun monorepo feature; safe to skip in single-package repos).\n\nOptions:\n\n- `packages` (string[]): glob(s) to `package.json` files (ignored: `**/node_modules/**`).\n- `sections` (string[]): which dependency blocks to scan; defaults to `dependencies`, `devDependencies`, `peerDependencies`.\n- `allowlist` (string[]): package names (globs) to exempt.\n- `rootCatalogPath` (string): path to the root package file containing `catalogs` (default: `package.json`).\n\nBehaviour:\n\n- **check**: fails if any targeted dependency lacks `catalog:<name>` or `workspace:*`. When a catalog entry exists, the message points to the expected `catalog:<name>`; otherwise it asks to add the dep to root catalogs or the allowlist.\n- **fix**: rewrites eligible deps to `catalog:<name>` when a root catalog entry exists. Deps without catalog entries still fail with guidance.\n\nExample stage:\n\n```jsonc\n{\n  \"id\": \"package-catalog\",\n  \"type\": \"package-catalog\",\n  \"overrides\": {\n    \"packages\": [\n      \"packages/*/package.json\",\n      \"packages/*/*/package.json\",\n      \"packages/*/*/*/package.json\",\n      \"services/*/package.json\",\n      \"apps/*/package.json\",\n      \"!packages/example/stacks/**/package.json\"\n    ],\n    \"allowlist\": [\"@your-scope/*\"]\n  }\n}\n```\n\n### Husky hooks (recommended)\n\nUse Husky to connect Git hooks to your quality profiles. Example hooks that also keep Git LFS happy:\n\n`.husky/pre-commit`\n\n```sh\n#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\ncommand -v git-lfs >/dev/null 2>&1 && git lfs pre-commit \"$@\"\nbun x quality check --profile pre-commit --files-mode staged --reporter summary\n```\n\n`.husky/pre-push`\n\n```sh\n#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\ncommand -v git-lfs >/dev/null 2>&1 && git lfs pre-push \"$@\"\nbun x quality check --profile pre-push --files-mode workspace --reporter summary\n```\n\nSetup steps:\n\n1. `bun add -D husky`.\n2. Add `\"prepare\": \"husky install\"` to `package.json` so fresh installs create `.husky/`.\n3. Commit the `.husky/*` hook files alongside your `.qualityrc` profiles.\n\nDefine dedicated profiles (e.g., `pre-commit`, `pre-push`) in `.qualityrc` so hook commands stay stable. Husky lives at `.husky/` (via `core.hooksPath`), avoiding conflicts with Git LFS and other tools.\n\n### Stage specs\n\nEach stage entry resolves to a `ResolvedStage` with these fields:\n\n| Field | Description |\n| --- | --- |\n| `id` | Unique identifier printed in reports and used by `quality run --stage <id>`. |\n| `type` | Adapter type (`imports`, `command`, etc.). |\n| `preset` | Optional preset name defined under `stages.<type>.presets`. Presets may `extends` one or many other presets. |\n| `overrides` | Free-form options merged on top of the preset. |\n| `label` / `description` | Friendly metadata for reporters. |\n| `mode` | Overrides the pipeline mode (`check`, `fix`, or `report`). |\n| `files` | Glob array evaluated when the CLI is invoked without `--files`. |\n| `group` | String (group id) or object (`{ id, label?, parallel?, failFast?, continueOnError? }`). Stages sharing the same group id execute concurrently when `parallel` is true. |\n| `continueOnError` | When `true`, the pipeline continues even if the stage fails. Defaults to `false`, but can be inherited from presets or groups. Command stages also infer this from `options.abortPipelineOnFailure`. |\n| `if` | Boolean condition evaluated by a sandboxed parser (no dynamic code). Supports `env.*` lookups, string/number/boolean/null/undefined literals, comparisons (`===`, `!==`, `<`, `<=`, `>`, `>=`), and logical operators (`!`, `&&`, `||`). |\n| `reporters` | Overrides the profile-level reporters for this stage. |\n\nFile globs declared under `files` are resolved asynchronously and cached per pattern/root/ignore combination during a run so parallel groups that share patterns do not repeat identical filesystem scans.\n\n#### Conditional syntax\n\n- Access environment variables via `env.VAR_NAME` or dotted keys (`env.NODE_ENV`).\n- Supported operators: `!`, `&&`, `||`, `===`, `!==`, `==`, `!=`, `<`, `<=`, `>`, `>=`. `==`/`!=` perform limited coercion for env-provided strings (for example, `\"true\"` → `true`, numeric strings → numbers) to keep legacy guards working.\n- Supported literals: strings (single or double quotes), numbers, `true`/`false`, `null`, `undefined`.\n- Parentheses are allowed for grouping; unmatched parentheses or unknown tokens fail the condition and skip the stage.\n- Prefer short, explicit checks such as `env.NODE_ENV === \"ci\"` or `env.QUALITY_FLAG === \"1\"`; avoid chained logic that hides failure modes (`(env.A === \"1\" && env.B === \"1\") || env.C === \"1\"`).\n- Conditions resolve missing environment variables to `undefined`; include defaults explicitly (for example, `env.TARGET ?? \"local\" === \"ci\"` is not supported, use `env.TARGET === \"ci\"`).\n- Wrap string literals in quotes and avoid interpolated paths or shell expressions. All unknown tokens cause the condition to evaluate to `false` so the stage is skipped.\n- Capture common guardrails in presets (for example, a `ci-only` preset that sets `if: \"env.CI === \\\"true\\\"\"`) to keep stage specs consistent across services.\n- Share this guidance with config authors when adding new profiles to reduce invalid `if` expressions; keep conditions short, quoted, and explicit.\n\n### Groups & parallel execution\n\n- Stages within the same group id run concurrently when `parallel: true`.\n- `failFast: true` (default) aborts sibling stages at the first failure via `AbortController`.\n- `continueOnError: true` on the stage or group allows the pipeline to keep running after failures.\n- The runner aggregates output in a deterministic order regardless of parallel execution.\n- Cap concurrency per group with `profiles.<name>.parallelLimit` (preferred) or `QUALITY_PARALLEL_LIMIT`. Profile values win when both are set.\n\n#### Telemetry for stage timing\n\n- Set `QUALITY_TELEMETRY=stdout` (or `file`) to emit run metadata that includes the resolved `parallelLimit`, its source, and a `stageTiming` summary (pipeline duration, aggregate stage time, longest stage, and per-stage timing with group ids).\n- Compare `stageTiming` fields across runs with different `parallelLimit` values to understand contention on constrained hosts; a large gap between `serialDurationMs` and `pipelineDurationMs` indicates effective parallelism.\n- Use the metadata to validate low-power profiles: keep the same stage ordering and results while monitoring whether tighter caps reduce wall-clock duration or stabilize CI throughput.\n\n##### Analyzing telemetry output\n\n- Run `quality telemetry analyze --file <path>` (defaults to `./quality-telemetry.log`) to summarize stage timing by `parallelLimit` and its source. Add `--profile <name>` or `--context <substring>` to focus on specific runs, `--success-only` to exclude failures, and `--json` for machine-readable output.\n- Inspect the `parallel ratio` column (`pipelineDurationMs / serialDurationMs`) to gauge how much parallelism you gain at each limit. Lower values indicate better overlap (for example, `0.5x` beats `1.0x`, which is purely serial execution).\n- Capture and compare summaries from low-power hosts when tuning `parallelLimit`: if a tighter cap improves efficiency without lowering success rate, prefer the smaller limit for that profile.\n\n### Command adapter options\n\n`command` stages accept:\n\n| Option | Description |\n| --- | --- |\n| `commands` | Array of either shell strings or objects `{ command, args?, cwd?, env?, shell?, timeoutMs?, continueOnError?, label? }`. Arrays in `command` allow specifying the binary plus default args. |\n| `cwd` | Working directory for commands (default: repo root). |\n| `env` | Additional environment variables. |\n| `shell` | Whether to execute through the shell (`true`, `false`, or shell binary). Shell strings default to `shell: true`. |\n| `timeoutMs` | Per-command timeout. |\n| `abortPipelineOnFailure` | When `false`, the stage inherits `continueOnError: true` so downstream stages continue. |\n| `output` | Optional object that enables quiet logging. Supports `preset` (`bun-test`, `playwright`, `turbo`), `mode` (`passthrough` or `errors-only`), pattern overrides, and `showOnSuccess`/`showOnFailure` toggles. |\n\nThe adapter collects stdout/stderr per command, respects pipeline abort signals, and reports timeouts with structured details.\n\nWhen `output` is configured the adapter streams stdout/stderr through the\ncommand-output filter and only emits the filtered lines (for example, failing\nbun:test assertions). Passing stages can suppress logs entirely by setting\n`showOnSuccess: \"none\"`, keeping `quality check` output tight even when the\nunderlying command is noisy. Set `QUALITY_SHOW_ALL_OUTPUT=1` or pass\n`--show-command-output` to the CLI to bypass filtering for a given run.\n\n### Extending adapters\n\nAdd custom adapters by exporting modules that return a `StageAdapter`:\n\n```ts\n// tools/quality/custom-adapter.ts\nimport type { StageAdapter } from \"@codegeneai/quality\";\n\nexport const greetAdapter: StageAdapter<{ message?: string }> = {\n  type: \"greet\",\n  label: \"Greeter\",\n  description: \"Prints a greeting\",\n  async run(context) {\n    const message = context.options.message ?? \"hello\";\n    console.log(message);\n    return { status: \"passed\" };\n  },\n};\n\nexport default { adapters: [greetAdapter] };\n```\n\nReference the module path from `.qualityrc`:\n\n```jsonc\n{\n  \"$schema\": \"./node_modules/@codegeneai/quality/schemas/qualityrc.schema.json\",\n  \"adapters\": [\"./tools/quality/custom-adapter.ts\"],\n  \"profiles\": {\n    \"local\": {\n      \"pipeline\": [\n        { \"id\": \"greet\", \"type\": \"greet\", \"overrides\": { \"message\": \"hi\" } }\n      ]\n    }\n  }\n}\n```\n\nThe loader resolves module paths relative to the config file, registers adapters, and exposes preset metadata to the CLI.\n\n### Schema & validation\n\nThe bundled JSON Schema (`@codegeneai/quality/schemas/qualityrc.schema.json`) describes:\n\n- Root keys (`$schema`, `adapters`, `stages`, `profiles`, `reporters`, `hooks`).\n- Built-in adapter option specs (imports/bun-native/filenames/structure/no-root-barrel/command).\n- Group metadata, parallel semantics, and hook specs.\n\nUnit tests use a vendored JSON Schema validator to ensure sample `.qualityrc` files remain compliant. Point editors at the relative schema path (`./node_modules/@codegeneai/quality/schemas/qualityrc.schema.json`) or host the schema at `$id` for global distribution.\n\n## CLI reference\n\n```\nUsage: quality <command> [options]\n\nCommands:\n  quality check [-a|--auto-fix] [--no-auto-fix] [--profile <name>] [--files <glob>] [--stage <id>] [--reporter <name>] [--json <path>]\n  quality run --stage <id> [--mode check|fix|report] [--files <glob>]\n  quality list [--adapters]\n  quality validate-config [--profile <name>] [--stage <id>]\n  quality config validate [--shard-dir <dir>]\n  quality config print [--compact]\n  quality init [--cwd <path>]\n  quality telemetry analyze [--file <path>] [--profile <name>] [--context <substring>] [--success-only] [--json]\n```\n\nHighlights:\n\n- `quality list` prints the resolved pipeline. `quality list --adapters` shows registered adapters, supported modes, and preset descriptions.\n- `-a` / `--auto-fix` runs fixable stages before verification (with `--no-auto-fix` to disable); set `autoFix: true` on a profile to default to this behaviour.\n- `quality validate-config` outputs the merged profile JSON, or a specific stage via `--stage`.\n- `quality run --stage` executes a single stage ad-hoc (useful for command adapters or debugging).\n- `--reporter` can be repeated; `--json <path>` adds the JSON reporter automatically.\n- Use Husky to wire git hooks to the profiles you define (see Husky section above); the quality CLI does not manage `.git/hooks` directly.\n\n## Nested configs\n\nPlace additional `.qualityrc` files within packages to customize presets or append stages for that subtree. The loader merges configs in this order:\n\n1. Repository root `.qualityrc`.\n2. Profile inheritance (`extends`).\n3. Nested `.qualityrc` files closest to the targeted files.\n4. Stage-level overrides.\n\nAdapters declared in nested configs are registered automatically.\n\n## Development\n\n```bash\ngit clone https://github.com/CodeGeneAI/quality.git\ncd quality\nbun install\nbun run test:unit\n```\n\n- Type check: `bun run typecheck`\n- Lint: `bun run lint`\n- Unit tests: `bun run test:unit`\n- Avoid `bun test`; it runs an unintended scope. Always execute `bun run test:unit` for reliable results.\n\nTests live alongside the source (e.g., `src/pipeline/runner.unit.test.ts`). Fixtures under `test/fixtures/**` exercise loader behaviours, preset inheritance, and schema validation.\n\nRun `quality check` before publishing changes to ensure reporters, hooks, and adapters remain functional.\n\n## Contributing\n\nContributions are welcome — see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for setup, conventional-commit conventions, and how to add a new stage adapter. Security issues should be reported privately via [GitHub Security Advisories](https://github.com/CodeGeneAI/quality/security/advisories/new) — see [`SECURITY.md`](./SECURITY.md).\n\n## License\n\n[MIT](./LICENSE) © CodeGeneAI\n","readmeFilename":"README.md"}