quality_gate 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +292 -21
- data/docs/codex.md +37 -9
- data/docs/releasing.md +16 -4
- data/lib/generators/quality_gate/install/install_generator.rb +18 -3
- data/lib/generators/quality_gate/install/templates/agents_section.md.tt +13 -2
- data/lib/generators/quality_gate/install/templates/codex_fast.rb.tt +36 -0
- data/lib/generators/quality_gate/install/templates/codex_hooks.json.tt +1 -0
- data/lib/generators/quality_gate/install/templates/codex_verify_stop.rb.tt +28 -0
- data/lib/generators/quality_gate/install/templates/quality_gate.yml.tt +6 -0
- data/lib/generators/quality_gate/install/templates/quality_gate_fast.rb.tt +16 -3
- data/lib/generators/quality_gate/install/templates/quality_gate_workflow.yml.tt +28 -0
- data/lib/generators/quality_gate/install/templates/rails_quality_gate.yml.tt +45 -0
- data/lib/generators/quality_gate/install/templates/ruby_agents_section.md.tt +13 -2
- data/lib/generators/quality_gate/install/templates/ruby_quality_gate.yml.tt +5 -0
- data/lib/generators/quality_gate/install/templates/simplecov.rb.tt +1 -0
- data/lib/quality_gate/adapters/bundler_audit.rb +28 -3
- data/lib/quality_gate/adapters/database_consistency.rb +51 -0
- data/lib/quality_gate/adapters/database_consistency_report.rb +61 -0
- data/lib/quality_gate/adapters/database_consistency_report_item.rb +122 -0
- data/lib/quality_gate/adapters/debride.rb +67 -0
- data/lib/quality_gate/adapters/debride_report.rb +80 -0
- data/lib/quality_gate/adapters/herb.rb +303 -0
- data/lib/quality_gate/adapters/reek.rb +21 -2
- data/lib/quality_gate/adapters/rubocop.rb +23 -9
- data/lib/quality_gate/adapters/rubycritic.rb +74 -0
- data/lib/quality_gate/adapters/rubycritic_report.rb +112 -0
- data/lib/quality_gate/adapters/test_suite.rb +12 -1
- data/lib/quality_gate/baseline.rb +269 -0
- data/lib/quality_gate/baseline_run.rb +80 -0
- data/lib/quality_gate/cli.rb +129 -6
- data/lib/quality_gate/codex_fast_hook.rb +163 -0
- data/lib/quality_gate/codex_patch_files.rb +95 -0
- data/lib/quality_gate/codex_stop_hook.rb +102 -0
- data/lib/quality_gate/config.rb +20 -6
- data/lib/quality_gate/database_consistency_runner.rb +124 -0
- data/lib/quality_gate/doctor.rb +217 -0
- data/lib/quality_gate/doctor_bounded_file.rb +74 -0
- data/lib/quality_gate/doctor_command.rb +130 -0
- data/lib/quality_gate/doctor_coverage.rb +113 -0
- data/lib/quality_gate/doctor_git.rb +121 -0
- data/lib/quality_gate/doctor_hooks.rb +99 -0
- data/lib/quality_gate/doctor_launchers.rb +300 -0
- data/lib/quality_gate/doctor_path_lookup.rb +52 -0
- data/lib/quality_gate/doctor_report.rb +38 -0
- data/lib/quality_gate/init_command.rb +3 -1
- data/lib/quality_gate/installation.rb +72 -17
- data/lib/quality_gate/installer.rb +3 -0
- data/lib/quality_gate/reporters/doctor.rb +57 -0
- data/lib/quality_gate/reporters/json.rb +18 -1
- data/lib/quality_gate/reporters/markdown.rb +11 -1
- data/lib/quality_gate/reporters/text.rb +14 -6
- data/lib/quality_gate/ruby_profile.rb +121 -2
- data/lib/quality_gate/runner.rb +15 -17
- data/lib/quality_gate/version.rb +1 -1
- data/lib/quality_gate.rb +15 -0
- data/sig/quality_gate.rbs +117 -2
- metadata +30 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e438f281cbb59bb4c7abd81290d1281e5ded80d8f6840c3268e0392a72307488
|
|
4
|
+
data.tar.gz: 6d0d56e91fa33fe72753dceb7e0a51f43c082639adc23f19eb2b6c8a7a003d11
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d36248ffca64a9908d3dbb7ec1c835a005c0491431c5dba2fa6bb7b83d0f510762835b0cf6234abf925370eb04285d373d82b1a162db45d9caaacab5bdddca3
|
|
7
|
+
data.tar.gz: 356a4eeeecfb0ca945efa3f8f6af080b10adae9f75d04747d152c1c27209d574223b8de71ccdc6ca1ca7bfe7f95a036b1003560456b08fd144c7ffee4302c98e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [0.3.0] - 2026-10-04
|
|
4
|
+
|
|
5
|
+
- Add `quality_gate doctor` for read-only setup preflight checks with text or JSON output.
|
|
6
|
+
- Add an optional, explicitly invoked RubyCritic-backed `deep` gate for project-wide design analysis. RubyCritic remains a host-project dependency; the gate does not add a score budget or generated hooks/workflows.
|
|
7
|
+
- Add optional Debride support to the manual, project-wide `deep` gate for potentially unused method candidates. Debride remains a host-project dependency; the existing RubyCritic default and generated hooks/workflows are unchanged.
|
|
8
|
+
- Add an optional, project-wide `audit` adapter for database consistency using the host project's `database_consistency ~> 3.0.14`; analyzer scan failures are reported as tool failures.
|
|
9
|
+
- Add opt-in fast/verify warning baselines with comparison, create, and shrink-only ratchet modes; protected findings and tool failures remain enforced.
|
|
10
|
+
- Treat RuboCop process errors and Reek source-processing diagnostics as tool failures even when their JSON output is valid and empty.
|
|
11
|
+
- Add opt-in Codex patch feedback after native `apply_patch` calls while retaining full Stop verification.
|
|
12
|
+
- Add an opt-in native Codex Stop verification hook for plain Ruby and Rails installs.
|
|
13
|
+
|
|
14
|
+
## [0.2.3] - 2026-10-02
|
|
15
|
+
|
|
16
|
+
- Reek scans the project when a bare gate invocation has no selected paths.
|
|
17
|
+
- When SimpleCov is enabled in verify, its aggregate summary must come from the current test run.
|
|
18
|
+
- bundler-audit treats abnormal process exits and status/report conflicts as tool failures.
|
|
19
|
+
- Rails setup can select Minitest or RSpec, a helper, and a test command.
|
|
20
|
+
- The optional Herb adapter adds ERB checks without changing fast-gate defaults.
|
|
21
|
+
- Ruby and Rails setup can opt in to a full-history GitHub Actions workflow with separate gate steps.
|
|
22
|
+
|
|
1
23
|
## [0.2.2] - 2026-09-28
|
|
2
24
|
|
|
3
25
|
- Fiddle is now a runtime dependency, so the installer loads it with a plain `require` on Ruby 4.x under Bundler. This removes the runtime `Kernel#require` patch and the hand-built extension path that missed on hosts where RbConfig and RubyGems spell the platform differently (for example `arm64-darwin25` vs `arm64-darwin-25`).
|
data/README.md
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
QualityGate gives Ruby projects one workflow for checking changes: quick feedback while editing, verification before finishing, and a separate security audit. Set up a plain Ruby project with `quality_gate init`, or a Rails application with the Rails generator.
|
|
4
4
|
|
|
5
|
-
The `fast` gate runs RuboCop. `verify` runs Reek, the test suite, and Undercover in order. For `audit`, Rails defaults run Brakeman followed by bundler-audit; the Ruby setup uses bundler-audit alone.
|
|
5
|
+
The `fast` gate runs RuboCop, with optional adapters such as Herb. `verify` runs Reek, the test suite, and Undercover in order. For `audit`, Rails defaults run Brakeman followed by bundler-audit; the Ruby setup uses bundler-audit alone.
|
|
6
|
+
|
|
7
|
+
Database consistency checks are not enabled by generated configuration. They are an optional addition to `audit`; generated hooks use other gates, while a CI workflow that invokes `audit` will run this adapter after it is explicitly configured and the application provides its boot and database prerequisites.
|
|
8
|
+
|
|
9
|
+
This source prepares the unpublished 0.3.0 release candidate. It includes Doctor preflight checks, optional RubyCritic and Debride deep analysis, warning-baseline ratchets, Codex patch feedback and Stop verification hooks, stricter analyzer tool-error reporting, and an optional database consistency audit adapter. The latest RubyGems release is 0.2.2; the latest GitHub release is v0.2.3.
|
|
10
|
+
|
|
11
|
+
The optional `deep` gate is introduced in 0.3.0. Its default adapter is RubyCritic; Debride can be enabled explicitly for project-wide potentially unused method candidates. The gate runs only when requested, and `--files` does not narrow either analyzer.
|
|
6
12
|
|
|
7
13
|
## Quick start
|
|
8
14
|
|
|
@@ -17,7 +23,9 @@ bundle exec quality_gate verify
|
|
|
17
23
|
|
|
18
24
|
For Rails, replace the init command with `bin/rails generate quality_gate:install`.
|
|
19
25
|
|
|
20
|
-
Review the installer summary: existing configuration is preserved, and conflicts require manual integration.
|
|
26
|
+
Review the installer summary: existing configuration is preserved, and conflicts require manual integration. Claude hooks are optional; add `--agents` to install them. Add `--codex` to install Codex patch feedback, native Stop verification, and the owned `AGENTS.md` contract. Codex activation requires a trusted project and review of both hook commands in `/hooks`; see the [Codex integration guide](docs/codex.md). Use `--pretend` to preview filesystem changes. See [Ruby setup](#plain-ruby-and-other-test-runners) for test-runner selection and command overrides.
|
|
27
|
+
|
|
28
|
+
Claude Code's fast hook responds to native `Edit` and `Write` calls; Codex's equivalent patch feedback responds to native `apply_patch` calls.
|
|
21
29
|
|
|
22
30
|
The same commands work from your terminal and CI. QualityGate runs existing tools, collects their findings, and distinguishes code findings from tools that could not complete. A clean result only describes the configured checks and their scope.
|
|
23
31
|
|
|
@@ -39,6 +47,96 @@ bundle exec quality_gate verify
|
|
|
39
47
|
bundle exec quality_gate audit
|
|
40
48
|
```
|
|
41
49
|
|
|
50
|
+
### Database consistency (optional audit adapter)
|
|
51
|
+
|
|
52
|
+
QualityGate does not install the analyzer. Add it to the host application's development bundle and explicitly append it to the existing audit adapters:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
gem 'database_consistency', '~> 3.0.14', group: :development, require: false
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
adapters:
|
|
60
|
+
audit:
|
|
61
|
+
- brakeman
|
|
62
|
+
- bundler_audit
|
|
63
|
+
- database_consistency
|
|
64
|
+
timeouts:
|
|
65
|
+
database_consistency: 120
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The adapter scans the project as a whole; `--files` validates input paths but does not narrow its checks. The default launcher is the current Ruby interpreter and QualityGate's packaged bridge. An optional `commands.audit.database_consistency` array replaces the Ruby launcher prefix, with the bridge path appended. The bridge loads the current Bundler context, `config/boot.rb`, and `config/environment.rb`, then eager-loads the Rails application. Run `quality_gate audit` manually from the application root after installing the bundle. Doctor can inspect the configured launcher without booting Rails and does not establish that the analyzer or database is available.
|
|
69
|
+
|
|
70
|
+
The bridge uses the analyzer's internal configuration and processor APIs from version 3.0.14 (`~> 3.0.14`, which allows patch releases below 3.1). It requests reports only; it never calls the analyzer's autofix or todo writers. The upstream processor can write a diagnostic file in the project root when it rescues a checker exception; QualityGate detects that condition and reports a tool failure instead of presenting a clean result. Application boot and schema/database access can still have project-specific effects.
|
|
71
|
+
|
|
72
|
+
Findings use the regular text, JSON, and Markdown reports, with fail reports mapped to errors and warnings mapped to warnings. A completed clean scan exits `0`, findings exit `1`, and boot, dependency, malformed-output, and execution failures exit `2`.
|
|
73
|
+
|
|
74
|
+
### Deep analysis (introduced in 0.3.0)
|
|
75
|
+
|
|
76
|
+
The `deep` gate is invoked explicitly and supports the usual output formats:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
bundle exec quality_gate deep --format text
|
|
80
|
+
bundle exec quality_gate deep --format json
|
|
81
|
+
bundle exec quality_gate deep --format markdown
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
RubyCritic is optional and is not installed by QualityGate. Add it to the host project's Gemfile (for example, `gem "rubycritic", "~> 5", require: false`) and run `bundle install` before invoking the gate. The default is `deep: [rubycritic]`; `commands.deep.rubycritic` overrides the launcher argv prefix, with the adapter supplying RubyCritic's analysis flags and managing its output directory. Its timeout can be set with `timeouts.rubycritic` (otherwise the existing 120-second default applies).
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
adapters:
|
|
88
|
+
deep:
|
|
89
|
+
- rubycritic
|
|
90
|
+
commands:
|
|
91
|
+
deep:
|
|
92
|
+
rubycritic:
|
|
93
|
+
- bundle
|
|
94
|
+
- exec
|
|
95
|
+
- rubycritic
|
|
96
|
+
timeouts:
|
|
97
|
+
rubycritic: 120
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
RubyCritic analyzes the project as a whole; `--files` does not narrow this gate. Its findings complement tests and security checks and may overlap Reek. QualityGate does not add a score budget or minimum; RubyCritic owns its score. A completed analysis with no smells exits `0`, reported smells exit `1`, and missing input, configuration, or tool failures exit `2`. A report containing no analyzed Ruby modules is a tool failure, not a clean result. The JSON report is captured through a temporary file that QualityGate removes on success or failure; the adapter does not request HTML output or project-local report artifacts.
|
|
101
|
+
|
|
102
|
+
#### Debride: potentially unused methods
|
|
103
|
+
|
|
104
|
+
Debride is an optional host-project dependency; QualityGate does not install it. Add it to the project's Gemfile and install the bundle before enabling the adapter:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
gem "debride", "~> 1.15", require: false
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Select Debride alone or alongside RubyCritic in `.quality_gate.yml`:
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
adapters:
|
|
114
|
+
deep:
|
|
115
|
+
- debride
|
|
116
|
+
timeouts:
|
|
117
|
+
debride: 120
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
To run both analyzers, add `- rubycritic` before `- debride`. The default remains `deep: [rubycritic]`. The Debride command defaults to the `debride` executable; `commands.deep.debride` overrides its launcher argv prefix, and QualityGate appends `--json` and `.`. For Rails conventions with Bundler, for example:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
commands:
|
|
124
|
+
deep:
|
|
125
|
+
debride:
|
|
126
|
+
- bundle
|
|
127
|
+
- exec
|
|
128
|
+
- debride
|
|
129
|
+
- --rails
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
QualityGate adds `--json` and `.` after this prefix. It does not select framework options automatically. Leave `--verbose` off: Debride stderr diagnostics, including launcher chatter, make the result a tool failure. `timeouts.debride` uses the existing 120-second default when omitted.
|
|
133
|
+
|
|
134
|
+
Debride examines the whole project even when `--files` is supplied. Its candidates can be false positives when code is reached through dynamic dispatch, external APIs, metaprogramming, or Rails callbacks. Treat them as review leads: QualityGate does not delete code or prove that a method is dead. Debride does not report how many Ruby files it analyzed, so an empty report can be clean while providing no guarantee that files were present or fully understood.
|
|
135
|
+
|
|
136
|
+
Debride returns `0` for a clean report or candidates; QualityGate maps these to gate exits `0` and `1`, respectively. Missing tools, timeouts, malformed output, and any stderr diagnostics are tool failures and make the gate exit `2`. This strict check matters because Debride can skip invalid Ruby files, print a warning, and still exit successfully. Keep custom launchers quiet and emit only Debride's JSON on stdout. Like the other adapters, the result uses the standard text, JSON, and Markdown reporters.
|
|
137
|
+
|
|
138
|
+
This gate is a manual command only. It does not add generated hooks or workflow steps.
|
|
139
|
+
|
|
42
140
|
The built-in fast path is meant for changed files:
|
|
43
141
|
|
|
44
142
|
```sh
|
|
@@ -56,6 +154,18 @@ undercover clean git_diff 619ms
|
|
|
56
154
|
|
|
57
155
|
(Durations above are illustrative, not measured figures.) These tool lines make a clean run visible: you see every tool that ran, not just an absence of findings.
|
|
58
156
|
|
|
157
|
+
Run a read-only setup preflight with `bundle exec quality_gate doctor`. It prints text by default; `--format json` emits a machine-readable report, regardless of the gate format in the project configuration. `--help` works without loading that configuration. Doctor rejects positional arguments, `--files`, Markdown output, and unknown options.
|
|
158
|
+
|
|
159
|
+
Doctor is introduced in 0.3.0.
|
|
160
|
+
|
|
161
|
+
Doctor checks configuration, runtime and bundle context, whether supported launch paths are available, Undercover's comparison point, required coverage evidence, and recent optional hook history. It does not execute analyzers, test suites, or application boot code; install or repair anything; fetch from Git; or establish that the application is clean or works. A ready launcher check means only that the inspected executable or explicit script was found. Custom wrappers and nested bare commands that cannot be resolved safely remain `unchecked`.
|
|
162
|
+
|
|
163
|
+
The report has scope `preflight`, checks with `id`, `status`, and `message`, and summary counts for every status. Each message describes what was observed and gives a next step when needed. Statuses are `ready`, `warning`, `blocked`, `unchecked`, and `not_applicable`. Exit `0` means applicable preflight checks are ready; `1` means a warning or unchecked observation remains; `2` means a blocker, invalid input, or report failure. `not_applicable` is neutral. These results describe preflight observations, not gate findings or proof of application health.
|
|
164
|
+
|
|
165
|
+
Coverage artifacts are inspected only when an enabled adapter needs them. Before the first suite run, missing coverage is `unchecked`; run `bundle exec quality_gate verify` to create the evidence. Doctor reads at most 1 MiB from each artifact and does not check freshness, coverage wiring, or budget compliance. Hook history is advisory: absent optional hooks are `not_applicable`; installed hooks without valid history are `unchecked`; and valid history does not verify that hooks are currently installed. The Git comparison probe has a shared five-second budget and never fetches history.
|
|
166
|
+
|
|
167
|
+
If Bundler prevents the `quality_gate` command from starting, Doctor cannot run. Check Ruby and Bundler outside QualityGate with `ruby -v`, `command -v ruby`, `bundle --version`, and `bundle check`; these are manual troubleshooting commands, not Doctor checks.
|
|
168
|
+
|
|
59
169
|
Use `--files` to select paths for RuboCop and Reek; the first path follows the option and further paths follow it as separate arguments:
|
|
60
170
|
|
|
61
171
|
```sh
|
|
@@ -74,6 +184,7 @@ rubocop clean project 842ms
|
|
|
74
184
|
| Adapter | Scope with `--files` |
|
|
75
185
|
| --- | --- |
|
|
76
186
|
| RuboCop, Reek | Selected files/directories, subject to the tool's exclusions |
|
|
187
|
+
| Herb | Project scan, or selected ERB files/directories; unrelated files are omitted |
|
|
77
188
|
| Test suite | Full configured suite |
|
|
78
189
|
| Undercover | Git changes against the comparison point |
|
|
79
190
|
| SimpleCov | Aggregate coverage summary |
|
|
@@ -93,10 +204,43 @@ The shorter form `quality_gate version` works when the installed executable is a
|
|
|
93
204
|
|
|
94
205
|
The repository config must also use exactly `text`, `json`, or `markdown` for `format`; any other configured value is rejected as a configuration error before a gate runs.
|
|
95
206
|
|
|
207
|
+
## Warning baselines
|
|
208
|
+
|
|
209
|
+
Fast and verify can compare their current results with an explicitly created warning baseline. The feature is disabled by default. Create a snapshot, then compare it on later runs:
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
bundle exec quality_gate fast --create-baseline config/fast-baseline.json
|
|
213
|
+
bundle exec quality_gate fast --baseline config/fast-baseline.json
|
|
214
|
+
# After resolving findings, shrink the accepted set.
|
|
215
|
+
bundle exec quality_gate fast --ratchet-baseline config/fast-baseline.json
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
`--baseline PATH` accepts existing entries while reporting new or protected findings normally. `--create-baseline PATH` writes only when every finding is eligible for the snapshot. `--ratchet-baseline PATH` compares first and shrinks the snapshot only when the run has no new or protected findings; a blocked ratchet keeps the original bytes and exits with the ordinary findings or tool-failure status. All three options work only with `fast` and `verify`, are mutually exclusive, and use the command's `--format` reporter. Creation and ratcheting require a full scan: they reject `--files` and non-empty configured `files` before running tools. Comparison can use `--files` and never writes the snapshot.
|
|
219
|
+
|
|
220
|
+
Baselines store only warning and info findings from RuboCop, Reek, and Herb. Errors, tool failures, test and security results, coverage results, and other analyzers remain enforced. Matching uses tool, normalized project-relative file, rule, severity, and message plus a bounded duplicate count; line numbers do not participate, so moving a finding within its file does not make it new. Identical findings in one file are interchangeable up to their stored count, and the snapshot does not prove semantic identity or source provenance. Review analyzer configuration whenever using ratchet, and review manual baseline JSON edits in Git.
|
|
221
|
+
|
|
222
|
+
Analyzer process status also remains part of the result contract: RuboCop accepts exits `0` and `1`, while Reek accepts `0` and `2`. Other statuses and process signals fail the tool. Reek's explicit “cannot be processed” source diagnostic also fails the tool even if its JSON is empty and the process exits successfully.
|
|
223
|
+
|
|
224
|
+
The versioned JSON snapshot records its gate, configured adapter order, and finding entries. It must match the gate and current adapter list exactly. The parent directory must already exist. A successful create or ratchet writes before report output; an output-stream failure does not undo that completed file write. This is a reviewed warning policy for QualityGate results, not a replacement for RuboCop's `.rubocop_todo.yml` mechanism.
|
|
225
|
+
|
|
226
|
+
Snapshots contain analyzer messages and project-relative paths, so treat them as belonging to the host project. Keep baseline files in the project that owns the findings; do not ship them with QualityGate.
|
|
227
|
+
|
|
228
|
+
To enable comparison from `.quality_gate.yml`, add a gate-to-path mapping. It remains disabled for gates not listed:
|
|
229
|
+
|
|
230
|
+
```yaml
|
|
231
|
+
baseline:
|
|
232
|
+
fast: config/fast-baseline.json
|
|
233
|
+
verify: config/verify-baseline.json
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
An explicit `--baseline PATH` takes precedence for that invocation. `quality_gate <gate> --help` documents the command-line options without loading configuration.
|
|
237
|
+
|
|
96
238
|
## Output contract
|
|
97
239
|
|
|
98
240
|
Gate text output prints, in order: one line per tool that ran, then findings, then the tally.
|
|
99
241
|
|
|
242
|
+
When a baseline is active, checks keep each adapter's raw status while the finding list and JSON summary describe enforced findings after comparison. The JSON `baseline` object reports the mode, accepted finding records, counts, and whether a create or ratchet write completed. Without a baseline, JSON retains the existing `checks`, `findings`, and `summary` shape.
|
|
243
|
+
|
|
100
244
|
When at least one tool ran, each gets a line naming the tool, its status, what it inspected, and how long it took:
|
|
101
245
|
|
|
102
246
|
```text
|
|
@@ -221,6 +365,7 @@ timeouts:
|
|
|
221
365
|
undercover: 120
|
|
222
366
|
compare_point:
|
|
223
367
|
rubocop_config:
|
|
368
|
+
# baseline: {}
|
|
224
369
|
```
|
|
225
370
|
|
|
226
371
|
Default adapters when no project configuration overrides them (the Rails setup uses these; Ruby init writes its own test command and omits Brakeman):
|
|
@@ -228,6 +373,7 @@ Default adapters when no project configuration overrides them (the Rails setup u
|
|
|
228
373
|
- `fast` => `rubocop`
|
|
229
374
|
- `verify` => `reek`, then `test_suite`, then `undercover`
|
|
230
375
|
- `audit` => `brakeman`, then `bundler_audit`
|
|
376
|
+
- `deep` => `rubycritic` (introduced in 0.3.0; manual invocation only)
|
|
231
377
|
|
|
232
378
|
Default timeouts:
|
|
233
379
|
|
|
@@ -236,7 +382,7 @@ Default timeouts:
|
|
|
236
382
|
- `test_suite` => `120`
|
|
237
383
|
- `undercover` => `120`
|
|
238
384
|
|
|
239
|
-
`adapters` lists adapter names per gate. The built-in registry knows `rubocop`, `reek`, `test_suite`, `undercover`, `simplecov`, `brakeman`, and `
|
|
385
|
+
`adapters` lists adapter names per gate. The built-in registry knows `rubocop`, `reek`, `test_suite`, `undercover`, `simplecov`, `brakeman`, `bundler_audit`, `database_consistency`, `herb`, `rubycritic`, and `debride`. SimpleCov, Herb, Debride, and database_consistency are registry-known optional adapters, not defaults. RubyCritic is the `deep` default; Debride can be selected alongside it or by itself. The default verify adapters are Reek, the test suite, and Undercover, in that order. Unknown adapter names still become reported tool failures instead of being ignored.
|
|
240
386
|
|
|
241
387
|
### Aggregate coverage budgets
|
|
242
388
|
|
|
@@ -255,9 +401,9 @@ coverage:
|
|
|
255
401
|
|
|
256
402
|
`coverage.minimum_line` and `coverage.minimum_branch` are independent numeric percentage budgets in the inclusive range `0..100`. At least one is required when the `simplecov` adapter is enabled, and equality with the configured minimum passes. A valid `coverage` mapping alone is inert without `simplecov` in `adapters.verify`.
|
|
257
403
|
|
|
258
|
-
After the test suite runs, the adapter reads SimpleCov's `coverage/.last_run.json` summary without rerunning tests. A missing or unusable record is a tool failure. A branch budget without usable branch data is also a tool failure and names `enable_coverage :branch` as the required SimpleCov setup. Coverage below a configured budget produces a stable error finding: `line_coverage_below_minimum` for the line budget and `branch_coverage_below_minimum` for the branch budget.
|
|
404
|
+
After the test suite runs, the adapter reads SimpleCov's `coverage/.last_run.json` summary without rerunning tests. When SimpleCov is configured in `verify`, QualityGate removes only that aggregate summary before the test command. A command that produces no fresh summary cannot pass using stale coverage. A missing or unusable record is a tool failure. A branch budget without usable branch data is also a tool failure and names `enable_coverage :branch` as the required SimpleCov setup. Coverage below a configured budget produces a stable error finding: `line_coverage_below_minimum` for the line budget and `branch_coverage_below_minimum` for the branch budget.
|
|
259
405
|
|
|
260
|
-
`timeouts` sets the default adapter timeout in seconds and allows per-tool entries. The shipped RuboCop timeout is 10 seconds, while the test suite and Undercover each have an explicit 120-second timeout. Brakeman and bundler-audit inherit the 120-second default.
|
|
406
|
+
`timeouts` sets the default adapter timeout in seconds and allows per-tool entries. The shipped RuboCop timeout is 10 seconds, while the test suite and Undercover each have an explicit 120-second timeout. Brakeman and bundler-audit inherit the 120-second default; database_consistency also inherits it unless configured separately.
|
|
261
407
|
|
|
262
408
|
### Projects with longer test suites
|
|
263
409
|
|
|
@@ -298,9 +444,9 @@ can write a log record. Check `log/quality_gate_hooks.jsonl` and run
|
|
|
298
444
|
|
|
299
445
|
### Configuration validation
|
|
300
446
|
|
|
301
|
-
`adapters` must be a mapping whose only permitted keys are `fast`, `verify`, and `
|
|
447
|
+
`adapters` must be a mapping whose only permitted keys are `fast`, `verify`, `audit`, and `deep`, and each layer value must be an array of non-empty strings. The mapping may specify any subset of those gates; unspecified gates keep the shipped defaults. A misspelled layer key such as `fasst` is rejected as a configuration error instead of silently falling back to a clean run.
|
|
302
448
|
|
|
303
|
-
`commands` follows the same
|
|
449
|
+
`commands` follows the same four gate layers. Every command is an argv array of non-empty strings, never a shell command string. `commands.verify.test_suite` defaults to `["bin/rails", "test"]`; deep analyzer commands default to their executable names.
|
|
304
450
|
|
|
305
451
|
`compare_point` may be `nil` or a non-empty String. Set it to a Git ref or commit when CI has too little history to find a common ancestor automatically.
|
|
306
452
|
|
|
@@ -400,13 +546,13 @@ Each uncovered region is a warning that names its file, first line, full line ra
|
|
|
400
546
|
|
|
401
547
|
The security adapters deliberately ignore `--files`. Brakeman scans the whole application because its data-flow analysis crosses file boundaries. bundler-audit always checks `Gemfile.lock`, and dependency advisories use that file with line `0` rather than inventing a source location.
|
|
402
548
|
|
|
403
|
-
bundler-audit tries to update its advisory database first. If
|
|
549
|
+
bundler-audit tries to update its advisory database first. A clean report must exit `0`; vulnerability findings must exit `1`. Abnormal exits or conflicting statuses and reports become tool failures. If the update fails and a real, usable local database exists, QualityGate scans the cached database and writes exactly one fallback warning to standard error. If no usable advisory database exists, bundler-audit returns a tool failure and exit code `2`; an unchecked dependency audit is never reported as clean.
|
|
404
550
|
|
|
405
551
|
### Coverage template
|
|
406
552
|
|
|
407
|
-
QualityGate packages coverage templates for Rails
|
|
553
|
+
QualityGate packages coverage templates for Rails Minitest, Rails RSpec, and plain Ruby. Both setup paths render coverage into a marked block after the Ruby source prologue and before host application code is required.
|
|
408
554
|
|
|
409
|
-
The host-facing coverage templates are Undercover-only. They activate only when `ENV["COVERAGE"] == "1"`, load SimpleCov and the Undercover formatter, start branch coverage, and write `coverage/coverage.json`.
|
|
555
|
+
The host-facing coverage templates are Undercover-only. They activate only when `ENV["COVERAGE"] == "1"`, load SimpleCov and the Undercover formatter, start branch coverage, and write `coverage/coverage.json`. Generated Rails and Ruby templates filter both `test` and `spec`. HTML output is only part of this gem's self-dogfood setup and is not configured for generated hosts.
|
|
410
556
|
|
|
411
557
|
## Exit codes
|
|
412
558
|
|
|
@@ -484,17 +630,48 @@ bundle exec quality_gate init --help
|
|
|
484
630
|
|
|
485
631
|
Setup reports written, unchanged, skipped, and conflicting files. It never replaces custom configuration automatically; merge the displayed template where needed. Repeating setup with unchanged inputs is idempotent. Init uses a text summary; `--format json` applies to gate commands.
|
|
486
632
|
|
|
487
|
-
Coverage starts only with `COVERAGE=1`, which the test-suite adapter supplies, and filters both `test` and `spec`. Undercover requires a Git comparison point; set `compare_point` in shallow CI checkouts or fetch the base branch/history.
|
|
633
|
+
Coverage starts only with `COVERAGE=1`, which the test-suite adapter supplies, and filters both `test` and `spec`. Undercover requires a Git comparison point; set `compare_point` in shallow CI checkouts or fetch the base branch/history. Claude hooks require `--agents`; the separate native Codex hook requires `--codex`.
|
|
488
634
|
|
|
489
635
|
## Installation
|
|
490
636
|
|
|
491
|
-
|
|
637
|
+
Install the published gem as a development and test dependency. The executable is
|
|
638
|
+
used through Bundler, so the Gemfile entry does not require the library:
|
|
639
|
+
|
|
640
|
+
```ruby
|
|
641
|
+
group :development, :test do
|
|
642
|
+
gem "quality_gate", "~> 0.2", require: false
|
|
643
|
+
end
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
The Rails/RSpec options, `--ci`, and Herb support were introduced in the v0.2.3 GitHub release and are included in this candidate. They are not in the current RubyGems release, 0.2.2.
|
|
647
|
+
The `~> 0.2` version constraint will accept 0.3.x once published.
|
|
648
|
+
|
|
649
|
+
Bundler installs the gem's runtime dependencies automatically. The published
|
|
650
|
+
gemspec currently declares:
|
|
651
|
+
|
|
652
|
+
| Runtime dependency | Version requirement |
|
|
653
|
+
| --- | --- |
|
|
654
|
+
| brakeman | `~> 8.0` |
|
|
655
|
+
| bullet | `~> 8.2.0` |
|
|
656
|
+
| bundler-audit | `~> 0.9.3` |
|
|
657
|
+
| fiddle | `~> 1.1` |
|
|
658
|
+
| reek | `~> 6.5` |
|
|
659
|
+
| rubocop | `~> 1.90` |
|
|
660
|
+
| rubocop-minitest | `~> 0.40` |
|
|
661
|
+
| rubocop-performance | `~> 1.27` |
|
|
662
|
+
| rubocop-rails | `~> 2.37` |
|
|
663
|
+
| simplecov | `~> 1.1.1` |
|
|
664
|
+
| strong_migrations | `~> 2.5.2` |
|
|
665
|
+
| undercover | `~> 0.8.5` |
|
|
666
|
+
|
|
667
|
+
If you need to install directly from the repository instead, Bundler also
|
|
668
|
+
supports this Gemfile entry:
|
|
492
669
|
|
|
493
670
|
```ruby
|
|
494
|
-
gem "quality_gate", github: "lucianghinda/quality_gate"
|
|
671
|
+
gem "quality_gate", github: "lucianghinda/quality_gate", require: false
|
|
495
672
|
```
|
|
496
673
|
|
|
497
|
-
Then install for Ruby or Rails:
|
|
674
|
+
Then install and set up for Ruby or Rails:
|
|
498
675
|
|
|
499
676
|
```sh
|
|
500
677
|
bundle install
|
|
@@ -505,13 +682,39 @@ bundle exec quality_gate init --profile ruby
|
|
|
505
682
|
bin/rails generate quality_gate:install
|
|
506
683
|
```
|
|
507
684
|
|
|
685
|
+
### Rails test setup
|
|
686
|
+
|
|
687
|
+
The Rails generator detects one existing test helper. If both helpers exist,
|
|
688
|
+
choose Minitest or RSpec explicitly:
|
|
689
|
+
|
|
690
|
+
```sh
|
|
691
|
+
bin/rails generate quality_gate:install --test-framework rspec
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
Rails defaults to `test/test_helper.rb` and `bin/rails test`. RSpec uses
|
|
695
|
+
`spec/rails_helper.rb` and `bundle exec rspec`. A custom helper under `spec/`
|
|
696
|
+
selects RSpec; other custom helpers select Minitest unless specified.
|
|
697
|
+
|
|
698
|
+
Pass a project-relative helper and command when needed:
|
|
699
|
+
|
|
700
|
+
```sh
|
|
701
|
+
bin/rails generate quality_gate:install --test-helper spec/rails_helper.rb --test-command 'bundle exec rspec'
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
An explicit custom helper must exist when coverage wiring is enabled. Use
|
|
705
|
+
`--skip-coverage` to omit coverage wiring. With no detected helper, Rails keeps
|
|
706
|
+
Minitest, warns, and installs the remaining artifacts.
|
|
707
|
+
|
|
708
|
+
The generated `.quality_gate.yml` activates the selected test command as an
|
|
709
|
+
argv array. The generator renders each argument as a safe YAML scalar.
|
|
710
|
+
|
|
508
711
|
The Rails generator manages these host artifacts:
|
|
509
712
|
|
|
510
713
|
- `.quality_gate.yml`
|
|
511
714
|
- `.rubocop.yml`
|
|
512
715
|
- `config/initializers/bullet.rb`
|
|
513
716
|
- `config/initializers/strong_migrations.rb`
|
|
514
|
-
- a marked coverage block in
|
|
717
|
+
- a marked coverage block in the selected helper, before executable host code
|
|
515
718
|
|
|
516
719
|
With `--agents`, it additionally manages:
|
|
517
720
|
|
|
@@ -521,11 +724,20 @@ With `--agents`, it additionally manages:
|
|
|
521
724
|
- one marker-owned Quality Gate contract section in `CLAUDE.md`
|
|
522
725
|
- one marker-owned Quality Gate contract section in `AGENTS.md`
|
|
523
726
|
|
|
524
|
-
|
|
727
|
+
With `--codex`, it additionally manages `.codex/hooks.json`, executable
|
|
728
|
+
`.codex/hooks/quality_gate_fast.rb` and `.codex/hooks/quality_gate_verify_stop.rb`
|
|
729
|
+
scripts, and one marker-owned contract section in `AGENTS.md`. Codex activation
|
|
730
|
+
requires a trusted project and explicit review of both hook commands in `/hooks`;
|
|
731
|
+
the installer does not change trust. A custom Codex hook configuration is left
|
|
732
|
+
untouched for manual integration. See the
|
|
733
|
+
[Codex integration guide](docs/codex.md) for runtime limits, project discovery,
|
|
734
|
+
conflict handling, and removal.
|
|
735
|
+
|
|
736
|
+
Installation is idempotent. A missing file is written, while a byte-identical file is left untouched. For wholly owned files such as `.quality_gate.yml`, `.rubocop.yml`, hook scripts, and hook configuration, if an existing file has different content the generator never overwrites or merges it except when it exactly matches one narrowly defined prior snapshot. `.claude/settings.json` must match the previously shipped PostToolUse-only template; `.codex/hooks.json` must match the previously shipped Stop-only template generated for this same project root. The installer safely replaces those snapshots with current configuration while preserving file mode. Customized configuration, a Codex snapshot generated for another project root, and symlinks remain manual conflicts; other conflicts print the current template for manual use.
|
|
525
737
|
|
|
526
738
|
The generated Strong Migrations initializer begins with the exact provenance line `# Generated by Quality Gate.`. On its first install, QualityGate records the newest existing migration as the baseline, or records that no migration exists yet. On later runs, that provenance makes the recorded baseline take precedence, so newer migrations leave the generated initializer unchanged. An unmarked initializer is always developer-owned and therefore follows the conflict/manual policy; when it already contains `StrongMigrations.start_after`, the printed marked template preserves that established baseline instead of advancing it.
|
|
527
739
|
|
|
528
|
-
Use `--skip-initializers` when the host does not use Bullet or Strong Migrations. Use `--skip-coverage` to leave the
|
|
740
|
+
Use `--skip-initializers` when the host does not use Bullet or Strong Migrations. Use `--skip-coverage` to leave the selected test helper alone. Use `--pretend` to preview the run without changing the filesystem; pending writes are reported as skipped.
|
|
529
741
|
|
|
530
742
|
```sh
|
|
531
743
|
bin/rails generate quality_gate:install --skip-initializers
|
|
@@ -533,7 +745,66 @@ bin/rails generate quality_gate:install --skip-coverage
|
|
|
533
745
|
bin/rails generate quality_gate:install --pretend
|
|
534
746
|
```
|
|
535
747
|
|
|
536
|
-
For coverage, the generator preserves a UTF-8 BOM and shebang, then leading blank lines, ordinary comments, all Ruby and Emacs directives, and complete `=begin`/`=end` comment blocks before the marked block. It inserts coverage immediately before the first executable host code. Inserted lines use the helper's existing LF or CRLF convention.
|
|
748
|
+
For coverage, the generator preserves a UTF-8 BOM and shebang, then leading blank lines, ordinary comments, all Ruby and Emacs directives, and complete `=begin`/`=end` comment blocks before the marked block. It inserts coverage immediately before the first executable host code. Inserted lines use the helper's existing LF or CRLF convention. Generated Rails and Ruby coverage blocks exclude both `test` and `spec`.
|
|
749
|
+
|
|
750
|
+
### Optional GitHub Actions workflow
|
|
751
|
+
|
|
752
|
+
Pass `--ci` to either setup command to create
|
|
753
|
+
`.github/workflows/quality_gate.yml`:
|
|
754
|
+
|
|
755
|
+
```sh
|
|
756
|
+
bundle exec quality_gate init --ci
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
```sh
|
|
760
|
+
bin/rails generate quality_gate:install --ci
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
The workflow is opt-in. `--pretend` previews it without writing files. An
|
|
764
|
+
existing customized `.github/workflows/quality_gate.yml` is preserved and
|
|
765
|
+
reported for manual integration. Later setup without `--ci` leaves an installed
|
|
766
|
+
workflow alone.
|
|
767
|
+
|
|
768
|
+
The generated workflow runs on pushes and pull requests. It grants `contents: read`
|
|
769
|
+
and uses `actions/checkout@v7` with `fetch-depth: 0` and
|
|
770
|
+
`persist-credentials: false`. It uses `ruby/setup-ruby@v1` with Bundler caching.
|
|
771
|
+
Its Ruby selector uses the installing runtime's exact `RUBY_VERSION`. Separate
|
|
772
|
+
direct `fast`, `verify`, and `audit` steps enforce each gate's exit status.
|
|
773
|
+
|
|
774
|
+
Customize the workflow for your supported Ruby matrix, services, and environment.
|
|
775
|
+
The generator cannot infer application database services or secrets.
|
|
776
|
+
|
|
777
|
+
### Optional Herb checks
|
|
778
|
+
|
|
779
|
+
Herb adds ERB linting to the fast gate without changing its defaults. Install the
|
|
780
|
+
official CLI separately, then configure its local executable when needed:
|
|
781
|
+
|
|
782
|
+
```sh
|
|
783
|
+
npm install --save-dev @herb-tools/linter@0.11.0
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
```yaml
|
|
787
|
+
adapters:
|
|
788
|
+
fast:
|
|
789
|
+
- rubocop
|
|
790
|
+
- herb
|
|
791
|
+
commands:
|
|
792
|
+
fast:
|
|
793
|
+
herb:
|
|
794
|
+
- node_modules/.bin/herb-lint
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
Generated CI installs Ruby and Bundler dependencies only. If Herb is enabled,
|
|
798
|
+
customize the workflow to set up Node and install locked npm dependencies before
|
|
799
|
+
the fast step.
|
|
800
|
+
|
|
801
|
+
QualityGate appends JSON output flags and eligible selected paths to the command.
|
|
802
|
+
The default launcher is `herb-lint`. Bundler does not add npm's local binaries
|
|
803
|
+
to `PATH`. With no selected paths, Herb scans the project. With
|
|
804
|
+
selected paths, it receives ERB files and directories; unrelated files are
|
|
805
|
+
omitted. Herb applies its own `.herb.yml` exclusions. The generated fast hook
|
|
806
|
+
keeps Ruby checks unchanged. It checks ERB only when Herb is enabled. Hook
|
|
807
|
+
feedback may fail open; CI enforces direct gate exit codes.
|
|
537
808
|
|
|
538
809
|
### Claude Code agent hooks
|
|
539
810
|
|
|
@@ -543,13 +814,13 @@ Plain Ruby projects use `bundle exec quality_gate init --profile ruby --agents`
|
|
|
543
814
|
|
|
544
815
|
For agent integration, run `bin/rails generate quality_gate:install --agents`. The generator writes `.claude/hooks/quality_gate_fast.rb` and `.claude/hooks/quality_gate_verify_stop.rb`, installs the exact Claude Code `PostToolUse` and `Stop` entries in `.claude/settings.json`, and manages one marker-owned Quality Gate contract block inside `CLAUDE.md` and `AGENTS.md`. The Stop command has a 300-second Claude Code timeout. The marker-owned contract sections are narrower than the wholly owned files: a single stale Quality Gate block is replaced in place, the surrounding bytes are preserved, and any unmatched or multiple marker cases fall back to manual installation. If a hook file is byte-identical but has lost its executable mode, reinstalling repairs the mode without rewriting the file. After `bundle install` or a gem upgrade, rerun `bin/rails generate quality_gate:install --agents` to reinstall the generated hooks and contract files.
|
|
545
816
|
|
|
546
|
-
The `PostToolUse` hook runs file-scoped `quality_gate fast` after Ruby edits. Findings exit 2 and return the gate's JSON report to Claude as feedback. If an attempted fast run is unavailable, the first attempt in that unavailable streak exits 2 with one stderr line naming `bundle exec quality_gate fast` and `log/quality_gate_hooks.jsonl`; the already-applied edit stands and is not rolled back. Repeated unavailable attempts exit 0 silently.
|
|
817
|
+
The `PostToolUse` hook runs file-scoped `quality_gate fast` after Ruby edits. It also checks ERB edits when Herb is configured in the fast gate. Findings exit 2 and return the gate's JSON report to Claude as feedback. If an attempted fast run is unavailable, the first attempt in that unavailable streak exits 2 with one stderr line naming `bundle exec quality_gate fast` and `log/quality_gate_hooks.jsonl`; the already-applied edit stands and is not rolled back. Repeated unavailable attempts exit 0 silently. Other non-Ruby paths and deleted files remain cheap skips.
|
|
547
818
|
|
|
548
819
|
The `Stop` hook checks for Ruby working-tree edits and automatically runs `quality_gate verify` before Claude finishes. With no Ruby edits it skips without starting the verifier. A clean result from the same `session_id` is debounced when no Ruby edit was logged at or after that result. Findings exit 2 with the machine-readable JSON report only after the matching `verify_blocked` record is safely appended, so Claude receives the feedback and continues working. If prior hook history cannot be read safely or that record cannot be written, the hook suppresses the feedback and fails open so the retry cap cannot deadlock. Invalid verifier output, a tool failure, a verifier timeout, or a command exception also fails open as unavailable. After three consecutive blocked finish attempts in one session, the next attempt is capped and exits 0.
|
|
549
820
|
|
|
550
821
|
Hook activity is appended to `log/quality_gate_hooks.jsonl`. Stop records include `session_id` and use the outcomes `verify_skipped`, `verify_debounced`, `verify_clean`, `verify_blocked`, `verify_unavailable`, and `verify_cap`. The CLI warns on stderr when the last 20 valid records include either fast-hook `unavailable` or Stop-hook `verify_unavailable` outcomes. The warning does not change the gate's JSON output or exit code.
|
|
551
822
|
|
|
552
|
-
Codex
|
|
823
|
+
Codex uses its native patch and Stop hooks only when you install them with `--codex`, start Codex in the installed project or one of its descendants, and explicitly review and trust both commands. Patch feedback runs only after native `apply_patch` calls; shell writes still reach final Stop verification. It is advisory and does not roll back edits. The 30-second native patch-hook timeout can be exceeded by a project fast budget longer than the shipped 10-second RuboCop timeout, in which case run fast manually. The full activation and removal instructions are in `docs/codex.md`.
|
|
553
824
|
|
|
554
825
|
For the Rails generator, when `test/test_helper.rb` is missing, it warns that Minitest coverage wiring was skipped, installs the other files, and exits successfully. Plain Ruby init instead requires an existing helper or `--skip-coverage`. Every successful install or preview run ends by naming the next command:
|
|
555
826
|
|
|
@@ -559,7 +830,7 @@ bundle exec quality_gate fast
|
|
|
559
830
|
|
|
560
831
|
`bin/rails destroy quality_gate:install` is intentionally read-only. Automatic removal is not supported because coverage is embedded in a developer-owned helper and the agent contract files may contain developer-owned text around the managed markers; the command changes nothing and directs you to the manual removal steps below instead of printing an install summary or next command.
|
|
561
832
|
|
|
562
|
-
To undo a clean installation, delete the files that the generator wrote (`.quality_gate.yml`, `.rubocop.yml`, `config/initializers/bullet.rb`, `config/initializers/strong_migrations.rb`,
|
|
833
|
+
To undo a clean installation, delete the files that the generator wrote (`.quality_gate.yml`, `.rubocop.yml`, `config/initializers/bullet.rb`, `config/initializers/strong_migrations.rb`, the installed Claude and Codex hook scripts, `.claude/settings.json`, and `.codex/hooks.json` only when it contains solely generated Quality Gate configuration). Then remove the complete block in `test/test_helper.rb` from `# quality_gate coverage — start` through `# quality_gate coverage — end`, including both marker lines, and remove the complete Quality Gate block from `CLAUDE.md` and `AGENTS.md` from `<!-- quality_gate agent contract — start -->` through `<!-- quality_gate agent contract — end -->`. Do not delete a file that predated the generator or contains developer changes outside the managed markers.
|
|
563
834
|
|
|
564
835
|
## Acceptance evidence
|
|
565
836
|
|
data/docs/codex.md
CHANGED
|
@@ -1,14 +1,42 @@
|
|
|
1
|
-
# Codex and
|
|
1
|
+
# Codex and Quality Gate
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Quality Gate offers two optional native Codex hooks. The `PostToolUse` hook gives file-scoped fast feedback after patches; the `Stop` hook runs the full verification gate. Install both explicitly in a plain Ruby project:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
bundle exec quality_gate init --codex
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Claude Code's existing fast feedback is triggered by native `Edit` and `Write` calls. Codex uses its native `apply_patch` tool event for the equivalent patch feedback; the hook matcher does not include shell writes or other tools.
|
|
10
|
+
|
|
11
|
+
For Rails:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
bin/rails generate quality_gate:install --codex
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`--codex` installs `.codex/hooks.json`, executable `.codex/hooks/quality_gate_fast.rb` and `.codex/hooks/quality_gate_verify_stop.rb` scripts, and the Quality Gate section in `AGENTS.md`. It does not install Claude Code files. Use `--agents --codex` to install both clients; the shared `AGENTS.md` section is still installed once. `--pretend` previews filesystem changes. Reinstalling repairs either script's executable mode and leaves matching files unchanged.
|
|
18
|
+
|
|
19
|
+
The patch hook runs `quality_gate fast` after completed native `apply_patch` calls only. It selects changed Ruby files and, when Herb is configured in the fast gate, ERB files. A mixed patch gets one file-scoped run. Other tools, including shell writes, do not trigger this feedback hook; those changes are still checked by the final Stop hook. The patch has already been applied before this hook runs, so findings are advisory context for Codex and never roll the edit back.
|
|
20
|
+
|
|
21
|
+
A clean run returns no extra context. Findings provide Codex with file and rule details to guide a repair. When input, configuration, or a tool is unavailable, the hook reports that fact to Codex and asks it to tell you and run `bundle exec quality_gate fast` manually. A missing fast check never claims the files are clean. Run the manual gate and use CI exit status as enforcement evidence.
|
|
22
|
+
|
|
23
|
+
Codex gives the patch hook a 30-second native timeout. The shipped RuboCop fast timeout is 10 seconds, but a longer project-specific fast budget or slow analyzer can exceed Codex's hook timeout. In that case, use the manual fast command. The full Stop hook remains synchronous on every Stop and uses its existing 600-second hook timeout. It runs the full `verify` gate, can add substantial latency, and asks for one repair continuation when it finds issues. Codex verifies again on the resumed Stop; if findings remain, it reports the cap and allows the turn to finish. Runtime, input, and tool failures report unavailable and also allow the turn to finish. Hooks provide feedback; an agent session ending is not proof that checks passed.
|
|
24
|
+
|
|
25
|
+
This integration requires a Codex CLI version with native hooks; it was verified with CLI 0.160.0. Check the [official Codex hooks documentation](https://developers.openai.com/codex/hooks) for current requirements and behavior. [Project configuration layers](https://developers.openai.com/codex/config-basic) load from the project root down to the session working directory, so start Codex in the installed project or one of its descendants for its `.codex` configuration to apply. In a monorepo, a session started at the repository root does not load a nested subproject's hook configuration.
|
|
26
|
+
|
|
27
|
+
Codex project hooks require a trusted project and explicit hook review. In Codex, open `/hooks`, inspect both scripts and both generated command definitions in `.codex/hooks.json`, then decide whether to trust them. Review both commands again after hook configuration changes or a Quality Gate upgrade. Quality Gate never writes Codex trust state, user-home files, or `.codex/config.toml`. Doctor can recognize installed files, but cannot establish trust, activation, or execution; Codex supplies no Quality Gate hook-history source, so Doctor leaves execution history unchecked.
|
|
28
|
+
|
|
29
|
+
The generated commands contain absolute paths to the installed Ruby scripts, so they work when Codex starts in a nested working directory. If the project moves, update both command paths and review them in `/hooks` again. Existing customized `.codex/hooks.json` is left unchanged and needs manual integration using the proposal printed by the installer. The only upgrade exception is the exact previously shipped Stop-only JSON generated for this same project root; changed-root snapshots, formatting changes, extra hooks, and customized bytes need manual integration. Symlink destinations are never followed.
|
|
30
|
+
|
|
31
|
+
The launchers use the installed project's `Gemfile`; install the project's bundle with `bundle install` before trusting the hooks. Ruby and Bundler must be available to the Codex process. To remove the integration, remove both Quality Gate hook entries and scripts, and remove `.codex/hooks.json` only when it contains solely generated Quality Gate configuration. Remove only the Codex instructions from `AGENTS.md` when it also contains Claude guidance, or remove the Quality Gate section when Codex is its only client.
|
|
32
|
+
|
|
33
|
+
Run the gates directly as well:
|
|
4
34
|
|
|
5
35
|
- Run `bundle exec quality_gate fast` after Ruby edits.
|
|
6
36
|
- Run `bundle exec quality_gate verify` before you finish a change.
|
|
7
37
|
- Run `bundle exec quality_gate audit` before you merge security-sensitive work.
|
|
8
38
|
|
|
9
|
-
Fix findings before you continue editing. Use `--format json` for structured results
|
|
10
|
-
|
|
11
|
-
Automatic Claude hooks can fail open or cap retries. An agent session ending is not proof of verification. CI should run the gate commands directly and enforce their exit status.
|
|
39
|
+
Fix findings before you continue editing. Use `--format json` for structured results and inspect `checks` with findings to see each tool's status and scope. Explicit selected paths must exist; a missing path is an input failure. A clean gate describes only its configured checks, not overall application correctness.
|
|
12
40
|
|
|
13
41
|
Exit meanings stay the same in Codex and Claude Code:
|
|
14
42
|
|
|
@@ -16,16 +44,16 @@ Exit meanings stay the same in Codex and Claude Code:
|
|
|
16
44
|
- Exit 1 means the gate reported findings and no tool failures.
|
|
17
45
|
- Exit 2 means the gate could not complete cleanly because of invalid input, configuration, or another tool failure.
|
|
18
46
|
|
|
19
|
-
If the automatic Claude Code hook becomes unavailable, inspect `log/quality_gate_hooks.jsonl`, run `bundle install`, and reinstall the generated integration with the setup command for your project.
|
|
47
|
+
If the automatic Claude Code hook becomes unavailable, inspect `log/quality_gate_hooks.jsonl`, run `bundle install`, and reinstall the generated integration with the setup command for your project. Codex does not provide this Claude hook history log.
|
|
20
48
|
|
|
21
|
-
For a plain Ruby project, install or refresh
|
|
49
|
+
For a plain Ruby project, install or refresh both Claude Code and Codex integration with:
|
|
22
50
|
|
|
23
51
|
```sh
|
|
24
|
-
bundle exec quality_gate init --profile ruby --agents
|
|
52
|
+
bundle exec quality_gate init --profile ruby --agents --codex
|
|
25
53
|
```
|
|
26
54
|
|
|
27
55
|
For Rails:
|
|
28
56
|
|
|
29
57
|
```sh
|
|
30
|
-
bin/rails generate quality_gate:install --agents
|
|
58
|
+
bin/rails generate quality_gate:install --agents --codex
|
|
31
59
|
```
|