@prompt-lint/rules 1.0.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 +21 -0
- package/README.md +72 -0
- package/dist/convention/filename-naming.d.ts +16 -0
- package/dist/convention/filename-naming.d.ts.map +1 -0
- package/dist/convention/filename-naming.js +50 -0
- package/dist/convention/filename-naming.js.map +1 -0
- package/dist/cost/high-token-estimate.d.ts +4 -0
- package/dist/cost/high-token-estimate.d.ts.map +1 -0
- package/dist/cost/high-token-estimate.js +51 -0
- package/dist/cost/high-token-estimate.js.map +1 -0
- package/dist/generated/manifest.d.ts +19 -0
- package/dist/generated/manifest.d.ts.map +1 -0
- package/dist/generated/manifest.js +98 -0
- package/dist/generated/manifest.js.map +1 -0
- package/dist/helpers/filename.d.ts +19 -0
- package/dist/helpers/filename.d.ts.map +1 -0
- package/dist/helpers/filename.js +59 -0
- package/dist/helpers/filename.js.map +1 -0
- package/dist/helpers/index.d.ts +16 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +16 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/instruction-override.d.ts +28 -0
- package/dist/helpers/instruction-override.d.ts.map +1 -0
- package/dist/helpers/instruction-override.js +43 -0
- package/dist/helpers/instruction-override.js.map +1 -0
- package/dist/helpers/pii.d.ts +31 -0
- package/dist/helpers/pii.d.ts.map +1 -0
- package/dist/helpers/pii.js +36 -0
- package/dist/helpers/pii.js.map +1 -0
- package/dist/helpers/regex.d.ts +53 -0
- package/dist/helpers/regex.d.ts.map +1 -0
- package/dist/helpers/regex.js +79 -0
- package/dist/helpers/regex.js.map +1 -0
- package/dist/helpers/structured-data.d.ts +19 -0
- package/dist/helpers/structured-data.d.ts.map +1 -0
- package/dist/helpers/structured-data.js +72 -0
- package/dist/helpers/structured-data.js.map +1 -0
- package/dist/helpers/tokens.d.ts +26 -0
- package/dist/helpers/tokens.d.ts.map +1 -0
- package/dist/helpers/tokens.js +63 -0
- package/dist/helpers/tokens.js.map +1 -0
- package/dist/helpers/vague-quantifiers.d.ts +20 -0
- package/dist/helpers/vague-quantifiers.d.ts.map +1 -0
- package/dist/helpers/vague-quantifiers.js +83 -0
- package/dist/helpers/vague-quantifiers.js.map +1 -0
- package/dist/helpers/variables.d.ts +36 -0
- package/dist/helpers/variables.d.ts.map +1 -0
- package/dist/helpers/variables.js +66 -0
- package/dist/helpers/variables.js.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/quality/missing-output-schema.d.ts +15 -0
- package/dist/quality/missing-output-schema.d.ts.map +1 -0
- package/dist/quality/missing-output-schema.js +39 -0
- package/dist/quality/missing-output-schema.js.map +1 -0
- package/dist/quality/vague-quantifier-language.d.ts +13 -0
- package/dist/quality/vague-quantifier-language.d.ts.map +1 -0
- package/dist/quality/vague-quantifier-language.js +34 -0
- package/dist/quality/vague-quantifier-language.js.map +1 -0
- package/dist/security/instruction-override-pattern.d.ts +17 -0
- package/dist/security/instruction-override-pattern.d.ts.map +1 -0
- package/dist/security/instruction-override-pattern.js +39 -0
- package/dist/security/instruction-override-pattern.js.map +1 -0
- package/dist/security/pii-pattern.d.ts +18 -0
- package/dist/security/pii-pattern.d.ts.map +1 -0
- package/dist/security/pii-pattern.js +56 -0
- package/dist/security/pii-pattern.js.map +1 -0
- package/dist/structure/missing-description.d.ts +14 -0
- package/dist/structure/missing-description.d.ts.map +1 -0
- package/dist/structure/missing-description.js +32 -0
- package/dist/structure/missing-description.js.map +1 -0
- package/dist/structure/missing-model.d.ts +16 -0
- package/dist/structure/missing-model.d.ts.map +1 -0
- package/dist/structure/missing-model.js +34 -0
- package/dist/structure/missing-model.js.map +1 -0
- package/dist/structure/undefined-variable.d.ts +15 -0
- package/dist/structure/undefined-variable.d.ts.map +1 -0
- package/dist/structure/undefined-variable.js +39 -0
- package/dist/structure/undefined-variable.js.map +1 -0
- package/dist/structure/unused-variable.d.ts +15 -0
- package/dist/structure/unused-variable.d.ts.map +1 -0
- package/dist/structure/unused-variable.js +38 -0
- package/dist/structure/unused-variable.js.map +1 -0
- package/dist/test-helpers.d.ts +40 -0
- package/dist/test-helpers.d.ts.map +1 -0
- package/dist/test-helpers.js +52 -0
- package/dist/test-helpers.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { defineRule } from "@prompt-lint/rule-engine";
|
|
2
|
+
import { collectBodyVariables, collectDeclaredVariables } from "../helpers/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* `structure/unused-variable`
|
|
5
|
+
*
|
|
6
|
+
* Reports a finding for every variable declared in `frontmatter.variables`
|
|
7
|
+
* that is **not** referenced anywhere in the parsed prompt body. Each
|
|
8
|
+
* unused variable is emitted separately so reporters can point at the
|
|
9
|
+
* exact identifier.
|
|
10
|
+
*
|
|
11
|
+
* The rule does not emit duplicate findings even if the same name was
|
|
12
|
+
* declared multiple times in the frontmatter.
|
|
13
|
+
*/
|
|
14
|
+
const unusedVariableRule = defineRule({
|
|
15
|
+
id: "structure/unused-variable",
|
|
16
|
+
description: "Flags variables defined in frontmatter but never referenced in the prompt body.",
|
|
17
|
+
defaultSeverity: "warning",
|
|
18
|
+
options: Object.freeze([]),
|
|
19
|
+
check: ({ file, report }) => {
|
|
20
|
+
const declared = collectDeclaredVariables(file);
|
|
21
|
+
const referenced = new Set(collectBodyVariables(file).map((v) => v.name));
|
|
22
|
+
for (const name of declared) {
|
|
23
|
+
if (referenced.has(name))
|
|
24
|
+
continue;
|
|
25
|
+
report({
|
|
26
|
+
message: `Declared variable \`${name}\` is never referenced in the prompt body.`,
|
|
27
|
+
severity: "warning",
|
|
28
|
+
suggestions: [
|
|
29
|
+
`Reference \`{{ ${name} }}\` somewhere in the body, or`,
|
|
30
|
+
"Remove the entry from `variables:` in the frontmatter.",
|
|
31
|
+
],
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return { findings: [] };
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
export default unusedVariableRule;
|
|
38
|
+
//# sourceMappingURL=unused-variable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unused-variable.js","sourceRoot":"","sources":["../../src/structure/unused-variable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAEpF;;;;;;;;;;GAUG;AACH,MAAM,kBAAkB,GAAmB,UAAU,CAAC;IACpD,EAAE,EAAE,2BAA2B;IAC/B,WAAW,EAAE,iFAAiF;IAC9F,eAAe,EAAE,SAAS;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAA;QAC/C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;QACzE,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAQ;YAClC,MAAM,CAAC;gBACL,OAAO,EAAE,uBAAuB,IAAI,4CAA4C;gBAChF,QAAQ,EAAE,SAAS;gBACnB,WAAW,EAAE;oBACX,kBAAkB,IAAI,iCAAiC;oBACvD,wDAAwD;iBACzD;aACF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,eAAe,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Finding, PromptFile, RuleContext } from "@prompt-lint/types";
|
|
2
|
+
/**
|
|
3
|
+
* Construct a `RuleContext` for a single rule call.
|
|
4
|
+
*
|
|
5
|
+
* The helper ports the engine's `runOneRuleOneFile` plumbing so unit tests
|
|
6
|
+
* can exercise `rule.check(ctx)` directly without spinning up the engine.
|
|
7
|
+
*/
|
|
8
|
+
export declare function makeContext(file: PromptFile, options?: Readonly<Record<string, unknown>>): {
|
|
9
|
+
context: RuleContext;
|
|
10
|
+
emitted: Omit<Finding, "ruleId" | "fileId" | "filePath">[];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Run a rule synchronously and return its emitted findings together with
|
|
14
|
+
* any findings the rule returned from `check`.
|
|
15
|
+
*
|
|
16
|
+
* Variables in the body are extracted via `@prompt-lint/parser` so the
|
|
17
|
+
* tests do not have to enumerate each `{{ var }}` reference manually.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runRule(rule: {
|
|
20
|
+
check: (ctx: RuleContext) => RuleResult | Promise<RuleResult>;
|
|
21
|
+
}, input?: {
|
|
22
|
+
path?: string;
|
|
23
|
+
body?: string;
|
|
24
|
+
frontmatter?: PromptFile["frontmatter"];
|
|
25
|
+
variables?: PromptFile["variables"];
|
|
26
|
+
format?: PromptFile["format"];
|
|
27
|
+
}, options?: Readonly<Record<string, unknown>>): Promise<{
|
|
28
|
+
findings: Finding[];
|
|
29
|
+
emitted: Omit<Finding, "ruleId" | "fileId" | "filePath">[];
|
|
30
|
+
}>;
|
|
31
|
+
interface RuleResult {
|
|
32
|
+
findings: readonly unknown[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Convenience helper for tests that prefer to start from a parsed-style
|
|
36
|
+
* `PromptFile` literal.
|
|
37
|
+
*/
|
|
38
|
+
export declare function frozen<T>(value: T): T;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=test-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAE1E;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM,GAC9C;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC,EAAE,CAAA;CAAE,CAUtF;AAED;;;;;;GAMG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE;IAAE,KAAK,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;CAAE,EACvE,KAAK,GAAE;IACL,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;IACvC,SAAS,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,CAAA;IACnC,MAAM,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;CACzB,EACN,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM,GAC9C,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC,EAAE,CAAA;CAAE,CAAC,CAiB9F;AAED,UAAU,UAAU;IAClB,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CAC7B;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAErC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { collectVariables, scanVariables } from "@prompt-lint/parser";
|
|
2
|
+
import { makePromptFile } from "@prompt-lint/test-utils";
|
|
3
|
+
/**
|
|
4
|
+
* Construct a `RuleContext` for a single rule call.
|
|
5
|
+
*
|
|
6
|
+
* The helper ports the engine's `runOneRuleOneFile` plumbing so unit tests
|
|
7
|
+
* can exercise `rule.check(ctx)` directly without spinning up the engine.
|
|
8
|
+
*/
|
|
9
|
+
export function makeContext(file, options = {}) {
|
|
10
|
+
const emitted = [];
|
|
11
|
+
const context = Object.freeze({
|
|
12
|
+
file,
|
|
13
|
+
options: Object.freeze({ ...options }),
|
|
14
|
+
report: (raw) => {
|
|
15
|
+
emitted.push({ ...raw });
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
return { context, emitted };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Run a rule synchronously and return its emitted findings together with
|
|
22
|
+
* any findings the rule returned from `check`.
|
|
23
|
+
*
|
|
24
|
+
* Variables in the body are extracted via `@prompt-lint/parser` so the
|
|
25
|
+
* tests do not have to enumerate each `{{ var }}` reference manually.
|
|
26
|
+
*/
|
|
27
|
+
export async function runRule(rule, input = {}, options = {}) {
|
|
28
|
+
const body = input.body ?? "";
|
|
29
|
+
const occurrences = scanVariables(body);
|
|
30
|
+
const variables = collectVariables(occurrences);
|
|
31
|
+
const file = makePromptFile({
|
|
32
|
+
path: input.path ?? "prompts/sample.prompt.md",
|
|
33
|
+
format: input.format ?? "prompt.md",
|
|
34
|
+
body,
|
|
35
|
+
frontmatter: (input.frontmatter ?? {}),
|
|
36
|
+
variables,
|
|
37
|
+
});
|
|
38
|
+
const { context, emitted } = makeContext(file, options);
|
|
39
|
+
const result = await rule.check(context);
|
|
40
|
+
return {
|
|
41
|
+
findings: Array.isArray(result.findings) ? result.findings : [],
|
|
42
|
+
emitted,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Convenience helper for tests that prefer to start from a parsed-style
|
|
47
|
+
* `PromptFile` literal.
|
|
48
|
+
*/
|
|
49
|
+
export function frozen(value) {
|
|
50
|
+
return Object.freeze(value);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=test-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,IAAgB,EAChB,UAA6C,EAAE;IAE/C,MAAM,OAAO,GAAsD,EAAE,CAAA;IACrE,MAAM,OAAO,GAAgB,MAAM,CAAC,MAAM,CAAC;QACzC,IAAI;QACJ,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC;QACtC,MAAM,EAAE,CAAC,GAAoD,EAAE,EAAE;YAC/D,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAA;QAC1B,CAAC;KACF,CAAC,CAAA;IACF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAA;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAuE,EACvE,QAMI,EAAE,EACN,UAA6C,EAAE;IAE/C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAA;IAC7B,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAA;IAC/C,MAAM,IAAI,GAAG,cAAc,CAAC;QAC1B,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,0BAA0B;QAC9C,MAAM,EAAE,KAAK,CAAC,MAAM,IAAK,WAAoC;QAC7D,IAAI;QACJ,WAAW,EAAE,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAA8B;QACnE,SAAS;KACV,CAAC,CAAA;IACF,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACxC,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,QAAsB,CAAC,CAAC,CAAC,EAAE;QAC9E,OAAO;KACR,CAAA;AACH,CAAC;AAMD;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAI,KAAQ;IAChC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prompt-lint/rules",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Built-in lint rules for PromptLint V1.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"!**/*.tsbuildinfo"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@prompt-lint/parser": "1.0.0",
|
|
21
|
+
"@prompt-lint/types": "1.0.0",
|
|
22
|
+
"@prompt-lint/rule-engine": "1.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "20.17.10",
|
|
26
|
+
"typescript": "5.7.2",
|
|
27
|
+
"vitest": "2.1.8",
|
|
28
|
+
"@prompt-lint/biome-config": "0.0.0",
|
|
29
|
+
"@prompt-lint/test-utils": "0.0.0",
|
|
30
|
+
"@prompt-lint/tsconfig": "0.0.0"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"lint": "biome check src",
|
|
34
|
+
"lint:fix": "biome check --write src",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "vitest",
|
|
37
|
+
"test:run": "vitest run",
|
|
38
|
+
"build": "tsc -p tsconfig.build.json",
|
|
39
|
+
"clean": "rm -rf dist .turbo coverage",
|
|
40
|
+
"topo": "echo \"topo\""
|
|
41
|
+
}
|
|
42
|
+
}
|