Skip to content

Commit 6b9e596

Browse files
committed
refactor(auto-code-quality): replace Stop hooks with /cq skill
The 3 Stop hooks (format-on-stop, lint-file, advisory-test-runner) caused race conditions with background agents, fired too frequently during orchestration pauses, and produced lint results as passive context that Claude couldn't act on. Replace them with: - /cq skill — Claude runs format, lint (auto-fix), and tests explicitly - quality-gate.py — lightweight Stop hook that prompts /cq when needed - task-tracker.py — tracks active background tasks to avoid conflicts The gate is background-task-aware and self-cleaning (deletes temp files on block to prevent loops).
1 parent 360e113 commit 6b9e596

13 files changed

Lines changed: 436 additions & 1247 deletions

File tree

container/.devcontainer/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Declared in `settings.json` under `enabledPlugins`, auto-activated on start:
5050
- **skill-engine** — 23 general coding skills + auto-suggestion
5151
- **spec-workflow** — 3 spec lifecycle skills (`/spec`, `/build`, `/specs`) + spec-reminder hook
5252
- **session-context** — Git state injection, TODO harvesting, commit reminders
53-
- **auto-code-quality**Auto-format + auto-lint + advisory test runner
53+
- **auto-code-quality**File tracking, syntax validation, `/cq` quality gate (format + lint + test on demand)
5454
- **workspace-scope-guard** — Blocks writes outside working directory
5555
- **dangerous-command-blocker** — Blocks destructive bash commands
5656
- **protected-files-guard** — Blocks edits to secrets/lock files

container/.devcontainer/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@
4040
- **Cross-references added** — before-you-install, accessing-services, troubleshooting, and devcontainer-cli pages now link to the Windows networking guide
4141
- **Agent-browser CDP troubleshooting** — new troubleshooting section for host Chrome connection issues (localhost vs host.docker.internal, Chrome version requirements, port exposure)
4242

43+
### Code Quality
44+
45+
- **Replaced auto-format/lint/test Stop hooks with `/cq` skill** — the three Stop hooks (`format-on-stop.py`, `lint-file.py`, `advisory-test-runner.py`) that ran automatically on every stop are replaced by a single `/cq` skill that Claude invokes explicitly. Eliminates race conditions with background agents, stops firing during orchestration pauses, and lets Claude act on lint/test results instead of ignoring passive context.
46+
- **New quality gate Stop hook** — lightweight `quality-gate.py` (~1ms) checks whether files were edited and no background tasks are running, then blocks the stop with a prompt to run `/cq`. Deletes temp files on block to prevent loops.
47+
- **New task tracker hooks**`task-tracker.py` handles `TaskCreated`/`TaskCompleted` events to maintain an active-task count. The quality gate skips blocking while tasks are running, preventing format/lint conflicts with background agents.
48+
4349
### CI
4450

4551
- **Canary pre-release publishing** — every push to `staging` that touches `container/` now auto-publishes a canary build to npm. Install with `npm i @coredirective/cf-container@canary` to try unreleased changes. Versions use the format `{version}-staging.{sha7}`.

container/.devcontainer/README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,21 @@ claude --resume # Resume previous session
218218
| `codex` | OpenAI Codex CLI terminal coding agent |
219219
| `hermes` | Nous Research Hermes Agent CLI (run `hermes setup` on first use) |
220220

221+
### Windows Host Chrome CDP
222+
223+
For Hermes, Vercel agent-browser, Codex, or Claude Code to control Chrome running on a Windows host, run this from an Administrator PowerShell at the repository root:
224+
225+
```powershell
226+
.\.devcontainer\scripts\start-hermes-chrome.ps1
227+
```
228+
229+
The devcontainer uses `HERMES_CDP_ENDPOINT=http://192.168.65.254:9223` for Docker Desktop. Verify the current host IPv4 from inside the container:
230+
231+
```bash
232+
CDP_HOST=$(getent ahostsv4 host.docker.internal | awk 'NR==1 {print $1}')
233+
curl http://$CDP_HOST:9223/json/version
234+
```
235+
221236
### Code Intelligence
222237
| Tool | Description |
223238
|------|-------------|
@@ -335,7 +350,7 @@ CodeForge includes custom devcontainer features. Any feature can be disabled by
335350

336351
### auto-code-quality
337352

