javi-forge 1.5.0 → 1.6.1
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/README.md +191 -3
- package/ci-local/hooks/pre-push +17 -13
- package/dist/commands/analyze.d.ts +1 -1
- package/dist/commands/analyze.js +15 -15
- package/dist/commands/atlassian-mcp.d.ts +42 -0
- package/dist/commands/atlassian-mcp.js +98 -0
- package/dist/commands/ci.d.ts +3 -3
- package/dist/commands/ci.js +185 -147
- package/dist/commands/crash-recovery.d.ts +34 -0
- package/dist/commands/crash-recovery.js +123 -0
- package/dist/commands/doctor.d.ts +2 -2
- package/dist/commands/doctor.js +113 -61
- package/dist/commands/harness-audit.d.ts +35 -0
- package/dist/commands/harness-audit.js +277 -0
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +415 -118
- package/dist/commands/llmstxt.d.ts +1 -1
- package/dist/commands/llmstxt.js +36 -34
- package/dist/commands/parallel-batch.d.ts +42 -0
- package/dist/commands/parallel-batch.js +90 -0
- package/dist/commands/plugin.d.ts +26 -1
- package/dist/commands/plugin.js +138 -24
- package/dist/commands/secret-scanner.d.ts +30 -0
- package/dist/commands/secret-scanner.js +272 -0
- package/dist/commands/security-analysis.d.ts +74 -0
- package/dist/commands/security-analysis.js +487 -0
- package/dist/commands/security.d.ts +31 -0
- package/dist/commands/security.js +445 -0
- package/dist/commands/skill-scanner.d.ts +63 -0
- package/dist/commands/skill-scanner.js +383 -0
- package/dist/commands/skills.d.ts +139 -0
- package/dist/commands/skills.js +895 -0
- package/dist/commands/supply-chain.d.ts +23 -0
- package/dist/commands/supply-chain.js +126 -0
- package/dist/commands/tdd-pipeline.d.ts +17 -0
- package/dist/commands/tdd-pipeline.js +144 -0
- package/dist/commands/tdd.d.ts +21 -0
- package/dist/commands/tdd.js +120 -0
- package/dist/commands/team-presets.d.ts +53 -0
- package/dist/commands/team-presets.js +201 -0
- package/dist/commands/workflow.d.ts +23 -0
- package/dist/commands/workflow.js +114 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.js +208 -37
- package/dist/index.js +400 -54
- package/dist/lib/agent-skills.d.ts +73 -0
- package/dist/lib/agent-skills.js +260 -0
- package/dist/lib/auto-skill-install.d.ts +37 -0
- package/dist/lib/auto-skill-install.js +92 -0
- package/dist/lib/auto-wire.d.ts +20 -0
- package/dist/lib/auto-wire.js +240 -0
- package/dist/lib/claudemd.d.ts +20 -0
- package/dist/lib/claudemd.js +222 -0
- package/dist/lib/codex-export.d.ts +16 -0
- package/dist/lib/codex-export.js +109 -0
- package/dist/lib/common.d.ts +1 -1
- package/dist/lib/common.js +52 -44
- package/dist/lib/context.d.ts +27 -0
- package/dist/lib/context.js +204 -0
- package/dist/lib/docker.d.ts +1 -1
- package/dist/lib/docker.js +141 -112
- package/dist/lib/frontmatter.d.ts +1 -1
- package/dist/lib/frontmatter.js +29 -15
- package/dist/lib/plugin.d.ts +19 -1
- package/dist/lib/plugin.js +174 -47
- package/dist/lib/skill-publish.d.ts +40 -0
- package/dist/lib/skill-publish.js +146 -0
- package/dist/lib/stack-detector.d.ts +38 -0
- package/dist/lib/stack-detector.js +207 -0
- package/dist/lib/template.d.ts +16 -1
- package/dist/lib/template.js +46 -17
- package/dist/lib/workflow/discovery.d.ts +19 -0
- package/dist/lib/workflow/discovery.js +68 -0
- package/dist/lib/workflow/index.d.ts +5 -0
- package/dist/lib/workflow/index.js +5 -0
- package/dist/lib/workflow/parser.d.ts +16 -0
- package/dist/lib/workflow/parser.js +198 -0
- package/dist/lib/workflow/renderer.d.ts +9 -0
- package/dist/lib/workflow/renderer.js +152 -0
- package/dist/lib/workflow/validator.d.ts +10 -0
- package/dist/lib/workflow/validator.js +189 -0
- package/dist/tasks/index.d.ts +4 -0
- package/dist/tasks/index.js +4 -0
- package/dist/tasks/scaffold-tasks.d.ts +3 -0
- package/dist/tasks/scaffold-tasks.js +14 -0
- package/dist/tasks/task-id.d.ts +30 -0
- package/dist/tasks/task-id.js +55 -0
- package/dist/tasks/task-tracker.d.ts +15 -0
- package/dist/tasks/task-tracker.js +81 -0
- package/dist/types/index.d.ts +252 -5
- package/dist/types/index.js +11 -1
- package/dist/ui/AnalyzeUI.d.ts +1 -1
- package/dist/ui/AnalyzeUI.js +38 -39
- package/dist/ui/App.d.ts +5 -3
- package/dist/ui/App.js +92 -46
- package/dist/ui/AutoSkills.d.ts +9 -0
- package/dist/ui/AutoSkills.js +124 -0
- package/dist/ui/CI.d.ts +2 -2
- package/dist/ui/CI.js +24 -26
- package/dist/ui/CIContext.d.ts +1 -1
- package/dist/ui/CIContext.js +3 -2
- package/dist/ui/CISelector.d.ts +2 -2
- package/dist/ui/CISelector.js +23 -15
- package/dist/ui/Doctor.d.ts +1 -1
- package/dist/ui/Doctor.js +35 -29
- package/dist/ui/Header.d.ts +1 -1
- package/dist/ui/Header.js +14 -14
- package/dist/ui/HookProfileSelector.d.ts +9 -0
- package/dist/ui/HookProfileSelector.js +54 -0
- package/dist/ui/LlmsTxt.d.ts +1 -1
- package/dist/ui/LlmsTxt.js +31 -22
- package/dist/ui/MemorySelector.d.ts +2 -2
- package/dist/ui/MemorySelector.js +28 -16
- package/dist/ui/NameInput.d.ts +1 -1
- package/dist/ui/NameInput.js +21 -21
- package/dist/ui/OptionSelector.d.ts +8 -2
- package/dist/ui/OptionSelector.js +83 -26
- package/dist/ui/Plugin.d.ts +4 -3
- package/dist/ui/Plugin.js +89 -29
- package/dist/ui/Progress.d.ts +3 -3
- package/dist/ui/Progress.js +23 -22
- package/dist/ui/Skills.d.ts +11 -0
- package/dist/ui/Skills.js +148 -0
- package/dist/ui/StackSelector.d.ts +2 -2
- package/dist/ui/StackSelector.js +26 -16
- package/dist/ui/Summary.d.ts +3 -3
- package/dist/ui/Summary.js +60 -50
- package/dist/ui/Welcome.d.ts +1 -1
- package/dist/ui/Welcome.js +15 -16
- package/dist/ui/theme.d.ts +1 -1
- package/dist/ui/theme.js +6 -6
- package/package.json +9 -6
- package/templates/common/atlassian/mcp-atlassian-snippet.json +16 -0
- package/templates/common/repoforge/mcp-repoforge-snippet.json +11 -0
- package/templates/common/repoforge/repoforge.yaml +34 -0
- package/templates/github/deploy-docker-zero-downtime.yml +140 -0
- package/templates/github/repoforge-graph.yml +45 -0
- package/templates/gitlab/deploy-docker-zero-downtime.yml +57 -0
- package/templates/local-ai/.env.example +17 -0
- package/templates/local-ai/docker-compose.yml +95 -0
- package/templates/security-hooks/claude-settings-security.json +30 -0
- package/templates/security-hooks/commit-msg-signing +29 -0
- package/templates/security-hooks/pre-commit-permissions +74 -0
- package/templates/security-hooks/pre-commit-secrets +74 -0
- package/templates/security-hooks/pre-push-branch-protection +62 -0
- package/templates/security-hooks/pre-push-deps +83 -0
- package/templates/security-hooks/pre-push-signing +67 -0
- package/templates/woodpecker/deploy-docker-zero-downtime.yml +50 -0
- package/templates/workflows/ci-pipeline.dot +15 -0
- package/templates/workflows/feature-flow.dot +21 -0
- package/templates/workflows/release.dot +16 -0
- package/dist/__integration__/helpers.d.ts +0 -20
- package/dist/__integration__/helpers.d.ts.map +0 -1
- package/dist/__integration__/helpers.js +0 -31
- package/dist/__integration__/helpers.js.map +0 -1
- package/dist/commands/analyze.d.ts.map +0 -1
- package/dist/commands/analyze.js.map +0 -1
- package/dist/commands/ci.d.ts.map +0 -1
- package/dist/commands/ci.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/llmstxt.d.ts.map +0 -1
- package/dist/commands/llmstxt.js.map +0 -1
- package/dist/commands/plugin.d.ts.map +0 -1
- package/dist/commands/plugin.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/common.d.ts.map +0 -1
- package/dist/lib/common.js.map +0 -1
- package/dist/lib/docker.d.ts.map +0 -1
- package/dist/lib/docker.js.map +0 -1
- package/dist/lib/frontmatter.d.ts.map +0 -1
- package/dist/lib/frontmatter.js.map +0 -1
- package/dist/lib/plugin.d.ts.map +0 -1
- package/dist/lib/plugin.js.map +0 -1
- package/dist/lib/template.d.ts.map +0 -1
- package/dist/lib/template.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/ui/AnalyzeUI.d.ts.map +0 -1
- package/dist/ui/AnalyzeUI.js.map +0 -1
- package/dist/ui/App.d.ts.map +0 -1
- package/dist/ui/App.js.map +0 -1
- package/dist/ui/CI.d.ts.map +0 -1
- package/dist/ui/CI.js.map +0 -1
- package/dist/ui/CIContext.d.ts.map +0 -1
- package/dist/ui/CIContext.js.map +0 -1
- package/dist/ui/CISelector.d.ts.map +0 -1
- package/dist/ui/CISelector.js.map +0 -1
- package/dist/ui/Doctor.d.ts.map +0 -1
- package/dist/ui/Doctor.js.map +0 -1
- package/dist/ui/Header.d.ts.map +0 -1
- package/dist/ui/Header.js.map +0 -1
- package/dist/ui/LlmsTxt.d.ts.map +0 -1
- package/dist/ui/LlmsTxt.js.map +0 -1
- package/dist/ui/MemorySelector.d.ts.map +0 -1
- package/dist/ui/MemorySelector.js.map +0 -1
- package/dist/ui/NameInput.d.ts.map +0 -1
- package/dist/ui/NameInput.js.map +0 -1
- package/dist/ui/OptionSelector.d.ts.map +0 -1
- package/dist/ui/OptionSelector.js.map +0 -1
- package/dist/ui/Plugin.d.ts.map +0 -1
- package/dist/ui/Plugin.js.map +0 -1
- package/dist/ui/Progress.d.ts.map +0 -1
- package/dist/ui/Progress.js.map +0 -1
- package/dist/ui/StackSelector.d.ts.map +0 -1
- package/dist/ui/StackSelector.js.map +0 -1
- package/dist/ui/Summary.d.ts.map +0 -1
- package/dist/ui/Summary.js.map +0 -1
- package/dist/ui/Welcome.d.ts.map +0 -1
- package/dist/ui/Welcome.js.map +0 -1
- package/dist/ui/theme.d.ts.map +0 -1
- package/dist/ui/theme.js.map +0 -1
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness audit — scores how well-configured the AI agent development
|
|
3
|
+
* environment is (hooks, skills, memory, configs). Detects which AI
|
|
4
|
+
* agent harness is installed and generates appropriate config.
|
|
5
|
+
*/
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import path from "path";
|
|
8
|
+
// ── Harness Detection ──
|
|
9
|
+
const HARNESS_SIGNATURES = [
|
|
10
|
+
{
|
|
11
|
+
harness: "claude",
|
|
12
|
+
markers: [".claude", "CLAUDE.md"],
|
|
13
|
+
configDir: ".claude",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
harness: "cursor",
|
|
17
|
+
markers: [".cursor", ".cursorrules"],
|
|
18
|
+
configDir: ".cursor",
|
|
19
|
+
},
|
|
20
|
+
{ harness: "codex", markers: [".codex", "AGENTS.md"], configDir: ".codex" },
|
|
21
|
+
{
|
|
22
|
+
harness: "copilot",
|
|
23
|
+
markers: [".github/copilot-instructions.md"],
|
|
24
|
+
configDir: ".github",
|
|
25
|
+
},
|
|
26
|
+
{ harness: "windsurf", markers: [".windsurfrules"], configDir: "." },
|
|
27
|
+
];
|
|
28
|
+
export function detectHarness(projectDir) {
|
|
29
|
+
for (const sig of HARNESS_SIGNATURES) {
|
|
30
|
+
for (const marker of sig.markers) {
|
|
31
|
+
const fullPath = path.join(projectDir, marker);
|
|
32
|
+
if (fs.existsSync(fullPath)) {
|
|
33
|
+
return {
|
|
34
|
+
harness: sig.harness,
|
|
35
|
+
configDir: path.join(projectDir, sig.configDir),
|
|
36
|
+
version: null,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Check home directory for global installs
|
|
42
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
43
|
+
if (home && fs.existsSync(path.join(home, ".claude"))) {
|
|
44
|
+
return {
|
|
45
|
+
harness: "claude",
|
|
46
|
+
configDir: path.join(home, ".claude"),
|
|
47
|
+
version: null,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return { harness: "none", configDir: null, version: null };
|
|
51
|
+
}
|
|
52
|
+
export function detectAllHarnesses(projectDir) {
|
|
53
|
+
const found = [];
|
|
54
|
+
for (const sig of HARNESS_SIGNATURES) {
|
|
55
|
+
for (const marker of sig.markers) {
|
|
56
|
+
if (fs.existsSync(path.join(projectDir, marker))) {
|
|
57
|
+
found.push({
|
|
58
|
+
harness: sig.harness,
|
|
59
|
+
configDir: path.join(projectDir, sig.configDir),
|
|
60
|
+
version: null,
|
|
61
|
+
});
|
|
62
|
+
break; // one detection per harness
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return found;
|
|
67
|
+
}
|
|
68
|
+
// ── Audit Checks ──
|
|
69
|
+
function checkFileExists(dir, relativePath) {
|
|
70
|
+
return fs.existsSync(path.join(dir, relativePath));
|
|
71
|
+
}
|
|
72
|
+
function checkDirHasFiles(dir, relativePath) {
|
|
73
|
+
const full = path.join(dir, relativePath);
|
|
74
|
+
if (!fs.existsSync(full))
|
|
75
|
+
return false;
|
|
76
|
+
try {
|
|
77
|
+
const entries = fs.readdirSync(full);
|
|
78
|
+
return entries.length > 0;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function auditClaude(projectDir, configDir) {
|
|
85
|
+
const categories = [];
|
|
86
|
+
// Config category
|
|
87
|
+
const configChecks = [
|
|
88
|
+
{
|
|
89
|
+
id: "claude-md",
|
|
90
|
+
label: "CLAUDE.md exists",
|
|
91
|
+
passed: checkFileExists(projectDir, "CLAUDE.md") ||
|
|
92
|
+
checkFileExists(configDir, "CLAUDE.md"),
|
|
93
|
+
points: 15,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: "settings",
|
|
97
|
+
label: "settings.json configured",
|
|
98
|
+
passed: checkFileExists(configDir, "settings.json") ||
|
|
99
|
+
checkFileExists(configDir, "settings.local.json"),
|
|
100
|
+
points: 10,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: "project-config",
|
|
104
|
+
label: "Project-level config exists",
|
|
105
|
+
passed: checkDirHasFiles(configDir, "projects"),
|
|
106
|
+
points: 5,
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
// Skills category
|
|
110
|
+
const skillChecks = [
|
|
111
|
+
{
|
|
112
|
+
id: "skills-dir",
|
|
113
|
+
label: "Skills directory exists",
|
|
114
|
+
passed: checkDirHasFiles(configDir, "skills"),
|
|
115
|
+
points: 15,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "skills-count",
|
|
119
|
+
label: "At least 5 skills installed",
|
|
120
|
+
passed: countSubdirs(path.join(configDir, "skills")) >= 5,
|
|
121
|
+
points: 10,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: "shared-conventions",
|
|
125
|
+
label: "Shared conventions configured",
|
|
126
|
+
passed: checkDirHasFiles(configDir, "skills/_shared"),
|
|
127
|
+
points: 5,
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
// Hooks category
|
|
131
|
+
const hookChecks = [
|
|
132
|
+
{
|
|
133
|
+
id: "hooks-configured",
|
|
134
|
+
label: "Hooks configured in settings",
|
|
135
|
+
passed: hasHooksInSettings(configDir),
|
|
136
|
+
points: 15,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: "pre-commit-hook",
|
|
140
|
+
label: "Pre-commit or CI hook exists",
|
|
141
|
+
passed: checkFileExists(projectDir, ".husky/pre-commit") ||
|
|
142
|
+
checkFileExists(projectDir, ".git/hooks/pre-commit"),
|
|
143
|
+
points: 5,
|
|
144
|
+
},
|
|
145
|
+
];
|
|
146
|
+
// Memory category
|
|
147
|
+
const memoryChecks = [
|
|
148
|
+
{
|
|
149
|
+
id: "memory-dir",
|
|
150
|
+
label: "Memory/projects directory exists",
|
|
151
|
+
passed: checkDirHasFiles(configDir, "projects"),
|
|
152
|
+
points: 10,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: "memory-md",
|
|
156
|
+
label: "MEMORY.md exists in projects",
|
|
157
|
+
passed: hasMemoryMd(configDir),
|
|
158
|
+
points: 10,
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
categories.push(buildCategory("Configuration", configChecks));
|
|
162
|
+
categories.push(buildCategory("Skills", skillChecks));
|
|
163
|
+
categories.push(buildCategory("Hooks", hookChecks));
|
|
164
|
+
categories.push(buildCategory("Memory", memoryChecks));
|
|
165
|
+
return categories;
|
|
166
|
+
}
|
|
167
|
+
function auditGeneric(projectDir) {
|
|
168
|
+
const checks = [
|
|
169
|
+
{
|
|
170
|
+
id: "has-config",
|
|
171
|
+
label: "AI agent config file exists",
|
|
172
|
+
passed: HARNESS_SIGNATURES.some((sig) => sig.markers.some((m) => checkFileExists(projectDir, m))),
|
|
173
|
+
points: 30,
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: "has-gitignore",
|
|
177
|
+
label: ".gitignore excludes agent artifacts",
|
|
178
|
+
passed: gitignoreHasAgent(projectDir),
|
|
179
|
+
points: 10,
|
|
180
|
+
},
|
|
181
|
+
];
|
|
182
|
+
return [buildCategory("Basic Setup", checks)];
|
|
183
|
+
}
|
|
184
|
+
// ── Helpers ──
|
|
185
|
+
function countSubdirs(dir) {
|
|
186
|
+
if (!fs.existsSync(dir))
|
|
187
|
+
return 0;
|
|
188
|
+
try {
|
|
189
|
+
return fs
|
|
190
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
191
|
+
.filter((d) => d.isDirectory()).length;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function hasHooksInSettings(configDir) {
|
|
198
|
+
const settingsPath = path.join(configDir, "settings.json");
|
|
199
|
+
if (!fs.existsSync(settingsPath))
|
|
200
|
+
return false;
|
|
201
|
+
try {
|
|
202
|
+
const content = fs.readFileSync(settingsPath, "utf-8");
|
|
203
|
+
return content.includes("hooks") || content.includes("hook");
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function hasMemoryMd(configDir) {
|
|
210
|
+
const projectsDir = path.join(configDir, "projects");
|
|
211
|
+
if (!fs.existsSync(projectsDir))
|
|
212
|
+
return false;
|
|
213
|
+
try {
|
|
214
|
+
const dirs = fs.readdirSync(projectsDir, { withFileTypes: true });
|
|
215
|
+
return dirs.some((d) => {
|
|
216
|
+
if (!d.isDirectory())
|
|
217
|
+
return false;
|
|
218
|
+
const memDir = path.join(projectsDir, d.name, "memory");
|
|
219
|
+
return (fs.existsSync(memDir) && fs.existsSync(path.join(memDir, "MEMORY.md")));
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function gitignoreHasAgent(projectDir) {
|
|
227
|
+
const giPath = path.join(projectDir, ".gitignore");
|
|
228
|
+
if (!fs.existsSync(giPath))
|
|
229
|
+
return false;
|
|
230
|
+
try {
|
|
231
|
+
const content = fs.readFileSync(giPath, "utf-8");
|
|
232
|
+
return (content.includes(".claude") ||
|
|
233
|
+
content.includes(".cursor") ||
|
|
234
|
+
content.includes(".codex"));
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function buildCategory(name, checks) {
|
|
241
|
+
const score = checks
|
|
242
|
+
.filter((c) => c.passed)
|
|
243
|
+
.reduce((sum, c) => sum + c.points, 0);
|
|
244
|
+
const maxScore = checks.reduce((sum, c) => sum + c.points, 0);
|
|
245
|
+
return { name, score, maxScore, checks };
|
|
246
|
+
}
|
|
247
|
+
function computeGrade(score, max) {
|
|
248
|
+
if (max === 0)
|
|
249
|
+
return "F";
|
|
250
|
+
const pct = (score / max) * 100;
|
|
251
|
+
if (pct >= 90)
|
|
252
|
+
return "A";
|
|
253
|
+
if (pct >= 75)
|
|
254
|
+
return "B";
|
|
255
|
+
if (pct >= 60)
|
|
256
|
+
return "C";
|
|
257
|
+
if (pct >= 40)
|
|
258
|
+
return "D";
|
|
259
|
+
return "F";
|
|
260
|
+
}
|
|
261
|
+
// ── Main ──
|
|
262
|
+
export function runHarnessAudit(projectDir) {
|
|
263
|
+
const detection = detectHarness(projectDir);
|
|
264
|
+
const categories = detection.harness === "claude" && detection.configDir
|
|
265
|
+
? auditClaude(projectDir, detection.configDir)
|
|
266
|
+
: auditGeneric(projectDir);
|
|
267
|
+
const totalScore = categories.reduce((s, c) => s + c.score, 0);
|
|
268
|
+
const maxScore = categories.reduce((s, c) => s + c.maxScore, 0);
|
|
269
|
+
return {
|
|
270
|
+
harness: detection.harness,
|
|
271
|
+
totalScore,
|
|
272
|
+
maxScore,
|
|
273
|
+
grade: computeGrade(totalScore, maxScore),
|
|
274
|
+
categories,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=harness-audit.js.map
|
package/dist/commands/init.d.ts
CHANGED