@harness-engineering/cli 3.0.1 → 4.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/dist/agents/personas/harness-pm.yaml +33 -0
- package/dist/agents/skills/claude-code/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/claude-code/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +59 -26
- package/dist/agents/skills/claude-code/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/claude-code/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/claude-code/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/claude-code/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +40 -43
- package/dist/agents/skills/claude-code/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/claude-code/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/codex/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/codex/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/codex/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/codex/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/codex/harness-execution/SKILL.md +59 -26
- package/dist/agents/skills/codex/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/codex/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/codex/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/codex/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/codex/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/codex/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +40 -43
- package/dist/agents/skills/codex/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/codex/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/cursor/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/cursor/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/cursor/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/cursor/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/cursor/harness-execution/SKILL.md +59 -26
- package/dist/agents/skills/cursor/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/cursor/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/cursor/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/cursor/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/cursor/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/cursor/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +40 -43
- package/dist/agents/skills/cursor/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/cursor/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/gemini-cli/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/gemini-cli/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +59 -26
- package/dist/agents/skills/gemini-cli/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/gemini-cli/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/gemini-cli/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/gemini-cli/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +40 -43
- package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/gemini-cli/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/tests/interaction-channel.test.ts +64 -0
- package/dist/{agents-md-XOJE5ETA.js → agents-md-7OSNWU52.js} +2 -2
- package/dist/{architecture-JEZPJ725.js → architecture-2XYGJGT3.js} +3 -3
- package/dist/{assess-project-RHXOQNMM.js → assess-project-3KPP2D6M.js} +1 -1
- package/dist/bin/harness-mcp.js +16 -15
- package/dist/bin/harness.js +27 -25
- package/dist/{check-phase-gate-GNDOMS35.js → check-phase-gate-46U5AAXE.js} +4 -3
- package/dist/{chunk-MGUPSE6D.js → chunk-363V6GPR.js} +5 -5
- package/dist/{chunk-HEIMJJI4.js → chunk-6NCREWWM.js} +2 -2
- package/dist/{chunk-XFU6SB2Q.js → chunk-6YXCZV33.js} +2171 -924
- package/dist/{chunk-HWTUUQOW.js → chunk-AK67S3O4.js} +3 -3
- package/dist/{chunk-BYVT5LVO.js → chunk-BV45354Q.js} +3 -3
- package/dist/{chunk-WWEVS7RO.js → chunk-ERILXQBP.js} +1181 -486
- package/dist/{chunk-UX3PQKVZ.js → chunk-FZ4Q73HA.js} +1 -1
- package/dist/{chunk-Z4AWEIBY.js → chunk-GXCPDAS5.js} +3 -3
- package/dist/{chunk-XX4OLNWQ.js → chunk-HMW3C5DP.js} +2 -2
- package/dist/{chunk-PC2R5RUJ.js → chunk-HXMAIVV2.js} +1 -1
- package/dist/{chunk-QBC7DI4Q.js → chunk-IYWT3JJW.js} +1 -1
- package/dist/{chunk-N24HCQA4.js → chunk-KLPX55TI.js} +3015 -1138
- package/dist/{chunk-527G27VI.js → chunk-MSBJ445U.js} +4 -4
- package/dist/{chunk-NWLGL3IR.js → chunk-MYVTYFQD.js} +2 -2
- package/dist/{chunk-KAJOS3BA.js → chunk-PHX45JYN.js} +5 -9
- package/dist/{chunk-6WQCLCBO.js → chunk-S2RQPPL6.js} +1 -1
- package/dist/chunk-SPE7P4GL.js +61 -0
- package/dist/{chunk-YQSYCBAH.js → chunk-TTWNGOBT.js} +6 -6
- package/dist/{chunk-6B6UN6SG.js → chunk-UTJJJDNN.js} +11 -1
- package/dist/{chunk-WWACIIBA.js → chunk-V3ZQUCRH.js} +1 -1
- package/dist/{chunk-GSP2XIVS.js → chunk-VTU3QOJT.js} +48 -4
- package/dist/{chunk-3ISHDWO7.js → chunk-VTUINXWR.js} +1 -1
- package/dist/{chunk-27AJKSQY.js → chunk-WBVCN35T.js} +1 -1
- package/dist/{chunk-ONCPJGHY.js → chunk-WL3O2PKJ.js} +6 -6
- package/dist/{chunk-GGKRA7A7.js → chunk-XFHZ7GCI.js} +1 -1
- package/dist/chunk-Y6SUQC32.js +9 -0
- package/dist/{chunk-DE5U6KOL.js → chunk-ZEYAOYJL.js} +1 -1
- package/dist/{ci-workflow-ORZ4F45F.js → ci-workflow-XJN4UO3Q.js} +2 -2
- package/dist/{dist-LHINSVK4.js → dist-IPVFYGY2.js} +85 -15
- package/dist/{docs-AU3DXFFO.js → docs-RSFZTNPG.js} +3 -3
- package/dist/{engine-6GPWOYQH.js → engine-DJIHY4JT.js} +2 -2
- package/dist/{entropy-VLKDRMRT.js → entropy-EAEKJKRM.js} +2 -2
- package/dist/{feedback-YXYY44ZC.js → feedback-JT5X3DBC.js} +1 -1
- package/dist/{generate-agent-definitions-XIHQPKG3.js → generate-agent-definitions-CC6KED3E.js} +4 -4
- package/dist/hooks/adoption-tracker.js +6 -5
- package/dist/hooks/format-check.js +202 -0
- package/dist/hooks/protect-config.js +15 -5
- package/dist/hooks/quality-warner.js +32 -0
- package/dist/hooks/strict-quality-gate.js +48 -0
- package/dist/{index-builder-3AOQ3ZII.js → index-builder-52IJJHJC.js} +2 -2
- package/dist/index.d.ts +8 -8
- package/dist/index.js +27 -25
- package/dist/{loader-YAN56MT3.js → loader-UWNVTYBY.js} +2 -2
- package/dist/{mcp-RK3SFVYB.js → mcp-TCLNK7HG.js} +18 -17
- package/dist/{performance-64DPTLLQ.js → performance-R6O3N3UB.js} +3 -3
- package/dist/{review-pipeline-NENG6LW7.js → review-pipeline-MOOWXWSQ.js} +2 -2
- package/dist/{runtime-FFIIRT2T.js → runtime-RIWQUKBQ.js} +2 -2
- package/dist/{security-3PIBN35B.js → security-U76C54W6.js} +1 -1
- package/dist/{skill-executor-MOCUIAYS.js → skill-executor-BGUCAVBU.js} +2 -2
- package/dist/state-events-F44CUUZG.js +25 -0
- package/dist/{validate-7IAF2ES3.js → validate-IUAV7MOU.js} +3 -3
- package/dist/{validate-cross-check-QPSAOZKD.js → validate-cross-check-M2ZM6RFY.js} +2 -2
- package/package.json +7 -7
- package/dist/hooks/quality-gate.js +0 -131
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// format-check.js — shared detection core for the format/lint hooks.
|
|
2
|
+
//
|
|
3
|
+
// Single source of truth for formatter detection and execution, imported by
|
|
4
|
+
// both `quality-warner.js` (warn-only) and `strict-quality-gate.js` (blocking).
|
|
5
|
+
// Takes NO opinion on exit codes — it returns a structured result and lets each
|
|
6
|
+
// entrypoint decide what to do with it.
|
|
7
|
+
//
|
|
8
|
+
// Result shape:
|
|
9
|
+
// { status: 'clean' | 'violations' | 'infra-error', name, output, message }
|
|
10
|
+
//
|
|
11
|
+
// Disambiguation contract (load-bearing): `violations` (the formatter spawned
|
|
12
|
+
// and reported real format/lint problems) MUST be distinguishable from
|
|
13
|
+
// `infra-error` (the tool is absent, timed out, or could not run). The strict
|
|
14
|
+
// gate blocks only on `violations`; everything ambiguous defaults to
|
|
15
|
+
// `infra-error` so the gate fails open rather than walling off every edit.
|
|
16
|
+
|
|
17
|
+
import { accessSync, readFileSync } from 'node:fs';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
import { execFileSync } from 'node:child_process';
|
|
20
|
+
|
|
21
|
+
// Detection order: first match wins
|
|
22
|
+
const DETECTORS = [
|
|
23
|
+
{
|
|
24
|
+
configs: ['biome.json', 'biome.jsonc'],
|
|
25
|
+
cmd: 'npx',
|
|
26
|
+
args: ['biome', 'check'],
|
|
27
|
+
name: 'Biome',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
configs: [
|
|
31
|
+
'.prettierrc',
|
|
32
|
+
'.prettierrc.json',
|
|
33
|
+
'.prettierrc.yml',
|
|
34
|
+
'.prettierrc.yaml',
|
|
35
|
+
'.prettierrc.js',
|
|
36
|
+
'.prettierrc.cjs',
|
|
37
|
+
'.prettierrc.mjs',
|
|
38
|
+
'prettier.config.js',
|
|
39
|
+
'prettier.config.cjs',
|
|
40
|
+
'prettier.config.mjs',
|
|
41
|
+
],
|
|
42
|
+
cmd: 'npx',
|
|
43
|
+
args: ['prettier', '--check'],
|
|
44
|
+
name: 'Prettier',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
configs: ['.ruff.toml', 'ruff.toml'],
|
|
48
|
+
cmd: 'ruff',
|
|
49
|
+
args: ['check'],
|
|
50
|
+
name: 'Ruff',
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
export function detectFormatter(cwd) {
|
|
55
|
+
for (const detector of DETECTORS) {
|
|
56
|
+
for (const config of detector.configs) {
|
|
57
|
+
try {
|
|
58
|
+
accessSync(join(cwd, config));
|
|
59
|
+
return detector;
|
|
60
|
+
} catch {
|
|
61
|
+
// Config not found, try next
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Concatenate whatever a failed execFileSync left on stdout/stderr. */
|
|
69
|
+
function errorOutput(err) {
|
|
70
|
+
return `${err?.stdout ?? ''}${err?.stderr ?? ''}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Classify a non-zero formatter exit as a real `violations` result or an
|
|
75
|
+
* `infra-error`. The detector's exit code alone is ambiguous (linters exit
|
|
76
|
+
* non-zero both for genuine violations and for usage/spawn failures), so we
|
|
77
|
+
* default to `infra-error` (fail open) unless we can positively identify
|
|
78
|
+
* parseable violation output.
|
|
79
|
+
*/
|
|
80
|
+
function classifyError(err) {
|
|
81
|
+
// The command binary itself is missing / not spawnable.
|
|
82
|
+
if (err?.code === 'ENOENT') return 'infra-error';
|
|
83
|
+
// Killed by a signal — almost always our own timeout.
|
|
84
|
+
if (err?.signal) return 'infra-error';
|
|
85
|
+
|
|
86
|
+
const output = errorOutput(err);
|
|
87
|
+
|
|
88
|
+
// npx/npm could not locate or run the underlying tool, or the tool was
|
|
89
|
+
// invoked without a target it requires (e.g. `prettier --check` with no
|
|
90
|
+
// file). These are usage/infra failures, NOT format violations.
|
|
91
|
+
if (
|
|
92
|
+
/could not determine executable|npm error|command not found|not found|ENOENT|expected at least one|no files matching|usage:/i.test(
|
|
93
|
+
output
|
|
94
|
+
)
|
|
95
|
+
) {
|
|
96
|
+
return 'infra-error';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Spawned, exited non-zero, and produced parseable output → real violations.
|
|
100
|
+
if (typeof err?.status === 'number' && output.trim()) return 'violations';
|
|
101
|
+
|
|
102
|
+
// Non-zero but nothing to parse — treat as infra and fail open.
|
|
103
|
+
return 'infra-error';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Run the project's formatter/linter for the edited file and classify the
|
|
108
|
+
* outcome. Performs detection only — never calls process.exit.
|
|
109
|
+
*
|
|
110
|
+
* @param {{ tool_input?: { file_path?: string } }} input Parsed hook stdin.
|
|
111
|
+
* @param {string} cwd Project root.
|
|
112
|
+
* @returns {{ status: 'clean'|'violations'|'infra-error', name: string|null, output: string, message: string }}
|
|
113
|
+
*/
|
|
114
|
+
export function runFormatCheck(input, cwd) {
|
|
115
|
+
const filePath = input?.tool_input?.file_path ?? '';
|
|
116
|
+
|
|
117
|
+
// Special case: .go files use `gofmt -l`, which lists files needing formatting.
|
|
118
|
+
if (typeof filePath === 'string' && filePath.endsWith('.go')) {
|
|
119
|
+
try {
|
|
120
|
+
const result = execFileSync('gofmt', ['-l', filePath], {
|
|
121
|
+
encoding: 'utf-8',
|
|
122
|
+
cwd,
|
|
123
|
+
timeout: 10000,
|
|
124
|
+
});
|
|
125
|
+
if (result.trim()) {
|
|
126
|
+
return {
|
|
127
|
+
status: 'violations',
|
|
128
|
+
name: 'gofmt',
|
|
129
|
+
output: result.trim(),
|
|
130
|
+
message: `gofmt found formatting issues in: ${result.trim()}`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return { status: 'clean', name: 'gofmt', output: '', message: 'gofmt check passed' };
|
|
134
|
+
} catch (err) {
|
|
135
|
+
// gofmt not available or failed to run — fail open.
|
|
136
|
+
return {
|
|
137
|
+
status: 'infra-error',
|
|
138
|
+
name: 'gofmt',
|
|
139
|
+
output: errorOutput(err),
|
|
140
|
+
message: 'gofmt check failed (tool may not be installed)',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const detector = detectFormatter(cwd);
|
|
146
|
+
if (!detector) {
|
|
147
|
+
// No formatter detected — nothing to check.
|
|
148
|
+
return { status: 'clean', name: null, output: '', message: 'No formatter detected' };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
execFileSync(detector.cmd, detector.args, {
|
|
153
|
+
encoding: 'utf-8',
|
|
154
|
+
cwd,
|
|
155
|
+
timeout: 30000,
|
|
156
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
157
|
+
});
|
|
158
|
+
return {
|
|
159
|
+
status: 'clean',
|
|
160
|
+
name: detector.name,
|
|
161
|
+
output: '',
|
|
162
|
+
message: `${detector.name} check passed`,
|
|
163
|
+
};
|
|
164
|
+
} catch (err) {
|
|
165
|
+
const output = errorOutput(err).slice(0, 500);
|
|
166
|
+
if (classifyError(err) === 'violations') {
|
|
167
|
+
return {
|
|
168
|
+
status: 'violations',
|
|
169
|
+
name: detector.name,
|
|
170
|
+
output,
|
|
171
|
+
message: `${detector.name} check reported issues:\n${output}`,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
status: 'infra-error',
|
|
176
|
+
name: detector.name,
|
|
177
|
+
output,
|
|
178
|
+
message: `${detector.name} check could not run (treated as non-blocking):\n${output}`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Read and parse hook stdin (the JSON event payload). Returns null when stdin
|
|
185
|
+
* is empty or malformed so callers can fail open.
|
|
186
|
+
*
|
|
187
|
+
* @param {number} fd File descriptor to read (0 = stdin).
|
|
188
|
+
*/
|
|
189
|
+
export function readHookInput(fd) {
|
|
190
|
+
let raw;
|
|
191
|
+
try {
|
|
192
|
+
raw = readFileSync(fd, 'utf-8');
|
|
193
|
+
} catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
if (!raw.trim()) return null;
|
|
197
|
+
try {
|
|
198
|
+
return JSON.parse(raw);
|
|
199
|
+
} catch {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// protect-config.js — PreToolUse:Write/Edit hook
|
|
3
3
|
// Blocks modifications to linter/formatter config files.
|
|
4
|
-
// Fail
|
|
4
|
+
// Fail policy is split by failure mode:
|
|
5
|
+
// - Absent/partial stdin (unreadable / empty / unparseable JSON): fail-OPEN (exit 0),
|
|
6
|
+
// logged to stderr. These are the environmental/partial-stdin glitches issue #619
|
|
7
|
+
// documents; blocking them would self-DoS legitimate writes.
|
|
8
|
+
// - Well-formed request whose edit target is unresolvable (missing/non-string file_path,
|
|
9
|
+
// or an unexpected processing error): fail-CLOSED (exit 2) — refuse rather than allow a
|
|
10
|
+
// potentially unprotected config edit.
|
|
5
11
|
// Exit codes: 0 = allow, 2 = block
|
|
6
12
|
|
|
7
13
|
import { readFileSync } from 'node:fs';
|
|
@@ -54,8 +60,10 @@ function main() {
|
|
|
54
60
|
const filePath = input?.tool_input?.file_path;
|
|
55
61
|
|
|
56
62
|
if (typeof filePath !== 'string' || !filePath) {
|
|
57
|
-
process.stderr.write(
|
|
58
|
-
|
|
63
|
+
process.stderr.write(
|
|
64
|
+
'BLOCKED: protect-config could not verify the edit target (missing or unresolvable file_path) — refusing to allow a potentially unprotected config edit.\n'
|
|
65
|
+
);
|
|
66
|
+
process.exit(2);
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
if (isProtected(filePath)) {
|
|
@@ -67,8 +75,10 @@ function main() {
|
|
|
67
75
|
|
|
68
76
|
process.exit(0);
|
|
69
77
|
} catch {
|
|
70
|
-
process.stderr.write(
|
|
71
|
-
|
|
78
|
+
process.stderr.write(
|
|
79
|
+
'BLOCKED: protect-config hit an unexpected error verifying the edit target — blocking (fail-closed).\n'
|
|
80
|
+
);
|
|
81
|
+
process.exit(2);
|
|
72
82
|
}
|
|
73
83
|
}
|
|
74
84
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// quality-warner.js — PostToolUse:Edit/Write hook (standard profile)
|
|
3
|
+
// Runs the project formatter/linter after edits and WARNS on violations.
|
|
4
|
+
// Never blocks (always exits 0). Warnings go to stderr.
|
|
5
|
+
// Exit codes: 0 = allow (always)
|
|
6
|
+
//
|
|
7
|
+
// This is the warn-tier sibling of strict-quality-gate.js. Both obtain their
|
|
8
|
+
// detection from format-check.js; only the exit-code policy differs.
|
|
9
|
+
|
|
10
|
+
import process from 'node:process';
|
|
11
|
+
import { runFormatCheck, readHookInput } from './format-check.js';
|
|
12
|
+
|
|
13
|
+
function main() {
|
|
14
|
+
const input = readHookInput(0);
|
|
15
|
+
if (!input) {
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const result = runFormatCheck(input, process.cwd());
|
|
21
|
+
// Warn-only: surface every outcome on stderr, never block.
|
|
22
|
+
if (result.status !== 'clean' || result.name) {
|
|
23
|
+
process.stderr.write(`[quality-warner] ${result.message}\n`);
|
|
24
|
+
}
|
|
25
|
+
process.exit(0);
|
|
26
|
+
} catch {
|
|
27
|
+
// Unexpected error — fail open.
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
main();
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// strict-quality-gate.js — PostToolUse:Edit/Write hook (strict profile only)
|
|
3
|
+
// Runs the project formatter/linter after edits and BLOCKS on real violations.
|
|
4
|
+
// Exit codes:
|
|
5
|
+
// 0 = allow (clean, or infra-error → fail open)
|
|
6
|
+
// 2 = block (genuine format/lint violations; stderr is fed back to Claude)
|
|
7
|
+
//
|
|
8
|
+
// A PostToolUse hook that exits 2 surfaces its stderr to Claude as a must-fix:
|
|
9
|
+
// the edit already landed, so the model is told to correct the violation.
|
|
10
|
+
//
|
|
11
|
+
// Fail-open contract: when the formatter is absent, times out, or its output is
|
|
12
|
+
// unparseable (status 'infra-error'), this hook writes a loud warning and exits
|
|
13
|
+
// 0 — a missing formatter must not wall off every edit. See format-check.js.
|
|
14
|
+
|
|
15
|
+
import process from 'node:process';
|
|
16
|
+
import { runFormatCheck, readHookInput } from './format-check.js';
|
|
17
|
+
|
|
18
|
+
function main() {
|
|
19
|
+
const input = readHookInput(0);
|
|
20
|
+
if (!input) {
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const result = runFormatCheck(input, process.cwd());
|
|
26
|
+
|
|
27
|
+
if (result.status === 'violations') {
|
|
28
|
+
process.stderr.write(
|
|
29
|
+
`[strict-quality-gate] BLOCKED — ${result.message}\n` +
|
|
30
|
+
`Fix the formatting/lint violations above before continuing.\n`
|
|
31
|
+
);
|
|
32
|
+
process.exit(2);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (result.status === 'infra-error') {
|
|
36
|
+
process.stderr.write(`[strict-quality-gate] WARNING (failing open) — ${result.message}\n`);
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// clean
|
|
41
|
+
process.exit(0);
|
|
42
|
+
} catch {
|
|
43
|
+
// Unexpected error — fail open.
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
main();
|
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
buildIndex,
|
|
3
3
|
computeSkillsDirHash,
|
|
4
4
|
loadOrRebuildIndex
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-WBVCN35T.js";
|
|
6
|
+
import "./chunk-UTJJJDNN.js";
|
|
7
7
|
import "./chunk-HIK6OEUF.js";
|
|
8
8
|
import "./chunk-KFQGP6VL.js";
|
|
9
9
|
export {
|
package/dist/index.d.ts
CHANGED
|
@@ -1576,14 +1576,14 @@ declare const HarnessConfigSchema: z.ZodObject<{
|
|
|
1576
1576
|
modules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodEnum<["circular-deps", "layer-violations", "complexity", "coupling", "forbidden-imports", "module-size", "dependency-depth"]>, z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>>>;
|
|
1577
1577
|
}, "strip", z.ZodTypeAny, {
|
|
1578
1578
|
enabled: boolean;
|
|
1579
|
+
thresholds: Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>;
|
|
1580
|
+
modules: Record<string, Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>>;
|
|
1579
1581
|
baselinePath: string;
|
|
1580
|
-
thresholds: Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>;
|
|
1581
|
-
modules: Record<string, Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>>;
|
|
1582
1582
|
}, {
|
|
1583
1583
|
enabled?: boolean | undefined;
|
|
1584
|
+
thresholds?: Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>> | undefined;
|
|
1585
|
+
modules?: Record<string, Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>> | undefined;
|
|
1584
1586
|
baselinePath?: string | undefined;
|
|
1585
|
-
thresholds?: Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>> | undefined;
|
|
1586
|
-
modules?: Record<string, Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>> | undefined;
|
|
1587
1587
|
}>>;
|
|
1588
1588
|
/** Skill loading, suggestion, and tier override settings */
|
|
1589
1589
|
skills: z.ZodOptional<z.ZodObject<{
|
|
@@ -2235,9 +2235,9 @@ declare const HarnessConfigSchema: z.ZodObject<{
|
|
|
2235
2235
|
} | undefined;
|
|
2236
2236
|
architecture?: {
|
|
2237
2237
|
enabled: boolean;
|
|
2238
|
+
thresholds: Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>;
|
|
2239
|
+
modules: Record<string, Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>>;
|
|
2238
2240
|
baselinePath: string;
|
|
2239
|
-
thresholds: Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>;
|
|
2240
|
-
modules: Record<string, Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>>;
|
|
2241
2241
|
} | undefined;
|
|
2242
2242
|
traceability?: {
|
|
2243
2243
|
enabled: boolean;
|
|
@@ -2553,9 +2553,9 @@ declare const HarnessConfigSchema: z.ZodObject<{
|
|
|
2553
2553
|
} | undefined;
|
|
2554
2554
|
architecture?: {
|
|
2555
2555
|
enabled?: boolean | undefined;
|
|
2556
|
+
thresholds?: Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>> | undefined;
|
|
2557
|
+
modules?: Record<string, Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>> | undefined;
|
|
2556
2558
|
baselinePath?: string | undefined;
|
|
2557
|
-
thresholds?: Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>> | undefined;
|
|
2558
|
-
modules?: Record<string, Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>> | undefined;
|
|
2559
2559
|
} | undefined;
|
|
2560
2560
|
traceability?: {
|
|
2561
2561
|
enabled?: boolean | undefined;
|
package/dist/index.js
CHANGED
|
@@ -12,19 +12,20 @@ import {
|
|
|
12
12
|
runSnapshotCapture,
|
|
13
13
|
runUninstall,
|
|
14
14
|
runUninstallConstraints
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-6YXCZV33.js";
|
|
16
16
|
import {
|
|
17
17
|
generateRuntime
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-S2RQPPL6.js";
|
|
19
19
|
import {
|
|
20
20
|
generateAgentsMd
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-IYWT3JJW.js";
|
|
22
22
|
import {
|
|
23
23
|
generateCIWorkflow
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-VTU3QOJT.js";
|
|
25
|
+
import "./chunk-SPE7P4GL.js";
|
|
25
26
|
import {
|
|
26
27
|
runCrossCheck
|
|
27
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-VTUINXWR.js";
|
|
28
29
|
import {
|
|
29
30
|
AGENT_DESCRIPTIONS,
|
|
30
31
|
DEFAULT_TOOLS,
|
|
@@ -33,14 +34,14 @@ import {
|
|
|
33
34
|
generateAgentDefinitions,
|
|
34
35
|
renderClaudeCodeAgent,
|
|
35
36
|
renderGeminiAgent
|
|
36
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-MYVTYFQD.js";
|
|
37
38
|
import "./chunk-KET4QQZB.js";
|
|
38
39
|
import {
|
|
39
40
|
runScan
|
|
40
41
|
} from "./chunk-2N4OENGE.js";
|
|
41
42
|
import {
|
|
42
43
|
TemplateEngine
|
|
43
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-FZ4Q73HA.js";
|
|
44
45
|
import "./chunk-CQ553GZO.js";
|
|
45
46
|
import {
|
|
46
47
|
generateSkillFiles
|
|
@@ -48,14 +49,14 @@ import {
|
|
|
48
49
|
import {
|
|
49
50
|
listPersonas,
|
|
50
51
|
loadPersona
|
|
51
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-HXMAIVV2.js";
|
|
52
53
|
import {
|
|
53
54
|
detectTrigger,
|
|
54
55
|
runPersona
|
|
55
56
|
} from "./chunk-GISMXMVL.js";
|
|
56
57
|
import {
|
|
57
58
|
executeSkill
|
|
58
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-V3ZQUCRH.js";
|
|
59
60
|
import {
|
|
60
61
|
ALLOWED_PERSONA_COMMANDS
|
|
61
62
|
} from "./chunk-TEFCFC4H.js";
|
|
@@ -63,36 +64,37 @@ import {
|
|
|
63
64
|
OutputFormatter,
|
|
64
65
|
OutputMode,
|
|
65
66
|
runCheckPhaseGate
|
|
66
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-PHX45JYN.js";
|
|
67
68
|
import {
|
|
68
69
|
createHarnessServer,
|
|
69
70
|
generateSlashCommands,
|
|
70
71
|
getToolDefinitions,
|
|
71
72
|
startServer
|
|
72
|
-
} from "./chunk-
|
|
73
|
-
import "./chunk-
|
|
74
|
-
import "./chunk-
|
|
75
|
-
import "./chunk-
|
|
76
|
-
import "./chunk-
|
|
77
|
-
import "./chunk-
|
|
73
|
+
} from "./chunk-ERILXQBP.js";
|
|
74
|
+
import "./chunk-BV45354Q.js";
|
|
75
|
+
import "./chunk-6NCREWWM.js";
|
|
76
|
+
import "./chunk-HMW3C5DP.js";
|
|
77
|
+
import "./chunk-TTWNGOBT.js";
|
|
78
|
+
import "./chunk-363V6GPR.js";
|
|
79
|
+
import "./chunk-GXCPDAS5.js";
|
|
80
|
+
import "./chunk-WL3O2PKJ.js";
|
|
78
81
|
import "./chunk-IOW3MW2K.js";
|
|
79
|
-
import "./chunk-BYVT5LVO.js";
|
|
80
82
|
import "./chunk-3ISINLYT.js";
|
|
81
83
|
import "./chunk-CLI4K2CH.js";
|
|
82
|
-
import "./chunk-
|
|
83
|
-
import "./chunk-
|
|
84
|
-
import "./chunk-DE5U6KOL.js";
|
|
85
|
-
import "./chunk-MGUPSE6D.js";
|
|
84
|
+
import "./chunk-AK67S3O4.js";
|
|
85
|
+
import "./chunk-MSBJ445U.js";
|
|
86
86
|
import "./chunk-RC3OI5NK.js";
|
|
87
|
+
import "./chunk-ZEYAOYJL.js";
|
|
87
88
|
import "./chunk-W6Y7ZW3Y.js";
|
|
88
|
-
import "./chunk-
|
|
89
|
-
import "./chunk-
|
|
89
|
+
import "./chunk-WBVCN35T.js";
|
|
90
|
+
import "./chunk-UTJJJDNN.js";
|
|
90
91
|
import "./chunk-HIK6OEUF.js";
|
|
92
|
+
import "./chunk-Y6SUQC32.js";
|
|
91
93
|
import {
|
|
92
94
|
findConfigFile,
|
|
93
95
|
loadConfig,
|
|
94
96
|
resolveConfig
|
|
95
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-XFHZ7GCI.js";
|
|
96
98
|
import "./chunk-ZCZD7FHU.js";
|
|
97
99
|
import {
|
|
98
100
|
logger
|
|
@@ -102,7 +104,7 @@ import {
|
|
|
102
104
|
ExitCode,
|
|
103
105
|
handleError
|
|
104
106
|
} from "./chunk-3WGJMBKH.js";
|
|
105
|
-
import "./chunk-
|
|
107
|
+
import "./chunk-KLPX55TI.js";
|
|
106
108
|
import "./chunk-BM3PWGXQ.js";
|
|
107
109
|
import "./chunk-N55WOGN3.js";
|
|
108
110
|
import "./chunk-BDGTZRZ6.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
listPersonas,
|
|
3
3
|
loadPersona
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-HXMAIVV2.js";
|
|
5
|
+
import "./chunk-KLPX55TI.js";
|
|
6
6
|
import "./chunk-N55WOGN3.js";
|
|
7
7
|
import "./chunk-BDGTZRZ6.js";
|
|
8
8
|
import "./chunk-PP6ZRL5T.js";
|
|
@@ -2,34 +2,35 @@ import {
|
|
|
2
2
|
createHarnessServer,
|
|
3
3
|
getToolDefinitions,
|
|
4
4
|
startServer
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-ERILXQBP.js";
|
|
6
|
+
import "./chunk-BV45354Q.js";
|
|
7
|
+
import "./chunk-6NCREWWM.js";
|
|
8
|
+
import "./chunk-HMW3C5DP.js";
|
|
9
|
+
import "./chunk-TTWNGOBT.js";
|
|
10
|
+
import "./chunk-363V6GPR.js";
|
|
11
|
+
import "./chunk-GXCPDAS5.js";
|
|
12
|
+
import "./chunk-WL3O2PKJ.js";
|
|
11
13
|
import "./chunk-IOW3MW2K.js";
|
|
12
|
-
import "./chunk-BYVT5LVO.js";
|
|
13
14
|
import "./chunk-3ISINLYT.js";
|
|
14
15
|
import "./chunk-CLI4K2CH.js";
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import {
|
|
18
|
-
resolveProjectConfig
|
|
19
|
-
} from "./chunk-DE5U6KOL.js";
|
|
20
|
-
import "./chunk-MGUPSE6D.js";
|
|
16
|
+
import "./chunk-AK67S3O4.js";
|
|
17
|
+
import "./chunk-MSBJ445U.js";
|
|
21
18
|
import {
|
|
22
19
|
resultToMcpResponse
|
|
23
20
|
} from "./chunk-RC3OI5NK.js";
|
|
21
|
+
import {
|
|
22
|
+
resolveProjectConfig
|
|
23
|
+
} from "./chunk-ZEYAOYJL.js";
|
|
24
24
|
import "./chunk-W6Y7ZW3Y.js";
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-
|
|
25
|
+
import "./chunk-WBVCN35T.js";
|
|
26
|
+
import "./chunk-UTJJJDNN.js";
|
|
27
27
|
import "./chunk-HIK6OEUF.js";
|
|
28
|
-
import "./chunk-
|
|
28
|
+
import "./chunk-Y6SUQC32.js";
|
|
29
|
+
import "./chunk-XFHZ7GCI.js";
|
|
29
30
|
import "./chunk-ZCZD7FHU.js";
|
|
30
31
|
import "./chunk-EBJQ6N4M.js";
|
|
31
32
|
import "./chunk-3WGJMBKH.js";
|
|
32
|
-
import "./chunk-
|
|
33
|
+
import "./chunk-KLPX55TI.js";
|
|
33
34
|
import "./chunk-N55WOGN3.js";
|
|
34
35
|
import "./chunk-BDGTZRZ6.js";
|
|
35
36
|
import "./chunk-PP6ZRL5T.js";
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
handleGetPerfBaselines,
|
|
8
8
|
handleUpdatePerfBaselines,
|
|
9
9
|
updatePerfBaselinesDefinition
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WL3O2PKJ.js";
|
|
11
11
|
import "./chunk-RC3OI5NK.js";
|
|
12
12
|
import "./chunk-W6Y7ZW3Y.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-XFHZ7GCI.js";
|
|
14
14
|
import "./chunk-ZCZD7FHU.js";
|
|
15
15
|
import "./chunk-3WGJMBKH.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-KLPX55TI.js";
|
|
17
17
|
import "./chunk-N55WOGN3.js";
|
|
18
18
|
import "./chunk-BDGTZRZ6.js";
|
|
19
19
|
import "./chunk-PP6ZRL5T.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleRunCodeReview,
|
|
3
3
|
runCodeReviewDefinition
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HMW3C5DP.js";
|
|
5
5
|
import "./chunk-W6Y7ZW3Y.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-KLPX55TI.js";
|
|
7
7
|
import "./chunk-N55WOGN3.js";
|
|
8
8
|
import "./chunk-BDGTZRZ6.js";
|
|
9
9
|
import "./chunk-PP6ZRL5T.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateRuntime
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-S2RQPPL6.js";
|
|
4
4
|
import "./chunk-KET4QQZB.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-KLPX55TI.js";
|
|
6
6
|
import "./chunk-N55WOGN3.js";
|
|
7
7
|
import "./chunk-BDGTZRZ6.js";
|
|
8
8
|
import "./chunk-PP6ZRL5T.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
emitApprovalRequested,
|
|
3
|
+
emitApprovalResolved,
|
|
4
|
+
emitCoreEvent,
|
|
5
|
+
emitUserInputCaptured,
|
|
6
|
+
isEmptyHarnessState,
|
|
7
|
+
readAuditTimeline,
|
|
8
|
+
readHarnessState
|
|
9
|
+
} from "./chunk-SPE7P4GL.js";
|
|
10
|
+
import "./chunk-KLPX55TI.js";
|
|
11
|
+
import "./chunk-N55WOGN3.js";
|
|
12
|
+
import "./chunk-BDGTZRZ6.js";
|
|
13
|
+
import "./chunk-PP6ZRL5T.js";
|
|
14
|
+
import "./chunk-QCLOIUMX.js";
|
|
15
|
+
import "./chunk-XARGEOJV.js";
|
|
16
|
+
import "./chunk-KFQGP6VL.js";
|
|
17
|
+
export {
|
|
18
|
+
emitApprovalRequested,
|
|
19
|
+
emitApprovalResolved,
|
|
20
|
+
emitCoreEvent,
|
|
21
|
+
emitUserInputCaptured,
|
|
22
|
+
isEmptyHarnessState,
|
|
23
|
+
readAuditTimeline,
|
|
24
|
+
readHarnessState
|
|
25
|
+
};
|