338-
Combined auto-formatter, auto-linter, and advisory test runner plugin at `plugins/devs-marketplace/plugins/auto-code-quality/`. Three-phase pipeline: collect edited files (PostToolUse), batch format + lint (Stop), and advisory test runner (Stop). Supports all languages from the former auto-formatter + auto-linter plugins. Replaces the separate `auto-formatter` and `auto-linter` plugins.
353+
Code quality plugin at `plugins/devs-marketplace/plugins/auto-code-quality/`. Tracks edited files (PostToolUse), validates data file syntax instantly, tracks background tasks (TaskCreated/Completed), and gates stops with a lightweight check — if files were edited and no tasks are running, prompts Claude to run the `/cq` skill for formatting, linting (with auto-fix), and affected test execution. Supports Python, JS/TS, Go, Shell, Rust, Markdown, YAML, TOML, and Dockerfiles.
339354

340355
## Alias Management
341356

container/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
},
8585
{
8686
"name": "auto-code-quality",
87-
"description": "Self-contained code quality: auto-format + auto-lint edited files (Ruff/Black, Biome, gofmt, shfmt, dprint, rustfmt, Pyright, ShellCheck, go vet, hadolint, clippy)",
87+
"description": "Code quality with /cq skill: file tracking, syntax validation, background-task-aware quality gate, on-demand format + lint + test (Ruff, Biome, gofmt, shfmt, dprint, rustfmt, Pyright, ShellCheck, go vet, hadolint, clippy)",
8888
"version": "1.0.0",
8989
"source": "./plugins/auto-code-quality",
9090
"category": "development",

container/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "auto-code-quality",
3-
"description": "Self-contained code quality plugin: collects edited files, batch-formats at Stop (Ruff/Black for Python, gofmt for Go, Biome for JS/TS/CSS/JSON/GraphQL/HTML, shfmt for Shell, dprint for Markdown/YAML/TOML/Dockerfile, rustfmt for Rust), batch-lints at Stop (Pyright + Ruff for Python, Biome for JS/TS/CSS/GraphQL, ShellCheck for Shell, go vet for Go, hadolint for Dockerfile, clippy for Rust), and validates JSON/JSONC/YAML/TOML syntax on edit",
3+
"description": "Code quality plugin: collects edited files on edit, validates JSON/JSONC/YAML/TOML syntax instantly, tracks background tasks, and gates stops with a /cq skill prompt — format, lint, and test on demand instead of automatically",
44
"author": {
55
"name": "AnExiledDev"
66
}

container/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/README.md

Lines changed: 89 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
# auto-code-quality
22

3-
Self-contained Claude Code plugin that automatically formats and lints edited files. Drop it into any Claude Code plugin marketplace and enable it — no other plugins required.
3+
Claude Code plugin that tracks edited files and runs code quality checks on demand via the `/cq` skill. Drop it into any Claude Code plugin marketplace and enable it — no other plugins required.
44

55
## What It Does
66

7-
Three-phase pipeline that runs transparently during your Claude Code session:
7+
Two-phase pipeline with an explicit quality gate:
88

9-
1. **Collect** (PostToolUse on Edit/Write) — Records which files Claude edits
10-
2. **Format** (Stop hook) — Batch-formats all edited files when Claude finishes responding
11-
3. **Lint** (Stop hook) — Batch-lints all edited files and surfaces warnings as context
9+
1. **Track** (PostToolUse on Edit/Write) — Records which files Claude edits, validates data file syntax instantly
10+
2. **Gate** (Stop hook) — Lightweight check: if files were edited and no background tasks are running, blocks the stop and prompts Claude to run `/cq`
11+
3. **Quality** (`/cq` skill) — Claude formats, lints (with auto-fix), and runs affected tests on all edited files
1212

13-
Additionally validates JSON, JSONC, YAML, and TOML syntax immediately after each edit.
13+
The `/cq` skill can also be invoked manually at any time during a session.
1414

15-
All phases are non-blocking. Missing tools are silently skipped. The plugin always exits cleanly — it will never interrupt Claude.
15+
### Why a skill instead of automatic hooks?
16+
17+
Previous versions ran formatters, linters, and test runners as Stop hooks. This caused issues with background agents (race conditions on file writes), fired too frequently during orchestration pauses, and produced lint results as passive context that was often ignored. The `/cq` skill runs explicitly — Claude can act on results, fix issues, and re-run checks.
1618

1719
## Required Tools
1820

@@ -21,7 +23,6 @@ Install the tools for the languages you work with. Everything is optional — th
2123
| Language | Formatter | Linter(s) | Install |
2224
|----------|-----------|-----------|---------|
2325
| Python | [ruff](https://docs.astral.sh/ruff/) | [pyright](https://github.com/microsoft/pyright), ruff check | `pip install ruff` / `npm i -g pyright` |
24-
| Python (fallback) | [black](https://github.com/psf/black) || `pip install black` |
2526
| Go | gofmt (bundled with Go) | go vet (bundled with Go) | [Install Go](https://go.dev/dl/) |
2627
| JS/TS/CSS/GraphQL/HTML | [biome](https://biomejs.dev/) | biome lint | `npm i -D @biomejs/biome` or `npm i -g @biomejs/biome` |
2728
| Shell | [shfmt](https://github.com/mvdan/sh) | [shellcheck](https://github.com/koalaman/shellcheck) | `brew install shfmt shellcheck` |
@@ -48,6 +49,28 @@ Biome is resolved in this order:
4849
1. Project-local: walks up from the edited file looking for `node_modules/.bin/biome`
4950
2. Global: checks PATH via `which biome`
5051

52+
## Usage
53+
54+
### Automatic (quality gate)
55+
56+
Just work normally. When Claude stops after editing files:
57+
58+
1. The quality gate checks for edited files and active background tasks
59+
2. If files were edited and no tasks are running, it blocks the stop
60+
3. Claude runs `/cq` automatically — formats, lints, tests, fixes issues
61+
4. Claude stops cleanly on the second attempt (temp files cleaned up)
62+
63+
### Manual
64+
65+
Type `/cq` at any point to run quality checks on all files edited so far in the session.
66+
67+
### With background tasks
68+
69+
The quality gate is background-task-aware:
70+
- While tasks are running, the gate stays silent (no blocking)
71+
- Once all tasks complete and Claude stops, the gate activates
72+
- This prevents race conditions from formatting files that agents are still writing
73+
5174
## Installation
5275

5376
### CodeForge DevContainer
@@ -85,60 +108,97 @@ You edit a file (Edit/Write tool)
85108
86109
├─→ collect-edited-files.py Appends path to temp files
87110
└─→ syntax-validator.py Validates JSON/YAML/TOML syntax immediately
88-
89-
│ ... Claude keeps working ...
90-
111+
112+
Background task spawned (TaskCreated)
113+
└─→ task-tracker.py Records task as active
114+
115+
Background task done (TaskCompleted)
116+
└─→ task-tracker.py Removes task from active list
117+
91118
Claude stops responding (Stop event)
92-
93-
├─→ format-on-stop.py Reads temp file, formats each file by extension
94-
└─→ lint-file.py Reads temp file, lints each file, injects warnings
119+
└─→ quality-gate.py Checks tasks + edited files
120+
121+
├─ Tasks active? → skip (exit 0)
122+
├─ No edits? → skip (exit 0)
123+
└─ Edits found → block stop → Claude runs /cq
124+
→ /cq formats, lints, tests
125+
→ cleans up temp files
126+
→ Claude stops again → gate exits clean
95127
```
96128

97129
### Temp File Convention
98130

99-
Edited file paths are stored in session-scoped temp files:
100-
- `/tmp/claude-cq-edited-{session_id}` — consumed by the formatter
101-
- `/tmp/claude-cq-lint-{session_id}` — consumed by the linter
131+
Session-scoped temp files in `/tmp/`:
102132

103-
Both are always cleaned up after processing (even on error).
133+
| File | Purpose | Written by | Read by |
134+
|------|---------|------------|---------|
135+
| `claude-cq-edited-{session_id}` | Edited file paths (format + test) | collect-edited-files.py | quality-gate.py, /cq skill |
136+
| `claude-cq-lint-{session_id}` | Edited file paths (lint) | collect-edited-files.py | /cq skill |
137+
| `claude-active-tasks-{session_id}` | Active background task IDs | task-tracker.py | quality-gate.py |
138+
139+
All temp files are cleaned up after processing (by the gate and/or the skill).
140+
141+
### Loop Prevention
142+
143+
The quality gate deletes the edited-files temp file when it blocks. On the second stop (after `/cq` runs), the temp file is gone — the gate exits clean. The `/cq` skill also cleans up temp files as a safety net.
104144

105145
### Timeouts
106146

107147
| Hook | Timeout |
108148
|------|---------|
109149
| File collection | 3s |
110150
| Syntax validation | 5s |
111-
| Batch formatting | 15s total |
112-
| Batch linting | 60s total |
113-
| Individual tool | 10-12s each |
151+
| Task tracking | 3s |
152+
| Quality gate | 3s |
153+
154+
The `/cq` skill has no timeout — it runs as a normal Claude conversation turn.
155+
156+
## Disabling
157+
158+
### Disable the entire plugin
159+
160+
Remove from `enabledPlugins` in your settings.
161+
162+
### Disable individual hooks
163+
164+
Add the script name (without `.py`) to the `disabled` array in `~/.claude/disabled-hooks.json`:
165+
166+
```json
167+
{
168+
"disabled": ["quality-gate"]
169+
}
170+
```
171+
172+
Available hook names: `collect-edited-files`, `syntax-validator`, `task-tracker`, `quality-gate`
114173

115174
## Conflict Warning
116175

117176
This plugin bundles functionality that may overlap with other plugins. If you're using any of the following, **disable them** before enabling this plugin to avoid duplicate processing:
118177

119-
- `auto-formatter` — formatting is included here
120-
- `auto-linter` — linting is included here
178+
- `auto-formatter` — formatting is included in `/cq`
179+
- `auto-linter` — linting is included in `/cq`
121180
- `code-directive` `collect-edited-files.py` hook — file collection is included here
122181

123-
All pipelines use the `claude-cq-*` temp file prefix, so enabling both won't corrupt data — but files would be formatted and linted twice.
124-
125182
## Plugin Structure
126183

127184
```
128185
auto-code-quality/
129186
├── .claude-plugin/
130187
│ └── plugin.json # Plugin metadata
131188
├── hooks/
132-
│ └── hooks.json # Hook registrations (PostToolUse + Stop)
189+
│ └── hooks.json # Hook registrations
133190
├── scripts/
134191
│ ├── collect-edited-files.py # File path collector (PostToolUse)
135192
│ ├── syntax-validator.py # JSON/YAML/TOML validator (PostToolUse)
136-
│ ├── format-on-stop.py # Batch formatter (Stop)
137-
│ └── lint-file.py # Batch linter (Stop)
193+
│ ├── task-tracker.py # Background task counter (TaskCreated/Completed)
194+
│ └── quality-gate.py # Stop gate — prompts /cq if needed (Stop)
195+
├── skills/
196+
│ └── cq/
197+
│ └── SKILL.md # /cq skill definition
138198
└── README.md # This file
139199
```
140200

141201
## Requirements
142202

143203
- Python 3.11+ (for `tomllib` support in syntax validation; older Python skips TOML)
144-
- Claude Code with plugin hook support
204+
- Claude Code with plugin hook support and skill support

container/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/hooks/hooks.json

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"description": "Self-contained code quality: file collection on edit, syntax validation, batch formatting + linting at stop",
2+
"description": "Code quality: file collection on edit, syntax validation, task tracking, and /cq quality gate at stop",
33
"hooks": {
44
"PostToolUse": [
55
{
@@ -18,23 +18,35 @@
1818
]
1919
}
2020
],
21-
"Stop": [
21+
"TaskCreated": [
2222
{
2323
"hooks": [
2424
{
2525
"type": "command",
26-
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/format-on-stop.py",
27-
"timeout": 15
28-
},
26+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/task-tracker.py",
27+
"timeout": 3
28+
}
29+
]
30+
}
31+
],
32+
"TaskCompleted": [
33+
{
34+
"hooks": [
2935
{
3036
"type": "command",
31-
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/lint-file.py",
32-
"timeout": 60
33-
},
37+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/task-tracker.py",
38+
"timeout": 3
39+
}
40+
]
41+
}
42+
],
43+
"Stop": [
44+
{
45+
"hooks": [
3446
{
3547
"type": "command",
36-
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/advisory-test-runner.py",
37-
"timeout": 20
48+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/quality-gate.py",
49+
"timeout": 3
3850
}
3951
]
4052
}

0 commit comments

Comments
 (0)