@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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -0
  3. package/dist/convention/filename-naming.d.ts +16 -0
  4. package/dist/convention/filename-naming.d.ts.map +1 -0
  5. package/dist/convention/filename-naming.js +50 -0
  6. package/dist/convention/filename-naming.js.map +1 -0
  7. package/dist/cost/high-token-estimate.d.ts +4 -0
  8. package/dist/cost/high-token-estimate.d.ts.map +1 -0
  9. package/dist/cost/high-token-estimate.js +51 -0
  10. package/dist/cost/high-token-estimate.js.map +1 -0
  11. package/dist/generated/manifest.d.ts +19 -0
  12. package/dist/generated/manifest.d.ts.map +1 -0
  13. package/dist/generated/manifest.js +98 -0
  14. package/dist/generated/manifest.js.map +1 -0
  15. package/dist/helpers/filename.d.ts +19 -0
  16. package/dist/helpers/filename.d.ts.map +1 -0
  17. package/dist/helpers/filename.js +59 -0
  18. package/dist/helpers/filename.js.map +1 -0
  19. package/dist/helpers/index.d.ts +16 -0
  20. package/dist/helpers/index.d.ts.map +1 -0
  21. package/dist/helpers/index.js +16 -0
  22. package/dist/helpers/index.js.map +1 -0
  23. package/dist/helpers/instruction-override.d.ts +28 -0
  24. package/dist/helpers/instruction-override.d.ts.map +1 -0
  25. package/dist/helpers/instruction-override.js +43 -0
  26. package/dist/helpers/instruction-override.js.map +1 -0
  27. package/dist/helpers/pii.d.ts +31 -0
  28. package/dist/helpers/pii.d.ts.map +1 -0
  29. package/dist/helpers/pii.js +36 -0
  30. package/dist/helpers/pii.js.map +1 -0
  31. package/dist/helpers/regex.d.ts +53 -0
  32. package/dist/helpers/regex.d.ts.map +1 -0
  33. package/dist/helpers/regex.js +79 -0
  34. package/dist/helpers/regex.js.map +1 -0
  35. package/dist/helpers/structured-data.d.ts +19 -0
  36. package/dist/helpers/structured-data.d.ts.map +1 -0
  37. package/dist/helpers/structured-data.js +72 -0
  38. package/dist/helpers/structured-data.js.map +1 -0
  39. package/dist/helpers/tokens.d.ts +26 -0
  40. package/dist/helpers/tokens.d.ts.map +1 -0
  41. package/dist/helpers/tokens.js +63 -0
  42. package/dist/helpers/tokens.js.map +1 -0
  43. package/dist/helpers/vague-quantifiers.d.ts +20 -0
  44. package/dist/helpers/vague-quantifiers.d.ts.map +1 -0
  45. package/dist/helpers/vague-quantifiers.js +83 -0
  46. package/dist/helpers/vague-quantifiers.js.map +1 -0
  47. package/dist/helpers/variables.d.ts +36 -0
  48. package/dist/helpers/variables.d.ts.map +1 -0
  49. package/dist/helpers/variables.js +66 -0
  50. package/dist/helpers/variables.js.map +1 -0
  51. package/dist/index.d.ts +62 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +80 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/quality/missing-output-schema.d.ts +15 -0
  56. package/dist/quality/missing-output-schema.d.ts.map +1 -0
  57. package/dist/quality/missing-output-schema.js +39 -0
  58. package/dist/quality/missing-output-schema.js.map +1 -0
  59. package/dist/quality/vague-quantifier-language.d.ts +13 -0
  60. package/dist/quality/vague-quantifier-language.d.ts.map +1 -0
  61. package/dist/quality/vague-quantifier-language.js +34 -0
  62. package/dist/quality/vague-quantifier-language.js.map +1 -0
  63. package/dist/security/instruction-override-pattern.d.ts +17 -0
  64. package/dist/security/instruction-override-pattern.d.ts.map +1 -0
  65. package/dist/security/instruction-override-pattern.js +39 -0
  66. package/dist/security/instruction-override-pattern.js.map +1 -0
  67. package/dist/security/pii-pattern.d.ts +18 -0
  68. package/dist/security/pii-pattern.d.ts.map +1 -0
  69. package/dist/security/pii-pattern.js +56 -0
  70. package/dist/security/pii-pattern.js.map +1 -0
  71. package/dist/structure/missing-description.d.ts +14 -0
  72. package/dist/structure/missing-description.d.ts.map +1 -0
  73. package/dist/structure/missing-description.js +32 -0
  74. package/dist/structure/missing-description.js.map +1 -0
  75. package/dist/structure/missing-model.d.ts +16 -0
  76. package/dist/structure/missing-model.d.ts.map +1 -0
  77. package/dist/structure/missing-model.js +34 -0
  78. package/dist/structure/missing-model.js.map +1 -0
  79. package/dist/structure/undefined-variable.d.ts +15 -0
  80. package/dist/structure/undefined-variable.d.ts.map +1 -0
  81. package/dist/structure/undefined-variable.js +39 -0
  82. package/dist/structure/undefined-variable.js.map +1 -0
  83. package/dist/structure/unused-variable.d.ts +15 -0
  84. package/dist/structure/unused-variable.d.ts.map +1 -0
  85. package/dist/structure/unused-variable.js +38 -0
  86. package/dist/structure/unused-variable.js.map +1 -0
  87. package/dist/test-helpers.d.ts +40 -0
  88. package/dist/test-helpers.d.ts.map +1 -0
  89. package/dist/test-helpers.js +52 -0
  90. package/dist/test-helpers.js.map +1 -0
  91. package/package.json +42 -0
