@aicqtools/guardrail 1.0.0-alpha.6 → 1.0.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/matcher/yaml-rule.d.ts +5 -2
- package/dist/matcher/yaml-rule.d.ts.map +1 -1
- package/dist/matcher/yaml-rule.js +7 -5
- package/dist/matcher/yaml-rule.js.map +1 -1
- package/dist/rules-default/no-direct-anthropic.yaml +6 -0
- package/dist/rules-default/no-direct-openai.yaml +8 -0
- package/dist/rules-default/no-magic-number.d.ts.map +1 -1
- package/dist/rules-default/no-magic-number.js +112 -9
- package/dist/rules-default/no-magic-number.js.map +1 -1
- package/dist/rules-default/no-process-env-leak.d.ts.map +1 -1
- package/dist/rules-default/no-process-env-leak.js +5 -2
- package/dist/rules-default/no-process-env-leak.js.map +1 -1
- package/dist/runner/apply-rule-config.d.ts +49 -0
- package/dist/runner/apply-rule-config.d.ts.map +1 -0
- package/dist/runner/apply-rule-config.js +121 -0
- package/dist/runner/apply-rule-config.js.map +1 -0
- package/dist/runner/index.d.ts +3 -1
- package/dist/runner/index.d.ts.map +1 -1
- package/dist/runner/index.js +2 -1
- package/dist/runner/index.js.map +1 -1
- package/dist/runner/run-file.d.ts.map +1 -1
- package/dist/runner/run-file.js +13 -1
- package/dist/runner/run-file.js.map +1 -1
- package/dist/runner/run-project.d.ts +19 -1
- package/dist/runner/run-project.d.ts.map +1 -1
- package/dist/runner/run-project.js +54 -5
- package/dist/runner/run-project.js.map +1 -1
- package/dist/runner/run-rule.d.ts.map +1 -1
- package/dist/runner/run-rule.js +17 -0
- package/dist/runner/run-rule.js.map +1 -1
- package/dist/runner/suppressions.d.ts +37 -0
- package/dist/runner/suppressions.d.ts.map +1 -0
- package/dist/runner/suppressions.js +127 -0
- package/dist/runner/suppressions.js.map +1 -0
- package/dist/suggest/analyze.d.ts.map +1 -1
- package/dist/suggest/analyze.js +27 -3
- package/dist/suggest/analyze.js.map +1 -1
- package/dist/suggest/format.d.ts +8 -2
- package/dist/suggest/format.d.ts.map +1 -1
- package/dist/suggest/format.js +40 -22
- package/dist/suggest/format.js.map +1 -1
- package/dist/suggest/mine.d.ts.map +1 -1
- package/dist/suggest/mine.js +21 -1
- package/dist/suggest/mine.js.map +1 -1
- package/dist/suggest/types.d.ts +12 -0
- package/dist/suggest/types.d.ts.map +1 -1
- package/package.json +5 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { runFile, runFileWithSource, runProject, runRule, } from './runner/index.js';
|
|
2
|
-
export type { RunFileResult, RunProjectOptions } from './runner/index.js';
|
|
1
|
+
export { runFile, runFileWithSource, runProject, runRule, applyRuleConfig, applyOverridesForFile, collectUnknownOverrideIds, } from './runner/index.js';
|
|
2
|
+
export type { RunFileResult, RunProjectOptions, ApplyRuleConfigResult, UnknownOverrideId, } from './runner/index.js';
|
|
3
3
|
export { traverse, parseYamlRule } from './matcher/index.js';
|
|
4
4
|
export type { YamlRuleInput } from './matcher/index.js';
|
|
5
5
|
export { builtinFunctionRules, loadBuiltinYamlRules, loadAllBuiltinRules, loadFunctionRulesFromDir, } from './rules-default/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,iBAAiB,EACjB,UAAU,EACV,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,iBAAiB,EACjB,UAAU,EACV,OAAO,EACP,eAAe,EACf,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACtF,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEzE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzH,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { runFile, runFileWithSource, runProject, runRule, } from './runner/index.js';
|
|
1
|
+
export { runFile, runFileWithSource, runProject, runRule, applyRuleConfig, applyOverridesForFile, collectUnknownOverrideIds, } from './runner/index.js';
|
|
2
2
|
export { traverse, parseYamlRule } from './matcher/index.js';
|
|
3
3
|
export { builtinFunctionRules, loadBuiltinYamlRules, loadAllBuiltinRules, loadFunctionRulesFromDir, } from './rules-default/index.js';
|
|
4
4
|
export { buildMcpServer, startStdio, handleCheckSnippet, handleListRules, checkSnippetInputSchema, } from './mcp/index.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,iBAAiB,EACjB,UAAU,EACV,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,iBAAiB,EACjB,UAAU,EACV,OAAO,EACP,eAAe,EACf,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,UAAU,GACX,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGtF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -7,23 +7,26 @@ declare const yamlRuleSchema: z.ZodObject<{
|
|
|
7
7
|
message: z.ZodString;
|
|
8
8
|
messageKo: z.ZodOptional<z.ZodString>;
|
|
9
9
|
docs: z.ZodOptional<z.ZodString>;
|
|
10
|
+
pathExclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
10
11
|
query: z.ZodString;
|
|
11
12
|
}, "strip", z.ZodTypeAny, {
|
|
12
13
|
language: "typescript" | "javascript" | "tsx" | "python" | ("typescript" | "javascript" | "tsx" | "python")[];
|
|
14
|
+
query: string;
|
|
13
15
|
id: string;
|
|
14
16
|
message: string;
|
|
15
17
|
severity: "error" | "warning" | "info";
|
|
16
|
-
query: string;
|
|
17
18
|
messageKo?: string | undefined;
|
|
18
19
|
docs?: string | undefined;
|
|
20
|
+
pathExclude?: string[] | undefined;
|
|
19
21
|
}, {
|
|
20
22
|
language: "typescript" | "javascript" | "tsx" | "python" | ("typescript" | "javascript" | "tsx" | "python")[];
|
|
23
|
+
query: string;
|
|
21
24
|
id: string;
|
|
22
25
|
message: string;
|
|
23
26
|
severity: "error" | "warning" | "info";
|
|
24
|
-
query: string;
|
|
25
27
|
messageKo?: string | undefined;
|
|
26
28
|
docs?: string | undefined;
|
|
29
|
+
pathExclude?: string[] | undefined;
|
|
27
30
|
}>;
|
|
28
31
|
export type YamlRuleInput = z.infer<typeof yamlRuleSchema>;
|
|
29
32
|
export declare function parseYamlRule(source: string): PatternRule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml-rule.d.ts","sourceRoot":"","sources":["../../src/matcher/yaml-rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD,QAAA,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"yaml-rule.d.ts","sourceRoot":"","sources":["../../src/matcher/yaml-rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;EASlB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE3D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAgBzD"}
|
|
@@ -9,6 +9,7 @@ const yamlRuleSchema = z.object({
|
|
|
9
9
|
message: z.string().min(1),
|
|
10
10
|
messageKo: z.string().optional(),
|
|
11
11
|
docs: z.string().url().optional(),
|
|
12
|
+
pathExclude: z.array(z.string().min(1)).optional(),
|
|
12
13
|
query: z.string().min(1),
|
|
13
14
|
});
|
|
14
15
|
export function parseYamlRule(source) {
|
|
@@ -20,11 +21,12 @@ export function parseYamlRule(source) {
|
|
|
20
21
|
severity: parsed.severity,
|
|
21
22
|
message: parsed.message,
|
|
22
23
|
query: parsed.query,
|
|
24
|
+
...(parsed.messageKo !== undefined ? { messageKo: parsed.messageKo } : {}),
|
|
25
|
+
...(parsed.docs !== undefined ? { docs: parsed.docs } : {}),
|
|
26
|
+
...(parsed.pathExclude !== undefined && parsed.pathExclude.length > 0
|
|
27
|
+
? { pathExclude: parsed.pathExclude }
|
|
28
|
+
: {}),
|
|
23
29
|
};
|
|
24
|
-
return
|
|
25
|
-
? { ...rule, messageKo: parsed.messageKo }
|
|
26
|
-
: parsed.docs !== undefined
|
|
27
|
-
? { ...rule, docs: parsed.docs }
|
|
28
|
-
: rule;
|
|
30
|
+
return rule;
|
|
29
31
|
}
|
|
30
32
|
//# sourceMappingURL=yaml-rule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml-rule.js","sourceRoot":"","sources":["../../src/matcher/yaml-rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAI1C,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC7E,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5D,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,QAAQ,EAAE,cAAc;IACxB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACzB,CAAC,CAAC;AAIH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC,QAA0C;QAC3D,QAAQ,EAAE,MAAM,CAAC,QAAoB;QACrC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;
|
|
1
|
+
{"version":3,"file":"yaml-rule.js","sourceRoot":"","sources":["../../src/matcher/yaml-rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAI1C,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC7E,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5D,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,QAAQ,EAAE,cAAc;IACxB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACjC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACzB,CAAC,CAAC;AAIH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC,QAA0C;QAC3D,QAAQ,EAAE,MAAM,CAAC,QAAoB;QACrC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;YACnE,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE;YACrC,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -3,6 +3,12 @@ language: typescript
|
|
|
3
3
|
severity: error
|
|
4
4
|
message: Use the llmClient singleton. Direct Anthropic instantiation is forbidden.
|
|
5
5
|
messageKo: llmClient 싱글톤을 사용하세요. 직접 Anthropic 인스턴스화는 금지입니다.
|
|
6
|
+
# Allow the designated LLM wrapper module to construct the SDK once. Conventions only —
|
|
7
|
+
# add an inline `// aicq-disable-next-line no-direct-anthropic` outside these paths.
|
|
8
|
+
pathExclude:
|
|
9
|
+
- '**/llm/client.*'
|
|
10
|
+
- '**/llm/index.*'
|
|
11
|
+
- '**/ai/**/*client*.*'
|
|
6
12
|
query: |
|
|
7
13
|
(new_expression
|
|
8
14
|
constructor: (identifier) @ctor
|
|
@@ -3,6 +3,14 @@ language: typescript
|
|
|
3
3
|
severity: error
|
|
4
4
|
message: Use the llmClient singleton. Direct OpenAI instantiation is forbidden.
|
|
5
5
|
messageKo: llmClient 싱글톤을 사용하세요. 직접 OpenAI 인스턴스화는 금지입니다.
|
|
6
|
+
# Allow the *designated* LLM wrapper module to construct the SDK once. Conventions only —
|
|
7
|
+
# the project structures `src/**/llm/{client,index}.ts` or `src/**/ai/**/{*client*}.ts`
|
|
8
|
+
# as the single permitted call-site. Add an inline `// aicq-disable-next-line no-direct-openai`
|
|
9
|
+
# for one-off exceptions outside these paths.
|
|
10
|
+
pathExclude:
|
|
11
|
+
- '**/llm/client.*'
|
|
12
|
+
- '**/llm/index.*'
|
|
13
|
+
- '**/ai/**/*client*.*'
|
|
6
14
|
query: |
|
|
7
15
|
(new_expression
|
|
8
16
|
constructor: (identifier) @ctor
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-magic-number.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-magic-number.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"no-magic-number.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-magic-number.ts"],"names":[],"mappings":";AA6HA,wBAiBG"}
|
|
@@ -1,10 +1,48 @@
|
|
|
1
1
|
import { defineRule } from '@aicqtools/rule-sdk';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/**
|
|
3
|
+
* `no-magic-number` — info-severity rule that flags numeric literals appearing inline in
|
|
4
|
+
* application code (rather than being given a named constant). The hardest part is choosing
|
|
5
|
+
* a defensible default for "what's NOT a magic number." This rule errs on the side of fewer
|
|
6
|
+
* false positives because it ships at `info` severity and historically dominates noise budgets.
|
|
7
|
+
*
|
|
8
|
+
* Skipped contexts (all heuristic; project-specific tuning belongs in a future per-rule
|
|
9
|
+
* options seam):
|
|
10
|
+
* - Test fixture / spec files (filename heuristic)
|
|
11
|
+
* - `*.config.{ts,tsx,js,jsx}`, `*.polyfill.{ts,tsx,js,jsx}`, `**\/polyfills/**` (filename)
|
|
12
|
+
* - Database migrations / seeders / fixtures directories (alpha.8) — these are data files where
|
|
13
|
+
* numeric literals are the payload, not magic numbers. Other rules (e.g. camelcase-migration-column)
|
|
14
|
+
* keep firing on the same files because this skip is scoped to no-magic-number only.
|
|
15
|
+
* - Variable declarator RHS (`const X = 7;` — 7 is being NAMED, not used inline)
|
|
16
|
+
* - JSX attribute values (`<View width={24} />`)
|
|
17
|
+
* - Enum members (`enum E { A = 7 }`)
|
|
18
|
+
* - Array index subscripts (`arr[42]`)
|
|
19
|
+
* - `for` loop initializer/condition/update
|
|
20
|
+
* - Arguments to obvious numeric APIs (`parseInt(s, 16)`, `Math.*`, `Number(...)`, `.toFixed(2)`,
|
|
21
|
+
* `.padStart(8, '0')`, `setTimeout(f, 100)`, `setInterval(f, 1000)`)
|
|
22
|
+
* - "Timeout-ish" variable-name contexts (carried over from alpha.6)
|
|
23
|
+
*
|
|
24
|
+
* Allowed-numbers default extended to common-sense values: powers of two, common bases,
|
|
25
|
+
* time/clock constants, etc.
|
|
26
|
+
*/
|
|
27
|
+
const ALLOWED_NUMBERS = new Set([
|
|
28
|
+
'0', '1', '-1', '2', '-2', '10', '16', '24', '60', '100', '1000', '1024',
|
|
29
|
+
]);
|
|
30
|
+
const SKIP_FILE_RE = /(\.test\.|\.spec\.|__tests__|fixtures|\.config\.|\.polyfill\.|[/\\]polyfills[/\\]|[/\\]seeders[/\\]|[/\\]migrations[/\\])/;
|
|
31
|
+
// Callee names whose numeric args are almost always intentional, not magic numbers.
|
|
32
|
+
// Matched on the leaf identifier (last name segment) — covers both `parseInt(...)` and
|
|
33
|
+
// `Number.parseInt(...)` / `globalThis.setTimeout(...)`.
|
|
34
|
+
const NUMERIC_API_CALLEES = new Set([
|
|
35
|
+
'parseInt', 'parseFloat', 'Number',
|
|
36
|
+
'setTimeout', 'setInterval', 'setImmediate',
|
|
37
|
+
'toFixed', 'toPrecision', 'toExponential', 'toString',
|
|
38
|
+
'padStart', 'padEnd', 'repeat', 'slice', 'substr', 'substring', 'charAt', 'codePointAt',
|
|
39
|
+
'round', 'floor', 'ceil', 'trunc', 'abs', 'sign', 'min', 'max', 'pow', 'log',
|
|
40
|
+
]);
|
|
41
|
+
function isInSkippedFile(filePath) {
|
|
42
|
+
return SKIP_FILE_RE.test(filePath);
|
|
5
43
|
}
|
|
6
44
|
function isInTimeoutMsContext(node, textOf) {
|
|
7
|
-
// Allow magic numbers in obvious time/duration contexts where the unit is in the variable name
|
|
45
|
+
// Allow magic numbers in obvious time/duration contexts where the unit is in the variable name.
|
|
8
46
|
let parent = node.parent;
|
|
9
47
|
while (parent) {
|
|
10
48
|
const text = textOf(parent);
|
|
@@ -16,6 +54,71 @@ function isInTimeoutMsContext(node, textOf) {
|
|
|
16
54
|
}
|
|
17
55
|
return false;
|
|
18
56
|
}
|
|
57
|
+
const SKIP_ANCESTOR_TYPES = new Set([
|
|
58
|
+
// Variable declarator: `const RETRY = 5;` — the literal IS the named constant we want.
|
|
59
|
+
'variable_declarator',
|
|
60
|
+
// Enum members: `enum E { A = 7 }`
|
|
61
|
+
'enum_body',
|
|
62
|
+
'enum_assignment',
|
|
63
|
+
// JSX attribute values: `<View width={24} />`
|
|
64
|
+
'jsx_attribute',
|
|
65
|
+
'jsx_expression',
|
|
66
|
+
// Array index subscripts: `arr[42]`
|
|
67
|
+
'subscript_expression',
|
|
68
|
+
// For loop header: `for (let i = 0; i < 5; i++) {}`
|
|
69
|
+
'for_statement',
|
|
70
|
+
'for_in_statement',
|
|
71
|
+
'for_of_statement',
|
|
72
|
+
]);
|
|
73
|
+
function hasSkippableAncestor(node) {
|
|
74
|
+
let parent = node.parent;
|
|
75
|
+
let depth = 0;
|
|
76
|
+
while (parent && depth < 8) {
|
|
77
|
+
if (SKIP_ANCESTOR_TYPES.has(parent.type))
|
|
78
|
+
return true;
|
|
79
|
+
// Stop at clear statement / function boundaries so a number deep in a function body
|
|
80
|
+
// doesn't get silently allowed by a far-away for-loop ancestor.
|
|
81
|
+
if (parent.type === 'statement_block' ||
|
|
82
|
+
parent.type === 'function_declaration' ||
|
|
83
|
+
parent.type === 'method_definition' ||
|
|
84
|
+
parent.type === 'arrow_function' ||
|
|
85
|
+
parent.type === 'function_expression') {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
parent = parent.parent;
|
|
89
|
+
depth += 1;
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Returns true if the number is a positional argument to a call expression whose final
|
|
95
|
+
* identifier is a known numeric API (parseInt, parseFloat, Math.*, .toFixed, …).
|
|
96
|
+
*/
|
|
97
|
+
function isArgOfNumericApi(node, textOf) {
|
|
98
|
+
const parent = node.parent;
|
|
99
|
+
if (!parent || parent.type !== 'arguments')
|
|
100
|
+
return false;
|
|
101
|
+
const callExpr = parent.parent;
|
|
102
|
+
if (!callExpr || callExpr.type !== 'call_expression')
|
|
103
|
+
return false;
|
|
104
|
+
const fn = callExpr.childForFieldName('function');
|
|
105
|
+
if (!fn)
|
|
106
|
+
return false;
|
|
107
|
+
// Pull out the *final* name segment whether the callee is `foo` or `Obj.foo` or `a.b.foo`.
|
|
108
|
+
let nameNode = fn;
|
|
109
|
+
while (nameNode && (nameNode.type === 'member_expression' || nameNode.type === 'parenthesized_expression')) {
|
|
110
|
+
const fromField = nameNode.childForFieldName('property');
|
|
111
|
+
const fallback = nameNode.namedChildren[nameNode.namedChildren.length - 1];
|
|
112
|
+
const prop = fromField ?? fallback ?? null;
|
|
113
|
+
if (!prop || prop === nameNode)
|
|
114
|
+
break;
|
|
115
|
+
nameNode = prop;
|
|
116
|
+
}
|
|
117
|
+
if (!nameNode)
|
|
118
|
+
return false;
|
|
119
|
+
const name = textOf(nameNode);
|
|
120
|
+
return NUMERIC_API_CALLEES.has(name);
|
|
121
|
+
}
|
|
19
122
|
export default defineRule({
|
|
20
123
|
id: 'no-magic-number',
|
|
21
124
|
language: ['typescript', 'javascript', 'tsx'],
|
|
@@ -24,16 +127,16 @@ export default defineRule({
|
|
|
24
127
|
messageKo: '매직 넘버 — 명명된 상수로 추출해 의미를 명확히 하세요.',
|
|
25
128
|
visitors: {
|
|
26
129
|
number(node, ctx) {
|
|
27
|
-
if (
|
|
130
|
+
if (isInSkippedFile(ctx.filePath))
|
|
28
131
|
return;
|
|
29
132
|
const text = ctx.textOf(node);
|
|
30
133
|
if (ALLOWED_NUMBERS.has(text))
|
|
31
134
|
return;
|
|
32
|
-
if (
|
|
135
|
+
if (hasSkippableAncestor(node))
|
|
136
|
+
return;
|
|
137
|
+
if (isArgOfNumericApi(node, ctx.textOf))
|
|
33
138
|
return;
|
|
34
|
-
|
|
35
|
-
const parent = node.parent;
|
|
36
|
-
if (parent && parent.type === 'variable_declarator')
|
|
139
|
+
if (isInTimeoutMsContext(node, ctx.textOf))
|
|
37
140
|
return;
|
|
38
141
|
ctx.report({ node });
|
|
39
142
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-magic-number.js","sourceRoot":"","sources":["../../src/rules-default/no-magic-number.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"no-magic-number.js","sourceRoot":"","sources":["../../src/rules-default/no-magic-number.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-process-env-leak.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-process-env-leak.ts"],"names":[],"mappings":"AAEA;;;GAGG;;AACH,
|
|
1
|
+
{"version":3,"file":"no-process-env-leak.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-process-env-leak.ts"],"names":[],"mappings":"AAEA;;;GAGG;;AACH,wBA8BG"}
|
|
@@ -22,8 +22,11 @@ export default defineRule({
|
|
|
22
22
|
innerProp &&
|
|
23
23
|
ctx.textOf(inner) === 'process' &&
|
|
24
24
|
ctx.textOf(innerProp) === 'env') {
|
|
25
|
-
// Allowlist: config
|
|
26
|
-
|
|
25
|
+
// Allowlist: `config/`, `env/`, and `*.config.*` / `*.env.*` files (e.g. `next.config.ts`,
|
|
26
|
+
// `vite.config.ts`, `jest.config.ts`). Includes a leading `.` in the prefix character
|
|
27
|
+
// class so dotted filenames where `config`/`env` is preceded by `.` (e.g. `next.config.ts`)
|
|
28
|
+
// are recognized.
|
|
29
|
+
if (/(^|[/\\.])(config|env)([/\\.]|$)/.test(ctx.filePath))
|
|
27
30
|
return;
|
|
28
31
|
ctx.report({ node });
|
|
29
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-process-env-leak.js","sourceRoot":"","sources":["../../src/rules-default/no-process-env-leak.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;GAGG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,qBAAqB;IACzB,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,gEAAgE;IACzE,SAAS,EAAE,+DAA+D;IAC1E,QAAQ,EAAE;QACR,iBAAiB,CAAC,IAAI,EAAE,GAAG;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAChD,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;gBAAE,OAAO;YAC1B,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBACrC,MAAM,KAAK,GAAG,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBAC9C,MAAM,SAAS,GAAG,GAAG,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;gBACpD,IACE,KAAK;oBACL,SAAS;oBACT,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS;oBAC/B,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,EAC/B,CAAC;oBACD,
|
|
1
|
+
{"version":3,"file":"no-process-env-leak.js","sourceRoot":"","sources":["../../src/rules-default/no-process-env-leak.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;GAGG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,qBAAqB;IACzB,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,gEAAgE;IACzE,SAAS,EAAE,+DAA+D;IAC1E,QAAQ,EAAE;QACR,iBAAiB,CAAC,IAAI,EAAE,GAAG;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAChD,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;gBAAE,OAAO;YAC1B,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBACrC,MAAM,KAAK,GAAG,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBAC9C,MAAM,SAAS,GAAG,GAAG,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;gBACpD,IACE,KAAK;oBACL,SAAS;oBACT,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS;oBAC/B,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,EAC/B,CAAC;oBACD,2FAA2F;oBAC3F,sFAAsF;oBACtF,4FAA4F;oBAC5F,kBAAkB;oBAClB,IAAI,kCAAkC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;wBAAE,OAAO;oBAClE,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;KACF;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { RuleOverride } from '@aicqtools/core';
|
|
2
|
+
import type { Rule } from '@aicqtools/rule-sdk';
|
|
3
|
+
/**
|
|
4
|
+
* Resolution of `config.modules.guardrail.rules` (the `{ ruleId: 'off' | 'warn' | 'error' }` map)
|
|
5
|
+
* against the loaded rule set. Filters out `off`'d rules, overrides severity for `warn`/`error`
|
|
6
|
+
* entries, and reports unknown rule ids back to the caller so the CLI can warn the user once.
|
|
7
|
+
*/
|
|
8
|
+
export interface ApplyRuleConfigResult {
|
|
9
|
+
readonly rules: readonly Rule[];
|
|
10
|
+
/** rule ids that appeared in the config map but matched no loaded rule */
|
|
11
|
+
readonly unknownIds: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
type RuleLevel = 'off' | 'warn' | 'error';
|
|
14
|
+
/**
|
|
15
|
+
* Apply the user-supplied `rules:` map to a loaded rule list.
|
|
16
|
+
*
|
|
17
|
+
* - `off` → drop the rule from the returned list
|
|
18
|
+
* - `warn`/`error` → return a copy of the rule with `severity` overridden
|
|
19
|
+
* - missing entry → rule passes through unchanged
|
|
20
|
+
*
|
|
21
|
+
* Map keys that don't correspond to any loaded rule are collected in `unknownIds`. The function
|
|
22
|
+
* never throws; an invalid level value (should already be rejected by zod) is treated as "no
|
|
23
|
+
* override" rather than crashing the run.
|
|
24
|
+
*/
|
|
25
|
+
export declare function applyRuleConfig(rules: readonly Rule[], cfgMap: Readonly<Record<string, RuleLevel>> | undefined): ApplyRuleConfigResult;
|
|
26
|
+
/**
|
|
27
|
+
* Apply per-path `overrides` (alpha.8) on top of an already-globally-resolved rule list.
|
|
28
|
+
*
|
|
29
|
+
* For each override entry whose `paths` globs match `filePath`, merge its `rules` map into a
|
|
30
|
+
* per-file effective level map. Later matching entries win for the same rule id (ESLint semantics).
|
|
31
|
+
* `off` drops the rule for this file; `warn`/`error` copies the rule with overridden severity.
|
|
32
|
+
*
|
|
33
|
+
* Fast path: if no overrides are configured, returns the input list unchanged so the file loop
|
|
34
|
+
* stays cheap when this feature is unused.
|
|
35
|
+
*/
|
|
36
|
+
export declare function applyOverridesForFile(baselineRules: readonly Rule[], overrides: readonly RuleOverride[], filePath: string): readonly Rule[];
|
|
37
|
+
/**
|
|
38
|
+
* Collect rule ids referenced by `overrides` entries that don't match any loaded rule, paired
|
|
39
|
+
* with the index of the offending override entry. The caller (CLI) uses these to emit one
|
|
40
|
+
* stderr warning per typo so configuration mistakes surface early rather than silently no-op'ing.
|
|
41
|
+
*/
|
|
42
|
+
export interface UnknownOverrideId {
|
|
43
|
+
readonly index: number;
|
|
44
|
+
readonly id: string;
|
|
45
|
+
readonly paths: readonly string[];
|
|
46
|
+
}
|
|
47
|
+
export declare function collectUnknownOverrideIds(baselineRules: readonly Rule[], overrides: readonly RuleOverride[]): readonly UnknownOverrideId[];
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=apply-rule-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-rule-config.d.ts","sourceRoot":"","sources":["../../src/runner/apply-rule-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,iBAAiB,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,KAAK,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AAM1C;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,GACtD,qBAAqB,CAgCvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,SAAS,IAAI,EAAE,EAC9B,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,QAAQ,EAAE,MAAM,GACf,SAAS,IAAI,EAAE,CAqCjB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,SAAS,IAAI,EAAE,EAC9B,SAAS,EAAE,SAAS,YAAY,EAAE,GACjC,SAAS,iBAAiB,EAAE,CAY9B"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import micromatch from 'micromatch';
|
|
2
|
+
const LEVEL_TO_SEVERITY = {
|
|
3
|
+
warn: 'warning',
|
|
4
|
+
error: 'error',
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Apply the user-supplied `rules:` map to a loaded rule list.
|
|
8
|
+
*
|
|
9
|
+
* - `off` → drop the rule from the returned list
|
|
10
|
+
* - `warn`/`error` → return a copy of the rule with `severity` overridden
|
|
11
|
+
* - missing entry → rule passes through unchanged
|
|
12
|
+
*
|
|
13
|
+
* Map keys that don't correspond to any loaded rule are collected in `unknownIds`. The function
|
|
14
|
+
* never throws; an invalid level value (should already be rejected by zod) is treated as "no
|
|
15
|
+
* override" rather than crashing the run.
|
|
16
|
+
*/
|
|
17
|
+
export function applyRuleConfig(rules, cfgMap) {
|
|
18
|
+
if (!cfgMap || Object.keys(cfgMap).length === 0) {
|
|
19
|
+
return { rules, unknownIds: [] };
|
|
20
|
+
}
|
|
21
|
+
const knownIds = new Set(rules.map((r) => r.id));
|
|
22
|
+
const unknownIds = [];
|
|
23
|
+
for (const id of Object.keys(cfgMap)) {
|
|
24
|
+
if (!knownIds.has(id))
|
|
25
|
+
unknownIds.push(id);
|
|
26
|
+
}
|
|
27
|
+
const out = [];
|
|
28
|
+
for (const rule of rules) {
|
|
29
|
+
const level = cfgMap[rule.id];
|
|
30
|
+
if (level === undefined) {
|
|
31
|
+
out.push(rule);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (level === 'off')
|
|
35
|
+
continue;
|
|
36
|
+
const severity = LEVEL_TO_SEVERITY[level];
|
|
37
|
+
if (!severity) {
|
|
38
|
+
// Unrecognized level — treat as no override, never crash.
|
|
39
|
+
out.push(rule);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
// Copy with overridden severity. `Rule` is a discriminated union; preserve the union
|
|
43
|
+
// by re-spreading per branch.
|
|
44
|
+
if (rule.kind === 'function') {
|
|
45
|
+
out.push({ ...rule, severity });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
out.push({ ...rule, severity });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return { rules: out, unknownIds };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Apply per-path `overrides` (alpha.8) on top of an already-globally-resolved rule list.
|
|
55
|
+
*
|
|
56
|
+
* For each override entry whose `paths` globs match `filePath`, merge its `rules` map into a
|
|
57
|
+
* per-file effective level map. Later matching entries win for the same rule id (ESLint semantics).
|
|
58
|
+
* `off` drops the rule for this file; `warn`/`error` copies the rule with overridden severity.
|
|
59
|
+
*
|
|
60
|
+
* Fast path: if no overrides are configured, returns the input list unchanged so the file loop
|
|
61
|
+
* stays cheap when this feature is unused.
|
|
62
|
+
*/
|
|
63
|
+
export function applyOverridesForFile(baselineRules, overrides, filePath) {
|
|
64
|
+
if (overrides.length === 0)
|
|
65
|
+
return baselineRules;
|
|
66
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
67
|
+
const effective = new Map();
|
|
68
|
+
let anyMatch = false;
|
|
69
|
+
for (const ov of overrides) {
|
|
70
|
+
const paths = [...ov.paths];
|
|
71
|
+
const matched = micromatch.isMatch(normalized, paths, { dot: true }) ||
|
|
72
|
+
micromatch.isMatch(filePath, paths, { dot: true });
|
|
73
|
+
if (!matched)
|
|
74
|
+
continue;
|
|
75
|
+
anyMatch = true;
|
|
76
|
+
for (const [id, level] of Object.entries(ov.rules)) {
|
|
77
|
+
effective.set(id, level);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!anyMatch)
|
|
81
|
+
return baselineRules;
|
|
82
|
+
const out = [];
|
|
83
|
+
for (const rule of baselineRules) {
|
|
84
|
+
const level = effective.get(rule.id);
|
|
85
|
+
if (level === undefined) {
|
|
86
|
+
out.push(rule);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (level === 'off')
|
|
90
|
+
continue;
|
|
91
|
+
const severity = LEVEL_TO_SEVERITY[level];
|
|
92
|
+
if (!severity) {
|
|
93
|
+
out.push(rule);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (rule.kind === 'function') {
|
|
97
|
+
out.push({ ...rule, severity });
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
out.push({ ...rule, severity });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
export function collectUnknownOverrideIds(baselineRules, overrides) {
|
|
106
|
+
if (overrides.length === 0)
|
|
107
|
+
return [];
|
|
108
|
+
const knownIds = new Set(baselineRules.map((r) => r.id));
|
|
109
|
+
const out = [];
|
|
110
|
+
for (let i = 0; i < overrides.length; i++) {
|
|
111
|
+
const ov = overrides[i];
|
|
112
|
+
if (!ov)
|
|
113
|
+
continue;
|
|
114
|
+
for (const id of Object.keys(ov.rules)) {
|
|
115
|
+
if (!knownIds.has(id))
|
|
116
|
+
out.push({ index: i, id, paths: ov.paths });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=apply-rule-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-rule-config.js","sourceRoot":"","sources":["../../src/runner/apply-rule-config.ts"],"names":[],"mappings":"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"}
|
package/dist/runner/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { runFile, runFileWithSource } from './run-file.js';
|
|
2
|
-
export { runProject } from './run-project.js';
|
|
2
|
+
export { runProject, resolveIgnores } from './run-project.js';
|
|
3
3
|
export { runRule } from './run-rule.js';
|
|
4
4
|
export { ruleSignature, rulesetSignature } from './ruleset-signature.js';
|
|
5
|
+
export { applyRuleConfig, applyOverridesForFile, collectUnknownOverrideIds } from './apply-rule-config.js';
|
|
6
|
+
export type { ApplyRuleConfigResult, UnknownOverrideId } from './apply-rule-config.js';
|
|
5
7
|
export type { RunFileResult } from './run-file.js';
|
|
6
8
|
export type { RunProjectOptions } from './run-project.js';
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC3G,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACvF,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/runner/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { runFile, runFileWithSource } from './run-file.js';
|
|
2
|
-
export { runProject } from './run-project.js';
|
|
2
|
+
export { runProject, resolveIgnores } from './run-project.js';
|
|
3
3
|
export { runRule } from './run-rule.js';
|
|
4
4
|
export { ruleSignature, rulesetSignature } from './ruleset-signature.js';
|
|
5
|
+
export { applyRuleConfig, applyOverridesForFile, collectUnknownOverrideIds } from './apply-rule-config.js';
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/dist/runner/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-file.d.ts","sourceRoot":"","sources":["../../src/runner/run-file.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-file.d.ts","sourceRoot":"","sources":["../../src/runner/run-file.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAIhD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;CAC7C;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAM9F;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,SAAS,IAAI,EAAE,GACrB,aAAa,CAsBf"}
|
package/dist/runner/run-file.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { detectLanguage, parseSource } from '@aicqtools/core';
|
|
3
3
|
import { runRule } from './run-rule.js';
|
|
4
|
+
import { applySuppressions, parseSuppressions } from './suppressions.js';
|
|
4
5
|
export async function runFile(filePath, rules) {
|
|
5
6
|
const language = detectLanguage(filePath);
|
|
6
7
|
if (!language)
|
|
@@ -20,7 +21,18 @@ export function runFileWithSource(filePath, source, language, rules) {
|
|
|
20
21
|
diagnostics.push(ruleFailedDiagnostic(filePath, rule.id, err));
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
+
// Apply inline-suppression directives last so they catch diagnostics from every rule
|
|
25
|
+
// (function rules, YAML pattern rules, and synthetic `@aicq/parse-failed`/rule-failed).
|
|
26
|
+
let suppressed = diagnostics;
|
|
27
|
+
try {
|
|
28
|
+
const suppressions = parseSuppressions(tree, source, language);
|
|
29
|
+
suppressed = applySuppressions(diagnostics, suppressions);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Suppression parsing must never abort a run. If the tree shape surprises us,
|
|
33
|
+
// fall through with the unfiltered diagnostics.
|
|
34
|
+
}
|
|
35
|
+
return { filePath, language, diagnostics: suppressed };
|
|
24
36
|
}
|
|
25
37
|
function ruleFailedDiagnostic(filePath, ruleId, err) {
|
|
26
38
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-file.js","sourceRoot":"","sources":["../../src/runner/run-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"run-file.js","sourceRoot":"","sources":["../../src/runner/run-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAQzE,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAgB,EAAE,KAAsB;IACpE,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IAEpE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,MAAc,EACd,QAAkB,EAClB,KAAsB;IAEtB,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAiB,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,qFAAqF;IACrF,wFAAwF;IACxF,IAAI,UAAU,GAA0B,WAAW,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/D,UAAU,GAAG,iBAAiB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,8EAA8E;QAC9E,gDAAgD;IAClD,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACzD,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB,EAAE,MAAc,EAAE,GAAY;IAC1E,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO;QACL,MAAM,EAAE,oBAAoB;QAC5B,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,yBAAyB,MAAM,KAAK,OAAO,EAAE;QACtD,SAAS,EAAE,YAAY,MAAM,MAAM,OAAO,EAAE;QAC5C,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;KACtE,CAAC;AACJ,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CheckResult } from '@aicqtools/core';
|
|
1
|
+
import type { CheckResult, RuleOverride } from '@aicqtools/core';
|
|
2
2
|
import { FileCache } from '@aicqtools/core';
|
|
3
3
|
import type { Rule } from '@aicqtools/rule-sdk';
|
|
4
4
|
export interface RunProjectOptions {
|
|
@@ -7,6 +7,24 @@ export interface RunProjectOptions {
|
|
|
7
7
|
readonly exclude: readonly string[];
|
|
8
8
|
readonly rules: readonly Rule[];
|
|
9
9
|
readonly cache?: FileCache;
|
|
10
|
+
/**
|
|
11
|
+
* When true, the file walker appends entries from the repo-root `.gitignore` to the effective
|
|
12
|
+
* exclude list. Unreadable / missing / malformed `.gitignore` is silently ignored (never throws).
|
|
13
|
+
* Defaults to false to keep behavior deterministic across projects.
|
|
14
|
+
*/
|
|
15
|
+
readonly respectGitignore?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Per-path rule overrides (alpha.8). When set, each file's rule set is re-resolved against
|
|
18
|
+
* matching `overrides` entries on top of the globally-resolved `rules` baseline. Empty array
|
|
19
|
+
* (or omitted) is the fast path — runner falls back to the baseline list unchanged.
|
|
20
|
+
*/
|
|
21
|
+
readonly overrides?: readonly RuleOverride[];
|
|
10
22
|
}
|
|
11
23
|
export declare function runProject(opts: RunProjectOptions): Promise<CheckResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Build the final ignore list for `fast-glob`. Always starts from the configured `exclude`;
|
|
26
|
+
* when `respectGitignore` is true, parses the root `.gitignore` (best-effort) and appends its
|
|
27
|
+
* entries. Negation (`!pattern`) and trailing-slash directory entries are honored.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveIgnores(cwd: string, exclude: readonly string[], respectGitignore: boolean): Promise<string[]>;
|
|
12
30
|
//# sourceMappingURL=run-project.d.ts.map
|