fchek 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -0
- package/bin/fchek.js +107 -0
- package/lib/api.js +110 -0
- package/lib/audit.js +211 -0
- package/lib/bench.js +248 -0
- package/lib/config.js +191 -0
- package/lib/context.js +356 -0
- package/lib/convention.js +526 -0
- package/lib/coverage.js +604 -0
- package/lib/db.js +135 -0
- package/lib/deps-check.js +264 -0
- package/lib/deps.js +374 -0
- package/lib/docker.js +84 -0
- package/lib/doctor.js +149 -0
- package/lib/dom.js +226 -0
- package/lib/fuzz.js +470 -0
- package/lib/git.js +290 -0
- package/lib/goto.js +544 -0
- package/lib/launch.js +182 -0
- package/lib/lint.js +624 -0
- package/lib/new_features.test.js +181 -0
- package/lib/output.js +46 -0
- package/lib/port.js +173 -0
- package/lib/process.js +228 -0
- package/lib/profile.js +453 -0
- package/lib/python.js +41 -0
- package/lib/race.js +186 -0
- package/lib/registry.js +179 -0
- package/lib/repl.js +135 -0
- package/lib/run.js +403 -0
- package/lib/screenshot.js +152 -0
- package/lib/secrets.js +257 -0
- package/lib/state.js +219 -0
- package/lib/test.js +471 -0
- package/lib/vuln.js +253 -0
- package/lib/watch.js +240 -0
- package/lib/winlog.js +123 -0
- package/package.json +27 -0
- package/skills/ACTIVATE.md +274 -0
- package/skills/README.md +163 -0
- package/skills/agent.md +444 -0
- package/skills/api.md +47 -0
- package/skills/bench.md +117 -0
- package/skills/context.md +116 -0
- package/skills/convention.md +143 -0
- package/skills/coverage.md +99 -0
- package/skills/csharp.md +97 -0
- package/skills/db.md +66 -0
- package/skills/deps-check.md +135 -0
- package/skills/deps.md +143 -0
- package/skills/docker.md +61 -0
- package/skills/dom.md +56 -0
- package/skills/fuzz.md +167 -0
- package/skills/goto.md +111 -0
- package/skills/lint.md +123 -0
- package/skills/port.md +57 -0
- package/skills/profile.md +91 -0
- package/skills/race.md +117 -0
- package/skills/repl.md +81 -0
- package/skills/rules.md +318 -0
- package/skills/run.md +135 -0
- package/skills/secrets.md +170 -0
- package/skills/security.md +360 -0
- package/skills/state.md +261 -0
- package/skills/vuln.md +57 -0
- package/skills/windows.md +320 -0
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# fchek — Developer & AI Autonomous Toolbox
|
|
2
|
+
|
|
3
|
+
`fchek` is a command-line toolbox designed for developers and AI agents to run code, verify tests, check network ports, query databases, audit container health, profile performance, and manage codebases efficiently.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g .
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Verify with:
|
|
14
|
+
```bash
|
|
15
|
+
fchek --help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## All Commands
|
|
21
|
+
|
|
22
|
+
### Full Automation
|
|
23
|
+
* `fchek audit [dir]` — Full audit: context + secrets + lint + test + deps in one run.
|
|
24
|
+
* `fchek test [dir]` — Auto-detect test framework (pytest, jest, vitest, mocha, cargo, go, dotnet) and run tests.
|
|
25
|
+
* `fchek git <action>` — Safe git operations (status, diff, stage, commit, etc.).
|
|
26
|
+
* `fchek config [action]` — Read or write `.fchekrc` config.
|
|
27
|
+
|
|
28
|
+
### Code Intelligence (Before Code)
|
|
29
|
+
* `fchek context <dir>` — Dump all symbols to avoid duplicates.
|
|
30
|
+
* `fchek convention <dir>` — Analyze coding patterns (style, error handling, logging).
|
|
31
|
+
* `fchek deps-check <lib>` — Live API registry checking.
|
|
32
|
+
|
|
33
|
+
### Execute & Verify (After Code)
|
|
34
|
+
* `fchek run <file>` — Execute file and get structured JSON stdout/stderr/exit_code.
|
|
35
|
+
* `fchek secrets <path>` — Scan for credentials (gitleaks, trufflehog, or regex).
|
|
36
|
+
* `fchek vuln [dir]` — Scan dependencies for vulnerabilities and typosquatting.
|
|
37
|
+
* `fchek dom <url|file> <selector>` — Query HTML page elements using CSS selectors.
|
|
38
|
+
|
|
39
|
+
### Network & Databases
|
|
40
|
+
* `fchek port <port> [--all]` — Network port inspector (checks if a port is in use and returns the process PID & name).
|
|
41
|
+
* `fchek api <url> [options]` — HTTP API tester with status codes, headers, and timing metrics.
|
|
42
|
+
* `fchek db <action> <db_path> [sql]` — SQLite schema inspector (`schema`) and query runner (`query`).
|
|
43
|
+
* `fchek docker <action> [options]` — Docker assistant: lists containers (`list`) or gets logs (`logs`).
|
|
44
|
+
|
|
45
|
+
### Windows Integration
|
|
46
|
+
* `fchek screenshot [--window=<title>]` — Screenshot window or desktop.
|
|
47
|
+
* `fchek launch <exe>` — Launch application and wait for window creation.
|
|
48
|
+
* `fchek winlog` — Get Windows event logs.
|
|
49
|
+
* `fchek registry <action>` — Query or modify Windows Registry.
|
|
50
|
+
* `fchek process <action>` — Manage processes.
|
|
51
|
+
* `fchek watch <dir>` — Watch directory, rebuild, and relaunch on modification.
|
|
52
|
+
|
|
53
|
+
### Analysis & Memory
|
|
54
|
+
* `fchek profile <file>` — Hot path profiling.
|
|
55
|
+
* `fchek coverage <dir>` — Code coverage reports.
|
|
56
|
+
* `fchek bench --before --after` — Benchmark code speedups.
|
|
57
|
+
* `fchek lint <dir>` — Code format and linter with auto-fixing.
|
|
58
|
+
* `fchek deps <dir>` — Identify dead code/circular dependencies.
|
|
59
|
+
* `fchek race <file>` — ThreadSanitizer/AddressSanitizer checks.
|
|
60
|
+
* `fchek fuzz <file>` — AFL++/cargo-fuzz runner.
|
|
61
|
+
* `fchek goto <file:line>` — Navigation & references.
|
|
62
|
+
* `fchek state <action>` — Persistent project memory.
|
|
63
|
+
* `fchek repl` — Interactive REPL with session variables.
|
|
64
|
+
* `fchek doctor` — Verify local environment & dependencies.
|
package/bin/fchek.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const COMMANDS = {
|
|
6
|
+
context: () => require('../lib/context'),
|
|
7
|
+
convention: () => require('../lib/convention'),
|
|
8
|
+
'deps-check': () => require('../lib/deps-check'),
|
|
9
|
+
run: () => require('../lib/run'),
|
|
10
|
+
test: () => require('../lib/test'),
|
|
11
|
+
secrets: () => require('../lib/secrets'),
|
|
12
|
+
audit: () => require('../lib/audit'),
|
|
13
|
+
git: () => require('../lib/git'),
|
|
14
|
+
config: () => require('../lib/config'),
|
|
15
|
+
screenshot: () => require('../lib/screenshot'),
|
|
16
|
+
launch: () => require('../lib/launch'),
|
|
17
|
+
winlog: () => require('../lib/winlog'),
|
|
18
|
+
registry: () => require('../lib/registry'),
|
|
19
|
+
process: () => require('../lib/process'),
|
|
20
|
+
watch: () => require('../lib/watch'),
|
|
21
|
+
profile: () => require('../lib/profile'),
|
|
22
|
+
coverage: () => require('../lib/coverage'),
|
|
23
|
+
bench: () => require('../lib/bench'),
|
|
24
|
+
lint: () => require('../lib/lint'),
|
|
25
|
+
deps: () => require('../lib/deps'),
|
|
26
|
+
race: () => require('../lib/race'),
|
|
27
|
+
fuzz: () => require('../lib/fuzz'),
|
|
28
|
+
goto: () => require('../lib/goto'),
|
|
29
|
+
state: () => require('../lib/state'),
|
|
30
|
+
repl: () => require('../lib/repl'),
|
|
31
|
+
doctor: () => require('../lib/doctor'),
|
|
32
|
+
port: () => require('../lib/port'),
|
|
33
|
+
api: () => require('../lib/api'),
|
|
34
|
+
db: () => require('../lib/db'),
|
|
35
|
+
docker: () => require('../lib/docker'),
|
|
36
|
+
vuln: () => require('../lib/vuln'),
|
|
37
|
+
dom: () => require('../lib/dom'),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const HELP = `
|
|
41
|
+
fchek — developer & AI autonomous toolbox
|
|
42
|
+
|
|
43
|
+
── Full Automation ──────────────────────────────────────────────────────
|
|
44
|
+
audit [dir] [--quick] Full audit in one command
|
|
45
|
+
test [dir] [--filter=<n>] Auto-detect & run tests
|
|
46
|
+
git <action> status/diff/log/stage/commit
|
|
47
|
+
config [action] Read/write .fchekrc
|
|
48
|
+
|
|
49
|
+
── Code Intelligence (BEFORE code) ─────────────────────────────────────
|
|
50
|
+
context <dir> All symbols — avoid duplicates
|
|
51
|
+
convention <dir> Coding patterns (style, errors, logging)
|
|
52
|
+
deps-check <lib> Live API check from registry
|
|
53
|
+
|
|
54
|
+
── Execute & Verify (AFTER code) ───────────────────────────────────────
|
|
55
|
+
run <file> Run → stdout/stderr/exit_code
|
|
56
|
+
secrets <path> Scan for credentials
|
|
57
|
+
vuln [dir] Scan for typosquatting & vulnerabilities
|
|
58
|
+
dom <url|file> <sel> Query HTML DOM elements
|
|
59
|
+
|
|
60
|
+
── Windows ─────────────────────────────────────────────────────────────
|
|
61
|
+
screenshot [--window=<title>] Capture window/screen → PNG
|
|
62
|
+
launch <exe> [--wait=ms] Launch app, wait for window
|
|
63
|
+
winlog [--filter=<app>] Event Viewer logs
|
|
64
|
+
registry <action> <key> Read/write registry
|
|
65
|
+
process <action> [name|pid] List/kill/info processes
|
|
66
|
+
watch <dir> [--cmd=<build>] Auto-rebuild on file change
|
|
67
|
+
|
|
68
|
+
── Network & Databases ─────────────────────────────────────────────────
|
|
69
|
+
port <port> [--all] Network port scanner & connection info
|
|
70
|
+
api <url> [options] API / HTTP query tester
|
|
71
|
+
db <action> <db> [sql] SQLite schema & query runner
|
|
72
|
+
docker <action> [options] Docker ps and logs helper
|
|
73
|
+
|
|
74
|
+
── Analysis ────────────────────────────────────────────────────────────
|
|
75
|
+
profile / coverage / bench / lint / deps / race / fuzz / goto
|
|
76
|
+
|
|
77
|
+
── Memory & Environment ────────────────────────────────────────────────
|
|
78
|
+
state / repl / doctor
|
|
79
|
+
|
|
80
|
+
Output: JSON { "status": "ok"|"error", "data":{...} }
|
|
81
|
+
`.trim();
|
|
82
|
+
|
|
83
|
+
async function main() {
|
|
84
|
+
const args = process.argv.slice(2);
|
|
85
|
+
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
86
|
+
console.log(HELP); process.exit(0);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const cmd = args[0];
|
|
90
|
+
const cmdArgs = args.slice(1);
|
|
91
|
+
|
|
92
|
+
if (!COMMANDS[cmd]) {
|
|
93
|
+
console.error(`\nError: unknown command "${cmd}"\n`);
|
|
94
|
+
console.log(HELP); process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
await COMMANDS[cmd]().run(cmdArgs);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
const { output, fail } = require('../lib/output');
|
|
101
|
+
output(fail(err.message, cmd));
|
|
102
|
+
if (process.env.DEBUG) console.error(err.stack);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
main();
|
package/lib/api.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const { URL } = require('url');
|
|
6
|
+
const { output, ok, fail } = require('./output');
|
|
7
|
+
|
|
8
|
+
const HELP = `
|
|
9
|
+
fchek api <url> [--method=<method>] [--headers=<key:val,key2:val2>] [--body=<body>]
|
|
10
|
+
|
|
11
|
+
Test API endpoints and HTTP services.
|
|
12
|
+
Returns response status, headers, body size, and roundtrip latency.
|
|
13
|
+
`.trim();
|
|
14
|
+
|
|
15
|
+
function run(args) {
|
|
16
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
17
|
+
console.log(HELP);
|
|
18
|
+
return Promise.resolve();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const urlStr = args.find(a => !a.startsWith('-'));
|
|
22
|
+
if (!urlStr) {
|
|
23
|
+
output(fail('Please specify a URL (e.g. fchek api https://api.github.com)', 'api'));
|
|
24
|
+
return Promise.resolve();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let method = 'GET';
|
|
28
|
+
let headers = {};
|
|
29
|
+
let body = '';
|
|
30
|
+
|
|
31
|
+
for (const arg of args) {
|
|
32
|
+
if (arg.startsWith('--method=')) {
|
|
33
|
+
method = arg.split('=')[1].toUpperCase();
|
|
34
|
+
} else if (arg.startsWith('--headers=')) {
|
|
35
|
+
const headersStr = arg.slice(10);
|
|
36
|
+
const items = headersStr.split(',');
|
|
37
|
+
for (const item of items) {
|
|
38
|
+
const colonIdx = item.indexOf(':');
|
|
39
|
+
if (colonIdx !== -1) {
|
|
40
|
+
const k = item.slice(0, colonIdx).trim();
|
|
41
|
+
const v = item.slice(colonIdx + 1).trim();
|
|
42
|
+
headers[k] = v;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} else if (arg.startsWith('--body=')) {
|
|
46
|
+
body = arg.slice(7);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let parsedUrl;
|
|
51
|
+
try {
|
|
52
|
+
parsedUrl = new URL(urlStr);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
output(fail(`Invalid URL: ${err.message}`, 'api'));
|
|
55
|
+
return Promise.resolve();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const protocol = parsedUrl.protocol === 'https:' ? https : http;
|
|
59
|
+
const options = {
|
|
60
|
+
method,
|
|
61
|
+
headers,
|
|
62
|
+
timeout: 10000,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const startTime = process.hrtime();
|
|
66
|
+
|
|
67
|
+
return new Promise((resolve) => {
|
|
68
|
+
const req = protocol.request(urlStr, options, (res) => {
|
|
69
|
+
let responseData = '';
|
|
70
|
+
res.setEncoding('utf8');
|
|
71
|
+
res.on('data', (chunk) => {
|
|
72
|
+
responseData += chunk;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
res.on('end', () => {
|
|
76
|
+
const diff = process.hrtime(startTime);
|
|
77
|
+
const timeMs = Math.round(diff[0] * 1000 + diff[1] / 1000000);
|
|
78
|
+
|
|
79
|
+
output(ok({
|
|
80
|
+
status_code: res.statusCode,
|
|
81
|
+
status_text: res.statusMessage || '',
|
|
82
|
+
time_ms: timeMs,
|
|
83
|
+
headers: res.headers,
|
|
84
|
+
body_size_bytes: Buffer.byteLength(responseData, 'utf8'),
|
|
85
|
+
body: responseData.slice(0, 10000), // Cap body output to avoid massive JSONs
|
|
86
|
+
body_truncated: responseData.length > 10000,
|
|
87
|
+
}, 'api'));
|
|
88
|
+
resolve();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
req.on('error', (err) => {
|
|
93
|
+
output(fail(`Request failed: ${err.message}`, 'api'));
|
|
94
|
+
resolve();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
req.on('timeout', () => {
|
|
98
|
+
req.destroy();
|
|
99
|
+
output(fail('Request timed out after 10s', 'api'));
|
|
100
|
+
resolve();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (body) {
|
|
104
|
+
req.write(body);
|
|
105
|
+
}
|
|
106
|
+
req.end();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = { run };
|
package/lib/audit.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* audit.js — full project audit in one command
|
|
5
|
+
*
|
|
6
|
+
* Runs sequentially: context → convention → secrets → lint → test → deps → coverage
|
|
7
|
+
* Returns consolidated JSON with summary and per-tool results.
|
|
8
|
+
* Agent uses this at project start to understand the full picture.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const { output, ok, fail } = require('./output');
|
|
14
|
+
|
|
15
|
+
const HELP = `
|
|
16
|
+
fchek audit [dir] [--quick] [--fix]
|
|
17
|
+
|
|
18
|
+
Run a full project audit: context, convention, secrets, lint, test, deps, coverage.
|
|
19
|
+
One command instead of six. Use at project start or before a major change.
|
|
20
|
+
|
|
21
|
+
Options:
|
|
22
|
+
--quick Skip slow steps (coverage, fuzz). Faster for CI.
|
|
23
|
+
--fix Apply auto-fixes during lint step.
|
|
24
|
+
--json Always output JSON (default)
|
|
25
|
+
|
|
26
|
+
Output: consolidated report with status per tool and overall verdict.
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
fchek audit .
|
|
30
|
+
fchek audit src/ --quick
|
|
31
|
+
fchek audit . --fix
|
|
32
|
+
`.trim();
|
|
33
|
+
|
|
34
|
+
async function runStep(name, fn) {
|
|
35
|
+
const t0 = Date.now();
|
|
36
|
+
try {
|
|
37
|
+
// Capture output by temporarily overriding console.log
|
|
38
|
+
const lines = [];
|
|
39
|
+
const orig = console.log;
|
|
40
|
+
console.log = (s) => lines.push(s);
|
|
41
|
+
await fn();
|
|
42
|
+
console.log = orig;
|
|
43
|
+
|
|
44
|
+
let data = null;
|
|
45
|
+
if (lines.length > 0) {
|
|
46
|
+
try { data = JSON.parse(lines[lines.length - 1]); } catch {}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
step: name,
|
|
51
|
+
status: data?.status ?? 'ok',
|
|
52
|
+
duration_ms: Date.now() - t0,
|
|
53
|
+
data: data?.data ?? null,
|
|
54
|
+
error: data?.error ?? null,
|
|
55
|
+
};
|
|
56
|
+
} catch (err) {
|
|
57
|
+
return {
|
|
58
|
+
step: name,
|
|
59
|
+
status: 'error',
|
|
60
|
+
duration_ms: Date.now() - t0,
|
|
61
|
+
data: null,
|
|
62
|
+
error: err.message,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function run(args) {
|
|
68
|
+
if (args[0] === '--help') { console.log(HELP); return; }
|
|
69
|
+
|
|
70
|
+
const dir = args.find(a => !a.startsWith('--')) || '.';
|
|
71
|
+
const quick = args.includes('--quick');
|
|
72
|
+
const fix = args.includes('--fix');
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(dir)) {
|
|
75
|
+
return output(fail(`Directory not found: ${dir}`));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const absDir = path.resolve(dir);
|
|
79
|
+
const results = [];
|
|
80
|
+
const t0Total = Date.now();
|
|
81
|
+
|
|
82
|
+
console.error(`[fchek audit] Starting full audit of: ${absDir}`);
|
|
83
|
+
|
|
84
|
+
// 1. context — what exists
|
|
85
|
+
console.error('[fchek audit] 1/7 context...');
|
|
86
|
+
results.push(await runStep('context', async () => {
|
|
87
|
+
await require('./context').run([absDir, '--names-only']);
|
|
88
|
+
}));
|
|
89
|
+
|
|
90
|
+
// 2. convention — project patterns
|
|
91
|
+
console.error('[fchek audit] 2/7 convention...');
|
|
92
|
+
results.push(await runStep('convention', async () => {
|
|
93
|
+
await require('./convention').run([absDir]);
|
|
94
|
+
}));
|
|
95
|
+
|
|
96
|
+
// 3. secrets — credentials scan
|
|
97
|
+
console.error('[fchek audit] 3/7 secrets...');
|
|
98
|
+
results.push(await runStep('secrets', async () => {
|
|
99
|
+
await require('./secrets').run([absDir]);
|
|
100
|
+
}));
|
|
101
|
+
|
|
102
|
+
// 4. lint — code quality
|
|
103
|
+
console.error('[fchek audit] 4/7 lint...');
|
|
104
|
+
results.push(await runStep('lint', async () => {
|
|
105
|
+
const lintArgs = [absDir];
|
|
106
|
+
if (!fix) lintArgs.push('--no-fix');
|
|
107
|
+
await require('./lint').run(lintArgs);
|
|
108
|
+
}));
|
|
109
|
+
|
|
110
|
+
// 5. test — run tests
|
|
111
|
+
console.error('[fchek audit] 5/7 test...');
|
|
112
|
+
results.push(await runStep('test', async () => {
|
|
113
|
+
await require('./test').run([absDir]);
|
|
114
|
+
}));
|
|
115
|
+
|
|
116
|
+
// 6. deps — dependencies
|
|
117
|
+
console.error('[fchek audit] 6/7 deps...');
|
|
118
|
+
results.push(await runStep('deps', async () => {
|
|
119
|
+
await require('./deps').run([absDir]);
|
|
120
|
+
}));
|
|
121
|
+
|
|
122
|
+
// 7. coverage — only if not quick
|
|
123
|
+
if (!quick) {
|
|
124
|
+
console.error('[fchek audit] 7/7 coverage...');
|
|
125
|
+
results.push(await runStep('coverage', async () => {
|
|
126
|
+
await require('./coverage').run([absDir]);
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const totalMs = Date.now() - t0Total;
|
|
131
|
+
|
|
132
|
+
// Build summary
|
|
133
|
+
const secretsStep = results.find(r => r.step === 'secrets');
|
|
134
|
+
const testStep = results.find(r => r.step === 'test');
|
|
135
|
+
const lintStep = results.find(r => r.step === 'lint');
|
|
136
|
+
const coverageStep = results.find(r => r.step === 'coverage');
|
|
137
|
+
const depsStep = results.find(r => r.step === 'deps');
|
|
138
|
+
|
|
139
|
+
const criticalIssues = [];
|
|
140
|
+
|
|
141
|
+
if (secretsStep?.data?.verdict && secretsStep.data.verdict !== 'clean') {
|
|
142
|
+
criticalIssues.push(`SECRETS: ${secretsStep.data.total_findings} findings (${secretsStep.data.verdict})`);
|
|
143
|
+
}
|
|
144
|
+
if (testStep?.data?.verdict === 'failures_found') {
|
|
145
|
+
criticalIssues.push(`TESTS: ${testStep.data.failed} failed`);
|
|
146
|
+
}
|
|
147
|
+
if (lintStep?.data?.issues_count > 0) {
|
|
148
|
+
criticalIssues.push(`LINT: ${lintStep.data.issues_count} issues`);
|
|
149
|
+
}
|
|
150
|
+
if (coverageStep?.data?.total_pct !== null && coverageStep?.data?.total_pct < 60) {
|
|
151
|
+
criticalIssues.push(`COVERAGE: ${coverageStep.data.total_pct}% (below 60%)`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const verdict = criticalIssues.length === 0 ? 'healthy' : 'needs_attention';
|
|
155
|
+
|
|
156
|
+
output(ok({
|
|
157
|
+
dir: absDir,
|
|
158
|
+
verdict,
|
|
159
|
+
critical_issues: criticalIssues,
|
|
160
|
+
total_ms: totalMs,
|
|
161
|
+
quick_mode: quick,
|
|
162
|
+
steps: results.map(r => ({
|
|
163
|
+
step: r.step,
|
|
164
|
+
status: r.status,
|
|
165
|
+
duration_ms: r.duration_ms,
|
|
166
|
+
// Key metrics per step
|
|
167
|
+
summary: buildStepSummary(r),
|
|
168
|
+
})),
|
|
169
|
+
full_results: results,
|
|
170
|
+
next_actions: buildNextActions(criticalIssues, results),
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function buildStepSummary(r) {
|
|
175
|
+
if (!r.data) return r.error ? `error: ${r.error.slice(0, 80)}` : 'no data';
|
|
176
|
+
const d = r.data;
|
|
177
|
+
switch (r.step) {
|
|
178
|
+
case 'context': return `${d.total_symbols ?? 0} symbols in ${d.total_files ?? 0} files`;
|
|
179
|
+
case 'convention': return d.summary ?? 'ok';
|
|
180
|
+
case 'secrets': return `${d.total_findings ?? 0} findings, verdict: ${d.verdict ?? '?'}`;
|
|
181
|
+
case 'lint': return `${d.issues_count ?? 0} issues, build_clean: ${d.build_clean ?? '?'}`;
|
|
182
|
+
case 'test': return `${d.passed ?? 0} passed, ${d.failed ?? 0} failed (${d.framework ?? '?'})`;
|
|
183
|
+
case 'deps': return `${d.package_count ?? 0} packages, ${d.outdated_count ?? 0} outdated`;
|
|
184
|
+
case 'coverage': return `${d.total_pct ?? '?'}% coverage`;
|
|
185
|
+
default: return 'ok';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function buildNextActions(issues, results) {
|
|
190
|
+
const actions = [];
|
|
191
|
+
for (const issue of issues) {
|
|
192
|
+
if (issue.startsWith('SECRETS')) {
|
|
193
|
+
actions.push('Fix secrets: replace hardcoded values with environment variables');
|
|
194
|
+
}
|
|
195
|
+
if (issue.startsWith('TESTS')) {
|
|
196
|
+
actions.push('Fix failing tests before making any other changes');
|
|
197
|
+
}
|
|
198
|
+
if (issue.startsWith('LINT')) {
|
|
199
|
+
actions.push('Run: fchek lint . --fix to apply auto-fixes');
|
|
200
|
+
}
|
|
201
|
+
if (issue.startsWith('COVERAGE')) {
|
|
202
|
+
actions.push('Add tests for uncovered code: fchek coverage . to see which lines');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (actions.length === 0) {
|
|
206
|
+
actions.push('Project looks healthy. Proceed with your task.');
|
|
207
|
+
}
|
|
208
|
+
return actions;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
module.exports = { run };
|