agent-quality-skills 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Narenrit Hadsadintorn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,293 @@
1
+ # agent-quality-skills
2
+
3
+ [![npm](https://img.shields.io/npm/v/agent-quality-skills)](https://www.npmjs.com/package/agent-quality-skills)
4
+ [![licence: MIT](https://img.shields.io/badge/licence-MIT-blue)](LICENSE)
5
+
6
+ A pre-ship **quality gate** skill for coding agents (Claude Code, Cursor, Codex and
7
+ others). Ask *"is this ready to merge?"* and the agent:
8
+
9
+ 1. runs your repo's real lint, typecheck, test and build scripts;
10
+ 2. reviews the diff against your written standards **and** against the spec it came from;
11
+ 3. applies only fixes a formatter could make;
12
+ 4. returns a structured report: Blocking / Major / Minor findings and a verdict.
13
+
14
+ It installs alongside Cloudflare's **security-audit** skill. The two do different jobs:
15
+
16
+ | | reviews | cost | when |
17
+ |---|---|---|---|
18
+ | **quality-gate** (here) | a **diff** | one agent, minutes | every change, before merge |
19
+ | **security-audit** ([Cloudflare](https://github.com/cloudflare/security-audit-skill)) | a **system** | many agents, hours | scheduled, before a pen test |
20
+
21
+ The gate reviews and applies mechanically-safe fixes. The audit surveys and reports, and
22
+ does not modify source. Neither replaces the other.
23
+
24
+ ---
25
+
26
+ ## Install
27
+
28
+ Pick one. All of them install the same files.
29
+
30
+ **skills CLI** ([skills.sh](https://skills.sh)): detects your agents and asks where to
31
+ install.
32
+
33
+ ```bash
34
+ npx skills add captainkie/agent-quality-skills # the gate
35
+ npx skills add cloudflare/security-audit-skill # the audit, from upstream
36
+ ```
37
+
38
+ **npm package**: installs both skills into Claude Code in one command.
39
+
40
+ ```bash
41
+ npx agent-quality-skills # both, into ~/.claude/skills
42
+ npx agent-quality-skills --gate-only # just the gate, no network or git needed
43
+ npx agent-quality-skills --project # into ./.claude/skills, for one repo
44
+ npx agent-quality-skills --dir <path> # somewhere explicit
45
+ ```
46
+
47
+ **Shell script**: for machines without Node. It takes the same flags.
48
+
49
+ ```bash
50
+ curl -fsSL https://raw.githubusercontent.com/captainkie/agent-quality-skills/main/install.sh | bash
51
+ ```
52
+
53
+ Re-running any of them updates in place. Nothing outside the chosen skills directory is
54
+ written, and no shell profile is touched.
55
+
56
+ Updating and removing:
57
+
58
+ ```bash
59
+ npx skills update quality-gate # if installed with the skills CLI
60
+ npx agent-quality-skills # if installed with npm: just run it again
61
+ npx skills remove quality-gate
62
+ ```
63
+
64
+ ### Optional: per-project config
65
+
66
+ ```bash
67
+ curl -fsSL https://raw.githubusercontent.com/captainkie/agent-quality-skills/main/templates/QUALITY-GATE.md -o QUALITY-GATE.md
68
+ ```
69
+
70
+ Fill it in at your repo root. It tells the gate where your standards live and which
71
+ changes get the full review versus a batched one (lanes). It also lists your protected
72
+ branches and merge rules, and any project traps a reviewer cannot infer from the code.
73
+ The gate works without it.
74
+
75
+ ---
76
+
77
+ ## Using it
78
+
79
+ No special command. Ask in plain words once the work is done:
80
+
81
+ > is this ready to merge? · review this branch · does this follow our standards? ·
82
+ > does this match the spec in docs/specs/checkout.md? · security-review the auth changes
83
+
84
+ It triggers on those requests even without the words "skill" or "standards". It does
85
+ **not** trigger for writing features, explaining code, or scaffolding specs. It is a
86
+ reviewer, not an author.
87
+
88
+ ---
89
+
90
+ ## What it does, step by step
91
+
92
+ The gate runs the same six steps, in the same order, every time. That is the point:
93
+ two reviews of the same diff should not differ because one reviewer was tired.
94
+
95
+ ### Step 1 — Resolve the standards
96
+
97
+ **Goal:** review against *your* rules, not the agent's taste.
98
+
99
+ - Looks for your written standards, stopping at the first that exists:
100
+ `docs/standards/` → `docs/requirements/standards/` → `standards/` → `.standards/` →
101
+ `CONTRIBUTING.md`. It searches **upward** from the working directory, because in a
102
+ multi-repo workspace the standards often live one level above the repo.
103
+ - Reads `QUALITY-GATE.md` first if the project has one.
104
+ - **Your docs override the bundled checklists** wherever the two conflict.
105
+ - If you have no docs, it falls back to the bundled checklists. It reads only the ones
106
+ that match the files in the diff:
107
+
108
+ | bundled reference | read when the diff includes… |
109
+ |---|---|
110
+ | `backend-checklist.md` | controllers, services, repositories, DTOs, entities, migrations, workers, queues |
111
+ | `frontend-checklist.md` | components, pages, loaders, forms, client state, rendering user input |
112
+ | `security-checklist.md` | auth, authorization, input handling, uploads, logging, secrets, outbound URLs. Almost always |
113
+ | `evidence-contract.md` | every run that is about to write a security finding |
114
+ | `gates-and-fixes.md` | every run: how to find and run the real gates, and the safe-fix policy |
115
+ | `go-live-checklist.md` | release / production-readiness reviews only |
116
+
117
+ ### Step 2 — Determine scope, and pin what the change was supposed to be
118
+
119
+ **Goal:** say exactly what was reviewed, and what it was meant to do.
120
+
121
+ - **What to review:** the path you named. Otherwise the uncommitted changes plus the
122
+ branch against its base (`main` / `master` / `develop`). On a clean tree it reviews
123
+ the last commit. It also covers **what the change affects**: a changed DTO pulls in
124
+ its controller, its service and the published API contract. Generated and vendored
125
+ files are skipped.
126
+ - **One line at the top of the report** states the scope, so the reader knows what was
127
+ *not* covered.
128
+ - **What it was supposed to be.** It looks for the originating spec in this order: a
129
+ path you named → the project's spec directory → an issue referenced in the commits →
130
+ the PR body → the backlog file. If there is none, the report says
131
+ **"no spec available"**. The gate never invents a spec from the diff, because
132
+ checking a diff against itself always passes.
133
+
134
+ ### Step 3 — Run the repo's real gates
135
+
136
+ **Goal:** let machines catch the mechanical problems, so reading time goes to judgement.
137
+
138
+ - Reads the manifest (`package.json`, `Makefile`, `pyproject.toml`, `Cargo.toml`, …) and
139
+ runs **the scripts that exist**: lint, typecheck, test, build.
140
+ - Reports **real counts and the first real errors**, never a guess. A missing script is
141
+ reported as `⏭ no script`, which counts as neither a pass nor a failure.
142
+ - It guards against three traps that have each produced a false green:
143
+ - **Piping a gate hides its result.** `cmd | tail` returns `tail`'s exit code, not
144
+ the gate's.
145
+ - **A suite you remember is not the suite that exists.** It lists the scripts and
146
+ runs every one that is a gate.
147
+ - **The npm script may not be what CI runs.** When CI passes flags the script omits,
148
+ the script can exit 0 while CI fails, so the two are compared.
149
+
150
+ ### Step 4 — Audit against the standards
151
+
152
+ **Goal:** the judgement a careful reviewer brings, on nine axes.
153
+
154
+ | axis | asks |
155
+ |---|---|
156
+ | **Correctness** | requirements met · edge cases · null / undefined · failure paths |
157
+ | **Security** | held to the evidence contract (below) before anything is written |
158
+ | **Architecture** | layer boundaries · thin controllers · logic in services · persistence-only repositories |
159
+ | **API contract** | naming · versioning · envelope · pagination on collections · no unversioned breaking change |
160
+ | **Data** | keys · audit fields · soft delete · foreign keys and indexes · reversible migrations · no auto-sync in production |
161
+ | **Maintainability** | clear names · small functions · shallow nesting · no magic values · strict types |
162
+ | **Testing** | changed logic comes with tests · critical flows covered · no sleep-based or order-dependent tests |
163
+ | **Performance, caching, limits** | asked **together** for every endpoint the diff touches: bounded · cached per policy · authorized on every door to the same write · rate limited if public |
164
+ | **Spec fidelity** | only when step 2 found a spec. **Missing** · **Scope creep** · **Implemented but wrong** (the one that hides) |
165
+
166
+ Every finding gets a tier:
167
+
168
+ | tier | meaning |
169
+ |---|---|
170
+ | 🔴 **Blocking** | must fix before merge: confirmed security gap, missing authorization, data-corruption risk, undocumented breaking change, critical bug |
171
+ | 🟠 **Major** | should fix before release: missing tests, missing validation, N+1 or unbounded query, incomplete error handling |
172
+ | 🟡 **Minor** | optional: naming, readability, small refactors |
173
+ | 🔍 **Needs validation** | **no severity.** A source-grounded question blocked on a fact outside the repo |
174
+
175
+ ### Step 5 — Apply safe fixes only
176
+
177
+ **Goal:** remove the noise without touching anything that needs a human.
178
+
179
+ | applied, then listed | reported, never applied |
180
+ |---|---|
181
+ | formatter output | logic or control flow |
182
+ | import order, unused imports | replacing loose types with real ones |
183
+ | `const` over `let` | adding or changing validation |
184
+ | quote, semicolon, trailing-comma style | renaming public symbols, endpoints, fields, enum values |
185
+ | | security fixes · architecture moves · schema and migration changes |
186
+
187
+ The test: a fix is safe only if a formatter or linter would make it **and** it cannot
188
+ change runtime behaviour or a public contract. The affected gate is re-run afterwards,
189
+ so the report reflects the fixed state.
190
+
191
+ ### Step 6 — Emit the verdict
192
+
193
+ **Goal:** the same report shape every time, so it can be read in ten seconds.
194
+
195
+ ```
196
+ # Quality Gate — feature/checkout vs develop · 6 files
197
+
198
+ ## Summary
199
+ ## Gates Lint ✅ (3 auto-fixed) · Typecheck ✅ · Tests ❌ 2 failed · Build ⏭
200
+ ## Spec fidelity Missing / Scope creep / Implemented but wrong — each quoting the spec
201
+ ## 🔴 Blocking `path/file.ts:24` — defect — standard violated — smallest fix
202
+ ## 🟠 Major
203
+ ## 🟡 Minor
204
+ ## 🔍 Needs validation
205
+ ## Auto-fixes applied
206
+ ## Verdict Approve · Approve with Comments · Request Changes · Reject
207
+ ```
208
+
209
+ It will **not** Approve when any of these hold:
210
+
211
+ - a Blocking finding exists;
212
+ - a **confirmed** security concern exists;
213
+ - a breaking API or schema change ships without versioning and documentation;
214
+ - a critical test is failing;
215
+ - an architecture standard is violated;
216
+ - the diff departs from its spec and nobody called the departure out.
217
+
218
+ When in doubt the verdict is **Request Changes**. A flagged non-issue costs a second
219
+ look, and a missed Blocking costs an incident. **Reject** is reserved for a
220
+ fundamentally wrong approach.
221
+
222
+ ---
223
+
224
+ ## The evidence contract, for security findings
225
+
226
+ See [`evidence-contract.md`](skills/quality-gate/references/evidence-contract.md). The
227
+ expensive failure in review is rarely a missed check. It is a claim that says more than
228
+ was measured: a suspicion written in the same ink as a proven defect. A week later
229
+ nobody can tell them apart, and the real one is buried. Three rules prevent it:
230
+
231
+ 1. **A finding needs a boundary and a result.** Six rows: lower-trust principal ·
232
+ accepted input · intended control · crossed boundary · affected resource · observed
233
+ result. Without them it is a hardening note, not a security finding. Rejecting
234
+ takes one line: name the principal and what they gain, or stop.
235
+ 2. **`needs-validation` is a state, not a weak Blocking.** When the decisive fact sits
236
+ outside the repo (a proxy header, an IAM policy, a provider default), the finding
237
+ names that fact and a safe way to check it. It carries no severity.
238
+ 3. **Severity cannot exceed demonstrated impact.** If the concrete damage cannot be
239
+ stated, the severity is lower than it feels.
240
+
241
+ ## Using the gate with security-audit
242
+
243
+ The gate reads **one** domain file from the security-audit skill when the diff calls for
244
+ it: auth, data isolation, cloud, client-side, resource exhaustion, or supply chain.
245
+ Reading a reference is not running an audit.
246
+
247
+ 🔴 **Do not run the audit's six-phase workflow from inside the gate.** Its unit of cost
248
+ is an *agent invocation*. Even its `quick` profile runs four reconnaissance calls, a
249
+ hunter wave, a critic, and one or two verifiers per candidate. Schedule a full audit as
250
+ its own activity.
251
+
252
+ ⚠️ Before a full run, know that the audit requires an OS-enforced sandbox (no network,
253
+ empty environment, hard resource limits) before it executes any target code. Most
254
+ machines do not have one, so a run there is **source-only** and every dynamic claim
255
+ comes back `needs-validation`. That is the honest result, and it is why the evidence
256
+ contract has to be in place *before* the audit rather than after.
257
+
258
+ ---
259
+
260
+ ## Layout
261
+
262
+ ```
263
+ skills/quality-gate/
264
+ SKILL.md the six steps
265
+ references/
266
+ evidence-contract.md what makes a security claim count
267
+ gates-and-fixes.md finding and running the real gates; safe-fix policy
268
+ backend-checklist.md
269
+ frontend-checklist.md
270
+ security-checklist.md
271
+ go-live-checklist.md release reviews only
272
+ templates/
273
+ QUALITY-GATE.md optional per-project config
274
+ bin/install.js npm installer
275
+ install.sh shell installer
276
+ ```
277
+
278
+ ## Provenance
279
+
280
+ The gate grew out of a production review process and was rewritten here to be
281
+ project-neutral: no client names, no incident details, no internal hosts. What survives
282
+ is the method and the traps, which are general.
283
+
284
+ The evidence contract's three rules are adapted from Cloudflare's `security-audit`
285
+ skill (MIT). That skill is fetched from upstream at install time rather than vendored,
286
+ so it stays current and its licence and attribution travel with its own files.
287
+
288
+ ## Licence
289
+
290
+ MIT. See [`LICENSE`](LICENSE).
291
+
292
+ `security-audit` is © Cloudflare, MIT, and is not redistributed here. Both installers
293
+ clone it from upstream.
package/bin/install.js ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+ // Install the quality-gate skill, and Cloudflare's security-audit skill beside it.
3
+ // Same behaviour as install.sh, for machines that have Node.
4
+ //
5
+ // npx agent-quality-skills # both, into ~/.claude/skills
6
+ // npx agent-quality-skills --gate-only # just the gate, no network needed
7
+ // npx agent-quality-skills --project # into ./.claude/skills
8
+ // npx agent-quality-skills --dir <path> # somewhere explicit
9
+ //
10
+ // Idempotent: re-running updates in place. Nothing outside the chosen skills
11
+ // directory is written.
12
+ 'use strict';
13
+ const fs = require('node:fs');
14
+ const os = require('node:os');
15
+ const path = require('node:path');
16
+ const { spawnSync } = require('node:child_process');
17
+
18
+ const SKILLS_SRC = path.join(__dirname, '..', 'skills');
19
+ const AUDIT_REPO = 'https://github.com/cloudflare/security-audit-skill';
20
+ const AUDIT_SKILL_PATH = path.join('skills', 'security-audit');
21
+
22
+ function usage() {
23
+ console.log(`usage: npx agent-quality-skills [--gate-only] [--project | --dir <path>]
24
+
25
+ (default) quality-gate + security-audit into ~/.claude/skills (honours CLAUDE_CONFIG_DIR)
26
+ --gate-only skip the security-audit fetch (no network or git needed)
27
+ --project install into ./.claude/skills
28
+ --dir <path> install into <path>`);
29
+ }
30
+
31
+ let dest = null;
32
+ let gateOnly = false;
33
+ const args = process.argv.slice(2);
34
+ for (let i = 0; i < args.length; i++) {
35
+ const a = args[i];
36
+ if (a === '--gate-only') gateOnly = true;
37
+ else if (a === '--project') dest = path.join(process.cwd(), '.claude', 'skills');
38
+ else if (a === '--dir') {
39
+ if (!args[i + 1]) { console.error('error: --dir needs a path'); process.exit(2); }
40
+ dest = path.resolve(args[++i]);
41
+ } else if (a === '-h' || a === '--help') { usage(); process.exit(0); }
42
+ else { console.error(`unknown option: ${a}`); usage(); process.exit(2); }
43
+ }
44
+ if (!dest) {
45
+ const base = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
46
+ dest = path.join(base, 'skills');
47
+ }
48
+
49
+ function replaceDir(from, to) {
50
+ fs.rmSync(to, { recursive: true, force: true });
51
+ fs.cpSync(from, to, { recursive: true });
52
+ }
53
+
54
+ fs.mkdirSync(dest, { recursive: true });
55
+
56
+ // ── 1. the quality gate, from this package ──────────────────────────────────
57
+ replaceDir(path.join(SKILLS_SRC, 'quality-gate'), path.join(dest, 'quality-gate'));
58
+ console.log('→ quality-gate');
59
+
60
+ // ── 2. Cloudflare's security-audit skill, fetched from upstream ─────────────
61
+ // Fetched rather than vendored, so it stays current and its MIT licence and
62
+ // attribution travel with its own files. Announced only after it lands.
63
+ if (!gateOnly) {
64
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'aqs-'));
65
+ try {
66
+ const clone = spawnSync('git', ['clone', '--depth', '1', '--quiet', AUDIT_REPO, path.join(tmp, 'audit')], { stdio: 'ignore' });
67
+ if (clone.error) {
68
+ console.log('! git not found — skipped security-audit. Install git, or use --gate-only.');
69
+ } else if (clone.status !== 0) {
70
+ console.log(`! could not reach ${AUDIT_REPO} — skipped.`);
71
+ console.log(' The gate works without it; its security axis just loses the domain references.');
72
+ } else {
73
+ const src = path.join(tmp, 'audit', AUDIT_SKILL_PATH);
74
+ if (fs.existsSync(src)) {
75
+ replaceDir(src, path.join(dest, 'security-audit'));
76
+ const lic = path.join(tmp, 'audit', 'LICENSE');
77
+ if (fs.existsSync(lic)) fs.copyFileSync(lic, path.join(dest, 'security-audit', 'LICENSE'));
78
+ console.log(`→ security-audit (${AUDIT_REPO}, MIT)`);
79
+ } else {
80
+ console.log(`! upstream layout changed — '${AUDIT_SKILL_PATH}' not found. Skipped.`);
81
+ }
82
+ }
83
+ } finally {
84
+ fs.rmSync(tmp, { recursive: true, force: true });
85
+ }
86
+ }
87
+
88
+ console.log(`\ninstalled into: ${dest}`);
89
+ console.log('\nNext (optional): put the per-project config template in your repo root:');
90
+ console.log(' curl -fsSL https://raw.githubusercontent.com/captainkie/agent-quality-skills/main/templates/QUALITY-GATE.md -o QUALITY-GATE.md');
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "agent-quality-skills",
3
+ "version": "1.0.0",
4
+ "description": "Pre-ship quality gate skill for coding agents, with an evidence contract for security findings — installs alongside Cloudflare's security-audit skill",
5
+ "bin": {
6
+ "agent-quality-skills": "bin/install.js"
7
+ },
8
+ "files": [
9
+ "bin",
10
+ "skills",
11
+ "templates"
12
+ ],
13
+ "keywords": ["agent-skills", "claude-code", "skills", "code-review", "quality-gate", "security-review", "ai-agent"],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/captainkie/agent-quality-skills.git"
17
+ },
18
+ "homepage": "https://github.com/captainkie/agent-quality-skills#readme",
19
+ "bugs": "https://github.com/captainkie/agent-quality-skills/issues",
20
+ "author": "Narenrit Hadsadintorn",
21
+ "license": "MIT",
22
+ "engines": {
23
+ "node": ">=18.17"
24
+ }
25
+ }