@kiwidata/grimoire 0.1.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/.claude-plugin/plugin.json +8 -0
- package/AGENTS.md +217 -0
- package/README.md +748 -0
- package/bin/grimoire.js +2 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +42 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/commands/archive.d.ts +3 -0
- package/dist/commands/archive.d.ts.map +1 -0
- package/dist/commands/archive.js +22 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/branch-check.d.ts +3 -0
- package/dist/commands/branch-check.d.ts.map +1 -0
- package/dist/commands/branch-check.js +16 -0
- package/dist/commands/branch-check.js.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +22 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/ci.d.ts +3 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +18 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/diff.d.ts +3 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +10 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/docs.d.ts +3 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +11 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/health.d.ts +3 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +13 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +21 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +22 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/log.d.ts +3 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +15 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/map.d.ts +3 -0
- package/dist/commands/map.d.ts.map +1 -0
- package/dist/commands/map.js +17 -0
- package/dist/commands/map.js.map +1 -0
- package/dist/commands/pr.d.ts +3 -0
- package/dist/commands/pr.d.ts.map +1 -0
- package/dist/commands/pr.js +17 -0
- package/dist/commands/pr.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +12 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/test-quality.d.ts +3 -0
- package/dist/commands/test-quality.d.ts.map +1 -0
- package/dist/commands/test-quality.js +37 -0
- package/dist/commands/test-quality.js.map +1 -0
- package/dist/commands/trace.d.ts +3 -0
- package/dist/commands/trace.d.ts.map +1 -0
- package/dist/commands/trace.js +12 -0
- package/dist/commands/trace.js.map +1 -0
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +22 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +17 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/core/archive.d.ts +9 -0
- package/dist/core/archive.d.ts.map +1 -0
- package/dist/core/archive.js +92 -0
- package/dist/core/archive.js.map +1 -0
- package/dist/core/branch-check.d.ts +27 -0
- package/dist/core/branch-check.d.ts.map +1 -0
- package/dist/core/branch-check.js +205 -0
- package/dist/core/branch-check.js.map +1 -0
- package/dist/core/check.d.ts +24 -0
- package/dist/core/check.d.ts.map +1 -0
- package/dist/core/check.js +372 -0
- package/dist/core/check.js.map +1 -0
- package/dist/core/ci.d.ts +24 -0
- package/dist/core/ci.d.ts.map +1 -0
- package/dist/core/ci.js +162 -0
- package/dist/core/ci.js.map +1 -0
- package/dist/core/detect.d.ts +10 -0
- package/dist/core/detect.d.ts.map +1 -0
- package/dist/core/detect.js +368 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/diff.d.ts +29 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/diff.js +197 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/doc-style.d.ts +16 -0
- package/dist/core/doc-style.d.ts.map +1 -0
- package/dist/core/doc-style.js +192 -0
- package/dist/core/doc-style.js.map +1 -0
- package/dist/core/docs.d.ts +6 -0
- package/dist/core/docs.d.ts.map +1 -0
- package/dist/core/docs.js +478 -0
- package/dist/core/docs.js.map +1 -0
- package/dist/core/health.d.ts +7 -0
- package/dist/core/health.d.ts.map +1 -0
- package/dist/core/health.js +489 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/hooks.d.ts +5 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +168 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/init.d.ts +9 -0
- package/dist/core/init.d.ts.map +1 -0
- package/dist/core/init.js +563 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/list.d.ts +4 -0
- package/dist/core/list.d.ts.map +1 -0
- package/dist/core/list.js +170 -0
- package/dist/core/list.js.map +1 -0
- package/dist/core/log.d.ts +8 -0
- package/dist/core/log.d.ts.map +1 -0
- package/dist/core/log.js +150 -0
- package/dist/core/log.js.map +1 -0
- package/dist/core/map.d.ts +9 -0
- package/dist/core/map.d.ts.map +1 -0
- package/dist/core/map.js +302 -0
- package/dist/core/map.js.map +1 -0
- package/dist/core/pr.d.ts +9 -0
- package/dist/core/pr.d.ts.map +1 -0
- package/dist/core/pr.js +273 -0
- package/dist/core/pr.js.map +1 -0
- package/dist/core/shared-setup.d.ts +52 -0
- package/dist/core/shared-setup.d.ts.map +1 -0
- package/dist/core/shared-setup.js +221 -0
- package/dist/core/shared-setup.js.map +1 -0
- package/dist/core/status.d.ts +6 -0
- package/dist/core/status.d.ts.map +1 -0
- package/dist/core/status.js +114 -0
- package/dist/core/status.js.map +1 -0
- package/dist/core/test-quality.d.ts +33 -0
- package/dist/core/test-quality.d.ts.map +1 -0
- package/dist/core/test-quality.js +378 -0
- package/dist/core/test-quality.js.map +1 -0
- package/dist/core/trace.d.ts +6 -0
- package/dist/core/trace.d.ts.map +1 -0
- package/dist/core/trace.js +211 -0
- package/dist/core/trace.js.map +1 -0
- package/dist/core/update.d.ts +10 -0
- package/dist/core/update.d.ts.map +1 -0
- package/dist/core/update.js +149 -0
- package/dist/core/update.js.map +1 -0
- package/dist/core/validate.d.ts +20 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +275 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/config.d.ts +61 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +172 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/fs.d.ts +17 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +38 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/paths.d.ts +10 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +35 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/spawn.d.ts +5 -0
- package/dist/utils/spawn.d.ts.map +1 -0
- package/dist/utils/spawn.js +34 -0
- package/dist/utils/spawn.js.map +1 -0
- package/package.json +68 -0
- package/skills/grimoire-apply/SKILL.md +274 -0
- package/skills/grimoire-audit/SKILL.md +129 -0
- package/skills/grimoire-branch-guard/SKILL.md +111 -0
- package/skills/grimoire-bug/SKILL.md +160 -0
- package/skills/grimoire-bug-explore/SKILL.md +242 -0
- package/skills/grimoire-bug-report/SKILL.md +237 -0
- package/skills/grimoire-bug-session/SKILL.md +222 -0
- package/skills/grimoire-bug-triage/SKILL.md +274 -0
- package/skills/grimoire-commit/SKILL.md +150 -0
- package/skills/grimoire-discover/SKILL.md +297 -0
- package/skills/grimoire-draft/SKILL.md +202 -0
- package/skills/grimoire-plan/SKILL.md +329 -0
- package/skills/grimoire-pr/SKILL.md +134 -0
- package/skills/grimoire-pr-review/SKILL.md +240 -0
- package/skills/grimoire-refactor/SKILL.md +251 -0
- package/skills/grimoire-remove/SKILL.md +112 -0
- package/skills/grimoire-review/SKILL.md +247 -0
- package/skills/grimoire-verify/SKILL.md +223 -0
- package/skills/references/bug-classification.md +154 -0
- package/skills/references/build-vs-buy.md +77 -0
- package/skills/references/elicitation-personas.md +118 -0
- package/skills/references/refactor-register-format.md +88 -0
- package/skills/references/refactor-scan-categories.md +102 -0
- package/skills/references/schema-format.md +68 -0
- package/skills/references/security-compliance.md +110 -0
- package/skills/references/testing-contracts.md +93 -0
- package/templates/context.yml +110 -0
- package/templates/debt-exceptions.yml +61 -0
- package/templates/decision.md +50 -0
- package/templates/dupignore +93 -0
- package/templates/example.feature +24 -0
- package/templates/manifest.md +29 -0
- package/templates/mapignore +58 -0
- package/templates/mapkeys +65 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { writeFile, unlink } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { execFile } from "node:child_process";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import { simpleGit } from "simple-git";
|
|
9
|
+
import fg from "fast-glob";
|
|
10
|
+
import { loadConfig } from "../utils/config.js";
|
|
11
|
+
import { findProjectRoot } from "../utils/paths.js";
|
|
12
|
+
import { spawnWithStdin } from "../utils/spawn.js";
|
|
13
|
+
import { analyzeTestQuality, TEST_FILE_GLOBS, TEST_FILE_IGNORE } from "./test-quality.js";
|
|
14
|
+
import { checkDocStyle } from "./doc-style.js";
|
|
15
|
+
const execFileAsync = promisify(execFile);
|
|
16
|
+
export async function runCheck(options) {
|
|
17
|
+
const root = await findProjectRoot();
|
|
18
|
+
const config = await loadConfig(root);
|
|
19
|
+
// Determine which steps to run
|
|
20
|
+
let steps = options.steps?.length ? options.steps : config.checks;
|
|
21
|
+
if (options.skip?.length) {
|
|
22
|
+
const skipSet = new Set(options.skip);
|
|
23
|
+
steps = steps.filter((s) => !skipSet.has(s));
|
|
24
|
+
}
|
|
25
|
+
const results = [];
|
|
26
|
+
if (!options.json) {
|
|
27
|
+
console.log(chalk.bold("\ngrimoire check\n"));
|
|
28
|
+
}
|
|
29
|
+
for (const step of steps) {
|
|
30
|
+
const result = await runStep(step, root, config, options);
|
|
31
|
+
results.push(result);
|
|
32
|
+
if (!options.json)
|
|
33
|
+
printStepResult(result);
|
|
34
|
+
if (result.status === "fail" && !options.continueOnFail)
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
// Summary
|
|
38
|
+
const passed = results.filter((r) => r.status === "pass").length;
|
|
39
|
+
const failedCount = results.filter((r) => r.status === "fail").length;
|
|
40
|
+
const skipped = results.filter((r) => r.status === "skip").length;
|
|
41
|
+
const errored = results.filter((r) => r.status === "error").length;
|
|
42
|
+
if (options.json) {
|
|
43
|
+
console.log(JSON.stringify({
|
|
44
|
+
results,
|
|
45
|
+
summary: { passed, failed: failedCount, skipped, errored },
|
|
46
|
+
}, null, 2));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.log(`\n ${chalk.green(`${passed} passed`)}, ${failedCount > 0 ? chalk.red(`${failedCount} failed`) : `${failedCount} failed`}, ${skipped} skipped${errored > 0 ? `, ${errored} errored` : ""}\n`);
|
|
50
|
+
}
|
|
51
|
+
return { results, passed, failed: failedCount, skipped, errored };
|
|
52
|
+
}
|
|
53
|
+
async function runStep(step, root, config, options) {
|
|
54
|
+
if (step === "test_quality")
|
|
55
|
+
return runTestQualityStep(root);
|
|
56
|
+
if (step === "doc_style")
|
|
57
|
+
return runDocStyleStep(root, config);
|
|
58
|
+
// Complexity: use built-in auto-detect unless an explicit tool is configured
|
|
59
|
+
if (step === "complexity" && !config.tools[step]?.command && !config.tools[step]?.check_command) {
|
|
60
|
+
return runComplexityStep(root, config);
|
|
61
|
+
}
|
|
62
|
+
const tool = config.tools[step] ?? getBuiltinLlmFallback(step);
|
|
63
|
+
if (!tool || (!tool.command && !tool.check_command && tool.name !== "llm")) {
|
|
64
|
+
return { step, status: "skip", duration: 0, output: "", reason: "not configured" };
|
|
65
|
+
}
|
|
66
|
+
if (tool.name === "llm") {
|
|
67
|
+
return runLlmStep(step, tool.prompt ?? "", config.llm.coding.command, root, options.changed);
|
|
68
|
+
}
|
|
69
|
+
const command = tool.check_command ?? tool.command;
|
|
70
|
+
return runShellStep(step, command, root);
|
|
71
|
+
}
|
|
72
|
+
async function runShellStep(step, command, root) {
|
|
73
|
+
const start = Date.now();
|
|
74
|
+
try {
|
|
75
|
+
const { stdout, stderr } = await execFileAsync("sh", ["-c", command], {
|
|
76
|
+
cwd: root,
|
|
77
|
+
timeout: 300_000,
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
step,
|
|
81
|
+
status: "pass",
|
|
82
|
+
duration: Date.now() - start,
|
|
83
|
+
output: (stdout + stderr).trim(),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
const duration = Date.now() - start;
|
|
88
|
+
if (err && typeof err === "object" && "stdout" in err) {
|
|
89
|
+
const execErr = err;
|
|
90
|
+
return {
|
|
91
|
+
step,
|
|
92
|
+
status: "fail",
|
|
93
|
+
duration,
|
|
94
|
+
output: (execErr.stdout + execErr.stderr).trim(),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
step,
|
|
99
|
+
status: "error",
|
|
100
|
+
duration,
|
|
101
|
+
output: err instanceof Error ? err.message : String(err),
|
|
102
|
+
reason: "command failed to execute",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function runLlmStep(step, prompt, llmCommand, root, changedOnly) {
|
|
107
|
+
const start = Date.now();
|
|
108
|
+
// Check if LLM command is available
|
|
109
|
+
try {
|
|
110
|
+
await execFileAsync("which", [llmCommand]);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return {
|
|
114
|
+
step,
|
|
115
|
+
status: "skip",
|
|
116
|
+
duration: Date.now() - start,
|
|
117
|
+
output: "",
|
|
118
|
+
reason: `${llmCommand} not found`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// Get changed files
|
|
122
|
+
let files = [];
|
|
123
|
+
if (changedOnly) {
|
|
124
|
+
try {
|
|
125
|
+
const git = simpleGit(root);
|
|
126
|
+
const diffOutput = await git.diff(["--name-only", "HEAD"]);
|
|
127
|
+
files = diffOutput.trim().split("\n").filter(Boolean);
|
|
128
|
+
if (files.length === 0) {
|
|
129
|
+
// Try staged files
|
|
130
|
+
const staged = await git.diff(["--name-only", "--cached"]);
|
|
131
|
+
files = staged.trim().split("\n").filter(Boolean);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Not a git repo or no changes
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (changedOnly && files.length === 0) {
|
|
139
|
+
return {
|
|
140
|
+
step,
|
|
141
|
+
status: "pass",
|
|
142
|
+
duration: Date.now() - start,
|
|
143
|
+
output: "No changed files to review.",
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
const fileList = files.length > 0 ? `\n\nFiles to review:\n${files.join("\n")}` : "";
|
|
147
|
+
const fullPrompt = `${prompt}${fileList}\n\nRespond with PASS if no issues found, or FAIL followed by the issues.`;
|
|
148
|
+
const tmpFile = join(tmpdir(), `grimoire-prompt-${randomUUID()}.txt`);
|
|
149
|
+
try {
|
|
150
|
+
await writeFile(tmpFile, fullPrompt);
|
|
151
|
+
const output = await spawnWithStdin(llmCommand, ["--print"], fullPrompt, root);
|
|
152
|
+
const passed = output.toUpperCase().startsWith("PASS");
|
|
153
|
+
return {
|
|
154
|
+
step,
|
|
155
|
+
status: passed ? "pass" : "fail",
|
|
156
|
+
duration: Date.now() - start,
|
|
157
|
+
output,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
return {
|
|
162
|
+
step,
|
|
163
|
+
status: "error",
|
|
164
|
+
duration: Date.now() - start,
|
|
165
|
+
output: err instanceof Error ? err.message : String(err),
|
|
166
|
+
reason: "LLM command failed",
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
await unlink(tmpFile).catch(() => { });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const BUILTIN_LLM_FALLBACKS = {
|
|
174
|
+
security: {
|
|
175
|
+
name: "llm",
|
|
176
|
+
prompt: `Review these changed files for security vulnerabilities. For each finding:
|
|
177
|
+
1. Describe the vulnerability
|
|
178
|
+
2. Tag it with the relevant OWASP Top 10 category (e.g., A01:2021-Broken Access Control) and CWE ID (e.g., CWE-89)
|
|
179
|
+
3. Rate severity: critical / high / medium / low
|
|
180
|
+
|
|
181
|
+
Check specifically for:
|
|
182
|
+
- SQL injection (CWE-89) — string concatenation in queries instead of parameterized queries
|
|
183
|
+
- XSS (CWE-79) — unescaped user input in HTML/template output
|
|
184
|
+
- Broken authentication (CWE-287) — custom token generation, weak session management, missing auth checks
|
|
185
|
+
- Insecure cryptography (CWE-327) — MD5/SHA1 for passwords, custom crypto, weak random
|
|
186
|
+
- SSRF (CWE-918) — user-controlled URLs in server-side requests
|
|
187
|
+
- Path traversal (CWE-22) — user input in file paths without sanitization
|
|
188
|
+
- Insecure deserialization (CWE-502) — pickle.loads, yaml.load without SafeLoader, eval()
|
|
189
|
+
- Missing access control (CWE-862) — endpoints without authorization checks
|
|
190
|
+
- CSRF (CWE-352) — state-changing endpoints without CSRF tokens
|
|
191
|
+
- Hardcoded secrets (CWE-798) — API keys, passwords, tokens in source code`,
|
|
192
|
+
},
|
|
193
|
+
dep_audit: {
|
|
194
|
+
name: "llm",
|
|
195
|
+
prompt: `Review these changed files for newly added dependencies or imports. For each finding:
|
|
196
|
+
1. Verify the package name is real and correctly spelled — flag potential typosquatting (e.g., 'reqeusts' instead of 'requests', 'lodash-utils' instead of 'lodash')
|
|
197
|
+
2. Flag packages you cannot verify as real published packages
|
|
198
|
+
3. Flag packages with known security advisories if you are aware of them
|
|
199
|
+
4. Tag supply chain risks with CWE-1357 (Reliance on Insufficiently Trustworthy Component)`,
|
|
200
|
+
},
|
|
201
|
+
secrets: {
|
|
202
|
+
name: "llm",
|
|
203
|
+
prompt: `Review these changed files for hardcoded secrets, API keys, passwords, tokens, private keys, or credentials.
|
|
204
|
+
Tag findings with CWE-798 (Use of Hard-coded Credentials) or CWE-312 (Cleartext Storage of Sensitive Information).
|
|
205
|
+
Flag any string that looks like a secret value rather than a placeholder or environment variable reference.
|
|
206
|
+
Check for: API keys, database connection strings, JWT secrets, private keys, OAuth client secrets, webhook URLs with tokens.`,
|
|
207
|
+
},
|
|
208
|
+
best_practices: {
|
|
209
|
+
name: "llm",
|
|
210
|
+
prompt: "Review these changed files for best practices violations",
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
function getBuiltinLlmFallback(step) {
|
|
214
|
+
return BUILTIN_LLM_FALLBACKS[step];
|
|
215
|
+
}
|
|
216
|
+
function printStepResult(result) {
|
|
217
|
+
const duration = `(${(result.duration / 1000).toFixed(1)}s)`;
|
|
218
|
+
const stepName = result.step.padEnd(16);
|
|
219
|
+
switch (result.status) {
|
|
220
|
+
case "pass":
|
|
221
|
+
console.log(` ${stepName} ${chalk.green("✓ passed")} ${chalk.dim(duration)}`);
|
|
222
|
+
break;
|
|
223
|
+
case "fail":
|
|
224
|
+
console.log(` ${stepName} ${chalk.red("✗ failed")} ${chalk.dim(duration)}`);
|
|
225
|
+
if (result.output) {
|
|
226
|
+
const lines = result.output.split("\n").slice(0, 5);
|
|
227
|
+
for (const line of lines) {
|
|
228
|
+
console.log(` ${chalk.dim("→")} ${line}`);
|
|
229
|
+
}
|
|
230
|
+
if (result.output.split("\n").length > 5) {
|
|
231
|
+
console.log(chalk.dim(" ... (truncated)"));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
case "skip":
|
|
236
|
+
console.log(` ${stepName} ${chalk.dim("○ skipped")} ${chalk.dim(result.reason ?? "")}`);
|
|
237
|
+
break;
|
|
238
|
+
case "error":
|
|
239
|
+
console.log(` ${stepName} ${chalk.yellow("! error")} ${chalk.dim(result.reason ?? result.output)}`);
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async function runTestQualityStep(root) {
|
|
244
|
+
const start = Date.now();
|
|
245
|
+
try {
|
|
246
|
+
const filePaths = await fg(TEST_FILE_GLOBS, {
|
|
247
|
+
cwd: root,
|
|
248
|
+
absolute: true,
|
|
249
|
+
ignore: TEST_FILE_IGNORE,
|
|
250
|
+
});
|
|
251
|
+
if (filePaths.length === 0) {
|
|
252
|
+
return { step: "test_quality", status: "pass", duration: Date.now() - start, output: "No test files found." };
|
|
253
|
+
}
|
|
254
|
+
const report = await analyzeTestQuality(filePaths);
|
|
255
|
+
const output = report.issues.length === 0
|
|
256
|
+
? `${report.functions} test functions analyzed — no issues found.`
|
|
257
|
+
: report.issues.map(i => `${i.file}:${i.line} [${i.rule}] ${i.message}`).join("\n");
|
|
258
|
+
return {
|
|
259
|
+
step: "test_quality",
|
|
260
|
+
status: report.summary.critical > 0 ? "fail" : "pass",
|
|
261
|
+
duration: Date.now() - start,
|
|
262
|
+
output,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
return {
|
|
267
|
+
step: "test_quality",
|
|
268
|
+
status: "error",
|
|
269
|
+
duration: Date.now() - start,
|
|
270
|
+
output: err instanceof Error ? err.message : String(err),
|
|
271
|
+
reason: "test quality analysis failed",
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async function runDocStyleStep(root, config) {
|
|
276
|
+
const start = Date.now();
|
|
277
|
+
const style = config.project.comment_style;
|
|
278
|
+
if (!style) {
|
|
279
|
+
return {
|
|
280
|
+
step: "doc_style",
|
|
281
|
+
status: "skip",
|
|
282
|
+
duration: Date.now() - start,
|
|
283
|
+
output: "",
|
|
284
|
+
reason: "no comment_style configured",
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
try {
|
|
288
|
+
const report = await checkDocStyle(root, style, config.project.language);
|
|
289
|
+
const output = report.issues.length === 0
|
|
290
|
+
? `${report.filesChecked} files checked — all match ${style} style.`
|
|
291
|
+
: report.issues.map(i => `${i.file}:${i.line} ${i.message}`).join("\n");
|
|
292
|
+
return {
|
|
293
|
+
step: "doc_style",
|
|
294
|
+
status: report.issues.some(i => i.severity === "critical") ? "fail" : "pass",
|
|
295
|
+
duration: Date.now() - start,
|
|
296
|
+
output,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
catch (err) {
|
|
300
|
+
return {
|
|
301
|
+
step: "doc_style",
|
|
302
|
+
status: "error",
|
|
303
|
+
duration: Date.now() - start,
|
|
304
|
+
output: err instanceof Error ? err.message : String(err),
|
|
305
|
+
reason: "doc style check failed",
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
async function tryRadon(root) {
|
|
310
|
+
try {
|
|
311
|
+
await execFileAsync("which", ["radon"]);
|
|
312
|
+
const { stdout, stderr } = await execFileAsync("sh", [
|
|
313
|
+
"-c",
|
|
314
|
+
"radon cc . -a -nc --exclude 'node_modules,.venv,dist,migrations' 2>&1 || true",
|
|
315
|
+
], { cwd: root, timeout: 60_000 });
|
|
316
|
+
const output = (stdout + stderr).trim();
|
|
317
|
+
const hasHighComplexity = /\b[C-F]\s+\(\d+\)/.test(output) || /\b[C-F]\b/.test(output);
|
|
318
|
+
return { output, hasHighComplexity };
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
async function tryEslintComplexity(root) {
|
|
325
|
+
try {
|
|
326
|
+
await execFileAsync("which", ["npx"]);
|
|
327
|
+
const { stdout, stderr } = await execFileAsync("sh", [
|
|
328
|
+
"-c",
|
|
329
|
+
"npx eslint --no-eslintrc --rule 'complexity: [warn, 10]' --ext .ts,.tsx,.js,.jsx src/ 2>&1 || true",
|
|
330
|
+
], { cwd: root, timeout: 60_000 });
|
|
331
|
+
const output = (stdout + stderr).trim();
|
|
332
|
+
const hasWarnings = output.includes("warning") || output.includes("error");
|
|
333
|
+
return { output, hasWarnings };
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
async function runComplexityStep(root, config) {
|
|
340
|
+
const start = Date.now();
|
|
341
|
+
const lang = config.project.language;
|
|
342
|
+
if (!lang || lang === "python") {
|
|
343
|
+
const radon = await tryRadon(root);
|
|
344
|
+
if (radon) {
|
|
345
|
+
return {
|
|
346
|
+
step: "complexity",
|
|
347
|
+
status: radon.hasHighComplexity ? "fail" : "pass",
|
|
348
|
+
duration: Date.now() - start,
|
|
349
|
+
output: radon.output || "No high-complexity functions found.",
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (!lang || ["typescript", "javascript"].includes(lang ?? "")) {
|
|
354
|
+
const eslint = await tryEslintComplexity(root);
|
|
355
|
+
if (eslint) {
|
|
356
|
+
return {
|
|
357
|
+
step: "complexity",
|
|
358
|
+
status: eslint.hasWarnings ? "fail" : "pass",
|
|
359
|
+
duration: Date.now() - start,
|
|
360
|
+
output: eslint.output || "No high-complexity functions found.",
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return {
|
|
365
|
+
step: "complexity",
|
|
366
|
+
status: "skip",
|
|
367
|
+
duration: Date.now() - start,
|
|
368
|
+
output: "",
|
|
369
|
+
reason: "no complexity tool found (install radon for Python or eslint for JS/TS)",
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/core/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface CiOptions {
|
|
2
|
+
annotations: boolean;
|
|
3
|
+
skip?: string[];
|
|
4
|
+
setup: boolean;
|
|
5
|
+
}
|
|
6
|
+
interface CiResult {
|
|
7
|
+
validate: {
|
|
8
|
+
errors: number;
|
|
9
|
+
warnings: number;
|
|
10
|
+
};
|
|
11
|
+
check: {
|
|
12
|
+
passed: number;
|
|
13
|
+
failed: number;
|
|
14
|
+
errored: number;
|
|
15
|
+
};
|
|
16
|
+
testQuality: {
|
|
17
|
+
critical: number;
|
|
18
|
+
warning: number;
|
|
19
|
+
};
|
|
20
|
+
exitCode: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function runCi(options: CiOptions): Promise<CiResult>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=ci.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../src/core/ci.ts"],"names":[],"mappings":"AASA,UAAU,SAAS;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,UAAU,QAAQ;IAChB,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,WAAW,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2HjE"}
|
package/dist/core/ci.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { findProjectRoot } from "../utils/paths.js";
|
|
5
|
+
import { validateChange } from "./validate.js";
|
|
6
|
+
import { runCheck } from "./check.js";
|
|
7
|
+
import { analyzeTestQuality } from "./test-quality.js";
|
|
8
|
+
import { fileExists } from "../utils/fs.js";
|
|
9
|
+
export async function runCi(options) {
|
|
10
|
+
if (options.setup) {
|
|
11
|
+
await generateWorkflow();
|
|
12
|
+
return { validate: { errors: 0, warnings: 0 }, check: { passed: 0, failed: 0, errored: 0 }, testQuality: { critical: 0, warning: 0 }, exitCode: 0 };
|
|
13
|
+
}
|
|
14
|
+
const isGha = options.annotations || !!process.env.GITHUB_ACTIONS;
|
|
15
|
+
if (!isGha) {
|
|
16
|
+
console.log(chalk.bold("\ngrimoire ci\n"));
|
|
17
|
+
}
|
|
18
|
+
// 1. Validate specs
|
|
19
|
+
if (!isGha) {
|
|
20
|
+
console.log(chalk.bold("── Validate specs ──\n"));
|
|
21
|
+
}
|
|
22
|
+
const validateResult = await validateChange(undefined, {
|
|
23
|
+
strict: false,
|
|
24
|
+
json: isGha,
|
|
25
|
+
});
|
|
26
|
+
if (isGha) {
|
|
27
|
+
for (const r of validateResult.results) {
|
|
28
|
+
for (const err of r.errors) {
|
|
29
|
+
console.log(`::error file=${escapeGhaProp(r.file)}::${escapeGhaMsg(err)}`);
|
|
30
|
+
}
|
|
31
|
+
for (const warn of r.warnings) {
|
|
32
|
+
console.log(`::warning file=${escapeGhaProp(r.file)}::${escapeGhaMsg(warn)}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// 2. Run checks (skip steps if requested)
|
|
37
|
+
if (!isGha) {
|
|
38
|
+
console.log(chalk.bold("\n── Run checks ──\n"));
|
|
39
|
+
}
|
|
40
|
+
const checkResult = await runCheck({
|
|
41
|
+
continueOnFail: true,
|
|
42
|
+
changed: true,
|
|
43
|
+
skip: options.skip,
|
|
44
|
+
json: isGha,
|
|
45
|
+
});
|
|
46
|
+
if (isGha) {
|
|
47
|
+
for (const r of checkResult.results) {
|
|
48
|
+
if (r.status === "fail") {
|
|
49
|
+
console.log(`::error title=${escapeGhaProp(r.step)}::${escapeGhaMsg(r.output.split("\n")[0])}`);
|
|
50
|
+
}
|
|
51
|
+
else if (r.status === "error") {
|
|
52
|
+
console.log(`::error title=${escapeGhaProp(r.step)}::${escapeGhaMsg(r.reason ?? r.output)}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// 3. Test quality analysis
|
|
57
|
+
if (!isGha) {
|
|
58
|
+
console.log(chalk.bold("\n── Test quality ──\n"));
|
|
59
|
+
}
|
|
60
|
+
let testQualityCritical = 0;
|
|
61
|
+
let testQualityWarning = 0;
|
|
62
|
+
try {
|
|
63
|
+
const root = await findProjectRoot();
|
|
64
|
+
const glob = (await import("fast-glob")).default;
|
|
65
|
+
const testFiles = await glob(["**/*.test.ts", "**/*.test.js", "**/*.spec.ts", "**/*.spec.js", "**/test_*.py", "**/*_test.py"], { cwd: root, absolute: true, ignore: ["**/node_modules/**"] });
|
|
66
|
+
if (testFiles.length > 0) {
|
|
67
|
+
const report = await analyzeTestQuality(testFiles);
|
|
68
|
+
testQualityCritical = report.summary.critical;
|
|
69
|
+
testQualityWarning = report.summary.warning;
|
|
70
|
+
if (isGha) {
|
|
71
|
+
for (const issue of report.issues) {
|
|
72
|
+
const level = issue.severity === "critical" ? "error" : "warning";
|
|
73
|
+
console.log(`::${level} file=${escapeGhaProp(issue.file)},line=${issue.line}::${escapeGhaMsg(issue.message)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
if (report.issues.length === 0) {
|
|
78
|
+
console.log(chalk.green(" No test quality issues found."));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log(` ${report.summary.critical} critical, ${report.summary.warning} warnings`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
if (!isGha) {
|
|
87
|
+
console.log(chalk.dim(" No test files found."));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
if (!isGha) {
|
|
93
|
+
console.log(chalk.dim(" Test quality analysis skipped."));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Summary
|
|
97
|
+
const hasFailures = validateResult.errorCount > 0 ||
|
|
98
|
+
checkResult.failed > 0 ||
|
|
99
|
+
checkResult.errored > 0 ||
|
|
100
|
+
testQualityCritical > 0;
|
|
101
|
+
const exitCode = hasFailures ? 1 : 0;
|
|
102
|
+
if (!isGha) {
|
|
103
|
+
console.log(chalk.bold("\n── Summary ──\n"));
|
|
104
|
+
const icon = hasFailures ? chalk.red("✗") : chalk.green("✓");
|
|
105
|
+
console.log(` ${icon} Validate: ${validateResult.errorCount} errors, ${validateResult.warnCount} warnings`);
|
|
106
|
+
console.log(` ${icon} Checks: ${checkResult.passed} passed, ${checkResult.failed} failed`);
|
|
107
|
+
console.log(` ${icon} Test quality: ${testQualityCritical} critical, ${testQualityWarning} warnings`);
|
|
108
|
+
console.log();
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
validate: { errors: validateResult.errorCount, warnings: validateResult.warnCount },
|
|
112
|
+
check: { passed: checkResult.passed, failed: checkResult.failed, errored: checkResult.errored },
|
|
113
|
+
testQuality: { critical: testQualityCritical, warning: testQualityWarning },
|
|
114
|
+
exitCode,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function generateWorkflow() {
|
|
118
|
+
const root = await findProjectRoot();
|
|
119
|
+
const workflowDir = join(root, ".github", "workflows");
|
|
120
|
+
const workflowPath = join(workflowDir, "grimoire.yml");
|
|
121
|
+
if (await fileExists(workflowPath)) {
|
|
122
|
+
console.log(chalk.yellow(" .github/workflows/grimoire.yml already exists."));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
await mkdir(workflowDir, { recursive: true });
|
|
126
|
+
const workflow = `name: Grimoire CI
|
|
127
|
+
|
|
128
|
+
on:
|
|
129
|
+
pull_request:
|
|
130
|
+
paths:
|
|
131
|
+
- 'features/**'
|
|
132
|
+
- '.grimoire/**'
|
|
133
|
+
- 'src/**'
|
|
134
|
+
- 'tests/**'
|
|
135
|
+
|
|
136
|
+
jobs:
|
|
137
|
+
grimoire:
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
steps:
|
|
140
|
+
- uses: actions/checkout@v4
|
|
141
|
+
|
|
142
|
+
- uses: actions/setup-node@v4
|
|
143
|
+
with:
|
|
144
|
+
node-version: '20'
|
|
145
|
+
|
|
146
|
+
- run: npm ci
|
|
147
|
+
|
|
148
|
+
- name: Grimoire CI
|
|
149
|
+
run: npx grimoire ci --annotations
|
|
150
|
+
`;
|
|
151
|
+
await writeFile(workflowPath, workflow);
|
|
152
|
+
console.log(chalk.green(" Created .github/workflows/grimoire.yml"));
|
|
153
|
+
}
|
|
154
|
+
/** Escape a value for GHA workflow command properties (file, title, etc.) */
|
|
155
|
+
function escapeGhaProp(s) {
|
|
156
|
+
return s.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A").replace(/:/g, "%3A").replace(/,/g, "%2C");
|
|
157
|
+
}
|
|
158
|
+
/** Escape a value for GHA workflow command messages */
|
|
159
|
+
function escapeGhaMsg(s) {
|
|
160
|
+
return s.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=ci.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.js","sourceRoot":"","sources":["../../src/core/ci.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface Detection {
|
|
2
|
+
category: string;
|
|
3
|
+
name: string;
|
|
4
|
+
confidence: "high" | "medium" | "low";
|
|
5
|
+
signal: string;
|
|
6
|
+
command?: string;
|
|
7
|
+
check_command?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function detectTools(root: string): Promise<Detection[]>;
|
|
10
|
+
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/core/detect.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA6CD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CA0BpE"}
|