sequant 1.11.0 → 1.13.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 +93 -7
- package/dist/bin/cli.js +12 -9
- package/dist/src/commands/doctor.js +25 -20
- package/dist/src/commands/init.js +152 -65
- package/dist/src/commands/logs.js +7 -6
- package/dist/src/commands/run.d.ts +13 -1
- package/dist/src/commands/run.js +75 -12
- package/dist/src/commands/stats.js +67 -48
- package/dist/src/commands/status.js +30 -12
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +4 -0
- package/dist/src/lib/ac-linter.d.ts +116 -0
- package/dist/src/lib/ac-linter.js +304 -0
- package/dist/src/lib/cli-ui.d.ts +196 -0
- package/dist/src/lib/cli-ui.js +544 -0
- package/dist/src/lib/content-analyzer.d.ts +89 -0
- package/dist/src/lib/content-analyzer.js +437 -0
- package/dist/src/lib/phase-signal.d.ts +94 -0
- package/dist/src/lib/phase-signal.js +171 -0
- package/dist/src/lib/plugin-version-sync.d.ts +26 -0
- package/dist/src/lib/plugin-version-sync.js +91 -0
- package/dist/src/lib/project-name.d.ts +40 -0
- package/dist/src/lib/project-name.js +191 -0
- package/dist/src/lib/semgrep.d.ts +136 -0
- package/dist/src/lib/semgrep.js +406 -0
- package/dist/src/lib/solve-comment-parser.d.ts +84 -0
- package/dist/src/lib/solve-comment-parser.js +200 -0
- package/dist/src/lib/stack-config.d.ts +51 -0
- package/dist/src/lib/stack-config.js +77 -0
- package/dist/src/lib/stacks.d.ts +66 -0
- package/dist/src/lib/stacks.js +332 -0
- package/dist/src/lib/templates.d.ts +2 -0
- package/dist/src/lib/templates.js +12 -3
- package/dist/src/lib/upstream/assessment.d.ts +70 -0
- package/dist/src/lib/upstream/assessment.js +385 -0
- package/dist/src/lib/upstream/index.d.ts +11 -0
- package/dist/src/lib/upstream/index.js +14 -0
- package/dist/src/lib/upstream/issues.d.ts +38 -0
- package/dist/src/lib/upstream/issues.js +267 -0
- package/dist/src/lib/upstream/relevance.d.ts +50 -0
- package/dist/src/lib/upstream/relevance.js +209 -0
- package/dist/src/lib/upstream/report.d.ts +29 -0
- package/dist/src/lib/upstream/report.js +391 -0
- package/dist/src/lib/upstream/types.d.ts +207 -0
- package/dist/src/lib/upstream/types.js +5 -0
- package/dist/src/lib/workflow/log-writer.d.ts +1 -1
- package/dist/src/lib/workflow/metrics-schema.d.ts +3 -3
- package/dist/src/lib/workflow/qa-cache.d.ts +199 -0
- package/dist/src/lib/workflow/qa-cache.js +440 -0
- package/dist/src/lib/workflow/run-log-schema.d.ts +34 -6
- package/dist/src/lib/workflow/run-log-schema.js +12 -1
- package/dist/src/lib/workflow/state-schema.d.ts +4 -4
- package/dist/src/lib/workflow/types.d.ts +4 -0
- package/package.json +6 -1
- package/templates/hooks/pre-tool.sh +6 -0
- package/templates/memory/constitution.md +1 -5
- package/templates/skills/_shared/references/prompt-templates.md +350 -0
- package/templates/skills/_shared/references/subagent-types.md +131 -0
- package/templates/skills/exec/SKILL.md +82 -0
- package/templates/skills/fullsolve/SKILL.md +19 -2
- package/templates/skills/loop/SKILL.md +3 -1
- package/templates/skills/qa/SKILL.md +79 -9
- package/templates/skills/qa/references/quality-gates.md +85 -1
- package/templates/skills/qa/references/semgrep-rules.md +207 -0
- package/templates/skills/qa/scripts/quality-checks.sh +525 -15
- package/templates/skills/spec/SKILL.md +322 -9
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin version sync utilities
|
|
3
|
+
*
|
|
4
|
+
* Ensures plugin.json version stays in sync with package.json version.
|
|
5
|
+
* Used by CI validation and /release skill.
|
|
6
|
+
*/
|
|
7
|
+
export interface VersionSyncResult {
|
|
8
|
+
inSync: boolean;
|
|
9
|
+
packageVersion: string | null;
|
|
10
|
+
pluginVersion: string | null;
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Check if package.json and plugin.json versions are in sync
|
|
15
|
+
*
|
|
16
|
+
* @param projectRoot - Root directory of the project
|
|
17
|
+
* @returns Sync status with version details
|
|
18
|
+
*/
|
|
19
|
+
export declare function checkVersionSync(projectRoot?: string): VersionSyncResult;
|
|
20
|
+
/**
|
|
21
|
+
* Get a helpful error message for version mismatch
|
|
22
|
+
*
|
|
23
|
+
* @param result - Version sync result
|
|
24
|
+
* @returns Human-readable error message with fix command
|
|
25
|
+
*/
|
|
26
|
+
export declare function getVersionMismatchMessage(result: VersionSyncResult): string;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin version sync utilities
|
|
3
|
+
*
|
|
4
|
+
* Ensures plugin.json version stays in sync with package.json version.
|
|
5
|
+
* Used by CI validation and /release skill.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
/**
|
|
10
|
+
* Check if package.json and plugin.json versions are in sync
|
|
11
|
+
*
|
|
12
|
+
* @param projectRoot - Root directory of the project
|
|
13
|
+
* @returns Sync status with version details
|
|
14
|
+
*/
|
|
15
|
+
export function checkVersionSync(projectRoot = process.cwd()) {
|
|
16
|
+
const packageJsonPath = join(projectRoot, "package.json");
|
|
17
|
+
const pluginJsonPath = join(projectRoot, ".claude-plugin", "plugin.json");
|
|
18
|
+
// Check package.json exists
|
|
19
|
+
if (!existsSync(packageJsonPath)) {
|
|
20
|
+
return {
|
|
21
|
+
inSync: false,
|
|
22
|
+
packageVersion: null,
|
|
23
|
+
pluginVersion: null,
|
|
24
|
+
error: "package.json not found",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Check plugin.json exists
|
|
28
|
+
if (!existsSync(pluginJsonPath)) {
|
|
29
|
+
return {
|
|
30
|
+
inSync: false,
|
|
31
|
+
packageVersion: null,
|
|
32
|
+
pluginVersion: null,
|
|
33
|
+
error: "plugin.json not found",
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
38
|
+
const pluginJson = JSON.parse(readFileSync(pluginJsonPath, "utf8"));
|
|
39
|
+
const packageVersion = packageJson.version || null;
|
|
40
|
+
const pluginVersion = pluginJson.version || null;
|
|
41
|
+
if (!packageVersion) {
|
|
42
|
+
return {
|
|
43
|
+
inSync: false,
|
|
44
|
+
packageVersion: null,
|
|
45
|
+
pluginVersion,
|
|
46
|
+
error: "package.json missing version field",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (!pluginVersion) {
|
|
50
|
+
return {
|
|
51
|
+
inSync: false,
|
|
52
|
+
packageVersion,
|
|
53
|
+
pluginVersion: null,
|
|
54
|
+
error: "plugin.json missing version field",
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
inSync: packageVersion === pluginVersion,
|
|
59
|
+
packageVersion,
|
|
60
|
+
pluginVersion,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
return {
|
|
65
|
+
inSync: false,
|
|
66
|
+
packageVersion: null,
|
|
67
|
+
pluginVersion: null,
|
|
68
|
+
error: `Failed to parse JSON: ${e instanceof Error ? e.message : String(e)}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get a helpful error message for version mismatch
|
|
74
|
+
*
|
|
75
|
+
* @param result - Version sync result
|
|
76
|
+
* @returns Human-readable error message with fix command
|
|
77
|
+
*/
|
|
78
|
+
export function getVersionMismatchMessage(result) {
|
|
79
|
+
if (result.inSync) {
|
|
80
|
+
return `✓ Versions are in sync: ${result.packageVersion}`;
|
|
81
|
+
}
|
|
82
|
+
if (result.error) {
|
|
83
|
+
return `✗ Version sync check failed: ${result.error}`;
|
|
84
|
+
}
|
|
85
|
+
return `✗ Version mismatch!
|
|
86
|
+
package.json: ${result.packageVersion}
|
|
87
|
+
plugin.json: ${result.pluginVersion}
|
|
88
|
+
|
|
89
|
+
Run the following to sync:
|
|
90
|
+
node -e "const p=require('./.claude-plugin/plugin.json');p.version='${result.packageVersion}';require('fs').writeFileSync('./.claude-plugin/plugin.json',JSON.stringify(p,null,2)+'\\n')"`;
|
|
91
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project name detection utility
|
|
3
|
+
*
|
|
4
|
+
* Detects project name from various sources in priority order:
|
|
5
|
+
* 1. package.json → name field
|
|
6
|
+
* 2. Cargo.toml → [package] name
|
|
7
|
+
* 3. pyproject.toml → [project] name OR [tool.poetry] name
|
|
8
|
+
* 4. go.mod → module path (last segment)
|
|
9
|
+
* 5. git remote → extract repo name from origin URL
|
|
10
|
+
* 6. Directory name → basename(cwd) (fallback)
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Result of project name detection
|
|
14
|
+
*/
|
|
15
|
+
export interface ProjectNameResult {
|
|
16
|
+
/** The detected project name */
|
|
17
|
+
name: string;
|
|
18
|
+
/** The source from which the name was detected */
|
|
19
|
+
source: "package.json" | "Cargo.toml" | "pyproject.toml" | "go.mod" | "git-remote" | "directory";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Detect project name from available sources
|
|
23
|
+
*
|
|
24
|
+
* Tries sources in priority order:
|
|
25
|
+
* 1. package.json
|
|
26
|
+
* 2. Cargo.toml
|
|
27
|
+
* 3. pyproject.toml
|
|
28
|
+
* 4. go.mod
|
|
29
|
+
* 5. git remote
|
|
30
|
+
* 6. directory name
|
|
31
|
+
*
|
|
32
|
+
* @returns The detected project name and its source
|
|
33
|
+
*/
|
|
34
|
+
export declare function detectProjectName(): Promise<ProjectNameResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Detect project name, returning just the name string
|
|
37
|
+
*
|
|
38
|
+
* Convenience function for cases where only the name is needed.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getProjectName(): Promise<string>;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project name detection utility
|
|
3
|
+
*
|
|
4
|
+
* Detects project name from various sources in priority order:
|
|
5
|
+
* 1. package.json → name field
|
|
6
|
+
* 2. Cargo.toml → [package] name
|
|
7
|
+
* 3. pyproject.toml → [project] name OR [tool.poetry] name
|
|
8
|
+
* 4. go.mod → module path (last segment)
|
|
9
|
+
* 5. git remote → extract repo name from origin URL
|
|
10
|
+
* 6. Directory name → basename(cwd) (fallback)
|
|
11
|
+
*/
|
|
12
|
+
import { basename } from "path";
|
|
13
|
+
import { spawnSync } from "child_process";
|
|
14
|
+
import { fileExists, readFile } from "./fs.js";
|
|
15
|
+
/**
|
|
16
|
+
* Extract project name from package.json
|
|
17
|
+
*/
|
|
18
|
+
async function fromPackageJson() {
|
|
19
|
+
if (!(await fileExists("package.json"))) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const content = await readFile("package.json");
|
|
24
|
+
const pkg = JSON.parse(content);
|
|
25
|
+
if (typeof pkg.name === "string" && pkg.name.trim()) {
|
|
26
|
+
return pkg.name.trim();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Parse error or missing name field
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extract project name from Cargo.toml (Rust)
|
|
36
|
+
*/
|
|
37
|
+
async function fromCargoToml() {
|
|
38
|
+
if (!(await fileExists("Cargo.toml"))) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const content = await readFile("Cargo.toml");
|
|
43
|
+
// Look for: name = "project-name" in [package] section
|
|
44
|
+
// Simple regex approach - handles most common formats
|
|
45
|
+
const match = content.match(/\[package\][\s\S]*?name\s*=\s*["']([^"']+)["']/);
|
|
46
|
+
if (match && match[1]) {
|
|
47
|
+
return match[1].trim();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Parse error
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extract project name from pyproject.toml (Python)
|
|
57
|
+
*/
|
|
58
|
+
async function fromPyprojectToml() {
|
|
59
|
+
if (!(await fileExists("pyproject.toml"))) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const content = await readFile("pyproject.toml");
|
|
64
|
+
// Try [project] name first (PEP 621 standard)
|
|
65
|
+
const projectMatch = content.match(/\[project\][\s\S]*?name\s*=\s*["']([^"']+)["']/);
|
|
66
|
+
if (projectMatch && projectMatch[1]) {
|
|
67
|
+
return projectMatch[1].trim();
|
|
68
|
+
}
|
|
69
|
+
// Fallback to [tool.poetry] name
|
|
70
|
+
const poetryMatch = content.match(/\[tool\.poetry\][\s\S]*?name\s*=\s*["']([^"']+)["']/);
|
|
71
|
+
if (poetryMatch && poetryMatch[1]) {
|
|
72
|
+
return poetryMatch[1].trim();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Parse error
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Extract project name from go.mod (Go)
|
|
82
|
+
*/
|
|
83
|
+
async function fromGoMod() {
|
|
84
|
+
if (!(await fileExists("go.mod"))) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const content = await readFile("go.mod");
|
|
89
|
+
// Look for: module github.com/org/project-name
|
|
90
|
+
const match = content.match(/^module\s+(.+)$/m);
|
|
91
|
+
if (match && match[1]) {
|
|
92
|
+
const modulePath = match[1].trim();
|
|
93
|
+
// Extract the last segment of the module path
|
|
94
|
+
const segments = modulePath.split("/");
|
|
95
|
+
const lastSegment = segments[segments.length - 1];
|
|
96
|
+
if (lastSegment) {
|
|
97
|
+
return lastSegment;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Parse error
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Extract project name from git remote origin URL
|
|
108
|
+
*/
|
|
109
|
+
function fromGitRemote() {
|
|
110
|
+
try {
|
|
111
|
+
const result = spawnSync("git", ["remote", "get-url", "origin"], {
|
|
112
|
+
encoding: "utf-8",
|
|
113
|
+
timeout: 5000,
|
|
114
|
+
});
|
|
115
|
+
if (result.status !== 0 || !result.stdout) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
const url = result.stdout.trim();
|
|
119
|
+
// Handle SSH format: git@github.com:org/repo.git
|
|
120
|
+
const sshMatch = url.match(/[:/]([^/]+)\.git$/);
|
|
121
|
+
if (sshMatch && sshMatch[1]) {
|
|
122
|
+
return sshMatch[1];
|
|
123
|
+
}
|
|
124
|
+
// Handle HTTPS format: https://github.com/org/repo.git or https://github.com/org/repo
|
|
125
|
+
const httpsMatch = url.match(/\/([^/]+?)(?:\.git)?$/);
|
|
126
|
+
if (httpsMatch && httpsMatch[1]) {
|
|
127
|
+
return httpsMatch[1];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// Git not available or not a git repo
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get project name from directory name (fallback)
|
|
137
|
+
*/
|
|
138
|
+
function fromDirectory() {
|
|
139
|
+
return basename(process.cwd()) || "project";
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Detect project name from available sources
|
|
143
|
+
*
|
|
144
|
+
* Tries sources in priority order:
|
|
145
|
+
* 1. package.json
|
|
146
|
+
* 2. Cargo.toml
|
|
147
|
+
* 3. pyproject.toml
|
|
148
|
+
* 4. go.mod
|
|
149
|
+
* 5. git remote
|
|
150
|
+
* 6. directory name
|
|
151
|
+
*
|
|
152
|
+
* @returns The detected project name and its source
|
|
153
|
+
*/
|
|
154
|
+
export async function detectProjectName() {
|
|
155
|
+
// 1. Try package.json
|
|
156
|
+
const fromPkg = await fromPackageJson();
|
|
157
|
+
if (fromPkg) {
|
|
158
|
+
return { name: fromPkg, source: "package.json" };
|
|
159
|
+
}
|
|
160
|
+
// 2. Try Cargo.toml
|
|
161
|
+
const fromCargo = await fromCargoToml();
|
|
162
|
+
if (fromCargo) {
|
|
163
|
+
return { name: fromCargo, source: "Cargo.toml" };
|
|
164
|
+
}
|
|
165
|
+
// 3. Try pyproject.toml
|
|
166
|
+
const fromPyproject = await fromPyprojectToml();
|
|
167
|
+
if (fromPyproject) {
|
|
168
|
+
return { name: fromPyproject, source: "pyproject.toml" };
|
|
169
|
+
}
|
|
170
|
+
// 4. Try go.mod
|
|
171
|
+
const fromGo = await fromGoMod();
|
|
172
|
+
if (fromGo) {
|
|
173
|
+
return { name: fromGo, source: "go.mod" };
|
|
174
|
+
}
|
|
175
|
+
// 5. Try git remote
|
|
176
|
+
const fromRemote = fromGitRemote();
|
|
177
|
+
if (fromRemote) {
|
|
178
|
+
return { name: fromRemote, source: "git-remote" };
|
|
179
|
+
}
|
|
180
|
+
// 6. Fallback to directory name
|
|
181
|
+
return { name: fromDirectory(), source: "directory" };
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Detect project name, returning just the name string
|
|
185
|
+
*
|
|
186
|
+
* Convenience function for cases where only the name is needed.
|
|
187
|
+
*/
|
|
188
|
+
export async function getProjectName() {
|
|
189
|
+
const result = await detectProjectName();
|
|
190
|
+
return result.name;
|
|
191
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semgrep integration for static analysis
|
|
3
|
+
*
|
|
4
|
+
* Provides stack-aware ruleset mapping and execution utilities
|
|
5
|
+
* for integrating Semgrep into the /qa workflow.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Semgrep finding severity levels
|
|
9
|
+
*/
|
|
10
|
+
export type SemgrepSeverity = "error" | "warning" | "info";
|
|
11
|
+
/**
|
|
12
|
+
* A single Semgrep finding
|
|
13
|
+
*/
|
|
14
|
+
export interface SemgrepFinding {
|
|
15
|
+
path: string;
|
|
16
|
+
line: number;
|
|
17
|
+
column?: number;
|
|
18
|
+
endLine?: number;
|
|
19
|
+
endColumn?: number;
|
|
20
|
+
message: string;
|
|
21
|
+
ruleId: string;
|
|
22
|
+
severity: SemgrepSeverity;
|
|
23
|
+
category?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Result of a Semgrep scan
|
|
27
|
+
*/
|
|
28
|
+
export interface SemgrepResult {
|
|
29
|
+
success: boolean;
|
|
30
|
+
findings: SemgrepFinding[];
|
|
31
|
+
criticalCount: number;
|
|
32
|
+
warningCount: number;
|
|
33
|
+
infoCount: number;
|
|
34
|
+
error?: string;
|
|
35
|
+
skipped?: boolean;
|
|
36
|
+
skipReason?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Semgrep ruleset configuration
|
|
40
|
+
*/
|
|
41
|
+
export interface SemgrepRuleset {
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
rules: string[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Stack-to-ruleset mapping
|
|
48
|
+
*
|
|
49
|
+
* Maps detected stacks to appropriate Semgrep rulesets.
|
|
50
|
+
* Uses Semgrep's public rule registry identifiers.
|
|
51
|
+
*/
|
|
52
|
+
export declare const STACK_RULESETS: Record<string, SemgrepRuleset>;
|
|
53
|
+
/**
|
|
54
|
+
* Get the appropriate Semgrep ruleset for a detected stack
|
|
55
|
+
*
|
|
56
|
+
* @param stack - The detected stack name (e.g., "nextjs", "python")
|
|
57
|
+
* @returns The ruleset configuration for the stack
|
|
58
|
+
*/
|
|
59
|
+
export declare function getRulesForStack(stack: string | null): SemgrepRuleset;
|
|
60
|
+
/**
|
|
61
|
+
* Path to custom rules file
|
|
62
|
+
*/
|
|
63
|
+
export declare const CUSTOM_RULES_PATH = ".sequant/semgrep-rules.yaml";
|
|
64
|
+
/**
|
|
65
|
+
* Check if custom rules file exists
|
|
66
|
+
*
|
|
67
|
+
* @param projectRoot - Root directory of the project
|
|
68
|
+
* @returns true if custom rules file exists
|
|
69
|
+
*/
|
|
70
|
+
export declare function hasCustomRules(projectRoot?: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Get path to custom rules file if it exists
|
|
73
|
+
*
|
|
74
|
+
* @param projectRoot - Root directory of the project
|
|
75
|
+
* @returns Path to custom rules file, or null if it doesn't exist
|
|
76
|
+
*/
|
|
77
|
+
export declare function getCustomRulesPath(projectRoot?: string): string | null;
|
|
78
|
+
/**
|
|
79
|
+
* Check if Semgrep is available
|
|
80
|
+
*
|
|
81
|
+
* Checks for both 'semgrep' command and 'npx semgrep' fallback
|
|
82
|
+
*
|
|
83
|
+
* @returns Object with availability info and command to use
|
|
84
|
+
*/
|
|
85
|
+
export declare function checkSemgrepAvailability(): Promise<{
|
|
86
|
+
available: boolean;
|
|
87
|
+
command: string;
|
|
88
|
+
useNpx: boolean;
|
|
89
|
+
}>;
|
|
90
|
+
/**
|
|
91
|
+
* Parse Semgrep JSON output into findings
|
|
92
|
+
*
|
|
93
|
+
* @param output - Raw JSON output from Semgrep
|
|
94
|
+
* @returns Array of parsed findings
|
|
95
|
+
*/
|
|
96
|
+
export declare function parseSemgrepOutput(output: string): SemgrepFinding[];
|
|
97
|
+
/**
|
|
98
|
+
* Count findings by severity
|
|
99
|
+
*
|
|
100
|
+
* @param findings - Array of Semgrep findings
|
|
101
|
+
* @returns Object with counts by severity
|
|
102
|
+
*/
|
|
103
|
+
export declare function countFindingsBySeverity(findings: SemgrepFinding[]): {
|
|
104
|
+
critical: number;
|
|
105
|
+
warning: number;
|
|
106
|
+
info: number;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Run Semgrep scan on specified files or directories
|
|
110
|
+
*
|
|
111
|
+
* @param options - Scan options
|
|
112
|
+
* @returns Scan result with findings
|
|
113
|
+
*/
|
|
114
|
+
export declare function runSemgrepScan(options: {
|
|
115
|
+
targets: string[];
|
|
116
|
+
stack?: string | null;
|
|
117
|
+
projectRoot?: string;
|
|
118
|
+
useCustomRules?: boolean;
|
|
119
|
+
}): Promise<SemgrepResult>;
|
|
120
|
+
/**
|
|
121
|
+
* Format findings for display in QA output
|
|
122
|
+
*
|
|
123
|
+
* @param findings - Array of findings to format
|
|
124
|
+
* @returns Formatted markdown string
|
|
125
|
+
*/
|
|
126
|
+
export declare function formatFindingsForDisplay(findings: SemgrepFinding[]): string;
|
|
127
|
+
/**
|
|
128
|
+
* Generate QA verdict contribution from Semgrep results
|
|
129
|
+
*
|
|
130
|
+
* @param result - Semgrep scan result
|
|
131
|
+
* @returns Verdict contribution (blocking if critical findings)
|
|
132
|
+
*/
|
|
133
|
+
export declare function getSemgrepVerdictContribution(result: SemgrepResult): {
|
|
134
|
+
blocking: boolean;
|
|
135
|
+
reason: string;
|
|
136
|
+
};
|