@agentgrader/scorer-static 0.1.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.
@@ -0,0 +1,28 @@
1
+ import { Scorer, AgentResult, ScorerResult } from '@agentgrader/core';
2
+
3
+ /**
4
+ * deterministic, additive code-quality scorer: diff size, files touched,
5
+ * todo/fixme markers introduced, and biome lint violations on the changed
6
+ * files. never blocks a run (`passed` is always `true`) - it only annotates
7
+ * `metrics["static-quality"]` with `quality` data for reporting/optimizer
8
+ * use.
9
+ *
10
+ * no llm calls. lint runs via `npx @biomejs/biome` inside the sandbox; if
11
+ * that's unavailable (no network, image without npm), `linterviolations`
12
+ * degrades to `0` rather than failing the run.
13
+ */
14
+ declare class StaticQualityScorer implements Scorer {
15
+ readonly name = "static-quality";
16
+ score(input: {
17
+ result: AgentResult;
18
+ sandbox: {
19
+ exec(cmd: string): Promise<{
20
+ stdout: string;
21
+ stderr: string;
22
+ exitCode: number;
23
+ }>;
24
+ };
25
+ }): Promise<ScorerResult>;
26
+ }
27
+
28
+ export { StaticQualityScorer };
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ import { parseDiffStats } from '@agentgrader/core';
2
+
3
+ // src/index.ts
4
+ var TODO_PATTERN = /^\+.*\b(TODO|FIXME|HACK|XXX)\b/gm;
5
+ var StaticQualityScorer = class {
6
+ name = "static-quality";
7
+ async score(input) {
8
+ const diff = input.result.finalDiff ?? "";
9
+ const stats = parseDiffStats(diff);
10
+ const diffLines = stats.linesChanged;
11
+ const filesModified = stats.filesChanged.length;
12
+ const todosIntroduced = (diff.match(TODO_PATTERN) ?? []).length;
13
+ let linterViolations = 0;
14
+ if (stats.filesChanged.length > 0) {
15
+ try {
16
+ const fileArgs = stats.filesChanged.map((f) => `"${f}"`).join(" ");
17
+ const res = await input.sandbox.exec(
18
+ `npx --yes @biomejs/biome@2 check ${fileArgs} --reporter=json 2>/dev/null || echo '{}'`
19
+ );
20
+ linterViolations = parseBiomeViolationCount(res.stdout);
21
+ } catch {
22
+ }
23
+ }
24
+ return {
25
+ passed: true,
26
+ detail: `diff:${diffLines}L files:${filesModified} todos:${todosIntroduced} lint:${linterViolations}`,
27
+ quality: {
28
+ diffLines,
29
+ filesModified,
30
+ todosIntroduced,
31
+ linterViolations
32
+ }
33
+ };
34
+ }
35
+ };
36
+ function parseBiomeViolationCount(output) {
37
+ try {
38
+ const parsed = JSON.parse(output);
39
+ const errors = parsed?.summary?.errors;
40
+ const warnings = parsed?.summary?.warnings;
41
+ if (typeof errors === "number" || typeof warnings === "number") {
42
+ return (errors ?? 0) + (warnings ?? 0);
43
+ }
44
+ if (Array.isArray(parsed?.diagnostics)) {
45
+ return parsed.diagnostics.length;
46
+ }
47
+ } catch {
48
+ }
49
+ return 0;
50
+ }
51
+
52
+ export { StaticQualityScorer };
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@agentgrader/scorer-static",
3
+ "version": "0.1.0",
4
+ "description": "Deterministic, non-blocking code-quality scorer (diff size, TODOs, lint) for the Agentgrader framework",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup src/index.ts --format esm --dts --clean --treeshake",
21
+ "build:watch": "tsup src/index.ts --format esm --dts --watch"
22
+ },
23
+ "dependencies": {
24
+ "@agentgrader/core": "^1.1.0"
25
+ },
26
+ "devDependencies": {
27
+ "tsup": "^8.5.1"
28
+ },
29
+ "peerDependencies": {
30
+ "@agentgrader/core": "^1.1.0"
31
+ }
32
+ }