@alex-dbs/coderuler 0.0.0-stage → 1.3.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/LICENSE +175 -0
- package/README.md +218 -2
- package/dist/adapter/cli/commands/check.d.ts +3 -0
- package/dist/adapter/cli/commands/check.js +93 -0
- package/dist/adapter/cli/commands/deps.d.ts +3 -0
- package/dist/adapter/cli/commands/deps.js +4 -0
- package/dist/adapter/cli/commands/inspect.d.ts +3 -0
- package/dist/adapter/cli/commands/inspect.js +59 -0
- package/dist/adapter/cli/commands/rules.d.ts +10 -0
- package/dist/adapter/cli/commands/rules.js +17 -0
- package/dist/adapter/cli/commands/skill.d.ts +4 -0
- package/dist/adapter/cli/commands/skill.js +7 -0
- package/dist/adapter/cli/commands/test.d.ts +3 -0
- package/dist/adapter/cli/commands/test.js +78 -0
- package/dist/adapter/cli/commands/update.d.ts +3 -0
- package/dist/adapter/cli/commands/update.js +7 -0
- package/dist/adapter/cli/commands/validate.d.ts +3 -0
- package/dist/adapter/cli/commands/validate.js +12 -0
- package/dist/adapter/cli/exit.d.ts +7 -0
- package/dist/adapter/cli/exit.js +10 -0
- package/dist/adapter/cli/inspect-json.d.ts +9 -0
- package/dist/adapter/cli/inspect-json.js +160 -0
- package/dist/adapter/cli/inspect-usage.d.ts +9 -0
- package/dist/adapter/cli/inspect-usage.js +14 -0
- package/dist/adapter/cli/program.d.ts +4 -0
- package/dist/adapter/cli/program.js +216 -0
- package/dist/adapter/cli/progress.d.ts +22 -0
- package/dist/adapter/cli/progress.js +79 -0
- package/dist/adapter/cli/reports.d.ts +47 -0
- package/dist/adapter/cli/reports.js +735 -0
- package/dist/adapter/cli/self-update.d.ts +1 -0
- package/dist/adapter/cli/self-update.js +89 -0
- package/dist/adapter/cli/services.d.ts +101 -0
- package/dist/adapter/cli/services.js +1 -0
- package/dist/adapter/cli/text.d.ts +5 -0
- package/dist/adapter/cli/text.js +36 -0
- package/dist/adapter/cli/version.d.ts +1 -0
- package/dist/adapter/cli/version.js +3 -0
- package/dist/adapter/decision/jev.d.ts +11 -0
- package/dist/adapter/decision/jev.js +138 -0
- package/dist/adapter/filesystem/dependencies.d.ts +26 -0
- package/dist/adapter/filesystem/dependencies.js +577 -0
- package/dist/adapter/filesystem/dependency-installation.d.ts +11 -0
- package/dist/adapter/filesystem/dependency-installation.js +373 -0
- package/dist/adapter/filesystem/project.d.ts +14 -0
- package/dist/adapter/filesystem/project.js +387 -0
- package/dist/adapter/filesystem/rule-resolution.d.ts +4 -0
- package/dist/adapter/filesystem/rule-resolution.js +516 -0
- package/dist/adapter/filesystem/rule-test-worker.d.ts +17 -0
- package/dist/adapter/filesystem/rule-test-worker.js +47 -0
- package/dist/adapter/filesystem/rule-tests.d.ts +3 -0
- package/dist/adapter/filesystem/rule-tests.js +264 -0
- package/dist/adapter/filesystem/rules.d.ts +13 -0
- package/dist/adapter/filesystem/rules.js +242 -0
- package/dist/adapter/git/changes.d.ts +1 -0
- package/dist/adapter/git/changes.js +54 -0
- package/dist/adapter/git/environment.d.ts +1 -0
- package/dist/adapter/git/environment.js +10 -0
- package/dist/adapter/github/api.d.ts +5 -0
- package/dist/adapter/github/api.js +40 -0
- package/dist/adapter/github/comments.d.ts +3 -0
- package/dist/adapter/github/comments.js +235 -0
- package/dist/adapter/github/pull-request.d.ts +16 -0
- package/dist/adapter/github/pull-request.js +139 -0
- package/dist/adapter/scope/astgrep-languages.d.ts +5 -0
- package/dist/adapter/scope/astgrep-languages.js +119 -0
- package/dist/adapter/scope/astgrep.d.ts +14 -0
- package/dist/adapter/scope/astgrep.js +183 -0
- package/dist/adapter/scope/csv.d.ts +4 -0
- package/dist/adapter/scope/csv.js +158 -0
- package/dist/adapter/scope/file.d.ts +2 -0
- package/dist/adapter/scope/file.js +4 -0
- package/dist/adapter/scope/json.d.ts +7 -0
- package/dist/adapter/scope/json.js +132 -0
- package/dist/adapter/scope/lines.d.ts +10 -0
- package/dist/adapter/scope/lines.js +42 -0
- package/dist/adapter/scope/protobuf-options.d.ts +29 -0
- package/dist/adapter/scope/protobuf-options.js +64 -0
- package/dist/adapter/scope/protobuf-parser.d.ts +30 -0
- package/dist/adapter/scope/protobuf-parser.js +772 -0
- package/dist/adapter/scope/protobuf.d.ts +5 -0
- package/dist/adapter/scope/protobuf.js +53 -0
- package/dist/adapter/scope/structured.d.ts +10 -0
- package/dist/adapter/scope/structured.js +84 -0
- package/dist/adapter/scope/yaml.d.ts +7 -0
- package/dist/adapter/scope/yaml.js +224 -0
- package/dist/adapter/skills/cli.d.ts +10 -0
- package/dist/adapter/skills/cli.js +77 -0
- package/dist/app/concurrency.d.ts +1 -0
- package/dist/app/concurrency.js +44 -0
- package/dist/app/evaluators.d.ts +14 -0
- package/dist/app/evaluators.js +175 -0
- package/dist/app/execute.d.ts +2 -0
- package/dist/app/execute.js +427 -0
- package/dist/app/jsonpath.d.ts +1 -0
- package/dist/app/jsonpath.js +8 -0
- package/dist/app/ports.d.ts +165 -0
- package/dist/app/ports.js +1 -0
- package/dist/app/rule-tests.d.ts +20 -0
- package/dist/app/rule-tests.js +11 -0
- package/dist/app/rule.d.ts +121 -0
- package/dist/app/rule.js +24 -0
- package/dist/app/selection.d.ts +2 -0
- package/dist/app/selection.js +23 -0
- package/dist/app/usage.d.ts +2 -0
- package/dist/app/usage.js +13 -0
- package/dist/app/validate.d.ts +11 -0
- package/dist/app/validate.js +415 -0
- package/dist/app/violation-comments.d.ts +10 -0
- package/dist/app/violation-comments.js +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +3 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +11 -0
- package/dist/infra/runtime.d.ts +3 -0
- package/dist/infra/runtime.js +168 -0
- package/dist/infra/settings.d.ts +5 -0
- package/dist/infra/settings.js +91 -0
- package/package.json +86 -4
- package/skills/coderuler-new-rule/SKILL.md +141 -0
- package/skills/coderuler-new-rule/reference.md +447 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import type { AiUsage, CheckResult, GroupSubject, JsonValue, Rule, RuleSettings, ScopeSubject, Subject, TokenPricing, TokenUsage } from './rule.js';
|
|
2
|
+
export interface Project {
|
|
3
|
+
readonly root: string;
|
|
4
|
+
glob(patterns: string | readonly string[]): Promise<readonly string[]>;
|
|
5
|
+
hasFiles(patterns: string | readonly string[]): Promise<boolean>;
|
|
6
|
+
stat(path: string): Promise<{
|
|
7
|
+
readonly kind: 'file' | 'directory';
|
|
8
|
+
} | undefined>;
|
|
9
|
+
readText(path: string): Promise<string>;
|
|
10
|
+
readJson(path: string): Promise<JsonValue>;
|
|
11
|
+
readYaml(path: string): Promise<readonly JsonValue[]>;
|
|
12
|
+
readCsv(path: string, options?: CsvOptions): Promise<readonly CsvRow[]>;
|
|
13
|
+
}
|
|
14
|
+
export interface CsvOptions {
|
|
15
|
+
readonly headers?: boolean;
|
|
16
|
+
readonly delimiter?: string;
|
|
17
|
+
readonly key?: string;
|
|
18
|
+
}
|
|
19
|
+
export type CsvRow = Readonly<Record<string, string>> | readonly string[];
|
|
20
|
+
export interface RuleSelection {
|
|
21
|
+
readonly root: string;
|
|
22
|
+
readonly explicit?: string;
|
|
23
|
+
readonly name?: string;
|
|
24
|
+
readonly invocationCwd: string;
|
|
25
|
+
}
|
|
26
|
+
export interface LoadedRule {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly ruleFile: string;
|
|
29
|
+
readonly rule: Rule<unknown>;
|
|
30
|
+
}
|
|
31
|
+
export interface RuleLoader {
|
|
32
|
+
load(selection: RuleSelection): Promise<readonly LoadedRule[]>;
|
|
33
|
+
}
|
|
34
|
+
export interface DecisionInstructions {
|
|
35
|
+
readonly rule: string;
|
|
36
|
+
readonly question: string;
|
|
37
|
+
readonly examples?: {
|
|
38
|
+
readonly good: readonly string[];
|
|
39
|
+
readonly bad: readonly string[];
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export interface DecisionRequest {
|
|
43
|
+
readonly state: JsonValue;
|
|
44
|
+
readonly instructions: DecisionInstructions;
|
|
45
|
+
}
|
|
46
|
+
export interface DecisionOutcome {
|
|
47
|
+
readonly probability: number;
|
|
48
|
+
readonly model: string;
|
|
49
|
+
readonly usage?: TokenUsage;
|
|
50
|
+
}
|
|
51
|
+
export type DecisionExchange = {
|
|
52
|
+
readonly type: 'request';
|
|
53
|
+
readonly body: string;
|
|
54
|
+
} | {
|
|
55
|
+
readonly type: 'response';
|
|
56
|
+
readonly status: number;
|
|
57
|
+
readonly body: string;
|
|
58
|
+
} | {
|
|
59
|
+
readonly type: 'usage';
|
|
60
|
+
readonly usage: AiUsage;
|
|
61
|
+
};
|
|
62
|
+
export type DecisionObserver = (exchange: DecisionExchange) => void;
|
|
63
|
+
export interface DecisionBackend {
|
|
64
|
+
decide(request: DecisionRequest, observer?: DecisionObserver): Promise<DecisionOutcome>;
|
|
65
|
+
}
|
|
66
|
+
export interface DecisionRuntime {
|
|
67
|
+
readonly backend: DecisionBackend;
|
|
68
|
+
readonly threshold: number;
|
|
69
|
+
readonly pricing: TokenPricing;
|
|
70
|
+
}
|
|
71
|
+
export interface RunContext {
|
|
72
|
+
readonly project: Project;
|
|
73
|
+
readonly isTarget: (filepath: string) => boolean;
|
|
74
|
+
readonly changedFiles?: ReadonlySet<string>;
|
|
75
|
+
readonly concurrency: number;
|
|
76
|
+
readonly resolveDecision: (settings: RuleSettings) => DecisionRuntime;
|
|
77
|
+
readonly emit?: (event: RunEvent) => void;
|
|
78
|
+
}
|
|
79
|
+
export interface RuleEvaluation {
|
|
80
|
+
readonly subject: Subject;
|
|
81
|
+
readonly result: CheckResult;
|
|
82
|
+
}
|
|
83
|
+
export interface RuleReport {
|
|
84
|
+
readonly name: string;
|
|
85
|
+
readonly ruleFile: string;
|
|
86
|
+
readonly status: 'pass' | 'violation' | 'skipped';
|
|
87
|
+
readonly durationMs: number;
|
|
88
|
+
readonly reason?: string;
|
|
89
|
+
readonly evaluations: readonly RuleEvaluation[];
|
|
90
|
+
}
|
|
91
|
+
export type RunEvent = {
|
|
92
|
+
readonly type: 'progress';
|
|
93
|
+
readonly phase: 'selection' | 'evaluation';
|
|
94
|
+
readonly completed: number;
|
|
95
|
+
readonly total: number;
|
|
96
|
+
} | {
|
|
97
|
+
readonly type: 'rule';
|
|
98
|
+
readonly name: string;
|
|
99
|
+
readonly ruleFile: string;
|
|
100
|
+
} | {
|
|
101
|
+
readonly type: 'gate';
|
|
102
|
+
readonly name: string;
|
|
103
|
+
readonly enabled: boolean;
|
|
104
|
+
readonly applies: boolean;
|
|
105
|
+
readonly reason?: string;
|
|
106
|
+
} | {
|
|
107
|
+
readonly type: 'file';
|
|
108
|
+
readonly evaluationId?: number;
|
|
109
|
+
readonly name: string;
|
|
110
|
+
readonly filepath: string;
|
|
111
|
+
readonly selected: boolean;
|
|
112
|
+
readonly reason?: string;
|
|
113
|
+
} | {
|
|
114
|
+
readonly type: 'scope';
|
|
115
|
+
readonly name: string;
|
|
116
|
+
readonly subject: ScopeSubject;
|
|
117
|
+
readonly accepted: boolean;
|
|
118
|
+
readonly reason?: string;
|
|
119
|
+
} | {
|
|
120
|
+
readonly type: 'group';
|
|
121
|
+
readonly name: string;
|
|
122
|
+
readonly subject: GroupSubject;
|
|
123
|
+
} | {
|
|
124
|
+
readonly type: 'evaluation';
|
|
125
|
+
readonly evaluationId: number;
|
|
126
|
+
readonly name: string;
|
|
127
|
+
readonly subject: Subject;
|
|
128
|
+
} | {
|
|
129
|
+
readonly type: 'request';
|
|
130
|
+
readonly evaluationId: number;
|
|
131
|
+
readonly name: string;
|
|
132
|
+
readonly subject: Subject;
|
|
133
|
+
readonly body: string;
|
|
134
|
+
} | {
|
|
135
|
+
readonly type: 'response';
|
|
136
|
+
readonly evaluationId: number;
|
|
137
|
+
readonly name: string;
|
|
138
|
+
readonly subject: Subject;
|
|
139
|
+
readonly status: number;
|
|
140
|
+
readonly body: string;
|
|
141
|
+
} | {
|
|
142
|
+
readonly type: 'usage';
|
|
143
|
+
readonly evaluationId: number;
|
|
144
|
+
readonly name: string;
|
|
145
|
+
readonly subject: Subject;
|
|
146
|
+
readonly usage: AiUsage;
|
|
147
|
+
} | {
|
|
148
|
+
readonly type: 'result';
|
|
149
|
+
readonly evaluationId: number;
|
|
150
|
+
readonly name: string;
|
|
151
|
+
readonly subject: Subject;
|
|
152
|
+
readonly result: CheckResult;
|
|
153
|
+
} | {
|
|
154
|
+
readonly type: 'trace';
|
|
155
|
+
readonly evaluationId?: number;
|
|
156
|
+
readonly name: string;
|
|
157
|
+
readonly message: string;
|
|
158
|
+
readonly details?: JsonValue;
|
|
159
|
+
} | {
|
|
160
|
+
readonly type: 'error';
|
|
161
|
+
readonly evaluationId?: number;
|
|
162
|
+
readonly name?: string;
|
|
163
|
+
readonly stage: string;
|
|
164
|
+
readonly message: string;
|
|
165
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { JsonValue } from './rule.js';
|
|
2
|
+
export interface RuleTestCase {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly files: Readonly<Record<string, JsonValue>>;
|
|
5
|
+
readonly expected: 'pass' | 'violation' | 'skipped';
|
|
6
|
+
}
|
|
7
|
+
export interface RuleTestResult {
|
|
8
|
+
readonly ruleName: string;
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly expected: RuleTestCase['expected'];
|
|
11
|
+
readonly actual: RuleTestCase['expected'] | 'timeout';
|
|
12
|
+
readonly durationMs: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function test(name: string): {
|
|
15
|
+
withFiles(files: RuleTestCase['files']): {
|
|
16
|
+
passes: () => RuleTestCase;
|
|
17
|
+
violates: () => RuleTestCase;
|
|
18
|
+
skips: () => RuleTestCase;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function test(name) {
|
|
2
|
+
return {
|
|
3
|
+
withFiles(files) {
|
|
4
|
+
return {
|
|
5
|
+
passes: () => ({ name, files, expected: 'pass' }),
|
|
6
|
+
violates: () => ({ name, files, expected: 'violation' }),
|
|
7
|
+
skips: () => ({ name, files, expected: 'skipped' }),
|
|
8
|
+
};
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { Project } from './ports.js';
|
|
2
|
+
export type Awaitable<T> = T | Promise<T>;
|
|
3
|
+
export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
|
|
4
|
+
readonly [key: string]: JsonValue;
|
|
5
|
+
};
|
|
6
|
+
export type PredicateResult = boolean | {
|
|
7
|
+
readonly applies: boolean;
|
|
8
|
+
readonly reason?: string;
|
|
9
|
+
};
|
|
10
|
+
export interface SourceFile {
|
|
11
|
+
readonly filepath: string;
|
|
12
|
+
readonly source: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ScopeMatch<T = JsonValue> {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly source: string;
|
|
17
|
+
readonly data?: T;
|
|
18
|
+
readonly captures?: Readonly<Record<string, string | readonly string[]>>;
|
|
19
|
+
readonly lines?: {
|
|
20
|
+
readonly start: number;
|
|
21
|
+
readonly end: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface ScopeSubject<T = JsonValue> extends ScopeMatch<T> {
|
|
25
|
+
readonly kind: 'scope';
|
|
26
|
+
readonly filepath: string;
|
|
27
|
+
}
|
|
28
|
+
export interface GroupSubject<T = JsonValue> {
|
|
29
|
+
readonly kind: 'group';
|
|
30
|
+
readonly group: {
|
|
31
|
+
readonly type: 'file' | 'folder' | 'project';
|
|
32
|
+
readonly path: string;
|
|
33
|
+
};
|
|
34
|
+
readonly members: readonly ScopeSubject<T>[];
|
|
35
|
+
}
|
|
36
|
+
export type Subject<T = JsonValue> = ScopeSubject<T> | GroupSubject<T>;
|
|
37
|
+
export type ScopeSelector<T = JsonValue> = (file: SourceFile) => Awaitable<readonly ScopeMatch<T>[]>;
|
|
38
|
+
export type Grouping = 'scope' | 'file' | 'folder' | 'project' | {
|
|
39
|
+
readonly by: 'folder';
|
|
40
|
+
readonly level: number;
|
|
41
|
+
};
|
|
42
|
+
export interface RuleSettings {
|
|
43
|
+
readonly backend?: 'jev';
|
|
44
|
+
readonly model?: string;
|
|
45
|
+
readonly threshold?: number;
|
|
46
|
+
readonly inputCostPerMillion?: number;
|
|
47
|
+
readonly outputCostPerMillion?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface TokenUsage {
|
|
50
|
+
readonly inputTokens: number;
|
|
51
|
+
readonly outputTokens: number;
|
|
52
|
+
}
|
|
53
|
+
export interface TokenPricing {
|
|
54
|
+
readonly inputCostPerMillion: number;
|
|
55
|
+
readonly outputCostPerMillion: number;
|
|
56
|
+
}
|
|
57
|
+
export interface AiUsage extends TokenUsage {
|
|
58
|
+
readonly calls: number;
|
|
59
|
+
readonly unreportedCalls: number;
|
|
60
|
+
readonly inputCost: number;
|
|
61
|
+
readonly outputCost: number;
|
|
62
|
+
}
|
|
63
|
+
export interface ViolationLocation {
|
|
64
|
+
readonly filepath: string;
|
|
65
|
+
readonly scopeId?: string;
|
|
66
|
+
readonly lines?: {
|
|
67
|
+
readonly start: number;
|
|
68
|
+
readonly end: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export interface CheckResult {
|
|
72
|
+
readonly status: 'pass' | 'violation';
|
|
73
|
+
readonly message?: string;
|
|
74
|
+
readonly locations?: readonly ViolationLocation[];
|
|
75
|
+
readonly probability?: number;
|
|
76
|
+
readonly threshold?: number;
|
|
77
|
+
readonly model?: string;
|
|
78
|
+
readonly usage?: AiUsage;
|
|
79
|
+
}
|
|
80
|
+
export interface AiExamples {
|
|
81
|
+
readonly good?: readonly string[];
|
|
82
|
+
readonly bad?: readonly string[];
|
|
83
|
+
}
|
|
84
|
+
export interface AiOptions<T = JsonValue> {
|
|
85
|
+
readonly rule: string;
|
|
86
|
+
readonly examples?: AiExamples;
|
|
87
|
+
readonly violationMessage?: string;
|
|
88
|
+
readonly input?: (subject: Subject<T>, context: ProjectContext) => Awaitable<JsonValue>;
|
|
89
|
+
}
|
|
90
|
+
export type Evaluator<T = JsonValue> = (subject: Subject<T>, context: CheckContext<T>) => Awaitable<CheckResult>;
|
|
91
|
+
export interface ProjectContext {
|
|
92
|
+
readonly project: Project;
|
|
93
|
+
trace(message: string, details?: JsonValue): void;
|
|
94
|
+
}
|
|
95
|
+
export interface Selection<T = JsonValue> {
|
|
96
|
+
readonly files: readonly string[];
|
|
97
|
+
readonly exclude?: readonly string[];
|
|
98
|
+
readonly scope?: ScopeSelector<T>;
|
|
99
|
+
}
|
|
100
|
+
export interface SelectionContext extends ProjectContext {
|
|
101
|
+
select<T>(selection: Selection<T>): Promise<readonly ScopeSubject<T>[]>;
|
|
102
|
+
}
|
|
103
|
+
export interface CheckContext<T = JsonValue> extends SelectionContext {
|
|
104
|
+
readonly ruleName: string;
|
|
105
|
+
ai(options: AiOptions<T>): Promise<CheckResult>;
|
|
106
|
+
}
|
|
107
|
+
export declare const RULE_BRAND: symbol;
|
|
108
|
+
export declare abstract class Rule<T = JsonValue> {
|
|
109
|
+
enabled: boolean;
|
|
110
|
+
files: readonly string[];
|
|
111
|
+
exclude: readonly string[];
|
|
112
|
+
tags?: readonly string[];
|
|
113
|
+
scope?: ScopeSelector<T>;
|
|
114
|
+
settings: RuleSettings;
|
|
115
|
+
group: Grouping;
|
|
116
|
+
comment?: string;
|
|
117
|
+
when(_context: ProjectContext): Awaitable<PredicateResult>;
|
|
118
|
+
filter(_subject: ScopeSubject<T>, _context: ProjectContext): Awaitable<PredicateResult>;
|
|
119
|
+
select(context: SelectionContext): Awaitable<readonly ScopeSubject<T>[]>;
|
|
120
|
+
abstract check: Evaluator<T>;
|
|
121
|
+
}
|
package/dist/app/rule.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const RULE_BRAND = Symbol.for('coderuler.Rule');
|
|
2
|
+
export class Rule {
|
|
3
|
+
enabled = true;
|
|
4
|
+
files = ['**/*'];
|
|
5
|
+
exclude = [];
|
|
6
|
+
tags;
|
|
7
|
+
scope;
|
|
8
|
+
settings = {};
|
|
9
|
+
group = 'scope';
|
|
10
|
+
comment;
|
|
11
|
+
when(_context) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
filter(_subject, _context) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
select(context) {
|
|
18
|
+
const { files, exclude, scope } = this;
|
|
19
|
+
return scope === undefined
|
|
20
|
+
? context.select({ files, exclude })
|
|
21
|
+
: context.select({ files, exclude, scope });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(Rule.prototype, RULE_BRAND, { value: true, enumerable: false });
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
function lineCount(source) {
|
|
2
|
+
let count = 1;
|
|
3
|
+
let index = 0;
|
|
4
|
+
while (index < source.length) {
|
|
5
|
+
const code = source.charCodeAt(index);
|
|
6
|
+
if (code === 10) {
|
|
7
|
+
count += 1;
|
|
8
|
+
}
|
|
9
|
+
else if (code === 13) {
|
|
10
|
+
count += 1;
|
|
11
|
+
if (source.charCodeAt(index + 1) === 10)
|
|
12
|
+
index += 1;
|
|
13
|
+
}
|
|
14
|
+
index += 1;
|
|
15
|
+
}
|
|
16
|
+
const last = source.charCodeAt(source.length - 1);
|
|
17
|
+
if (source.length > 0 && (last === 10 || last === 13))
|
|
18
|
+
count -= 1;
|
|
19
|
+
return count;
|
|
20
|
+
}
|
|
21
|
+
export function wholeFileScope(file) {
|
|
22
|
+
return [{ id: '$', source: file.source, lines: { start: 1, end: lineCount(file.source) } }];
|
|
23
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { validateAiUsage } from './validate.js';
|
|
2
|
+
export function addUsage(current, usage) {
|
|
3
|
+
if (current === undefined)
|
|
4
|
+
return { ...usage };
|
|
5
|
+
return validateAiUsage({
|
|
6
|
+
calls: current.calls + usage.calls,
|
|
7
|
+
unreportedCalls: current.unreportedCalls + usage.unreportedCalls,
|
|
8
|
+
inputTokens: current.inputTokens + usage.inputTokens,
|
|
9
|
+
outputTokens: current.outputTokens + usage.outputTokens,
|
|
10
|
+
inputCost: current.inputCost + usage.inputCost,
|
|
11
|
+
outputCost: current.outputCost + usage.outputCost,
|
|
12
|
+
}, 'Accumulated AI usage');
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AiUsage, CheckResult, JsonValue, PredicateResult, Rule, ScopeMatch, ScopeSubject, Subject } from './rule.js';
|
|
2
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
3
|
+
export declare function isRuleBranded(value: unknown): boolean;
|
|
4
|
+
export declare function validateRule(value: unknown, ruleFile: string): Rule<unknown>;
|
|
5
|
+
export declare function validateJsonValue(value: unknown, label: string): JsonValue;
|
|
6
|
+
export declare function validateScopeMatch(value: unknown, label: string): ScopeMatch<JsonValue>;
|
|
7
|
+
export declare function validateScopeSubject(value: unknown, label: string): ScopeSubject<JsonValue>;
|
|
8
|
+
export declare function validateScopeSubjects(value: unknown, label: string): readonly ScopeSubject<JsonValue>[];
|
|
9
|
+
export declare function validatePredicateResult(value: unknown, label: string): PredicateResult;
|
|
10
|
+
export declare function validateAiUsage(value: unknown, label: string): AiUsage;
|
|
11
|
+
export declare function validateCheckResult(value: unknown, label: string, subject?: Subject<unknown>): CheckResult;
|