@@ -0,0 +1,62 @@
1
+ import type { RuleDefinition, RuleOption, Severity } from "@prompt-lint/types";
2
+ import conventionFilenameNaming from "./convention/filename-naming.js";
3
+ import costHighTokenEstimate from "./cost/high-token-estimate.js";
4
+ import { RULES_MANIFEST } from "./generated/manifest.js";
5
+ import qualityMissingOutputSchema from "./quality/missing-output-schema.js";
6
+ import qualityVagueQuantifierLanguage from "./quality/vague-quantifier-language.js";
7
+ import securityInstructionOverridePattern from "./security/instruction-override-pattern.js";
8
+ import securityPiiPattern from "./security/pii-pattern.js";
9
+ import structureMissingDescription from "./structure/missing-description.js";
10
+ import structureMissingModel from "./structure/missing-model.js";
11
+ import structureUndefinedVariable from "./structure/undefined-variable.js";
12
+ import structureUnusedVariable from "./structure/unused-variable.js";
13
+ /**
14
+ * Categories of V1 rules. Used by reporters to group findings and by
15
+ * the docs generator to filter rules per category page.
16
+ */
17
+ export type RuleCategory = "structure" | "cost" | "security" | "quality" | "convention";
18
+ /**
19
+ * Metadata-only descriptor for a rule, exported before implementation.
20
+ * Phase 0 ships one descriptor per declared rule so the manifest is a
21
+ * complete artifact; Phase 3 fills in the `check` function. Both phases
22
+ * re-export the same shape via `@prompt-lint/types`'s `RuleDefinition`.
23
+ */
24
+ export type RuleManifestEntry = {
25
+ readonly id: string;
26
+ readonly category: RuleCategory;
27
+ readonly description: string;
28
+ readonly severity: Severity;
29
+ readonly autoFixable: boolean;
30
+ readonly options: readonly RuleOption[];
31
+ };
32
+ /**
33
+ * The full V1 catalog. The order here is the order shown by `--list-rules`
34
+ * and in the docs.
35
+ *
36
+ * The entries live in `generated/manifest.ts` to keep this file focused on
37
+ * the public API; the order here is the canonical order that
38
+ * `getImplementedRules()` returns.
39
+ */
40
+ export { RULES_MANIFEST };
41
+ /**
42
+ * Look up a manifest entry by id. Phase 3 returns the implemented rule
43
+ * from this lookup; tests in Phase 0 verify the catalog content is stable.
44
+ */
45
+ export declare function findManifestEntry(id: string): RuleManifestEntry | undefined;
46
+ /**
47
+ * Return the list of declared rule ids. Phase 3 also exposes this as a
48
+ * side-effect of `getImplementedRules()`; the legacy function is retained
49
+ * for API stability with the Phase 0 surface.
50
+ */
51
+ export declare function definedRuleIds(): readonly string[];
52
+ /**
53
+ * Every implemented rule, in the order defined by `RULES_MANIFEST`.
54
+ *
55
+ * Callers that want to feed `runEngine` should iterate the result here
56
+ * rather than referencing the individual imports. This keeps the public
57
+ * surface stable when rule files move or are renamed.
58
+ */
59
+ export declare function getImplementedRules(): readonly RuleDefinition[];
60
+ export { structureMissingModel, structureMissingDescription, structureUnusedVariable, structureUndefinedVariable, costHighTokenEstimate, securityPiiPattern, securityInstructionOverridePattern, qualityMissingOutputSchema, qualityVagueQuantifierLanguage, conventionFilenameNaming, };
61
+ export type { RuleDefinition, RuleOption, Severity };
62
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC9E,OAAO,wBAAwB,MAAM,iCAAiC,CAAA;AACtE,OAAO,qBAAqB,MAAM,+BAA+B,CAAA;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,0BAA0B,MAAM,oCAAoC,CAAA;AAC3E,OAAO,8BAA8B,MAAM,wCAAwC,CAAA;AACnF,OAAO,kCAAkC,MAAM,4CAA4C,CAAA;AAC3F,OAAO,kBAAkB,MAAM,2BAA2B,CAAA;AAC1D,OAAO,2BAA2B,MAAM,oCAAoC,CAAA;AAC5E,OAAO,qBAAqB,MAAM,8BAA8B,CAAA;AAChE,OAAO,0BAA0B,MAAM,mCAAmC,CAAA;AAC1E,OAAO,uBAAuB,MAAM,gCAAgC,CAAA;AAEpE;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,CAAA;AAEvF;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;CACxC,CAAA;AAED;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,CAAA;AAEzB;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAE3E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,SAAS,MAAM,EAAE,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,cAAc,EAAE,CAE/D;AAED,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,kBAAkB,EAClB,kCAAkC,EAClC,0BAA0B,EAC1B,8BAA8B,EAC9B,wBAAwB,GACzB,CAAA;AAED,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,80 @@
1
+ import conventionFilenameNaming from "./convention/filename-naming.js";
2
+ import costHighTokenEstimate from "./cost/high-token-estimate.js";
3
+ import { RULES_MANIFEST } from "./generated/manifest.js";
4
+ import qualityMissingOutputSchema from "./quality/missing-output-schema.js";
5
+ import qualityVagueQuantifierLanguage from "./quality/vague-quantifier-language.js";
6
+ import securityInstructionOverridePattern from "./security/instruction-override-pattern.js";
7
+ import securityPiiPattern from "./security/pii-pattern.js";
8
+ import structureMissingDescription from "./structure/missing-description.js";
9
+ import structureMissingModel from "./structure/missing-model.js";
10
+ import structureUndefinedVariable from "./structure/undefined-variable.js";
11
+ import structureUnusedVariable from "./structure/unused-variable.js";
12
+ /**
13
+ * The full V1 catalog. The order here is the order shown by `--list-rules`
14
+ * and in the docs.
15
+ *
16
+ * The entries live in `generated/manifest.ts` to keep this file focused on
17
+ * the public API; the order here is the canonical order that
18
+ * `getImplementedRules()` returns.
19
+ */
20
+ export { RULES_MANIFEST };
21
+ /**
22
+ * Look up a manifest entry by id. Phase 3 returns the implemented rule
23
+ * from this lookup; tests in Phase 0 verify the catalog content is stable.
24
+ */
25
+ export function findManifestEntry(id) {
26
+ return RULES_MANIFEST.find((r) => r.id === id);
27
+ }
28
+ /**
29
+ * Return the list of declared rule ids. Phase 3 also exposes this as a
30
+ * side-effect of `getImplementedRules()`; the legacy function is retained
31
+ * for API stability with the Phase 0 surface.
32
+ */
33
+ export function definedRuleIds() {
34
+ return RULES_MANIFEST.map((r) => r.id);
35
+ }
36
+ /**
37
+ * Every implemented rule, in the order defined by `RULES_MANIFEST`.
38
+ *
39
+ * Callers that want to feed `runEngine` should iterate the result here
40
+ * rather than referencing the individual imports. This keeps the public
41
+ * surface stable when rule files move or are renamed.
42
+ */
43
+ export function getImplementedRules() {
44
+ return Object.freeze(IMPLEMENTED_RULES);
45
+ }
46
+ export { structureMissingModel, structureMissingDescription, structureUnusedVariable, structureUndefinedVariable, costHighTokenEstimate, securityPiiPattern, securityInstructionOverridePattern, qualityMissingOutputSchema, qualityVagueQuantifierLanguage, conventionFilenameNaming, };
47
+ // ---------------------------------------------------------------------------
48
+ // Implementation order MUST match `RULES_MANIFEST`. The build will panic
49
+ // at module-load time if the two lists drift apart, which is a deliberate
50
+ // guard against silent reordering.
51
+ // ---------------------------------------------------------------------------
52
+ const IMPLEMENTED_RULES = [
53
+ structureMissingModel,
54
+ structureMissingDescription,
55
+ structureUnusedVariable,
56
+ structureUndefinedVariable,
57
+ costHighTokenEstimate,
58
+ securityPiiPattern,
59
+ securityInstructionOverridePattern,
60
+ qualityMissingOutputSchema,
61
+ qualityVagueQuantifierLanguage,
62
+ conventionFilenameNaming,
63
+ ];
64
+ function assertManifestOrder() {
65
+ if (IMPLEMENTED_RULES.length !== RULES_MANIFEST.length) {
66
+ throw new Error(`[promptlint/rules] getImplementedRules length (${IMPLEMENTED_RULES.length}) does not match RULES_MANIFEST length (${RULES_MANIFEST.length}).`);
67
+ }
68
+ for (let i = 0; i < IMPLEMENTED_RULES.length; i += 1) {
69
+ const rule = IMPLEMENTED_RULES[i];
70
+ const entry = RULES_MANIFEST[i];
71
+ if (rule === undefined || entry === undefined) {
72
+ throw new Error(`[promptlint/rules] missing rule or manifest entry at index ${i}; this should be unreachable.`);
73
+ }
74
+ if (rule.id !== entry.id) {
75
+ throw new Error(`[promptlint/rules] order drift at index ${i}: expected \`${entry.id}\` but got \`${rule.id}\`.`);
76
+ }
77
+ }
78
+ }
79
+ assertManifestOrder();
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,wBAAwB,MAAM,iCAAiC,CAAA;AACtE,OAAO,qBAAqB,MAAM,+BAA+B,CAAA;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,0BAA0B,MAAM,oCAAoC,CAAA;AAC3E,OAAO,8BAA8B,MAAM,wCAAwC,CAAA;AACnF,OAAO,kCAAkC,MAAM,4CAA4C,CAAA;AAC3F,OAAO,kBAAkB,MAAM,2BAA2B,CAAA;AAC1D,OAAO,2BAA2B,MAAM,oCAAoC,CAAA;AAC5E,OAAO,qBAAqB,MAAM,8BAA8B,CAAA;AAChE,OAAO,0BAA0B,MAAM,mCAAmC,CAAA;AAC1E,OAAO,uBAAuB,MAAM,gCAAgC,CAAA;AAuBpE;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,CAAA;AAEzB;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAA;AACzC,CAAC;AAED,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,kBAAkB,EAClB,kCAAkC,EAClC,0BAA0B,EAC1B,8BAA8B,EAC9B,wBAAwB,GACzB,CAAA;AAID,8EAA8E;AAC9E,yEAAyE;AACzE,0EAA0E;AAC1E,mCAAmC;AACnC,8EAA8E;AAE9E,MAAM,iBAAiB,GAA8B;IACnD,qBAAqB;IACrB,2BAA2B;IAC3B,uBAAuB;IACvB,0BAA0B;IAC1B,qBAAqB;IACrB,kBAAkB;IAClB,kCAAkC;IAClC,0BAA0B;IAC1B,8BAA8B;IAC9B,wBAAwB;CACzB,CAAA;AAED,SAAS,mBAAmB;IAC1B,IAAI,iBAAiB,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CACb,kDAAkD,iBAAiB,CAAC,MAAM,2CAA2C,cAAc,CAAC,MAAM,IAAI,CAC/I,CAAA;IACH,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAA;QACjC,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;QAC/B,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CACb,8DAA8D,CAAC,+BAA+B,CAC/F,CAAA;QACH,CAAC;QACD,IAAI,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,2CAA2C,CAAC,gBAAgB,KAAK,CAAC,EAAE,gBAAgB,IAAI,CAAC,EAAE,KAAK,CACjG,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,mBAAmB,EAAE,CAAA"}
@@ -0,0 +1,15 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `quality/missing-output-schema`
4
+ *
5
+ * Reports a finding when a prompt's body requests structured output
6
+ * (e.g. JSON, YAML, CSV, a table) but the frontmatter does not declare
7
+ * an `outputSchema`. The presence of `outputSchema` is the convention
8
+ * the engine uses to drive post-validation in later phases.
9
+ *
10
+ * Prompts whose body looks like free-form natural language are not
11
+ * flagged, even when their frontmatter also lacks a schema.
12
+ */
13
+ declare const missingOutputSchemaRule: RuleDefinition;
14
+ export default missingOutputSchemaRule;
15
+ //# sourceMappingURL=missing-output-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-output-schema.d.ts","sourceRoot":"","sources":["../../src/quality/missing-output-schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD;;;;;;;;;;GAUG;AACH,QAAA,MAAM,uBAAuB,EAAE,cAyB7B,CAAA;AAEF,eAAe,uBAAuB,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ import { hasStructuredDataKeyword } from "../helpers/index.js";
3
+ /**
4
+ * `quality/missing-output-schema`
5
+ *
6
+ * Reports a finding when a prompt's body requests structured output
7
+ * (e.g. JSON, YAML, CSV, a table) but the frontmatter does not declare
8
+ * an `outputSchema`. The presence of `outputSchema` is the convention
9
+ * the engine uses to drive post-validation in later phases.
10
+ *
11
+ * Prompts whose body looks like free-form natural language are not
12
+ * flagged, even when their frontmatter also lacks a schema.
13
+ */
14
+ const missingOutputSchemaRule = defineRule({
15
+ id: "quality/missing-output-schema",
16
+ description: "Flags prompts that request structured data without an accompanying JSON Schema in frontmatter.",
17
+ defaultSeverity: "warning",
18
+ options: Object.freeze([]),
19
+ check: ({ file, report }) => {
20
+ if (file.frontmatter.outputSchema !== undefined) {
21
+ return { findings: [] };
22
+ }
23
+ if (!hasStructuredDataKeyword(file.body)) {
24
+ return { findings: [] };
25
+ }
26
+ report({
27
+ message: "Prompt requests structured output but does not declare an `outputSchema` in frontmatter.",
28
+ severity: "warning",
29
+ suggestions: [
30
+ "Add an `outputSchema:` entry to the frontmatter that describes the expected JSON shape.",
31
+ "If the response is meant to be unstructured prose, remove the structured-data phrasing from the body.",
32
+ "Use a `$ref` to an existing schema under `./schemas/` to keep prompts composable.",
33
+ ],
34
+ });
35
+ return { findings: [] };
36
+ },
37
+ });
38
+ export default missingOutputSchemaRule;
39
+ //# sourceMappingURL=missing-output-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-output-schema.js","sourceRoot":"","sources":["../../src/quality/missing-output-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAE9D;;;;;;;;;;GAUG;AACH,MAAM,uBAAuB,GAAmB,UAAU,CAAC;IACzD,EAAE,EAAE,+BAA+B;IACnC,WAAW,EACT,gGAAgG;IAClG,eAAe,EAAE,SAAS;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,IAAI,IAAI,CAAC,WAAW,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YAChD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;QACzB,CAAC;QACD,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;QACzB,CAAC;QACD,MAAM,CAAC;YACL,OAAO,EACL,0FAA0F;YAC5F,QAAQ,EAAE,SAAS;YACnB,WAAW,EAAE;gBACX,yFAAyF;gBACzF,uGAAuG;gBACvG,mFAAmF;aACpF;SACF,CAAC,CAAA;QACF,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,eAAe,uBAAuB,CAAA"}
@@ -0,0 +1,13 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `quality/vague-quantifier-language`
4
+ *
5
+ * Reports an `info`-severity finding for every occurrence of a vague
6
+ * quantifier (e.g. "a few", "various", "etc.", "and so on") in the
7
+ * prompt body. Each occurrence produces a distinct finding with a
8
+ * `location` that points at the matched token, allowing editors to
9
+ * highlight the phrase precisely.
10
+ */
11
+ declare const vagueQuantifierRule: RuleDefinition;
12
+ export default vagueQuantifierRule;
13
+ //# sourceMappingURL=vague-quantifier-language.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vague-quantifier-language.d.ts","sourceRoot":"","sources":["../../src/quality/vague-quantifier-language.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD;;;;;;;;GAQG;AACH,QAAA,MAAM,mBAAmB,EAAE,cAqBzB,CAAA;AAEF,eAAe,mBAAmB,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ import { findVagueQuantifierMatches } from "../helpers/index.js";
3
+ /**
4
+ * `quality/vague-quantifier-language`
5
+ *
6
+ * Reports an `info`-severity finding for every occurrence of a vague
7
+ * quantifier (e.g. "a few", "various", "etc.", "and so on") in the
8
+ * prompt body. Each occurrence produces a distinct finding with a
9
+ * `location` that points at the matched token, allowing editors to
10
+ * highlight the phrase precisely.
11
+ */
12
+ const vagueQuantifierRule = defineRule({
13
+ id: "quality/vague-quantifier-language",
14
+ description: 'Flags vague quantifier phrases (e.g., "a few", "various", "etc.", "and so on") in prompt bodies.',
15
+ defaultSeverity: "info",
16
+ options: Object.freeze([]),
17
+ check: ({ file, report }) => {
18
+ const matches = findVagueQuantifierMatches(file.body);
19
+ for (const match of matches) {
20
+ report({
21
+ message: `Vague quantifier (\`${match.term}\`) is hard for models to interpret precisely.`,
22
+ severity: "info",
23
+ location: match.location,
24
+ suggestions: [
25
+ "Replace the phrase with a concrete number, range, or exemplar list.",
26
+ "Spell out which items are included so the model cannot under- or over-deliver.",
27
+ ],
28
+ });
29
+ }
30
+ return { findings: [] };
31
+ },
32
+ });
33
+ export default vagueQuantifierRule;
34
+ //# sourceMappingURL=vague-quantifier-language.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vague-quantifier-language.js","sourceRoot":"","sources":["../../src/quality/vague-quantifier-language.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAA;AAEhE;;;;;;;;GAQG;AACH,MAAM,mBAAmB,GAAmB,UAAU,CAAC;IACrD,EAAE,EAAE,mCAAmC;IACvC,WAAW,EACT,kGAAkG;IACpG,eAAe,EAAE,MAAM;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,MAAM,OAAO,GAAG,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACrD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,CAAC;gBACL,OAAO,EAAE,uBAAuB,KAAK,CAAC,IAAI,gDAAgD;gBAC1F,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE;oBACX,qEAAqE;oBACrE,gFAAgF;iBACjF;aACF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,eAAe,mBAAmB,CAAA"}
@@ -0,0 +1,17 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `security/instruction-override-pattern`
4
+ *
5
+ * Reports a finding when the prompt body — or instructions encouraging
6
+ * such phrasing — contains language that attempts to override or
7
+ * reveal the system prompt. The patterns are deliberately conservative;
8
+ * phrasing a developer would normally use when authoring a system
9
+ * prompt is not flagged.
10
+ *
11
+ * The rule emits one finding per detected `(pattern-id, start)`
12
+ * occurrence so reporters can highlight the exact token. Findings are
13
+ * sorted by source order to keep the output deterministic.
14
+ */
15
+ declare const instructionOverrideRule: RuleDefinition;
16
+ export default instructionOverrideRule;
17
+ //# sourceMappingURL=instruction-override-pattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-override-pattern.d.ts","sourceRoot":"","sources":["../../src/security/instruction-override-pattern.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,uBAAuB,EAAE,cAsB7B,CAAA;AAEF,eAAe,uBAAuB,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ import { findInstructionOverrideMatches } from "../helpers/index.js";
3
+ /**
4
+ * `security/instruction-override-pattern`
5
+ *
6
+ * Reports a finding when the prompt body — or instructions encouraging
7
+ * such phrasing — contains language that attempts to override or
8
+ * reveal the system prompt. The patterns are deliberately conservative;
9
+ * phrasing a developer would normally use when authoring a system
10
+ * prompt is not flagged.
11
+ *
12
+ * The rule emits one finding per detected `(pattern-id, start)`
13
+ * occurrence so reporters can highlight the exact token. Findings are
14
+ * sorted by source order to keep the output deterministic.
15
+ */
16
+ const instructionOverrideRule = defineRule({
17
+ id: "security/instruction-override-pattern",
18
+ description: "Flags prompt bodies containing instruction-override phrasing or that encourage such phrasing.",
19
+ defaultSeverity: "warning",
20
+ options: Object.freeze([]),
21
+ check: ({ file, report }) => {
22
+ const matches = findInstructionOverrideMatches(file.body);
23
+ for (const match of matches) {
24
+ report({
25
+ message: `Detected instruction-override phrasing (${match.id}): \`${match.text.trim()}\`.`,
26
+ severity: "warning",
27
+ location: match.location,
28
+ suggestions: [
29
+ "Rephrase the body to remove the override-style language.",
30
+ "If this is a test of model robustness, gate it behind a separate, clearly-labeled prompt file.",
31
+ "Document the pattern in your team's contribution guide so future contributors recognize it.",
32
+ ],
33
+ });
34
+ }
35
+ return { findings: [] };
36
+ },
37
+ });
38
+ export default instructionOverrideRule;
39
+ //# sourceMappingURL=instruction-override-pattern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-override-pattern.js","sourceRoot":"","sources":["../../src/security/instruction-override-pattern.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAA;AAEpE;;;;;;;;;;;;GAYG;AACH,MAAM,uBAAuB,GAAmB,UAAU,CAAC;IACzD,EAAE,EAAE,uCAAuC;IAC3C,WAAW,EACT,+FAA+F;IACjG,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,OAAO,GAAG,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACzD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,CAAC;gBACL,OAAO,EAAE,2CAA2C,KAAK,CAAC,EAAE,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK;gBAC1F,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE;oBACX,0DAA0D;oBAC1D,gGAAgG;oBAChG,6FAA6F;iBAC9F;aACF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,eAAe,uBAAuB,CAAA"}
@@ -0,0 +1,18 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `security/pii-pattern`
4
+ *
5
+ * Reports findings when the prompt body contains a recognizable PII
6
+ * pattern: email, phone number, US-style SSN, or credit-card-shaped
7
+ * digit blocks. Each distinct occurrence of each pattern kind
8
+ * produces its own finding, with a stable ordering that traces the
9
+ * source of the match.
10
+ *
11
+ * The rule uses the helper `detectPiiMatches` so the matrix of
12
+ * patterns lives in a single, auditable file. Tests verify the
13
+ * deterministic ordering and the absence of duplicate findings for
14
+ * the same `(kind, start)` pair.
15
+ */
16
+ declare const piiPatternRule: RuleDefinition;
17
+ export default piiPatternRule;
18
+ //# sourceMappingURL=pii-pattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pii-pattern.d.ts","sourceRoot":"","sources":["../../src/security/pii-pattern.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,cAAc,EAAE,cAqBpB,CAAA;AAqBF,eAAe,cAAc,CAAA"}
@@ -0,0 +1,56 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ import { detectPiiMatches } from "../helpers/index.js";
3
+ /**
4
+ * `security/pii-pattern`
5
+ *
6
+ * Reports findings when the prompt body contains a recognizable PII
7
+ * pattern: email, phone number, US-style SSN, or credit-card-shaped
8
+ * digit blocks. Each distinct occurrence of each pattern kind
9
+ * produces its own finding, with a stable ordering that traces the
10
+ * source of the match.
11
+ *
12
+ * The rule uses the helper `detectPiiMatches` so the matrix of
13
+ * patterns lives in a single, auditable file. Tests verify the
14
+ * deterministic ordering and the absence of duplicate findings for
15
+ * the same `(kind, start)` pair.
16
+ */
17
+ const piiPatternRule = defineRule({
18
+ id: "security/pii-pattern",
19
+ description: "Detects common PII patterns (email, phone, SSN-shaped digits, credit-card-shaped numbers) in prompt bodies.",
20
+ defaultSeverity: "error",
21
+ options: Object.freeze([]),
22
+ check: ({ file, report }) => {
23
+ const matches = detectPiiMatches(file.body);
24
+ for (const match of matches) {
25
+ const builder = PII_MESSAGE_BY_KIND[match.kind];
26
+ const suggestions = PII_SUGGESTIONS_BY_KIND[match.kind];
27
+ if (builder === undefined || suggestions === undefined)
28
+ continue;
29
+ report({
30
+ message: builder(match.text),
31
+ severity: "error",
32
+ location: match.location,
33
+ suggestions,
34
+ });
35
+ }
36
+ return { findings: [] };
37
+ },
38
+ });
39
+ const PII_MESSAGE_BY_KIND = {
40
+ email: (text) => `Detected an email address (\`${text}\`) in the prompt body.`,
41
+ phone: (text) => `Detected a phone-number-shaped value (\`${text}\`) in the prompt body.`,
42
+ ssn: (text) => `Detected a US-style SSN (\`${text}\`) in the prompt body.`,
43
+ creditCard: (text) => `Detected a credit-card-shaped number (\`${text}\`) in the prompt body.`,
44
+ };
45
+ const PII_SUGGESTIONS_COMMON = [
46
+ "Move the personal data to environment variables or a secure datastore.",
47
+ "Reference the data via a `{{ variable }}` substitution rather than inlining it.",
48
+ ];
49
+ const PII_SUGGESTIONS_BY_KIND = {
50
+ email: PII_SUGGESTIONS_COMMON,
51
+ phone: PII_SUGGESTIONS_COMMON,
52
+ ssn: PII_SUGGESTIONS_COMMON,
53
+ creditCard: PII_SUGGESTIONS_COMMON,
54
+ };
55
+ export default piiPatternRule;
56
+ //# sourceMappingURL=pii-pattern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pii-pattern.js","sourceRoot":"","sources":["../../src/security/pii-pattern.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEtD;;;;;;;;;;;;;GAaG;AACH,MAAM,cAAc,GAAmB,UAAU,CAAC;IAChD,EAAE,EAAE,sBAAsB;IAC1B,WAAW,EACT,6GAA6G;IAC/G,eAAe,EAAE,OAAO;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAC/C,MAAM,WAAW,GAAG,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACvD,IAAI,OAAO,KAAK,SAAS,IAAI,WAAW,KAAK,SAAS;gBAAE,SAAQ;YAChE,MAAM,CAAC;gBACL,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC5B,QAAQ,EAAE,OAAO;gBACjB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW;aACZ,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,MAAM,mBAAmB,GAA2D;IAClF,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,gCAAgC,IAAI,yBAAyB;IAC9E,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,2CAA2C,IAAI,yBAAyB;IACzF,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,8BAA8B,IAAI,yBAAyB;IAC1E,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,2CAA2C,IAAI,yBAAyB;CAC/F,CAAA;AAED,MAAM,sBAAsB,GAAG;IAC7B,wEAAwE;IACxE,iFAAiF;CACzE,CAAA;AAEV,MAAM,uBAAuB,GAAkD;IAC7E,KAAK,EAAE,sBAAsB;IAC7B,KAAK,EAAE,sBAAsB;IAC7B,GAAG,EAAE,sBAAsB;IAC3B,UAAU,EAAE,sBAAsB;CACnC,CAAA;AAED,eAAe,cAAc,CAAA"}
@@ -0,0 +1,14 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `structure/missing-description`
4
+ *
5
+ * Reports a finding when a prompt file does not declare a `description`
6
+ * field in its frontmatter. A missing description makes the prompt
7
+ * invisible to documentation tooling and complicates code review.
8
+ *
9
+ * The rule fires once per file regardless of how the prompt was parsed
10
+ * — even a malformed frontmatter blocks resolution of `description`.
11
+ */
12
+ declare const missingDescriptionRule: RuleDefinition;
13
+ export default missingDescriptionRule;
14
+ //# sourceMappingURL=missing-description.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-description.d.ts","sourceRoot":"","sources":["../../src/structure/missing-description.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD;;;;;;;;;GASG;AACH,QAAA,MAAM,sBAAsB,EAAE,cAkB5B,CAAA;AAEF,eAAe,sBAAsB,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ /**
3
+ * `structure/missing-description`
4
+ *
5
+ * Reports a finding when a prompt file does not declare a `description`
6
+ * field in its frontmatter. A missing description makes the prompt
7
+ * invisible to documentation tooling and complicates code review.
8
+ *
9
+ * The rule fires once per file regardless of how the prompt was parsed
10
+ * — even a malformed frontmatter blocks resolution of `description`.
11
+ */
12
+ const missingDescriptionRule = defineRule({
13
+ id: "structure/missing-description",
14
+ description: "Detects prompt files without a `description` field in their frontmatter.",
15
+ defaultSeverity: "warning",
16
+ options: Object.freeze([]),
17
+ check: ({ file, report }) => {
18
+ if (file.frontmatter.description === undefined) {
19
+ report({
20
+ message: "Prompt is missing a `description` field in its frontmatter.",
21
+ severity: "warning",
22
+ suggestions: [
23
+ "Add a single-sentence `description:` describing the prompt's purpose.",
24
+ "Keep the description under ~120 characters for tooltips and docs.",
25
+ ],
26
+ });
27
+ }
28
+ return { findings: [] };
29
+ },
30
+ });
31
+ export default missingDescriptionRule;
32
+ //# sourceMappingURL=missing-description.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-description.js","sourceRoot":"","sources":["../../src/structure/missing-description.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAGrD;;;;;;;;;GASG;AACH,MAAM,sBAAsB,GAAmB,UAAU,CAAC;IACxD,EAAE,EAAE,+BAA+B;IACnC,WAAW,EAAE,0EAA0E;IACvF,eAAe,EAAE,SAAS;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,IAAI,IAAI,CAAC,WAAW,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YAC/C,MAAM,CAAC;gBACL,OAAO,EAAE,6DAA6D;gBACtE,QAAQ,EAAE,SAAS;gBACnB,WAAW,EAAE;oBACX,uEAAuE;oBACvE,mEAAmE;iBACpE;aACF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,eAAe,sBAAsB,CAAA"}
@@ -0,0 +1,16 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `structure/missing-model`
4
+ *
5
+ * Reports a finding when a prompt file does not declare a `model` field
6
+ * in its frontmatter. The model identifier is a prerequisite for many
7
+ * downstream concerns (cost budgeting, security posture), so missing
8
+ * values are surfaced with a `warning` by default.
9
+ *
10
+ * The rule fires once per file regardless of how the prompt was parsed
11
+ * — even a malformed frontmatter blocks resolution of `model` and
12
+ * therefore triggers the finding.
13
+ */
14
+ declare const missingModelRule: RuleDefinition;
15
+ export default missingModelRule;
16
+ //# sourceMappingURL=missing-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-model.d.ts","sourceRoot":"","sources":["../../src/structure/missing-model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,gBAAgB,EAAE,cAkBtB,CAAA;AAEF,eAAe,gBAAgB,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ /**
3
+ * `structure/missing-model`
4
+ *
5
+ * Reports a finding when a prompt file does not declare a `model` field
6
+ * in its frontmatter. The model identifier is a prerequisite for many
7
+ * downstream concerns (cost budgeting, security posture), so missing
8
+ * values are surfaced with a `warning` by default.
9
+ *
10
+ * The rule fires once per file regardless of how the prompt was parsed
11
+ * — even a malformed frontmatter blocks resolution of `model` and
12
+ * therefore triggers the finding.
13
+ */
14
+ const missingModelRule = defineRule({
15
+ id: "structure/missing-model",
16
+ description: "Detects prompt files without a `model` field in their frontmatter.",
17
+ defaultSeverity: "warning",
18
+ options: Object.freeze([]),
19
+ check: ({ file, report }) => {
20
+ if (file.frontmatter.model === undefined) {
21
+ report({
22
+ message: "Prompt is missing a `model` field in its frontmatter.",
23
+ severity: "warning",
24
+ suggestions: [
25
+ "Add a `model:` entry to the frontmatter (e.g. `model: gpt-5`).",
26
+ "Set a project-wide default in `promptlint.config.*` if every prompt targets the same model.",
27
+ ],
28
+ });
29
+ }
30
+ return { findings: [] };
31
+ },
32
+ });
33
+ export default missingModelRule;
34
+ //# sourceMappingURL=missing-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-model.js","sourceRoot":"","sources":["../../src/structure/missing-model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAGrD;;;;;;;;;;;GAWG;AACH,MAAM,gBAAgB,GAAmB,UAAU,CAAC;IAClD,EAAE,EAAE,yBAAyB;IAC7B,WAAW,EAAE,oEAAoE;IACjF,eAAe,EAAE,SAAS;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACzC,MAAM,CAAC;gBACL,OAAO,EAAE,uDAAuD;gBAChE,QAAQ,EAAE,SAAS;gBACnB,WAAW,EAAE;oBACX,gEAAgE;oBAChE,6FAA6F;iBAC9F;aACF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,eAAe,gBAAgB,CAAA"}
@@ -0,0 +1,15 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `structure/undefined-variable`
4
+ *
5
+ * Reports a finding for every variable referenced in the prompt body
6
+ * that is **not** declared in `frontmatter.variables`. Unknown variables
7
+ * are an `error` because the engine cannot resolve them safely at runtime.
8
+ *
9
+ * Findings point at the *first* location of the missing variable so that
10
+ * reporters can highlight the offending token. When the prompt declares
11
+ * no variables at all, every referenced variable is reported.
12
+ */
13
+ declare const undefinedVariableRule: RuleDefinition;
14
+ export default undefinedVariableRule;
15
+ //# sourceMappingURL=undefined-variable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undefined-variable.d.ts","sourceRoot":"","sources":["../../src/structure/undefined-variable.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD;;;;;;;;;;GAUG;AACH,QAAA,MAAM,qBAAqB,EAAE,cAsB3B,CAAA;AAEF,eAAe,qBAAqB,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ import { collectBodyVariables, collectDeclaredVariables } from "../helpers/index.js";
3
+ /**
4
+ * `structure/undefined-variable`
5
+ *
6
+ * Reports a finding for every variable referenced in the prompt body
7
+ * that is **not** declared in `frontmatter.variables`. Unknown variables
8
+ * are an `error` because the engine cannot resolve them safely at runtime.
9
+ *
10
+ * Findings point at the *first* location of the missing variable so that
11
+ * reporters can highlight the offending token. When the prompt declares
12
+ * no variables at all, every referenced variable is reported.
13
+ */
14
+ const undefinedVariableRule = defineRule({
15
+ id: "structure/undefined-variable",
16
+ description: "Flags variables referenced in the prompt body but not declared in frontmatter.",
17
+ defaultSeverity: "error",
18
+ options: Object.freeze([]),
19
+ check: ({ file, report }) => {
20
+ const declared = new Set(collectDeclaredVariables(file));
21
+ const referenced = collectBodyVariables(file);
22
+ for (const ref of referenced) {
23
+ if (declared.has(ref.name))
24
+ continue;
25
+ report({
26
+ message: `Variable \`${ref.name}\` is referenced in the body but not declared in frontmatter.`,
27
+ severity: "error",
28
+ location: ref.firstLocation,
29
+ suggestions: [
30
+ `Add \`${ref.name}\` to the \`variables:\` list in frontmatter, or`,
31
+ "Replace the reference with a literal value if no substitution is intended.",
32
+ ],
33
+ });
34
+ }
35
+ return { findings: [] };
36
+ },
37
+ });
38
+ export default undefinedVariableRule;
39
+ //# sourceMappingURL=undefined-variable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undefined-variable.js","sourceRoot":"","sources":["../../src/structure/undefined-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,qBAAqB,GAAmB,UAAU,CAAC;IACvD,EAAE,EAAE,8BAA8B;IAClC,WAAW,EAAE,gFAAgF;IAC7F,eAAe,EAAE,OAAO;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAA;QACxD,MAAM,UAAU,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;QAC7C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAQ;YACpC,MAAM,CAAC;gBACL,OAAO,EAAE,cAAc,GAAG,CAAC,IAAI,+DAA+D;gBAC9F,QAAQ,EAAE,OAAO;gBACjB,QAAQ,EAAE,GAAG,CAAC,aAAa;gBAC3B,WAAW,EAAE;oBACX,SAAS,GAAG,CAAC,IAAI,kDAAkD;oBACnE,4EAA4E;iBAC7E;aACF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,eAAe,qBAAqB,CAAA"}
@@ -0,0 +1,15 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `structure/unused-variable`
4
+ *
5
+ * Reports a finding for every variable declared in `frontmatter.variables`
6
+ * that is **not** referenced anywhere in the parsed prompt body. Each
7
+ * unused variable is emitted separately so reporters can point at the
8
+ * exact identifier.
9
+ *
10
+ * The rule does not emit duplicate findings even if the same name was
11
+ * declared multiple times in the frontmatter.
12
+ */
13
+ declare const unusedVariableRule: RuleDefinition;
14
+ export default unusedVariableRule;
15
+ //# sourceMappingURL=unused-variable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unused-variable.d.ts","sourceRoot":"","sources":["../../src/structure/unused-variable.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD;;;;;;;;;;GAUG;AACH,QAAA,MAAM,kBAAkB,EAAE,cAqBxB,CAAA;AAEF,eAAe,kBAAkB,CAAA"}