jevkit-lint 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.
- package/README.md +119 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +157 -0
- package/dist/cli.js.map +1 -0
- package/dist/diagnostic.d.ts +31 -0
- package/dist/diagnostic.d.ts.map +1 -0
- package/dist/diagnostic.js +60 -0
- package/dist/diagnostic.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/linter.d.ts +51 -0
- package/dist/linter.d.ts.map +1 -0
- package/dist/linter.js +72 -0
- package/dist/linter.js.map +1 -0
- package/dist/rules.d.ts +29 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +433 -0
- package/dist/rules.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# jevkit-lint
|
|
2
|
+
|
|
3
|
+
Static linter for [TypeSafe](https://typesafe.ai) Jev questions.
|
|
4
|
+
|
|
5
|
+
TypeSafe publishes a [list of failure modes](https://docs.typesafe.ai/model-jaggedness/jev-1.13)
|
|
6
|
+
for `jev-1.13`: it reads instructions literally, it cannot count, it reads dates
|
|
7
|
+
as text rather than ordered quantities, it loses accuracy on indirection. Most
|
|
8
|
+
of those are visible in your question definitions before you send anything.
|
|
9
|
+
|
|
10
|
+
`jevkit-lint` reads the definitions and tells you. It never calls the API, so it
|
|
11
|
+
needs no key and costs nothing to run in CI.
|
|
12
|
+
|
|
13
|
+
> Unofficial and unaffiliated with TypeSafe.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install jevkit-lint
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Use
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { lint } from "jevkit-lint";
|
|
25
|
+
|
|
26
|
+
const result = lint({
|
|
27
|
+
urgency: { type: "noul", instructions: "How many days has the customer waited?" },
|
|
28
|
+
team: {
|
|
29
|
+
type: "choice",
|
|
30
|
+
instructions: "Which team should handle this",
|
|
31
|
+
criteria: { billing: "Payment issues", technical: "Bugs" },
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log(result.format());
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
urgency: error [JEV001] Question asks the model to count or do arithmetic.
|
|
40
|
+
found: How many
|
|
41
|
+
hint: jev-1.13 is not a calculator and does not count reliably. Iterate the
|
|
42
|
+
candidates in code, ask one Noul per item, and sum the answers yourself.
|
|
43
|
+
team: warning [JEV008] Choice has no no-match option.
|
|
44
|
+
found: billing, technical
|
|
45
|
+
hint: A Choice always returns one of its options. With nothing meaning 'none of
|
|
46
|
+
these', a state that fits no option still produces a confident-looking
|
|
47
|
+
answer. Add an explicit none/unknown option, or gate on a separate
|
|
48
|
+
presence Noul.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`result.ok` is `true` when nothing rose to an error, so it drops straight into a
|
|
52
|
+
guard:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
if (!lint(questions, { state }).ok) {
|
|
56
|
+
throw new Error("refusing to send a request that will not answer what we meant");
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## CLI
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx jevkit-lint request.json # a {state, questions} object, or bare questions
|
|
64
|
+
npx jevkit-lint cassette.jevl # lint every recorded request
|
|
65
|
+
npx jevkit-lint - < request.json # stdin
|
|
66
|
+
npx jevkit-lint request.json --strict # exit non-zero on warnings too
|
|
67
|
+
npx jevkit-lint request.json --format json
|
|
68
|
+
npx jevkit-lint --list-rules
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Exit codes: `0` clean, `1` findings, `2` bad usage.
|
|
72
|
+
|
|
73
|
+
## Rules
|
|
74
|
+
|
|
75
|
+
Each rule names the documented failure mode it comes from.
|
|
76
|
+
|
|
77
|
+
| Code | Rule | Failure mode |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| JEV001 | math-and-counting | Math and Numbers |
|
|
80
|
+
| JEV002 | date-comparison | Date and time comparison |
|
|
81
|
+
| JEV003 | generation-request | Generation |
|
|
82
|
+
| JEV004 | negation | Literal reading |
|
|
83
|
+
| JEV005 | vague-scoping | Literal reading |
|
|
84
|
+
| JEV006 | indirection | Indirection |
|
|
85
|
+
| JEV007 | noul-polarity | Contradictory instructions and criteria |
|
|
86
|
+
| JEV008 | choice-no-match | Common-sense structural invariants |
|
|
87
|
+
| JEV009 | choice-arity | Common-sense structural invariants |
|
|
88
|
+
| JEV010 | option-descriptions | Literal reading |
|
|
89
|
+
| JEV011 | score-levels | Literal reading |
|
|
90
|
+
| JEV012 | instructions-present | Literal reading |
|
|
91
|
+
| JEV013 | question-id-reference | Indirection |
|
|
92
|
+
| JEV014 | state-budget | Large state full of irrelevant detail |
|
|
93
|
+
| JEV015 | total-budget | Large state full of irrelevant detail |
|
|
94
|
+
| JEV016 | state-noise-ratio | Large state full of irrelevant detail |
|
|
95
|
+
| JEV017 | numeric-representation | Math and Numbers |
|
|
96
|
+
| JEV018 | duplicate-questions | Common-sense structural invariants |
|
|
97
|
+
|
|
98
|
+
Select or suppress by code:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
lint(questions, { select: ["JEV001", "JEV002"] });
|
|
102
|
+
lint(questions, { ignore: ["JEV008"] });
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## What it cannot do
|
|
106
|
+
|
|
107
|
+
Adversarial content is a documented failure mode and is **not** linted. Whether
|
|
108
|
+
a state is hostile depends on the content at runtime, not on the question
|
|
109
|
+
definition, so a static rule would be theatre. Screen untrusted state at
|
|
110
|
+
request time instead.
|
|
111
|
+
|
|
112
|
+
Token counts are estimates. jevkit deliberately does not bundle a tokenizer:
|
|
113
|
+
TypeSafe does not publish which one Jev uses, and a confidently wrong count is
|
|
114
|
+
worse than an honest approximation. The estimator errs conservative, so leave
|
|
115
|
+
headroom near the limits.
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** `jevkit-lint` command line interface. */
|
|
3
|
+
export declare const EXIT_OK = 0;
|
|
4
|
+
export declare const EXIT_FINDINGS = 1;
|
|
5
|
+
export declare const EXIT_USAGE = 2;
|
|
6
|
+
export declare function main(argv?: string[]): number;
|
|
7
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,4CAA4C;AAS5C,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,UAAU,IAAI,CAAC;AA6C5B,wBAAgB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,MAAM,CAsGnE"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** `jevkit-lint` command line interface. */
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { RecordFormatError, parseRecords } from "jevkit-core";
|
|
5
|
+
import { lint } from "./linter.js";
|
|
6
|
+
import { RULES } from "./rules.js";
|
|
7
|
+
export const EXIT_OK = 0;
|
|
8
|
+
export const EXIT_FINDINGS = 1;
|
|
9
|
+
export const EXIT_USAGE = 2;
|
|
10
|
+
function readStdin() {
|
|
11
|
+
try {
|
|
12
|
+
return readFileSync(0, "utf8");
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function loadPayload(path) {
|
|
19
|
+
const text = path === "-" ? readStdin() : readFileSync(path, "utf8");
|
|
20
|
+
const source = path === "-" ? "<stdin>" : path;
|
|
21
|
+
if (path.endsWith(".jevl")) {
|
|
22
|
+
return parseRecords(text, source).map((record, i) => ({
|
|
23
|
+
label: `${source}#${i}`,
|
|
24
|
+
state: record.state,
|
|
25
|
+
questions: record.questions,
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
const data = JSON.parse(text);
|
|
29
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
30
|
+
throw new Error(`${source}: expected a JSON object at the top level`);
|
|
31
|
+
}
|
|
32
|
+
const obj = data;
|
|
33
|
+
const q = obj["questions"];
|
|
34
|
+
if (q && typeof q === "object" && !Array.isArray(q)) {
|
|
35
|
+
return [{ label: source, state: obj["state"] ?? "", questions: q }];
|
|
36
|
+
}
|
|
37
|
+
return [{ label: source, state: "", questions: obj }];
|
|
38
|
+
}
|
|
39
|
+
function printRules() {
|
|
40
|
+
const width = Math.max(...RULES.map((r) => r.name.length));
|
|
41
|
+
console.log("code name".padEnd(8 + width + 2) + " documented failure mode");
|
|
42
|
+
console.log("-".repeat(8 + width + 42));
|
|
43
|
+
for (const r of RULES) {
|
|
44
|
+
console.log(`${r.code} ${r.name.padEnd(width)} ${r.mode}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function main(argv = process.argv.slice(2)) {
|
|
48
|
+
const files = [];
|
|
49
|
+
let select;
|
|
50
|
+
let ignore;
|
|
51
|
+
let format = "text";
|
|
52
|
+
let strict = false;
|
|
53
|
+
let noColor = false;
|
|
54
|
+
for (let i = 0; i < argv.length; i++) {
|
|
55
|
+
const arg = argv[i];
|
|
56
|
+
switch (arg) {
|
|
57
|
+
case "--select":
|
|
58
|
+
select = argv[++i]?.split(",");
|
|
59
|
+
break;
|
|
60
|
+
case "--ignore":
|
|
61
|
+
ignore = argv[++i]?.split(",");
|
|
62
|
+
break;
|
|
63
|
+
case "--format": {
|
|
64
|
+
const v = argv[++i];
|
|
65
|
+
if (v !== "text" && v !== "json") {
|
|
66
|
+
console.error(`jevkit-lint: --format expects text or json`);
|
|
67
|
+
return EXIT_USAGE;
|
|
68
|
+
}
|
|
69
|
+
format = v;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case "--strict":
|
|
73
|
+
strict = true;
|
|
74
|
+
break;
|
|
75
|
+
case "--no-color":
|
|
76
|
+
noColor = true;
|
|
77
|
+
break;
|
|
78
|
+
case "--list-rules":
|
|
79
|
+
printRules();
|
|
80
|
+
return EXIT_OK;
|
|
81
|
+
case "-h":
|
|
82
|
+
case "--help":
|
|
83
|
+
console.log("usage: jevkit-lint [files...] [--select CODES] [--ignore CODES]\n" +
|
|
84
|
+
" [--format text|json] [--strict] [--no-color] [--list-rules]\n\n" +
|
|
85
|
+
"Statically lint TypeSafe Jev questions against the documented jev-1.13\n" +
|
|
86
|
+
"failure modes. Never calls the API.");
|
|
87
|
+
return EXIT_OK;
|
|
88
|
+
default:
|
|
89
|
+
if (arg.startsWith("--")) {
|
|
90
|
+
console.error(`jevkit-lint: unknown option ${arg}`);
|
|
91
|
+
return EXIT_USAGE;
|
|
92
|
+
}
|
|
93
|
+
files.push(arg);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (!files.length) {
|
|
97
|
+
console.error("jevkit-lint: no input files (use - to read stdin, or --list-rules)");
|
|
98
|
+
return EXIT_USAGE;
|
|
99
|
+
}
|
|
100
|
+
const payloads = [];
|
|
101
|
+
for (const path of files) {
|
|
102
|
+
try {
|
|
103
|
+
payloads.push(...loadPayload(path));
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
const message = err instanceof RecordFormatError ? err.message : err.message;
|
|
107
|
+
console.error(`jevkit-lint: ${message}`);
|
|
108
|
+
return EXIT_USAGE;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const color = Boolean(process.stdout.isTTY) && !noColor;
|
|
112
|
+
const reports = [];
|
|
113
|
+
let anyError = false;
|
|
114
|
+
let anyWarning = false;
|
|
115
|
+
for (const { label, state, questions } of payloads) {
|
|
116
|
+
let result;
|
|
117
|
+
try {
|
|
118
|
+
result = lint(questions, { state, select, ignore });
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
console.error(`jevkit-lint: ${label}: ${err.message}`);
|
|
122
|
+
return EXIT_USAGE;
|
|
123
|
+
}
|
|
124
|
+
anyError = anyError || result.errors.length > 0;
|
|
125
|
+
anyWarning = anyWarning || result.warnings.length > 0;
|
|
126
|
+
reports.push({ label, result });
|
|
127
|
+
}
|
|
128
|
+
if (format === "json") {
|
|
129
|
+
console.log(JSON.stringify({ results: reports.map(({ label, result }) => ({ source: label, ...result.toJSON() })) }, null, 2));
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const total = { error: 0, warning: 0, info: 0 };
|
|
133
|
+
for (const { label, result } of reports) {
|
|
134
|
+
if (payloads.length > 1)
|
|
135
|
+
console.log(`== ${label}`);
|
|
136
|
+
console.log(result.format(color));
|
|
137
|
+
if (payloads.length > 1)
|
|
138
|
+
console.log("");
|
|
139
|
+
const c = result.counts();
|
|
140
|
+
total.error += c.error;
|
|
141
|
+
total.warning += c.warning;
|
|
142
|
+
total.info += c.info;
|
|
143
|
+
}
|
|
144
|
+
if (total.error + total.warning + total.info > 0) {
|
|
145
|
+
console.log(`\n${total.error} error(s), ${total.warning} warning(s), ${total.info} info`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (anyError)
|
|
149
|
+
return EXIT_FINDINGS;
|
|
150
|
+
if (strict && anyWarning)
|
|
151
|
+
return EXIT_FINDINGS;
|
|
152
|
+
return EXIT_OK;
|
|
153
|
+
}
|
|
154
|
+
const invokedDirectly = process.argv[1] !== undefined && import.meta.url === `file://${process.argv[1]}`;
|
|
155
|
+
if (invokedDirectly)
|
|
156
|
+
process.exit(main());
|
|
157
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Diagnostics produced by the linter. */
|
|
2
|
+
export type Severity = "error" | "warning" | "info";
|
|
3
|
+
export interface DiagnosticInit {
|
|
4
|
+
code: string;
|
|
5
|
+
severity: Severity;
|
|
6
|
+
questionId: string | null;
|
|
7
|
+
message: string;
|
|
8
|
+
hint: string;
|
|
9
|
+
evidence?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class Diagnostic {
|
|
12
|
+
readonly code: string;
|
|
13
|
+
readonly severity: Severity;
|
|
14
|
+
readonly questionId: string | null;
|
|
15
|
+
readonly message: string;
|
|
16
|
+
readonly hint: string;
|
|
17
|
+
readonly evidence: string;
|
|
18
|
+
constructor(init: DiagnosticInit);
|
|
19
|
+
get sortKey(): [number, string, string];
|
|
20
|
+
format(color?: boolean): string;
|
|
21
|
+
toJSON(): {
|
|
22
|
+
code: string;
|
|
23
|
+
severity: Severity;
|
|
24
|
+
questionId: string | null;
|
|
25
|
+
message: string;
|
|
26
|
+
hint: string;
|
|
27
|
+
evidence: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export declare function compareDiagnostics(a: Diagnostic, b: Diagnostic): number;
|
|
31
|
+
//# sourceMappingURL=diagnostic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic.d.ts","sourceRoot":"","sources":["../src/diagnostic.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAE1C,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAIpD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,IAAI,EAAE,cAAc;IAShC,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAEtC;IAED,MAAM,CAAC,KAAK,UAAQ,GAAG,MAAM;IAiB7B,MAAM;;;;;;;;CAUP;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAOvE"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Diagnostics produced by the linter. */
|
|
2
|
+
const ORDER = { error: 0, warning: 1, info: 2 };
|
|
3
|
+
export class Diagnostic {
|
|
4
|
+
code;
|
|
5
|
+
severity;
|
|
6
|
+
questionId;
|
|
7
|
+
message;
|
|
8
|
+
hint;
|
|
9
|
+
evidence;
|
|
10
|
+
constructor(init) {
|
|
11
|
+
this.code = init.code;
|
|
12
|
+
this.severity = init.severity;
|
|
13
|
+
this.questionId = init.questionId;
|
|
14
|
+
this.message = init.message;
|
|
15
|
+
this.hint = init.hint;
|
|
16
|
+
this.evidence = init.evidence ?? "";
|
|
17
|
+
}
|
|
18
|
+
get sortKey() {
|
|
19
|
+
return [ORDER[this.severity], this.code, this.questionId ?? ""];
|
|
20
|
+
}
|
|
21
|
+
format(color = false) {
|
|
22
|
+
const loc = this.questionId ?? "<request>";
|
|
23
|
+
let head = `${loc}: ${this.severity} [${this.code}] ${this.message}`;
|
|
24
|
+
if (color) {
|
|
25
|
+
const tint = {
|
|
26
|
+
error: "\u001b[31m",
|
|
27
|
+
warning: "\u001b[33m",
|
|
28
|
+
info: "\u001b[36m",
|
|
29
|
+
};
|
|
30
|
+
head = `${tint[this.severity]}${head}\u001b[0m`;
|
|
31
|
+
}
|
|
32
|
+
const lines = [head];
|
|
33
|
+
if (this.evidence)
|
|
34
|
+
lines.push(` found: ${this.evidence}`);
|
|
35
|
+
lines.push(` hint: ${this.hint}`);
|
|
36
|
+
return lines.join("\n");
|
|
37
|
+
}
|
|
38
|
+
toJSON() {
|
|
39
|
+
return {
|
|
40
|
+
code: this.code,
|
|
41
|
+
severity: this.severity,
|
|
42
|
+
questionId: this.questionId,
|
|
43
|
+
message: this.message,
|
|
44
|
+
hint: this.hint,
|
|
45
|
+
evidence: this.evidence,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function compareDiagnostics(a, b) {
|
|
50
|
+
const [as_, ac, aq] = a.sortKey;
|
|
51
|
+
const [bs, bc, bq] = b.sortKey;
|
|
52
|
+
if (as_ !== bs)
|
|
53
|
+
return as_ - bs;
|
|
54
|
+
if (ac !== bc)
|
|
55
|
+
return ac < bc ? -1 : 1;
|
|
56
|
+
if (aq !== bq)
|
|
57
|
+
return aq < bq ? -1 : 1;
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=diagnostic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic.js","sourceRoot":"","sources":["../src/diagnostic.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAI1C,MAAM,KAAK,GAA6B,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAW1E,MAAM,OAAO,UAAU;IACZ,IAAI,CAAS;IACb,QAAQ,CAAW;IACnB,UAAU,CAAgB;IAC1B,OAAO,CAAS;IAChB,IAAI,CAAS;IACb,QAAQ,CAAS;IAE1B,YAAY,IAAoB;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,IAAI,OAAO;QACT,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,CAAC,KAAK,GAAG,KAAK;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,WAAW,CAAC;QAC3C,IAAI,IAAI,GAAG,GAAG,GAAG,KAAK,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;QACrE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,GAA6B;gBACrC,KAAK,EAAE,YAAY;gBACnB,OAAO,EAAE,YAAY;gBACrB,IAAI,EAAE,YAAY;aACnB,CAAC;YACF,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,WAAW,CAAC;QAClD,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,QAAQ;YAAE,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7D,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC;IACJ,CAAC;CACF;AAED,MAAM,UAAU,kBAAkB,CAAC,CAAa,EAAE,CAAa;IAC7D,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;IAChC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;IAC/B,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,GAAG,GAAG,EAAE,CAAC;IAChC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static linter for TypeSafe Jev questions.
|
|
3
|
+
*
|
|
4
|
+
* Catches the failure modes TypeSafe documents for jev-1.13 before you spend a
|
|
5
|
+
* token on them. Needs no API key.
|
|
6
|
+
*/
|
|
7
|
+
export { Diagnostic, type Severity } from "./diagnostic.js";
|
|
8
|
+
export { LintResult, lint, type LintOptions } from "./linter.js";
|
|
9
|
+
export { RULES, allCodes, rulesFor, type Rule, type LintContext } from "./rules.js";
|
|
10
|
+
export declare const VERSION = "0.1.0";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEpF,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static linter for TypeSafe Jev questions.
|
|
3
|
+
*
|
|
4
|
+
* Catches the failure modes TypeSafe documents for jev-1.13 before you spend a
|
|
5
|
+
* token on them. Needs no API key.
|
|
6
|
+
*/
|
|
7
|
+
export { Diagnostic } from "./diagnostic.js";
|
|
8
|
+
export { LintResult, lint } from "./linter.js";
|
|
9
|
+
export { RULES, allCodes, rulesFor } from "./rules.js";
|
|
10
|
+
export const VERSION = "0.1.0";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAiB,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,IAAI,EAAoB,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAA+B,MAAM,YAAY,CAAC;AAEpF,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
package/dist/linter.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** The lint entry point. */
|
|
2
|
+
import { Diagnostic, type Severity } from "./diagnostic.js";
|
|
3
|
+
export interface LintOptions {
|
|
4
|
+
state?: unknown;
|
|
5
|
+
select?: Iterable<string>;
|
|
6
|
+
ignore?: Iterable<string>;
|
|
7
|
+
}
|
|
8
|
+
/** Diagnostics for one request, ordered most severe first. */
|
|
9
|
+
export declare class LintResult {
|
|
10
|
+
readonly diagnostics: Diagnostic[];
|
|
11
|
+
constructor(diagnostics: Diagnostic[]);
|
|
12
|
+
[Symbol.iterator](): Iterator<Diagnostic>;
|
|
13
|
+
get length(): number;
|
|
14
|
+
bySeverity(severity: Severity): Diagnostic[];
|
|
15
|
+
get errors(): Diagnostic[];
|
|
16
|
+
get warnings(): Diagnostic[];
|
|
17
|
+
get infos(): Diagnostic[];
|
|
18
|
+
/** True when nothing rose to an error. */
|
|
19
|
+
get ok(): boolean;
|
|
20
|
+
counts(): {
|
|
21
|
+
error: number;
|
|
22
|
+
warning: number;
|
|
23
|
+
info: number;
|
|
24
|
+
};
|
|
25
|
+
toJSON(): {
|
|
26
|
+
ok: boolean;
|
|
27
|
+
counts: {
|
|
28
|
+
error: number;
|
|
29
|
+
warning: number;
|
|
30
|
+
info: number;
|
|
31
|
+
};
|
|
32
|
+
diagnostics: {
|
|
33
|
+
code: string;
|
|
34
|
+
severity: Severity;
|
|
35
|
+
questionId: string | null;
|
|
36
|
+
message: string;
|
|
37
|
+
hint: string;
|
|
38
|
+
evidence: string;
|
|
39
|
+
}[];
|
|
40
|
+
};
|
|
41
|
+
format(color?: boolean): string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Lint a jev request without calling the API.
|
|
45
|
+
*
|
|
46
|
+
* `questions` accepts SDK objects or plain objects. `state` is optional: omit it
|
|
47
|
+
* to check the questions alone, though the budget rules can only report
|
|
48
|
+
* meaningfully when the real state is supplied.
|
|
49
|
+
*/
|
|
50
|
+
export declare function lint(questions: Record<string, unknown>, options?: LintOptions): LintResult;
|
|
51
|
+
//# sourceMappingURL=linter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAI5B,OAAO,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAsB,MAAM,iBAAiB,CAAC;AAGhF,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC3B;AAED,8DAA8D;AAC9D,qBAAa,UAAU;IACrB,QAAQ,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC;gBAEvB,WAAW,EAAE,UAAU,EAAE;IAIrC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC;IAIzC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,UAAU,EAAE;IAI5C,IAAI,MAAM,IAAI,UAAU,EAAE,CAEzB;IAED,IAAI,QAAQ,IAAI,UAAU,EAAE,CAE3B;IAED,IAAI,KAAK,IAAI,UAAU,EAAE,CAExB;IAED,0CAA0C;IAC1C,IAAI,EAAE,IAAI,OAAO,CAEhB;IAED,MAAM,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAQ1D,MAAM;;;mBARa,MAAM;qBAAW,MAAM;kBAAQ,MAAM;;;;;;;;;;;IAgBxD,MAAM,CAAC,KAAK,UAAQ,GAAG,MAAM;CAI9B;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,OAAO,GAAE,WAAgB,GACxB,UAAU,CAWZ"}
|
package/dist/linter.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** The lint entry point. */
|
|
2
|
+
import { normalizeQuestions } from "jevkit-core";
|
|
3
|
+
import { compareDiagnostics } from "./diagnostic.js";
|
|
4
|
+
import { buildContext, rulesFor } from "./rules.js";
|
|
5
|
+
/** Diagnostics for one request, ordered most severe first. */
|
|
6
|
+
export class LintResult {
|
|
7
|
+
diagnostics;
|
|
8
|
+
constructor(diagnostics) {
|
|
9
|
+
this.diagnostics = [...diagnostics].sort(compareDiagnostics);
|
|
10
|
+
}
|
|
11
|
+
[Symbol.iterator]() {
|
|
12
|
+
return this.diagnostics[Symbol.iterator]();
|
|
13
|
+
}
|
|
14
|
+
get length() {
|
|
15
|
+
return this.diagnostics.length;
|
|
16
|
+
}
|
|
17
|
+
bySeverity(severity) {
|
|
18
|
+
return this.diagnostics.filter((d) => d.severity === severity);
|
|
19
|
+
}
|
|
20
|
+
get errors() {
|
|
21
|
+
return this.bySeverity("error");
|
|
22
|
+
}
|
|
23
|
+
get warnings() {
|
|
24
|
+
return this.bySeverity("warning");
|
|
25
|
+
}
|
|
26
|
+
get infos() {
|
|
27
|
+
return this.bySeverity("info");
|
|
28
|
+
}
|
|
29
|
+
/** True when nothing rose to an error. */
|
|
30
|
+
get ok() {
|
|
31
|
+
return this.errors.length === 0;
|
|
32
|
+
}
|
|
33
|
+
counts() {
|
|
34
|
+
return {
|
|
35
|
+
error: this.errors.length,
|
|
36
|
+
warning: this.warnings.length,
|
|
37
|
+
info: this.infos.length,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
toJSON() {
|
|
41
|
+
return {
|
|
42
|
+
ok: this.ok,
|
|
43
|
+
counts: this.counts(),
|
|
44
|
+
diagnostics: this.diagnostics.map((d) => d.toJSON()),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
format(color = false) {
|
|
48
|
+
if (!this.diagnostics.length)
|
|
49
|
+
return "No problems found.";
|
|
50
|
+
return this.diagnostics.map((d) => d.format(color)).join("\n");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Lint a jev request without calling the API.
|
|
55
|
+
*
|
|
56
|
+
* `questions` accepts SDK objects or plain objects. `state` is optional: omit it
|
|
57
|
+
* to check the questions alone, though the budget rules can only report
|
|
58
|
+
* meaningfully when the real state is supplied.
|
|
59
|
+
*/
|
|
60
|
+
export function lint(questions, options = {}) {
|
|
61
|
+
const normalized = normalizeQuestions(questions);
|
|
62
|
+
const ctx = buildContext(options.state ?? "", normalized);
|
|
63
|
+
const ignored = new Set([...(options.ignore ?? [])].map((c) => c.toUpperCase()));
|
|
64
|
+
const found = [];
|
|
65
|
+
for (const rule of rulesFor(options.select)) {
|
|
66
|
+
if (ignored.has(rule.code))
|
|
67
|
+
continue;
|
|
68
|
+
found.push(...rule.check(ctx));
|
|
69
|
+
}
|
|
70
|
+
return new LintResult(found);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=linter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"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"}
|
package/dist/rules.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lint rules.
|
|
3
|
+
*
|
|
4
|
+
* Every rule maps to a failure mode TypeSafe documents for `jev-1.13`
|
|
5
|
+
* (https://docs.typesafe.ai/model-jaggedness/jev-1.13) or to a structural
|
|
6
|
+
* mistake that makes an answer unusable. The `mode` field names the documented
|
|
7
|
+
* failure mode so the CLI can point at the source.
|
|
8
|
+
*
|
|
9
|
+
* Rules are static. They read your question definitions and never call the API,
|
|
10
|
+
* which is why jevkit-lint works without an API key.
|
|
11
|
+
*/
|
|
12
|
+
import { type BudgetReport, type Question } from "jevkit-core";
|
|
13
|
+
import { Diagnostic } from "./diagnostic.js";
|
|
14
|
+
export interface LintContext {
|
|
15
|
+
questions: Question[];
|
|
16
|
+
state: unknown;
|
|
17
|
+
budget: BudgetReport;
|
|
18
|
+
}
|
|
19
|
+
export interface Rule {
|
|
20
|
+
code: string;
|
|
21
|
+
name: string;
|
|
22
|
+
mode: string;
|
|
23
|
+
check: (ctx: LintContext) => Diagnostic[];
|
|
24
|
+
}
|
|
25
|
+
export declare function buildContext(state: unknown, questions: Question[]): LintContext;
|
|
26
|
+
export declare const RULES: Rule[];
|
|
27
|
+
export declare function rulesFor(codes?: Iterable<string>): Rule[];
|
|
28
|
+
export declare function allCodes(): string[];
|
|
29
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAe,MAAM,aAAa,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,UAAU,EAAE,CAAC;CAC3C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,WAAW,CAS/E;AAkbD,eAAO,MAAM,KAAK,EAAE,IAAI,EAmBvB,CAAC;AAEF,wBAAgB,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAIzD;AAED,wBAAgB,QAAQ,IAAI,MAAM,EAAE,CAEnC"}
|
package/dist/rules.js
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lint rules.
|
|
3
|
+
*
|
|
4
|
+
* Every rule maps to a failure mode TypeSafe documents for `jev-1.13`
|
|
5
|
+
* (https://docs.typesafe.ai/model-jaggedness/jev-1.13) or to a structural
|
|
6
|
+
* mistake that makes an answer unusable. The `mode` field names the documented
|
|
7
|
+
* failure mode so the CLI can point at the source.
|
|
8
|
+
*
|
|
9
|
+
* Rules are static. They read your question definitions and never call the API,
|
|
10
|
+
* which is why jevkit-lint works without an API key.
|
|
11
|
+
*/
|
|
12
|
+
import { checkBudget } from "jevkit-core";
|
|
13
|
+
import { Diagnostic } from "./diagnostic.js";
|
|
14
|
+
export function buildContext(state, questions) {
|
|
15
|
+
// Budget estimation canonicalizes its input, so questions are reduced to
|
|
16
|
+
// plain JSON here. SDK objects may not be serializable, and the raw form is
|
|
17
|
+
// only needed by rules that read the normalized view anyway.
|
|
18
|
+
const plain = {};
|
|
19
|
+
for (const q of questions) {
|
|
20
|
+
plain[q.id] = { type: q.type, instructions: q.instructions, criteria: q.criteria };
|
|
21
|
+
}
|
|
22
|
+
return { questions, state, budget: checkBudget(state, plain) };
|
|
23
|
+
}
|
|
24
|
+
function find(patterns, text) {
|
|
25
|
+
for (const pattern of patterns) {
|
|
26
|
+
const match = new RegExp(pattern.source, pattern.flags.replace("g", "")).exec(text);
|
|
27
|
+
if (match)
|
|
28
|
+
return match[0].trim();
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function findAll(pattern, text) {
|
|
33
|
+
return [...text.matchAll(new RegExp(pattern.source, pattern.flags + "g"))].map((m) => m[0]);
|
|
34
|
+
}
|
|
35
|
+
// -- JEV001 Math and Numbers ------------------------------------------------
|
|
36
|
+
const COUNT_PATTERNS = [
|
|
37
|
+
/\bhow many\b/i, /\bnumber of\b/i, /\bcount (?:the|of|how)\b/i, /\btally\b/i,
|
|
38
|
+
/\btotal (?:number|count|of)\b/i, /\bsum of\b/i, /\baverage\b/i, /\bmean of\b/i,
|
|
39
|
+
/\bcalculate\b/i, /\bcompute the\b/i, /\bpercentage of\b/i, /\bhow much (?:is|does)\b/i,
|
|
40
|
+
/\bmultipl(?:y|ied)\b/i, /\bdivided?\b/i, /\bsubtract\b/i,
|
|
41
|
+
];
|
|
42
|
+
const checkMath = (ctx) => ctx.questions.flatMap((q) => {
|
|
43
|
+
const hit = find(COUNT_PATTERNS, q.text);
|
|
44
|
+
return hit
|
|
45
|
+
? [new Diagnostic({
|
|
46
|
+
code: "JEV001", severity: "error", questionId: q.id,
|
|
47
|
+
message: "Question asks the model to count or do arithmetic.",
|
|
48
|
+
evidence: hit,
|
|
49
|
+
hint: "jev-1.13 is not a calculator and does not count reliably. Iterate the " +
|
|
50
|
+
"candidates in code, ask one Noul per item, and sum the answers yourself.",
|
|
51
|
+
})]
|
|
52
|
+
: [];
|
|
53
|
+
});
|
|
54
|
+
// -- JEV002 Date and time comparison ---------------------------------------
|
|
55
|
+
const DATE_PATTERNS = [
|
|
56
|
+
/\b(?:before|after|earlier than|later than|prior to)\b[^.?]{0,40}\b(?:date|day|month|year|deadline|timestamp)\b/i,
|
|
57
|
+
/\b(?:date|day|month|year|deadline|timestamp)\b[^.?]{0,40}\b(?:before|after|earlier|later)\b/i,
|
|
58
|
+
/\bhow (?:long|many days|many months|many years)\b/i,
|
|
59
|
+
/\bwithin \d+ (?:day|week|month|year)s?\b/i,
|
|
60
|
+
/\b(?:days|weeks|months|years) (?:between|apart|since|until)\b/i,
|
|
61
|
+
/\bmost recent\b/i, /\bchronologic(?:al|ally)\b/i,
|
|
62
|
+
/\b(?:which|what)\b[^.?]{0,30}\b(?:came|comes|happened|occurred|was|is)\s+(?:first|last|earliest|latest|more recent)\b/i,
|
|
63
|
+
/\b(?:earliest|latest|oldest|newest)\b[^.?]{0,20}\b(?:date|day|month|year|deadline|timestamp|event|entry)\b/i,
|
|
64
|
+
/\b(?:date|day|month|year|deadline|timestamp)\b[^.?]{0,20}\b(?:first|last|earliest|latest)\b/i,
|
|
65
|
+
/\bexpired?\b/i, /\boverdue\b/i, /\bin the (?:past|last|next) \d+\b/i,
|
|
66
|
+
];
|
|
67
|
+
const checkDates = (ctx) => ctx.questions.flatMap((q) => {
|
|
68
|
+
const hit = find(DATE_PATTERNS, q.text);
|
|
69
|
+
return hit
|
|
70
|
+
? [new Diagnostic({
|
|
71
|
+
code: "JEV002", severity: "error", questionId: q.id,
|
|
72
|
+
message: "Question compares or measures dates.",
|
|
73
|
+
evidence: hit,
|
|
74
|
+
hint: "jev-1.13 reads dates as text, not ordered quantities. Extract the parts " +
|
|
75
|
+
"as Choices over closed sets (12 months, 31 days, a bounded year range, " +
|
|
76
|
+
"plus an explicit 'not stated'), then order and subtract in code.",
|
|
77
|
+
})]
|
|
78
|
+
: [];
|
|
79
|
+
});
|
|
80
|
+
// -- JEV003 Generation ------------------------------------------------------
|
|
81
|
+
const GENERATION_PATTERNS = [
|
|
82
|
+
/\b(?:write|draft|compose|author) (?:a|an|the|some)\b/i,
|
|
83
|
+
/\b(?:generate|produce|create) (?:a|an|the)\s+(?:summary|response|reply|message|list|description|explanation|text|paragraph)\b/i,
|
|
84
|
+
/\bsummari[sz]e\b/i, /\bparaphrase\b/i, /\brephrase\b/i, /\brewrite\b/i,
|
|
85
|
+
/\bexplain (?:why|how|what)\b/i, /\bdescribe (?:in|the|what|how)\b/i,
|
|
86
|
+
/\bin your own words\b/i,
|
|
87
|
+
/\bprovide (?:a|an) (?:summary|explanation|rationale|reason)\b/i,
|
|
88
|
+
/\bgive (?:a|an) (?:reason|explanation|rationale)\b/i, /\btranslate\b/i,
|
|
89
|
+
];
|
|
90
|
+
const checkGeneration = (ctx) => ctx.questions.flatMap((q) => {
|
|
91
|
+
const hit = find(GENERATION_PATTERNS, q.instructionsText);
|
|
92
|
+
return hit
|
|
93
|
+
? [new Diagnostic({
|
|
94
|
+
code: "JEV003", severity: "error", questionId: q.id,
|
|
95
|
+
message: "Question asks the model to generate text.",
|
|
96
|
+
evidence: hit,
|
|
97
|
+
hint: "Jev returns typed answers and probabilities, never generated text. Use a " +
|
|
98
|
+
"generative model for this, or restate it as a selection over candidates " +
|
|
99
|
+
"your code already has.",
|
|
100
|
+
})]
|
|
101
|
+
: [];
|
|
102
|
+
});
|
|
103
|
+
// -- JEV004 Literal reading: negation --------------------------------------
|
|
104
|
+
const NEGATIONS = /\b(?:not|never|no|none|neither|nor|without|except|unless|excluding|absent|lacks?|fails? to|cannot|can't|doesn't|does not|isn't|is not|aren't|won't)\b/i;
|
|
105
|
+
const checkNegation = (ctx) => ctx.questions.flatMap((q) => {
|
|
106
|
+
const hits = findAll(NEGATIONS, q.instructionsText);
|
|
107
|
+
if (hits.length >= 2) {
|
|
108
|
+
const unique = [...new Set(hits.map((h) => h.toLowerCase()))].sort();
|
|
109
|
+
return [new Diagnostic({
|
|
110
|
+
code: "JEV004", severity: "warning", questionId: q.id,
|
|
111
|
+
message: `Instructions contain ${hits.length} negations, which compounds into a double negative.`,
|
|
112
|
+
evidence: unique.join(", "),
|
|
113
|
+
hint: "jev-1.13 reads negations literally and loses accuracy on double negatives. " +
|
|
114
|
+
"Restate positively, or split into two literal questions and combine them in code.",
|
|
115
|
+
})];
|
|
116
|
+
}
|
|
117
|
+
if (hits.length === 1 && q.type === "noul") {
|
|
118
|
+
return [new Diagnostic({
|
|
119
|
+
code: "JEV004", severity: "info", questionId: q.id,
|
|
120
|
+
message: "Noul instruction is phrased negatively.",
|
|
121
|
+
evidence: hits[0].toLowerCase(),
|
|
122
|
+
hint: "A Noul returns the probability the statement is true. A negative statement " +
|
|
123
|
+
"inverts the reading of every threshold downstream. Prefer the positive form " +
|
|
124
|
+
"and invert in code if you need it.",
|
|
125
|
+
})];
|
|
126
|
+
}
|
|
127
|
+
return [];
|
|
128
|
+
});
|
|
129
|
+
// -- JEV005 Literal reading: vague scoping ---------------------------------
|
|
130
|
+
const VAGUE = /\b(?:relevant|appropriate|important|significant|suitable|proper|good|bad|better|reasonable|acceptable|sufficient|adequate|meaningful|noteworthy|problematic)\b/i;
|
|
131
|
+
const checkVague = (ctx) => ctx.questions.flatMap((q) => {
|
|
132
|
+
const found = [...new Set(findAll(VAGUE, q.instructionsText).map((h) => h.toLowerCase()))].sort();
|
|
133
|
+
if (found.length && !q.criteriaText.trim()) {
|
|
134
|
+
return [new Diagnostic({
|
|
135
|
+
code: "JEV005", severity: "warning", questionId: q.id,
|
|
136
|
+
message: "Instructions lean on an undefined evaluative word and give no criteria to pin it down.",
|
|
137
|
+
evidence: found.join(", "),
|
|
138
|
+
hint: "jev-1.13 answers the question you wrote, not the one you meant. Define what " +
|
|
139
|
+
"the word means here in the criteria, including the boundary cases.",
|
|
140
|
+
})];
|
|
141
|
+
}
|
|
142
|
+
if (found.length >= 2) {
|
|
143
|
+
return [new Diagnostic({
|
|
144
|
+
code: "JEV005", severity: "info", questionId: q.id,
|
|
145
|
+
message: "Instructions stack several undefined evaluative words.",
|
|
146
|
+
evidence: found.join(", "),
|
|
147
|
+
hint: "Each one is a separate judgment the model has to guess at. Name the exact " +
|
|
148
|
+
"condition, or split into separate questions.",
|
|
149
|
+
})];
|
|
150
|
+
}
|
|
151
|
+
return [];
|
|
152
|
+
});
|
|
153
|
+
// -- JEV006 Indirection -----------------------------------------------------
|
|
154
|
+
const INDIRECTION_PATTERNS = [
|
|
155
|
+
/\bthe \w+ of the \w+ of the\b/i,
|
|
156
|
+
/\bwhoever\b[^.?]{0,40}\bwhose\b/i,
|
|
157
|
+
/\bif .{0,60}\bthen\b.{0,60}\bif\b/i,
|
|
158
|
+
/\bwould have (?:been|had)\b/i,
|
|
159
|
+
/\bimplies? that\b[^.?]{0,40}\bwhich\b/i,
|
|
160
|
+
/\bindirectly\b/i, /\btransitively\b/i,
|
|
161
|
+
];
|
|
162
|
+
const checkIndirection = (ctx) => ctx.questions.flatMap((q) => {
|
|
163
|
+
const hit = find(INDIRECTION_PATTERNS, q.instructionsText);
|
|
164
|
+
return hit
|
|
165
|
+
? [new Diagnostic({
|
|
166
|
+
code: "JEV006", severity: "warning", questionId: q.id,
|
|
167
|
+
message: "Instructions require multiple hops of reasoning.",
|
|
168
|
+
evidence: hit,
|
|
169
|
+
hint: "Every hop costs accuracy. Resolve the intermediate step in code and name " +
|
|
170
|
+
"the resulting state field directly in the instruction.",
|
|
171
|
+
})]
|
|
172
|
+
: [];
|
|
173
|
+
});
|
|
174
|
+
// -- JEV007 Noul polarity ---------------------------------------------------
|
|
175
|
+
const FALSEY = ["no", "false", "absent", "none", "negative", "not present", "does not", "fails"];
|
|
176
|
+
const TRUTHY = ["yes", "true", "present", "positive", "does", "passes"];
|
|
177
|
+
const checkNoulPolarity = (ctx) => ctx.questions.flatMap((q) => {
|
|
178
|
+
const c = q.criteria;
|
|
179
|
+
if (q.type !== "noul" || !c || typeof c !== "object" || Array.isArray(c))
|
|
180
|
+
return [];
|
|
181
|
+
const crit = c;
|
|
182
|
+
const trueSide = String(crit["true"] ?? "").toLowerCase();
|
|
183
|
+
const falseSide = String(crit["false"] ?? "").toLowerCase();
|
|
184
|
+
if (!trueSide && !falseSide)
|
|
185
|
+
return [];
|
|
186
|
+
const inverted = FALSEY.some((t) => trueSide.includes(t)) && TRUTHY.some((t) => falseSide.includes(t));
|
|
187
|
+
return inverted
|
|
188
|
+
? [new Diagnostic({
|
|
189
|
+
code: "JEV007", severity: "error", questionId: q.id,
|
|
190
|
+
message: "Noul criteria invert polarity: 'true' describes a no and 'false' describes a yes.",
|
|
191
|
+
evidence: `true=${JSON.stringify(trueSide)} false=${JSON.stringify(falseSide)}`,
|
|
192
|
+
hint: "TypeSafe documents this exact shape as a performance loss. Swap the two " +
|
|
193
|
+
"descriptions and rewrite the instruction so 'true' means yes.",
|
|
194
|
+
})]
|
|
195
|
+
: [];
|
|
196
|
+
});
|
|
197
|
+
// -- JEV008 / JEV009 / JEV010 Choice structure -----------------------------
|
|
198
|
+
const NO_MATCH = new Set([
|
|
199
|
+
"none", "none_of_the_above", "no_match", "nomatch", "other", "unknown", "unclear",
|
|
200
|
+
"not_stated", "not_applicable", "n_a", "na", "neither", "cannot_tell", "insufficient",
|
|
201
|
+
"uncertain", "ambiguous", "not_specified",
|
|
202
|
+
]);
|
|
203
|
+
const checkChoiceNoMatch = (ctx) => ctx.questions.flatMap((q) => {
|
|
204
|
+
if (q.type !== "choice")
|
|
205
|
+
return [];
|
|
206
|
+
const keys = q.options.map((k) => k.toLowerCase().replace(/[- ]/g, "_"));
|
|
207
|
+
if (!keys.length || keys.some((k) => NO_MATCH.has(k)))
|
|
208
|
+
return [];
|
|
209
|
+
return [new Diagnostic({
|
|
210
|
+
code: "JEV008", severity: "warning", questionId: q.id,
|
|
211
|
+
message: "Choice has no no-match option.",
|
|
212
|
+
evidence: [...keys].sort().join(", "),
|
|
213
|
+
hint: "A Choice always returns one of its options. With nothing meaning 'none of " +
|
|
214
|
+
"these', a state that fits no option still produces a confident-looking answer. " +
|
|
215
|
+
"Add an explicit none/unknown option, or gate on a separate presence Noul.",
|
|
216
|
+
})];
|
|
217
|
+
});
|
|
218
|
+
const checkChoiceArity = (ctx) => ctx.questions.flatMap((q) => {
|
|
219
|
+
if (q.type !== "choice")
|
|
220
|
+
return [];
|
|
221
|
+
const n = q.options.length;
|
|
222
|
+
if (n === 0) {
|
|
223
|
+
return [new Diagnostic({
|
|
224
|
+
code: "JEV009", severity: "error", questionId: q.id,
|
|
225
|
+
message: "Choice defines no options.",
|
|
226
|
+
hint: "Give the Choice a criteria object mapping each option key to a description " +
|
|
227
|
+
"of when it applies.",
|
|
228
|
+
})];
|
|
229
|
+
}
|
|
230
|
+
if (n === 1) {
|
|
231
|
+
return [new Diagnostic({
|
|
232
|
+
code: "JEV009", severity: "error", questionId: q.id,
|
|
233
|
+
message: "Choice defines a single option, so the answer is predetermined.",
|
|
234
|
+
evidence: q.options[0],
|
|
235
|
+
hint: "Use a Noul if the question is really yes/no, or add the competing options.",
|
|
236
|
+
})];
|
|
237
|
+
}
|
|
238
|
+
return [];
|
|
239
|
+
});
|
|
240
|
+
const checkEmptyDescriptions = (ctx) => ctx.questions.flatMap((q) => {
|
|
241
|
+
if (q.type !== "choice")
|
|
242
|
+
return [];
|
|
243
|
+
const blank = q.optionDescriptions().filter(([, d]) => !d.trim()).map(([k]) => k);
|
|
244
|
+
return blank.length
|
|
245
|
+
? [new Diagnostic({
|
|
246
|
+
code: "JEV010", severity: "warning", questionId: q.id,
|
|
247
|
+
message: "Choice options have no description.",
|
|
248
|
+
evidence: blank.join(", "),
|
|
249
|
+
hint: "The option key alone is all the model gets. Describe when each option " +
|
|
250
|
+
"applies, especially the boundary against its nearest rival.",
|
|
251
|
+
})]
|
|
252
|
+
: [];
|
|
253
|
+
});
|
|
254
|
+
// -- JEV011 Score structure -------------------------------------------------
|
|
255
|
+
const checkScoreLevels = (ctx) => ctx.questions.flatMap((q) => {
|
|
256
|
+
if (q.type !== "score")
|
|
257
|
+
return [];
|
|
258
|
+
const levels = q.options;
|
|
259
|
+
if (levels.length < 2) {
|
|
260
|
+
return [new Diagnostic({
|
|
261
|
+
code: "JEV011", severity: "error", questionId: q.id,
|
|
262
|
+
message: `Score defines ${levels.length} level(s); at least 2 are needed to form a scale.`,
|
|
263
|
+
hint: "Give each level a concrete description of the situation it covers.",
|
|
264
|
+
})];
|
|
265
|
+
}
|
|
266
|
+
const terse = levels.filter((lv) => lv.trim().split(/\s+/).length < 2);
|
|
267
|
+
return terse.length
|
|
268
|
+
? [new Diagnostic({
|
|
269
|
+
code: "JEV011", severity: "warning", questionId: q.id,
|
|
270
|
+
message: "Score levels are bare labels rather than descriptions.",
|
|
271
|
+
evidence: terse.join(", "),
|
|
272
|
+
hint: "Levels must describe concrete situations and stand on their own. " +
|
|
273
|
+
"'Frustrated but civil' works; 'medium' does not.",
|
|
274
|
+
})]
|
|
275
|
+
: [];
|
|
276
|
+
});
|
|
277
|
+
// -- JEV012 Instructions present -------------------------------------------
|
|
278
|
+
const checkInstructions = (ctx) => ctx.questions.flatMap((q) => {
|
|
279
|
+
const text = q.instructionsText.trim();
|
|
280
|
+
if (!text) {
|
|
281
|
+
return [new Diagnostic({
|
|
282
|
+
code: "JEV012", severity: "error", questionId: q.id,
|
|
283
|
+
message: "Question has no instructions.",
|
|
284
|
+
hint: "The instruction carries the judgment. Without it the model only has the " +
|
|
285
|
+
"criteria to go on.",
|
|
286
|
+
})];
|
|
287
|
+
}
|
|
288
|
+
if (text.split(/\s+/).length < 3) {
|
|
289
|
+
return [new Diagnostic({
|
|
290
|
+
code: "JEV012", severity: "warning", questionId: q.id,
|
|
291
|
+
message: "Instructions are too terse to state a condition.",
|
|
292
|
+
evidence: text,
|
|
293
|
+
hint: "State the exact condition being judged, in language an average reader would " +
|
|
294
|
+
"resolve the same way you do.",
|
|
295
|
+
})];
|
|
296
|
+
}
|
|
297
|
+
return [];
|
|
298
|
+
});
|
|
299
|
+
// -- JEV013 Question ids are not sent to the model --------------------------
|
|
300
|
+
function escapeRe(s) {
|
|
301
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
302
|
+
}
|
|
303
|
+
const checkIdReference = (ctx) => {
|
|
304
|
+
const ids = ctx.questions.map((q) => q.id);
|
|
305
|
+
return ctx.questions.flatMap((q) => {
|
|
306
|
+
const text = q.instructionsText;
|
|
307
|
+
const referenced = ids
|
|
308
|
+
.filter((other) => other !== q.id)
|
|
309
|
+
.filter((other) => new RegExp(`(?<![\\w.\`])${escapeRe(other)}(?![\\w\`])`).test(text))
|
|
310
|
+
.sort();
|
|
311
|
+
return referenced.length
|
|
312
|
+
? [new Diagnostic({
|
|
313
|
+
code: "JEV013", severity: "warning", questionId: q.id,
|
|
314
|
+
message: "Instructions refer to another question by its id.",
|
|
315
|
+
evidence: referenced.join(", "),
|
|
316
|
+
hint: "Question ids are for your code and are not sent to the model. Questions in " +
|
|
317
|
+
"one request are answered in parallel and cannot see each other. State the " +
|
|
318
|
+
"premise explicitly, or split into a second request.",
|
|
319
|
+
})]
|
|
320
|
+
: [];
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
// -- JEV014 / JEV015 Budgets ------------------------------------------------
|
|
324
|
+
const checkStateBudget = (ctx) => ctx.budget.overState
|
|
325
|
+
? [new Diagnostic({
|
|
326
|
+
code: "JEV014", severity: "error", questionId: null,
|
|
327
|
+
message: `state plus the longest question is about ${ctx.budget.longestPair.toLocaleString("en-US")} tokens, over the 32,000 limit.`,
|
|
328
|
+
evidence: `longest question: ${ctx.budget.longestQuestionId}`,
|
|
329
|
+
hint: "Retrieve and filter in code so the state carries only the fields this " +
|
|
330
|
+
"judgment needs. Estimates are approximate; leave headroom.",
|
|
331
|
+
})]
|
|
332
|
+
: [];
|
|
333
|
+
const checkTotalBudget = (ctx) => ctx.budget.overTotal
|
|
334
|
+
? [new Diagnostic({
|
|
335
|
+
code: "JEV015", severity: "error", questionId: null,
|
|
336
|
+
message: `state plus all ${ctx.questions.length} questions is about ${ctx.budget.total.toLocaleString("en-US")} tokens, over the 64,000 limit.`,
|
|
337
|
+
hint: "Split into several requests, or drop speculative questions that this state " +
|
|
338
|
+
"can never make relevant.",
|
|
339
|
+
})]
|
|
340
|
+
: [];
|
|
341
|
+
// -- JEV016 Noisy state -----------------------------------------------------
|
|
342
|
+
const LARGE_STATE_RATIO = 8;
|
|
343
|
+
const LARGE_STATE_FLOOR = 4_000;
|
|
344
|
+
const checkStateSize = (ctx) => {
|
|
345
|
+
const b = ctx.budget;
|
|
346
|
+
if (b.overState || b.overTotal)
|
|
347
|
+
return []; // Already an error; don't double up.
|
|
348
|
+
const questionTokens = Object.values(b.questionTokens).reduce((a, c) => a + c, 0) || 1;
|
|
349
|
+
const ratio = b.stateTokens / questionTokens;
|
|
350
|
+
if (b.stateTokens >= LARGE_STATE_FLOOR && ratio >= LARGE_STATE_RATIO) {
|
|
351
|
+
return [new Diagnostic({
|
|
352
|
+
code: "JEV016", severity: "info", questionId: null,
|
|
353
|
+
message: `state is about ${b.stateTokens.toLocaleString("en-US")} tokens against ${questionTokens.toLocaleString("en-US")} tokens of questions (${Math.round(ratio)}x).`,
|
|
354
|
+
hint: "Accuracy falls as the state grows with content unrelated to the decision, and " +
|
|
355
|
+
"a large state makes a wrong answer hard to attribute. Filter in code first, or " +
|
|
356
|
+
"use a Noul to screen for relevance.",
|
|
357
|
+
})];
|
|
358
|
+
}
|
|
359
|
+
return [];
|
|
360
|
+
};
|
|
361
|
+
// -- JEV017 Numeric representations ----------------------------------------
|
|
362
|
+
const NUMERIC_REPR = [
|
|
363
|
+
/#[0-9a-fA-F]{6}\b/, /\brgba?\s*\(/i, /\bhex(?:adecimal)? (?:value|code|colou?r)\b/i,
|
|
364
|
+
/\bbinary (?:value|encoding|representation)\b/i, /\bbase64\b/i,
|
|
365
|
+
/\bassembly (?:instruction|opcode)\b/i, /\bopcode\b/i, /\bbytecode\b/i,
|
|
366
|
+
];
|
|
367
|
+
const checkNumericRepr = (ctx) => ctx.questions.flatMap((q) => {
|
|
368
|
+
const hit = find(NUMERIC_REPR, q.text);
|
|
369
|
+
return hit
|
|
370
|
+
? [new Diagnostic({
|
|
371
|
+
code: "JEV017", severity: "warning", questionId: q.id,
|
|
372
|
+
message: "Question reasons over a machine-oriented numeric representation.",
|
|
373
|
+
evidence: hit,
|
|
374
|
+
hint: "jev-1.13 does better on semantic representations than numeric ones: colour " +
|
|
375
|
+
"names beat hex, high-level code beats bytecode. Convert in code and pass " +
|
|
376
|
+
"the name or a named bucket.",
|
|
377
|
+
})]
|
|
378
|
+
: [];
|
|
379
|
+
});
|
|
380
|
+
// -- JEV018 Duplicate judgments --------------------------------------------
|
|
381
|
+
const checkDuplicates = (ctx) => {
|
|
382
|
+
const seen = new Map();
|
|
383
|
+
const out = [];
|
|
384
|
+
for (const q of ctx.questions) {
|
|
385
|
+
const key = q.text.toLowerCase().replace(/\W+/g, " ").trim();
|
|
386
|
+
if (!key)
|
|
387
|
+
continue;
|
|
388
|
+
const prior = seen.get(key);
|
|
389
|
+
if (prior !== undefined) {
|
|
390
|
+
out.push(new Diagnostic({
|
|
391
|
+
code: "JEV018", severity: "info", questionId: q.id,
|
|
392
|
+
message: `Question is textually identical to "${prior}".`,
|
|
393
|
+
hint: "Identical questions in one request cost tokens twice for the same answer. If " +
|
|
394
|
+
"you meant to measure self-consistency, note that they are evaluated in one " +
|
|
395
|
+
"pass and are not independent samples.",
|
|
396
|
+
}));
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
seen.set(key, q.id);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return out;
|
|
403
|
+
};
|
|
404
|
+
export const RULES = [
|
|
405
|
+
{ code: "JEV001", name: "math-and-counting", mode: "Math and Numbers", check: checkMath },
|
|
406
|
+
{ code: "JEV002", name: "date-comparison", mode: "Date and time comparison", check: checkDates },
|
|
407
|
+
{ code: "JEV003", name: "generation-request", mode: "Generation", check: checkGeneration },
|
|
408
|
+
{ code: "JEV004", name: "negation", mode: "Literal reading", check: checkNegation },
|
|
409
|
+
{ code: "JEV005", name: "vague-scoping", mode: "Literal reading", check: checkVague },
|
|
410
|
+
{ code: "JEV006", name: "indirection", mode: "Indirection", check: checkIndirection },
|
|
411
|
+
{ code: "JEV007", name: "noul-polarity", mode: "Contradictory instructions and criteria", check: checkNoulPolarity },
|
|
412
|
+
{ code: "JEV008", name: "choice-no-match", mode: "Common-sense structural invariants", check: checkChoiceNoMatch },
|
|
413
|
+
{ code: "JEV009", name: "choice-arity", mode: "Common-sense structural invariants", check: checkChoiceArity },
|
|
414
|
+
{ code: "JEV010", name: "option-descriptions", mode: "Literal reading", check: checkEmptyDescriptions },
|
|
415
|
+
{ code: "JEV011", name: "score-levels", mode: "Literal reading", check: checkScoreLevels },
|
|
416
|
+
{ code: "JEV012", name: "instructions-present", mode: "Literal reading", check: checkInstructions },
|
|
417
|
+
{ code: "JEV013", name: "question-id-reference", mode: "Indirection", check: checkIdReference },
|
|
418
|
+
{ code: "JEV014", name: "state-budget", mode: "Large state full of irrelevant detail", check: checkStateBudget },
|
|
419
|
+
{ code: "JEV015", name: "total-budget", mode: "Large state full of irrelevant detail", check: checkTotalBudget },
|
|
420
|
+
{ code: "JEV016", name: "state-noise-ratio", mode: "Large state full of irrelevant detail", check: checkStateSize },
|
|
421
|
+
{ code: "JEV017", name: "numeric-representation", mode: "Math and Numbers", check: checkNumericRepr },
|
|
422
|
+
{ code: "JEV018", name: "duplicate-questions", mode: "Common-sense structural invariants", check: checkDuplicates },
|
|
423
|
+
];
|
|
424
|
+
export function rulesFor(codes) {
|
|
425
|
+
if (!codes)
|
|
426
|
+
return [...RULES];
|
|
427
|
+
const wanted = new Set([...codes].map((c) => c.toUpperCase()));
|
|
428
|
+
return RULES.filter((r) => wanted.has(r.code));
|
|
429
|
+
}
|
|
430
|
+
export function allCodes() {
|
|
431
|
+
return RULES.map((r) => r.code);
|
|
432
|
+
}
|
|
433
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jevkit-lint",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Static linter for TypeSafe Jev questions. Catches the documented jev-1.13 failure modes before you spend a token. No API key required.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"jev",
|
|
7
|
+
"typesafe",
|
|
8
|
+
"system-one",
|
|
9
|
+
"lint",
|
|
10
|
+
"linter",
|
|
11
|
+
"static-analysis"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"bin": {
|
|
24
|
+
"jevkit-lint": "./dist/cli.js"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/pjdurden/jevkit-js.git"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"jevkit-core": "^0.2.0"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -b"
|
|
42
|
+
}
|
|
43
|
+
}
|