@harness-engineering/cli 1.6.2 → 1.7.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/planner.yaml +27 -0
- package/dist/agents/personas/verifier.yaml +30 -0
- package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +19 -0
- package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +274 -0
- package/dist/agents/skills/claude-code/harness-accessibility/skill.yaml +51 -0
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +111 -72
- package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +4 -2
- package/dist/agents/skills/claude-code/harness-dependency-health/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-design/SKILL.md +265 -0
- package/dist/agents/skills/claude-code/harness-design/skill.yaml +53 -0
- package/dist/agents/skills/claude-code/harness-design-mobile/SKILL.md +336 -0
- package/dist/agents/skills/claude-code/harness-design-mobile/skill.yaml +49 -0
- package/dist/agents/skills/claude-code/harness-design-system/SKILL.md +282 -0
- package/dist/agents/skills/claude-code/harness-design-system/skill.yaml +50 -0
- package/dist/agents/skills/claude-code/harness-design-web/SKILL.md +360 -0
- package/dist/agents/skills/claude-code/harness-design-web/skill.yaml +52 -0
- package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +16 -0
- package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +19 -1
- package/dist/agents/skills/claude-code/harness-knowledge-mapper/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-onboarding/SKILL.md +19 -1
- package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +13 -9
- package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-verify/SKILL.md +26 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +274 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/skill.yaml +51 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +111 -72
- package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +4 -2
- package/dist/agents/skills/gemini-cli/harness-dependency-health/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-design/SKILL.md +265 -0
- package/dist/agents/skills/gemini-cli/harness-design/skill.yaml +53 -0
- package/dist/agents/skills/gemini-cli/harness-design-mobile/SKILL.md +336 -0
- package/dist/agents/skills/gemini-cli/harness-design-mobile/skill.yaml +49 -0
- package/dist/agents/skills/gemini-cli/harness-design-system/SKILL.md +282 -0
- package/dist/agents/skills/gemini-cli/harness-design-system/skill.yaml +50 -0
- package/dist/agents/skills/gemini-cli/harness-design-web/SKILL.md +360 -0
- package/dist/agents/skills/gemini-cli/harness-design-web/skill.yaml +52 -0
- package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +16 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +13 -9
- package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +1 -1
- package/dist/agents/skills/node_modules/.bin/vitest +2 -2
- package/dist/agents/skills/shared/design-knowledge/anti-patterns/color.yaml +106 -0
- package/dist/agents/skills/shared/design-knowledge/anti-patterns/layout.yaml +109 -0
- package/dist/agents/skills/shared/design-knowledge/anti-patterns/motion.yaml +109 -0
- package/dist/agents/skills/shared/design-knowledge/anti-patterns/typography.yaml +112 -0
- package/dist/agents/skills/shared/design-knowledge/industries/creative.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/ecommerce.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/emerging-tech.yaml +83 -0
- package/dist/agents/skills/shared/design-knowledge/industries/fintech.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/healthcare.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/lifestyle.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/saas.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/services.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/palettes/curated.yaml +234 -0
- package/dist/agents/skills/shared/design-knowledge/platform-rules/android.yaml +125 -0
- package/dist/agents/skills/shared/design-knowledge/platform-rules/flutter.yaml +144 -0
- package/dist/agents/skills/shared/design-knowledge/platform-rules/ios.yaml +106 -0
- package/dist/agents/skills/shared/design-knowledge/platform-rules/web.yaml +102 -0
- package/dist/agents/skills/shared/design-knowledge/typography/pairings.yaml +274 -0
- package/dist/bin/harness.js +3 -3
- package/dist/{chunk-UDWGSL3T.js → chunk-4WUGOJQ7.js} +3 -3
- package/dist/{chunk-IUFFBBYV.js → chunk-FFIX3QVG.js} +60 -32
- package/dist/{chunk-USEYPS7F.js → chunk-GA6GN5J2.js} +6 -6
- package/dist/{dist-RBZXXJHG.js → dist-C4J67MPP.js} +1 -1
- package/dist/{dist-4MYPT3OE.js → dist-N4D4QWFV.js} +294 -13
- package/dist/index.d.ts +79 -0
- package/dist/index.js +3 -3
- package/dist/validate-cross-check-WGXQ7K62.js +7 -0
- package/package.json +4 -4
- package/dist/validate-cross-check-CPEPNLOD.js +0 -7
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
description: "Curated font pairings with complete fallback stacks and usage guidance"
|
|
2
|
+
|
|
3
|
+
pairings:
|
|
4
|
+
- name: "Modern Editorial"
|
|
5
|
+
tags: ["editorial", "creative", "premium"]
|
|
6
|
+
display:
|
|
7
|
+
family: "Instrument Serif"
|
|
8
|
+
fallback: "Georgia, 'Times New Roman', serif"
|
|
9
|
+
weights: [400, 700]
|
|
10
|
+
variable: false
|
|
11
|
+
source: "Google Fonts"
|
|
12
|
+
body:
|
|
13
|
+
family: "Geist"
|
|
14
|
+
fallback: "system-ui, -apple-system, sans-serif"
|
|
15
|
+
weights: [400, 500, 600]
|
|
16
|
+
variable: true
|
|
17
|
+
source: "Vercel"
|
|
18
|
+
mono:
|
|
19
|
+
family: "Geist Mono"
|
|
20
|
+
fallback: "'SF Mono', 'Fira Code', 'Cascadia Code', monospace"
|
|
21
|
+
weights: [400, 500]
|
|
22
|
+
source: "Vercel"
|
|
23
|
+
scale:
|
|
24
|
+
base: "1rem"
|
|
25
|
+
ratio: 1.25
|
|
26
|
+
sizes:
|
|
27
|
+
xs: "0.75rem"
|
|
28
|
+
sm: "0.875rem"
|
|
29
|
+
base: "1rem"
|
|
30
|
+
lg: "1.125rem"
|
|
31
|
+
xl: "1.25rem"
|
|
32
|
+
"2xl": "1.5rem"
|
|
33
|
+
"3xl": "1.875rem"
|
|
34
|
+
"4xl": "2.25rem"
|
|
35
|
+
"5xl": "3rem"
|
|
36
|
+
usage: "Best for editorial, blog, and content-heavy sites that want to feel premium and literary."
|
|
37
|
+
|
|
38
|
+
- name: "Clean Tech"
|
|
39
|
+
tags: ["tech", "saas", "dashboard", "modern"]
|
|
40
|
+
display:
|
|
41
|
+
family: "Inter"
|
|
42
|
+
fallback: "system-ui, -apple-system, 'Segoe UI', sans-serif"
|
|
43
|
+
weights: [500, 600, 700]
|
|
44
|
+
variable: true
|
|
45
|
+
source: "Google Fonts"
|
|
46
|
+
body:
|
|
47
|
+
family: "Inter"
|
|
48
|
+
fallback: "system-ui, -apple-system, 'Segoe UI', sans-serif"
|
|
49
|
+
weights: [400, 500, 600]
|
|
50
|
+
variable: true
|
|
51
|
+
source: "Google Fonts"
|
|
52
|
+
mono:
|
|
53
|
+
family: "JetBrains Mono"
|
|
54
|
+
fallback: "'SF Mono', 'Fira Code', 'Cascadia Code', monospace"
|
|
55
|
+
weights: [400, 500]
|
|
56
|
+
source: "Google Fonts"
|
|
57
|
+
scale:
|
|
58
|
+
base: "1rem"
|
|
59
|
+
ratio: 1.2
|
|
60
|
+
sizes:
|
|
61
|
+
xs: "0.75rem"
|
|
62
|
+
sm: "0.875rem"
|
|
63
|
+
base: "1rem"
|
|
64
|
+
lg: "1.125rem"
|
|
65
|
+
xl: "1.25rem"
|
|
66
|
+
"2xl": "1.5rem"
|
|
67
|
+
"3xl": "1.8rem"
|
|
68
|
+
"4xl": "2.16rem"
|
|
69
|
+
"5xl": "2.592rem"
|
|
70
|
+
usage: "Ideal for SaaS dashboards, developer tools, and data-heavy interfaces where clarity and density matter."
|
|
71
|
+
|
|
72
|
+
- name: "Traditional Pro"
|
|
73
|
+
tags: ["professional", "corporate", "legal", "finance"]
|
|
74
|
+
display:
|
|
75
|
+
family: "Playfair Display"
|
|
76
|
+
fallback: "Georgia, 'Times New Roman', 'Palatino Linotype', serif"
|
|
77
|
+
weights: [400, 700, 900]
|
|
78
|
+
variable: true
|
|
79
|
+
source: "Google Fonts"
|
|
80
|
+
body:
|
|
81
|
+
family: "Source Sans 3"
|
|
82
|
+
fallback: "'Segoe UI', 'Helvetica Neue', Arial, sans-serif"
|
|
83
|
+
weights: [400, 600, 700]
|
|
84
|
+
variable: true
|
|
85
|
+
source: "Google Fonts"
|
|
86
|
+
mono:
|
|
87
|
+
family: "Source Code Pro"
|
|
88
|
+
fallback: "'SF Mono', 'Courier New', monospace"
|
|
89
|
+
weights: [400, 500]
|
|
90
|
+
source: "Google Fonts"
|
|
91
|
+
scale:
|
|
92
|
+
base: "1rem"
|
|
93
|
+
ratio: 1.333
|
|
94
|
+
sizes:
|
|
95
|
+
xs: "0.75rem"
|
|
96
|
+
sm: "0.875rem"
|
|
97
|
+
base: "1rem"
|
|
98
|
+
lg: "1.125rem"
|
|
99
|
+
xl: "1.333rem"
|
|
100
|
+
"2xl": "1.777rem"
|
|
101
|
+
"3xl": "2.369rem"
|
|
102
|
+
"4xl": "3.157rem"
|
|
103
|
+
"5xl": "4.209rem"
|
|
104
|
+
usage: "Best for corporate sites, law firms, financial services, and publications that need gravitas and authority."
|
|
105
|
+
|
|
106
|
+
- name: "Friendly Rounded"
|
|
107
|
+
tags: ["friendly", "approachable", "lifestyle", "consumer"]
|
|
108
|
+
display:
|
|
109
|
+
family: "Nunito"
|
|
110
|
+
fallback: "'Varela Round', 'Helvetica Neue', Arial, sans-serif"
|
|
111
|
+
weights: [600, 700, 800]
|
|
112
|
+
variable: true
|
|
113
|
+
source: "Google Fonts"
|
|
114
|
+
body:
|
|
115
|
+
family: "DM Sans"
|
|
116
|
+
fallback: "'Helvetica Neue', Arial, sans-serif"
|
|
117
|
+
weights: [400, 500, 700]
|
|
118
|
+
variable: true
|
|
119
|
+
source: "Google Fonts"
|
|
120
|
+
mono:
|
|
121
|
+
family: "DM Mono"
|
|
122
|
+
fallback: "'SF Mono', 'Fira Code', monospace"
|
|
123
|
+
weights: [400, 500]
|
|
124
|
+
source: "Google Fonts"
|
|
125
|
+
scale:
|
|
126
|
+
base: "1rem"
|
|
127
|
+
ratio: 1.25
|
|
128
|
+
sizes:
|
|
129
|
+
xs: "0.75rem"
|
|
130
|
+
sm: "0.875rem"
|
|
131
|
+
base: "1rem"
|
|
132
|
+
lg: "1.125rem"
|
|
133
|
+
xl: "1.25rem"
|
|
134
|
+
"2xl": "1.5rem"
|
|
135
|
+
"3xl": "1.875rem"
|
|
136
|
+
"4xl": "2.25rem"
|
|
137
|
+
"5xl": "3rem"
|
|
138
|
+
usage: "Perfect for consumer apps, lifestyle brands, and friendly SaaS products that want to feel warm and approachable."
|
|
139
|
+
|
|
140
|
+
- name: "Geometric Minimal"
|
|
141
|
+
tags: ["minimal", "geometric", "startup", "clean"]
|
|
142
|
+
display:
|
|
143
|
+
family: "Space Grotesk"
|
|
144
|
+
fallback: "'Helvetica Neue', Arial, sans-serif"
|
|
145
|
+
weights: [500, 700]
|
|
146
|
+
variable: true
|
|
147
|
+
source: "Google Fonts"
|
|
148
|
+
body:
|
|
149
|
+
family: "Work Sans"
|
|
150
|
+
fallback: "'Helvetica Neue', Arial, sans-serif"
|
|
151
|
+
weights: [400, 500, 600]
|
|
152
|
+
variable: true
|
|
153
|
+
source: "Google Fonts"
|
|
154
|
+
mono:
|
|
155
|
+
family: "Space Mono"
|
|
156
|
+
fallback: "'SF Mono', 'Courier New', monospace"
|
|
157
|
+
weights: [400, 700]
|
|
158
|
+
source: "Google Fonts"
|
|
159
|
+
scale:
|
|
160
|
+
base: "1rem"
|
|
161
|
+
ratio: 1.2
|
|
162
|
+
sizes:
|
|
163
|
+
xs: "0.75rem"
|
|
164
|
+
sm: "0.875rem"
|
|
165
|
+
base: "1rem"
|
|
166
|
+
lg: "1.125rem"
|
|
167
|
+
xl: "1.25rem"
|
|
168
|
+
"2xl": "1.5rem"
|
|
169
|
+
"3xl": "1.8rem"
|
|
170
|
+
"4xl": "2.16rem"
|
|
171
|
+
"5xl": "2.592rem"
|
|
172
|
+
usage: "Great for startups, portfolios, and minimal landing pages that favor geometric precision over ornamentation."
|
|
173
|
+
|
|
174
|
+
- name: "Monospace Forward"
|
|
175
|
+
tags: ["developer", "technical", "code", "hacker"]
|
|
176
|
+
display:
|
|
177
|
+
family: "JetBrains Mono"
|
|
178
|
+
fallback: "'SF Mono', 'Fira Code', 'Cascadia Code', monospace"
|
|
179
|
+
weights: [500, 700, 800]
|
|
180
|
+
variable: true
|
|
181
|
+
source: "Google Fonts"
|
|
182
|
+
body:
|
|
183
|
+
family: "IBM Plex Sans"
|
|
184
|
+
fallback: "'Helvetica Neue', Arial, sans-serif"
|
|
185
|
+
weights: [400, 500, 600]
|
|
186
|
+
variable: false
|
|
187
|
+
source: "Google Fonts"
|
|
188
|
+
mono:
|
|
189
|
+
family: "JetBrains Mono"
|
|
190
|
+
fallback: "'SF Mono', 'Fira Code', 'Cascadia Code', monospace"
|
|
191
|
+
weights: [400, 500]
|
|
192
|
+
source: "Google Fonts"
|
|
193
|
+
scale:
|
|
194
|
+
base: "1rem"
|
|
195
|
+
ratio: 1.2
|
|
196
|
+
sizes:
|
|
197
|
+
xs: "0.75rem"
|
|
198
|
+
sm: "0.875rem"
|
|
199
|
+
base: "1rem"
|
|
200
|
+
lg: "1.125rem"
|
|
201
|
+
xl: "1.25rem"
|
|
202
|
+
"2xl": "1.5rem"
|
|
203
|
+
"3xl": "1.8rem"
|
|
204
|
+
"4xl": "2.16rem"
|
|
205
|
+
"5xl": "2.592rem"
|
|
206
|
+
usage: "Tailored for developer tools, documentation sites, and technical blogs where code is a first-class citizen."
|
|
207
|
+
|
|
208
|
+
- name: "High Contrast A11y"
|
|
209
|
+
tags: ["accessible", "healthcare", "government", "high-contrast"]
|
|
210
|
+
display:
|
|
211
|
+
family: "Atkinson Hyperlegible"
|
|
212
|
+
fallback: "Arial, 'Helvetica Neue', sans-serif"
|
|
213
|
+
weights: [400, 700]
|
|
214
|
+
variable: false
|
|
215
|
+
source: "Google Fonts"
|
|
216
|
+
body:
|
|
217
|
+
family: "Atkinson Hyperlegible"
|
|
218
|
+
fallback: "Arial, 'Helvetica Neue', sans-serif"
|
|
219
|
+
weights: [400, 700]
|
|
220
|
+
variable: false
|
|
221
|
+
source: "Google Fonts"
|
|
222
|
+
mono:
|
|
223
|
+
family: "Red Hat Mono"
|
|
224
|
+
fallback: "'SF Mono', 'Courier New', monospace"
|
|
225
|
+
weights: [400, 700]
|
|
226
|
+
source: "Google Fonts"
|
|
227
|
+
scale:
|
|
228
|
+
base: "1.125rem"
|
|
229
|
+
ratio: 1.25
|
|
230
|
+
sizes:
|
|
231
|
+
xs: "0.875rem"
|
|
232
|
+
sm: "1rem"
|
|
233
|
+
base: "1.125rem"
|
|
234
|
+
lg: "1.25rem"
|
|
235
|
+
xl: "1.5rem"
|
|
236
|
+
"2xl": "1.875rem"
|
|
237
|
+
"3xl": "2.25rem"
|
|
238
|
+
"4xl": "3rem"
|
|
239
|
+
"5xl": "3.75rem"
|
|
240
|
+
usage: "Designed for maximum legibility. Ideal for healthcare, government, education, and any context where accessibility is paramount."
|
|
241
|
+
|
|
242
|
+
- name: "System Native"
|
|
243
|
+
tags: ["system", "performance", "native", "zero-download"]
|
|
244
|
+
display:
|
|
245
|
+
family: "system-ui"
|
|
246
|
+
fallback: "-apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
|
247
|
+
weights: [500, 600, 700]
|
|
248
|
+
variable: false
|
|
249
|
+
source: "System"
|
|
250
|
+
body:
|
|
251
|
+
family: "system-ui"
|
|
252
|
+
fallback: "-apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
|
253
|
+
weights: [400, 500, 600]
|
|
254
|
+
variable: false
|
|
255
|
+
source: "System"
|
|
256
|
+
mono:
|
|
257
|
+
family: "ui-monospace"
|
|
258
|
+
fallback: "'SF Mono', 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Courier New', monospace"
|
|
259
|
+
weights: [400, 500]
|
|
260
|
+
source: "System"
|
|
261
|
+
scale:
|
|
262
|
+
base: "1rem"
|
|
263
|
+
ratio: 1.25
|
|
264
|
+
sizes:
|
|
265
|
+
xs: "0.75rem"
|
|
266
|
+
sm: "0.875rem"
|
|
267
|
+
base: "1rem"
|
|
268
|
+
lg: "1.125rem"
|
|
269
|
+
xl: "1.25rem"
|
|
270
|
+
"2xl": "1.5rem"
|
|
271
|
+
"3xl": "1.875rem"
|
|
272
|
+
"4xl": "2.25rem"
|
|
273
|
+
"5xl": "3rem"
|
|
274
|
+
usage: "Zero font downloads, instant rendering. Best for performance-critical apps, internal tools, and native-feeling web applications."
|
package/dist/bin/harness.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createProgram
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-FFIX3QVG.js";
|
|
5
|
+
import "../chunk-4WUGOJQ7.js";
|
|
6
|
+
import "../chunk-GA6GN5J2.js";
|
|
7
7
|
import {
|
|
8
8
|
handleError
|
|
9
9
|
} from "../chunk-ACMDUQJG.js";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Ok
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-GA6GN5J2.js";
|
|
4
4
|
|
|
5
5
|
// src/commands/validate-cross-check.ts
|
|
6
6
|
import * as fs from "fs";
|
|
7
7
|
import * as path from "path";
|
|
8
|
-
import {
|
|
8
|
+
import { execFileSync } from "child_process";
|
|
9
9
|
function findFiles(dir, ext) {
|
|
10
10
|
if (!fs.existsSync(dir)) return [];
|
|
11
11
|
return fs.readdirSync(dir).filter((f) => f.endsWith(ext)).map((f) => path.join(dir, f));
|
|
@@ -21,7 +21,7 @@ function extractPlannedFiles(planContent) {
|
|
|
21
21
|
}
|
|
22
22
|
function getFileModTime(filePath, projectPath) {
|
|
23
23
|
try {
|
|
24
|
-
const output =
|
|
24
|
+
const output = execFileSync("git", ["log", "-1", "--format=%aI", "--", filePath], {
|
|
25
25
|
cwd: projectPath,
|
|
26
26
|
encoding: "utf-8",
|
|
27
27
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
validateAgentsMap,
|
|
33
33
|
validateDependencies,
|
|
34
34
|
validateKnowledgeMap
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-GA6GN5J2.js";
|
|
36
36
|
import {
|
|
37
37
|
CLIError,
|
|
38
38
|
ExitCode,
|
|
@@ -86,6 +86,23 @@ var PhaseGatesConfigSchema = z.object({
|
|
|
86
86
|
severity: z.enum(["error", "warning"]).default("error"),
|
|
87
87
|
mappings: z.array(PhaseGateMappingSchema).default([{ implPattern: "src/**/*.ts", specPattern: "docs/specs/{feature}.md" }])
|
|
88
88
|
});
|
|
89
|
+
var SecurityConfigSchema = z.object({
|
|
90
|
+
enabled: z.boolean().default(true),
|
|
91
|
+
strict: z.boolean().default(false),
|
|
92
|
+
rules: z.record(z.string(), z.enum(["off", "error", "warning", "info"])).optional(),
|
|
93
|
+
exclude: z.array(z.string()).optional()
|
|
94
|
+
}).passthrough();
|
|
95
|
+
var PerformanceConfigSchema = z.object({
|
|
96
|
+
complexity: z.record(z.unknown()).optional(),
|
|
97
|
+
coupling: z.record(z.unknown()).optional(),
|
|
98
|
+
sizeBudget: z.record(z.unknown()).optional()
|
|
99
|
+
}).passthrough();
|
|
100
|
+
var DesignConfigSchema = z.object({
|
|
101
|
+
strictness: z.enum(["strict", "standard", "permissive"]).default("standard"),
|
|
102
|
+
platforms: z.array(z.enum(["web", "mobile"])).default([]),
|
|
103
|
+
tokenPath: z.string().optional(),
|
|
104
|
+
aestheticIntent: z.string().optional()
|
|
105
|
+
});
|
|
89
106
|
var HarnessConfigSchema = z.object({
|
|
90
107
|
version: z.literal(1),
|
|
91
108
|
name: z.string().optional(),
|
|
@@ -97,12 +114,15 @@ var HarnessConfigSchema = z.object({
|
|
|
97
114
|
docsDir: z.string().default("./docs"),
|
|
98
115
|
agent: AgentConfigSchema.optional(),
|
|
99
116
|
entropy: EntropyConfigSchema.optional(),
|
|
117
|
+
security: SecurityConfigSchema.optional(),
|
|
118
|
+
performance: PerformanceConfigSchema.optional(),
|
|
100
119
|
template: z.object({
|
|
101
120
|
level: z.enum(["basic", "intermediate", "advanced"]),
|
|
102
121
|
framework: z.string().optional(),
|
|
103
122
|
version: z.number()
|
|
104
123
|
}).optional(),
|
|
105
|
-
phaseGates: PhaseGatesConfigSchema.optional()
|
|
124
|
+
phaseGates: PhaseGatesConfigSchema.optional(),
|
|
125
|
+
design: DesignConfigSchema.optional()
|
|
106
126
|
});
|
|
107
127
|
|
|
108
128
|
// src/config/loader.ts
|
|
@@ -294,7 +314,7 @@ function createValidateCommand() {
|
|
|
294
314
|
process.exit(result.error.exitCode);
|
|
295
315
|
}
|
|
296
316
|
if (opts.crossCheck) {
|
|
297
|
-
const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-
|
|
317
|
+
const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-WGXQ7K62.js");
|
|
298
318
|
const cwd = process.cwd();
|
|
299
319
|
const specsDir = path2.join(cwd, "docs", "specs");
|
|
300
320
|
const plansDir = path2.join(cwd, "docs", "plans");
|
|
@@ -660,7 +680,7 @@ function createPerfCommand() {
|
|
|
660
680
|
perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
|
|
661
681
|
const globalOpts = cmd.optsWithGlobals();
|
|
662
682
|
const cwd = process.cwd();
|
|
663
|
-
const { BenchmarkRunner } = await import("./dist-
|
|
683
|
+
const { BenchmarkRunner } = await import("./dist-C4J67MPP.js");
|
|
664
684
|
const runner = new BenchmarkRunner();
|
|
665
685
|
const benchFiles = runner.discover(cwd, glob2);
|
|
666
686
|
if (benchFiles.length === 0) {
|
|
@@ -729,7 +749,7 @@ Results (${result.results.length} benchmarks):`);
|
|
|
729
749
|
baselines.command("update").description("Update baselines from latest benchmark run").action(async (_opts, cmd) => {
|
|
730
750
|
const globalOpts = cmd.optsWithGlobals();
|
|
731
751
|
const cwd = process.cwd();
|
|
732
|
-
const { BenchmarkRunner } = await import("./dist-
|
|
752
|
+
const { BenchmarkRunner } = await import("./dist-C4J67MPP.js");
|
|
733
753
|
const runner = new BenchmarkRunner();
|
|
734
754
|
const manager = new BaselineManager(cwd);
|
|
735
755
|
logger.info("Running benchmarks to update baselines...");
|
|
@@ -742,8 +762,8 @@ Results (${result.results.length} benchmarks):`);
|
|
|
742
762
|
}
|
|
743
763
|
let commitHash = "unknown";
|
|
744
764
|
try {
|
|
745
|
-
const { execSync:
|
|
746
|
-
commitHash =
|
|
765
|
+
const { execSync: execSync3 } = await import("child_process");
|
|
766
|
+
commitHash = execSync3("git rev-parse --short HEAD", { cwd, encoding: "utf-8" }).trim();
|
|
747
767
|
} catch {
|
|
748
768
|
}
|
|
749
769
|
manager.save(benchResult.results, commitHash);
|
|
@@ -757,7 +777,7 @@ Results (${result.results.length} benchmarks):`);
|
|
|
757
777
|
perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
|
|
758
778
|
const globalOpts = cmd.optsWithGlobals();
|
|
759
779
|
const cwd = process.cwd();
|
|
760
|
-
const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-
|
|
780
|
+
const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-C4J67MPP.js");
|
|
761
781
|
const analyzer = new EntropyAnalyzer2({
|
|
762
782
|
rootDir: path6.resolve(cwd),
|
|
763
783
|
analyze: { complexity: true, coupling: true }
|
|
@@ -1230,8 +1250,7 @@ import * as path10 from "path";
|
|
|
1230
1250
|
import * as os from "os";
|
|
1231
1251
|
import chalk2 from "chalk";
|
|
1232
1252
|
var HARNESS_MCP_ENTRY = {
|
|
1233
|
-
command: "
|
|
1234
|
-
args: ["@harness-engineering/mcp-server"]
|
|
1253
|
+
command: "harness-mcp"
|
|
1235
1254
|
};
|
|
1236
1255
|
function readJsonFile(filePath) {
|
|
1237
1256
|
if (!fs4.existsSync(filePath)) return null;
|
|
@@ -3211,7 +3230,7 @@ import * as path24 from "path";
|
|
|
3211
3230
|
import { parse as parse5 } from "yaml";
|
|
3212
3231
|
|
|
3213
3232
|
// src/skill/complexity.ts
|
|
3214
|
-
import {
|
|
3233
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
3215
3234
|
function evaluateSignals(signals) {
|
|
3216
3235
|
if (signals.fileCount >= 3) return "full";
|
|
3217
3236
|
if (signals.newDir) return "full";
|
|
@@ -3223,17 +3242,17 @@ function evaluateSignals(signals) {
|
|
|
3223
3242
|
}
|
|
3224
3243
|
function detectComplexity(projectPath) {
|
|
3225
3244
|
try {
|
|
3226
|
-
const base =
|
|
3245
|
+
const base = execFileSync2("git", ["merge-base", "HEAD", "main"], {
|
|
3227
3246
|
cwd: projectPath,
|
|
3228
3247
|
encoding: "utf-8",
|
|
3229
3248
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3230
3249
|
}).trim();
|
|
3231
|
-
const diffFiles =
|
|
3250
|
+
const diffFiles = execFileSync2("git", ["diff", "--name-only", base], {
|
|
3232
3251
|
cwd: projectPath,
|
|
3233
3252
|
encoding: "utf-8",
|
|
3234
3253
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3235
3254
|
}).trim().split("\n").filter(Boolean);
|
|
3236
|
-
const diffStat =
|
|
3255
|
+
const diffStat = execFileSync2("git", ["diff", "--stat", base], {
|
|
3237
3256
|
cwd: projectPath,
|
|
3238
3257
|
encoding: "utf-8",
|
|
3239
3258
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4526,7 +4545,7 @@ function createCICommand() {
|
|
|
4526
4545
|
|
|
4527
4546
|
// src/commands/update.ts
|
|
4528
4547
|
import { Command as Command36 } from "commander";
|
|
4529
|
-
import {
|
|
4548
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
4530
4549
|
import { realpathSync } from "fs";
|
|
4531
4550
|
import readline3 from "readline";
|
|
4532
4551
|
import chalk4 from "chalk";
|
|
@@ -4546,7 +4565,7 @@ function detectPackageManager() {
|
|
|
4546
4565
|
return "npm";
|
|
4547
4566
|
}
|
|
4548
4567
|
function getLatestVersion(pkg = "@harness-engineering/cli") {
|
|
4549
|
-
const output =
|
|
4568
|
+
const output = execFileSync3("npm", ["view", pkg, "dist-tags.latest"], {
|
|
4550
4569
|
encoding: "utf-8",
|
|
4551
4570
|
timeout: 15e3
|
|
4552
4571
|
});
|
|
@@ -4554,7 +4573,7 @@ function getLatestVersion(pkg = "@harness-engineering/cli") {
|
|
|
4554
4573
|
}
|
|
4555
4574
|
function getInstalledVersion(pm) {
|
|
4556
4575
|
try {
|
|
4557
|
-
const output =
|
|
4576
|
+
const output = execFileSync3(pm, ["list", "-g", "@harness-engineering/cli", "--json"], {
|
|
4558
4577
|
encoding: "utf-8",
|
|
4559
4578
|
timeout: 15e3
|
|
4560
4579
|
});
|
|
@@ -4567,7 +4586,7 @@ function getInstalledVersion(pm) {
|
|
|
4567
4586
|
}
|
|
4568
4587
|
function getInstalledPackages(pm) {
|
|
4569
4588
|
try {
|
|
4570
|
-
const output =
|
|
4589
|
+
const output = execFileSync3(pm, ["list", "-g", "--json"], {
|
|
4571
4590
|
encoding: "utf-8",
|
|
4572
4591
|
timeout: 15e3
|
|
4573
4592
|
});
|
|
@@ -4622,19 +4641,19 @@ function createUpdateCommand() {
|
|
|
4622
4641
|
if (globalOpts.verbose) {
|
|
4623
4642
|
logger.info(`Installed packages: ${packages.join(", ")}`);
|
|
4624
4643
|
}
|
|
4625
|
-
const
|
|
4644
|
+
const installPkgs = packages.map((pkg) => {
|
|
4626
4645
|
if (opts.version && pkg === "@harness-engineering/cli") {
|
|
4627
4646
|
return `${pkg}@${opts.version}`;
|
|
4628
4647
|
}
|
|
4629
4648
|
return `${pkg}@latest`;
|
|
4630
|
-
})
|
|
4631
|
-
const installCmd = `${pm} install -g ${
|
|
4649
|
+
});
|
|
4650
|
+
const installCmd = `${pm} install -g ${installPkgs.join(" ")}`;
|
|
4632
4651
|
if (globalOpts.verbose) {
|
|
4633
4652
|
logger.info(`Running: ${installCmd}`);
|
|
4634
4653
|
}
|
|
4635
4654
|
try {
|
|
4636
4655
|
logger.info("Updating packages...");
|
|
4637
|
-
|
|
4656
|
+
execFileSync3(pm, ["install", "-g", ...installPkgs], { stdio: "inherit", timeout: 12e4 });
|
|
4638
4657
|
console.log("");
|
|
4639
4658
|
logger.success("Update complete");
|
|
4640
4659
|
} catch {
|
|
@@ -4647,12 +4666,14 @@ function createUpdateCommand() {
|
|
|
4647
4666
|
const regenAnswer = await prompt("Regenerate slash commands and agent definitions? (y/N) ");
|
|
4648
4667
|
if (regenAnswer === "y" || regenAnswer === "yes") {
|
|
4649
4668
|
const scopeAnswer = await prompt("Generate for (g)lobal or (l)ocal project? (g/l) ");
|
|
4650
|
-
const
|
|
4669
|
+
const isGlobal = scopeAnswer === "g" || scopeAnswer === "global";
|
|
4651
4670
|
try {
|
|
4652
|
-
|
|
4671
|
+
execFileSync3("harness", ["generate", ...isGlobal ? ["--global"] : []], {
|
|
4672
|
+
stdio: "inherit"
|
|
4673
|
+
});
|
|
4653
4674
|
} catch {
|
|
4654
4675
|
logger.warn("Generation failed. Run manually:");
|
|
4655
|
-
console.log(` ${chalk4.cyan(`harness generate${
|
|
4676
|
+
console.log(` ${chalk4.cyan(`harness generate${isGlobal ? " --global" : ""}`)}`);
|
|
4656
4677
|
}
|
|
4657
4678
|
}
|
|
4658
4679
|
process.exit(ExitCode.SUCCESS);
|
|
@@ -4672,7 +4693,9 @@ var AGENT_DESCRIPTIONS = {
|
|
|
4672
4693
|
"parallel-coordinator": "Dispatch independent tasks across isolated agents for parallel execution. Use when multiple independent tasks need to run concurrently, splitting work across agents, or coordinating parallel implementation.",
|
|
4673
4694
|
"architecture-enforcer": "Validate architectural constraints and dependency rules. Use when checking layer boundaries, detecting circular dependencies, or verifying import direction compliance.",
|
|
4674
4695
|
"documentation-maintainer": "Keep documentation in sync with source code. Use when detecting documentation drift, validating doc coverage, or aligning docs with code changes.",
|
|
4675
|
-
"entropy-cleaner": "Detect and fix codebase entropy including drift, dead code, and pattern violations. Use when running cleanup, detecting dead code, or fixing pattern violations."
|
|
4696
|
+
"entropy-cleaner": "Detect and fix codebase entropy including drift, dead code, and pattern violations. Use when running cleanup, detecting dead code, or fixing pattern violations.",
|
|
4697
|
+
planner: "Create detailed implementation plans from specs with task breakdown, dependency ordering, and checkpoint placement. Use when planning a phase, breaking a spec into tasks, or creating an execution plan.",
|
|
4698
|
+
verifier: "Verify implementation completeness against spec and plan at three tiers (EXISTS, SUBSTANTIVE, WIRED). Use when checking if built code matches what was planned, validating phase completion, or auditing implementation quality."
|
|
4676
4699
|
};
|
|
4677
4700
|
var DEFAULT_TOOLS = ["Bash", "Read", "Write", "Edit", "Glob", "Grep"];
|
|
4678
4701
|
function generateAgentDefinition(persona, skillContents) {
|
|
@@ -4765,7 +4788,12 @@ function renderGeminiAgent(def) {
|
|
|
4765
4788
|
lines.push(`name: ${def.name}`);
|
|
4766
4789
|
lines.push(`description: >`);
|
|
4767
4790
|
lines.push(` ${def.description}`);
|
|
4768
|
-
|
|
4791
|
+
if (def.tools.length > 0) {
|
|
4792
|
+
lines.push("tools:");
|
|
4793
|
+
for (const tool of def.tools) {
|
|
4794
|
+
lines.push(` - ${tool}`);
|
|
4795
|
+
}
|
|
4796
|
+
}
|
|
4769
4797
|
lines.push("---");
|
|
4770
4798
|
lines.push("");
|
|
4771
4799
|
lines.push(GENERATED_HEADER_AGENT);
|
|
@@ -4966,7 +4994,7 @@ function createGenerateCommand3() {
|
|
|
4966
4994
|
import { Command as Command39 } from "commander";
|
|
4967
4995
|
import * as path37 from "path";
|
|
4968
4996
|
async function runScan(projectPath) {
|
|
4969
|
-
const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-
|
|
4997
|
+
const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-N4D4QWFV.js");
|
|
4970
4998
|
const store = new GraphStore();
|
|
4971
4999
|
const start = Date.now();
|
|
4972
5000
|
await new CodeIngestor(store).ingest(projectPath);
|
|
@@ -5047,7 +5075,7 @@ async function runIngest(projectPath, source, opts) {
|
|
|
5047
5075
|
SyncManager,
|
|
5048
5076
|
JiraConnector,
|
|
5049
5077
|
SlackConnector
|
|
5050
|
-
} = await import("./dist-
|
|
5078
|
+
} = await import("./dist-N4D4QWFV.js");
|
|
5051
5079
|
const graphDir = path38.join(projectPath, ".harness", "graph");
|
|
5052
5080
|
const store = new GraphStore();
|
|
5053
5081
|
await store.load(graphDir);
|
|
@@ -5140,7 +5168,7 @@ function createIngestCommand() {
|
|
|
5140
5168
|
import { Command as Command41 } from "commander";
|
|
5141
5169
|
import * as path39 from "path";
|
|
5142
5170
|
async function runQuery(projectPath, rootNodeId, opts) {
|
|
5143
|
-
const { GraphStore, ContextQL } = await import("./dist-
|
|
5171
|
+
const { GraphStore, ContextQL } = await import("./dist-N4D4QWFV.js");
|
|
5144
5172
|
const store = new GraphStore();
|
|
5145
5173
|
const graphDir = path39.join(projectPath, ".harness", "graph");
|
|
5146
5174
|
const loaded = await store.load(graphDir);
|
|
@@ -5189,7 +5217,7 @@ import { Command as Command42 } from "commander";
|
|
|
5189
5217
|
// src/commands/graph/status.ts
|
|
5190
5218
|
import * as path40 from "path";
|
|
5191
5219
|
async function runGraphStatus(projectPath) {
|
|
5192
|
-
const { GraphStore } = await import("./dist-
|
|
5220
|
+
const { GraphStore } = await import("./dist-N4D4QWFV.js");
|
|
5193
5221
|
const graphDir = path40.join(projectPath, ".harness", "graph");
|
|
5194
5222
|
const store = new GraphStore();
|
|
5195
5223
|
const loaded = await store.load(graphDir);
|
|
@@ -5229,7 +5257,7 @@ async function runGraphStatus(projectPath) {
|
|
|
5229
5257
|
// src/commands/graph/export.ts
|
|
5230
5258
|
import * as path41 from "path";
|
|
5231
5259
|
async function runGraphExport(projectPath, format) {
|
|
5232
|
-
const { GraphStore } = await import("./dist-
|
|
5260
|
+
const { GraphStore } = await import("./dist-N4D4QWFV.js");
|
|
5233
5261
|
const graphDir = path41.join(projectPath, ".harness", "graph");
|
|
5234
5262
|
const store = new GraphStore();
|
|
5235
5263
|
const loaded = await store.load(graphDir);
|
|
@@ -46,7 +46,7 @@ import { dirname as dirname6, basename as basename4, join as join5 } from "path"
|
|
|
46
46
|
import { z } from "zod";
|
|
47
47
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
48
48
|
import { join as join6, dirname as dirname7 } from "path";
|
|
49
|
-
import { execFileSync
|
|
49
|
+
import { execFileSync } from "child_process";
|
|
50
50
|
import * as fs2 from "fs";
|
|
51
51
|
import * as path from "path";
|
|
52
52
|
import { appendFileSync, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
@@ -54,10 +54,10 @@ import { dirname as dirname8 } from "path";
|
|
|
54
54
|
import { z as z2 } from "zod";
|
|
55
55
|
import * as fs4 from "fs";
|
|
56
56
|
import * as path3 from "path";
|
|
57
|
-
import { execSync as
|
|
57
|
+
import { execSync as execSync2 } from "child_process";
|
|
58
58
|
import * as fs3 from "fs";
|
|
59
59
|
import * as path2 from "path";
|
|
60
|
-
import { execSync
|
|
60
|
+
import { execSync } from "child_process";
|
|
61
61
|
import { z as z3 } from "zod";
|
|
62
62
|
import * as fs6 from "fs/promises";
|
|
63
63
|
import { z as z4 } from "zod";
|
|
@@ -3492,7 +3492,7 @@ var BenchmarkRunner = class {
|
|
|
3492
3492
|
}
|
|
3493
3493
|
args.push("--reporter=json");
|
|
3494
3494
|
try {
|
|
3495
|
-
const rawOutput =
|
|
3495
|
+
const rawOutput = execFileSync("npx", args, {
|
|
3496
3496
|
cwd,
|
|
3497
3497
|
encoding: "utf-8",
|
|
3498
3498
|
timeout,
|
|
@@ -4612,7 +4612,7 @@ function getCurrentBranch(projectPath) {
|
|
|
4612
4612
|
return cached.branch;
|
|
4613
4613
|
}
|
|
4614
4614
|
try {
|
|
4615
|
-
const branch =
|
|
4615
|
+
const branch = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
4616
4616
|
cwd: projectPath,
|
|
4617
4617
|
stdio: "pipe"
|
|
4618
4618
|
}).toString().trim();
|
|
@@ -5071,7 +5071,7 @@ async function runMechanicalGate(projectPath) {
|
|
|
5071
5071
|
for (const check of checks) {
|
|
5072
5072
|
const start = Date.now();
|
|
5073
5073
|
try {
|
|
5074
|
-
|
|
5074
|
+
execSync2(check.command, {
|
|
5075
5075
|
cwd: projectPath,
|
|
5076
5076
|
stdio: "pipe",
|
|
5077
5077
|
timeout: 12e4
|